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;
345 absorbers.push_back(innerName +
"::Absorber");
346 electrodes.push_back(innerName +
"::Electrode");
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 ");
395 EMECAccordionConstruction emecAccordionConstructor;
396 emecAccordionConstructor.setWheelParameters();
397 emecAccordionConstructor.setInnerWheel(fullPV);
398 emecAccordionConstructor.setMaterial(
"LiquidArgon",
LAr);
399 emecAccordionConstructor.setMaterial(
"Steel", innerAbsorberMaterial);
400 emecAccordionConstructor.setMaterial(
"Glue", Glue);
401 emecAccordionConstructor.setMaterial(
"Lead", Lead);
402 emecAccordionConstructor.setMaterial(
"Kapton", electrodeMaterial);
403 emecAccordionConstructor.constructInnerWheelStructure(makeSlices =
true);
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;
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";
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 ");
470 EMECAccordionConstruction emecAccordionConstructor;
471 emecAccordionConstructor.setWheelParameters();
472 emecAccordionConstructor.setOuterWheel(fullPV);
473 emecAccordionConstructor.setMaterial(
"LiquidArgon",
LAr);
474 emecAccordionConstructor.setMaterial(
"Steel", outerAbsorberMaterial);
475 emecAccordionConstructor.setMaterial(
"Glue", Glue);
476 emecAccordionConstructor.setMaterial(
"Lead", Lead);
477 emecAccordionConstructor.setMaterial(
"Kapton", electrodeMaterial);
478 emecAccordionConstructor.constructOuterWheelStructure(makeSlices =
true);
482 outerAbsorberMaterial, electrodeMaterial, Glue, Lead
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;
541 EMECSupportConstruction *fsc =
nullptr;
543 else fsc =
new EMECSupportConstruction(FrontSupp, bPos);
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;
551 EMECSupportConstruction *bsc =
nullptr;
553 else bsc =
new EMECSupportConstruction(BackSupp, bPos);
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;
563 EMECSupportConstruction *
osc =
nullptr;
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;
573 EMECSupportConstruction *isc =
nullptr;
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;
583 EMECSupportConstruction *msc =
nullptr;
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;