Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/persistency/gdml/src/G4GDMLRead.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 // G4GDMLRead implementation
 27 //
 28 // Author: Zoltan Torzsok, November 2007
 29 // --------------------------------------------------------------------
 30 
 31 #include "globals.hh"
 32 
 33 #include "G4GDMLRead.hh"
 34 
 35 #include "G4UnitsTable.hh"
 36 #include "G4Element.hh"
 37 #include "G4Material.hh"
 38 #include "G4SolidStore.hh"
 39 #include "G4LogicalVolumeStore.hh"
 40 #include "G4PhysicalVolumeStore.hh"
 41 #include "G4EnvironmentUtils.hh"
 42 #include "G4Exception.hh"
 43 
 44 // --------------------------------------------------------------------
 45 G4GDMLRead::G4GDMLRead()
 46 {
 47   // Make sure units are defined.
 48   G4UnitDefinition::GetUnitsTable();
 49 }
 50 
 51 // --------------------------------------------------------------------
 52 G4GDMLRead::~G4GDMLRead()
 53 {
 54 }
 55 
 56 // --------------------------------------------------------------------
 57 G4String G4GDMLRead::Transcode(const XMLCh* const toTranscode)
 58 {
 59   char* char_str = xercesc::XMLString::transcode(toTranscode);
 60   G4String my_str(char_str);
 61   xercesc::XMLString::release(&char_str);
 62   return my_str;
 63 }
 64 
 65 // --------------------------------------------------------------------
 66 void G4GDMLRead::OverlapCheck(G4bool flag)
 67 {
 68   check = flag;
 69 }
 70 
 71 // --------------------------------------------------------------------
 72 G4String G4GDMLRead::GenerateName(const G4String& nameIn, G4bool strip)
 73 {
 74   G4String nameOut(nameIn);
 75 
 76   if(inLoop > 0)
 77   {
 78     nameOut = eval.SolveBrackets(nameOut);
 79   }
 80   if(strip)
 81   {
 82     StripName(nameOut);
 83   }
 84 
 85   return nameOut;
 86 }
 87 
 88 // --------------------------------------------------------------------
 89 void G4GDMLRead::GeneratePhysvolName(const G4String& nameIn,
 90                                      G4VPhysicalVolume* physvol)
 91 {
 92   G4String nameOut(nameIn);
 93 
 94   if(nameIn.empty())
 95   {
 96     std::stringstream stream;
 97     stream << physvol->GetLogicalVolume()->GetName() << "_PV";
 98     nameOut = stream.str();
 99   }
100   nameOut = eval.SolveBrackets(nameOut);
101 
102   physvol->SetName(nameOut);
103 }
104 
105 // --------------------------------------------------------------------
106 G4String G4GDMLRead::Strip(const G4String& name) const
107 {
108   G4String sname(name);
109   StripName(sname);
110   return sname;
111 }
112 
113 // --------------------------------------------------------------------
114 void G4GDMLRead::StripName(G4String& name) const
115 {
116   auto idx = name.find("0x");
117   if(idx != G4String::npos)
118   {
119     name.erase(idx);
120   }
121 }
122 
123 // --------------------------------------------------------------------
124 void G4GDMLRead::StripNames() const
125 {
126   // Strips off names of volumes, solids elements and materials from possible
127   // reference pointers or IDs attached to their original identifiers.
128 
129   G4PhysicalVolumeStore* pvols     = G4PhysicalVolumeStore::GetInstance();
130   G4LogicalVolumeStore* lvols      = G4LogicalVolumeStore::GetInstance();
131   G4SolidStore* solids             = G4SolidStore::GetInstance();
132   const G4ElementTable* elements   = G4Element::GetElementTable();
133   const G4MaterialTable* materials = G4Material::GetMaterialTable();
134 
135   G4cout << "Stripping off GDML names of materials, solids and volumes ..."
136          << G4endl;
137 
138   G4String sname;
139   std::size_t i;
140 
141   // Solids...
142   //
143   for(i = 0; i < solids->size(); ++i)
144   {
145     G4VSolid* psol = (*solids)[i];
146     sname          = psol->GetName();
147     StripName(sname);
148     psol->SetName(sname);
149   }
150   solids->UpdateMap();
151 
152   // Logical volumes...
153   //
154   for(i = 0; i < lvols->size(); ++i)
155   {
156     G4LogicalVolume* lvol = (*lvols)[i];
157     sname                 = lvol->GetName();
158     StripName(sname);
159     lvol->SetName(sname);
160   }
161   lvols->UpdateMap();
162 
163   // Physical volumes...
164   //
165   for(i = 0; i < pvols->size(); ++i)
166   {
167     G4VPhysicalVolume* pvol = (*pvols)[i];
168     sname                   = pvol->GetName();
169     StripName(sname);
170     pvol->SetName(sname);
171   }
172   pvols->UpdateMap();
173 
174   // Materials...
175   //
176   for(i = 0; i < materials->size(); ++i)
177   {
178     G4Material* pmat = (*materials)[i];
179     sname            = pmat->GetName();
180     StripName(sname);
181     pmat->SetName(sname);
182   }
183 
184   // Elements...
185   //
186   for(i = 0; i < elements->size(); ++i)
187   {
188     G4Element* pelm = (*elements)[i];
189     sname           = pelm->GetName();
190     StripName(sname);
191     pelm->SetName(sname);
192   }
193 }
194 
195 // --------------------------------------------------------------------
196 void G4GDMLRead::LoopRead( const xercesc::DOMElement* const element,
197   void (G4GDMLRead::*func)(const xercesc::DOMElement* const))
198 {
199   G4String var;
200   G4String from;
201   G4String to;
202   G4String step;
203 
204   const xercesc::DOMNamedNodeMap* const attributes = element->getAttributes();
205   XMLSize_t attributeCount                         = attributes->getLength();
206 
207   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
208       ++attribute_index)
209   {
210     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
211 
212     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
213     {
214       continue;
215     }
216 
217     const xercesc::DOMAttr* const attribute =
218       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
219     if(!attribute)
220     {
221       G4Exception("G4GDMLRead::LoopRead()", "InvalidRead", FatalException,
222                   "No attribute found!");
223       return;
224     }
225     const G4String attribute_name  = Transcode(attribute->getName());
226     const G4String attribute_value = Transcode(attribute->getValue());
227 
228     if(attribute_name == "for")
229     {
230       var = attribute_value;
231     }
232     else if(attribute_name == "from")
233     {
234       from = attribute_value;
235     }
236     else if(attribute_name == "to")
237     {
238       to = attribute_value;
239     }
240     else if(attribute_name == "step")
241     {
242       step = attribute_value;
243     }
244   }
245 
246   if(var.empty())
247   {
248     G4Exception("G4GDMLRead::loopRead()", "InvalidRead", FatalException,
249                 "No variable is determined for loop!");
250   }
251 
252   if(!eval.IsVariable(var))
253   {
254     G4Exception("G4GDMLRead::loopRead()", "InvalidRead", FatalException,
255                 "Variable is not defined in loop!");
256   }
257 
258   G4int _var  = eval.EvaluateInteger(var);
259   G4int _from = eval.EvaluateInteger(from);
260   G4int _to   = eval.EvaluateInteger(to);
261   G4int _step = eval.EvaluateInteger(step);
262 
263   if(!from.empty())
264   {
265     _var = _from;
266   }
267 
268   if((_from < _to) && (_step <= 0))
269   {
270     G4Exception("G4GDMLRead::loopRead()", "InvalidRead", FatalException,
271                 "Infinite loop!");
272   }
273   if((_from > _to) && (_step >= 0))
274   {
275     G4Exception("G4GDMLRead::loopRead()", "InvalidRead", FatalException,
276                 "Infinite loop!");
277   }
278 
279   ++inLoop;
280 
281   while(_var <= _to)
282   {
283     eval.SetVariable(var, _var);
284     (this->*func)(element);
285     _var += _step;
286     ++loopCount;
287   }
288 
289   --inLoop;
290   if(!inLoop)
291   {
292     loopCount = 0;
293   }
294 }
295 
296 // --------------------------------------------------------------------
297 G4GDMLAuxStructType G4GDMLRead::AuxiliaryRead(
298   const xercesc::DOMElement* const auxiliaryElement)
299 {
300   G4GDMLAuxStructType auxstruct = { "", "", "", 0 };
301   G4GDMLAuxListType* auxList    = nullptr;
302 
303   const xercesc::DOMNamedNodeMap* const attributes =
304     auxiliaryElement->getAttributes();
305   XMLSize_t attributeCount = attributes->getLength();
306 
307   for(XMLSize_t attribute_index = 0; attribute_index < attributeCount;
308       ++attribute_index)
309   {
310     xercesc::DOMNode* attribute_node = attributes->item(attribute_index);
311 
312     if(attribute_node->getNodeType() != xercesc::DOMNode::ATTRIBUTE_NODE)
313     {
314       continue;
315     }
316 
317     const xercesc::DOMAttr* const attribute =
318       dynamic_cast<xercesc::DOMAttr*>(attribute_node);
319     if(!attribute)
320     {
321       G4Exception("G4GDMLRead::AuxiliaryRead()", "InvalidRead", FatalException,
322                   "No attribute found!");
323       return auxstruct;
324     }
325     const G4String attName  = Transcode(attribute->getName());
326     const G4String attValue = Transcode(attribute->getValue());
327 
328     if(attName == "auxtype")
329     {
330       auxstruct.type = attValue;
331     }
332     else if(attName == "auxvalue")
333     {
334       auxstruct.value = attValue;
335     }
336     else if(attName == "auxunit")
337     {
338       auxstruct.unit = attValue;
339     }
340   }
341 
342   for(xercesc::DOMNode* iter = auxiliaryElement->getFirstChild();
343                         iter != nullptr; iter = iter->getNextSibling())
344   {
345     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
346     {
347       continue;
348     }
349 
350     const xercesc::DOMElement* const child =
351       dynamic_cast<xercesc::DOMElement*>(iter);
352     if(!child)
353     {
354       G4Exception("G4GDMLRead::AuxiliaryRead()", "InvalidRead", FatalException,
355                   "No child found!");
356       break;
357     }
358     const G4String tag = Transcode(child->getTagName());
359 
360     if(tag == "auxiliary")
361     {
362       if(!auxList)
363       {
364         auxList = new G4GDMLAuxListType;
365       }
366       auxList->push_back(AuxiliaryRead(child));
367     }
368   }
369 
370   if(auxList)
371   {
372     auxstruct.auxList = auxList;
373   }
374 
375   return auxstruct;
376 }
377 
378 // --------------------------------------------------------------------
379 void G4GDMLRead::UserinfoRead(const xercesc::DOMElement* const userinfoElement)
380 {
381 #ifdef G4VERBOSE
382   G4cout << "G4GDML: Reading userinfo..." << G4endl;
383 #endif
384   for(xercesc::DOMNode* iter = userinfoElement->getFirstChild();
385                         iter != nullptr; iter = iter->getNextSibling())
386   {
387     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
388     {
389       continue;
390     }
391 
392     const xercesc::DOMElement* const child =
393       dynamic_cast<xercesc::DOMElement*>(iter);
394     if(!child)
395     {
396       G4Exception("G4GDMLRead::UserinfoRead()", "InvalidRead", FatalException,
397                   "No child found!");
398       return;
399     }
400     const G4String tag = Transcode(child->getTagName());
401 
402     if(tag == "auxiliary")
403     {
404       auxGlobalList.push_back(AuxiliaryRead(child));
405     }
406     else
407     {
408       G4String error_msg = "Unknown tag in structure: " + tag;
409       G4Exception("G4GDMLRead::UserinfoRead()", "ReadError", FatalException,
410                   error_msg);
411     }
412   }
413 }
414 
415 // --------------------------------------------------------------------
416 void G4GDMLRead::ExtensionRead(const xercesc::DOMElement* const)
417 {
418   G4String error_msg = "No handle to user-code for parsing extensions!";
419   G4Exception("G4GDMLRead::ExtensionRead()", "NotImplemented", JustWarning,
420               error_msg);
421 }
422 
423 // --------------------------------------------------------------------
424 const G4String& G4GDMLRead::GetSchemaFile() const
425 {
426   return schema;
427 }
428 
429 // --------------------------------------------------------------------
430 void G4GDMLRead::SetSchemaFile(const G4String& schemaFile)
431 {
432   schema = schemaFile;
433 }
434 
435 // --------------------------------------------------------------------
436 void G4GDMLRead::Read(const G4String& fileName, G4bool validation,
437                       G4bool isModule, G4bool strip)
438 {
439   dostrip = strip;
440 #ifdef G4VERBOSE
441   if(isModule)
442   {
443     G4cout << "G4GDML: Reading module '" << fileName << "'..." << G4endl;
444   }
445   else
446   {
447     G4cout << "G4GDML: Reading '" << fileName << "'..." << G4endl;
448   }
449 #endif
450   inLoop   = 0;
451   validate = validation;
452 
453   xercesc::ErrorHandler* handler   = new G4GDMLErrorHandler(!validate);
454   xercesc::XercesDOMParser* parser = new xercesc::XercesDOMParser;
455 
456   if(validate)
457   {
458     parser->setValidationScheme(xercesc::XercesDOMParser::Val_Always);
459    
460     // Load alternative schema path if specified by user in
461     // 1. environment variable, or
462     // 2. `schema` data member, or
463     // Will fall back to default validation otherwise (`xsi:noNamespaceSchemaLocation` in input file)
464     if(auto schemaPath = G4GetEnv<G4String>("G4GDML_SCHEMA_FILE", schema); schemaPath != "")
465     {
466       // Pre-parse grammar to check it's present/valid
467       if(parser->loadGrammar(schemaPath.c_str(), xercesc::Grammar::SchemaGrammarType, true) != nullptr)
468       {
469         G4cout << "G4GDML: Loaded alternative schema URI: " << schemaPath << G4endl;
470       }
471       else 
472       {
473         G4Exception("G4GDMLRead::Read()",
474                     "InvalidGDMLSchemaFile",
475                     FatalException,
476                     G4String("Failed to load/parse schema file '" + schemaPath + "'").c_str());
477       }
478       parser->useCachedGrammarInParse(true);
479       // If the schema has been set manually then we want to ignore path set in input file, if any
480       parser->setExternalNoNamespaceSchemaLocation(schemaPath.c_str());
481     }
482   }
483   parser->setValidationSchemaFullChecking(validate);
484   parser->setCreateEntityReferenceNodes(false);
485   // Entities will be automatically resolved by Xerces
486 
487   parser->setDoNamespaces(true);
488   parser->setDoSchema(validate);
489   parser->setErrorHandler(handler);
490 
491   try
492   {
493     parser->parse(fileName.c_str());
494   } catch(const xercesc::XMLException& e)
495   {
496     G4cout << "G4GDML: " << Transcode(e.getMessage()) << G4endl;
497   } catch(const xercesc::DOMException& e)
498   {
499     G4cout << "G4GDML: " << Transcode(e.getMessage()) << G4endl;
500   }
501 
502   xercesc::DOMDocument* doc = parser->getDocument();
503 
504   if(doc == nullptr)
505   {
506     G4String error_msg = "Unable to open document: " + fileName;
507     G4Exception("G4GDMLRead::Read()", "InvalidRead", FatalException, error_msg);
508     return;
509   }
510   xercesc::DOMElement* element = doc->getDocumentElement();
511 
512   if(element == nullptr )
513   {
514     std::ostringstream message;
515     message << "ERROR - Empty document or unable to validate schema!" << G4endl
516             << "        Check Internet connection is ON in case of schema"
517             << G4endl
518             << "        validation enabled and location defined as URL in"
519             << G4endl << "        the GDML file - " << fileName
520             << " - being imported!" << G4endl
521             << "        Otherwise, verify GDML schema server is reachable!";
522     G4Exception("G4GDMLRead::Read()", "InvalidRead", FatalException, message);
523     return;
524   }
525 
526   for(xercesc::DOMNode* iter = element->getFirstChild(); iter != nullptr;
527       iter                   = iter->getNextSibling())
528   {
529     if(iter->getNodeType() != xercesc::DOMNode::ELEMENT_NODE)
530     {
531       continue;
532     }
533 
534     const xercesc::DOMElement* const child =
535       dynamic_cast<xercesc::DOMElement*>(iter);
536     if(child == nullptr)
537     {
538       G4Exception("G4GDMLRead::Read()", "InvalidRead", FatalException,
539                   "No child found!");
540       return;
541     }
542     const G4String tag = Transcode(child->getTagName());
543 
544     if(tag == "define")
545     {
546       DefineRead(child);
547     }
548     else if(tag == "materials")
549     {
550       MaterialsRead(child);
551     }
552     else if(tag == "solids")
553     {
554       SolidsRead(child);
555     }
556     else if(tag == "setup")
557     {
558       SetupRead(child);
559     }
560     else if(tag == "structure")
561     {
562       StructureRead(child);
563     }
564     else if(tag == "userinfo")
565     {
566       UserinfoRead(child);
567     }
568     else if(tag == "extension")
569     {
570       ExtensionRead(child);
571     }
572     else
573     {
574       G4String error_msg = "Unknown tag in gdml: " + tag;
575       G4Exception("G4GDMLRead::Read()", "InvalidRead", FatalException,
576                   error_msg);
577     }
578   }
579 
580   delete parser;
581   delete handler;
582 
583   if(isModule)
584   {
585 #ifdef G4VERBOSE
586     G4cout << "G4GDML: Reading module '" << fileName << "' done!" << G4endl;
587 #endif
588   }
589   else
590   {
591     G4cout << "G4GDML: Reading '" << fileName << "' done!" << G4endl;
592     if(strip)
593     {
594       StripNames();
595     }
596   }
597 }
598 
599 // --------------------------------------------------------------------
600 const G4GDMLAuxListType* G4GDMLRead::GetAuxList() const
601 {
602   return &auxGlobalList;
603 }
604