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;
344 absorbers.push_back(innerName +
"::Absorber");
345 electrodes.push_back(innerName +
"::Electrode");
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 ");
399 EMECAccordionConstruction emecAccordionConstructor;
400 emecAccordionConstructor.setWheelParameters();
401 emecAccordionConstructor.setInnerWheel(fullPV);
402 emecAccordionConstructor.setMaterial(
"LiquidArgon",
LAr);
403 emecAccordionConstructor.setMaterial(
"Steel", innerAbsorberMaterial);
404 emecAccordionConstructor.setMaterial(
"Glue", Glue);
405 emecAccordionConstructor.setMaterial(
"Lead", Lead);
406 emecAccordionConstructor.setMaterial(
"Kapton", electrodeMaterial);
407 emecAccordionConstructor.constructInnerWheelStructure(makeSlices =
true);
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;
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";
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 ");
478 EMECAccordionConstruction emecAccordionConstructor;
479 emecAccordionConstructor.setWheelParameters();
480 emecAccordionConstructor.setOuterWheel(fullPV);
481 emecAccordionConstructor.setMaterial(
"LiquidArgon",
LAr);
482 emecAccordionConstructor.setMaterial(
"Steel", outerAbsorberMaterial);
483 emecAccordionConstructor.setMaterial(
"Glue", Glue);
484 emecAccordionConstructor.setMaterial(
"Lead", Lead);
485 emecAccordionConstructor.setMaterial(
"Kapton", electrodeMaterial);
486 emecAccordionConstructor.constructOuterWheelStructure(makeSlices =
true);
490 outerAbsorberMaterial, electrodeMaterial, Glue, Lead
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;
549 EMECSupportConstruction *fsc =
nullptr;
551 else fsc =
new EMECSupportConstruction(FrontSupp, bPos);
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;
559 EMECSupportConstruction *bsc =
nullptr;
561 else bsc =
new EMECSupportConstruction(BackSupp, bPos);
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;
571 EMECSupportConstruction *
osc =
nullptr;
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;
581 EMECSupportConstruction *isc =
nullptr;
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;
591 EMECSupportConstruction *msc =
nullptr;
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;