// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // G4AdjointPosOnPhysVolGenerator class implementation // // Author: L. Desorgher, SpaceIT GmbH - 01.06.2006 // Contract: ESA contract 21435/08/NL/AT // Customer: ESA/ESTEC // -------------------------------------------------------------------- #include "G4AdjointPosOnPhysVolGenerator.hh" #include "G4VSolid.hh" #include "G4VoxelLimits.hh" #include "G4AffineTransform.hh" #include "Randomize.hh" #include "G4VPhysicalVolume.hh" #include "G4PhysicalVolumeStore.hh" #include "G4LogicalVolumeStore.hh" G4ThreadLocal G4AdjointPosOnPhysVolGenerator* G4AdjointPosOnPhysVolGenerator::theInstance = nullptr; // -------------------------------------------------------------------- // G4AdjointPosOnPhysVolGenerator* G4AdjointPosOnPhysVolGenerator::GetInstance() { if(theInstance == nullptr) { theInstance = new G4AdjointPosOnPhysVolGenerator; } return theInstance; } // -------------------------------------------------------------------- // G4AdjointPosOnPhysVolGenerator::~G4AdjointPosOnPhysVolGenerator() { } //////////////////////////////////////////////////// // G4AdjointPosOnPhysVolGenerator::G4AdjointPosOnPhysVolGenerator() : UseSphere(true), ModelOfSurfaceSource("OnSolid"), AreaOfExtSurfaceOfThePhysicalVolume(0.), CosThDirComparedToNormal(0.) { } // -------------------------------------------------------------------- // G4VPhysicalVolume* G4AdjointPosOnPhysVolGenerator::DefinePhysicalVolume(const G4String& aName) { thePhysicalVolume = nullptr; theSolid = nullptr; G4PhysicalVolumeStore* thePhysVolStore = G4PhysicalVolumeStore::GetInstance(); for ( unsigned int i=0; i< thePhysVolStore->size(); ++i ) { G4String vol_name =(*thePhysVolStore)[i]->GetName(); if (vol_name == "") { vol_name = (*thePhysVolStore)[i]->GetLogicalVolume()->GetName(); } if (vol_name == aName) { thePhysicalVolume = (*thePhysVolStore)[i]; } } if (thePhysicalVolume != nullptr) { theSolid = thePhysicalVolume->GetLogicalVolume()->GetSolid(); ComputeTransformationFromPhysVolToWorld(); } else { G4cout << "The physical volume with name " << aName << " does not exist!!" << G4endl; G4cout << "Before generating a source on an external surface " << G4endl << "of a volume you should select another physical volume." << G4endl; } return thePhysicalVolume; } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator::DefinePhysicalVolume1(const G4String& aName) { thePhysicalVolume = DefinePhysicalVolume(aName); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface() { return ComputeAreaOfExtSurface(theSolid); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface(G4int NStats) { return ComputeAreaOfExtSurface(theSolid,NStats); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface(G4double eps) { return ComputeAreaOfExtSurface(theSolid,eps); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface(G4VSolid* aSolid) { return ComputeAreaOfExtSurface(aSolid,1.e-3); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface(G4VSolid* aSolid, G4int NStats) { if (ModelOfSurfaceSource == "OnSolid") { if (UseSphere) { return ComputeAreaOfExtSurfaceStartingFromSphere(aSolid,NStats); } else { return ComputeAreaOfExtSurfaceStartingFromBox(aSolid,NStats); } } else { G4ThreeVector p, dir; if (ModelOfSurfaceSource == "ExternalSphere") { return GenerateAPositionOnASphereBoundary(aSolid, p,dir); } return GenerateAPositionOnABoxBoundary(aSolid, p,dir); } } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator::ComputeAreaOfExtSurface(G4VSolid* aSolid, G4double eps) { G4int Nstats = G4int(1./(eps*eps)); return ComputeAreaOfExtSurface(aSolid,Nstats); } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator:: GenerateAPositionOnTheExtSurfaceOfASolid(G4VSolid* aSolid, G4ThreeVector& p, G4ThreeVector& direction) { if (ModelOfSurfaceSource == "OnSolid") { GenerateAPositionOnASolidBoundary(aSolid, p,direction); return; } if (ModelOfSurfaceSource == "ExternalSphere") { GenerateAPositionOnASphereBoundary(aSolid, p, direction); return; } GenerateAPositionOnABoxBoundary(aSolid, p, direction); return; } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator:: GenerateAPositionOnTheExtSurfaceOfTheSolid(G4ThreeVector& p, G4ThreeVector& direction) { GenerateAPositionOnTheExtSurfaceOfASolid(theSolid,p,direction); } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator:: ComputeAreaOfExtSurfaceStartingFromBox(G4VSolid* aSolid, G4int Nstat) { if ( Nstat <= 0 ) { return 0.; } G4double area=1.; G4int i=0, j=0; while (iDistanceToIn(p,direction); if (dist_to_inDistanceToIn(p,direction); if (dist_to_inDistanceToIn(p,direction); if (dist_to_inCalculateExtent(kXAxis,limit,origin,minX,maxX); aSolid->CalculateExtent(kYAxis,limit,origin,minY,maxY); aSolid->CalculateExtent(kZAxis,limit,origin,minZ,maxZ); G4ThreeVector center = G4ThreeVector((minX+maxX)/2., (minY+maxY)/2., (minZ+maxZ)/2.); G4double dX=(maxX-minX)/2.; G4double dY=(maxY-minY)/2.; G4double dZ=(maxZ-minZ)/2.; G4double scale=1.01; G4double r=scale*std::sqrt(dX*dX+dY*dY+dZ*dZ); G4double cos_th2 = G4UniformRand(); G4double theta = std::acos(std::sqrt(cos_th2)); G4double phi=G4UniformRand()*CLHEP::twopi; direction.setRThetaPhi(1.,theta,phi); direction=-direction; G4double cos_th = (1.-2.*G4UniformRand()); theta = std::acos(cos_th); if (G4UniformRand() < 0.5) { theta=CLHEP::pi-theta; } phi=G4UniformRand()*CLHEP::twopi; p.setRThetaPhi(r,theta,phi); p+=center; direction.rotateY(theta); direction.rotateZ(phi); return 4.*CLHEP::pi*r*r;; } // -------------------------------------------------------------------- // G4double G4AdjointPosOnPhysVolGenerator:: GenerateAPositionOnABoxBoundary(G4VSolid* aSolid, G4ThreeVector& p, G4ThreeVector& direction) { G4double ran_var,px,py,pz,minX,maxX,minY,maxY,minZ,maxZ; // values needed for CalculateExtent signature G4VoxelLimits limit; // Unlimited G4AffineTransform origin; // min max extents of pSolid along X,Y,Z aSolid->CalculateExtent(kXAxis,limit,origin,minX,maxX); aSolid->CalculateExtent(kYAxis,limit,origin,minY,maxY); aSolid->CalculateExtent(kZAxis,limit,origin,minZ,maxZ); G4double scale=.1; minX-=scale*std::abs(minX); minY-=scale*std::abs(minY); minZ-=scale*std::abs(minZ); maxX+=scale*std::abs(maxX); maxY+=scale*std::abs(maxY); maxZ+=scale*std::abs(maxZ); G4double dX=(maxX-minX); G4double dY=(maxY-minY); G4double dZ=(maxZ-minZ); G4double XY_prob=2.*dX*dY; G4double YZ_prob=2.*dY*dZ; G4double ZX_prob=2.*dZ*dX; G4double area=XY_prob+YZ_prob+ZX_prob; XY_prob/=area; YZ_prob/=area; ZX_prob/=area; ran_var=G4UniformRand(); G4double cos_th2 = G4UniformRand(); G4double sth = std::sqrt(1.-cos_th2); G4double cth = std::sqrt(cos_th2); G4double phi = G4UniformRand()*CLHEP::twopi; G4double dirX = sth*std::cos(phi); G4double dirY = sth*std::sin(phi); G4double dirZ = cth; if (ran_var <=XY_prob) // on the XY faces { G4double ran_var1=ran_var/XY_prob; G4double ranX=ran_var1; if (ran_var1<=0.5) { pz=minZ; direction=G4ThreeVector(dirX,dirY,dirZ); ranX=ran_var1*2.; } else { pz=maxZ; direction=-G4ThreeVector(dirX,dirY,dirZ); ranX=(ran_var1-0.5)*2.; } G4double ranY=G4UniformRand(); px=minX+(maxX-minX)*ranX; py=minY+(maxY-minY)*ranY; } else if (ran_var <=(XY_prob+YZ_prob)) // on the YZ faces { G4double ran_var1=(ran_var-XY_prob)/YZ_prob; G4double ranY=ran_var1; if (ran_var1<=0.5) { px=minX; direction=G4ThreeVector(dirZ,dirX,dirY); ranY=ran_var1*2.; } else { px=maxX; direction=-G4ThreeVector(dirZ,dirX,dirY); ranY=(ran_var1-0.5)*2.; } G4double ranZ=G4UniformRand(); py=minY+(maxY-minY)*ranY; pz=minZ+(maxZ-minZ)*ranZ; } else // on the ZX faces { G4double ran_var1=(ran_var-XY_prob-YZ_prob)/ZX_prob; G4double ranZ=ran_var1; if (ran_var1<=0.5) { py=minY; direction=G4ThreeVector(dirY,dirZ,dirX); ranZ=ran_var1*2.; } else { py=maxY; direction=-G4ThreeVector(dirY,dirZ,dirX); ranZ=(ran_var1-0.5)*2.; } G4double ranX=G4UniformRand(); px=minX+(maxX-minX)*ranX; pz=minZ+(maxZ-minZ)*ranZ; } p=G4ThreeVector(px,py,pz); return area; } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator:: GenerateAPositionOnTheExtSurfaceOfThePhysicalVolume(G4ThreeVector& p, G4ThreeVector& direction) { if (thePhysicalVolume == nullptr) { G4cout << "Before generating a source on an external surface" << G4endl << "of volume you should select a physical volume" << G4endl; return; } GenerateAPositionOnTheExtSurfaceOfTheSolid(p,direction); p = theTransformationFromPhysVolToWorld.TransformPoint(p); direction = theTransformationFromPhysVolToWorld.TransformAxis(direction); } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator:: GenerateAPositionOnTheExtSurfaceOfThePhysicalVolume(G4ThreeVector& p, G4ThreeVector& direction, G4double& costh_to_normal) { GenerateAPositionOnTheExtSurfaceOfThePhysicalVolume(p, direction); costh_to_normal = CosThDirComparedToNormal; } // -------------------------------------------------------------------- // void G4AdjointPosOnPhysVolGenerator::ComputeTransformationFromPhysVolToWorld() { G4VPhysicalVolume* daughter = thePhysicalVolume; G4LogicalVolume* mother = thePhysicalVolume->GetMotherLogical(); theTransformationFromPhysVolToWorld = G4AffineTransform(); G4PhysicalVolumeStore* thePhysVolStore = G4PhysicalVolumeStore::GetInstance(); while (mother != nullptr) { theTransformationFromPhysVolToWorld *= G4AffineTransform(daughter->GetFrameRotation(), daughter->GetObjectTranslation()); for ( unsigned int i=0; isize(); ++i ) { if ((*thePhysVolStore)[i]->GetLogicalVolume() == mother) { daughter = (*thePhysVolStore)[i]; mother = daughter->GetMotherLogical(); break; } } } }