56 #include "GeoModelKernel/GeoElement.h"
57 #include "GeoModelKernel/GeoMaterial.h"
58 #include "GeoModelKernel/GeoFullPhysVol.h"
59 #include "GeoModelKernel/GeoPhysVol.h"
60 #include "GeoModelKernel/GeoVPhysVol.h"
61 #include "GeoModelKernel/GeoLogVol.h"
62 #include "GeoModelKernel/GeoPcon.h"
63 #include "GeoModelKernel/GeoNameTag.h"
64 #include "GeoModelKernel/GeoTransform.h"
65 #include "GeoModelKernel/GeoIdentifierTag.h"
66 #include "GeoModelKernel/GeoDefinitions.h"
72 #include "GaudiKernel/IService.h"
73 #include "GaudiKernel/ISvcLocator.h"
74 #include "GaudiKernel/PhysicalConstants.h"
83 #include "GeoModelKernel/GeoUnidentifiedShape.h"
90 , m_hasInnerWheel(has_inner)
91 , m_hasOuterWheel(has_outer)
92 , m_innerWheelVariant(
"Wheel")
93 , m_outerWheelVariant(
"Wheel")
102 ISvcLocator *svcLocator = Gaudi::svcLocator();
103 SmartIF<StoreGateSvc>
detStore{svcLocator->service(
"DetectorStore")};
105 throw std::runtime_error(
"Error in EndcapCryostatConstruction, cannot access DetectorStore");
109 SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service(
"RDBAccessSvc")};
110 if(!pAccessSvc.isValid()) {
111 throw std::runtime_error(
"EMECConstruction: cannot locate RDBAccessSvc!");
114 SmartIF<IGeoModelSvc> geoModelSvc{svcLocator->service(
"GeoModelSvc")};
115 if(!geoModelSvc.isValid()) {
116 throw std::runtime_error(
"EMECConstruction: cannot locate GeoModelSvc!");
122 int multilayered_absorbers = 0;
123 IRDBRecordset_ptr larSwitches = pAccessSvc->getRecordsetPtr(
"LArSwitches", larVersionKey.
tag(), larVersionKey.
node());
124 if(larSwitches->size()!=0){
125 if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER_EC")){
126 multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER_EC");
127 }
else if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER")){
128 multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER");
132 if(multilayered_absorbers > 0){
133 ATH_MSG_INFO(
"multi-layered version of absorbers activated, "
134 <<
"parameter value is " << multilayered_absorbers );
138 if(StatusCode::SUCCESS !=
detStore->retrieve(materialManager, std::string(
"MATERIALS")))
return nullptr;
144 const GeoMaterial *
LAr = materialManager->
getMaterial(
"std::LiquidArgon");
145 if(!
LAr)
throw std::runtime_error(
"Error in EMECConstruction, std::LiquidArgon is not found.");
147 const GeoMaterial* innerAbsorberMaterial =
nullptr;
148 std::string innerAbsorberMaterial_name =
"LAr::EMEC_Thickabs";
149 if(multilayered_absorbers > 0){
150 if(multilayered_absorbers != 2){
152 innerAbsorberMaterial_name =
"std::Iron";
154 innerAbsorberMaterial_name =
"LAr::EMEC_shell";
157 innerAbsorberMaterial = materialManager->
getMaterial(innerAbsorberMaterial_name);
158 if(!innerAbsorberMaterial){
159 throw std::runtime_error(
160 (innerAbsorberMaterial_name +
161 " is not found for inner absorber in EMECConstruction.").c_str()
165 const GeoMaterial* outerAbsorberMaterial =
nullptr;
166 std::string outerAbsorberMaterial_name =
"LAr::EMEC_Thinabs";
167 if(multilayered_absorbers > 0){
168 if(multilayered_absorbers != 2){
170 outerAbsorberMaterial_name =
"std::Iron";
172 outerAbsorberMaterial_name =
"LAr::EMEC_shell";
175 outerAbsorberMaterial = materialManager->
getMaterial(outerAbsorberMaterial_name);
176 if(!outerAbsorberMaterial){
177 throw std::runtime_error(
178 (outerAbsorberMaterial_name +
179 " is not found for outer absorber in EMECConstruction.").c_str()
183 const GeoMaterial *Glue =
nullptr;
184 const GeoMaterial *Lead =
nullptr;
185 if(multilayered_absorbers > 0){
188 if(!Glue)
throw std::runtime_error(
"Error in EMECConstruction, LAr::Glue is not found.");
190 if(!Lead)
throw std::runtime_error(
"Error in EMECConstruction, LAr::Lead is not found.");
193 const GeoMaterial* electrodeMaterial = materialManager->
getMaterial(
"LAr::KaptonC");
194 if(!electrodeMaterial)
throw std::runtime_error(
"Error in EMECConstruction, LAr::KaptonC is not found.");
201 std::string baseName =
"LAr::EMEC";
203 double phiPosition, phiSize;
227 pAccessSvc->getRecordsetPtr(
"CryoPcons", larVersionKey.
tag(), larVersionKey.
node());
228 if(cryoPcons->size() == 0){
229 cryoPcons = pAccessSvc->getRecordsetPtr(
"CryoPcons",
"CryoPcons-EMEC-00");
239 std::string emecMotherName = baseName +
"::Mother";
241 GeoTransform *refSystemTransform =
nullptr;
245 GeoPcon* emecMotherShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
247 if(currentRecord->getString(
"PCON") ==
"EMEC::Mother"){
248 if(!refSystemTransform){
256 refSystemTransform =
new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
258 emecMotherShape->addPlane(currentRecord->getDouble(
"ZPLANE") + zMSTrans,
259 currentRecord->getDouble(
"RMIN"),
260 currentRecord->getDouble(
"RMAX"));
265 pAccessSvc->getRecordsetPtr(
"EmecGeometry", larVersionKey.
tag(), larVersionKey.
node());
266 if(DB_EmecGeometry->size() == 0){
267 DB_EmecGeometry = pAccessSvc->getRecordsetPtr(
"EmecGeometry",
"EmecGeometry-00");
269 double zWheelRefPoint = (*DB_EmecGeometry)[0]->getDouble(
"Z0")*
Gaudi::Units::cm;
270 double dMechFocaltoWRP=(*DB_EmecGeometry)[0]->getDouble(
"Z1")*
Gaudi::Units::cm;
271 double LArTotalThickness = (*DB_EmecGeometry)[0]->getDouble(
"ETOT") *
Gaudi::Units::cm;
272 double halfGapBetweenWheels = (*DB_EmecGeometry)[0]->getDouble(
"DCRACK")*
Gaudi::Units::cm;
273 double rOuterCutoff = (*DB_EmecGeometry)[0]->getDouble(
"RLIMIT")*
Gaudi::Units::cm;
276 pAccessSvc->getRecordsetPtr(
"EmecMagicNumbers", larVersionKey.
tag(), larVersionKey.
node());
277 if(DB_EMECmn->size() == 0)
278 DB_EMECmn = pAccessSvc->getRecordsetPtr(
"EmecMagicNumbers",
"EMECMagicNumbers-00");
279 double reftoactive = (*DB_EMECmn)[0]->getDouble(
"REFTOACTIVE") *
Gaudi::Units::mm;
280 double activelength = (*DB_EMECmn)[0]->getDouble(
"ACTIVELENGTH") *
Gaudi::Units::mm;
281 double straightstartsection = (*DB_EMECmn)[0]->getDouble(
"STRAIGHTSTARTSECTION")*
Gaudi::Units::mm;
282 double wheelThickness=activelength+2*straightstartsection;
283 double dWRPtoFrontFace = reftoactive;
284 double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace;
285 double zWheelBackFace = zWheelFrontFace+wheelThickness;
287 pAccessSvc->getRecordsetPtr(
"EmecWheelParameters", larVersionKey.
tag(),larVersionKey.
node());
288 if (DB_EMECwp->size()==0)
289 DB_EMECwp=pAccessSvc->getRecordsetPtr(
"EmecWheelParameters",
"EmecWheelParameters",
"EmecWheelParameters-00");
290 int numberOfHalfWavesInner=2*(*DB_EMECwp)[0]->getInt(
"NACC")+2;
291 int numberOfHalfWavesOuter=2*(*DB_EMECwp)[1]->getInt(
"NACC")+3;
292 double eta_hi = (*DB_EMECwp)[0]->getDouble(
"ETAINT");
293 double eta_mid = (*DB_EMECwp)[0]->getDouble(
"ETAEXT");
294 double eta_low = (*DB_EMECwp)[1]->getDouble(
"ETAEXT");
301 double tanThetaMid = 2. *
std::exp(-eta_mid) / (1. -
std::exp(-2.*eta_mid));
302 double tanThetaOuter = 2. *
std::exp(-eta_low) / (1. -
std::exp(-2.*eta_low));
303 double tanThetaInner = 2. *
std::exp(-eta_hi ) / (1. -
std::exp(-2.*eta_hi ));
304 double inv_tanThetaOuter = (1. -
std::exp(-2.*eta_low)) / (2. *
std::exp(-eta_low));
307 rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
308 rMax[0][1] = zWheelBackFace * tanThetaMid - halfGapBetweenWheels;
310 rMax[1][0] = zWheelFrontFace * tanThetaOuter;
311 rMax[1][1] = rOuterCutoff;
312 rMax[1][2] = rOuterCutoff;
318 rMin[0][0] = zWheelFrontFace * tanThetaInner;
319 rMin[0][1] = zWheelBackFace * tanThetaInner;
323 rMin[1][0] = zWheelFrontFace * tanThetaMid + halfGapBetweenWheels;
324 rMin[1][1] = rOuterCutoff * inv_tanThetaOuter * tanThetaMid + halfGapBetweenWheels;
325 rMin[1][2] = zWheelBackFace * tanThetaMid + halfGapBetweenWheels;
326 zMid[1] = rOuterCutoff * inv_tanThetaOuter - zWheelFrontFace;
329 const GeoLogVol* emecMotherLogical =
330 new GeoLogVol(emecMotherName, emecMotherShape,
LAr);
331 GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical =
new GeoFullPhysVol(emecMotherLogical);
333 if(!m_isTB) baseName += bPos?
"::Pos":
"::Neg";
336 std::string innerName = baseName +
"::Inner";
337 std::string LArName = innerName + (m_isTB?
"Module":
"Wheel");
339 std::vector<std::string> absorbers;
340 std::vector<std::string> electrodes;
342 if(m_innerWheelVariant ==
"Cone"){
344 absorbers.push_back(innerName +
"::Absorber");
345 electrodes.push_back(innerName +
"::Electrode");
346 }
else if(m_innerWheelVariant ==
"Slices"){
347 innerName +=
"Slice";
351 snprintf(buf, 4,
"%02d",
slice);
353 std::string
a = innerName + buf +
"::Absorber";
354 std::string
e = innerName + buf +
"::Electrode";
355 absorbers.push_back(
a);
356 electrodes.push_back(
e);
359 numberOfHalfWavesInner >
slice
364 <<
" goes wrong in EMECConstruction" );
368 innerName += (m_isTB?
"Module":
"Wheel");
369 absorbers.push_back(innerName +
"::Absorber");
370 electrodes.push_back(innerName +
"::Electrode");
374 << electrodes.size() <<
" electrode shapes created" );
377 double zBack = wheelThickness;
378 GeoPcon* innerShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
380 innerShape->addPlane(zBack , rMin[0][1], rMax[0][1]);
382 GeoLogVol* innerLogical =
new GeoLogVol (LArName,innerShape,
LAr);
383 GeoIntrusivePtr<GeoFullPhysVol> fullPV =
new GeoFullPhysVol(innerLogical);
385 emecMotherPhysical->add(
new GeoIdentifierTag(1));
386 emecMotherPhysical->add(refSystemTransform);
387 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
388 emecMotherPhysical->add(fullPV);
393 throw std::runtime_error(bPos?
"Cannot store EMEC_INNER_WHEEL_POS":
"Cannot store EMEC_INNER_WHEEL_NEG");
396 if (geoModelSvc->isEmecStandard()){
398 ATH_MSG_INFO(
"EMECConstruction build NewInnerWheel with standard Geant4 shapes: G4GenericTrap ");
403 emecAccordionConstructor.
setMaterial(
"Steel", innerAbsorberMaterial);
404 emecAccordionConstructor.
setMaterial(
"Glue", Glue);
405 emecAccordionConstructor.
setMaterial(
"Lead", Lead);
406 emecAccordionConstructor.
setMaterial(
"Kapton", electrodeMaterial);
410 place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,innerAbsorberMaterial, electrodeMaterial, Glue, Lead);
415 std::string outerName = baseName +
"::Outer";
416 const std::string LArName = outerName + (m_isTB?
"Module":
"Wheel");
418 std::vector<std::string> absorbers;
419 std::vector<std::string> electrodes;
421 if(m_outerWheelVariant ==
"Cone"){
422 absorbers.push_back(outerName +
"FrontCone::Absorber");
423 absorbers.push_back(outerName +
"BackCone::Absorber");
424 electrodes.push_back(outerName +
"FrontCone::Electrode");
425 electrodes.push_back(outerName +
"BackCone::Electrode");
426 outerName +=
"Cones";
427 }
else if(m_outerWheelVariant ==
"Slices"){
428 outerName +=
"Slice";
432 snprintf(buf, 4,
"%02d",
slice);
433 std::string
a = outerName + buf +
"::Absorber";
434 std::string
e = outerName + buf +
"::Electrode";
435 absorbers.push_back(
a);
436 electrodes.push_back(
e);
439 numberOfHalfWavesOuter >
slice
444 <<
" goes wrong in EMECConstruction" );
448 outerName += (m_isTB?
"Module":
"Wheel");
449 absorbers.push_back(outerName +
"::Absorber");
450 electrodes.push_back(outerName +
"::Electrode");
454 << electrodes.size() <<
" electrode shapes created" );
456 double zBack = wheelThickness;
457 GeoPcon *outerShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
459 outerShape->addPlane(zMid[1] , rMin[1][1], rMax[1][1]);
460 outerShape->addPlane(zBack , rMin[1][2], rMax[1][2]);
462 GeoLogVol *outerLogical =
new GeoLogVol(LArName, outerShape,
LAr);
463 GeoIntrusivePtr<GeoFullPhysVol>fullPV =
new GeoFullPhysVol(outerLogical);
465 emecMotherPhysical->add(
new GeoIdentifierTag(1));
466 emecMotherPhysical->add(refSystemTransform);
467 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
468 emecMotherPhysical->add(fullPV);
473 throw std::runtime_error(bPos?
"Cannot store EMEC_OUTER_WHEEL_POS":
"Cannot store EMEC_OUTER_WHEEL_NEG");
475 if (geoModelSvc->isEmecStandard()){
477 ATH_MSG_INFO(
"EMECConstruction build NewOuterWheel with standard Geant4 shapes: G4GenericTrap ");
482 emecAccordionConstructor.
setMaterial(
"Steel", outerAbsorberMaterial);
483 emecAccordionConstructor.
setMaterial(
"Glue", Glue);
484 emecAccordionConstructor.
setMaterial(
"Lead", Lead);
485 emecAccordionConstructor.
setMaterial(
"Kapton", electrodeMaterial);
489 place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,
490 outerAbsorberMaterial, electrodeMaterial, Glue, Lead
507 if(m_hasInnerWheel && !m_hasOuterWheel){
510 }
else if(m_hasOuterWheel && !m_hasInnerWheel){
516 pAccessSvc->getRecordsetPtr(
"EmecDMPCons", larVersionKey.
tag(), larVersionKey.
node());
517 if(DMpcons->size() == 0){
518 DMpcons = pAccessSvc->getRecordsetPtr(
"EmecDMPCons",
"EmecDMPCons-00");
525 const std::string&
object = dmPcon->getString(
"PCONNAME");
526 if(
object ==
"FrontSupportMother"){
527 int zplane = dmPcon->getInt(
"NZPLANE");
529 else if(zplane == 1) front_shift -= dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
531 }
else if(
object ==
"BackSupportMother"){
532 int zplane = dmPcon->getInt(
"NZPLANE");
533 if(zplane == 0) back_shift -= 0.;
534 else if(zplane == 1) back_shift += dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
538 front_shift += reftoactive;
539 back_shift += LArTotalThickness - reftoactive;
544 std::cout <<
"EMECConstruction: WARNING: cannot get front|back_shift from DB"
548 z0 = zWheelRefPoint + front_shift;
552 GeoIntrusivePtr<GeoPhysVol> physicalFSM = fsc->
GetEnvelope();
553 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
554 emecMotherPhysical->add(refSystemTransform);
555 emecMotherPhysical->add(physicalFSM);
558 z0 = zWheelRefPoint + back_shift;
562 GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->
GetEnvelope();
564 if(m_isTB) rotBSM = GeoTrf::RotateZ3D(
M_PI)*rotBSM;
565 emecMotherPhysical->add(refSystemTransform);
566 emecMotherPhysical->add(
new GeoTransform(
GeoTrf::Transform3D(GeoTrf::Translate3D(0., 0.,
z0)*rotBSM)));
567 emecMotherPhysical->add(physicalBSM);
570 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
574 GeoIntrusivePtr<GeoPhysVol>physicalOSM =
osc->GetEnvelope();
575 emecMotherPhysical->add(refSystemTransform);
576 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
577 emecMotherPhysical->add(physicalOSM);
580 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
584 GeoIntrusivePtr<GeoPhysVol>physicalISM = isc->
GetEnvelope();
585 emecMotherPhysical->add(refSystemTransform);
586 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
587 emecMotherPhysical->add(physicalISM);
590 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
594 GeoIntrusivePtr<GeoPhysVol>physicalMSM = msc->
GetEnvelope();
595 emecMotherPhysical->add(refSystemTransform);
596 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
597 emecMotherPhysical->add(physicalMSM);
601 return emecMotherPhysical;
611 GeoIntrusivePtr<GeoFullPhysVol>fullPV,
612 std::vector<std::string> &absorbers,
613 std::vector<std::string> &electrodes,
614 int multilayered_absorbers,
615 const GeoMaterial *Absorber,
const GeoMaterial *Electrode,
616 const GeoMaterial *Glue,
const GeoMaterial *Lead
620 for(
const auto&
name: absorbers){
621 GeoLogVol* log_volume =
new GeoLogVol(
name,
new GeoUnidentifiedShape(
"LArCustomShape",
name) , Absorber);
622 GeoIntrusivePtr<GeoPhysVol> phys_volume =
new GeoPhysVol(log_volume);
623 fullPV->add(
new GeoIdentifierTag(1));
624 fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
625 fullPV->add(phys_volume);
626 if(multilayered_absorbers > 0){
627 GeoIntrusivePtr<GeoPhysVol> glue_phys = phys_volume;
628 std::string lead_name =
name;
629 size_t repl = lead_name.find(
"Absorber");
630 if(std::string::npos != repl) lead_name.replace(repl, 8,
"Lead");
631 else throw std::runtime_error(lead_name +
": cannot find 'Absorber'");
632 if(multilayered_absorbers != 2){
633 std::string glue_name =
name;
634 glue_name.replace(repl, 8,
"Glue");
635 GeoLogVol* glue_log =
new GeoLogVol(glue_name,
new GeoUnidentifiedShape(
"LArCustomShape",glue_name), Glue);
636 glue_phys =
new GeoPhysVol(glue_log);
637 phys_volume->add(
new GeoIdentifierTag(1));
638 phys_volume->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
639 phys_volume->add(glue_phys);
641 GeoLogVol *lead_log =
new GeoLogVol(lead_name,
new GeoUnidentifiedShape(
"LArCustomShape",lead_name), Lead);
642 GeoIntrusivePtr<GeoPhysVol>lead_phys =
new GeoPhysVol(lead_log);
643 glue_phys->add(
new GeoIdentifierTag(1));
644 glue_phys->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
645 glue_phys->add(lead_phys);
649 for(
const auto&
name: electrodes){
650 GeoLogVol* log_volume =
new GeoLogVol(
name,
new GeoUnidentifiedShape(
"LArCustomShape",
name), Electrode);
651 GeoIntrusivePtr<GeoPhysVol> phys_volume =
new GeoPhysVol(log_volume);
652 fullPV->add(
new GeoIdentifierTag(1));
653 fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
654 fullPV->add(phys_volume);