Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/geometry/volumes/src/G4ReflectionFactory.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  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 G4ReflectionFactory Implementation
 27 //
 28 // Decomposition of a general transformation
 29 // that can include reflection in a "reflection-free" transformation:
 30 // 
 31 // x(inM') = TG*x(inM)         TG - general transformation
 32 //         = T*(R*x(inM))      T  - "reflection-free" transformation
 33 //         = T* x(inReflM)   
 34 //
 35 // Daughters transformation:
 36 // When a volume V containing daughter D with transformation TD
 37 // is placed in mother M with a general tranformation TGV,
 38 // the TGV is decomposed,
 39 // new reflected volume ReflV containing a new daughter ReflD
 40 // with reflected transformation ReflTD is created:
 41 // 
 42 // x(inV) = TD * x(inD);
 43 // x(inM) = TGV * x(inV) 
 44 //        = TV * R * x(inV) 
 45 //        = TV * R * TD * x(inD)
 46 //        = TV * R*TD*R-1 * R*x(inD)
 47 //        = TV * ReflTD * x(inReflD)
 48 //
 49 // Author: Ivana Hrivnacova (Ivana.Hrivnacova@cern.ch), 16.10.2001
 50 // --------------------------------------------------------------------
 51 
 52 #include "G4ReflectionFactory.hh"
 53 #include "G4ReflectedSolid.hh"
 54 #include "G4Region.hh" 
 55 #include "G4LogicalVolume.hh"  
 56 #include "G4PVPlacement.hh"  
 57 #include "G4PVReplica.hh"  
 58 #include "G4VPVDivisionFactory.hh"
 59 #include "G4GeometryTolerance.hh"
 60 
 61 G4ThreadLocal G4ReflectionFactory* G4ReflectionFactory::fInstance = nullptr;
 62 const G4String  G4ReflectionFactory::fDefaultNameExtension = "_refl";
 63 const G4Scale3D G4ReflectionFactory::fScale = G4ScaleZ3D(-1.0);
 64 
 65 //_____________________________________________________________________________
 66 
 67 G4ReflectionFactory* G4ReflectionFactory::Instance() 
 68 {
 69   // Static singleton access method.
 70   // ---
 71 
 72   if (fInstance == nullptr) { fInstance = new G4ReflectionFactory(); }
 73 
 74   return fInstance;
 75 }  
 76 
 77 //_____________________________________________________________________________
 78 
 79 G4ReflectionFactory::G4ReflectionFactory()
 80   : fNameExtension(fDefaultNameExtension)    
 81 {
 82   // Protected singleton constructor.
 83   // ---
 84 
 85   fScalePrecision = 10.
 86                   * G4GeometryTolerance::GetInstance()->GetSurfaceTolerance();
 87   fInstance = this;
 88 }
 89 
 90 //_____________________________________________________________________________
 91 
 92 G4ReflectionFactory::~G4ReflectionFactory()
 93 {
 94   delete fInstance;
 95 }
 96 
 97 //
 98 // public methods
 99 //
