示例#1
0
文件: g4rich.C 项目: krafczyk/AMS
G4double RichG4Cerenkov::PostStepGetPhysicalInteractionLength(const G4Track& aTrack,
							      G4double,
							      G4ForceCondition* condition)
{
  // Get the current radiator and skip the rich part if it is not rich
  const G4Material* aMaterial = aTrack.GetMaterial();
  const G4Material &material=*aMaterial;
  if(!(material.GetName()==aerogel_name) && 
     !(material.GetName()==naf_name))
    return G4Cerenkov::PostStepGetPhysicalInteractionLength(aTrack,0,condition);

  const G4Step &aStep=*aTrack.GetStep();
  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
  G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
  G4ThreeVector x0 = pPostStepPoint->GetPosition();
  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
  const G4double charge = aParticle->GetDefinition()->GetPDGCharge();
  const G4double beta = aParticle->GetTotalMomentum()/aParticle->GetTotalEnergy();
  *condition=NotForced;
  G4double MeanNumberOfPhotons = GetAverageNumberOfPhotons(charge,beta,0.1,x0,p0);
  if(MeanNumberOfPhotons==0) return DBL_MAX; 
  *condition=StronglyForced;
  if(fMaxPhotons<=0)  return 800.0/MeanNumberOfPhotons; 
  return fMaxPhotons/MeanNumberOfPhotons;
}
示例#2
0
// Process hits.
G4bool base_SD::ProcessHits( G4Step * step, G4TouchableHistory * /*ROhist*/ ) {

  MCDetectorHit hit;

  hit.Edep=step->GetTotalEnergyDeposit();
  
  G4StepPoint * prestep = step->GetPreStepPoint();
  G4StepPoint * poststep = step->GetPostStepPoint();

  G4TouchableHandle touchable = prestep->GetTouchableHandle();

  hit.id=touchable->GetCopyNumber();
  if (hit.id>=2000)
    {
      plugin->debug(0,"Hit id is too large... bailing out \n");
      exit(-1);
    }

  G4Track * track = step->GetTrack();

  hit.time = prestep->GetGlobalTime();
  hit.track = track->GetTrackID();

   // Get the true world and local coordinate positions.
  
   G4ThreeVector trueworld =
      ( prestep->GetPosition() + poststep->GetPosition() ) / 2.0;

   // If this first time store transformation and inverse.

   if( !transformValid[hit.id] ) {
     if (WorldtoLocal.size()<hit.id+1) //too small
       {
	 WorldtoLocal.resize(hit.id+1);
	 LocaltoWorld.resize(hit.id+1);
       }
      WorldtoLocal[hit.id] = touchable->GetHistory()->GetTopTransform();
      LocaltoWorld[hit.id] = WorldtoLocal[hit.id].Inverse();
      transformValid[hit.id] = true;
   }

   G4ThreeVector Tmp = WorldtoLocal[hit.id].TransformPoint(trueworld);

   hit.world=TVector3(trueworld.x(),trueworld.y(),trueworld.z());
   hit.local=TVector3(Tmp.x(),Tmp.y(),Tmp.z());

   // find average momentum

   G4ThreeVector mom=0.5*(prestep->GetMomentum()+poststep->GetMomentum());
   hit.fourmomentum.SetXYZM(mom.x()/MeV,mom.y()/MeV,mom.z()/MeV,prestep->GetMass()/MeV);
   mom=WorldtoLocal[hit.id].TransformAxis(mom);
   hit.localmomentum=TVector3(mom.x(),mom.y(),mom.z());
   data->hits.push_back(hit);
   return true;
}
示例#3
0
//---------------------------------------------------------------------------
G4int SteppingAction::IsBoxSurfaceFlux(const G4Step* aStep) //returns 1(in), 2(out), or -1
{  //G4PSFlatSurfaceFlux
	
	G4StepPoint* preStep = aStep->GetPreStepPoint();
	
	G4VPhysicalVolume* physVol = preStep->GetPhysicalVolume();
	G4VPVParameterisation* physParam = physVol->GetParameterisation();
	G4VSolid * solid = 0;
	if(physParam)
	{ // for parameterized volume
	//G4int idx = ((G4TouchableHistory*)(aStep->GetPreStepPoint()->GetTouchable()))
	//->GetReplicaNumber(indexDepth);//TODO find indexDepth and use these
	//solid = physParam->ComputeSolid(idx, physVol);
	//solid->ComputeDimensions(physParam,idx,physVol);
	}
	else
	{ // for ordinary volume
		solid = physVol->GetLogicalVolume()->GetSolid();
	}
	
	G4Box* boxSolid = (G4Box*)(solid);
	
	G4TouchableHandle theTouchable = 
	aStep->GetPreStepPoint()->GetTouchableHandle();
	G4double kCarTolerance=G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
	
	if (aStep->GetPreStepPoint()->GetStepStatus() == fGeomBoundary ){
		// Entering Geometry
		G4ThreeVector stppos1= aStep->GetPreStepPoint()->GetPosition();
		G4ThreeVector localpos1 = 
		theTouchable->GetHistory()->GetTopTransform().TransformPoint(stppos1);
		if(std::fabs( localpos1.z() + boxSolid->GetZHalfLength())<kCarTolerance 
			||std::fabs( localpos1.z() - boxSolid->GetZHalfLength())<kCarTolerance
			||std::fabs( localpos1.y() + boxSolid->GetYHalfLength())<kCarTolerance 
			||std::fabs( localpos1.y() - boxSolid->GetYHalfLength())<kCarTolerance 
			||std::fabs( localpos1.x() + boxSolid->GetXHalfLength())<kCarTolerance 
			||std::fabs( localpos1.x() - boxSolid->GetXHalfLength())<kCarTolerance 
		){
			return 1;//fFlux_In; _InOut =0 		
		}
		
	}
	
	if (aStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary ){
		// Exiting Geometry
		G4ThreeVector stppos2= aStep->GetPostStepPoint()->GetPosition();
		G4ThreeVector localpos2 = 
		theTouchable->GetHistory()->GetTopTransform().TransformPoint(stppos2);
		if(std::fabs( localpos2.z() + boxSolid->GetZHalfLength())<kCarTolerance 
			||std::fabs( localpos2.z() - boxSolid->GetZHalfLength())<kCarTolerance
			||std::fabs( localpos2.y() + boxSolid->GetYHalfLength())<kCarTolerance 
			||std::fabs( localpos2.y() - boxSolid->GetYHalfLength())<kCarTolerance 
			||std::fabs( localpos2.x() + boxSolid->GetXHalfLength())<kCarTolerance 
			||std::fabs( localpos2.x() - boxSolid->GetXHalfLength())<kCarTolerance 			
		){
			return 2;//fFlux_Out;
		}
	}
	
	return -1;
}
示例#4
0
G4int SteppingAction::IsCylSurfaceFlux(const G4Step* aStep, G4double fRadius, G4double fHalfHt)
{  //from G4PSCylinderSurfaceFlux        //returns 1(in), 2(out), or -1
	
	G4StepPoint* preStep = aStep->GetPreStepPoint(); //?????
	G4VPhysicalVolume* physVol = preStep->GetPhysicalVolume();
	G4VPVParameterisation* physParam = physVol->GetParameterisation();
	//G4VSolid* solid = NULL;
	if(physParam)
	{ // for parameterized volume
		//G4int idx = ((G4TouchableHistory*)(aStep->GetPreStepPoint()->GetTouchable()))
		//->GetReplicaNumber(indexDepth);//TODO get indexdepth and uncomment these
		//solid = physParam->ComputeSolid(idx, physVol);
		//solid->ComputeDimensions(physParam,idx,physVol);
	}
	else
	{ // for ordinary volume
	//	solid = physVol->GetLogicalVolume()->GetSolid();
		//G4cout << " logvol " << physVol->GetLogicalVolume()->GetName() << G4endl;
		//NOTE this is wrong
	}
	
	//G4Tubs* tubsSolid = (G4Tubs*)(solid);  //NOTE solid dimensions are all 0
	//now it is bypassed by passing in ht and rad. TODO correct it
	
	G4TouchableHandle theTouchable = aStep->GetPreStepPoint()->GetTouchableHandle();
	G4double kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();  
	
	if (aStep->GetPreStepPoint()->GetStepStatus() == fGeomBoundary )
	{
		// Entering Geometry. Prestep point is at the Outer surface. 
		G4ThreeVector stppos1= aStep->GetPreStepPoint()->GetPosition();
		G4ThreeVector localpos1 = 
		theTouchable->GetHistory()->GetTopTransform().TransformPoint(stppos1);
		//if ( std::fabs(localpos1.z()) > tubsSolid->GetZHalfLength()) return -1;			
		if ( std::fabs(localpos1.z()) > (fHalfHt+ kCarTolerance))//tubsSolid->GetZHalfLength()
		{//G4cout << " preGeom:-1:z " << localpos1.z() << " halfz " << tubsSolid->GetZHalfLength() 
		 //      <<" tol " << kCarTolerance << G4endl; // NOTE solid dimensions are all 0
			return -1; 												
		}
		G4double localR2 = localpos1.x()*localpos1.x()+localpos1.y()*localpos1.y();
		G4double outerRad = fRadius;//tubsSolid->GetOuterRadius();// GetInnerRadius();//NOTE
		if( (localR2 > (outerRad-kCarTolerance)*(outerRad-kCarTolerance)
			&& localR2 < (outerRad+kCarTolerance)*(outerRad+kCarTolerance))
			||
			( std::fabs( localpos1.z())< (fHalfHt +kCarTolerance)//tubsSolid->GetZHalfLength() 
			&&	localR2 < (outerRad+kCarTolerance)*(outerRad+kCarTolerance) )
		){
			//G4cout << " preGeom:1 " << G4endl;
			return 1;//fFlux_In;
		}
	}
	
	if (aStep->GetPostStepPoint()->GetStepStatus() == fGeomBoundary )
	{
		// Exiting Geometry. Post step point is at the outer surface.
		G4ThreeVector stppos2= aStep->GetPostStepPoint()->GetPosition();
		G4ThreeVector localpos2 = 
		theTouchable->GetHistory()->GetTopTransform().TransformPoint(stppos2);
		//if ( std::fabs(localpos2.z()) > tubsSolid->GetZHalfLength() )	return -1;
		if ( std::fabs(localpos2.z()) > (fHalfHt+ kCarTolerance))//tubsSolid->GetZHalfLength() 
		{
			return -1;
		}
		G4double localR2 = localpos2.x()*localpos2.x()+localpos2.y()*localpos2.y();
		G4double outerRad = fRadius;//tubsSolid->GetOuterRadius();//GetInnerRadius();//NOTE
		if( (localR2 > (outerRad-kCarTolerance)*(outerRad-kCarTolerance)
			&& localR2 < (outerRad+kCarTolerance)*(outerRad+kCarTolerance))
			||
			( std::fabs( localpos2.z())< ( fHalfHt+kCarTolerance)// tubsSolid->GetZHalfLength()
			&&	localR2 < (outerRad+kCarTolerance)*(outerRad+kCarTolerance) )
		){
			//G4cout << " postGeom:2 " << G4endl;
			return 2;//fFlux_Out;
		}
	}
	
	return -1;
}
示例#5
0
void SteppingAction::UserSteppingAction(const G4Step* step)
{
	
	G4bool skipStepping = false; //set true if only SD is needed
	if ( skipStepping )return;

    G4Track* track = step->GetTrack();	
    G4String postVol    = "NIL";
    G4String preVol     = "NIL";
    G4String partName   = "NIL";
    G4int    pdgCode    = -999;
    G4String proc       = "NIL";
    G4double time       = -1;
    G4String postProc   = "NIL";
    G4String preProc    = "NIL";
    G4String trackProc  = "NIL";
    G4String trkNextVol = "NIL";
	G4double preKE = 0;


	if(step->GetPostStepPoint()->GetPhysicalVolume())
		postVol  = step->GetPostStepPoint()->GetPhysicalVolume()->GetName(); 
        //step->GetPostStepPoint()->GetTouchableHandle()->GetVolume()->GetName();

	if(step->GetPreStepPoint()->GetPhysicalVolume())
		preVol  =  step->GetPreStepPoint()->GetPhysicalVolume()->GetName(); 

    if(track->GetDynamicParticle()->GetDefinition()) // GetParticleDefinition
    {
        partName = track->GetDynamicParticle()->GetDefinition()->GetParticleName();
    }
    if(step->GetPreStepPoint())
    {
        preKE = step->GetPreStepPoint()->GetKineticEnergy();
    }

	G4bool skipVolume = true;

	if(skipVolume)
	{
        if(!(postVol=="SNSDetectorCsI"|| postVol=="DetPolyShield"|| postVol=="DetLeadShield" 
            ||preVol=="SNSDetectorCsI"|| preVol=="DetPolyShield"|| preVol=="DetLeadShield"
            )) return;
        if( postVol != "SNSDetectorCsI" && partName !="neutron" )   return;
        //skip if not neutron in other volumes
    }

    if(step->GetTotalEnergyDeposit()<0.1*keV && partName !="neutron") return;  


    G4bool skipParticles = true; // all particles ?
    if(skipParticles && step->GetTrack()->GetDynamicParticle()->GetDefinition())
    {
        if( partName == "nu_e"|| partName =="nu_mu"|| partName == "anti_nu_mu" 
            ||partName == "anti_nu_e" || partName == "mu+" || partName =="pi+" 
            || partName =="pi-") // skipped previously e- e+, gamma
                return;
    }

    Analysis* man = Analysis::GetInstance();
    G4StepPoint* pre  = step->GetPreStepPoint();



    if(step->GetPostStepPoint()->GetProcessDefinedStep())
        proc =  step->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName();

    if(step->GetPostStepPoint())
		time = track->GetGlobalTime(); //step->GetPostStepPoint()->GetGlobalTime();//
    if(track->GetDynamicParticle()->GetDefinition()) // GetParticleDefinition
    {
        pdgCode  = track->GetDynamicParticle()->GetDefinition()->GetPDGEncoding();
    }

    if( step->GetPostStepPoint()->GetProcessDefinedStep())
        postProc = step->GetPostStepPoint()->GetProcessDefinedStep()->GetProcessName();

    if( step->GetPreStepPoint()->GetProcessDefinedStep())
        preProc = step->GetPreStepPoint()->GetProcessDefinedStep()->GetProcessName();

    if(track->GetCreatorProcess())
        trackProc =  track->GetCreatorProcess()->GetProcessName();

	G4double kCarTolerance = G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();  

	
	//############################################
	//In SNS Detector
 
	G4bool snsDetectorCsI = true;  // detector
	G4bool verbDetCsIInfo = false; 	//text output
    G4int volumeID = -1;    
	if( snsDetectorCsI && (postVol=="SNSDetectorCsI" 
	|| postVol=="DetPolyShield" || postVol=="DetLeadShield") )// && partName == "neutron"))
	{
		//if(	!(partName == "gamma"|| partName == "e-"))
		//{
			G4double trackKE = track->GetKineticEnergy();
			G4int stepNum   = track->GetCurrentStepNumber();
            G4int evtid     = G4RunManager::GetRunManager()->GetCurrentEvent()->GetEventID();
            G4int trackid   = track->GetTrackID();
			G4int parentID  = track->GetParentID();

			G4double xx = track->GetPosition().x(); //trackpos= postpos
			G4double yy = track->GetPosition().y();
			G4double zz = track->GetPosition().z();
			G4double postX = step->GetPostStepPoint()->GetPosition().x();
			G4double postY = step->GetPostStepPoint()->GetPosition().y();				
			G4double postZ = step->GetPostStepPoint()->GetPosition().z();
			G4double weight = track->GetWeight() ;//step->GetPreStepPoint()->GetWeight();
			G4double eDep =0;
			
            if(partName == "neutron")// && step->GetPostStepPoint()->GetStepStatus()==fGeomBoundary ) 
            {//fGeomBoundary =1, from G4StepStatus.hh.  use poststep, not pre

                if(postVol=="SNSDetectorCsI" && preVol != "SNSDetectorCsI" ) volumeID = 1;
                else if( postVol == "DetLeadShield" &&  !(preVol == "SNSDetectorCsI" 
                        || preVol == "DetLeadShield"))  volumeID = 2;
                else if( postVol == "DetPolyShield"&&  !(preVol == "SNSDetectorCsI" 
                        || preVol == "DetPolyShield" || preVol == "DetLeadShield"))volumeID = 3;
                //else if( postVol == "DetWaterShield"&&  !(preVol == "SNSDetectorCsI" 
                //   || preVol == "DetLeadShield" ||preVol == "DetPolyShield" ))volumeID = 4;    
                //else if( preVol == "MonolithSteelCyl")volumeID = 5;//NOTE
                //xx = (aTrack->GetVertexPosition()).x();
                //yy = (aTrack->GetVertexPosition()).y();
                //zz = (aTrack->GetVertexPosition()).z();
				
				G4double preX = step->GetPreStepPoint()->GetPosition().x();
				G4double preY = step->GetPreStepPoint()->GetPosition().y();				
				G4double preZ = step->GetPreStepPoint()->GetPosition().z();
				//pass without interaction
                if(step->GetPostStepPoint()->GetStepStatus()==fGeomBoundary &&  
                    preVol == "DetLeadShield" && postVol == "DetLeadShield")
                {   
                    volumeID = 1;
                    G4cout  << " Passed vol1 ...... " << G4endl;
                }

                if(track->GetNextVolume() == 0) volumeID = 0;

                if(volumeID > -1)
					man->FillSNSneutronFlux(volumeID, preKE/MeV , trackKE/MeV, pdgCode, weight, xx/m,  
                    yy/m, zz/m, evtid, trackid, parentID, stepNum, time/microsecond); 
                

				if(verbDetCsIInfo && volumeID > -1)
				{
                    G4cout  << " NFLUX "
					<< std::setprecision(3) << preKE/MeV 
					<< " preKE(mev):postKE " << std::setprecision(3) << trackKE/MeV    
                    << " " << partName << " eDep "
                    << std::setprecision(3) << eDep/MeV <<  " mev|pre:post " <<  preVol 
                    <<  " " << postVol << " volID "<< volumeID << " " << weight 
                    << " wt|evt:track:step " << evtid << " "<< trackid << " " << stepNum
                    << "  " << preProc << " preproc|postproc " << postProc << " "
                    << track->GetCreatorProcess()->GetProcessName()
                    <<  " create_proc|in " << track->GetLogicalVolumeAtVertex()->GetName()
					<< "  withKE "<< track->GetVertexKineticEnergy()/MeV
                    //<< " track_xyz_m " << std::setprecision(3) << xx/m << " " << std::setprecision(3) 
                    //<< yy/m << " " << std::setprecision(3) <<  zz/m
                    << " post_xyz_m " << std::setprecision(3) << postX/m << " " << std::setprecision(3) 
					<< postY/m << " " << std::setprecision(3) << postZ/m
					<< " pre_xyz_m " << std::setprecision(3) << preX/m << " " << std::setprecision(3) 
					<< preY/m << " " << std::setprecision(3) << preZ/m
                    << " postStatus " << step->GetPostStepPoint()->GetStepStatus()
                    << G4endl;
				}
			
				G4bool shieldSteps = false;
                if( shieldSteps && (postVol== "DetPolyShield"|| postVol=="DetLeadShield" ||
					postVol=="SNSDetectorCsI" ) &&  postVol != preVol ) 
                {
                    G4cout  << " ShieldN "
                    << std::setprecision(3) << preKE/MeV 
                    << " preKE(mev):postKE " << std::setprecision(3) << trackKE/MeV    
                    << " " << partName << " eDep "
                    << std::setprecision(3) << eDep/MeV <<  " mev|pre:post " <<  preVol 
                    <<  " " << postVol << " volID "<< volumeID << " " << weight 
                    << " wt|evt:track:step " << evtid << " "<< trackid << " " << stepNum
                    << "  " << preProc << " preproc|postproc " << postProc
                    << "  " << track->GetCreatorProcess()->GetProcessName()
                    <<  " create_proc|in " << track->GetLogicalVolumeAtVertex()->GetName()
                    << "  withKE "<< track->GetVertexKineticEnergy()/MeV
                    << " xyz_m " << std::setprecision(3) << postX/m << " " << std::setprecision(3) 
                    << postY/m << " " << std::setprecision(3) << postZ/m
                    << " postStatus " << step->GetPostStepPoint()->GetStepStatus()
                    << G4endl;
                }	
            }//nuetron nFlux vol


            //Detections
			eDep = step->GetTotalEnergyDeposit();	
			if(postVol=="SNSDetectorCsI")
			{
				man->FillSNSDetection(eDep/MeV, preKE/MeV , trackKE/MeV, pdgCode, weight, postX/m, 
				postY/m, postZ/m, evtid, trackid, parentID, stepNum, time/microsecond);
				//proc, vol

                if(verbDetCsIInfo)
                {
					G4cout  << " Det "			
                    << std::setprecision(3) << preKE/MeV 
                    << " preKE(mev):postKE " << std::setprecision(3) << trackKE/MeV    
                    << " " << partName << " eDep "
                    << std::setprecision(3) << eDep/MeV <<  " mev|pre:post " <<  preVol 
                    <<  " " << postVol << " volID "<< volumeID << " " << weight 
                    << " wt|evt:track:step " << evtid << " "<< trackid << " " << stepNum
                    << "  " << preProc << " preproc|postproc " << postProc 
                    << "  " << track->GetCreatorProcess()->GetProcessName()
                    <<  " create_proc:in " << track->GetLogicalVolumeAtVertex()->GetName()
                    << "  withKE "<< track->GetVertexKineticEnergy()/MeV
                    << " post_xyz_m " << std::setprecision(3) << postX/m 
                    << " " << std::setprecision(3) 
                    << postY/m << " " << std::setprecision(3) <<  postZ/m
                    << " postStatus " << step->GetPostStepPoint()->GetStepStatus()
                    << G4endl;
                }
            }//if CsI
	}//if vol det

	
    
    //###############################################
    //NFLUX at BasementLayer
G4bool nFluxBaseLayer = true;    
    if(nFluxBaseLayer && partName == "neutron" &&
        preVol == "BasementIn" && postVol == "BasementLayer")
    {
        G4double trackKE = track->GetKineticEnergy();
        G4int evtid     = G4RunManager::GetRunManager()->GetCurrentEvent()->GetEventID();
        G4int trackid   = track->GetTrackID();
        G4double xx     = track->GetPosition().x(); //trackpos= postpos
        G4double yy     = track->GetPosition().y();
        G4double zz     = track->GetPosition().z();
        G4double weight = track->GetWeight() ; 

        G4cout  << " BaseFLUX "
            << std::setprecision(3) << trackKE/MeV    
            << " " <<  weight << " " << partName << " "<< preVol <<  " " << postVol 
            << " " << preProc << " " << postProc << " " << evtid << " " << trackid 
            << track->GetCreatorProcess()->GetProcessName()
            << " cr_pr|in " << track->GetLogicalVolumeAtVertex()->GetName()
            << " KE "<< track->GetVertexKineticEnergy()/MeV
            << " xyz_m " << std::setprecision(3) << xx/m << " " 
            << std::setprecision(3) 
            <<  yy/m << " " << std::setprecision(3) << zz/m
            << " st " << step->GetPostStepPoint()->GetStepStatus()
            << G4endl;
    }

	////############################################
	//NEUTRONS FLUX at Target and MonolithSteel

    G4bool HgNflux = false;
    if(HgNflux && partName =="neutron")
    {
        if(postVol != "HgTarget" && preVol == "HgTarget" )
        G4cout << "NFLUX_HgTargetOUT " << partName << " preKE "<< std::setprecision(3)
               << preKE/MeV << " " << preVol << " pre:post " << postVol << G4endl;

        if(preVol != "HgTarget" && postVol == "HgTarget" )
        G4cout << "NFLUX_HgTargetIN " << partName << " preKE "<< std::setprecision(3)
               << preKE/MeV << " " << preVol << " pre:post " << postVol << G4endl;
    }

    G4bool monoNflux = false;

    if(monoNflux && partName =="neutron")
    {
        G4double monOuterRad = 5.*m;
        G4double monTopZ = 8.*m;
        G4double monBotZ = -4.5*m;
        if(postVol != "MonolithSteelCyl" && preVol == "MonolithSteelCyl" )
        {
            G4double radius = std::sqrt((track->GetPosition().x()) *  
                    (track->GetPosition().x()) + (track->GetPosition().y()) *
                    (track->GetPosition().y()) ); 
            G4double prerad = std::sqrt((step->GetPreStepPoint()->GetPosition().x()) *  
                    (step->GetPreStepPoint()->GetPosition().x()) + 
                    (step->GetPreStepPoint()->GetPosition().y()) *
                    (step->GetPreStepPoint()->GetPosition().y()) ); 
            G4double postrad = std::sqrt((step->GetPostStepPoint()->GetPosition().x()) *  
                    (step->GetPostStepPoint()->GetPosition().x()) + 
                    (step->GetPostStepPoint()->GetPosition().y()) *
                    (step->GetPostStepPoint()->GetPosition().y()) ); 

            G4double zpos = step->GetPostStepPoint()->GetPosition().z();
            if(radius > monOuterRad - kCarTolerance || (zpos > monTopZ-kCarTolerance
                || zpos < monBotZ+kCarTolerance) )
            {
                G4cout << "NFLUX_monoOUT " << partName << " preKE "
                       << std::setprecision(3)<< preKE/MeV << " postKE "
                       << std::setprecision(3) << step->GetPostStepPoint()->GetKineticEnergy()
                       << " "<< preVol<< " pre:post " << postVol  << " trackrad " << radius 
                       << " prerad " << prerad << " postrad " << postrad 
                       << " stat.pre:post " << step->GetPreStepPoint()->GetStepStatus()
                       << "  " << step->GetPostStepPoint()->GetStepStatus()
                       << " postxyz " << std::setprecision(3) 
                       << step->GetPostStepPoint()->GetPosition().x() 
                       << "  "  << std::setprecision(3) 
                       << step->GetPostStepPoint()->GetPosition().y()
                       << " " << std::setprecision(3) 
                       << step->GetPostStepPoint()->GetPosition().z()
                       << " prexyz " << std::setprecision(3) 
                       << step->GetPreStepPoint()->GetPosition().x() 
                       << "  "  << std::setprecision(3) 
                       << step->GetPreStepPoint()->GetPosition().y()
                       << " " << std::setprecision(3) 
                       << step->GetPreStepPoint()->GetPosition().z()
                       << G4endl;
            }
        }
    }

    //#######################################
    //COUNT NEUTRONS produced by proton
    G4bool  verbNeutCount  = false; 
    if(verbNeutCount)
    {
        static G4int numNeutPerEvt = 0;
        static G4int staticEvtId = 0;
        static G4int beamSec     = 0;
        G4double    neutronsKE   = 0;
        G4int       numNthisStep = 0;
        G4String    thisSecPart  = "";
        G4String    thisProc     = "";
        G4bool      pFlag        = true;
        G4bool      isBeamProt   = (track->GetParentID()==0) ? true:false;
        //if(track->GetParentID() == 0)//parent is primary proton
        //{
        const std::vector<const G4Track*>* secVec=step->GetSecondaryInCurrentStep();
        //G4int thisPDG = (*secVec)[secN]->GetDynamicParticle()->GetPDGcode();

        if(postVol == "HgTarget")
        {
            for(size_t secN = 0; secN < secVec->size(); secN++)
            {
                thisSecPart = (*secVec)[secN]->GetDynamicParticle()->GetDefinition()->GetParticleName();
                if(thisSecPart == "neutron"|| thisSecPart == "proton")
                {

                    if(pFlag)
                    {
                        G4cout << "particle: "<<partName << " ke(mev) "<< std::setprecision(2) 
                            << preKE/MeV  << " Nsec " << secVec->size()
                            << " postVol " << postVol ;
                        if(isBeamProt){ G4cout  << "  :primary ";} 
                        G4cout << G4endl;
                        pFlag = false;
                    }
                    const G4VProcess* creator = (*secVec)[secN]->GetCreatorProcess();
                    if(creator) thisProc = creator->GetProcessName();

                    G4double keThisN = (*secVec)[secN]->GetDynamicParticle()->GetKineticEnergy();

                    G4cout  << " \t sec: " << thisSecPart<< " ke: " << std::setprecision(2)
                            << keThisN/MeV << " " << thisProc;
                    if(isBeamProt){ G4cout  << " \t firstImpact "; }
                    G4cout << G4endl;

                    if(thisSecPart == "neutron")
                    {
                        numNthisStep++;
                        if(isBeamProt)beamSec++; 
                        neutronsKE = neutronsKE +  keThisN;
                    }
                }//n
                //else G4cout  <<"other : " << thisSecPart << G4endl;
            }//for
        }//if Target
       // }//primary
        G4int thisEvtId = G4RunManager::GetRunManager()->GetCurrentEvent()->GetEventID();

        if(thisEvtId == staticEvtId) numNeutPerEvt += numNthisStep;
        else 
        {
            if(numNeutPerEvt>0 )
                G4cout << "####Evt " <<  thisEvtId <<" numN  " << numNeutPerEvt
                       << "  firstImpact " << beamSec << G4endl;
            numNeutPerEvt = numNthisStep;
            beamSec       = 0;//only first time needed
        }
        staticEvtId = thisEvtId;
    }//if countN
    //########## End of Neutron Count


    //NEUTRONS FLUX escaping to outofWorld
	G4bool nFluxOutOfWorld = false;
    if(nFluxOutOfWorld)
    {
		static  G4String preVolStatic = "";
		static  G4double preX  = -1;
		static  G4double preY  = -1;
		static  G4double preZ  = -1;
		static  G4double prePx = -1;
		static  G4double prePy = -1;
		static  G4double prePz = -1;
		static  G4double preKe = -1;
		static  G4bool  preExists = false;

		if(track->GetCurrentStepNumber() <=1) preExists = false;
        preVolStatic  = preVol;

		G4bool verb2 = false;
		if(verb2)
		{
			if(track->GetNextVolume())  
			G4cout << "# " << track->GetCurrentStepNumber() 
                   << postVol
			       << "   " << track->GetVolume()->GetName()
			//<< " preVol "  << preVol  
				//<< " pos: "         <<  track->GetPosition().x() //present or post
				//<< " "             <<  track->GetPosition().y()
				//<< " "             <<  track->GetPosition().z() 
				<< "  prexist " << preExists
				<< G4endl;
		}

		G4bool takeIt = (track->GetCurrentStepNumber() ==0 && track->GetTrackID()==1) ? false:true;  
        if( preVolStatic== "SNSTargetDetector") takeIt = false;
		if( preVolStatic== "World") takeIt = false;

		if( takeIt && pre && pdgCode==2112 &&
			( postVol=="SNSTargetDetector"||	postVol=="World"||
			  postVol=="OutOfWorld" )  )
		{
			preExists   = true;
			preX    = pre->GetPosition().x();
			preY    = pre->GetPosition().y();
			preZ    = pre->GetPosition().z(); // track->GetPosition().z()
			prePx   = pre->GetMomentumDirection().x();//track->GetMomentumDirection().x()
			prePy   = pre->GetMomentumDirection().y();
			prePz   = pre->GetMomentumDirection().z();
			preKe   = pre->GetKineticEnergy();
		}
	   //TODO reset when out of scope			
		if(  track->GetNextVolume() == 0 || postVol =="OutOfWorld" 	|| postVol=="World" )
		{
			if(preExists && pdgCode ==2112 ) //neutron
			{
				RunAction::CountParticles(); 
				G4bool verb = false;
				if(verb)
				{
					G4cout 
					//<< " :PART: " 
					<< " "          << partName
					<< "  "         << preVolStatic
					<< "  "         << preX
					<< "  "         << preY
					<< "  "         << preZ
					<<  " current " << track->GetPosition().x()  
					<< "  "         << track->GetPosition().y()
					<< "  "         << track->GetPosition().z()
					<< " Mom: "     << prePx   
					<< " "          << prePy 
					<< " "          << prePz
					<< " ke "       << preKe/MeV
					//<< " time " << track->GetGlobalTime()
					//<< " :proc: "   << postProc
					//<< " :prestKE: "  << pre->GetKineticEnergy()/MeV  
					//<< " :poststKE: " << pre->GetKineticEnergy()/MeV	
					//<< " trackL " << track->GetTrackLength()
					//<< " stepL " << track->GetStepLength()
					
					//VERTEX (,where this track was created) information 
					//<< " MeV.VertMom: " << track->GetVertexMomentumDirection().x()
					//<< " " << track->GetVertexMomentumDirection().y()
					//<< " " << track->GetVertexMomentumDirection().z()
					//<< "ke " << track->GetVertexKineticEnergy()/MeV
					//<< "   "<< track->GetLogicalVolumeAtVertex()->GetName()
					//<< "  VertPOS: "<< track->GetVertexPosition().x()
					//<< "  "<< track->GetVertexPosition().y()
					//<< "  "<< track->GetVertexPosition().z()
					//<< "   "<< track->GetCreatorProcess()->GetProcessName() //NOTE: check before
					//<< " model "<< track->GetCreatorModelName()
					<< G4endl;
				} //if verb
				//fill in root file
                man->FillSNSneutronFlux(0, preKE/MeV, preKe/MeV, pdgCode,  0, track->GetPosition().x()/m, 
                    track->GetPosition().y()/m, track->GetPosition().z()/m, 0, 0, 0, 0, 0);//, prePx, prePy, prePz );

			}		
		}
	} //END of FIND NEUTRONS escaping to outofWorld





	//##############################################
    //SCINTILLATOR DETECTOR analysis process
    //

	G4bool verbScint = false;
    //set verbScint if secondary size>0
	//if( step->GetSecondaryInCurrentStep()->size() )  verbScint=true;	
        
	if(verbScint)
	{
		G4ParticleDefinition* particleType = track->GetDefinition();
		G4double edep = step->GetTotalEnergyDeposit()/MeV; 
        G4StepPoint* preStep  = step->GetPreStepPoint();
        G4StepPoint* postStep = step->GetPostStepPoint();
		//NOTE prestep and postep may not exist in some cases !

		//const G4VProcess* postDefStep = postStep->GetProcessDefinedStep();
        G4cout << " eDep " << std::setprecision(4) << edep;
		if( postProc)
		{
			G4cout << " post:" << postProc << " ";		
		}else {  G4cout << " postproc: NONE ";}

		if( preProc)
		{
			G4cout << " pre:" << preProc << " ";		
		}else { G4cout << " preproc: NONE ";}

		if(trackProc){ 
			G4cout<< " trackProc:" <<trackProc << " ";
		}else { G4cout << " trackProc: NONE ";}
		


        //if(step->GetTrack()->GetParentID()==0)
        //fpSteppingManager available only in SteppingAction class
        G4TrackVector* fSecondary=fpSteppingManager->GetfSecondary();
        G4int nSecThisStep = fpSteppingManager->GetfN2ndariesAtRestDoIt()
          + fpSteppingManager->GetfN2ndariesAlongStepDoIt()
          + fpSteppingManager->GetfN2ndariesPostStepDoIt();
       //const std::vector<const G4Track*>* fSecondary=step->GetSecondaryInCurrentStep();
		
		size_t secSize = fSecondary->size();// total of all steaps so far.
        //if( secSize > 0)
		G4cout  << "secSize: " << secSize-nSecThisStep ;
		
        G4double totalKE = 0;
        G4double totalEn = track->GetTotalEnergy();
        // track->GetDynamicParticle()->GetTotalEnergy();

        if(postStep)
		    totalKE = postStep->GetKineticEnergy(); 
		
        size_t nOptPhot = 0;
        G4bool printPhot  = true;		
        if( nSecThisStep>0 ) //nSecThisStep = that of this step
        {
          for(size_t lp1 = secSize-nSecThisStep; lp1 < secSize; lp1++)
          {
			  
			  //(*fSecondary)[lp1]->GetDynamicParticle()->GetKineticEnergy();
			  //GetTotalEnergy();
//               G4String secPart = (*fSecondary)[lp1]->GetDefinition()->GetParticleName();
//               if(secPart =="neutron" || secPart == "proton" || secPart == "deutron"
//                 ||secPart == "alpha" || secPart == "gamma"  || secPart=="e-"||secPart=="e+")
//               {
                totalKE = totalKE +  (*fSecondary)[lp1]->
                                      GetDynamicParticle()->GetKineticEnergy();
                totalEn = totalEn + (*fSecondary)[lp1]->GetTotalEnergy();
             // }
              //if(postProc ~ /neutronInelastic|nCapture/ )
              //  G4cout<< " part: " << (*fSecondary)[lp1]->GetDefinition()->GetParticleName()
              //	<< " KE: " << (*fSecondary)[lp1]->GetDynamicParticle()->GetKineticEnergy()
              //  << G4endl;
			  
			  
			  
			 //optical photon 
            if(particleType == G4OpticalPhoton::Definition()) 
			{
				nOptPhot++;
				if(printPhot)
                {
                  G4cout << " Op.photon "; 
                  const G4VProcess* creator=(*fSecondary)[lp1]->GetCreatorProcess();
                  if(creator)
                  {
                    G4cout<<" sec.proc: "<< creator->GetProcessName();
                    printPhot= false;
                  }
                  G4cout << " " << G4endl;
                        
               }//print
            }//if phot
            
          }//for
        }//if secSize
        G4cout<<" nOptPhot: "<< G4endl;       

		G4bool verb4 = false;
		if(verb4)
		{
            G4double  preTotE = -1;
            if(preStep)
            {
                preKE   = preStep->GetKineticEnergy()/MeV ;
                preTotE = preStep->GetTotalEnergy()/MeV;
            }
            G4double postKE = -1, postTotE = -1;
            if(postStep)
            {
                postKE   = postStep->GetKineticEnergy()/MeV;
                postTotE =  postStep->GetTotalEnergy()/MeV;
            }

			G4cout 
			<< partName
			<< " trackID: " << track->GetTrackID()  
			<< " :prestKE: " << std::setprecision(4)<< preKE  
			<< " :poststKE: " << std::setprecision(4) << postKE
			<< " :preTotEn: " << std::setprecision(4)<< preTotE
			<< " :postTotEn: " << std::setprecision(4)<< postTotE
			//<< " :TotEn: " << std::setprecision(4) << totalEn/MeV		
			//<< " :totalKE: " << std::setprecision(4) << totalKE/MeV			
			<< " :trackKE: " << std::setprecision(4) << track->GetKineticEnergy() /MeV
			<< " :eDep: " << std::setprecision(4) << edep 
			<< " :-deltaE: " << std::setprecision(4)<< -step->GetDeltaEnergy()/MeV 
			//<< " :-deltaE-edep: "<< std::setprecision(4)<< -step->GetDeltaEnergy()/MeV-edep
			//<< " :niel: " << std::setprecision(4)<< step->GetNonIonizingEnergyDeposit()/MeV
			//<< " :proc: "<<  postStep->GetProcessDefinedStep()->GetProcessName()
			<< G4endl;
		}
        if( nSecThisStep>0 ) G4cout<<" EndProcSearchKeyWord "<< G4endl;  //don't delete this, just comment it 
    }//verbose    
    //####################################
    
}//end of userSteppingAction
示例#6
0
文件: g4rich.C 项目: krafczyk/AMS
G4VParticleChange*
RichG4Cerenkov::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep){

  // Do not do RICH stuff
  //  return G4Cerenkov::PostStepDoIt(aTrack,aStep);


  // Get the current point
  G4Material &material=*aTrack.GetMaterial();

  if(!(material.GetName()==aerogel_name) && 
     !(material.GetName()==naf_name))
    return G4Cerenkov::PostStepDoIt(aTrack,aStep);

  // This is a RICH radiator, use the tools already available to compute everything
  // Copy and paste of original G4Cerenkov class

  aParticleChange.Initialize(aTrack);

  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();
  const G4Material* aMaterial = aTrack.GetMaterial();

  G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();
if(!aParticle || !aMaterial || !pPreStepPoint || !pPostStepPoint)return pParticleChange;
  G4ThreeVector x0 = pPreStepPoint->GetPosition();
  G4ThreeVector p0 = aStep.GetDeltaPosition().unit();
  G4double t0 = pPreStepPoint->GetGlobalTime();


  G4MaterialPropertiesTable* aMaterialPropertiesTable =
    aMaterial->GetMaterialPropertiesTable();
  if (!aMaterialPropertiesTable) return pParticleChange;
  const G4MaterialPropertyVector* Rindex =
    aMaterialPropertiesTable->GetProperty("RINDEX");
  if (!Rindex) return pParticleChange;
  
  // particle charge
  const G4double charge = aParticle->GetDefinition()->GetPDGCharge();
  
  // particle beta
  const G4double beta = (pPreStepPoint ->GetBeta() +
			 pPostStepPoint->GetBeta())/2.;

  G4double step_length = aStep.GetStepLength();

  G4double MeanNumberOfPhotons=GetAverageNumberOfPhotons(charge,beta,step_length/cm,x0,p0);

  // Copy and paste from the original function
  if (MeanNumberOfPhotons <= 0.0) {
    // return unchanged particle and no secondaries
    aParticleChange.SetNumberOfSecondaries(0);
    return pParticleChange;
  }
  
  MeanNumberOfPhotons *= step_length;
  
  G4int NumPhotons = (G4int) G4Poisson(MeanNumberOfPhotons);
  
  if (NumPhotons <= 0) {
    // return unchanged particle and no secondaries  
    aParticleChange.SetNumberOfSecondaries(0);
    return pParticleChange;
  }

  ////////////////////////////////////////////////////////////////
  
  aParticleChange.SetNumberOfSecondaries(NumPhotons);
  
  if (fTrackSecondariesFirst) {
    if (aTrack.GetTrackStatus() == fAlive )
      aParticleChange.ProposeTrackStatus(fSuspend);
  }
  
  ////////////////////////////////////////////////////////////////

  G4double BetaInverse = 1./beta;
  for (G4int i = 0; i < NumPhotons; i++) {
    G4double sampledEnergy, sampledRI; 
    G4double cosTheta, sin2Theta;

    geant _RINDEX;
    geant _p;
    _p=getmomentum_(&_RINDEX); // _p is in GeV/c, _RINDEX is the refractive index for this guy

    sampledEnergy=_p*GeV;     // energy in G4 units
    sampledRI=_RINDEX;
    cosTheta = BetaInverse / sampledRI;  
    sin2Theta = (1.0 - cosTheta)*(1.0 + cosTheta);

    // Generate random position of photon on cone surface 
    // defined by Theta 
    G4double rand = G4UniformRand();
    G4double phi = twopi*rand;
    G4double sinPhi = sin(phi);
    G4double cosPhi = cos(phi);
    // calculate x,y, and z components of photon energy
    // (in coord system with primary particle direction 
    //  aligned with the z axis)
    
    G4double sinTheta = sqrt(sin2Theta); 
    G4double px = sinTheta*cosPhi;
    G4double py = sinTheta*sinPhi;
    G4double pz = cosTheta;
    // Create photon momentum direction vector 
    // The momentum direction is still with respect
    // to the coordinate system where the primary
    // particle direction is aligned with the z axis  
    G4ParticleMomentum photonMomentum(px, py, pz);
    // Rotate momentum direction back to global reference
    // system 
    photonMomentum.rotateUz(p0);
    // Determine polarization of new photon 
    G4double sx = cosTheta*cosPhi;
    G4double sy = cosTheta*sinPhi; 
    G4double sz = -sinTheta;
    G4ThreeVector photonPolarization(sx, sy, sz);
    // Rotate back to original coord system 
    photonPolarization.rotateUz(p0);
    // Generate a new photon:

    G4DynamicParticle* aCerenkovPhoton =
      new G4DynamicParticle(G4OpticalPhoton::OpticalPhoton(), 
			    photonMomentum);
    aCerenkovPhoton->SetPolarization
      (photonPolarization.x(),
       photonPolarization.y(),
       photonPolarization.z());
    aCerenkovPhoton->SetKineticEnergy(sampledEnergy);
    rand = G4UniformRand();
    G4double delta=rand*aStep.GetStepLength();
    G4double deltaTime = delta /
      ((pPreStepPoint->GetVelocity()+
	pPostStepPoint->GetVelocity())/2.);
    
    G4double aSecondaryTime = t0 + deltaTime;
    
    G4ThreeVector aSecondaryPosition = x0 + rand * aStep.GetDeltaPosition();
    
    G4Track* aSecondaryTrack = new G4Track(aCerenkovPhoton,aSecondaryTime,aSecondaryPosition);
    aSecondaryTrack->SetTouchableHandle(aStep.GetPreStepPoint()->GetTouchableHandle());
    aSecondaryTrack->SetParentID(aTrack.GetTrackID());
    aParticleChange.AddSecondary(aSecondaryTrack);
  }

  if (verboseLevel>0) {
    G4cout << "\n Exiting from RichG4Cerenkov::DoIt -- NumberOfSecondaries = " 
	   << aParticleChange.GetNumberOfSecondaries() << G4endl;
  }
  
  return pParticleChange;
}
示例#7
0
文件: g4rich.C 项目: krafczyk/AMS
G4VParticleChange*
RichG4OpBoundaryProcess::PostStepDoIt(const G4Track& aTrack, const G4Step& aStep)
{
  // I do not know where these guys come, but I kill them explicitly
  if(isnan(aTrack.GetPosition()[0]) || isnan(aTrack.GetMomentum()[0])){
    aParticleChange.ProposeTrackStatus(fStopAndKill);
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }

  // Initialization
  aParticleChange.Initialize(aTrack);

  // Get the properties of the particle
  const G4DynamicParticle* aParticle = aTrack.GetDynamicParticle();

  G4double thePhotonMomentum      = aParticle->GetTotalMomentum();
  G4StepPoint* pPreStepPoint  = aStep.GetPreStepPoint();
  G4StepPoint* pPostStepPoint = aStep.GetPostStepPoint();


  if(isnan(pPreStepPoint->GetPosition()[0])){
    aParticleChange.ProposeTrackStatus(fStopAndKill);
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }
  
  if (pPostStepPoint->GetStepStatus() != fGeomBoundary){
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }

  if (aTrack.GetStepLength()<=1e-7){
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }
  
  G4Material *Material1 = pPreStepPoint  -> GetMaterial();
  G4Material *Material2 = pPostStepPoint -> GetMaterial();
  
  // Follow the standard path if not RICH radiator to vacuum transition
  if(!(Material1->GetName()==aerogel_name))
    return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);
