57 #include "GeoModelKernel/GeoElement.h" 
   58 #include "GeoModelKernel/GeoMaterial.h" 
   59 #include "GeoModelKernel/GeoFullPhysVol.h" 
   60 #include "GeoModelKernel/GeoPhysVol.h" 
   61 #include "GeoModelKernel/GeoVPhysVol.h" 
   62 #include "GeoModelKernel/GeoLogVol.h" 
   63 #include "GeoModelKernel/GeoPcon.h" 
   64 #include "GeoModelKernel/GeoNameTag.h" 
   65 #include "GeoModelKernel/GeoTransform.h" 
   66 #include "GeoModelKernel/GeoIdentifierTag.h" 
   67 #include "GeoModelKernel/GeoDefinitions.h" 
   73 #include "GaudiKernel/IService.h" 
   74 #include "GaudiKernel/ISvcLocator.h" 
   75 #include "GaudiKernel/PhysicalConstants.h" 
   84 #include "GeoModelKernel/GeoUnidentifiedShape.h" 
   91   , m_hasInnerWheel(has_inner)
 
   92   , m_hasOuterWheel(has_outer)
 
   93   , m_innerWheelVariant(
"Wheel")
 
   94   , m_outerWheelVariant(
"Wheel") 
 
  103   ISvcLocator *svcLocator = Gaudi::svcLocator();
 
  104   SmartIF<StoreGateSvc> 
