Geant4 10.7.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4AdjointCrossSurfChecker.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// G4AdjointCrossSurfChecker class implementation
27//
28// Author: L. Desorgher, SpaceIT GmbH
29// Contract: ESA contract 21435/08/NL/AT
30// Customer: ESA/ESTEC
31// --------------------------------------------------------------------
32
35#include "G4SystemOfUnits.hh"
36#include "G4Step.hh"
37#include "G4StepPoint.hh"
39#include "G4VSolid.hh"
40#include "G4AffineTransform.hh"
41
42//////////////////////////////////////////////////////////////////////////////
43//
45 G4AdjointCrossSurfChecker::instance = nullptr;
46
47//////////////////////////////////////////////////////////////////////////////
48//
49G4AdjointCrossSurfChecker::G4AdjointCrossSurfChecker()
50{
51}
52
53//////////////////////////////////////////////////////////////////////////////
54//
55G4AdjointCrossSurfChecker::~G4AdjointCrossSurfChecker()
56{
57 delete instance;
58}
59
60//////////////////////////////////////////////////////////////////////////////
61//
63{
64 if (instance == nullptr) instance = new G4AdjointCrossSurfChecker();
65 return instance;
66}
67
68//////////////////////////////////////////////////////////////////////////////
69//
71CrossingASphere(const G4Step* aStep, G4double sphere_radius,
72 G4ThreeVector sphere_center, G4ThreeVector& crossing_pos,
73 G4double& cos_th , G4bool& GoingIn)
74{
75 G4ThreeVector pos1 = aStep->GetPreStepPoint()->GetPosition() - sphere_center;
76 G4ThreeVector pos2 = aStep->GetPostStepPoint()->GetPosition() - sphere_center;
77 G4double r1 = pos1.mag();
78 G4double r2 = pos2.mag();
79 G4bool did_cross = false;
80
81 if (r1<=sphere_radius && r2>sphere_radius)
82 {
83 did_cross = true;
84 GoingIn = false;
85 }
86 else if (r2<=sphere_radius && r1>sphere_radius)
87 {
88 did_cross = true;
89 GoingIn = true;
90 }
91
92 if (did_cross)
93 {
94 G4ThreeVector dr = pos2-pos1;
95 G4double r12 = r1*r1;
96 G4double rdr = dr.mag();
97 G4double a,b,c,d;
98 a = rdr*rdr;
99 b = 2.*pos1.dot(dr);
100 c = r12-sphere_radius*sphere_radius;
101 d = std::sqrt(b*b-4.*a*c);
102 G4double l = (-b+d)/2./a;
103 if (l > 1.) l=(-b-d)/2./a;
104 crossing_pos = pos1+l*dr;
105 cos_th = std::abs(dr.cosTheta(crossing_pos));
106 }
107 return did_cross;
108}
109
110//////////////////////////////////////////////////////////////////////////////
111//
113GoingInOrOutOfaVolume(const G4Step* aStep, const G4String& volume_name,
114 G4double&, G4bool& GoingIn) // from external surface
115{
116 G4bool step_at_boundary =
118 G4bool did_cross = false;
119 if (step_at_boundary)
120 {
121 const G4VTouchable* postStepTouchable =
122 aStep->GetPostStepPoint()->GetTouchable();
123 const G4VTouchable* preStepTouchable =
124 aStep->GetPreStepPoint()->GetTouchable();
125 if (preStepTouchable && postStepTouchable
126 && postStepTouchable->GetVolume() && preStepTouchable->GetVolume())
127 {
128 G4String post_vol_name = postStepTouchable->GetVolume()->GetName();
129 G4String pre_vol_name = preStepTouchable->GetVolume()->GetName();
130
131 if (post_vol_name == volume_name )
132 {
133 GoingIn = true;
134 did_cross = true;
135 }
136 else if (pre_vol_name == volume_name)
137 {
138 GoingIn = false;
139 did_cross = true;
140 }
141 }
142 }
143 return did_cross; // still need to compute the cosine of the direction
144}
145
146/////////////////////////////////////////////////////////////////////////////
147//
150 const G4String& volume_name,
151 const G4String& mother_logical_vol_name,
152 G4double&,
153 G4bool& GoingIn) // from external surf.
154{
155 G4bool step_at_boundary =
157 G4bool did_cross = false;
158 if (step_at_boundary)
159 {
160 const G4VTouchable* postStepTouchable =
161 aStep->GetPostStepPoint()->GetTouchable();
162 const G4VTouchable* preStepTouchable =
163 aStep->GetPreStepPoint()->GetTouchable();
164 const G4VPhysicalVolume* postVol = (postStepTouchable != nullptr)
165 ? postStepTouchable->GetVolume() : nullptr;
166 const G4VPhysicalVolume* preVol = (preStepTouchable != nullptr)
167 ? preStepTouchable->GetVolume() : nullptr;
168 if (preStepTouchable != nullptr && postStepTouchable != nullptr
169 && postVol != nullptr && preVol != nullptr)
170 {
171 G4String post_vol_name = postVol->GetName();
172 G4String post_log_vol_name = postVol->GetLogicalVolume()->GetName();
173 G4String pre_vol_name = preVol->GetName();
174 G4String pre_log_vol_name = preVol->GetLogicalVolume()->GetName();
175 if (post_vol_name == volume_name
176 && pre_log_vol_name == mother_logical_vol_name)
177 {
178 GoingIn = true;
179 did_cross = true;
180 }
181 else if (pre_vol_name == volume_name
182 && post_log_vol_name == mother_logical_vol_name )
183 {
184 GoingIn = false;
185 did_cross = true;
186 }
187 }
188 }
189 return did_cross; // still need to compute the cosine of the direction
190}
191
192//////////////////////////////////////////////////////////////////////////////
193//
196 const G4String& surface_name,
197 G4ThreeVector& crossing_pos,
198 G4double& cos_to_surface, G4bool& GoingIn)
199{
200 G4int ind = FindRegisteredSurface(surface_name);
201 G4bool did_cross = false;
202 if (ind >=0)
203 {
204 did_cross = CrossingAGivenRegisteredSurface(aStep, ind, crossing_pos,
205 cos_to_surface, GoingIn);
206 }
207 return did_cross;
208}
209
210//////////////////////////////////////////////////////////////////////////////
211//
214 G4ThreeVector& crossing_pos,
215 G4double& cos_to_surface, G4bool& GoingIn)
216{
217 G4String surf_type = ListOfSurfaceType[ind];
218 G4double radius = ListOfSphereRadius[ind];
219 G4ThreeVector center = ListOfSphereCenter[ind];
220 G4String vol1 = ListOfVol1Name[ind];
221 G4String vol2 = ListOfVol2Name[ind];
222
223 G4bool did_cross = false;
224 if (surf_type == "Sphere")
225 {
226 did_cross = CrossingASphere(aStep, radius, center,crossing_pos,
227 cos_to_surface, GoingIn);
228 }
229 else if (surf_type == "ExternalSurfaceOfAVolume")
230 {
231 did_cross = GoingInOrOutOfaVolumeByExtSurface(aStep, vol1, vol2,
232 cos_to_surface, GoingIn);
233 crossing_pos= aStep->GetPostStepPoint()->GetPosition();
234 }
235 else if (surf_type == "BoundaryBetweenTwoVolumes")
236 {
237 did_cross = CrossingAnInterfaceBetweenTwoVolumes(aStep, vol1, vol2,
238 crossing_pos,
239 cos_to_surface, GoingIn);
240 }
241 return did_cross;
242}
243
244//////////////////////////////////////////////////////////////////////////////
245//
247CrossingOneOfTheRegisteredSurface(const G4Step* aStep, G4String& surface_name,
248 G4ThreeVector& crossing_pos,
249 G4double& cos_to_surface,
250 G4bool& GoingIn)
251{
252 for (std::size_t i=0; i<ListOfSurfaceName.size(); ++i)
253 {
254 if (CrossingAGivenRegisteredSurface(aStep, G4int(i), crossing_pos,
255 cos_to_surface, GoingIn))
256 {
257 surface_name = ListOfSurfaceName[i];
258 return true;
259 }
260 }
261 return false;
262}
263
264//////////////////////////////////////////////////////////////////////////////
265//
268 const G4String& vol1_name,
269 const G4String& vol2_name,
271 G4bool& GoingIn)
272{
273 G4bool step_at_boundary =
275 G4bool did_cross = false;
276 if (step_at_boundary)
277 {
278 const G4VTouchable* postStepTouchable =
279 aStep->GetPostStepPoint()->GetTouchable();
280 const G4VTouchable* preStepTouchable =
281 aStep->GetPreStepPoint()->GetTouchable();
282 if (preStepTouchable && postStepTouchable)
283 {
284 G4String post_vol_name = postStepTouchable->GetVolume()->GetName();
285 if (post_vol_name == "")
286 {
287 post_vol_name = postStepTouchable->GetVolume()->GetLogicalVolume()
288 ->GetName();
289 }
290 G4String pre_vol_name = preStepTouchable->GetVolume()->GetName();
291 if (pre_vol_name == "")
292 {
293 pre_vol_name = preStepTouchable->GetVolume()->GetLogicalVolume()
294 ->GetName();
295 }
296 if (pre_vol_name == vol1_name && post_vol_name == vol2_name)
297 {
298 GoingIn=true;
299 did_cross=true;
300 }
301 else if (pre_vol_name == vol2_name && post_vol_name == vol1_name)
302 {
303 GoingIn=false;
304 did_cross=true;
305 }
306 }
307 }
308 return did_cross; // still need to compute the cosine of the direction
309}
310
311//////////////////////////////////////////////////////////////////////////////
312//
314AddaSphericalSurface(const G4String& SurfaceName, G4double radius,
315 G4ThreeVector pos, G4double& Area)
316{
317 G4int ind = FindRegisteredSurface(SurfaceName);
318 Area = 4.*pi*radius*radius;
319 if (ind>=0)
320 {
321 ListOfSurfaceType[ind] = "Sphere";
322 ListOfSphereRadius[ind] = radius;
323 ListOfSphereCenter[ind] = pos;
324 ListOfVol1Name[ind] = "";
325 ListOfVol2Name[ind] = "";
326 AreaOfSurface[ind] = Area;
327 }
328 else
329 {
330 ListOfSurfaceName.push_back(SurfaceName);
331 ListOfSurfaceType.push_back("Sphere");
332 ListOfSphereRadius.push_back(radius);
333 ListOfSphereCenter.push_back(pos);
334 ListOfVol1Name.push_back("");
335 ListOfVol2Name.push_back("");
336 AreaOfSurface.push_back(Area);
337 }
338 return true;
339}
340
341//////////////////////////////////////////////////////////////////////////////
342//
345 G4double radius,
346 const G4String& volume_name,
347 G4ThreeVector& center,
348 G4double& area)
349{
350 G4VPhysicalVolume* thePhysicalVolume = nullptr;
352 for (std::size_t i=0; i<thePhysVolStore->size(); ++i)
353 {
354 if ((*thePhysVolStore)[i]->GetName() == volume_name)
355 {
356 thePhysicalVolume = (*thePhysVolStore)[i];
357 }
358 }
359 if (thePhysicalVolume != nullptr)
360 {
361 G4VPhysicalVolume* daughter = thePhysicalVolume;
362 G4LogicalVolume* mother = thePhysicalVolume->GetMotherLogical();
363 G4AffineTransform theTransformationFromPhysVolToWorld = G4AffineTransform();
364 while (mother != nullptr)
365 {
366 theTransformationFromPhysVolToWorld *=
368 daughter->GetObjectTranslation());
369 for ( std::size_t i=0; i<thePhysVolStore->size(); ++i)
370 {
371 if ((*thePhysVolStore)[i]->GetLogicalVolume() == mother)
372 {
373 daughter = (*thePhysVolStore)[i];
374 mother =daughter->GetMotherLogical();
375 break;
376 }
377 }
378 }
379 center = theTransformationFromPhysVolToWorld.NetTranslation();
380 G4cout << "Center of the spherical surface is at the position: "
381 << center/cm << " cm" << G4endl;
382 }
383 else
384 {
385 G4cout << "The physical volume with name " << volume_name
386 << " does not exist!! " << G4endl;
387 return false;
388 }
389 return AddaSphericalSurface(SurfaceName, radius, center, area);
390}
391
392//////////////////////////////////////////////////////////////////////////////
393//
395AddanExtSurfaceOfAvolume(const G4String& SurfaceName,
396 const G4String& volume_name, G4double& Area)
397{
398 G4int ind = FindRegisteredSurface(SurfaceName);
399
400 G4VPhysicalVolume* thePhysicalVolume = nullptr;
402 for (std::size_t i=0; i<thePhysVolStore->size(); ++i)
403 {
404 if ((*thePhysVolStore)[i]->GetName() == volume_name)
405 {
406 thePhysicalVolume = (*thePhysVolStore)[i];
407 }
408 }
409 if (thePhysicalVolume == nullptr)
410 {
411 G4cout << "The physical volume with name " << volume_name
412 << " does not exist!!" << G4endl;
413 return false;
414 }
415 Area = thePhysicalVolume->GetLogicalVolume()->GetSolid()->GetSurfaceArea();
416 G4String mother_vol_name = "";
417 G4LogicalVolume* theMother = thePhysicalVolume->GetMotherLogical();
418
419 if (theMother != nullptr) mother_vol_name= theMother->GetName();
420 if (ind>=0)
421 {
422 ListOfSurfaceType[ind] = "ExternalSurfaceOfAVolume";
423 ListOfSphereRadius[ind] = 0.;
424 ListOfSphereCenter[ind] = G4ThreeVector(0.,0.,0.);
425 ListOfVol1Name[ind] = volume_name;
426 ListOfVol2Name[ind] = mother_vol_name;
427 AreaOfSurface[ind] = Area;
428 }
429 else
430 {
431 ListOfSurfaceName.push_back(SurfaceName);
432 ListOfSurfaceType.push_back("ExternalSurfaceOfAVolume");
433 ListOfSphereRadius.push_back(0.);
434 ListOfSphereCenter.push_back(G4ThreeVector(0.,0.,0.));
435 ListOfVol1Name.push_back(volume_name);
436 ListOfVol2Name.push_back(mother_vol_name);
437 AreaOfSurface.push_back(Area);
438 }
439 return true;
440}
441
442//////////////////////////////////////////////////////////////////////////////
443//
446 const G4String& volume_name1,
447 const G4String& volume_name2, G4double& Area)
448{
449 G4int ind = FindRegisteredSurface(SurfaceName);
450 Area = -1.; // the way to compute the surface is not known yet
451 if (ind>=0)
452 {
453 ListOfSurfaceType[ind] = "BoundaryBetweenTwoVolumes";
454 ListOfSphereRadius[ind] = 0.;
455 ListOfSphereCenter[ind] = G4ThreeVector(0.,0.,0.);
456 ListOfVol1Name[ind] = volume_name1;
457 ListOfVol2Name[ind] = volume_name2;
458 AreaOfSurface[ind] = Area;
459 }
460 else
461 {
462 ListOfSurfaceName.push_back(SurfaceName);
463 ListOfSurfaceType.push_back("BoundaryBetweenTwoVolumes");
464 ListOfSphereRadius.push_back(0.);
465 ListOfSphereCenter.push_back(G4ThreeVector(0.,0.,0.));
466 ListOfVol1Name.push_back(volume_name1);
467 ListOfVol2Name.push_back(volume_name2);
468 AreaOfSurface.push_back(Area);
469 }
470 return true;
471}
472
473//////////////////////////////////////////////////////////////////////////////
474//
476{
477 ListOfSurfaceName.clear();
478 ListOfSurfaceType.clear();
479 ListOfSphereRadius.clear();
480 ListOfSphereCenter.clear();
481 ListOfVol1Name.clear();
482 ListOfVol2Name.clear();
483}
484
485//////////////////////////////////////////////////////////////////////////////
486//
487G4int G4AdjointCrossSurfChecker::FindRegisteredSurface(const G4String& name)
488{
489 for (std::size_t i=0; i<ListOfSurfaceName.size(); ++i)
490 {
491 if (name == ListOfSurfaceName[i]) return G4int(i);
492 }
493 return -1;
494}
@ fGeomBoundary
Definition: G4StepStatus.hh:43
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
double mag() const
double cosTheta() const
G4bool CrossingAGivenRegisteredSurface(const G4Step *aStep, const G4String &surface_name, G4ThreeVector &cross_pos, G4double &cos_to_surface, G4bool &GoingIn)
G4bool CrossingAnInterfaceBetweenTwoVolumes(const G4Step *aStep, const G4String &vol1_name, const G4String &vol2_name, G4ThreeVector &cross_pos, G4double &cos_to_surface, G4bool &GoingIn)
G4bool CrossingOneOfTheRegisteredSurface(const G4Step *aStep, G4String &surface_name, G4ThreeVector &cross_pos, G4double &cos_to_surface, G4bool &GoingIn)
G4bool AddaSphericalSurface(const G4String &SurfaceName, G4double radius, G4ThreeVector pos, G4double &area)
G4bool GoingInOrOutOfaVolumeByExtSurface(const G4Step *aStep, const G4String &volume_name, const G4String &mother_lvol_name, G4double &cos_to_surface, G4bool &GoingIn)
G4bool AddanExtSurfaceOfAvolume(const G4String &SurfaceName, const G4String &volume_name, G4double &area)
static G4AdjointCrossSurfChecker * GetInstance()
G4bool AddanInterfaceBetweenTwoVolumes(const G4String &SurfaceName, const G4String &volume_name1, const G4String &volume_name2, G4double &area)
G4bool AddaSphericalSurfaceWithCenterAtTheCenterOfAVolume(const G4String &SurfaceName, G4double radius, const G4String &volume_name, G4ThreeVector &center, G4double &area)
G4bool GoingInOrOutOfaVolume(const G4Step *aStep, const G4String &volume_name, G4double &cos_to_surface, G4bool &GoingIn)
G4bool CrossingASphere(const G4Step *aStep, G4double sphere_radius, G4ThreeVector sphere_center, G4ThreeVector &cross_pos, G4double &cos_to_surface, G4bool &GoingIn)
G4ThreeVector NetTranslation() const
G4VSolid * GetSolid() const
const G4String & GetName() const
static G4PhysicalVolumeStore * GetInstance()
G4StepStatus GetStepStatus() const
const G4VTouchable * GetTouchable() const
const G4ThreeVector & GetPosition() const
Definition: G4Step.hh:62
G4StepPoint * GetPreStepPoint() const
G4StepPoint * GetPostStepPoint() const
G4LogicalVolume * GetMotherLogical() const
G4LogicalVolume * GetLogicalVolume() const
const G4RotationMatrix * GetFrameRotation() const
const G4String & GetName() const
G4ThreeVector GetObjectTranslation() const
virtual G4double GetSurfaceArea()
Definition: G4VSolid.cc:238
virtual G4VPhysicalVolume * GetVolume(G4int depth=0) const
Definition: G4VTouchable.cc:41
#define G4ThreadLocal
Definition: tls.hh:77