Files
geant4/source/persistency/geometry/management/src/G4PersistentGeomMan.cc
T
2016-06-08 16:03:00 +02:00

607 lines
20 KiB
C++

// This code implementation is the intellectual property of
// the GEANT4 collaboration.
//
// By copying, distributing or modifying the Program (or any work
// based on the Program) you indicate your acceptance of this statement,
// and all its terms.
//
// $Id: G4PersistentGeomMan.cc,v 1.14 2000/06/09 12:56:44 morita Exp $
// GEANT4 tag $Name: geant4-03-01 $
//
// class G4PersistentGeomMan
//
// Implementation for concrete G4PersistentGeomMan.
//
// History:
// 98.10.30 Y.Morita Splited from G4PersistencyManager
#include <assert.h>
#include "G4PersistentGeomMan.hh"
// include files for forward declarations
#include "HepODBMS/clustering/HepDbApplication.h"
#include "G4VSolid.hh"
#include "G4VPhysicalVolume.hh"
#include "G4LogicalVolume.hh"
#include "G4PVPhysicalVolume.hh"
#include "G4PLogicalVolume.hh"
#include "G4PVSolid.hh"
#include "G4PGeometryObjectMap.hh"
// other used classes
#include "G4PBox.hh"
#include "G4PCons.hh"
#include "G4PPara.hh"
#include "G4PSphere.hh"
#include "G4PTorus.hh"
#include "G4PTrap.hh"
#include "G4PTrd.hh"
#include "G4PTubs.hh"
//#include "G4PEllipticalTube.hh"
#include "G4PHype.hh"
//#include "G4PPolycone.hh"
//#include "G4PPolyhedra.hh"
#include "G4PDisplacedSolid.hh"
#include "G4PIntersectionSolid.hh"
#include "G4PSubtractionSolid.hh"
#include "G4PUnionSolid.hh"
#include "G4BooleanSolid.hh"
#include "G4DisplacedSolid.hh"
#include "G4PPVPlacement.hh"
#include "G4PPVReplica.hh"
#include "G4PPVParameterised.hh"
#include "G4ios.hh"
G4PersistentGeomMan::G4PersistentGeomMan()
: f_GeomMap(NULL), f_GeomMapScopeName("Geant4 Geometry Object Map")
{;}
G4PersistentGeomMan::~G4PersistentGeomMan()
{;}
//----------------------------------------------------------------------------
G4bool G4PersistentGeomMan::Store( HepDbApplication* dbApp,
const G4VPhysicalVolume* theWorld)
{
void* aWorld = (void*) theWorld;
const G4String theGeometryName = "Geant4 geometry";
// clear the recursive call counter
f_nRecursive = 0;
f_tRecursive = 0;
// ----------------------- Objectivity Feature ----------------------- //
// Look for the geometry object map in the database and create it
// if it does not exist
if ( ! f_GeomMap.lookupObj( f_DB, f_GeomMapScopeName, oocUpdate ) )
{
// Prepare lookup table for the geometry object tree
f_GeomMap =
new(f_container) G4PGeometryObjectMap( theGeometryName );
// Add ScopeName to f_GeomMap for future reference (*Objy feature)
if ( ! f_GeomMap.nameObj( f_DB, f_GeomMapScopeName ) )
{
G4cerr << "G4PersistentGeomMan::Store"
<< " -- error in naming the geometry object map: "
<< f_GeomMapScopeName << G4endl;
return false;
}
}
else
{
G4cerr << "G4PersistentGeomMan: Geometry alreday stored in the"
<< "geometry database." << G4endl
<< " Geometry not stored." << G4endl;
return false;
}
// ----------------------- Objectivity Feature ----------------------- //
// make the persistent world volume object from "theWorld"
HepRef(G4PVPhysicalVolume) persWorld =
MakePersistentObject( (G4VPhysicalVolume*)aWorld );
if ( persWorld != NULL )
{
// set the persistent World Volume to f_GeomMap
f_GeomMap->SetWorldVolume( persWorld );
return true;
}
else
{
G4cerr << "G4PersistentGeomMan: Error in storing geometry." << G4endl;
return false;
}
}
G4bool G4PersistentGeomMan::Retrieve( HepDbApplication* dbApp,
G4VPhysicalVolume*& theWorld)
{
theWorld = NULL;
G4VMaterialMap* f_Materialmap = G4VMaterialMap::GetMaterialMap();
if(f_verboseLevel>0)
{
if(!f_MaterialMap)
G4cout << "G4PersistentGeomMan::Retrieve"
<< " -- Material Map not provided by user code." << G4endl;
}
// ----------------------- Objectivity Feature ----------------------- //
// Load the geometry object map from the database with read-only mode
if ( ! f_GeomMap.lookupObj( f_DB, f_GeomMapScopeName, oocRead ) )
{
G4cerr << "G4PersistentGeomMan::Retrieve"
<< " -- error in looking up the geometry object map: "
<< f_GeomMapScopeName << G4endl;
return false;
}
// ----------------------- Objectivity Feature ----------------------- //
if ( f_GeomMap == NULL )
{
G4cerr << "G4PersistentGeomMan::Retrieve()"
<< " -- error in searching the geometry object map: "
<< f_GeomMapScopeName << G4endl;
return false;
}
if(f_verboseLevel>2)
G4cout << "G4PersistentGeomMan::Retrieve()"
<< " -- f_GeomMap is loaded." << G4endl;
// initialize the transient part of the geometry object map
f_GeomMap->InitTransientMap();
if(f_verboseLevel>2)
G4cout << "G4PersistentGeomMan::Retrieve(G4VPhysicalVolume*)"
<< " -- f_GeomMap is initialized." << G4endl;
// loop through the number of solids in the database
G4int nSolids = f_GeomMap->GetNoSolids();
for(G4int i=0;i<nSolids;i++)
{
// load persistent solid object from DB
HepRef(G4PVSolid) persSolid = f_GeomMap->GetPSolid(i);
// make transient version of G4VSolid from the persistent solid
G4VSolid* theSolid = MakeTransientObject(persSolid);
}
if(f_verboseLevel>2)
G4cout << "G4PersistentGeomMan::Retrieve(G4VPhysicalVolume*)"
<< " -- Transient Solid is created for nSolids:"
<< nSolids << G4endl;
// Locate the persistent world physics volume
HepRef(G4PVPhysicalVolume) persWorld = f_GeomMap->GetWorldVolume();
if ( persWorld == NULL )
{
G4cerr << "G4PersistentGeomMan::Retrieve"
<< " -- geometry object map does not have world volume."
<< G4endl;
return false;
}
// start the recursive data member copy
// to create the transient geometry object tree
HepRef(G4PVPhysicalVolume) persMother = NULL;
theWorld = MakeTransientObject( persWorld, persMother );
if ( theWorld == NULL )
{
G4cerr << "G4PersistentGeomMan::Retrieve"
<< " -- transient world volume is empty."
<< G4endl;
return false;
}
return true;
}
//----------------------------------------------------------------------------
HepRef(G4PVPhysicalVolume) G4PersistentGeomMan::MakePersistentObject (
G4VPhysicalVolume* thePhysVol )
{
// check the depth of the recursive call to this method
if ( ++f_nRecursive > G4_PHYS_VOLUME_DEPTH_MAX )
{
G4cerr << "G4PersistentGeomMan::MakePersistentObject" <<
" -- Physical Volume recursive depth reached to G4_PHYS_VOLUME_DEPTH_MAX."
<< G4endl;
return NULL;
}
if( f_verboseLevel>2 && f_nRecursive % 1000 == 0 )
G4cout << "G4PersistentGeomMan: "
<< "Physical Volume recursive depth is "
<< f_nRecursive << G4endl;
// check if the persistent version of thePhysVol exists
HepRef(G4PVPhysicalVolume) persPhysVol = f_GeomMap->LookUp(thePhysVol);
if ( persPhysVol == NULL )
{
// Get the Logical Volume in thePhysVol
G4LogicalVolume* theLogVol = thePhysVol->GetLogicalVolume();
// make the persistent logical volume object from "theLogVol"
HepRef(G4PLogicalVolume) persLogVol =
MakePersistentObject( theLogVol );
#ifdef G4DEBUG
assert( persLogVol != NULL );
#endif
// Construct the persistent version of thePhysVol for each type of volume
switch (VolumeType(thePhysVol))
{
case kNormal:
persPhysVol = new(f_container)
G4PPVPlacement( thePhysVol, persLogVol);
break;
case kReplica:
persPhysVol = new(f_container)
G4PPVReplica( thePhysVol, persLogVol);
break;
case kParameterised:
persPhysVol = new(f_container)
G4PPVReplica( thePhysVol, persLogVol);
// G4PPVParameterized( thePhysVol, persLogVol);
break;
}
#ifdef G4DEBUG
assert( persPhysVol != NULL );
#endif
// register persPhysVol to the geometry object lookup table
f_GeomMap->Add( thePhysVol, persPhysVol );
} // end of if f_GeomMap->LookUp(thePhysVol)
return persPhysVol;
}
HepRef(G4PLogicalVolume) G4PersistentGeomMan::MakePersistentObject (
G4LogicalVolume* theLogVol )
{
// check if the persistent version of theLogVol exists
HepRef(G4PLogicalVolume) persLogVol = f_GeomMap->LookUp(theLogVol);
if ( persLogVol == NULL )
{
// get the solid of the transient logical volume
G4VSolid* theSolid = theLogVol->GetSolid();
// make the persistent solid object from "theSolid"
HepRef(G4PVSolid) persSolid = MakePersistentObject(theSolid);
// Construct the persistent version of theLogVol
persLogVol = new(f_container) G4PLogicalVolume(theLogVol, persSolid);
#ifdef G4DEBUG
assert( persLogVol != NULL );
#endif
// register persLogVol to the geometry object lookup table
f_GeomMap->Add( theLogVol, persLogVol );
// loop through the daughter physical volumes in theLogVol
G4int nDaughters = theLogVol->GetNoDaughters();
for(G4int i=0;i<nDaughters;i++)
{
// Get the i-th daughter physics volume
G4VPhysicalVolume* dPhysVol = theLogVol->GetDaughter(i);
// make the persistent physics volume object from "dPhysVol"
HepRef(G4PVPhysicalVolume) persDaughterPhysVol =
MakePersistentObject( dPhysVol );
// add persistent daughter volume to the persistent logical volume
if ( persDaughterPhysVol != NULL )
persLogVol->AddDaughter( persDaughterPhysVol );
} // end of for(G4int i=0;i<nDaughters;i++)
} // end of if f_GeomMap->LookUp(theLogVol)
return persLogVol;
}
HepRef(G4PVSolid) G4PersistentGeomMan::MakePersistentObject (
G4VSolid* theSolid )
{
// check if the persistent version of theSolid exists
HepRef(G4PVSolid) persSolid = f_GeomMap->LookUp(theSolid);
if ( persSolid == NULL )
{
G4GeometryType theSolidType = theSolid->GetEntityType();
if(f_verboseLevel>3)
G4cout << "G4PersistentGeomMan::MakePersistentObject (G4VSolid) "
<< "-- theSolidType is " << theSolidType << G4endl;
// Construct persistent and concrete solid object
// according to the entity type of theSolid
// Pure CSG
if ( theSolidType == "G4Box")
persSolid = new(f_container) G4PBox ( (G4Box*)theSolid );
else if ( theSolidType == "G4Cons")
persSolid = new(f_container) G4PCons ( (G4Cons*)theSolid );
else if ( theSolidType == "G4Para")
persSolid = new(f_container) G4PPara ( (G4Para*)theSolid );
else if ( theSolidType == "G4Sphere")
persSolid = new(f_container) G4PSphere( (G4Sphere*)theSolid );
else if ( theSolidType == "G4Torus")
persSolid = new(f_container) G4PTorus ( (G4Torus*)theSolid );
else if ( theSolidType == "G4Trap")
persSolid = new(f_container) G4PTrap ( (G4Trap*)theSolid );
else if ( theSolidType == "G4Trd")
persSolid = new(f_container) G4PTrd ( (G4Trd*)theSolid );
else if ( theSolidType == "G4Tubs")
persSolid = new(f_container) G4PTubs ( (G4Tubs*)theSolid );
// Specific CSG
// else if ( theSolidType == "G4EllipticalTube")
// persSolid = new(f_container) G4PEllipticalTube
// ( (G4EllipticalTube*)theSolid );
else if ( theSolidType == "G4Hype")
persSolid = new(f_container) G4PHype
( (G4Hype*)theSolid );
// else if ( theSolidType == "G4Polycone")
// persSolid = new(f_container) G4PPolycone
// ( (G4Polycone*)theSolid );
// else if ( theSolidType == "G4Polyhedra")
// persSolid = new(f_container) G4PPolyhedra
// ( (G4Polyhedra*)theSolid );
// Boolian Solids
else if ( theSolidType == "G4UnionSolid" ||
theSolidType == "G4SubtractionSolid" ||
theSolidType == "G4IntersectionSolid" )
{
// This is Boolean solid, so get the constituent solids
G4BooleanSolid* boolSolid = (G4BooleanSolid*) theSolid;
G4VSolid* aSolidA = boolSolid->GetConstituentSolid(0);
G4VSolid* aSolidB = boolSolid->GetConstituentSolid(1);
#ifdef G4DEBUG
assert(aSolidA!=NULL);
assert(aSolidB!=NULL);
#endif
HepRef(G4PVSolid) persSolidA = MakePersistentObject(aSolidA);
HepRef(G4PVSolid) persSolidB = MakePersistentObject(aSolidB);
const G4String solidName = theSolid->GetName();
// Create persistent boolean solid according to its type
if ( theSolidType == "G4UnionSolid")
{
persSolid = new(f_container)
G4PUnionSolid( solidName, persSolidA, persSolidB);
}
else if ( theSolidType == "G4SubtractionSolid")
{
persSolid = new(f_container)
G4PSubtractionSolid( solidName, persSolidA, persSolidB);
}
else if ( theSolidType == "G4IntersectionSolid")
{
persSolid = new(f_container)
G4PIntersectionSolid( solidName, persSolidA, persSolidB);
}
}
else if ( theSolidType == "G4DisplacedSolid")
{
// This is a displaced solid, so get the constituent solid and transform
G4DisplacedSolid* dispSolid = (G4DisplacedSolid*) theSolid;
G4VSolid* movedSolid = dispSolid->GetConstituentMovedSolid();
#ifdef G4DEBUG
assert(movedSolid!=NULL);
#endif
HepRef(G4PVSolid) persMovedSolid = MakePersistentObject(movedSolid);
HepRef(G4PAffineTransform) pTransform = new(f_container)
G4PAffineTransform( dispSolid->GetDirectTransform() );
persSolid = new(f_container)
G4PDisplacedSolid( persMovedSolid, pTransform );
}
#ifdef G4DEBUG
else
{
G4cerr << " Warning (G4PersistentGeomMan): The solid type ("
<< theSolidType << ") is not supported yet." << G4endl;
}
#endif
// register persSolid to the geometry object lookup table
if ( persSolid != NULL )
f_GeomMap->Add( theSolid, persSolid );
} // end of if f_GeomMap->LookUp(theSolid)
return persSolid;
}
//----------------------------------------------------------------------------
G4VPhysicalVolume* G4PersistentGeomMan::MakeTransientObject (
HepRef(G4PVPhysicalVolume) persPhysVol,
HepRef(G4PVPhysicalVolume) persMotherVol )
{
// check the depth of the recursive call to this method
if ( ++f_tRecursive > G4_PHYS_VOLUME_DEPTH_MAX )
{
G4cerr << "G4PersistentGeomMan::MakeTransientObject" <<
" -- Physical Volume recursive depth reached to G4_PHYS_VOLUME_DEPTH_MAX."
<< G4endl;
return NULL;
}
if( f_verboseLevel>2 && f_tRecursive % 1000 == 0 )
G4cout << "G4PersistentGeomMan: "
<< "Physical Volume recursive depth is "
<< f_tRecursive << G4endl;
// check if the transient version of persPhysVol exists
G4VPhysicalVolume* thePhysVol = f_GeomMap->LookUp(persPhysVol);
if ( thePhysVol == NULL )
{
// Get the Logical Volume in persPhysVol
HepRef(G4PLogicalVolume) persLogVol = persPhysVol->GetLogicalVolume();
// make the transient logical volume object from "persPhysVol"
G4LogicalVolume* theLogVol =
MakeTransientObject( persLogVol, persPhysVol );
#ifdef G4DEBUG
assert( theLogVol != NULL );
#endif
// Construct the transient version of persPhysVol
G4VPhysicalVolume*
thePhysVol = persPhysVol->MakeTransientObject(
theLogVol, f_GeomMap->LookUp(persMotherVol) );
#ifdef G4DEBUG
assert( thePhysVol != NULL );
#endif
// register thePhysVol to the geometry object lookup table
f_GeomMap->Add( persPhysVol, thePhysVol );
} // end of if f_GeomMap->LookUp(persPhysVol)
return thePhysVol;
}
G4LogicalVolume* G4PersistentGeomMan::MakeTransientObject (
HepRef(G4PLogicalVolume) persLogVol,
HepRef(G4PVPhysicalVolume) persMotherVol )
{
// check if the transient version of persLogVol exists
G4LogicalVolume* theLogVol = f_GeomMap->LookUp(persLogVol);
if ( theLogVol == NULL )
{
// get the solid of the persistent logical volume
HepRef(G4PVSolid) persSolid = persLogVol->GetSolid();
#ifdef G4DEBUG
assert( persSolid != NULL );
#endif
// check if the transient version of persSolid exists
G4VSolid* theSolid = f_GeomMap->LookUp(persSolid);
#ifdef G4DEBUG
if ( theSolid == NULL )
{
G4cerr << "G4PersistentGeomMan::MakeTransientObject" <<
" -- transient Solid not found for the persistent Solid" << G4endl;
}
#endif
// Lookup the material from name
G4Material* theMaterial = NULL;
if( f_MaterialMap )
{
theMaterial = f_MaterialMap->LookUp(persLogVol->GetMaterialName());
}
// Construct the persistent version of theLogVol with theSolid
theLogVol = persLogVol->MakeTransientObject(theSolid, theMaterial);
#ifdef G4DEBUG
assert( theLogVol != NULL );
#endif
// register theLogVol to the geometry object lookup table
f_GeomMap->Add( persLogVol, theLogVol );
// loop through the daughter physical volumes in persLogVol
G4int nDaughters = persLogVol->GetNoDaughters();
for(G4int i=0;i<nDaughters;i++)
{
// Get the i-th daughter physics volume
HepRef(G4PVPhysicalVolume) persDaughterPhysVol
= persLogVol->GetDaughter(i);
// make the transient physics volume object from "persDaughterPhysVol"
G4VPhysicalVolume* theDaughterPhysVol =
MakeTransientObject( persDaughterPhysVol, persMotherVol );
// add transient daughter volume to the transient logical volume
if ( theDaughterPhysVol != NULL )
theLogVol->AddDaughter( theDaughterPhysVol );
} // end of for(G4int i=0;i<nDaughters;i++)
} // end of if f_GeomMap->LookUp(persLogVol)
return theLogVol;
}
G4VSolid* G4PersistentGeomMan::MakeTransientObject (
HepRef(G4PVSolid) persSolid )
{
// check if the persistent version of theSolid exists
G4VSolid* transSolid = f_GeomMap->LookUp(persSolid);
if ( transSolid == NULL )
{
G4GeometryType theSolidType = persSolid->GetEntityType();
// Construct transient and concrete solid object
// according to the entity type of theSolid
if ( theSolidType == "G4UnionSolid" ||
theSolidType == "G4SubtractionSolid" ||
theSolidType == "G4IntersectionSolid" )
{
// This is Boolean solid, so get the constituent solids
HepRef(G4PBooleanSolid) boolSolid = (HepRef(G4PBooleanSolid)) persSolid;
HepRef(G4PVSolid) aSolidA = boolSolid->GetConstituentSolid(0);
HepRef(G4PVSolid) aSolidB = boolSolid->GetConstituentSolid(1);
#ifdef G4DEBUG
assert(aSolidA!=NULL);
assert(aSolidB!=NULL);
#endif
G4VSolid* transSolidA = MakeTransientObject(aSolidA);
G4VSolid* transSolidB = MakeTransientObject(aSolidB);
transSolid = boolSolid->MakeTransientBooleanSolid
(transSolidA, transSolidB);
}
else if ( theSolidType == "G4DisplacedSolid")
{
// This is a displaced solid, so get the constituent solid and
// its transform
HepRef(G4PDisplacedSolid) dispSolid =
(HepRef(G4PDisplacedSolid)) persSolid;
HepRef(G4PVSolid) movedSolid = dispSolid->GetConstituentMovedSolid();
#ifdef G4DEBUG
assert(movedSolid!=NULL);
#endif
G4VSolid* transMovedSolid = MakeTransientObject(movedSolid);
transSolid = dispSolid->MakeTransientDisplacedSolid( transMovedSolid );
}
else
{
// This is a simple solid
transSolid = persSolid->MakeTransientObject();
}
#ifdef G4DEBUG
assert( transSolid != NULL );
#endif
f_GeomMap->Add( persSolid, transSolid );
}
return transSolid;
}
//----------------------------------------------------------------------------