detStore{svcLocator->service(
"DetectorStore")};
 
  106     throw std::runtime_error(
"Error in EndcapCryostatConstruction, cannot access DetectorStore");
 
  110   SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service(
"RDBAccessSvc")};
 
  111   if(!pAccessSvc.isValid()) {
 
  112     throw std::runtime_error(
"EMECConstruction: cannot locate RDBAccessSvc!");
 
  115   SmartIF<IGeoModelSvc> geoModelSvc{svcLocator->service(
"GeoModelSvc")};
 
  116   if(!geoModelSvc.isValid()) {
 
  117     throw std::runtime_error(
"EMECConstruction: cannot locate GeoModelSvc!");
 
  123   int multilayered_absorbers = 0;
 
  124   IRDBRecordset_ptr larSwitches = pAccessSvc->getRecordsetPtr(
"LArSwitches", larVersionKey.
tag(), larVersionKey.
node());
 
  125   if(larSwitches->size()!=0){
 
  126     if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER_EC")){
 
  127       multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER_EC");
 
  128     } 
else if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER")){
 
  129       multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER");
 
  133   if(multilayered_absorbers > 0){
 
  134     ATH_MSG_INFO( 
"multi-layered version of absorbers activated, " 
  135                   << 
"parameter value is " << multilayered_absorbers );
 
  139   if(StatusCode::SUCCESS != 
detStore->retrieve(materialManager, std::string(
"MATERIALS"))) 
return nullptr;
 
  145   const GeoMaterial *
LAr  = materialManager->
getMaterial(
"std::LiquidArgon");
 
  146   if(!
LAr) 
throw std::runtime_error(
"Error in EMECConstruction, std::LiquidArgon is not found.");
 
  148   const GeoMaterial* innerAbsorberMaterial = 
nullptr;
 
  149   std::string innerAbsorberMaterial_name = 
"LAr::EMEC_Thickabs";
 
  150   if(multilayered_absorbers > 0){
 
  151     if(multilayered_absorbers != 2){
 
  153       innerAbsorberMaterial_name = 
"std::Iron";
 
  155       innerAbsorberMaterial_name = 
"LAr::EMEC_shell";
 
  158   innerAbsorberMaterial = materialManager->
getMaterial(innerAbsorberMaterial_name);
 
  159   if(!innerAbsorberMaterial){
 
  160     throw std::runtime_error(
 
  161       (innerAbsorberMaterial_name +
 
  162        " is not found for inner absorber in EMECConstruction.").c_str()
 
  166   const GeoMaterial* outerAbsorberMaterial = 
nullptr;
 
  167   std::string outerAbsorberMaterial_name = 
"LAr::EMEC_Thinabs";
 
  168   if(multilayered_absorbers > 0){
 
  169     if(multilayered_absorbers != 2){
 
  171       outerAbsorberMaterial_name = 
"std::Iron";
 
  173       outerAbsorberMaterial_name = 
"LAr::EMEC_shell";
 
  176   outerAbsorberMaterial = materialManager->
getMaterial(outerAbsorberMaterial_name);
 
  177   if(!outerAbsorberMaterial){
 
  178     throw std::runtime_error(
 
  179       (outerAbsorberMaterial_name +
 
  180        " is not found for outer absorber in EMECConstruction.").c_str()
 
  184   const GeoMaterial *Glue = 
nullptr;
 
  185   const GeoMaterial *Lead = 
nullptr;
 
  186   if(multilayered_absorbers > 0){
 
  189     if(!Glue) 
throw std::runtime_error(
"Error in EMECConstruction, LAr::Glue is not found.");
 
  191     if(!Lead) 
throw std::runtime_error(
"Error in EMECConstruction, LAr::Lead is not found.");
 
  194   const GeoMaterial* electrodeMaterial = materialManager->
getMaterial(
"LAr::KaptonC");
 
  195   if(!electrodeMaterial) 
throw std::runtime_error(
"Error in EMECConstruction, LAr::KaptonC is not found.");
 
  202   std::string baseName = 
"LAr::EMEC";
 
  204   double phiPosition, phiSize;
 
  228     pAccessSvc->getRecordsetPtr(
"CryoPcons", larVersionKey.
tag(), larVersionKey.
node());
 
  229   if(cryoPcons->size() == 0){
 
  230     cryoPcons = pAccessSvc->getRecordsetPtr(
"CryoPcons", 
"CryoPcons-EMEC-00");
 
  240   std::string emecMotherName = baseName + 
"::Mother"; 
 
  242   GeoTransform *refSystemTransform = 
nullptr;
 
  246   GeoPcon* emecMotherShape = 
new GeoPcon(phiPosition - phiSize, 2.*phiSize);  
 
  248     if(currentRecord->getString(
"PCON") == 
"EMEC::Mother"){
 
  249       if(!refSystemTransform){
 
  257         refSystemTransform =  
new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
 
  259       emecMotherShape->addPlane(currentRecord->getDouble(
"ZPLANE") + zMSTrans,
 
  260                                 currentRecord->getDouble(
"RMIN"),
 
  261                                 currentRecord->getDouble(
"RMAX"));
 
  266         pAccessSvc->getRecordsetPtr(
"EmecGeometry", larVersionKey.
tag(), larVersionKey.
node());
 
  267     if(DB_EmecGeometry->size() == 0){
 
  268         DB_EmecGeometry = pAccessSvc->getRecordsetPtr(
"EmecGeometry", 
"EmecGeometry-00");
 
  270     double zWheelRefPoint = (*DB_EmecGeometry)[0]->getDouble(
"Z0")*
Gaudi::Units::cm;
 
  271     double dMechFocaltoWRP=(*DB_EmecGeometry)[0]->getDouble(
"Z1")*
Gaudi::Units::cm;
 
  272     double LArTotalThickness = (*DB_EmecGeometry)[0]->getDouble(
"ETOT") *
Gaudi::Units::cm;
 
  273     double halfGapBetweenWheels = (*DB_EmecGeometry)[0]->getDouble(
"DCRACK")*
Gaudi::Units::cm;
 
  274     double rOuterCutoff = (*DB_EmecGeometry)[0]->getDouble(
"RLIMIT")*
Gaudi::Units::cm;
 
  277       pAccessSvc->getRecordsetPtr(
"EmecMagicNumbers", larVersionKey.
tag(), larVersionKey.
node());
 
  278     if(DB_EMECmn->size() == 0)
 
  279       DB_EMECmn = pAccessSvc->getRecordsetPtr(
"EmecMagicNumbers",
"EMECMagicNumbers-00");
 
  280     double reftoactive = (*DB_EMECmn)[0]->getDouble(
"REFTOACTIVE") *
Gaudi::Units::mm;
 
  281     double activelength = (*DB_EMECmn)[0]->getDouble(
"ACTIVELENGTH") *
Gaudi::Units::mm;
 
  282     double straightstartsection = (*DB_EMECmn)[0]->getDouble(
"STRAIGHTSTARTSECTION")*
Gaudi::Units::mm;
 
  283     double wheelThickness=activelength+2*straightstartsection;
 
  284     double dWRPtoFrontFace = reftoactive;
 
  285     double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace;
 
  286     double zWheelBackFace  = zWheelFrontFace+wheelThickness;
 
  288       pAccessSvc->getRecordsetPtr(
"EmecWheelParameters", larVersionKey.
tag(),larVersionKey.
node());
 
  289     if (DB_EMECwp->size()==0) 
 
  290       DB_EMECwp=pAccessSvc->getRecordsetPtr(
"EmecWheelParameters", 
"EmecWheelParameters",
"EmecWheelParameters-00");
 
  291     int numberOfHalfWavesInner=2*(*DB_EMECwp)[0]->getInt(
"NACC")+2;
 
  292     int numberOfHalfWavesOuter=2*(*DB_EMECwp)[1]->getInt(
"NACC")+3;
 
  293     double eta_hi = (*DB_EMECwp)[0]->getDouble(
"ETAINT");
 
  294     double eta_mid = (*DB_EMECwp)[0]->getDouble(
"ETAEXT");
 
  295     double eta_low = (*DB_EMECwp)[1]->getDouble(
"ETAEXT");
 
  302       double tanThetaMid   = 2. * 
std::exp(-eta_mid) / (1. - 
std::exp(-2.*eta_mid));
 
  303       double tanThetaOuter = 2. * 
std::exp(-eta_low) / (1. - 
std::exp(-2.*eta_low));
 
  304       double tanThetaInner = 2. * 
std::exp(-eta_hi ) / (1. - 
std::exp(-2.*eta_hi ));
 
  305       double inv_tanThetaOuter = (1. - 
std::exp(-2.*eta_low)) / (2. * 
std::exp(-eta_low));
 
  308       rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
 
  309       rMax[0][1] = zWheelBackFace  * tanThetaMid - halfGapBetweenWheels;
 
  311       rMax[1][0] = zWheelFrontFace * tanThetaOuter;
 
  312       rMax[1][1] = rOuterCutoff;
 
  313       rMax[1][2] = rOuterCutoff;
 
  319       rMin[0][0] = zWheelFrontFace * tanThetaInner;
 
  320       rMin[0][1] = zWheelBackFace  * tanThetaInner;
 
  324       rMin[1][0] = zWheelFrontFace * tanThetaMid + halfGapBetweenWheels;
 
  325       rMin[1][1] = rOuterCutoff * inv_tanThetaOuter * tanThetaMid + halfGapBetweenWheels;
 
  326       rMin[1][2] = zWheelBackFace  * tanThetaMid + halfGapBetweenWheels;
 
  327       zMid[1] = rOuterCutoff * inv_tanThetaOuter - zWheelFrontFace;
 
  330     const GeoLogVol* emecMotherLogical =
 
  331         new GeoLogVol(emecMotherName, emecMotherShape, 
LAr);
 
  332     GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical = 
new GeoFullPhysVol(emecMotherLogical);
 
  334     if(!m_isTB) baseName += bPos? 
"::Pos": 
"::Neg";
 
  337         std::string innerName = baseName + 
"::Inner";
 
  338         std::string LArName = innerName + (m_isTB? 
"Module": 
"Wheel");
 
  340         std::vector<std::string> absorbers;
 
  341         std::vector<std::string> electrodes;
 
  343         if(m_innerWheelVariant == 
"Cone"){
 
  345             absorbers.push_back(innerName + 
"::Absorber");
 
  346             electrodes.push_back(innerName + 
"::Electrode");
 
  347         } 
else if(m_innerWheelVariant == 
"Slices"){
 
  348             innerName += 
"Slice";
 
  355                 numberOfHalfWavesInner > 
slice 
  360                                << 
" goes wrong in EMECConstruction" );
 
  364             innerName += (m_isTB? 
"Module": 
"Wheel");
 
  365             absorbers.push_back(innerName + 
"::Absorber");
 
  366             electrodes.push_back(innerName + 
"::Electrode");
 
  370                        << electrodes.size() << 
" electrode shapes created" );
 
  373         double zBack = wheelThickness;
 
  374         GeoPcon* innerShape = 
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
 
  376         innerShape->addPlane(zBack              , rMin[0][1], rMax[0][1]);
 
  378         GeoLogVol*  innerLogical  = 
new GeoLogVol (LArName,innerShape, 
LAr);
 
  379         GeoIntrusivePtr<GeoFullPhysVol> fullPV = 
new GeoFullPhysVol(innerLogical);
 
  381         emecMotherPhysical->add(
new GeoIdentifierTag(1));
 
  382         emecMotherPhysical->add(refSystemTransform);
 
  383         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
 
  384         emecMotherPhysical->add(fullPV);
 
  389             throw std::runtime_error(bPos? 
"Cannot store EMEC_INNER_WHEEL_POS": 
"Cannot store EMEC_INNER_WHEEL_NEG");
 
  392         if (geoModelSvc->isEmecStandard()){
 
  394       ATH_MSG_INFO( 
"EMECConstruction build NewInnerWheel with standard Geant4 shapes: G4GenericTrap ");
 
  399       emecAccordionConstructor.
setMaterial(
"Steel", innerAbsorberMaterial);
 
  400       emecAccordionConstructor.
setMaterial(
"Glue", Glue);
 
  401       emecAccordionConstructor.
setMaterial(
"Lead", Lead);
 
  402       emecAccordionConstructor.
setMaterial(
"Kapton", electrodeMaterial);
 
  406           place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,innerAbsorberMaterial, electrodeMaterial, Glue, Lead);
 
  411         std::string outerName = baseName + 
"::Outer";
 
  412         const std::string LArName = outerName + (m_isTB? 
"Module": 
"Wheel");
 
  414         std::vector<std::string> absorbers;
 
  415         std::vector<std::string> electrodes;
 
  417         if(m_outerWheelVariant == 
"Cone"){
 
  418             absorbers.push_back(outerName + 
"FrontCone::Absorber");
 
  419             absorbers.push_back(outerName + 
"BackCone::Absorber");
 
  420             electrodes.push_back(outerName + 
"FrontCone::Electrode");
 
  421             electrodes.push_back(outerName + 
"BackCone::Electrode");
 
  422             outerName += 
"Cones";
 
  423         } 
else if(m_outerWheelVariant == 
"Slices"){
 
  424             outerName += 
"Slice";
 
  431                 numberOfHalfWavesOuter > 
slice 
  436                               << 
" goes wrong in EMECConstruction" );
 
  440             outerName += (m_isTB? 
"Module": 
"Wheel");
 
  441             absorbers.push_back(outerName + 
"::Absorber");
 
  442             electrodes.push_back(outerName + 
"::Electrode");
 
  446                        << electrodes.size() << 
" electrode shapes created" );
 
  448         double zBack = wheelThickness;
 
  449         GeoPcon *outerShape = 
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
 
  451         outerShape->addPlane(zMid[1]            , rMin[1][1], rMax[1][1]);
 
  452         outerShape->addPlane(zBack              , rMin[1][2], rMax[1][2]);
 
  454         GeoLogVol *outerLogical = 
new GeoLogVol(LArName, outerShape, 
LAr);
 
  455         GeoIntrusivePtr<GeoFullPhysVol>fullPV = 
new GeoFullPhysVol(outerLogical);
 
  457         emecMotherPhysical->add(
new GeoIdentifierTag(1));
 
  458         emecMotherPhysical->add(refSystemTransform);
 
  459         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
 
  460         emecMotherPhysical->add(fullPV);
 
  465             throw std::runtime_error(bPos? 
"Cannot store EMEC_OUTER_WHEEL_POS": 
"Cannot store EMEC_OUTER_WHEEL_NEG");
 
  467         if (geoModelSvc->isEmecStandard()){
 
  469       ATH_MSG_INFO( 
"EMECConstruction build NewOuterWheel with standard Geant4 shapes: G4GenericTrap ");
 
  474       emecAccordionConstructor.
setMaterial(
"Steel", outerAbsorberMaterial);
 
  475       emecAccordionConstructor.
setMaterial(
"Glue", Glue);
 
  476       emecAccordionConstructor.
setMaterial(
"Lead", Lead);
 
  477       emecAccordionConstructor.
setMaterial(
"Kapton", electrodeMaterial);
 
  481            place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,
 
  482             outerAbsorberMaterial, electrodeMaterial, Glue, Lead
 
  499         if(m_hasInnerWheel && !m_hasOuterWheel){
 
  502         } 
else if(m_hasOuterWheel && !m_hasInnerWheel){
 
  508             pAccessSvc->getRecordsetPtr(
"EmecDMPCons", larVersionKey.
tag(), larVersionKey.
node());
 
  509         if(DMpcons->size() == 0){
 
  510             DMpcons = pAccessSvc->getRecordsetPtr(
"EmecDMPCons", 
"EmecDMPCons-00");
 
  517                 const std::string& 
object = dmPcon->getString(
"PCONNAME");
 
  518                 if(
object == 
"FrontSupportMother"){
 
  519                     int zplane = dmPcon->getInt(
"NZPLANE");
 
  521                     else if(zplane == 1) front_shift -= dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
 
  523                 } 
else if(
object == 
"BackSupportMother"){
 
  524                     int zplane = dmPcon->getInt(
"NZPLANE");
 
  525                     if(zplane == 0) back_shift -= 0.;
 
  526                     else if(zplane == 1) back_shift += dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
 
  530             front_shift += reftoactive;
 
  531             back_shift += LArTotalThickness - reftoactive;
 
  536             std::cout << 
"EMECConstruction: WARNING: cannot get front|back_shift from DB" 
  540         z0 = zWheelRefPoint + front_shift;
 
  544         GeoIntrusivePtr<GeoPhysVol> physicalFSM = fsc->
GetEnvelope();
 
  545         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
 
  546         emecMotherPhysical->add(refSystemTransform);
 
  547         emecMotherPhysical->add(physicalFSM);
 
  550         z0 = zWheelRefPoint + back_shift; 
 
  554         GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->
GetEnvelope();
 
  556         if(m_isTB) rotBSM = GeoTrf::RotateZ3D(
M_PI)*rotBSM;
 
  557         emecMotherPhysical->add(refSystemTransform);
 
  558         emecMotherPhysical->add(
new GeoTransform(
GeoTrf::Transform3D(GeoTrf::Translate3D(0., 0., 
z0)*rotBSM)));
 
  559         emecMotherPhysical->add(physicalBSM);
 
  562         z0 = zWheelRefPoint + LArTotalThickness * 0.5; 
 
  566         GeoIntrusivePtr<GeoPhysVol>physicalOSM = 
osc->GetEnvelope();
 
  567         emecMotherPhysical->add(refSystemTransform);
 
  568         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
 
  569         emecMotherPhysical->add(physicalOSM);
 
  572         z0 = zWheelRefPoint + LArTotalThickness * 0.5;
 
  576         GeoIntrusivePtr<GeoPhysVol>physicalISM = isc->
GetEnvelope();
 
  577         emecMotherPhysical->add(refSystemTransform);
 
  578         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
 
  579         emecMotherPhysical->add(physicalISM);
 
  582         z0 = zWheelRefPoint + LArTotalThickness * 0.5;
 
  586         GeoIntrusivePtr<GeoPhysVol>physicalMSM = msc->
GetEnvelope();
 
  587         emecMotherPhysical->add(refSystemTransform);
 
  588         emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
 
  589         emecMotherPhysical->add(physicalMSM);
 
  593     return emecMotherPhysical;
 
  603     GeoIntrusivePtr<GeoFullPhysVol>fullPV,
 
  604     std::vector<std::string> &absorbers,
 
  605     std::vector<std::string> &electrodes,
 
  606     int multilayered_absorbers,
 
  607     const GeoMaterial *Absorber, 
const GeoMaterial *Electrode,
 
  608     const GeoMaterial *Glue, 
const GeoMaterial *Lead
 
  612   for(
const auto& 
name: absorbers){
 
  613     GeoLogVol* log_volume = 
new GeoLogVol(
name, 
new GeoUnidentifiedShape(
"LArCustomShape", 
name) , Absorber);
 
  614     GeoIntrusivePtr<GeoPhysVol> phys_volume = 
new GeoPhysVol(log_volume);
 
  615     fullPV->add(
new GeoIdentifierTag(1));
 
  616     fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
 
  617     fullPV->add(phys_volume);
 
  618     if(multilayered_absorbers > 0){
 
  619       GeoIntrusivePtr<GeoPhysVol> glue_phys = phys_volume;
 
  620       std::string lead_name = 
name;
 
  621       size_t repl = lead_name.find(
"Absorber");
 
  622       if(std::string::npos != repl) lead_name.replace(repl, 8, 
"Lead");
 
  623       else throw std::runtime_error(lead_name + 
": cannot find 'Absorber'");
 
  624       if(multilayered_absorbers != 2){
 
  625     std::string glue_name = 
name;
 
  626     glue_name.replace(repl, 8, 
"Glue");
 
  627     GeoLogVol* glue_log = 
new GeoLogVol(glue_name, 
new GeoUnidentifiedShape(
"LArCustomShape",glue_name), Glue);
 
  628     glue_phys = 
new GeoPhysVol(glue_log);
 
  629     phys_volume->add(
new GeoIdentifierTag(1));
 
  630     phys_volume->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
 
  631     phys_volume->add(glue_phys);
 
  633       GeoLogVol *lead_log = 
new GeoLogVol(lead_name, 
new GeoUnidentifiedShape(
"LArCustomShape",lead_name), Lead);
 
  634       GeoIntrusivePtr<GeoPhysVol>lead_phys  = 
new GeoPhysVol(lead_log);
 
  635       glue_phys->add(
new GeoIdentifierTag(1));
 
  636       glue_phys->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
 
  637       glue_phys->add(lead_phys);
 
  641     for(
const auto& 
name: electrodes){
 
  642       GeoLogVol* log_volume = 
new GeoLogVol(
name, 
new GeoUnidentifiedShape(
"LArCustomShape",
name), Electrode);
 
  643       GeoIntrusivePtr<GeoPhysVol> phys_volume = 
new GeoPhysVol(log_volume);
 
  644       fullPV->add(
new GeoIdentifierTag(1));
 
  645       fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
 
  646       fullPV->add(phys_volume);