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
G4PhantomParameterisation.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// class G4PhantomParameterisation implementation
27//
28// May 2007 Pedro Arce, first version
29//
30// --------------------------------------------------------------------
31
33
34#include "globals.hh"
35#include "G4VSolid.hh"
36#include "G4VPhysicalVolume.hh"
37#include "G4LogicalVolume.hh"
40
41//------------------------------------------------------------------
43{
45}
46
47
48//------------------------------------------------------------------
50{
51}
52
53
54//------------------------------------------------------------------
56BuildContainerSolid( G4VPhysicalVolume* pMotherPhysical )
57{
58 fContainerSolid = pMotherPhysical->GetLogicalVolume()->GetSolid();
62
63 // CheckVoxelsFillContainer();
64}
65
66//------------------------------------------------------------------
68BuildContainerSolid( G4VSolid* pMotherSolid )
69{
70 fContainerSolid = pMotherSolid;
74
75 // CheckVoxelsFillContainer();
76}
77
78
79//------------------------------------------------------------------
81ComputeTransformation(const G4int copyNo, G4VPhysicalVolume* physVol ) const
82{
83 // Voxels cannot be rotated, return translation
84 //
85 G4ThreeVector trans = GetTranslation( copyNo );
86
87 physVol->SetTranslation( trans );
88}
89
90
91//------------------------------------------------------------------
93GetTranslation(const G4int copyNo ) const
94{
95 CheckCopyNo( copyNo );
96
97 std::size_t nx;
98 std::size_t ny;
99 std::size_t nz;
100
101 ComputeVoxelIndices( copyNo, nx, ny, nz );
102
103 G4ThreeVector trans( (2*nx+1)*fVoxelHalfX - fContainerWallX,
104 (2*ny+1)*fVoxelHalfY - fContainerWallY,
105 (2*nz+1)*fVoxelHalfZ - fContainerWallZ);
106 return trans;
107}
108
109
110//------------------------------------------------------------------
112ComputeSolid(const G4int, G4VPhysicalVolume* pPhysicalVol)
113{
114 return pPhysicalVol->GetLogicalVolume()->GetSolid();
115}
116
117
118//------------------------------------------------------------------
120ComputeMaterial(const G4int copyNo, G4VPhysicalVolume *, const G4VTouchable *)
121{
122 CheckCopyNo( copyNo );
123 std::size_t matIndex = GetMaterialIndex(copyNo);
124
125 return fMaterials[ matIndex ];
126}
127
128
129//------------------------------------------------------------------
131GetMaterialIndex( std::size_t copyNo ) const
132{
133 CheckCopyNo( copyNo );
134
135 if( fMaterialIndices == nullptr ) { return 0; }
136 return *(fMaterialIndices+copyNo);
137}
138
139
140//------------------------------------------------------------------
142GetMaterialIndex( std::size_t nx, std::size_t ny, std::size_t nz ) const
143{
144 std::size_t copyNo = nx + fNoVoxelsX*ny + fNoVoxelsXY*nz;
145 return GetMaterialIndex( copyNo );
146}
147
148
149//------------------------------------------------------------------
151G4PhantomParameterisation::GetMaterial( std::size_t nx, std::size_t ny, std::size_t nz) const
152{
153 return fMaterials[GetMaterialIndex(nx,ny,nz)];
154}
155
156
157//------------------------------------------------------------------
159{
160 return fMaterials[GetMaterialIndex(copyNo)];
161}
162
163
164//------------------------------------------------------------------
165void G4PhantomParameterisation::
166ComputeVoxelIndices(const G4int copyNo, std::size_t& nx,
167 std::size_t& ny, std::size_t& nz ) const
168{
169 CheckCopyNo( copyNo );
170 nx = std::size_t(copyNo%fNoVoxelsX);
171 ny = std::size_t( (copyNo/fNoVoxelsX)%fNoVoxelsY );
172 nz = std::size_t(copyNo/fNoVoxelsXY);
173}
174
175
176//------------------------------------------------------------------
178CheckVoxelsFillContainer( G4double contX, G4double contY, G4double contZ ) const
179{
180 G4double toleranceForWarning = 0.25*kCarTolerance;
181
182 // Any bigger value than 0.25*kCarTolerance will give a warning in
183 // G4NormalNavigation::ComputeStep(), because the Inverse of a container
184 // translation that is Z+epsilon gives -Z+epsilon (and the maximum tolerance
185 // in G4Box::Inside is 0.5*kCarTolerance
186 //
187 G4double toleranceForError = 1.*kCarTolerance;
188
189 // Any bigger value than kCarTolerance will give an error in GetReplicaNo()
190 //
191 if( std::fabs(contX-fNoVoxelsX*fVoxelHalfX) >= toleranceForError
192 || std::fabs(contY-fNoVoxelsY*fVoxelHalfY) >= toleranceForError
193 || std::fabs(contZ-fNoVoxelsZ*fVoxelHalfZ) >= toleranceForError )
194 {
195 std::ostringstream message;
196 message << "Voxels do not fully fill the container: "
198 << " DiffX= " << contX-fNoVoxelsX*fVoxelHalfX << G4endl
199 << " DiffY= " << contY-fNoVoxelsY*fVoxelHalfY << G4endl
200 << " DiffZ= " << contZ-fNoVoxelsZ*fVoxelHalfZ << G4endl
201 << " Maximum difference is: " << toleranceForError;
202 G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
203 "GeomNav0002", FatalException, message);
204
205 }
206 else if( std::fabs(contX-fNoVoxelsX*fVoxelHalfX) >= toleranceForWarning
207 || std::fabs(contY-fNoVoxelsY*fVoxelHalfY) >= toleranceForWarning
208 || std::fabs(contZ-fNoVoxelsZ*fVoxelHalfZ) >= toleranceForWarning )
209 {
210 std::ostringstream message;
211 message << "Voxels do not fully fill the container: "
213 << " DiffX= " << contX-fNoVoxelsX*fVoxelHalfX << G4endl
214 << " DiffY= " << contY-fNoVoxelsY*fVoxelHalfY << G4endl
215 << " DiffZ= " << contZ-fNoVoxelsZ*fVoxelHalfZ << G4endl
216 << " Maximum difference is: " << toleranceForWarning;
217 G4Exception("G4PhantomParameterisation::CheckVoxelsFillContainer()",
218 "GeomNav1002", JustWarning, message);
219 }
220}
221
222
223//------------------------------------------------------------------
225GetReplicaNo( const G4ThreeVector& localPoint, const G4ThreeVector& localDir )
226{
227
228 // Check first that point is really inside voxels
229 //
230 if( fContainerSolid->Inside( localPoint ) == kOutside )
231 {
232 if( std::fabs(localPoint.x()) - fContainerWallX > kCarTolerance
233 && std::fabs(localPoint.y()) - fContainerWallY > kCarTolerance
234 && std::fabs(localPoint.z()) - fContainerWallZ > kCarTolerance )
235 {
236 std::ostringstream message;
237 message << "Point outside voxels!" << G4endl
238 << " localPoint - " << localPoint
239 << " - is outside container solid: "
241 << "DIFFERENCE WITH PHANTOM WALLS X: "
242 << std::fabs(localPoint.x()) - fContainerWallX
243 << " Y: " << std::fabs(localPoint.y()) - fContainerWallY
244 << " Z: " << std::fabs(localPoint.z()) - fContainerWallZ;
245 G4Exception("G4PhantomParameterisation::GetReplicaNo()", "GeomNav0003",
246 FatalErrorInArgument, message);
247 }
248 }
249
250 // Check the voxel numbers corresponding to localPoint
251 // When a particle is on a surface, it may be between -kCarTolerance and
252 // +kCartolerance. By a simple distance as:
253 // G4int nx = G4int( (localPoint.x()+)/fVoxelHalfX/2.);
254 // those between -kCartolerance and 0 will be placed on voxel N-1 and those
255 // between 0 and kCarTolerance on voxel N.
256 // To avoid precision problems place the tracks that are on the surface on
257 // voxel N-1 if they have negative direction and on voxel N if they have
258 // positive direction.
259 // Add +kCarTolerance so that they are first placed on voxel N, and then
260 // if the direction is negative substract 1
261
262 G4double fx = (localPoint.x()+fContainerWallX+kCarTolerance)/(fVoxelHalfX*2.);
263 G4int nx = G4int(fx);
264
265 G4double fy = (localPoint.y()+fContainerWallY+kCarTolerance)/(fVoxelHalfY*2.);
266 G4int ny = G4int(fy);
267
268 G4double fz = (localPoint.z()+fContainerWallZ+kCarTolerance)/(fVoxelHalfZ*2.);
269 G4int nz = G4int(fz);
270
271 // If it is on the surface side, check the direction: if direction is
272 // negative place it in the previous voxel (if direction is positive it is
273 // already in the next voxel).
274 // Correct also cases where n = -1 or n = fNoVoxels. It is always traced to be
275 // due to multiple scattering: track is entering a voxel but multiple
276 // scattering changes the angle towards outside
277 //
278 if( fx - nx < kCarTolerance*fVoxelHalfX )
279 {
280 if( localDir.x() < 0 )
281 {
282 if( nx != 0 )
283 {
284 nx -= 1;
285 }
286 }
287 else
288 {
289 if( nx == G4int(fNoVoxelsX) )
290 {
291 nx -= 1;
292 }
293 }
294 }
295 if( fy - ny < kCarTolerance*fVoxelHalfY )
296 {
297 if( localDir.y() < 0 )
298 {
299 if( ny != 0 )
300 {
301 ny -= 1;
302 }
303 }
304 else
305 {
306 if( ny == G4int(fNoVoxelsY) )
307 {
308 ny -= 1;
309 }
310 }
311 }
312 if( fz - nz < kCarTolerance*fVoxelHalfZ )
313 {
314 if( localDir.z() < 0 )
315 {
316 if( nz != 0 )
317 {
318 nz -= 1;
319 }
320 }
321 else
322 {
323 if( nz == G4int(fNoVoxelsZ) )
324 {
325 nz -= 1;
326 }
327 }
328 }
329
330 G4int copyNo = G4int(nx + fNoVoxelsX*ny + fNoVoxelsXY*nz);
331
332 // Check if there are still errors
333 //
334 G4bool isOK = true;
335 if( nx < 0 )
336 {
337 nx = 0;
338 isOK = false;
339 }
340 else if( nx >= G4int(fNoVoxelsX) )
341 {
342 nx = G4int(fNoVoxelsX)-1;
343 isOK = false;
344 }
345 if( ny < 0 )
346 {
347 ny = 0;
348 isOK = false;
349 }
350 else if( ny >= G4int(fNoVoxelsY) )
351 {
352 ny = G4int(fNoVoxelsY)-1;
353 isOK = false;
354 }
355 if( nz < 0 )
356 {
357 nz = 0;
358 isOK = false;
359 }
360 else if( nz >= G4int(fNoVoxelsZ) )
361 {
362 nz = G4int(fNoVoxelsZ)-1;
363 isOK = false;
364 }
365 if( !isOK )
366 {
367 if( std::fabs(localPoint.x()-fContainerWallX) > kCarTolerance &&
368 std::fabs(localPoint.y()-fContainerWallY) > kCarTolerance &&
369 std::fabs(localPoint.z()-fContainerWallZ) > kCarTolerance ){ // only if difference is big
370 std::ostringstream message;
371 message << "Corrected the copy number! It was negative or too big" << G4endl
372 << " LocalPoint: " << localPoint << G4endl
373 << " LocalDir: " << localDir << G4endl
374 << " Voxel container size: " << fContainerWallX
375 << " " << fContainerWallY << " " << fContainerWallZ << G4endl
376 << " LocalPoint - wall: "
377 << localPoint.x()-fContainerWallX << " "
378 << localPoint.y()-fContainerWallY << " "
379 << localPoint.z()-fContainerWallZ;
380 G4Exception("G4PhantomParameterisation::GetReplicaNo()",
381 "GeomNav1002", JustWarning, message);
382 }
383
384 copyNo = G4int(nx + fNoVoxelsX*ny + fNoVoxelsXY*nz);
385 }
386
387 return copyNo;
388}
389
390
391//------------------------------------------------------------------
392void G4PhantomParameterisation::CheckCopyNo( const G4long copyNo ) const
393{
394 if( copyNo < 0 || copyNo >= G4int(fNoVoxels) )
395 {
396 std::ostringstream message;
397 message << "Copy number is negative or too big!" << G4endl
398 << " Copy number: " << copyNo << G4endl
399 << " Total number of voxels: " << fNoVoxels;
400 G4Exception("G4PhantomParameterisation::CheckCopyNo()",
401 "GeomNav0002", FatalErrorInArgument, message);
402 }
403}
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
double G4double
Definition: G4Types.hh:83
long G4long
Definition: G4Types.hh:87
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
double z() const
double x() const
double y() const
G4double GetSurfaceTolerance() const
static G4GeometryTolerance * GetInstance()
G4VSolid * GetSolid() const
virtual G4int GetReplicaNo(const G4ThreeVector &localPoint, const G4ThreeVector &localDir)
void BuildContainerSolid(G4VPhysicalVolume *pPhysicalVol)
void CheckVoxelsFillContainer(G4double contX, G4double contY, G4double contZ) const
virtual G4Material * ComputeMaterial(const G4int repNo, G4VPhysicalVolume *currentVol, const G4VTouchable *parentTouch=nullptr)
G4Material * GetMaterial(std::size_t nx, std::size_t ny, std::size_t nz) const
virtual G4VSolid * ComputeSolid(const G4int, G4VPhysicalVolume *)
std::size_t GetMaterialIndex(std::size_t nx, std::size_t ny, std::size_t nz) const
G4ThreeVector GetTranslation(const G4int copyNo) const
virtual void ComputeTransformation(const G4int, G4VPhysicalVolume *) const
std::vector< G4Material * > fMaterials
G4LogicalVolume * GetLogicalVolume() const
void SetTranslation(const G4ThreeVector &v)
G4String GetName() const
virtual EInside Inside(const G4ThreeVector &p) const =0
@ kOutside
Definition: geomdefs.hh:68