Geant4 11.1.1
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4PVDivision.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// G4PVDivision Implementation file
27//
28// 26.05.03 - P.Arce, Initial version
29// --------------------------------------------------------------------
30
31#include "G4PVDivision.hh"
32#include "G4LogicalVolume.hh"
33#include "G4VSolid.hh"
34#include "G4ReflectedSolid.hh"
42
43//--------------------------------------------------------------------------
45 G4LogicalVolume* pLogical,
46 G4LogicalVolume* pMotherLogical,
47 const EAxis pAxis,
48 const G4int nDivs,
49 const G4double width,
50 const G4double offset )
51 : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical)
52{
53 if (pMotherLogical == nullptr)
54 {
55 std::ostringstream message;
56 message << "Invalid setup." << G4endl
57 << "NULL pointer specified as mother for volume: " << pName;
58 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
59 FatalException, message);
60 return;
61 }
62 if (pLogical == pMotherLogical)
63 {
64 std::ostringstream message;
65 message << "Invalid setup." << G4endl
66 << "Cannot place a volume inside itself! Volume: " << pName;
67 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
68 FatalException, message);
69 }
70 pMotherLogical->AddDaughter(this);
71 SetMotherLogical(pMotherLogical);
72 SetParameterisation(pMotherLogical, pAxis, nDivs,
73 width, offset, DivNDIVandWIDTH);
74 CheckAndSetParameters (pAxis, nDivs, width, offset,
75 DivNDIVandWIDTH, pMotherLogical);
76}
77
78//--------------------------------------------------------------------------
80 G4LogicalVolume* pLogical,
81 G4LogicalVolume* pMotherLogical,
82 const EAxis pAxis,
83 const G4int nDivs,
84 const G4double offset )
85 : G4PVReplica(pName, nDivs, pAxis, pLogical, pMotherLogical)
86{
87 if (pMotherLogical == nullptr)
88 {
89 std::ostringstream message;
90 message << "Invalid setup." << G4endl
91 << "NULL pointer specified as mother! Volume: " << pName;
92 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
93 FatalException, message);
94 return;
95 }
96 if (pLogical == pMotherLogical)
97 {
98 std::ostringstream message;
99 message << "Invalid setup." << G4endl
100 << "Cannot place a volume inside itself! Volume: " << pName;
101 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
102 FatalException, message);
103 }
104 pMotherLogical->AddDaughter(this);
105 SetMotherLogical(pMotherLogical);
106 SetParameterisation(pMotherLogical, pAxis, nDivs, 0., offset, DivNDIV);
107 CheckAndSetParameters (pAxis, nDivs, 0., offset, DivNDIV, pMotherLogical);
108}
109
110//--------------------------------------------------------------------------
112 G4LogicalVolume* pLogical,
113 G4LogicalVolume* pMotherLogical,
114 const EAxis pAxis,
115 const G4double width,
116 const G4double offset )
117 : G4PVReplica(pName, 0, pAxis, pLogical, pMotherLogical)
118{
119 if (pMotherLogical == nullptr)
120 {
121 std::ostringstream message;
122 message << "Invalid setup." << G4endl
123 << "NULL pointer specified as mother! Volume: " + pName;
124 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
125 FatalException, message);
126 return;
127 }
128 if (pLogical == pMotherLogical)
129 {
130 std::ostringstream message;
131 message << "Invalid setup." << G4endl
132 << "Cannot place a volume inside itself! Volume: "+ pName;
133 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
134 FatalException, message);
135 }
136 pMotherLogical->AddDaughter(this);
137 SetMotherLogical(pMotherLogical);
138 SetParameterisation(pMotherLogical, pAxis, 0, width, offset, DivWIDTH);
139 CheckAndSetParameters (pAxis, 0, width, offset, DivWIDTH, pMotherLogical);
140}
141
142//--------------------------------------------------------------------------
144 G4LogicalVolume* pLogical,
145 G4VPhysicalVolume* pMotherPhysical,
146 const EAxis pAxis,
147 const G4int nDivs,
148 const G4double width,
149 const G4double offset )
150 : G4PVReplica(pName, nDivs, pAxis, pLogical,
151 pMotherPhysical ? pMotherPhysical->GetLogicalVolume() : nullptr)
152{
153 if (pMotherPhysical == nullptr)
154 {
155 std::ostringstream message;
156 message << "Invalid setup." << G4endl
157 << "NULL pointer specified as mother for volume: " << pName;
158 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
159 FatalException, message);
160 return;
161 }
162 G4LogicalVolume* pMotherLogical = pMotherPhysical->GetLogicalVolume();
163 if (pLogical == pMotherLogical)
164 {
165 std::ostringstream message;
166 message << "Invalid setup." << G4endl
167 << "Cannot place a volume inside itself! Volume: " << pName;
168 G4Exception("G4PVDivision::G4PVDivision()", "GeomDiv0002",
169 FatalException, message);
170 }
171 pMotherLogical->AddDaughter(this);
172 SetMotherLogical(pMotherLogical);
173 SetParameterisation(pMotherLogical, pAxis, nDivs,
174 width, offset, DivNDIVandWIDTH);
175 CheckAndSetParameters (pAxis, nDivs, width, offset,
176 DivNDIVandWIDTH, pMotherLogical);
177}
178
179//--------------------------------------------------------------------------
180void
181G4PVDivision::CheckAndSetParameters( const EAxis pAxis,
182 const G4int nDivs,
183 const G4double width,
184 const G4double offset,
185 DivisionType divType,
186 const G4LogicalVolume* pMotherLogical )
187{
188 if( divType == DivWIDTH )
189 {
191 }
192 else
193 {
194 fnReplicas = nDivs;
195 }
196 if (fnReplicas < 1 )
197 {
198 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
199 FatalException, "Illegal number of replicas!");
200 }
201
202 if( divType != DivNDIV)
203 {
205 }
206 else
207 {
208 fwidth = width;
209 }
210 if( fwidth < 0 )
211 {
212 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
213 FatalException, "Width must be positive!");
214 }
215
216 foffset = offset;
217 fdivAxis = pAxis;
218
219 //!!!!! axis has to be x/y/z in G4VoxelLimits::GetMinExtent
220 //
221 if( pAxis == kRho || pAxis == kRadial3D || pAxis == kPhi )
222 {
223 faxis = kZAxis;
224 }
225 else
226 {
227 faxis = pAxis;
228 }
229
230 // Create rotation matrix: for phi axis it will be changed
231 // in G4VPVParameterisation::ComputeTransformation, for others
232 // it will stay the unity
233 //
234 G4RotationMatrix* pRMat = new G4RotationMatrix();
235 SetRotation(pRMat);
236
237 switch (faxis)
238 {
239 case kPhi:
240 break;
241 case kRho:
242 case kXAxis:
243 case kYAxis:
244 case kZAxis:
245 break;
246 default:
247 G4Exception("G4PVDivision::CheckAndSetParameters()", "GeomDiv0002",
248 FatalException, "Unknown axis of replication.");
249 break;
250 }
251
252
253 //----- Check that mother solid is of the same type than
254 // daughter solid (otherwise, the corresponding
255 // Parameterisation::ComputeDimension() will not be called)
256 //
257 G4String msolType = pMotherLogical->GetSolid()->GetEntityType();
259 if( msolType != dsolType && ( msolType != "G4Trd" || dsolType != "G4Trap" ) )
260 {
261 std::ostringstream message;
262 message << "Incorrect solid type for division of volume "
263 << GetName() << "." << G4endl
264 << "It is: " << msolType
265 << ", while it should be: " << dsolType << "!";
266 G4Exception("G4PVDivision::CheckAndSetParameters()",
267 "GeomDiv0002", FatalException, message );
268 }
269}
270
271//--------------------------------------------------------------------------
273{
274}
275
276//--------------------------------------------------------------------------
278{
279 return fdivAxis;
280}
281
282//--------------------------------------------------------------------------
284{
285 return true;
286}
287
288//--------------------------------------------------------------------------
290{
291 return false;
292}
293
294//--------------------------------------------------------------------------
296{
297 return true;
298}
299
300//--------------------------------------------------------------------------
302{
303 return fnReplicas;
304}
305
306//--------------------------------------------------------------------------
308{
309 return fparam;
310}
311
312//--------------------------------------------------------------------------
314 G4int& nDivs,
315 G4double& width,
316 G4double& offset,
317 G4bool& consuming ) const
318{
319 axis = faxis;
320 nDivs = fnReplicas;
321 width = fwidth;
322 offset = foffset;
323 consuming = false;
324}
325
326//--------------------------------------------------------------------------
328{
329 return kParameterised;
330}
331
332//--------------------------------------------------------------------------
333// TODO: this method should check that the child lv is of the correct type,
334// else the ComputeDimensions will never be called
335//
336void G4PVDivision::SetParameterisation( G4LogicalVolume* motherLogical,
337 const EAxis axis,
338 const G4int nDivs,
339 const G4double width,
340 const G4double offset,
341 DivisionType divType )
342{
343 // Check that solid is compatible with mother solid and axis of division
344 // CheckSolid( solid, motherSolid );
345 // G4cout << " Axis " << axis << G4endl;
346
347 G4VSolid* mSolid = motherLogical->GetSolid();
348 G4String mSolidType = mSolid->GetEntityType();
349
350 // If the solid is a reflected one, update type to its
351 // real constituent solid.
352 //
353 if (mSolidType == "G4ReflectedSolid")
354 {
355 mSolidType = ((G4ReflectedSolid*)mSolid)->GetConstituentMovedSolid()
356 ->GetEntityType();
357 }
358
359 // Parameterisation type depend of mother solid type and axis of division
360 //
361 if( mSolidType == "G4Box" )
362 {
363 switch( axis )
364 {
365 case kXAxis:
366 fparam = new G4ParameterisationBoxX( axis, nDivs, width,
367 offset, mSolid, divType );
368 break;
369 case kYAxis:
370 fparam = new G4ParameterisationBoxY( axis, nDivs, width,
371 offset, mSolid, divType );
372 break;
373 case kZAxis:
374 fparam = new G4ParameterisationBoxZ( axis, nDivs, width,
375 offset, mSolid, divType );
376 break;
377 default:
378 ErrorInAxis( axis, mSolid );
379 break;
380 }
381 }
382 else if( mSolidType == "G4Tubs" )
383 {
384 switch( axis )
385 {
386 case kRho:
387 fparam = new G4ParameterisationTubsRho( axis, nDivs, width,
388 offset, mSolid, divType );
389 break;
390 case kPhi:
391 fparam = new G4ParameterisationTubsPhi( axis, nDivs, width,
392 offset, mSolid, divType );
393 break;
394 case kZAxis:
395 fparam = new G4ParameterisationTubsZ( axis, nDivs, width,
396 offset, mSolid, divType );
397 break;
398 default:
399 ErrorInAxis( axis, mSolid );
400 break;
401 }
402 }
403 else if( mSolidType == "G4Cons" )
404 {
405 switch( axis )
406 {
407 case kRho:
408 fparam = new G4ParameterisationConsRho( axis, nDivs, width,
409 offset, mSolid, divType );
410 break;
411 case kPhi:
412 fparam = new G4ParameterisationConsPhi( axis, nDivs, width,
413 offset, mSolid, divType );
414 break;
415 case kZAxis:
416 fparam = new G4ParameterisationConsZ( axis, nDivs, width,
417 offset, mSolid, divType );
418 break;
419 default:
420 ErrorInAxis( axis, mSolid );
421 break;
422 }
423 }
424 else if( mSolidType == "G4Trd" )
425 {
426 switch( axis )
427 {
428 case kXAxis:
429 fparam = new G4ParameterisationTrdX( axis, nDivs, width,
430 offset, mSolid, divType );
431 break;
432 case kYAxis:
433 fparam = new G4ParameterisationTrdY( axis, nDivs, width,
434 offset, mSolid, divType );
435 break;
436 case kZAxis:
437 fparam = new G4ParameterisationTrdZ( axis, nDivs, width,
438 offset, mSolid, divType );
439 break;
440 default:
441 ErrorInAxis( axis, mSolid );
442 break;
443 }
444 }
445 else if( mSolidType == "G4Para" )
446 {
447 switch( axis )
448 {
449 case kXAxis:
450 fparam = new G4ParameterisationParaX( axis, nDivs, width,
451 offset, mSolid, divType );
452 break;
453 case kYAxis:
454 fparam = new G4ParameterisationParaY( axis, nDivs, width,
455 offset, mSolid, divType );
456 break;
457 case kZAxis:
458 fparam = new G4ParameterisationParaZ( axis, nDivs, width,
459 offset, mSolid, divType );
460 break;
461 default:
462 ErrorInAxis( axis, mSolid );
463 break;
464 }
465 }
466// else if( mSolidType == "G4Trap" )
467// {
468// }
469 else if( mSolidType == "G4Polycone" )
470 {
471 switch( axis )
472 {
473 case kRho:
474 fparam = new G4ParameterisationPolyconeRho( axis, nDivs, width,
475 offset, mSolid, divType );
476 break;
477 case kPhi:
478 fparam = new G4ParameterisationPolyconePhi( axis, nDivs, width,
479 offset, mSolid, divType );
480 break;
481 case kZAxis:
482 fparam = new G4ParameterisationPolyconeZ( axis, nDivs, width,
483 offset, mSolid, divType );
484 break;
485 default:
486 ErrorInAxis( axis, mSolid );
487 break;
488 }
489 }
490 else if( mSolidType == "G4Polyhedra" )
491 {
492 switch( axis )
493 {
494 case kRho:
495 fparam = new G4ParameterisationPolyhedraRho( axis, nDivs, width,
496 offset, mSolid, divType );
497 break;
498 case kPhi:
499 fparam = new G4ParameterisationPolyhedraPhi( axis, nDivs, width,
500 offset, mSolid, divType );
501 break;
502 case kZAxis:
503 fparam = new G4ParameterisationPolyhedraZ( axis, nDivs, width,
504 offset, mSolid, divType );
505 break;
506 default:
507 ErrorInAxis( axis, mSolid );
508 break;
509 }
510 }
511 else
512 {
513 std::ostringstream message;
514 message << "Solid type " << mSolidType << " not supported!" << G4endl
515 << "Divisions for " << mSolidType << " are not implemented.";
516 G4Exception("G4PVDivision::SetParameterisation()", "GeomDiv0001",
517 FatalException, message);
518 }
519}
520
521//--------------------------------------------------------------------------
522void G4PVDivision::ErrorInAxis( EAxis axis, G4VSolid* solid )
523{
524 G4String error = "Trying to divide solid " + solid->GetName()
525 + " of type " + solid->GetEntityType() + " along axis ";
526 switch( axis )
527 {
528 case kXAxis:
529 error += "X.";
530 break;
531 case kYAxis:
532 error += "Y.";
533 break;
534 case kZAxis:
535 error += "Z.";
536 break;
537 case kRho:
538 error += "Rho.";
539 break;
540 case kRadial3D:
541 error += "Radial3D.";
542 break;
543 case kPhi:
544 error += "Phi.";
545 break;
546 default:
547 break;
548 }
549 G4Exception("G4PVDivision::ErrorInAxis()", "GeomDiv0002",
550 FatalException, error);
551}
552
553// The next methods are for specialised repeated volumes (replicas,
554// parameterised vol.) which are completely regular.
555// Currently this is not applicable to divisions ( J.A. Nov 2005 )
556
557// ----------------------------------------------------------------------
558// IsRegularStructure()
559//
561{
562 return false;
563}
564
565// ----------------------------------------------------------------------
566// GetRegularStructureId()
567//
569{
570 return 0;
571}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:59
CLHEP::HepRotation G4RotationMatrix
double G4double
Definition: G4Types.hh:83
bool G4bool
Definition: G4Types.hh:86
int G4int
Definition: G4Types.hh:85
#define G4endl
Definition: G4ios.hh:57
G4VSolid * GetSolid() const
void AddDaughter(G4VPhysicalVolume *p)
virtual G4VPVParameterisation * GetParameterisation() const
virtual G4bool IsReplicated() const
virtual ~G4PVDivision()
virtual G4int GetMultiplicity() const
virtual EVolume VolumeType() const
G4double foffset
virtual G4bool IsMany() const
G4double fwidth
G4VDivisionParameterisation * fparam
EAxis GetDivisionAxis() const
virtual void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const
G4PVDivision(const G4String &pName, G4LogicalVolume *pLogical, G4LogicalVolume *pMother, const EAxis pAxis, const G4int nReplicas, const G4double width, const G4double offset)
Definition: G4PVDivision.cc:44
G4bool IsRegularStructure() const
G4bool IsParameterised() const
G4int GetRegularStructureId() const
G4double GetWidth() const
G4LogicalVolume * GetLogicalVolume() const
const G4String & GetName() const
void SetRotation(G4RotationMatrix *)
void SetMotherLogical(G4LogicalVolume *pMother)
G4String GetName() const
virtual G4GeometryType GetEntityType() const =0
EAxis
Definition: geomdefs.hh:54
@ kPhi
Definition: geomdefs.hh:60
@ kYAxis
Definition: geomdefs.hh:56
@ kRadial3D
Definition: geomdefs.hh:59
@ kXAxis
Definition: geomdefs.hh:55
@ kZAxis
Definition: geomdefs.hh:57
@ kRho
Definition: geomdefs.hh:58
EVolume
Definition: geomdefs.hh:83
@ kParameterised
Definition: geomdefs.hh:86