100 
101 //_____________________________________________________________________________
102 
103 G4PhysicalVolumesPair
104 G4ReflectionFactory::Place( const G4Transform3D& transform3D,
105                             const G4String&      name,
106                                   G4LogicalVolume* LV,
107                                   G4LogicalVolume* motherLV,
108                                   G4bool  isMany, 
109                                   G4int   copyNo,
110                                   G4bool  surfCheck)
111 {
112   // Evaluates the passed transformation; if it contains reflection
113   // it performs its decomposition, creates new reflected solid and
114   // logical volume (or retrieves them from a map if the reflected
115   // objects were already created), transforms the daughters (if present)
116   // and place it in the given mother.
117   // The result is a pair of physical volumes;
118   // the second physical volume is a placement in a reflected mother
119   // - or nullptr if mother LV was not reflected.
120   // ---
121 
122   if (fVerboseLevel>0)
123   {
124     G4cout << "Place " << name << " lv " << LV << " "
125            << LV->GetName() << G4endl;
126   }  
127 
128   // decompose transformation
129   G4Scale3D     scale;
130   G4Rotate3D    rotation;
131   G4Translate3D translation;
132 
133   transform3D.getDecomposition(scale, rotation, translation);
134   G4Transform3D pureTransform3D = translation * rotation;
135   
136   //PrintTransform(transform3D);
137   //PrintTransform(pureTransform3D);
138 
139   // check that scale correspond to fScale
140   //
141   CheckScale(scale);
142   
143   //
144   // reflection IS NOT present in transform3D 
145   //
146 
147   if (!IsReflection(scale))
148   {
149     if (fVerboseLevel>0)
150       G4cout << "Scale positive" << G4endl;
151 
152     G4VPhysicalVolume* pv1
153       =  new G4PVPlacement(pureTransform3D, LV, name,
154                            motherLV, isMany, copyNo, surfCheck);
155  
156     G4VPhysicalVolume* pv2 = nullptr;
157     if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
158     {
159       // if mother was reflected
160       // reflect this LV and place it in reflected mother
161       
162       pv2 = new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()),
163                               ReflectLV(LV, surfCheck), name, reflMotherLV,
164                               isMany, copyNo, surfCheck);
165     }
166     
167     return {pv1, pv2};            
168   }         
169            
170   //
171   //  reflection IS present in transform3D
172   //
173 
174   if (fVerboseLevel>0)
175     G4cout << "scale negative" << G4endl;
176 
177   G4VPhysicalVolume* pv1
178     = new G4PVPlacement(pureTransform3D, ReflectLV(LV, surfCheck), name,
179                         motherLV, isMany, copyNo, surfCheck);
180 
181   G4VPhysicalVolume* pv2 = nullptr;
182   if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
183   {
184 
185     // if mother was reflected
186     // place the refLV consituent in reflected mother
187 
188     pv2 =  new G4PVPlacement(fScale * (pureTransform3D * fScale.inverse()),
189                              LV, name, reflMotherLV, isMany, copyNo, surfCheck);
190   }
191 
192   return {pv1, pv2};
193 }           
194 
195 
196 //_____________________________________________________________________________
197 
198 G4PhysicalVolumesPair
199 G4ReflectionFactory::Replicate(const G4String& name, 
200                                      G4LogicalVolume* LV,
201                                      G4LogicalVolume* motherLV,
202                                      EAxis axis, 
203                                      G4int nofReplicas, 
204                                      G4double width,
205                                      G4double offset)
206 {
207   // Creates replica in given mother.
208   // The result is a pair of physical volumes;
209   // the second physical volume is a replica in a reflected mother
210   // - or nullptr if mother LV was not reflected.
211   // ---
212 
213   if (fVerboseLevel>0)
214   {
215     G4cout << "Replicate " << name << " lv " << LV << " " 
216            << LV->GetName() << G4endl;
217   }  
218 
219   G4VPhysicalVolume* pv1
220     = new G4PVReplica(name, LV, motherLV, axis, nofReplicas, width, offset);
221  
222   G4VPhysicalVolume* pv2 = nullptr;
223   if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
224   {
225     // if mother was reflected
226     // reflect the LV and replicate it in reflected mother
227     
228     pv2 = new G4PVReplica(name, ReflectLV(LV), reflMotherLV, 
229                           axis, nofReplicas, width, offset); 
230   }
231     
232   return {pv1, pv2};            
233 }         
234         
235 //_____________________________________________________________________________
236 
237 G4PhysicalVolumesPair
238 G4ReflectionFactory::Divide(const G4String& name, 
239                                   G4LogicalVolume* LV,
240                                   G4LogicalVolume* motherLV,
241                                   EAxis axis, 
242                                   G4int nofDivisions, 
243                                   G4double width,
244                                   G4double offset)
245 {
246   // Creates division in the given mother.
247   // The result is a pair of physical volumes;
248   // the second physical volume is a division in a reflected mother
249   // or nullptr if mother LV was not reflected.
250   // ---
251 
252   if (fVerboseLevel>0)
253   {
254     G4cout << "Divide " << name << " lv " << LV << " " 
255            << LV->GetName() << G4endl;
256   }  
257 
258   G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
259 
260   G4VPhysicalVolume* pv1 = divisionFactory
261       ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, width, offset);
262  
263   G4VPhysicalVolume* pv2 = nullptr;
264   if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
265   {
266     // if mother was reflected
267     // reflect the LV and replicate it in reflected mother
268     
269     pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 
270                                             axis, nofDivisions, width, offset); 
271   }
272     
273   return {pv1, pv2};            
274 }         
275         
276              
277 //_____________________________________________________________________________
278 
279 G4PhysicalVolumesPair
280 G4ReflectionFactory::Divide(const G4String& name, 
281                                   G4LogicalVolume* LV,
282                                   G4LogicalVolume* motherLV,
283                                   EAxis axis, 
284                                   G4int nofDivisions, 
285                                   G4double offset)
286 {
287   // Creates division in the given mother.
288   // The result is a pair of physical volumes;
289   // the second physical volume is a division in a reflected mother
290   // or nullptr if mother LV was not reflected.
291   // ---
292 
293   if (fVerboseLevel>0)
294   {
295     G4cout << "Divide " << name << " lv " << LV << " " 
296            << LV->GetName() << G4endl;
297   }  
298 
299   G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
300 
301   G4VPhysicalVolume* pv1 = divisionFactory
302       ->CreatePVDivision(name, LV, motherLV, axis, nofDivisions, offset);
303  
304   G4VPhysicalVolume* pv2 = nullptr;
305   if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
306   {
307     // if mother was reflected
308     // reflect the LV and replicate it in reflected mother
309     
310     pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 
311                                             axis, nofDivisions, offset); 
312   }
313     
314   return {pv1, pv2};            
315 }         
316         
317              
318 //_____________________________________________________________________________
319 
320 G4PhysicalVolumesPair
321 G4ReflectionFactory::Divide(const G4String& name, 
322                                   G4LogicalVolume* LV,
323                                   G4LogicalVolume* motherLV,
324                                   EAxis axis, 
325                                   G4double width,
326                                   G4double offset)
327 {
328   // Creates division in the given mother.
329   // The result is a pair of physical volumes;
330   // the second physical volume is a division in a reflected mother
331   // or nullptr if mother LV was not reflected.
332   // ---
333 
334   if (fVerboseLevel>0)
335   {
336     G4cout << "Divide " << name << " lv " << LV << " " 
337            << LV->GetName() << G4endl;
338   }  
339 
340   G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
341 
342   G4VPhysicalVolume* pv1 = divisionFactory
343     -> CreatePVDivision(name, LV, motherLV, axis, width, offset);
344  
345   G4VPhysicalVolume* pv2 = nullptr;
346   if (G4LogicalVolume* reflMotherLV = GetReflectedLV(motherLV))
347   {
348     // if mother was reflected
349     // reflect the LV and replicate it in reflected mother
350     
351     pv2 = divisionFactory->CreatePVDivision(name, ReflectLV(LV), reflMotherLV, 
352                                             axis, width, offset); 
353   }
354     
355   return {pv1, pv2};            
356 }         
357         
358              
359 //
360 // private methods
361 //
362 
363 //_____________________________________________________________________________
364 
365 G4LogicalVolume* G4ReflectionFactory::ReflectLV(G4LogicalVolume* LV,
366                                                 G4bool surfCheck) 
367 {
368   // Gets/creates the reflected solid and logical volume
369   // and copies + transforms LV daughters.
370   // ---
371 
372   G4LogicalVolume* refLV = GetReflectedLV(LV);
373 
374   if (refLV == nullptr)
375   {
376 
377     // create new (reflected) objects
378     //
379     refLV = CreateReflectedLV(LV);
380         
381     // process daughters  
382     //
383     ReflectDaughters(LV, refLV, surfCheck);
384 
385     // check if to be set as root region
386     //
387     if (LV->IsRootRegion())
388     {
389        LV->GetRegion()->AddRootLogicalVolume(refLV);
390     }
391   }
392 
393   return refLV;
394 }
395 
396 //_____________________________________________________________________________
397 
398 G4LogicalVolume* G4ReflectionFactory::CreateReflectedLV(G4LogicalVolume* LV) 
399 {
400   // Creates the reflected solid and logical volume
401   // and add the logical volumes pair in the maps.
402   // ---
403 
404   // consistency check
405   //
406   if (fReflectedLVMap.find(LV) != fReflectedLVMap.end())
407   {
408     std::ostringstream message;
409     message << "Invalid reflection for volume: "
410            << LV->GetName() << G4endl
411            << "Cannot be applied to a volume already reflected !";
412     G4Exception("G4ReflectionFactory::CreateReflectedLV()",
413                 "GeomVol0002", FatalException, message);
414   }        
415               
416   G4VSolid* refSolid 
417     = new G4ReflectedSolid(LV->GetSolid()->GetName() + fNameExtension,
418                            LV->GetSolid(), fScale);
419       
420   auto refLV
421     = new G4LogicalVolume(refSolid, 
422                           LV->GetMaterial(),                 
423                           LV->GetName() + fNameExtension,
424                           LV->GetFieldManager(),
425                           LV->GetSensitiveDetector(),
426                           LV->GetUserLimits());
427 
428   if (LV->GetVisAttributes() != nullptr) {
429     refLV->SetVisAttributes(*LV->GetVisAttributes());  // vis-attributes
430   }
431   refLV->SetBiasWeight(LV->GetBiasWeight());        // biasing weight
432   if (LV->IsRegion())
433   {
434     refLV->SetRegion(LV->GetRegion());              // set a region in case
435   }
436 
437   fConstituentLVMap[LV] = refLV;
438   fReflectedLVMap[refLV] = LV;
439 
440   return refLV;        
441 }
442 
443 //_____________________________________________________________________________
444 
445 void G4ReflectionFactory::ReflectDaughters(G4LogicalVolume* LV, 
446                                            G4LogicalVolume* refLV,
447                                            G4bool surfCheck)
448 {
449   // Reflects daughters recursively.
450   // ---
451 
452   if (fVerboseLevel>0)
453   {
454     G4cout << "G4ReflectionFactory::ReflectDaughters(): " 
455            << LV->GetNoDaughters() << " of " << LV->GetName() << G4endl;
456   }     
457 
458   for (std::size_t i=0; i<LV->GetNoDaughters(); ++i)
459   {
460     G4VPhysicalVolume* dPV = LV->GetDaughter((G4int)i);
461     
462     if (!dPV->IsReplicated())
463     {
464       ReflectPVPlacement(dPV, refLV, surfCheck); 
465     }  
466     else if (dPV->GetParameterisation() == nullptr)
467     {
468       ReflectPVReplica(dPV, refLV); 
469     }  
470     else if ((G4VPVDivisionFactory::Instance() != nullptr) &&
471              G4VPVDivisionFactory::Instance()->IsPVDivision(dPV))
472     {
473       ReflectPVDivision(dPV, refLV); 
474     }  
475     else
476     {
477       ReflectPVParameterised(dPV, refLV, surfCheck); 
478     }
479   }
480 }
481 
482 //_____________________________________________________________________________
483 
484 void G4ReflectionFactory::ReflectPVPlacement(G4VPhysicalVolume* dPV, 
485                                              G4LogicalVolume* refLV,
486                                              G4bool surfCheck)
487 {
488   // Copies and transforms daughter of PVPlacement type of
489   // a constituent volume into a reflected volume. 
490   // ---
491 
492   G4LogicalVolume* dLV = dPV->GetLogicalVolume();
493 
494   // update daughter transformation
495   //
496   G4Transform3D dt(dPV->GetObjectRotationValue(), dPV->GetObjectTranslation());
497   dt = fScale * (dt * fScale.inverse());
498 
499   G4LogicalVolume* refDLV;
500   
501   if (fVerboseLevel>0) 
502     G4cout << "Daughter: " << dPV << "  " << dLV->GetName();
503   
504   if (!IsReflected(dLV))
505   {
506 
507     if (fVerboseLevel>0) 
508       G4cout << " will be reflected." << G4endl;
509 
510     // get reflected volume if already created
511     refDLV = GetReflectedLV(dLV); 
512 
513     if (refDLV == nullptr)
514     {
515       // create new daughter solid and logical volume
516       //
517       refDLV = CreateReflectedLV(dLV); 
518   
519       // recursive call
520       //
521       ReflectDaughters(dLV, refDLV, surfCheck);   
522     }  
523 
524     // create new daughter physical volume
525     // with updated transformation
526 
527     new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV, 
528                       dPV->IsMany(), dPV->GetCopyNo(), surfCheck); 
529 
530   } 
531   else
532   {
533     if (fVerboseLevel>0) 
534       G4cout << " will be reconstitued." << G4endl;
535 
536     refDLV = GetConstituentLV(dLV); 
537 
538     new G4PVPlacement(dt, refDLV, dPV->GetName(), refLV, 
539                       dPV->IsMany(), dPV->GetCopyNo(), surfCheck); 
540   }       
541 }    
542 
543 //_____________________________________________________________________________
544 
545 void G4ReflectionFactory::ReflectPVReplica(G4VPhysicalVolume* dPV, 
546                                            G4LogicalVolume* refLV)
547 {
548   // Copies and transforms daughter of PVReplica type of
549   // a constituent volume into a reflected volume. 
550   // ---
551 
552   G4LogicalVolume* dLV = dPV->GetLogicalVolume();
553 
554   // get replication data
555   //
556   EAxis axis;
557   G4int nofReplicas;
558   G4double width;
559   G4double offset;
560   G4bool consuming;
561 
562   dPV->GetReplicationData(axis, nofReplicas, width, offset, consuming);
563 
564   G4LogicalVolume* refDLV;
565   
566   if (fVerboseLevel>0) 
567     G4cout << "Daughter: " << dPV << "  " << dLV->GetName();
568   
569   if (!IsReflected(dLV))
570   {
571     if (fVerboseLevel>0) 
572       G4cout << " will be reflected." << G4endl;
573 
574     // get reflected volume if already created
575     //
576     refDLV = GetReflectedLV(dLV); 
577 
578     if (refDLV == nullptr)
579     {
580       // create new daughter solid and logical volume
581       //
582       refDLV = CreateReflectedLV(dLV); 
583   
584       // recursive call
585       //
586       ReflectDaughters(dLV, refDLV); 
587     }     
588         
589     // create new daughter replica
590     //
591     new G4PVReplica(dPV->GetName(), refDLV, refLV, 
592                     axis, nofReplicas, width, offset);
593   }
594   else
595   {
596     if (fVerboseLevel>0) 
597       G4cout << " will be reconstitued." << G4endl;
598 
599     refDLV = GetConstituentLV(dLV); 
600 
601     new G4PVReplica(dPV->GetName(), refDLV, refLV, 
602                     axis, nofReplicas, width, offset); 
603   }       
604 }
605 
606 //_____________________________________________________________________________
607 
608 void G4ReflectionFactory::ReflectPVDivision(G4VPhysicalVolume* dPV, 
609                                             G4LogicalVolume* refLV)
610 {
611   // Copies and transforms daughter of PVDivision type of
612   // a constituent volume into a reflected volume. 
613   // ---
614 
615   G4VPVDivisionFactory* divisionFactory = GetPVDivisionFactory();
616 
617   G4LogicalVolume* dLV = dPV->GetLogicalVolume();
618 
619   // get parameterisation data
620   //
621   G4VPVParameterisation* param = dPV->GetParameterisation();
622 
623   G4LogicalVolume* refDLV;
624   
625   if (fVerboseLevel>0) 
626     G4cout << "Daughter: " << dPV << "  " << dLV->GetName();
627   
628   if (!IsReflected(dLV))
629   {
630     if (fVerboseLevel>0) 
631       G4cout << " will be reflected." << G4endl;
632 
633     // get reflected volume if already created
634     //
635     refDLV = GetReflectedLV(dLV); 
636 
637     if (refDLV == nullptr)
638     {
639       // create new daughter solid and logical volume
640       //
641       refDLV = CreateReflectedLV(dLV); 
642   
643       // recursive call
644       //
645       ReflectDaughters(dLV, refDLV); 
646     }     
647         
648     // create new daughter replica
649     //
650     divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param);
651   }
652   else
653   {
654     if (fVerboseLevel>0) 
655       G4cout << " will be reconstitued." << G4endl;
656 
657     refDLV = GetConstituentLV(dLV); 
658 
659     divisionFactory->CreatePVDivision(dPV->GetName(), refDLV, refLV, param); 
660   }       
661 }
662 
663 //_____________________________________________________________________________
664 
665 void G4ReflectionFactory::ReflectPVParameterised(G4VPhysicalVolume* dPV, 
666                                                  G4LogicalVolume*, G4bool)
667 {
668   // Not implemented.
669   // Should copy and transform daughter of PVReplica type of
670   // a constituent volume into a reflected volume. 
671   // ---
672 
673   std::ostringstream message;
674   message << "Not yet implemented. Volume: " << dPV->GetName() << G4endl
675           << "Reflection of parameterised volumes is not yet implemented.";
676   G4Exception("G4ReflectionFactory::ReflectPVParameterised()",
677               "GeomVol0001", FatalException, message);
678 }
679 
680 //_____________________________________________________________________________
681 
682 G4LogicalVolume*
683 G4ReflectionFactory::GetConstituentLV(G4LogicalVolume* reflLV) const
684 {              
685   // Returns the consituent volume of the given reflected volume,
686   // nullptr if the given reflected volume was not found.
687   // ---
688 
689   auto it = fReflectedLVMap.find(reflLV);
690 
691   if (it == fReflectedLVMap.end()) return nullptr;
692 
693   return (*it).second;
694 }        
695 
696 //_____________________________________________________________________________
697 
698 G4LogicalVolume*
699 G4ReflectionFactory::GetReflectedLV(G4LogicalVolume* lv) const
700 {              
701   // Returns the reflected volume of the given consituent volume,
702   // nullptr if the given volume was not reflected.
703   // ---
704 
705   auto it = fConstituentLVMap.find(lv);
706 
707   if (it == fConstituentLVMap.end()) return nullptr;
708 
709   return (*it).second;
710 }        
711 
712 //_____________________________________________________________________________
713 
714 G4bool G4ReflectionFactory::IsConstituent(G4LogicalVolume* lv) const
715 {
716   // Returns true if the given volume has been already reflected
717   // (is in the map of constituent volumes).
718   // ---
719 
720   return (fConstituentLVMap.find(lv) != fConstituentLVMap.end());
721 }  
722 
723 //_____________________________________________________________________________
724 
725 G4bool G4ReflectionFactory::IsReflected(G4LogicalVolume* lv) const
726 {
727   // Returns true if the given volume is a reflected volume
728   // (is in the map reflected  volumes).
729   // ---
730 
731   return (fReflectedLVMap.find(lv) != fReflectedLVMap.end());
732 }  
733 
734 //_____________________________________________________________________________
735 
736 G4bool G4ReflectionFactory::IsReflection(const G4Scale3D& scale) const
737 {
738   // Returns true if the scale is negative, false otherwise.
739   // ---
740 
741   return scale(0,0)*scale(1,1)*scale(2,2) < 0.;  
742 }
743 
744 //_____________________________________________________________________________
745 
746 const G4ReflectedVolumesMap&
747 G4ReflectionFactory::GetReflectedVolumesMap() const
748 {
749   return fReflectedLVMap;
750 }
751 
752 //_____________________________________________________________________________
753 
754 void G4ReflectionFactory::Clean()
755 {
756   fConstituentLVMap.clear();
757   fReflectedLVMap.clear();
758 }
759 
760 //_____________________________________________________________________________
761 
762 void G4ReflectionFactory::PrintConstituentLVMap()
763 {
764   // temporary - for debugging purpose
765   // ---
766 
767   LogicalVolumesMapIterator it;
768   for (it = fConstituentLVMap.begin(); it != fConstituentLVMap.end(); ++it)
769   {
770     G4cout << "lv: " << (*it).first << "  lv_refl: " << (*it).second << G4endl;
771   }
772   G4cout << G4endl;
773 }  
774 
775 //_____________________________________________________________________________
776 
777 void G4ReflectionFactory::CheckScale(const G4Scale3D& scale) const
778 {
779   // Check if scale correspond to fScale,
780   // if not give exception.
781   // ---
782 
783   if (!IsReflection(scale)) return;
784   
785   G4double diff = 0.;
786   for (auto i=0; i<4; ++i)
787     for (auto j=0; j<4; ++j) 
788       diff += std::abs(scale(i,j) - fScale(i,j));  
789 
790   if (diff > fScalePrecision)
791   {
792     std::ostringstream message;
793     message << "Unexpected scale in input !" << G4endl
794             << "        Difference: " << diff;
795     G4Exception("G4ReflectionFactory::CheckScale()",
796                 "GeomVol0002", FatalException, message);
797   }
798 }    
799 
800 //_____________________________________________________________________________
801 
802 G4VPVDivisionFactory* G4ReflectionFactory::GetPVDivisionFactory() const
803 {
804   // Returns the G4PVDivisionFactory instance if it exists,
805   // otherwise gives exception 
806   // ---
807 
808   G4VPVDivisionFactory* divisionFactory = G4VPVDivisionFactory::Instance();
809   if (divisionFactory == nullptr)
810   {
811     std::ostringstream message;
812     message << "A concrete G4PVDivisionFactory instantiated is required !"
813             << G4endl
814             << "        It has been requested to reflect divided volumes."
815             << G4endl
816             << "        In this case, it is required to instantiate a concrete"
817             << G4endl
818             << "        factory G4PVDivisionFactory in your program -before-"
819             << G4endl
820             << "        executing the reflection !";
821      G4Exception("G4ReflectionFactory::GetPVDivisionFactory()",
822                  "GeomVol0002", FatalException, message);
823   }
824   
825   return divisionFactory;
826 }  
827 
828 //_____________________________________________________________________________
829 
830 void G4ReflectionFactory::SetScalePrecision(G4double scaleValue)
831 {
832   fScalePrecision = scaleValue;
833 }
834 
835 //_____________________________________________________________________________
836 
837 G4double G4ReflectionFactory::GetScalePrecision() const
838 {
839   return fScalePrecision;
840 }
841 
842 //_____________________________________________________________________________
843 
844 void G4ReflectionFactory::SetVerboseLevel(G4int verboseLevel)
845 {
846   fVerboseLevel = verboseLevel;
847 }
848           
849 //_____________________________________________________________________________
850 
851 G4int G4ReflectionFactory::GetVerboseLevel() const
852 {
853   return fVerboseLevel;
854 }
855 
856 //_____________________________________________________________________________
857 
858 void G4ReflectionFactory::SetVolumesNameExtension(const G4String& nameExtension)
859 {
860   fNameExtension = nameExtension;
861 }
862           
863 //_____________________________________________________________________________
864 
865 const G4String& G4ReflectionFactory::GetVolumesNameExtension() const
866 {
867   return fNameExtension;
868 }
869