Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/persistency/gdml/src/G4GDMLWriteStructure.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 ]

Diff markup

Differences between /persistency/gdml/src/G4GDMLWriteStructure.cc (Version 11.3.0) and /persistency/gdml/src/G4GDMLWriteStructure.cc (Version 5.0.p1)


  1 //                                                  1 
  2 // *******************************************    
  3 // * License and Disclaimer                       
  4 // *                                              
  5 // * The  Geant4 software  is  copyright of th    
  6 // * the Geant4 Collaboration.  It is provided    
  7 // * conditions of the Geant4 Software License    
  8 // * LICENSE and available at  http://cern.ch/    
  9 // * include a list of copyright holders.         
 10 // *                                              
 11 // * Neither the authors of this software syst    
 12 // * institutes,nor the agencies providing fin    
 13 // * work  make  any representation or  warran    
 14 // * regarding  this  software system or assum    
 15 // * use.  Please see the license in the file     
 16 // * for the full disclaimer and the limitatio    
 17 // *                                              
 18 // * This  code  implementation is the result     
 19 // * technical work of the GEANT4 collaboratio    
 20 // * By using,  copying,  modifying or  distri    
 21 // * any work based  on the software)  you  ag    
 22 // * use  in  resulting  scientific  publicati    
 23 // * acceptance of all terms of the Geant4 Sof    
 24 // *******************************************    
 25 //                                                
 26 // G4GDMLWriteStructure implementation            
 27 //                                                
 28 // Author: Zoltan Torzsok, November 2007          
 29 // -------------------------------------------    
 30                                                   
 31 #include "G4GDMLWriteStructure.hh"                
 32 #include "G4GDMLEvaluator.hh"                     
 33                                                   
 34 #include "G4Material.hh"                          
 35 #include "G4ReflectedSolid.hh"                    
 36 #include "G4DisplacedSolid.hh"                    
 37 #include "G4LogicalVolumeStore.hh"                
 38 #include "G4PhysicalVolumeStore.hh"               
 39 #include "G4ReflectionFactory.hh"                 
 40 #include "G4PVDivision.hh"                        
 41 #include "G4PVReplica.hh"                         
 42 #include "G4Region.hh"                            
 43 #include "G4OpticalSurface.hh"                    
 44 #include "G4LogicalSkinSurface.hh"                
 45 #include "G4LogicalBorderSurface.hh"              
 46                                                   
 47 #include "G4ProductionCuts.hh"                    
 48 #include "G4ProductionCutsTable.hh"               
 49 #include "G4Gamma.hh"                             
 50 #include "G4Electron.hh"                          
 51 #include "G4Positron.hh"                          
 52 #include "G4Proton.hh"                            
 53                                                   
 54 #include "G4VSensitiveDetector.hh"                
 55 #include "G4AssemblyStore.hh"                     
 56 #include "G4AssemblyVolume.hh"                    
 57                                                   
 58 G4int G4GDMLWriteStructure::levelNo = 0;  // C    
 59                                                   
 60 // -------------------------------------------    
 61 G4GDMLWriteStructure::G4GDMLWriteStructure()      
 62   : G4GDMLWriteParamvol()                         
 63   , maxLevel(INT_MAX)                             
 64 {                                                 
 65   reflFactory = G4ReflectionFactory::Instance(    
 66 }                                                 
 67                                                   
 68 // -------------------------------------------    
 69 G4GDMLWriteStructure::~G4GDMLWriteStructure()     
 70 {                                                 
 71 }                                                 
 72                                                   
 73 // -------------------------------------------    
 74 void G4GDMLWriteStructure::DivisionvolWrite(      
 75   xercesc::DOMElement* volumeElement, const G4    
 76 {                                                 
 77   EAxis axis       = kUndefined;                  
 78   G4int number     = 0;                           
 79   G4double width   = 0.0;                         
 80   G4double offset  = 0.0;                         
 81   G4bool consuming = false;                       
 82                                                   
 83   divisionvol->GetReplicationData(axis, number    
 84   axis = divisionvol->GetDivisionAxis();          
 85                                                   
 86   G4String unitString("mm");                      
 87   G4String axisString("kUndefined");              
 88   if(axis == kXAxis)                              
 89   {                                               
 90     axisString = "kXAxis";                        
 91   }                                               
 92   else if(axis == kYAxis)                         
 93   {                                               
 94     axisString = "kYAxis";                        
 95   }                                               
 96   else if(axis == kZAxis)                         
 97   {                                               
 98     axisString = "kZAxis";                        
 99   }                                               
100   else if(axis == kRho)                           
101   {                                               
102     axisString = "kRho";                          
103   }                                               
104   else if(axis == kPhi)                           
105   {                                               
106     axisString = "kPhi";                          
107     unitString = "rad";                           
108   }                                               
109                                                   
110   const G4String name = GenerateName(divisionv    
111   const G4String volumeref =                      
112     GenerateName(divisionvol->GetLogicalVolume    
113                  divisionvol->GetLogicalVolume    
114                                                   
115   xercesc::DOMElement* divisionvolElement = Ne    
116   divisionvolElement->setAttributeNode(NewAttr    
117   divisionvolElement->setAttributeNode(NewAttr    
118   divisionvolElement->setAttributeNode(NewAttr    
119   divisionvolElement->setAttributeNode(NewAttr    
120   divisionvolElement->setAttributeNode(NewAttr    
121   xercesc::DOMElement* volumerefElement = NewE    
122   volumerefElement->setAttributeNode(NewAttrib    
123   divisionvolElement->appendChild(volumerefEle    
124   volumeElement->appendChild(divisionvolElemen    
125 }                                                 
126                                                   
127 // -------------------------------------------    
128 void G4GDMLWriteStructure::PhysvolWrite(xerces    
129                                         const     
130                                         const     
131                                         const     
132 {                                                 
133   HepGeom::Scale3D scale;                         
134   HepGeom::Rotate3D rotate;                       
135   HepGeom::Translate3D translate;                 
136                                                   
137   T.getDecomposition(scale, rotate, translate)    
138                                                   
139   const G4ThreeVector scl(scale(0, 0), scale(1    
140   const G4ThreeVector rot = GetAngles(rotate.g    
141   const G4ThreeVector pos = T.getTranslation()    
142                                                   
143   const G4String name    = GenerateName(physvo    
144   const G4int copynumber = physvol->GetCopyNo(    
145                                                   
146   xercesc::DOMElement* physvolElement = NewEle    
147   physvolElement->setAttributeNode(NewAttribut    
148   if(copynumber)                                  
149   {                                               
150     physvolElement->setAttributeNode(NewAttrib    
151   }                                               
152                                                   
153   volumeElement->appendChild(physvolElement);     
154                                                   
155   G4LogicalVolume* lv;                            
156   // Is it reflected?                             
157   if(reflFactory->IsReflected(physvol->GetLogi    
158   {                                               
159     lv = reflFactory->GetConstituentLV(physvol    
160   }                                               
161   else                                            
162   {                                               
163     lv = physvol->GetLogicalVolume();             
164   }                                               
165                                                   
166   const G4String volumeref = GenerateName(lv->    
167                                                   
168   if(ModuleName.empty())                          
169   {                                               
170     xercesc::DOMElement* volumerefElement = Ne    
171     volumerefElement->setAttributeNode(NewAttr    
172     physvolElement->appendChild(volumerefEleme    
173   }                                               
174   else                                            
175   {                                               
176     xercesc::DOMElement* fileElement = NewElem    
177     fileElement->setAttributeNode(NewAttribute    
178     fileElement->setAttributeNode(NewAttribute    
179     physvolElement->appendChild(fileElement);     
180   }                                               
181                                                   
182   if(std::fabs(pos.x()) > kLinearPrecision ||     
183      std::fabs(pos.y()) > kLinearPrecision ||     
184      std::fabs(pos.z()) > kLinearPrecision)       
185   {                                               
186     PositionWrite(physvolElement, name + "_pos    
187   }                                               
188   if(std::fabs(rot.x()) > kAngularPrecision ||    
189      std::fabs(rot.y()) > kAngularPrecision ||    
190      std::fabs(rot.z()) > kAngularPrecision)      
191   {                                               
192     RotationWrite(physvolElement, name + "_rot    
193   }                                               
194   if(std::fabs(scl.x() - 1.0) > kRelativePreci    
195      std::fabs(scl.y() - 1.0) > kRelativePreci    
196      std::fabs(scl.z() - 1.0) > kRelativePreci    
197   {                                               
198     ScaleWrite(physvolElement, name + "_scl",     
199   }                                               
200 }                                                 
201                                                   
202 // -------------------------------------------    
203 void G4GDMLWriteStructure::ReplicavolWrite(       
204   xercesc::DOMElement* volumeElement, const G4    
205 {                                                 
206   EAxis axis       = kUndefined;                  
207   G4int number     = 0;                           
208   G4double width   = 0.0;                         
209   G4double offset  = 0.0;                         
210   G4bool consuming = false;                       
211   G4String unitString("mm");                      
212                                                   
213   replicavol->GetReplicationData(axis, number,    
214                                                   
215   const G4String volumeref = GenerateName(        
216     replicavol->GetLogicalVolume()->GetName(),    
217                                                   
218   xercesc::DOMElement* replicavolElement = New    
219   replicavolElement->setAttributeNode(NewAttri    
220   xercesc::DOMElement* volumerefElement = NewE    
221   volumerefElement->setAttributeNode(NewAttrib    
222   replicavolElement->appendChild(volumerefElem    
223   xercesc::DOMElement* replicateElement = NewE    
224   replicavolElement->appendChild(replicateElem    
225                                                   
226   xercesc::DOMElement* dirElement = NewElement    
227   if(axis == kXAxis)                              
228   {                                               
229     dirElement->setAttributeNode(NewAttribute(    
230   }                                               
231   else if(axis == kYAxis)                         
232   {                                               
233     dirElement->setAttributeNode(NewAttribute(    
234   }                                               
235   else if(axis == kZAxis)                         
236   {                                               
237     dirElement->setAttributeNode(NewAttribute(    
238   }                                               
239   else if(axis == kRho)                           
240   {                                               
241     dirElement->setAttributeNode(NewAttribute(    
242   }                                               
243   else if(axis == kPhi)                           
244   {                                               
245     dirElement->setAttributeNode(NewAttribute(    
246     unitString = "rad";                           
247   }                                               
248   replicateElement->appendChild(dirElement);      
249                                                   
250   xercesc::DOMElement* widthElement = NewEleme    
251   widthElement->setAttributeNode(NewAttribute(    
252   widthElement->setAttributeNode(NewAttribute(    
253   replicateElement->appendChild(widthElement);    
254                                                   
255   xercesc::DOMElement* offsetElement = NewElem    
256   offsetElement->setAttributeNode(NewAttribute    
257   offsetElement->setAttributeNode(NewAttribute    
258   replicateElement->appendChild(offsetElement)    
259                                                   
260   volumeElement->appendChild(replicavolElement    
261 }                                                 
262                                                   
263 // -------------------------------------------    
264 void G4GDMLWriteStructure::AssemblyWrite(xerce    
265                                          const    
266 {                                                 
267   G4AssemblyStore* assemblies  = G4AssemblySto    
268   G4AssemblyVolume* myassembly = assemblies->G    
269                                                   
270   xercesc::DOMElement* assemblyElement = NewEl    
271   G4String name = "Assembly_" + std::to_string    
272                                                   
273   assemblyElement->setAttributeNode(NewAttribu    
274                                                   
275   auto vit = myassembly->GetTripletsIterator()    
276                                                   
277   G4int depth = 0;                                
278   const G4String ModuleName;                      
279                                                   
280   for(std::size_t i5 = 0; i5 < myassembly->Tot    
281   {                                               
282     G4LogicalVolume* lvol = (*vit).GetVolume()    
283     if (lvol == nullptr)                          
284     {                                             
285       G4String message = "Nested assemblies no    
286       G4Exception("G4GDMLWriteStructure::Assem    
287                   FatalException, message);       
288       return;                                     
289     }                                             
290     TraverseVolumeTree(lvol, depth + 1);          
291                                                   
292     const G4ThreeVector rot = GetAngles((*vit)    
293     const G4ThreeVector pos = (*vit).GetTransl    
294                                                   
295     const G4String pname =                        
296       GenerateName((*vit).GetVolume()->GetName    
297                                                   
298     xercesc::DOMElement* physvolElement = NewE    
299     physvolElement->setAttributeNode(NewAttrib    
300                                                   
301     assemblyElement->appendChild(physvolElemen    
302                                                   
303     const G4String volumeref =                    
304       GenerateName((*vit).GetVolume()->GetName    
305                                                   
306     xercesc::DOMElement* volumerefElement = Ne    
307     volumerefElement->setAttributeNode(NewAttr    
308     physvolElement->appendChild(volumerefEleme    
309                                                   
310     if(std::fabs(pos.x()) > kLinearPrecision |    
311        std::fabs(pos.y()) > kLinearPrecision |    
312        std::fabs(pos.z()) > kLinearPrecision)     
313     {                                             
314       PositionWrite(physvolElement,name+"_posi    
315     }                                             
316                                                   
317     if(std::fabs(rot.x()) > kAngularPrecision     
318        std::fabs(rot.y()) > kAngularPrecision     
319        std::fabs(rot.z()) > kAngularPrecision)    
320     {                                             
321       RotationWrite(physvolElement,name+"_rota    
322     }                                             
323     ++vit;                                        
324   }                                               
325                                                   
326   volumeElement->appendChild(assemblyElement);    
327 }                                                 
328                                                   
329 // -------------------------------------------    
330 void G4GDMLWriteStructure::BorderSurfaceCache(    
331   const G4LogicalBorderSurface* const bsurf)      
332 {                                                 
333   if(bsurf == nullptr)                            
334   {                                               
335     return;                                       
336   }                                               
337                                                   
338   const G4SurfaceProperty* psurf = bsurf->GetS    
339                                                   
340   // Generate the new element for border-surfa    
341   //                                              
342   const G4String& bsname             = Generat    
343   const G4String& psname             = Generat    
344   xercesc::DOMElement* borderElement = NewElem    
345   borderElement->setAttributeNode(NewAttribute    
346   borderElement->setAttributeNode(NewAttribute    
347                                                   
348   const G4String volumeref1 =                     
349     GenerateName(bsurf->GetVolume1()->GetName(    
350   const G4String volumeref2 =                     
351     GenerateName(bsurf->GetVolume2()->GetName(    
352   xercesc::DOMElement* volumerefElement1 = New    
353   xercesc::DOMElement* volumerefElement2 = New    
354   volumerefElement1->setAttributeNode(NewAttri    
355   volumerefElement2->setAttributeNode(NewAttri    
356   borderElement->appendChild(volumerefElement1    
357   borderElement->appendChild(volumerefElement2    
358                                                   
359   if(FindOpticalSurface(psurf))                   
360   {                                               
361     const G4OpticalSurface* opsurf =              
362       dynamic_cast<const G4OpticalSurface*>(ps    
363     if(opsurf == nullptr)                         
364     {                                             
365       G4Exception("G4GDMLWriteStructure::Borde    
366                   FatalException, "No optical     
367       return;                                     
368     }                                             
369     OpticalSurfaceWrite(solidsElement, opsurf)    
370   }                                               
371                                                   
372   borderElementVec.push_back(borderElement);      
373 }                                                 
374                                                   
375 // -------------------------------------------    
376 void G4GDMLWriteStructure::SkinSurfaceCache(      
377   const G4LogicalSkinSurface* const ssurf)        
378 {                                                 
379   if(ssurf == nullptr)                            
380   {                                               
381     return;                                       
382   }                                               
383                                                   
384   const G4SurfaceProperty* psurf = ssurf->GetS    
385                                                   
386   // Generate the new element for border-surfa    
387   //                                              
388   const G4String& ssname           = GenerateN    
389   const G4String& psname           = GenerateN    
390   xercesc::DOMElement* skinElement = NewElemen    
391   skinElement->setAttributeNode(NewAttribute("    
392   skinElement->setAttributeNode(NewAttribute("    
393                                                   
394   const G4String volumeref = GenerateName(ssur    
395                                           ssur    
396   xercesc::DOMElement* volumerefElement = NewE    
397   volumerefElement->setAttributeNode(NewAttrib    
398   skinElement->appendChild(volumerefElement);     
399                                                   
400   if(FindOpticalSurface(psurf))                   
401   {                                               
402     const G4OpticalSurface* opsurf =              
403       dynamic_cast<const G4OpticalSurface*>(ps    
404     if(opsurf == nullptr)                         
405     {                                             
406       G4Exception("G4GDMLWriteStructure::SkinS    
407                   FatalException, "No optical     
408       return;                                     
409     }                                             
410     OpticalSurfaceWrite(solidsElement, opsurf)    
411   }                                               
412                                                   
413   skinElementVec.push_back(skinElement);          
414 }                                                 
415                                                   
416 // -------------------------------------------    
417 G4bool G4GDMLWriteStructure::FindOpticalSurfac    
418 {                                                 
419   const G4OpticalSurface* osurf = dynamic_cast    
420   auto pos = std::find(opt_vec.cbegin(), opt_v    
421   if(pos != opt_vec.cend())                       
422   {                                               
423     return false;                                 
424   }  // item already created!                     
425                                                   
426   opt_vec.push_back(osurf);  // cache it for f    
427   return true;                                    
428 }                                                 
429                                                   
430 // -------------------------------------------    
431 const G4LogicalSkinSurface* G4GDMLWriteStructu    
432   const G4LogicalVolume* const lvol)              
433 {                                                 
434   G4LogicalSkinSurface* surf = nullptr;           
435   std::size_t nsurf = G4LogicalSkinSurface::Ge    
436   if(nsurf)                                       
437   {                                               
438     const G4LogicalSkinSurfaceTable* stable =     
439       G4LogicalSkinSurface::GetSurfaceTable();    
440     auto pos = stable->find(lvol);                
441     if(pos != stable->cend())                     
442     {                                             
443       surf = pos->second;                         
444     }                                             
445   }                                               
446   return surf;                                    
447 }                                                 
448                                                   
449 // -------------------------------------------    
450 const G4LogicalBorderSurface* G4GDMLWriteStruc    
451   const G4VPhysicalVolume* const pvol)            
452 {                                                 
453   G4LogicalBorderSurface* surf = nullptr;         
454   std::size_t nsurf = G4LogicalBorderSurface::    
455   if(nsurf)                                       
456   {                                               
457     const G4LogicalBorderSurfaceTable* btable     
458       G4LogicalBorderSurface::GetSurfaceTable(    
459     for(auto pos = btable->cbegin(); pos != bt    
460     {                                             
461       if(pvol == pos->first.first)  // just th    
462       {                             // could b    
463         surf = pos->second;         // break;     
464         BorderSurfaceCache(surf);                 
465       }                                           
466     }                                             
467   }                                               
468   return surf;                                    
469 }                                                 
470                                                   
471 // -------------------------------------------    
472 void G4GDMLWriteStructure::SurfacesWrite()        
473 {                                                 
474 #ifdef G4VERBOSE                                  
475   G4cout << "G4GDML: Writing surfaces..." << G    
476 #endif                                            
477   for(auto pos = skinElementVec.cbegin();         
478            pos != skinElementVec.cend(); ++pos    
479   {                                               
480     structureElement->appendChild(*pos);          
481   }                                               
482   for(auto pos = borderElementVec.cbegin();       
483            pos != borderElementVec.cend(); ++p    
484   {                                               
485     structureElement->appendChild(*pos);          
486   }                                               
487 }                                                 
488                                                   
489 // -------------------------------------------    
490 void G4GDMLWriteStructure::StructureWrite(xerc    
491 {                                                 
492 #ifdef G4VERBOSE                                  
493   G4cout << "G4GDML: Writing structure..." <<     
494 #endif                                            
495                                                   
496   // filling the list of phys volumes that are    
497                                                   
498   G4AssemblyStore* assemblies = G4AssemblyStor    
499                                                   
500   for(auto it = assemblies->cbegin(); it != as    
501   {                                               
502     auto vit = (*it)->GetVolumesIterator();       
503                                                   
504     for(std::size_t i5 = 0; i5 < (*it)->TotalI    
505     {                                             
506       G4String pvname = (*vit)->GetName();        
507       std::size_t pos = pvname.find("_impr_")     
508       G4String impID  = pvname.substr(pos);       
509                                                   
510       pos   = impID.find("_");                    
511       impID = impID.substr(0, pos);               
512                                                   
513       assemblyVolMap[*vit] = (*it)->GetAssembl    
514       imprintsMap[*vit]    = std::atoi(impID.c    
515       ++vit;                                      
516     }                                             
517   }                                               
518                                                   
519   structureElement = NewElement("structure");     
520   gdmlElement->appendChild(structureElement);     
521 }                                                 
522                                                   
523 // -------------------------------------------    
524 G4Transform3D G4GDMLWriteStructure::TraverseVo    
525   const G4LogicalVolume* const volumePtr, cons    
526 {                                                 
527   if(VolumeMap().find(volumePtr) != VolumeMap(    
528   {                                               
529     return VolumeMap()[volumePtr];  // Volume     
530   }                                               
531                                                   
532   G4VSolid* solidPtr = volumePtr->GetSolid();     
533   G4Transform3D R, invR;                          
534   G4int trans = 0;                                
535                                                   
536   std::map<const G4LogicalVolume*, G4GDMLAuxLi    
537                                                   
538   ++levelNo;                                      
539                                                   
540   while(true)  // Solve possible displacement/    
541   {            // of the referenced solid!        
542     if(trans > maxTransforms)                     
543     {                                             
544       G4String ErrorMessage = "Referenced soli    
545                               volumePtr->GetNa    
546                               "' was displaced    
547       G4Exception("G4GDMLWriteStructure::Trave    
548                   FatalException, ErrorMessage    
549     }                                             
550                                                   
551     if(G4ReflectedSolid* refl = dynamic_cast<G    
552     {                                             
553       R        = R * refl->GetTransform3D();      
554       solidPtr = refl->GetConstituentMovedSoli    
555       ++trans;                                    
556       continue;                                   
557     }                                             
558                                                   
559     if(G4DisplacedSolid* disp = dynamic_cast<G    
560     {                                             
561       R        = R * G4Transform3D(disp->GetOb    
562                             disp->GetObjectTra    
563       solidPtr = disp->GetConstituentMovedSoli    
564       ++trans;                                    
565       continue;                                   
566     }                                             
567                                                   
568     break;                                        
569   }                                               
570                                                   
571   // check if it is a reflected volume            
572   G4LogicalVolume* tmplv = const_cast<G4Logica    
573                                                   
574   if(reflFactory->IsReflected(tmplv))             
575   {                                               
576     tmplv = reflFactory->GetConstituentLV(tmpl    
577     if(VolumeMap().find(tmplv) != VolumeMap().    
578     {                                             
579       return R;  // Volume is already processe    
580     }                                             
581   }                                               
582                                                   
583   // Only compute the inverse when necessary!     
584   //                                              
585   if(trans > 0)                                   
586   {                                               
587     invR = R.inverse();                           
588   }                                               
589                                                   
590   const G4String name = GenerateName(tmplv->Ge    
591                                                   
592   G4String materialref = "NULL";                  
593                                                   
594   if(volumePtr->GetMaterial())                    
595   {                                               
596     materialref = GenerateName(volumePtr->GetM    
597                                volumePtr->GetM    
598   }                                               
599                                                   
600   const G4String solidref = GenerateName(solid    
601                                                   
602   xercesc::DOMElement* volumeElement = NewElem    
603   volumeElement->setAttributeNode(NewAttribute    
604   xercesc::DOMElement* materialrefElement = Ne    
605   materialrefElement->setAttributeNode(NewAttr    
606   volumeElement->appendChild(materialrefElemen    
607   xercesc::DOMElement* solidrefElement = NewEl    
608   solidrefElement->setAttributeNode(NewAttribu    
609   volumeElement->appendChild(solidrefElement);    
610                                                   
611   std::size_t daughterCount = volumePtr->GetNo    
612                                                   
613   if(levelNo == maxLevel)  // Stop exporting i    
614   {                                               
615     daughterCount = 0;                            
616   }                                               
617                                                   
618   std::map<G4int, std::vector<G4int> > assembl    
619                                                   
620   for(std::size_t i = 0; i < daughterCount; ++    
621   {                                               
622     const G4VPhysicalVolume* const physvol = v    
623     const G4String ModuleName              = M    
624                                                   
625     G4Transform3D daughterR;                      
626                                                   
627     if(ModuleName.empty())  // Check if subtre    
628     {                       // a separate modu    
629       daughterR = TraverseVolumeTree(physvol->    
630     }                                             
631     else                                          
632     {                                             
633       G4GDMLWriteStructure writer;                
634       daughterR = writer.Write(ModuleName, phy    
635                                SchemaLocation,    
636     }                                             
637                                                   
638     if(const G4PVDivision* const divisionvol =    
639          dynamic_cast<const G4PVDivision*>(phy    
640     {                                             
641       if(!G4Transform3D::Identity.isNear(invR     
642       {                                           
643         G4String ErrorMessage = "Division volu    
644                                 "' can not be     
645         G4Exception("G4GDMLWriteStructure::Tra    
646                     "InvalidSetup", FatalExcep    
647       }                                           
648       DivisionvolWrite(volumeElement, division    
649     }                                             
650     else                                          
651     {                                             
652       if(physvol->IsParameterised())  // Is it    
653       {                                           
654         if(!G4Transform3D::Identity.isNear(inv    
655                                            kRe    
656         {                                         
657           G4String ErrorMessage = "Parameteris    
658                                   "' can not b    
659           G4Exception("G4GDMLWriteStructure::T    
660                       "InvalidSetup", FatalExc    
661         }                                         
662         ParamvolWrite(volumeElement, physvol);    
663       }                                           
664       else                                        
665       {                                           
666         if(physvol->IsReplicated())  // Is it     
667         {                                         
668           if(!G4Transform3D::Identity.isNear(i    
669                                              k    
670           {                                       
671             G4String ErrorMessage = "Replica v    
672                                     "' can not    
673             G4Exception("G4GDMLWriteStructure:    
674                         "InvalidSetup", FatalE    
675           }                                       
676           ReplicavolWrite(volumeElement, physv    
677         }                                         
678         else  // Is it a physvol or an assembl    
679         {                                         
680           if(assemblyVolMap.find(physvol) != a    
681           {                                       
682             G4int assemblyID = assemblyVolMap[    
683                                                   
684             G4String assemblyref = "Assembly_"    
685                                                   
686             // here I need to retrieve the imp    
687                                                   
688             G4int imprintID = imprintsMap[phys    
689                                                   
690             // there are 2 steps:                 
691             //                                    
692             // 1) add assembly to the structur    
693             // (but after the constituents vol    
694             //                                    
695                                                   
696             if(std::find(addedAssemblies.cbegi    
697                          assemblyID) == addedA    
698             {                                     
699               AssemblyWrite(structureElement,     
700               addedAssemblies.push_back(assemb    
701               assemblyIDToAddedImprints[assemb    
702             }                                     
703                                                   
704             // 2) add the assembly (as physica    
705             // (but only once), using it's ori    
706             //                                    
707                                                   
708             // here I need a check if assembly    
709             // mother volume                      
710             std::vector<G4int>& addedImprints     
711             if(std::find(addedImprints.cbegin(    
712                          imprintID) == addedIm    
713             {                                     
714               G4String imprintname = "Imprint_    
715               imprintname          = GenerateN    
716                                                   
717               // I need to get those two from     
718               // the assembly I have the impri    
719               //                                  
720               G4Transform3D& transf = G4Assemb    
721                                         ->GetA    
722                                         ->GetI    
723                                                   
724               HepGeom::Scale3D scale;             
725               HepGeom::Rotate3D rotate;           
726               HepGeom::Translate3D translate;     
727                                                   
728               transf.getDecomposition(scale, r    
729                                                   
730               const G4ThreeVector scl(scale(0,    
731               const G4ThreeVector rot = GetAng    
732               const G4ThreeVector pos = transf    
733                                                   
734               // here I need a normal physvol     
735                                                   
736               xercesc::DOMElement* physvolElem    
737               physvolElement->setAttributeNode    
738                                                   
739               xercesc::DOMElement* volumerefEl    
740               volumerefElement->setAttributeNo    
741               physvolElement->appendChild(volu    
742                                                   
743               if(std::fabs(pos.x()) > kLinearP    
744                  std::fabs(pos.y()) > kLinearP    
745                  std::fabs(pos.z()) > kLinearP    
746               {                                   
747                 PositionWrite(physvolElement,     
748               }                                   
749               if(std::fabs(rot.x()) > kAngular    
750                  std::fabs(rot.y()) > kAngular    
751                  std::fabs(rot.z()) > kAngular    
752               {                                   
753                 RotationWrite(physvolElement,     
754               }                                   
755               if(std::fabs(scl.x() - 1.0) > kR    
756                  std::fabs(scl.y() - 1.0) > kR    
757                  std::fabs(scl.z() - 1.0) > kR    
758               {                                   
759                 ScaleWrite(physvolElement, nam    
760               }                                   
761                                                   
762               volumeElement->appendChild(physv    
763               //                                  
764               addedImprints.push_back(imprintI    
765             }                                     
766           }                                       
767           else  // not part of assembly, so a     
768           {                                       
769             G4RotationMatrix rot;                 
770             if(physvol->GetFrameRotation() !=     
771             {                                     
772               rot = *(physvol->GetFrameRotatio    
773             }                                     
774             G4Transform3D P(rot, physvol->GetO    
775                                                   
776             PhysvolWrite(volumeElement, physvo    
777                          ModuleName);             
778           }                                       
779         }                                         
780       }                                           
781     }                                             
782     // BorderSurfaceCache(GetBorderSurface(phy    
783     GetBorderSurface(physvol);                    
784   }                                               
785                                                   
786   if(cexport)                                     
787   {                                               
788     ExportEnergyCuts(volumePtr);                  
789   }                                               
790   // Add optional energy cuts                     
791                                                   
792   if(sdexport)                                    
793   {                                               
794     ExportSD(volumePtr);                          
795   }                                               
796   // Add optional SDs                             
797                                                   
798   // Here write the auxiliary info                
799   //                                              
800   auxiter = auxmap.find(volumePtr);               
801   if(auxiter != auxmap.cend())                    
802   {                                               
803     AddAuxInfo(&(auxiter->second), volumeEleme    
804   }                                               
805                                                   
806   structureElement->appendChild(volumeElement)    
807   // Append the volume AFTER traversing the ch    
808   // the order of volumes will be correct!        
809                                                   
810   VolumeMap()[tmplv] = R;                         
811                                                   
812   AddExtension(volumeElement, volumePtr);         
813   // Add any possible user defined extension a    
814                                                   
815   AddMaterial(volumePtr->GetMaterial());          
816   // Add the involved materials and solids!       
817                                                   
818   AddSolid(solidPtr);                             
819                                                   
820   SkinSurfaceCache(GetSkinSurface(volumePtr));    
821                                                   
822   return R;                                       
823 }                                                 
824                                                   
825 // -------------------------------------------    
826 void G4GDMLWriteStructure::AddVolumeAuxiliary(    
827                                                   
828 {                                                 
829   auto pos = auxmap.find(lvol);                   
830                                                   
831   if(pos == auxmap.cend())                        
832   {                                               
833     auxmap[lvol] = G4GDMLAuxListType();           
834   }                                               
835                                                   
836   auxmap[lvol].push_back(myaux);                  
837 }                                                 
838                                                   
839 // -------------------------------------------    
840 void G4GDMLWriteStructure::SetEnergyCutsExport    
841 {                                                 
842   cexport = fcuts;                                
843 }                                                 
844                                                   
845 // -------------------------------------------    
846 void G4GDMLWriteStructure::ExportEnergyCuts(co    
847 {                                                 
848   G4GDMLEvaluator eval;                           
849   G4ProductionCuts* pcuts     = lvol->GetRegio    
850   G4ProductionCutsTable* ctab = G4ProductionCu    
851   G4Gamma* gamma              = G4Gamma::Gamma    
852   G4Electron* eminus          = G4Electron::El    
853   G4Positron* eplus           = G4Positron::Po    
854   G4Proton* proton            = G4Proton::Prot    
855                                                   
856   G4double gamma_cut = ctab->ConvertRangeToEne    
857     gamma, lvol->GetMaterial(), pcuts->GetProd    
858   G4double eminus_cut = ctab->ConvertRangeToEn    
859     eminus, lvol->GetMaterial(), pcuts->GetPro    
860   G4double eplus_cut = ctab->ConvertRangeToEne    
861     eplus, lvol->GetMaterial(), pcuts->GetProd    
862   G4double proton_cut = ctab->ConvertRangeToEn    
863     proton, lvol->GetMaterial(), pcuts->GetPro    
864                                                   
865   G4GDMLAuxStructType gammainfo  = { "gammaECu    
866                                     eval.Conve    
867   G4GDMLAuxStructType eminusinfo = { "electron    
868                                      eval.Conv    
869                                      0 };         
870   G4GDMLAuxStructType eplusinfo  = { "positron    
871                                     eval.Conve    
872   G4GDMLAuxStructType protinfo   = { "protonEC    
873                                    eval.Conver    
874                                                   
875   AddVolumeAuxiliary(gammainfo, lvol);            
876   AddVolumeAuxiliary(eminusinfo, lvol);           
877   AddVolumeAuxiliary(eplusinfo, lvol);            
878   AddVolumeAuxiliary(protinfo, lvol);             
879 }                                                 
880                                                   
881 // -------------------------------------------    
882 void G4GDMLWriteStructure::SetSDExport(G4bool     
883 {                                                 
884   sdexport = fsd;                                 
885 }                                                 
886                                                   
887 // -------------------------------------------    
888 void G4GDMLWriteStructure::ExportSD(const G4Lo    
889 {                                                 
890   G4VSensitiveDetector* sd = lvol->GetMasterSe    
891                                                   
892   if(sd != nullptr)                               
893   {                                               
894     G4String SDname = sd->GetName();              
895                                                   
896     G4GDMLAuxStructType SDinfo = { "SensDet",     
897     AddVolumeAuxiliary(SDinfo, lvol);             
898   }                                               
899 }                                                 
900                                                   
901 // -------------------------------------------    
902 G4int G4GDMLWriteStructure::GetMaxExportLevel(    
903 {                                                 
904   return maxLevel;                                
905 }                                                 
906                                                   
907 // -------------------------------------------    
908 void G4GDMLWriteStructure::SetMaxExportLevel(G    
909 {                                                 
910   if(level <= 0)                                  
911   {                                               
912     G4Exception("G4GDMLWriteStructure::Travers    
913                 FatalException, "Levels to exp    
914     return;                                       
915   }                                               
916   maxLevel = level;                               
917   levelNo  = 0;                                   
918 }                                                 
919