//      return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);

  if(Material2->GetName()==aerogel_name)
    return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);
//      return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);
   
  if(!Material1->GetMaterialPropertiesTable() ||
     !Material2->GetMaterialPropertiesTable()){
    aParticleChange.ProposeTrackStatus(fStopAndKill);
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }


  OldMomentum       = aParticle->GetMomentumDirection();
  OldPolarization   = aParticle->GetPolarization();


  // Get the normal of the surface
  G4ThreeVector theGlobalPoint = pPostStepPoint->GetPosition();


  G4Navigator* theNavigator =
    G4TransportationManager::GetTransportationManager()->
    GetNavigatorForTracking();
  
  G4ThreeVector theLocalPoint = theNavigator->
    GetGlobalToLocalTransform().
    TransformPoint(theGlobalPoint);
  
  G4ThreeVector theLocalNormal;   // Normal points back into volume
  
  G4bool valid;
  theLocalNormal = theNavigator->GetLocalExitNormal(&valid);
  
  if (valid) {
    theLocalNormal = -theLocalNormal;
  }
  else {
    aParticleChange.ProposeTrackStatus(fStopAndKill);
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);

    G4cerr << " RichG4OpBoundaryProcess/PostStepDoIt(): "
	   << " The Navigator reports that it returned an invalid normal"
	   << G4endl;
    G4Exception("RichG4OpBoundaryProcess::PostStepDoIt",
		"Invalid Surface Normal",
		EventMustBeAborted,
		"Geometry must return valid surface normal");
    //    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }
  
  theGlobalNormal = theNavigator->GetLocalToGlobalTransform().
    TransformAxis(theLocalNormal);
  
  if (OldMomentum * theGlobalNormal > 0.0) {
    theGlobalNormal = -theGlobalNormal;
  }
  
  // Get the refractive index
  G4ThreeVector position = aTrack.GetPosition();
  const G4double cvpwl=1.2398E-6;
  G4double wavelength=cvpwl/thePhotonMomentum*GeV;

  Rindex1=RichRadiatorTileManager::get_refractive_index(position[0]/cm,position[1]/cm,wavelength);
  G4MaterialPropertyVector* Rindex = Material2->GetMaterialPropertiesTable()->GetProperty("RINDEX");

  if(!Rindex){
    aParticleChange.ProposeTrackStatus(fStopAndKill);
    return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
  }
