Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4GDMLWriteStructure.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4GDMLWriteStructure implementation
27//
28// Author: Zoltan Torzsok, November 2007
29// --------------------------------------------------------------------
30
32#include "G4GDMLEvaluator.hh"
33
34#include "G4Material.hh"
35#include "G4ReflectedSolid.hh"
36#include "G4DisplacedSolid.hh"
40#include "G4PVDivision.hh"
41#include "G4PVReplica.hh"
42#include "G4Region.hh"
43#include "G4OpticalSurface.hh"
46
47#include "G4ProductionCuts.hh"
49#include "G4Gamma.hh"
50#include "G4Electron.hh"
51#include "G4Positron.hh"
52#include "G4Proton.hh"
53
55#include "G4AssemblyStore.hh"
56#include "G4AssemblyVolume.hh"
57
58G4int G4GDMLWriteStructure::levelNo = 0; // Counter for level being exported
59
60// --------------------------------------------------------------------
67
68// --------------------------------------------------------------------
72
73// --------------------------------------------------------------------
75 xercesc::DOMElement* volumeElement, const G4PVDivision* const divisionvol)
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, width, offset, consuming);
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(divisionvol->GetName(), divisionvol);
111 const G4String volumeref =
112 GenerateName(divisionvol->GetLogicalVolume()->GetName(),
113 divisionvol->GetLogicalVolume());
114
115 xercesc::DOMElement* divisionvolElement = NewElement("divisionvol");
116 divisionvolElement->setAttributeNode(NewAttribute("axis", axisString));
117 divisionvolElement->setAttributeNode(NewAttribute("number", number));
118 divisionvolElement->setAttributeNode(NewAttribute("width", width));
119 divisionvolElement->setAttributeNode(NewAttribute("offset", offset));
120 divisionvolElement->setAttributeNode(NewAttribute("unit", unitString));
121 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
122 volumerefElement->setAttributeNode(NewAttribute("ref", volumeref));
123 divisionvolElement->appendChild(volumerefElement);
124 volumeElement->appendChild(divisionvolElement);
125}
126
127// --------------------------------------------------------------------
128void G4GDMLWriteStructure::PhysvolWrite(xercesc::DOMElement* volumeElement,
129 const G4VPhysicalVolume* const physvol,
130 const G4Transform3D& T,
131 const G4String& ModuleName)
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, 1), scale(2, 2));
140 const G4ThreeVector rot = GetAngles(rotate.getRotation());
141 const G4ThreeVector pos = T.getTranslation();
142
143 const G4String name = GenerateName(physvol->GetName(), physvol);
144 const G4int copynumber = physvol->GetCopyNo();
145
146 xercesc::DOMElement* physvolElement = NewElement("physvol");
147 physvolElement->setAttributeNode(NewAttribute("name", name));
148 if(copynumber)
149 {
150 physvolElement->setAttributeNode(NewAttribute("copynumber", copynumber));
151 }
152
153 volumeElement->appendChild(physvolElement);
154
155 G4LogicalVolume* lv;
156 // Is it reflected?
157 if(reflFactory->IsReflected(physvol->GetLogicalVolume()))
158 {
159 lv = reflFactory->GetConstituentLV(physvol->GetLogicalVolume());
160 }
161 else
162 {
163 lv = physvol->GetLogicalVolume();
164 }
165
166 const G4String volumeref = GenerateName(lv->GetName(), lv);
167
168 if(ModuleName.empty())
169 {
170 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
171 volumerefElement->setAttributeNode(NewAttribute("ref", volumeref));
172 physvolElement->appendChild(volumerefElement);
173 }
174 else
175 {
176 xercesc::DOMElement* fileElement = NewElement("file");
177 fileElement->setAttributeNode(NewAttribute("name", ModuleName));
178 fileElement->setAttributeNode(NewAttribute("volname", volumeref));
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", 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", rot);
193 }
194 if(std::fabs(scl.x() - 1.0) > kRelativePrecision ||
195 std::fabs(scl.y() - 1.0) > kRelativePrecision ||
196 std::fabs(scl.z() - 1.0) > kRelativePrecision)
197 {
198 ScaleWrite(physvolElement, name + "_scl", scl);
199 }
200}
201
202// --------------------------------------------------------------------
204 xercesc::DOMElement* volumeElement, const G4VPhysicalVolume* const replicavol)
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, width, offset, consuming);
214
215 const G4String volumeref = GenerateName(
216 replicavol->GetLogicalVolume()->GetName(), replicavol->GetLogicalVolume());
217
218 xercesc::DOMElement* replicavolElement = NewElement("replicavol");
219 replicavolElement->setAttributeNode(NewAttribute("number", number));
220 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
221 volumerefElement->setAttributeNode(NewAttribute("ref", volumeref));
222 replicavolElement->appendChild(volumerefElement);
223 xercesc::DOMElement* replicateElement = NewElement("replicate_along_axis");
224 replicavolElement->appendChild(replicateElement);
225
226 xercesc::DOMElement* dirElement = NewElement("direction");
227 if(axis == kXAxis)
228 {
229 dirElement->setAttributeNode(NewAttribute("x", "1"));
230 }
231 else if(axis == kYAxis)
232 {
233 dirElement->setAttributeNode(NewAttribute("y", "1"));
234 }
235 else if(axis == kZAxis)
236 {
237 dirElement->setAttributeNode(NewAttribute("z", "1"));
238 }
239 else if(axis == kRho)
240 {
241 dirElement->setAttributeNode(NewAttribute("rho", "1"));
242 }
243 else if(axis == kPhi)
244 {
245 dirElement->setAttributeNode(NewAttribute("phi", "1"));
246 unitString = "rad";
247 }
248 replicateElement->appendChild(dirElement);
249
250 xercesc::DOMElement* widthElement = NewElement("width");
251 widthElement->setAttributeNode(NewAttribute("value", width));
252 widthElement->setAttributeNode(NewAttribute("unit", unitString));
253 replicateElement->appendChild(widthElement);
254
255 xercesc::DOMElement* offsetElement = NewElement("offset");
256 offsetElement->setAttributeNode(NewAttribute("value", offset));
257 offsetElement->setAttributeNode(NewAttribute("unit", unitString));
258 replicateElement->appendChild(offsetElement);
259
260 volumeElement->appendChild(replicavolElement);
261}
262
263// --------------------------------------------------------------------
264void G4GDMLWriteStructure::AssemblyWrite(xercesc::DOMElement* volumeElement,
265 const G4int assemblyID)
266{
268 G4AssemblyVolume* myassembly = assemblies->GetAssembly(assemblyID);
269
270 xercesc::DOMElement* assemblyElement = NewElement("assembly");
271 G4String name = "Assembly_" + std::to_string(assemblyID);
272
273 assemblyElement->setAttributeNode(NewAttribute("name", name));
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->TotalTriplets(); ++i5)
281 {
282 G4LogicalVolume* lvol = (*vit).GetVolume();
283 if (lvol == nullptr)
284 {
285 G4String message = "Nested assemblies not yet supported for exporting. Sorry!";
286 G4Exception("G4GDMLWriteStructure::AssemblyWrite()", "InvalidSetup",
287 FatalException, message);
288 return;
289 }
290 TraverseVolumeTree(lvol, depth + 1);
291
292 const G4ThreeVector rot = GetAngles((*vit).GetRotation()->inverse());
293 const G4ThreeVector pos = (*vit).GetTranslation();
294
295 const G4String pname =
296 GenerateName((*vit).GetVolume()->GetName() + "_pv", &(*vit));
297
298 xercesc::DOMElement* physvolElement = NewElement("physvol");
299 physvolElement->setAttributeNode(NewAttribute("name", pname));
300
301 assemblyElement->appendChild(physvolElement);
302
303 const G4String volumeref =
304 GenerateName((*vit).GetVolume()->GetName(), (*vit).GetVolume());
305
306 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
307 volumerefElement->setAttributeNode(NewAttribute("ref", volumeref));
308 physvolElement->appendChild(volumerefElement);
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+"_position_" + std::to_string(i5), pos);
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+"_rotation_" + std::to_string(i5), rot);
322 }
323 ++vit;
324 }
325
326 volumeElement->appendChild(assemblyElement);
327}
328
329// --------------------------------------------------------------------
331 const G4LogicalBorderSurface* const bsurf)
332{
333 if(bsurf == nullptr)
334 {
335 return;
336 }
337
338 const G4SurfaceProperty* psurf = bsurf->GetSurfaceProperty();
339
340 // Generate the new element for border-surface
341 //
342 const G4String& bsname = GenerateName(bsurf->GetName(), bsurf);
343 const G4String& psname = GenerateName(psurf->GetName(), psurf);
344 xercesc::DOMElement* borderElement = NewElement("bordersurface");
345 borderElement->setAttributeNode(NewAttribute("name", bsname));
346 borderElement->setAttributeNode(NewAttribute("surfaceproperty", psname));
347
348 const G4String volumeref1 =
349 GenerateName(bsurf->GetVolume1()->GetName(), bsurf->GetVolume1());
350 const G4String volumeref2 =
351 GenerateName(bsurf->GetVolume2()->GetName(), bsurf->GetVolume2());
352 xercesc::DOMElement* volumerefElement1 = NewElement("physvolref");
353 xercesc::DOMElement* volumerefElement2 = NewElement("physvolref");
354 volumerefElement1->setAttributeNode(NewAttribute("ref", volumeref1));
355 volumerefElement2->setAttributeNode(NewAttribute("ref", volumeref2));
356 borderElement->appendChild(volumerefElement1);
357 borderElement->appendChild(volumerefElement2);
358
359 if(FindOpticalSurface(psurf))
360 {
361 const G4OpticalSurface* opsurf =
362 dynamic_cast<const G4OpticalSurface*>(psurf);
363 if(opsurf == nullptr)
364 {
365 G4Exception("G4GDMLWriteStructure::BorderSurfaceCache()", "InvalidSetup",
366 FatalException, "No optical surface found!");
367 return;
368 }
370 }
371
372 borderElementVec.push_back(borderElement);
373}
374
375// --------------------------------------------------------------------
377 const G4LogicalSkinSurface* const ssurf)
378{
379 if(ssurf == nullptr)
380 {
381 return;
382 }
383
384 const G4SurfaceProperty* psurf = ssurf->GetSurfaceProperty();
385
386 // Generate the new element for border-surface
387 //
388 const G4String& ssname = GenerateName(ssurf->GetName(), ssurf);
389 const G4String& psname = GenerateName(psurf->GetName(), psurf);
390 xercesc::DOMElement* skinElement = NewElement("skinsurface");
391 skinElement->setAttributeNode(NewAttribute("name", ssname));
392 skinElement->setAttributeNode(NewAttribute("surfaceproperty", psname));
393
394 const G4String volumeref = GenerateName(ssurf->GetLogicalVolume()->GetName(),
395 ssurf->GetLogicalVolume());
396 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
397 volumerefElement->setAttributeNode(NewAttribute("ref", volumeref));
398 skinElement->appendChild(volumerefElement);
399
400 if(FindOpticalSurface(psurf))
401 {
402 const G4OpticalSurface* opsurf =
403 dynamic_cast<const G4OpticalSurface*>(psurf);
404 if(opsurf == nullptr)
405 {
406 G4Exception("G4GDMLWriteStructure::SkinSurfaceCache()", "InvalidSetup",
407 FatalException, "No optical surface found!");
408 return;
409 }
411 }
412
413 skinElementVec.push_back(skinElement);
414}
415
416// --------------------------------------------------------------------
418{
419 const G4OpticalSurface* osurf = dynamic_cast<const G4OpticalSurface*>(psurf);
420 auto pos = std::find(opt_vec.cbegin(), opt_vec.cend(), osurf);
421 if(pos != opt_vec.cend())
422 {
423 return false;
424 } // item already created!
425
426 opt_vec.push_back(osurf); // cache it for future reference
427 return true;
428}
429
430// --------------------------------------------------------------------
432 const G4LogicalVolume* const lvol)
433{
434 G4LogicalSkinSurface* surf = nullptr;
436 if(nsurf)
437 {
438 const G4LogicalSkinSurfaceTable* stable =
440 auto pos = stable->find(lvol);
441 if(pos != stable->cend())
442 {
443 surf = pos->second;
444 }
445 }
446 return surf;
447}
448
449// --------------------------------------------------------------------
451 const G4VPhysicalVolume* const pvol)
452{
453 G4LogicalBorderSurface* surf = nullptr;
455 if(nsurf)
456 {
457 const G4LogicalBorderSurfaceTable* btable =
459 for(auto pos = btable->cbegin(); pos != btable->cend(); ++pos)
460 {
461 if(pvol == pos->first.first) // just the first in the couple
462 { // could be enough?
463 surf = pos->second; // break;
464 BorderSurfaceCache(surf);
465 }
466 }
467 }
468 return surf;
469}
470
471// --------------------------------------------------------------------
473{
474#ifdef G4VERBOSE
475 G4cout << "G4GDML: Writing surfaces..." << G4endl;
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(); ++pos)
484 {
485 structureElement->appendChild(*pos);
486 }
487}
488
489// --------------------------------------------------------------------
490void G4GDMLWriteStructure::StructureWrite(xercesc::DOMElement* gdmlElement)
491{
492#ifdef G4VERBOSE
493 G4cout << "G4GDML: Writing structure..." << G4endl;
494#endif
495
496 // filling the list of phys volumes that are parts of assemblies
497
499
500 for(auto it = assemblies->cbegin(); it != assemblies->cend(); ++it)
501 {
502 auto vit = (*it)->GetVolumesIterator();
503
504 for(std::size_t i5 = 0; i5 < (*it)->TotalImprintedVolumes(); ++i5)
505 {
506 G4String pvname = (*vit)->GetName();
507 std::size_t pos = pvname.find("_impr_") + 6;
508 G4String impID = pvname.substr(pos);
509
510 pos = impID.find("_");
511 impID = impID.substr(0, pos);
512
513 assemblyVolMap[*vit] = (*it)->GetAssemblyID();
514 imprintsMap[*vit] = std::atoi(impID.c_str());
515 ++vit;
516 }
517 }
518
519 structureElement = NewElement("structure");
520 gdmlElement->appendChild(structureElement);
521}
522
523// --------------------------------------------------------------------
525 const G4LogicalVolume* const volumePtr, const G4int depth)
526{
527 if(VolumeMap().find(volumePtr) != VolumeMap().cend())
528 {
529 return VolumeMap()[volumePtr]; // Volume is already processed
530 }
531
532 G4VSolid* solidPtr = volumePtr->GetSolid();
533 G4Transform3D R, invR;
534 G4int trans = 0;
535
536 std::map<const G4LogicalVolume*, G4GDMLAuxListType>::iterator auxiter;
537
538 ++levelNo;
539
540 while(true) // Solve possible displacement/reflection
541 { // of the referenced solid!
542 if(trans > maxTransforms)
543 {
544 G4String ErrorMessage = "Referenced solid in volume '" +
545 volumePtr->GetName() +
546 "' was displaced/reflected too many times!";
547 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()", "InvalidSetup",
548 FatalException, ErrorMessage);
549 }
550
551 if(G4ReflectedSolid* refl = dynamic_cast<G4ReflectedSolid*>(solidPtr))
552 {
553 R = R * refl->GetTransform3D();
554 solidPtr = refl->GetConstituentMovedSolid();
555 ++trans;
556 continue;
557 }
558
559 if(G4DisplacedSolid* disp = dynamic_cast<G4DisplacedSolid*>(solidPtr))
560 {
561 R = R * G4Transform3D(disp->GetObjectRotation(),
562 disp->GetObjectTranslation());
563 solidPtr = disp->GetConstituentMovedSolid();
564 ++trans;
565 continue;
566 }
567
568 break;
569 }
570
571 // check if it is a reflected volume
572 G4LogicalVolume* tmplv = const_cast<G4LogicalVolume*>(volumePtr);
573
574 if(reflFactory->IsReflected(tmplv))
575 {
576 tmplv = reflFactory->GetConstituentLV(tmplv);
577 if(VolumeMap().find(tmplv) != VolumeMap().cend())
578 {
579 return R; // Volume is already processed
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->GetName(), tmplv);
591
592 G4String materialref = "NULL";
593
594 if(volumePtr->GetMaterial())
595 {
596 materialref = GenerateName(volumePtr->GetMaterial()->GetName(),
597 volumePtr->GetMaterial());
598 }
599
600 const G4String solidref = GenerateName(solidPtr->GetName(), solidPtr);
601
602 xercesc::DOMElement* volumeElement = NewElement("volume");
603 volumeElement->setAttributeNode(NewAttribute("name", name));
604 xercesc::DOMElement* materialrefElement = NewElement("materialref");
605 materialrefElement->setAttributeNode(NewAttribute("ref", materialref));
606 volumeElement->appendChild(materialrefElement);
607 xercesc::DOMElement* solidrefElement = NewElement("solidref");
608 solidrefElement->setAttributeNode(NewAttribute("ref", solidref));
609 volumeElement->appendChild(solidrefElement);
610
611 std::size_t daughterCount = volumePtr->GetNoDaughters();
612
613 if(levelNo == maxLevel) // Stop exporting if reached levels limit
614 {
615 daughterCount = 0;
616 }
617
618 std::map<G4int, std::vector<G4int> > assemblyIDToAddedImprints;
619
620 for(std::size_t i = 0; i < daughterCount; ++i) // Traverse all the children!
621 {
622 const G4VPhysicalVolume* const physvol = volumePtr->GetDaughter(i);
623 const G4String ModuleName = Modularize(physvol, depth);
624
625 G4Transform3D daughterR;
626
627 if(ModuleName.empty()) // Check if subtree requested to be
628 { // a separate module!
629 daughterR = TraverseVolumeTree(physvol->GetLogicalVolume(), depth + 1);
630 }
631 else
632 {
634 daughterR = writer.Write(ModuleName, physvol->GetLogicalVolume(),
635 SchemaLocation, depth + 1);
636 }
637
638 if(const G4PVDivision* const divisionvol =
639 dynamic_cast<const G4PVDivision*>(physvol)) // Is it division?
640 {
641 if(!G4Transform3D::Identity.isNear(invR * daughterR, kRelativePrecision))
642 {
643 G4String ErrorMessage = "Division volume in '" + name +
644 "' can not be related to reflected solid!";
645 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
646 "InvalidSetup", FatalException, ErrorMessage);
647 }
648 DivisionvolWrite(volumeElement, divisionvol);
649 }
650 else
651 {
652 if(physvol->IsParameterised()) // Is it a paramvol?
653 {
654 if(!G4Transform3D::Identity.isNear(invR * daughterR,
656 {
657 G4String ErrorMessage = "Parameterised volume in '" + name +
658 "' can not be related to reflected solid!";
659 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
660 "InvalidSetup", FatalException, ErrorMessage);
661 }
662 ParamvolWrite(volumeElement, physvol);
663 }
664 else
665 {
666 if(physvol->IsReplicated()) // Is it a replicavol?
667 {
668 if(!G4Transform3D::Identity.isNear(invR * daughterR,
670 {
671 G4String ErrorMessage = "Replica volume in '" + name +
672 "' can not be related to reflected solid!";
673 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()",
674 "InvalidSetup", FatalException, ErrorMessage);
675 }
676 ReplicavolWrite(volumeElement, physvol);
677 }
678 else // Is it a physvol or an assembly?
679 {
680 if(assemblyVolMap.find(physvol) != assemblyVolMap.cend())
681 {
682 G4int assemblyID = assemblyVolMap[physvol];
683
684 G4String assemblyref = "Assembly_" + std::to_string(assemblyID);
685
686 // here I need to retrieve the imprint ID
687
688 G4int imprintID = imprintsMap[physvol];
689
690 // there are 2 steps:
691 //
692 // 1) add assembly to the structure if that has not yet been done
693 // (but after the constituents volumes have been added)
694 //
695
696 if(std::find(addedAssemblies.cbegin(), addedAssemblies.cend(),
697 assemblyID) == addedAssemblies.cend())
698 {
699 AssemblyWrite(structureElement, assemblyID);
700 addedAssemblies.push_back(assemblyID);
701 assemblyIDToAddedImprints[assemblyID] = std::vector<G4int>();
702 }
703
704 // 2) add the assembly (as physical volume) to the mother volume
705 // (but only once), using it's original position and rotation.
706 //
707
708 // here I need a check if assembly has been already added to the
709 // mother volume
710 std::vector<G4int>& addedImprints = assemblyIDToAddedImprints[assemblyID];
711 if(std::find(addedImprints.cbegin(), addedImprints.cend(),
712 imprintID) == addedImprints.cend())
713 {
714 G4String imprintname = "Imprint_" + std::to_string(imprintID) + "_";
715 imprintname = GenerateName(imprintname, physvol);
716
717 // I need to get those two from the container of imprints from
718 // the assembly I have the imprint ID, I need to get pos and rot
719 //
721 ->GetAssembly(assemblyID)
722 ->GetImprintTransformation(imprintID);
723
724 HepGeom::Scale3D scale;
725 HepGeom::Rotate3D rotate;
726 HepGeom::Translate3D translate;
727
728 transf.getDecomposition(scale, rotate, translate);
729
730 const G4ThreeVector scl(scale(0, 0), scale(1, 1), scale(2, 2));
731 const G4ThreeVector rot = GetAngles(rotate.getRotation().inverse());
732 const G4ThreeVector pos = transf.getTranslation();
733
734 // here I need a normal physvol referencing to my assemblyref
735
736 xercesc::DOMElement* physvolElement = NewElement("physvol");
737 physvolElement->setAttributeNode(NewAttribute("name", imprintname));
738
739 xercesc::DOMElement* volumerefElement = NewElement("volumeref");
740 volumerefElement->setAttributeNode(NewAttribute("ref", assemblyref));
741 physvolElement->appendChild(volumerefElement);
742
743 if(std::fabs(pos.x()) > kLinearPrecision ||
744 std::fabs(pos.y()) > kLinearPrecision ||
745 std::fabs(pos.z()) > kLinearPrecision)
746 {
747 PositionWrite(physvolElement, imprintname + "_pos", pos);
748 }
749 if(std::fabs(rot.x()) > kAngularPrecision ||
750 std::fabs(rot.y()) > kAngularPrecision ||
751 std::fabs(rot.z()) > kAngularPrecision)
752 {
753 RotationWrite(physvolElement, imprintname + "_rot", rot);
754 }
755 if(std::fabs(scl.x() - 1.0) > kRelativePrecision ||
756 std::fabs(scl.y() - 1.0) > kRelativePrecision ||
757 std::fabs(scl.z() - 1.0) > kRelativePrecision)
758 {
759 ScaleWrite(physvolElement, name + "_scl", scl);
760 }
761
762 volumeElement->appendChild(physvolElement);
763 //
764 addedImprints.push_back(imprintID);
765 }
766 }
767 else // not part of assembly, so a normal physical volume
768 {
770 if(physvol->GetFrameRotation() != nullptr)
771 {
772 rot = *(physvol->GetFrameRotation());
773 }
774 G4Transform3D P(rot, physvol->GetObjectTranslation());
775
776 PhysvolWrite(volumeElement, physvol, invR * P * daughterR,
777 ModuleName);
778 }
779 }
780 }
781 }
782 // BorderSurfaceCache(GetBorderSurface(physvol));
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), volumeElement);
804 }
805
806 structureElement->appendChild(volumeElement);
807 // Append the volume AFTER traversing the children so that
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 attached to a volume
814
815 AddMaterial(volumePtr->GetMaterial());
816 // Add the involved materials and solids!
817
818 AddSolid(solidPtr);
819
821
822 return R;
823}
824
825// --------------------------------------------------------------------
827 const G4LogicalVolume* const lvol)
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// --------------------------------------------------------------------
841{
842 cexport = fcuts;
843}
844
845// --------------------------------------------------------------------
847{
848 G4GDMLEvaluator eval;
849 G4ProductionCuts* pcuts = lvol->GetRegion()->GetProductionCuts();
851 G4Gamma* gamma = G4Gamma::Gamma();
854 G4Proton* proton = G4Proton::Proton();
855
856 G4double gamma_cut = ctab->ConvertRangeToEnergy(
857 gamma, lvol->GetMaterial(), pcuts->GetProductionCut("gamma"));
858 G4double eminus_cut = ctab->ConvertRangeToEnergy(
859 eminus, lvol->GetMaterial(), pcuts->GetProductionCut("e-"));
860 G4double eplus_cut = ctab->ConvertRangeToEnergy(
861 eplus, lvol->GetMaterial(), pcuts->GetProductionCut("e+"));
862 G4double proton_cut = ctab->ConvertRangeToEnergy(
863 proton, lvol->GetMaterial(), pcuts->GetProductionCut("proton"));
864
865 G4GDMLAuxStructType gammainfo = { "gammaECut",
866 eval.ConvertToString(gamma_cut), "MeV", 0 };
867 G4GDMLAuxStructType eminusinfo = { "electronECut",
868 eval.ConvertToString(eminus_cut), "MeV",
869 0 };
870 G4GDMLAuxStructType eplusinfo = { "positronECut",
871 eval.ConvertToString(eplus_cut), "MeV", 0 };
872 G4GDMLAuxStructType protinfo = { "protonECut",
873 eval.ConvertToString(proton_cut), "MeV", 0 };
874
875 AddVolumeAuxiliary(gammainfo, lvol);
876 AddVolumeAuxiliary(eminusinfo, lvol);
877 AddVolumeAuxiliary(eplusinfo, lvol);
878 AddVolumeAuxiliary(protinfo, lvol);
879}
880
881// --------------------------------------------------------------------
883{
884 sdexport = fsd;
885}
886
887// --------------------------------------------------------------------
889{
891
892 if(sd != nullptr)
893 {
894 G4String SDname = sd->GetName();
895
896 G4GDMLAuxStructType SDinfo = { "SensDet", SDname, "", 0 };
897 AddVolumeAuxiliary(SDinfo, lvol);
898 }
899}
900
901// --------------------------------------------------------------------
903{
904 return maxLevel;
905}
906
907// --------------------------------------------------------------------
909{
910 if(level <= 0)
911 {
912 G4Exception("G4GDMLWriteStructure::TraverseVolumeTree()", "InvalidSetup",
913 FatalException, "Levels to export must be greater than zero!");
914 return;
915 }
916 maxLevel = level;
917 levelNo = 0;
918}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
std::vector< G4GDMLAuxStructType > G4GDMLAuxListType
std::map< std::pair< const G4VPhysicalVolume *, const G4VPhysicalVolume * >, G4LogicalBorderSurface * > G4LogicalBorderSurfaceTable
std::map< const G4LogicalVolume *, G4LogicalSkinSurface * > G4LogicalSkinSurfaceTable
HepGeom::Transform3D G4Transform3D
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
double x() const
double y() const
HepRotation inverse() const
static G4AssemblyStore * GetInstance()
G4AssemblyVolume * GetAssembly(unsigned int id, G4bool verbose=true) const
G4Transform3D & GetImprintTransformation(unsigned int imprintID)
std::vector< G4AssemblyTriplet >::iterator GetTripletsIterator()
std::size_t TotalTriplets() const
static G4Electron * Electron()
Definition G4Electron.cc:91
G4String ConvertToString(G4int ival)
static const G4double kLinearPrecision
void RotationWrite(xercesc::DOMElement *element, const G4String &name, const G4ThreeVector &rot)
static const G4double kAngularPrecision
void PositionWrite(xercesc::DOMElement *element, const G4String &name, const G4ThreeVector &pos)
G4ThreeVector GetAngles(const G4RotationMatrix &)
void ScaleWrite(xercesc::DOMElement *element, const G4String &name, const G4ThreeVector &scl)
static const G4double kRelativePrecision
void AddMaterial(const G4Material *const)
virtual void ParamvolWrite(xercesc::DOMElement *, const G4VPhysicalVolume *const)
virtual void AddSolid(const G4VSolid *const)
xercesc::DOMElement * solidsElement
static const G4int maxTransforms
void OpticalSurfaceWrite(xercesc::DOMElement *, const G4OpticalSurface *const)
const G4LogicalBorderSurface * GetBorderSurface(const G4VPhysicalVolume *const)
void BorderSurfaceCache(const G4LogicalBorderSurface *const)
std::vector< xercesc::DOMElement * > borderElementVec
std::map< const G4LogicalVolume *, G4GDMLAuxListType > auxmap
void AssemblyWrite(xercesc::DOMElement *, const int assemblyID)
std::vector< xercesc::DOMElement * > skinElementVec
void SkinSurfaceCache(const G4LogicalSkinSurface *const)
const G4LogicalSkinSurface * GetSkinSurface(const G4LogicalVolume *const)
void PhysvolWrite(xercesc::DOMElement *, const G4VPhysicalVolume *const topVol, const G4Transform3D &transform, const G4String &moduleName)
void ExportEnergyCuts(const G4LogicalVolume *const)
virtual void StructureWrite(xercesc::DOMElement *)
G4Transform3D TraverseVolumeTree(const G4LogicalVolume *const topVol, const G4int depth)
xercesc::DOMElement * structureElement
void ExportSD(const G4LogicalVolume *const)
void DivisionvolWrite(xercesc::DOMElement *, const G4PVDivision *const)
G4bool FindOpticalSurface(const G4SurfaceProperty *)
void AddVolumeAuxiliary(G4GDMLAuxStructType myaux, const G4LogicalVolume *const)
void ReplicavolWrite(xercesc::DOMElement *, const G4VPhysicalVolume *const)
xercesc::DOMElement * NewElement(const G4String &)
G4String GenerateName(const G4String &, const void *const)
G4String SchemaLocation
G4String Modularize(const G4VPhysicalVolume *const topvol, const G4int depth)
virtual void AddExtension(xercesc::DOMElement *, const G4LogicalVolume *const)
G4Transform3D Write(const G4String &filename, const G4LogicalVolume *const topLog, const G4String &schemaPath, const G4int depth, G4bool storeReferences=true)
xercesc::DOMAttr * NewAttribute(const G4String &, const G4String &)
void AddAuxInfo(G4GDMLAuxListType *auxInfoList, xercesc::DOMElement *element)
VolumeMapType & VolumeMap()
static G4Gamma * Gamma()
Definition G4Gamma.cc:81
static std::size_t GetNumberOfBorderSurfaces()
static const G4LogicalBorderSurfaceTable * GetSurfaceTable()
const G4VPhysicalVolume * GetVolume2() const
const G4VPhysicalVolume * GetVolume1() const
const G4LogicalVolume * GetLogicalVolume() const
static const G4LogicalSkinSurfaceTable * GetSurfaceTable()
static std::size_t GetNumberOfSkinSurfaces()
const G4String & GetName() const
G4SurfaceProperty * GetSurfaceProperty() const
G4VSolid * GetSolid() const
G4VSensitiveDetector * GetMasterSensitiveDetector() const
std::size_t GetNoDaughters() const
G4Region * GetRegion() const
G4Material * GetMaterial() const
G4VPhysicalVolume * GetDaughter(const std::size_t i) const
const G4String & GetName() const
const G4String & GetName() const
void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const override
EAxis GetDivisionAxis() const
static G4Positron * Positron()
Definition G4Positron.cc:90
static G4ProductionCutsTable * GetProductionCutsTable()
G4double ConvertRangeToEnergy(const G4ParticleDefinition *particle, const G4Material *material, G4double range)
G4double GetProductionCut(G4int index) const
static G4Proton * Proton()
Definition G4Proton.cc:90
G4bool IsReflected(G4LogicalVolume *lv) const
static G4ReflectionFactory * Instance()
G4LogicalVolume * GetConstituentLV(G4LogicalVolume *reflLV) const
G4ProductionCuts * GetProductionCuts() const
const G4String & GetName() const
virtual G4bool IsReplicated() const =0
G4LogicalVolume * GetLogicalVolume() const
const G4RotationMatrix * GetFrameRotation() const
virtual void GetReplicationData(EAxis &axis, G4int &nReplicas, G4double &width, G4double &offset, G4bool &consuming) const =0
virtual G4int GetCopyNo() const =0
const G4String & GetName() const
G4ThreeVector GetObjectTranslation() const
virtual G4bool IsParameterised() const =0
G4String GetName() const
static DLL_API const Transform3D Identity
CLHEP::HepRotation getRotation() const
void getDecomposition(Scale3D &scale, Rotate3D &rotation, Translate3D &translation) const
CLHEP::Hep3Vector getTranslation() const
Transform3D inverse() const
EAxis
Definition geomdefs.hh:54
@ kPhi
Definition geomdefs.hh:60
@ kYAxis
Definition geomdefs.hh:56
@ kXAxis
Definition geomdefs.hh:55
@ kZAxis
Definition geomdefs.hh:57
@ kUndefined
Definition geomdefs.hh:61
@ kRho
Definition geomdefs.hh:58
#define INT_MAX
Definition templates.hh:90