Problem 741

Summary: Optical photons incorrectly propagating at phase velocity, should be group velocity
Product: Geant4 Reporter: gahs
Component: processes/opticalAssignee: gum
Status: RESOLVED FIXED    
Severity: major    
Priority: P2    
Version: 7.0   
Hardware: PC   
OS: All   

Description gahs 2005-04-14 14:16:40 CEST
Optical photons incorrectly propagate at the phase velocity v_phase= c/n.  They
should propagate at the group velocity, v_group= c/(n+dn/d(log E_phot)).

This problem is easily traced to G4Track::GetVelocity(), where the velocity for
optical photons is found by simply dividing the speed of light by the value of
the material property RINDEX at the photon's energy.  Note RINDEX _must_ be the
conventional index of refraction c/v_phase, not some unconventional "group
index" c/v_group, because RINDEX is used as c/v_phase in G4OpBoundaryProcess.

The only clean solution I can think of would be to automatically build
"GROUPVEL" material property vectors from the "RINDEX" data as needed, and
return GROUPVEL(E) from G4Track::GetVelocity() instead of c_light/RINDEX(E).  I
can provide code for this.
Comment 1 gahs 2005-04-16 09:16:59 CEST
An unofficial patch to fix this problem can be found at
http://neutrino.phys.ksu.edu/~gahs/G4_GROUPVEL_fix/
Comment 2 gum 2005-05-16 17:51:59 CEST
Dear Dr. Horton-Smith,

Thank you very much for not only pointing out the issue with group velocity vs
phase velocity, but also providing me with a solution to the problem. The group
velocity:

vg= c_light/(n0+(n1-n0)/log(E1/E0));

depends on the input for E and n provided by the user and

(n1-n0)/log(E1/E0)

can, in general, become large and/or negative. To protect against this case I
added the following statement to your new method - SetGROUPVEL:

    // add entry at first photon energy
    vg = c_light/(n0+(n1-n0)/log(E1/E0));
    // allow only for 'normal dispersion' -> dn/d(logE) > 0
    if(vg<0 || vg>c_light/n0)vg = c_light/n0;

and equivalent at the three places. I have also made this method a private
member of the G4MaterialPropertiesTable class instead of, as you proposed, a
static member function of G4Track. The method is called at the first request
fromG4Track::GetVelocity() for a given medium.


G4MaterialPropertyVector* G4MaterialPropertiesTable::GetProperty(const char *key)
{
//      Returns a Material Property Vector corresponding to a key


        if(MPT[G4String(key)] != 0) {
          return MPT[G4String(key)];
        }else{
          if(G4String(key) == "GROUPVEL") {
            return SetGROUPVEL();
          }else{
            return MPT[G4String(key)];
          }
        }
}

The fix(es) have been tagged: materials-V07-00-05 and track-V07-00-01