#if G4VERSION_NUMBER >945
  Rindex2 = Rindex->Value(thePhotonMomentum);
#else
  Rindex2 = Rindex->GetProperty(thePhotonMomentum);
#endif
  
  // SKIP photons exiting through the lateral sides of the tiles
   if(std::abs(theGlobalNormal[2])<1e-6){
cout <<" g4rich::abs "<<std::abs(theGlobalNormal[2])<<" "<<abs(theGlobalNormal[2])<<" "<<theGlobalNormal[2]<<endl;
     return G4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);
   } 
//   if(abs(theGlobalNormal[2])<1e-6)  return TOFG4OpBoundaryProcess::PostStepDoIt(aTrack,aStep);  

  DielectricDielectric();
  //  return G4OpBoundaryProcess::PostStepDoIt(aTrack, aStep); //CJD this solves the f*****g problem 

  NewMomentum = NewMomentum.unit();
  NewPolarization = NewPolarization.unit();

  if(Material1->GetName()==aerogel_name){
    // Simple parameterization to get the right number of p.e.
    if(G4UniformRand()<RICHDB::scatloss){
      aParticleChange.ProposeTrackStatus(fStopAndKill);
      return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
    }
    
    // Forward scattering
    if(G4UniformRand()<RICHDB::scatprob){
      // Aerogel scattering effect
      double phi=2*M_PI*G4UniformRand();
      double theta=sqrt(-2*log(G4UniformRand()))*RICHDB::scatang;
      
      // Build the vector
    G4ThreeVector direction(sin(theta)*cos(phi),sin(theta)*sin(phi),cos(theta));
    direction.rotateUz(NewMomentum);
    NewMomentum=direction.unit();
    }
  }

  aParticleChange.ProposeMomentumDirection(NewMomentum);
  aParticleChange.ProposePolarization(NewPolarization);

  return G4VDiscreteProcess::PostStepDoIt(aTrack, aStep);
}