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

Last change on this file since 1311 was 1228, checked in by garnier, 16 years ago

update geant4.9.3 tag

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