source: trunk/source/geometry/divisions/src/G4PVDivision.cc

Last change on this file was 1347, checked in by garnier, 15 years ago

geant4 tag 9.4

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