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