-
Marilena Bandieramonte authoredMarilena Bandieramonte authored
Code owners
Assign users and groups as approvers for specific file changes. Learn more.
ExtParameterisedVolumeBuilder.cxx 9.62 KiB
/*
Copyright (C) 2002-2018 CERN for the benefit of the ATLAS collaboration
*/
#include "GeoModel2G4/ExtParameterisedVolumeBuilder.h"
#include "GeoModel2G4/Geo2G4AssemblyFactory.h"
#include "GeoModel2G4/Geo2G4AssemblyVolume.h"
#include "GeoModel2G4/Geo2G4LVFactory.h"
#include "GeoModel2G4/Geo2G4STParameterisation.h"
#include "G4LogicalVolume.hh"
#include "G4PVPlacement.hh"
#include "G4ReflectionFactory.hh"
#include "G4VPVParameterisation.hh"
#include "G4PVParameterised.hh"
#include "globals.hh"
#include "GeoModelKernel/GeoAccessVolAndSTAction.h"
#include "GeoModelKernel/GeoVolumeCursor.h"
#include "GeoModelKernel/GeoMaterial.h"
#include "GeoModelKernel/GeoLogVol.h"
#include "GeoModelKernel/GeoSerialTransformer.h"
#include <iostream>
#include "GeoModel2G4/CLHEPtoEigenConverter.h"
ExtParameterisedVolumeBuilder::ExtParameterisedVolumeBuilder(std::string n):
VolumeBuilder(n),
m_getMatEther(true),
m_matEther(0),m_matHypUr(0)
{
}
G4LogicalVolume* ExtParameterisedVolumeBuilder::Build(const PVConstLink theGeoPhysVolume) const
{
PVConstLink theGeoPhysChild;
const GeoSerialTransformer* serialTransformerChild=0;
G4LogicalVolume* theG4LogChild;
unsigned int numChildNodes; // number of child nodes (PV and ST)
bool descend; // flag to continue geo tree navigation
bool serialExists = false; // flag for existence of ST among childs
std::string nameChild;
if(m_getMatEther) getMatEther();
static Geo2G4LVFactory LVFactory;
//std::cout<<" ----->ExtParameterisedVolumeBuilder::Build()"<<std::endl;
G4LogicalVolume* theG4LogVolume = LVFactory.Build(theGeoPhysVolume,descend);
//std::cout<<" ----->LVFactory built"<<std::endl;
if(!descend) return theG4LogVolume;
numChildNodes = theGeoPhysVolume->getNChildVolAndST();
//std::cout<<" ----->numChildNodes"<<numChildNodes<<std::endl;
// *****************************************************************
// **
// ** If m_ST2Param flag is set:
// ** Check if there's any serial transformer among child volumes
// **
// *****************************************************************
if(m_paramOn)
for(size_t counter1=0; counter1<numChildNodes; counter1++)
{
GeoAccessVolAndSTAction actionVolAndST(counter1);
theGeoPhysVolume->exec(&actionVolAndST);
if((serialTransformerChild=actionVolAndST.getSerialTransformer()))
{
nameChild = actionVolAndST.getName();
serialExists = true;
break;
}
}
//if(G4VERBOSE>1) std::cout<<" -----> Next steps:"<<std::endl;
// ***************************************************************************
// ** Next steps:
// **
// ** 1. If ST exists and numChildNodes==1, translate ST to G4 ST
// **
// ** 2. If ST exists and numChildNodes !=1, print information message and
// ** translate ST to single placements as well as all other child volumes
// **
// ** 3. There's no ST - ok, nothing special ...
// **
// ***************************************************************************
if(serialExists && (numChildNodes==1))
{
theGeoPhysChild = serialTransformerChild->getVolume();
// Build the child
if(!(theG4LogChild = Build(theGeoPhysChild))) return 0;
if (nameChild == "ANON") nameChild=theG4LogChild->GetName();
nameChild += "_Param";
Geo2G4STParameterisation* stParameterisation = new Geo2G4STParameterisation(serialTransformerChild->getFunction(),
serialTransformerChild->getNCopies());
G4VPhysicalVolume* pvParametrised __attribute__ ((unused)) = new G4PVParameterised(nameChild,
theG4LogChild,
theG4LogVolume,
kUndefined,
serialTransformerChild->getNCopies(),
stParameterisation);
}
else
{
if(serialExists)
{
std::string volName = theGeoPhysVolume->getLogVol()->getName();
PrintSTInfo(volName);
}
GeoVolumeCursor av(theGeoPhysVolume);
while (!av.atEnd())
{
int id = 16969;
// Get child phys volume
theGeoPhysChild = av.getVolume();
// Get its transform
G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
Query<int> Qint = av.getId();
if(Qint.isValid()) id = Qint;
if(m_matEther->getName() == theGeoPhysChild->getLogVol()->getMaterial()->getName() )
{
Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
if(Qint.isValid())
assembly->MakeImprint(theG4LogVolume,theG4Position,id);
else
assembly->MakeImprint(theG4LogVolume,theG4Position);
}
else if(m_matHypUr->getName() == theGeoPhysChild->getLogVol()->getMaterial()->getName() )
{
Geo2G4AssemblyVolume* assembly = BuildAssembly(theGeoPhysChild);
if(Qint.isValid())
assembly->MakeImprint(theG4LogVolume,theG4Position,id,true);
else
assembly->MakeImprint(theG4LogVolume,theG4Position,0,true);
}
else
{
nameChild = av.getName();
// Build the child
if(!(theG4LogChild = Build(theGeoPhysChild))) return 0;
if (nameChild == "ANON") nameChild=theG4LogChild->GetName();
//G4PhysicalVolumesPair pvPair =
G4ReflectionFactory::Instance()->Place(theG4Position,nameChild,theG4LogChild,theG4LogVolume,false,id);
//TODO Optical volumes
// if GeoModel volume is optical store it in the map
// if(optical_volumes!=0)
// {
// const GeoOpticalPhysVol* opticalGeoPhysChild =
// dynamic_cast < const GeoOpticalPhysVol* >(theGeoPhysChild.operator->());
// if(opticalGeoPhysChild)
// (*optical_volumes)[opticalGeoPhysChild] = pvPair.first;
// }
}
av.next();
}
}
return theG4LogVolume;
}
Geo2G4AssemblyVolume* ExtParameterisedVolumeBuilder::BuildAssembly(PVConstLink pv) const
{
PVConstLink theGeoPhysChild;
G4LogicalVolume* theG4LogChild = 0;
Geo2G4AssemblyVolume* theG4AssemblyChild = 0;
bool descend; // flag to continue geo tree navigation
if(m_getMatEther) getMatEther();
static Geo2G4AssemblyFactory AssemblyFactory;
Geo2G4AssemblyVolume* assemblyVolume = AssemblyFactory.Build(pv,descend);
if(!descend) return assemblyVolume;
// Loop over child volumes and add them to the Geo2G4AssemblyVolume
GeoVolumeCursor av(pv);
while (!av.atEnd())
{
theGeoPhysChild = av.getVolume();
std::string nameChild = av.getName();
std::string strVolume = std::string("Volume ") + nameChild + " ("
+ theGeoPhysChild->getLogVol()->getName() + ")";
// Check if it is an assembly
if(m_matEther->getName() == theGeoPhysChild->getLogVol()->getMaterial()->getName() ||
m_matHypUr->getName() == theGeoPhysChild->getLogVol()->getMaterial()->getName() )
{
// Build the child assembly
if(!(theG4AssemblyChild = BuildAssembly(theGeoPhysChild))) return 0;
// Get its transform
G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
assemblyVolume->AddPlacedAssembly(theG4AssemblyChild,theG4Position);
}
else
{
Query<int> Qint = av.getId();
// Build the child
if(!(theG4LogChild = Build(theGeoPhysChild))) return 0;
// Get its transform
G4Transform3D theG4Position(Amg::EigenTransformToCLHEP(av.getTransform()));
int placedID = 0;
if(Qint.isValid()) placedID = Qint;
std::string placedName = nameChild=="ANON" ? "" : nameChild;
assemblyVolume->AddPlacedVolume(theG4LogChild,theG4Position,placedID,placedName);
}
av.next();
}
return assemblyVolume;
}
void ExtParameterisedVolumeBuilder::PrintSTInfo(std::string volume) const
{
std::cout<< "**********************************************" << std::endl;
std::cout<< "** " << std::endl;
std::cout<< "** The Volume " << volume << std::endl;
std::cout<< "** Has children of two different types" << std::endl;
std::cout<< "** PeoPhysVolume and GeoSerialTransformer" << std::endl;
std::cout<< "** In this case GeoSerialTransformer will be " << std::endl;
std::cout<< "** translated into G4 placement but not in " << std::endl;
std::cout<< "** G4Parameterisation" << std::endl;
std::cout<< "** " << std::endl;
std::cout<< "********************************************** " << std::endl;
}
void ExtParameterisedVolumeBuilder::getMatEther() const
{
GeoElement* ethElement = new GeoElement("EtherEl","ET",500.0,0.0);
ethElement->ref();
GeoMaterial* ether = new GeoMaterial("Ether",0.0);
ether->add(ethElement,1.);
// "Alternative" assembly material
GeoMaterial* hyperUranium = new GeoMaterial("HyperUranium",0.0);
hyperUranium->add(ethElement,1.);
m_matEther = ether;
m_matHypUr = hyperUranium;
m_getMatEther = false;
}