Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
G4AdjointPosOnPhysVolGenerator.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4AdjointPosOnPhysVolGenerator class implementation
27//
28// Author: L. Desorgher, SpaceIT GmbH - 01.06.2006
29// Contract: ESA contract 21435/08/NL/AT
30// Customer: ESA/ESTEC
31// --------------------------------------------------------------------
32
34#include "G4VSolid.hh"
35#include "G4VoxelLimits.hh"
36#include "G4AffineTransform.hh"
37#include "Randomize.hh"
38#include "G4VPhysicalVolume.hh"
41
43G4AdjointPosOnPhysVolGenerator::theInstance = nullptr;
44
45// --------------------------------------------------------------------
46//
48{
49 if(theInstance == nullptr)
50 {
51 theInstance = new G4AdjointPosOnPhysVolGenerator;
52 }
53 return theInstance;
54}
55
56// --------------------------------------------------------------------
57//
60{
61 thePhysicalVolume = nullptr;
62 theSolid = nullptr;
64 for ( unsigned int i=0; i< thePhysVolStore->size(); ++i )
65 {
66 G4String vol_name =(*thePhysVolStore)[i]->GetName();
67 if (vol_name.empty())
68 {
69 vol_name = (*thePhysVolStore)[i]->GetLogicalVolume()->GetName();
70 }
71 if (vol_name == aName)
72 {
73 thePhysicalVolume = (*thePhysVolStore)[i];
74 }
75 }
76 if (thePhysicalVolume != nullptr)
77 {
78 theSolid = thePhysicalVolume->GetLogicalVolume()->GetSolid();
79 ComputeTransformationFromPhysVolToWorld();
80 }
81 else
82 {
83 G4cout << "The physical volume with name " << aName
84 << " does not exist!!" << G4endl;
85 G4cout << "Before generating a source on an external surface " << G4endl
86 << "of a volume you should select another physical volume."
87 << G4endl;
88 }
89 return thePhysicalVolume;
90}
91
92// --------------------------------------------------------------------
93//
94void
96{
97 thePhysicalVolume = DefinePhysicalVolume(aName);
98}
99
100// --------------------------------------------------------------------
101//
103{
104 return ComputeAreaOfExtSurface(theSolid);
105}
106
107// --------------------------------------------------------------------
108//
110{
111 return ComputeAreaOfExtSurface(theSolid,NStats);
112}
113
114// --------------------------------------------------------------------
115//
117{
118 return ComputeAreaOfExtSurface(theSolid,eps);
119}
120
121// --------------------------------------------------------------------
122//
125{
126 return ComputeAreaOfExtSurface(aSolid,1.e-3);
127}
128
129// --------------------------------------------------------------------
130//
133 G4int NStats)
134{
135 if (ModelOfSurfaceSource == "OnSolid")
136 {
137 if (UseSphere)
138 {
139 return ComputeAreaOfExtSurfaceStartingFromSphere(aSolid,NStats);
140 }
141
142 return ComputeAreaOfExtSurfaceStartingFromBox(aSolid,NStats);
143 }
144
145 G4ThreeVector p, dir;
146 if (ModelOfSurfaceSource == "ExternalSphere")
147 {
148 return GenerateAPositionOnASphereBoundary(aSolid, p,dir);
149 }
150
151 return GenerateAPositionOnABoxBoundary(aSolid, p,dir);
152}
153
154// --------------------------------------------------------------------
155//
158 G4double eps)
159{
160 G4int Nstats = G4int(1./(eps*eps));
161 return ComputeAreaOfExtSurface(aSolid,Nstats);
162}
163
164// --------------------------------------------------------------------
165//
168 G4ThreeVector& direction)
169{
170 if (ModelOfSurfaceSource == "OnSolid")
171 {
172 GenerateAPositionOnASolidBoundary(aSolid, p,direction);
173 return;
174 }
175 if (ModelOfSurfaceSource == "ExternalSphere")
176 {
177 GenerateAPositionOnASphereBoundary(aSolid, p, direction);
178 return;
179 }
180 GenerateAPositionOnABoxBoundary(aSolid, p, direction);
181 return;
182}
183
184// --------------------------------------------------------------------
185//
188 G4ThreeVector& direction)
189{
190 GenerateAPositionOnTheExtSurfaceOfASolid(theSolid,p,direction);
191}
192
193// --------------------------------------------------------------------
194//
195G4double G4AdjointPosOnPhysVolGenerator::
196ComputeAreaOfExtSurfaceStartingFromBox(G4VSolid* aSolid, G4int Nstat)
197{
198 if ( Nstat <= 0 ) { return 0.; }
199 G4double area=1.;
200 G4int i=0, j=0;
201 while (i<Nstat)
202 {
203 G4ThreeVector p, direction;
204 area = GenerateAPositionOnABoxBoundary( aSolid,p, direction);
205 G4double dist_to_in = aSolid->DistanceToIn(p,direction);
206 if (dist_to_in<kInfinity/2.) { ++i; }
207 ++j;
208 }
209 area=area*G4double(i)/G4double(j);
210 return area;
211}
212
213// --------------------------------------------------------------------
214//
215G4double G4AdjointPosOnPhysVolGenerator::
216ComputeAreaOfExtSurfaceStartingFromSphere(G4VSolid* aSolid, G4int Nstat)
217{
218 if ( Nstat <= 0 ) { return 0.; }
219 G4double area=1.;
220 G4int i=0, j=0;
221 while (i<Nstat)
222 {
223 G4ThreeVector p, direction;
224 area = GenerateAPositionOnASphereBoundary( aSolid,p, direction);
225 G4double dist_to_in = aSolid->DistanceToIn(p,direction);
226 if (dist_to_in<kInfinity/2.) { ++i; }
227 ++j;
228 }
229 area=area*G4double(i)/G4double(j);
230 return area;
231}
232
233// --------------------------------------------------------------------
234//
235void G4AdjointPosOnPhysVolGenerator::
236GenerateAPositionOnASolidBoundary(G4VSolid* aSolid, G4ThreeVector& p,
237 G4ThreeVector& direction)
238{
239 G4bool find_pos = false;
240 while (!find_pos)
241 {
242 if (UseSphere)
243 {
244 GenerateAPositionOnASphereBoundary( aSolid,p, direction );
245 }
246 else
247 {
248 GenerateAPositionOnABoxBoundary( aSolid,p, direction);
249 }
250 G4double dist_to_in = aSolid->DistanceToIn(p,direction);
251 if (dist_to_in<kInfinity/2.)
252 {
253 find_pos = true;
254 p += 0.999999*direction*dist_to_in;
255 }
256 }
257}
258
259// --------------------------------------------------------------------
260//
261G4double G4AdjointPosOnPhysVolGenerator::
262GenerateAPositionOnASphereBoundary(G4VSolid* aSolid, G4ThreeVector& p,
263 G4ThreeVector& direction)
264{
265 G4double minX,maxX,minY,maxY,minZ,maxZ;
266
267 // values needed for CalculateExtent signature
268
269 G4VoxelLimits limit; // Unlimited
270 G4AffineTransform origin;
271
272 // min max extents of pSolid along X,Y,Z
273
274 aSolid->CalculateExtent(kXAxis,limit,origin,minX,maxX);
275 aSolid->CalculateExtent(kYAxis,limit,origin,minY,maxY);
276 aSolid->CalculateExtent(kZAxis,limit,origin,minZ,maxZ);
277
278 G4ThreeVector center = G4ThreeVector((minX+maxX)/2.,
279 (minY+maxY)/2.,
280 (minZ+maxZ)/2.);
281 G4double dX=(maxX-minX)/2.;
282 G4double dY=(maxY-minY)/2.;
283 G4double dZ=(maxZ-minZ)/2.;
284 G4double scale=1.01;
285 G4double r=scale*std::sqrt(dX*dX+dY*dY+dZ*dZ);
286
287 G4double cos_th2 = G4UniformRand();
288 G4double theta = std::acos(std::sqrt(cos_th2));
289 G4double phi=G4UniformRand()*CLHEP::twopi;
290 direction.setRThetaPhi(1.,theta,phi);
291 direction=-direction;
292 G4double cos_th = (1.-2.*G4UniformRand());
293 theta = std::acos(cos_th);
294 if (G4UniformRand() < 0.5) { theta=CLHEP::pi-theta; }
295 phi=G4UniformRand()*CLHEP::twopi;
296 p.setRThetaPhi(r,theta,phi);
297 p+=center;
298 direction.rotateY(theta);
299 direction.rotateZ(phi);
300 return 4.*CLHEP::pi*r*r;;
301}
302
303// --------------------------------------------------------------------
304//
305G4double G4AdjointPosOnPhysVolGenerator::
306GenerateAPositionOnABoxBoundary(G4VSolid* aSolid, G4ThreeVector& p,
307 G4ThreeVector& direction)
308{
309
310 G4double ran_var,px,py,pz,minX,maxX,minY,maxY,minZ,maxZ;
311
312 // values needed for CalculateExtent signature
313
314 G4VoxelLimits limit; // Unlimited
315 G4AffineTransform origin;
316
317 // min max extents of pSolid along X,Y,Z
318
319 aSolid->CalculateExtent(kXAxis,limit,origin,minX,maxX);
320 aSolid->CalculateExtent(kYAxis,limit,origin,minY,maxY);
321 aSolid->CalculateExtent(kZAxis,limit,origin,minZ,maxZ);
322
323 G4double scale=.1;
324 minX-=scale*std::abs(minX);
325 minY-=scale*std::abs(minY);
326 minZ-=scale*std::abs(minZ);
327 maxX+=scale*std::abs(maxX);
328 maxY+=scale*std::abs(maxY);
329 maxZ+=scale*std::abs(maxZ);
330
331 G4double dX=(maxX-minX);
332 G4double dY=(maxY-minY);
333 G4double dZ=(maxZ-minZ);
334
335 G4double XY_prob=2.*dX*dY;
336 G4double YZ_prob=2.*dY*dZ;
337 G4double ZX_prob=2.*dZ*dX;
338 G4double area=XY_prob+YZ_prob+ZX_prob;
339 XY_prob/=area;
340 YZ_prob/=area;
341 ZX_prob/=area;
342
343 ran_var=G4UniformRand();
344 G4double cos_th2 = G4UniformRand();
345 G4double sth = std::sqrt(1.-cos_th2);
346 G4double cth = std::sqrt(cos_th2);
347 G4double phi = G4UniformRand()*CLHEP::twopi;
348 G4double dirX = sth*std::cos(phi);
349 G4double dirY = sth*std::sin(phi);
350 G4double dirZ = cth;
351 if (ran_var <=XY_prob) // on the XY faces
352 {
353 G4double ran_var1=ran_var/XY_prob;
354 G4double ranX=ran_var1;
355 if (ran_var1<=0.5)
356 {
357 pz=minZ;
358 direction=G4ThreeVector(dirX,dirY,dirZ);
359 ranX=ran_var1*2.;
360 }
361 else
362 {
363 pz=maxZ;
364 direction=-G4ThreeVector(dirX,dirY,dirZ);
365 ranX=(ran_var1-0.5)*2.;
366 }
367 G4double ranY=G4UniformRand();
368 px=minX+(maxX-minX)*ranX;
369 py=minY+(maxY-minY)*ranY;
370 }
371 else if (ran_var <=(XY_prob+YZ_prob)) // on the YZ faces
372 {
373 G4double ran_var1=(ran_var-XY_prob)/YZ_prob;
374 G4double ranY=ran_var1;
375 if (ran_var1<=0.5)
376 {
377 px=minX;
378 direction=G4ThreeVector(dirZ,dirX,dirY);
379 ranY=ran_var1*2.;
380 }
381 else
382 {
383 px=maxX;
384 direction=-G4ThreeVector(dirZ,dirX,dirY);
385 ranY=(ran_var1-0.5)*2.;
386 }
387 G4double ranZ=G4UniformRand();
388 py=minY+(maxY-minY)*ranY;
389 pz=minZ+(maxZ-minZ)*ranZ;
390 }
391 else // on the ZX faces
392 {
393 G4double ran_var1=(ran_var-XY_prob-YZ_prob)/ZX_prob;
394 G4double ranZ=ran_var1;
395 if (ran_var1<=0.5)
396 {
397 py=minY;
398 direction=G4ThreeVector(dirY,dirZ,dirX);
399 ranZ=ran_var1*2.;
400 }
401 else
402 {
403 py=maxY;
404 direction=-G4ThreeVector(dirY,dirZ,dirX);
405 ranZ=(ran_var1-0.5)*2.;
406 }
407 G4double ranX=G4UniformRand();
408 px=minX+(maxX-minX)*ranX;
409 pz=minZ+(maxZ-minZ)*ranZ;
410 }
411
412 p=G4ThreeVector(px,py,pz);
413 return area;
414}
415
416// --------------------------------------------------------------------
417//
420 G4ThreeVector& direction)
421{
422 if (thePhysicalVolume == nullptr)
423 {
424 G4cout << "Before generating a source on an external surface" << G4endl
425 << "of volume you should select a physical volume" << G4endl;
426 return;
427 }
429 p = theTransformationFromPhysVolToWorld.TransformPoint(p);
430 direction = theTransformationFromPhysVolToWorld.TransformAxis(direction);
431}
432
433// --------------------------------------------------------------------
434//
437 G4ThreeVector& direction,
438 G4double& costh_to_normal)
439{
441 costh_to_normal = CosThDirComparedToNormal;
442}
443
444// --------------------------------------------------------------------
445//
446void G4AdjointPosOnPhysVolGenerator::ComputeTransformationFromPhysVolToWorld()
447{
448 G4VPhysicalVolume* daughter = thePhysicalVolume;
449 G4LogicalVolume* mother = thePhysicalVolume->GetMotherLogical();
450 theTransformationFromPhysVolToWorld = G4AffineTransform();
452 while (mother != nullptr)
453 {
454 theTransformationFromPhysVolToWorld *=
456 daughter->GetObjectTranslation());
457 for ( unsigned int i=0; i<thePhysVolStore->size(); ++i )
458 {
459 if ((*thePhysVolStore)[i]->GetLogicalVolume() == mother)
460 {
461 daughter = (*thePhysVolStore)[i];
462 mother = daughter->GetMotherLogical();
463 break;
464 }
465 }
466 }
467}
CLHEP::Hep3Vector G4ThreeVector
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4GLOB_DLL std::ostream G4cout
#define G4UniformRand()
Definition: Randomize.hh:52
Hep3Vector & rotateY(double)
Definition: ThreeVector.cc:97
Hep3Vector & rotateZ(double)
Definition: ThreeVector.cc:107
void setRThetaPhi(double r, double theta, double phi)
void GenerateAPositionOnTheExtSurfaceOfTheSolid(G4ThreeVector &p, G4ThreeVector &direction)
void GenerateAPositionOnTheExtSurfaceOfThePhysicalVolume(G4ThreeVector &p, G4ThreeVector &direction)
G4VPhysicalVolume * DefinePhysicalVolume(const G4String &aName)
void DefinePhysicalVolume1(const G4String &aName)
void GenerateAPositionOnTheExtSurfaceOfASolid(G4VSolid *aSolid, G4ThreeVector &p, G4ThreeVector &direction)
static G4AdjointPosOnPhysVolGenerator * GetInstance()
G4ThreeVector TransformPoint(const G4ThreeVector &vec) const
G4ThreeVector TransformAxis(const G4ThreeVector &axis) const
G4VSolid * GetSolid() const
static G4PhysicalVolumeStore * GetInstance()
G4LogicalVolume * GetMotherLogical() const
G4LogicalVolume * GetLogicalVolume() const
const G4RotationMatrix * GetFrameRotation() const
G4ThreeVector GetObjectTranslation() const
virtual G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const =0
virtual G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const =0
@ kYAxis
Definition: geomdefs.hh:56
@ kXAxis
Definition: geomdefs.hh:55
@ kZAxis
Definition: geomdefs.hh:57
#define G4ThreadLocal
Definition: tls.hh:77