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