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"
82 #include "GeoModelKernel/GeoUnidentifiedShape.h"
87 m_fullGeo(true), m_isTB(is_tb), m_hasInnerWheel(has_inner), m_hasOuterWheel(has_outer),
88 m_innerWheelVariant(
"Wheel"), m_outerWheelVariant(
"Wheel")
113 ISvcLocator *svcLocator = Gaudi::svcLocator();
115 if(svcLocator->service(
"DetectorStore",
detStore,
false)==StatusCode::FAILURE) {
116 throw std::runtime_error(
"Error in EndcapCryostatConstruction, cannot access DetectorStore");
123 StatusCode sc = svcLocator->service(
"RDBAccessSvc",pAccessSvc);
124 if(
sc != StatusCode::SUCCESS){
125 throw std::runtime_error(
"EMECConstruction: cannot locate RDBAccessSvc!");
128 sc = svcLocator->service (
"GeoModelSvc",geoModelSvc);
129 if(
sc != StatusCode::SUCCESS){
130 throw std::runtime_error(
"EMECConstruction: cannot locate GeoModelSvc!");
136 int multilayered_absorbers = 0;
138 if(larSwitches->size()!=0){
139 if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER_EC")){
140 multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER_EC");
141 }
else if(!(*larSwitches)[0]->isFieldNull(
"DETAILED_ABSORBER")){
142 multilayered_absorbers = (*larSwitches)[0]->getInt(
"DETAILED_ABSORBER");
146 if(multilayered_absorbers > 0){
147 ATH_MSG_INFO(
"multi-layered version of absorbers activated, "
148 <<
"parameter value is " << multilayered_absorbers );
152 if(StatusCode::SUCCESS !=
detStore->retrieve(materialManager, std::string(
"MATERIALS")))
return nullptr;
158 const GeoMaterial *
LAr = materialManager->
getMaterial(
"std::LiquidArgon");
159 if(!
LAr)
throw std::runtime_error(
"Error in EMECConstruction, std::LiquidArgon is not found.");
161 const GeoMaterial* innerAbsorberMaterial =
nullptr;
162 std::string innerAbsorberMaterial_name =
"LAr::EMEC_Thickabs";
163 if(multilayered_absorbers > 0){
164 if(multilayered_absorbers != 2){
166 innerAbsorberMaterial_name =
"std::Iron";
168 innerAbsorberMaterial_name =
"LAr::EMEC_shell";
171 innerAbsorberMaterial = materialManager->
getMaterial(innerAbsorberMaterial_name);
172 if(!innerAbsorberMaterial){
173 throw std::runtime_error(
174 (innerAbsorberMaterial_name +
175 " is not found for inner absorber in EMECConstruction.").c_str()
179 const GeoMaterial* outerAbsorberMaterial =
nullptr;
180 std::string outerAbsorberMaterial_name =
"LAr::EMEC_Thinabs";
181 if(multilayered_absorbers > 0){
182 if(multilayered_absorbers != 2){
184 outerAbsorberMaterial_name =
"std::Iron";
186 outerAbsorberMaterial_name =
"LAr::EMEC_shell";
189 outerAbsorberMaterial = materialManager->
getMaterial(outerAbsorberMaterial_name);
190 if(!outerAbsorberMaterial){
191 throw std::runtime_error(
192 (outerAbsorberMaterial_name +
193 " is not found for outer absorber in EMECConstruction.").c_str()
197 const GeoMaterial *Glue =
nullptr;
198 const GeoMaterial *Lead =
nullptr;
199 if(multilayered_absorbers > 0){
202 if(!Glue)
throw std::runtime_error(
"Error in EMECConstruction, LAr::Glue is not found.");
204 if(!Lead)
throw std::runtime_error(
"Error in EMECConstruction, LAr::Lead is not found.");
207 const GeoMaterial* electrodeMaterial = materialManager->
getMaterial(
"LAr::KaptonC");
208 if(!electrodeMaterial)
throw std::runtime_error(
"Error in EMECConstruction, LAr::KaptonC is not found.");
215 std::string baseName =
"LAr::EMEC";
217 double phiPosition, phiSize;
242 if(cryoPcons->size() == 0){
243 cryoPcons = pAccessSvc->
getRecordsetPtr(
"CryoPcons",
"CryoPcons-EMEC-00");
253 std::string emecMotherName = baseName +
"::Mother";
255 GeoTransform *refSystemTransform =
nullptr;
259 GeoPcon* emecMotherShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
261 if(currentRecord->getString(
"PCON") ==
"EMEC::Mother"){
262 if(!refSystemTransform){
270 refSystemTransform =
new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
272 emecMotherShape->addPlane(currentRecord->getDouble(
"ZPLANE") + zMSTrans,
273 currentRecord->getDouble(
"RMIN"),
274 currentRecord->getDouble(
"RMAX"));
280 if(DB_EmecGeometry->size() == 0){
281 DB_EmecGeometry = pAccessSvc->
getRecordsetPtr(
"EmecGeometry",
"EmecGeometry-00");
283 double zWheelRefPoint = (*DB_EmecGeometry)[0]->getDouble(
"Z0")*
Gaudi::Units::cm;
284 double dMechFocaltoWRP=(*DB_EmecGeometry)[0]->getDouble(
"Z1")*
Gaudi::Units::cm;
285 double LArTotalThickness = (*DB_EmecGeometry)[0]->getDouble(
"ETOT") *
Gaudi::Units::cm;
286 double halfGapBetweenWheels = (*DB_EmecGeometry)[0]->getDouble(
"DCRACK")*
Gaudi::Units::cm;
287 double rOuterCutoff = (*DB_EmecGeometry)[0]->getDouble(
"RLIMIT")*
Gaudi::Units::cm;
291 if(DB_EMECmn->size() == 0)
292 DB_EMECmn = pAccessSvc->
getRecordsetPtr(
"EmecMagicNumbers",
"EMECMagicNumbers-00");
293 double reftoactive = (*DB_EMECmn)[0]->getDouble(
"REFTOACTIVE") *
Gaudi::Units::mm;
294 double activelength = (*DB_EMECmn)[0]->getDouble(
"ACTIVELENGTH") *
Gaudi::Units::mm;
295 double straightstartsection = (*DB_EMECmn)[0]->getDouble(
"STRAIGHTSTARTSECTION")*
Gaudi::Units::mm;
296 double wheelThickness=activelength+2*straightstartsection;
297 double dWRPtoFrontFace = reftoactive;
298 double zWheelFrontFace = dMechFocaltoWRP + dWRPtoFrontFace;
299 double zWheelBackFace = zWheelFrontFace+wheelThickness;
302 if (DB_EMECwp->size()==0)
303 DB_EMECwp=pAccessSvc->
getRecordsetPtr(
"EmecWheelParameters",
"EmecWheelParameters",
"EmecWheelParameters-00");
304 int numberOfHalfWavesInner=2*(*DB_EMECwp)[0]->getInt(
"NACC")+2;
305 int numberOfHalfWavesOuter=2*(*DB_EMECwp)[1]->getInt(
"NACC")+3;
306 double eta_hi = (*DB_EMECwp)[0]->getDouble(
"ETAINT");
307 double eta_mid = (*DB_EMECwp)[0]->getDouble(
"ETAEXT");
308 double eta_low = (*DB_EMECwp)[1]->getDouble(
"ETAEXT");
315 double tanThetaMid = 2. *
std::exp(-eta_mid) / (1. -
std::exp(-2.*eta_mid));
316 double tanThetaOuter = 2. *
std::exp(-eta_low) / (1. -
std::exp(-2.*eta_low));
317 double tanThetaInner = 2. *
std::exp(-eta_hi ) / (1. -
std::exp(-2.*eta_hi ));
318 double inv_tanThetaOuter = (1. -
std::exp(-2.*eta_low)) / (2. *
std::exp(-eta_low));
321 rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
322 rMax[0][1] = zWheelBackFace * tanThetaMid - halfGapBetweenWheels;
324 rMax[1][0] = zWheelFrontFace * tanThetaOuter;
325 rMax[1][1] = rOuterCutoff;
326 rMax[1][2] = rOuterCutoff;
332 rMin[0][0] = zWheelFrontFace * tanThetaInner;
333 rMin[0][1] = zWheelBackFace * tanThetaInner;
337 rMin[1][0] = zWheelFrontFace * tanThetaMid + halfGapBetweenWheels;
338 rMin[1][1] = rOuterCutoff * inv_tanThetaOuter * tanThetaMid + halfGapBetweenWheels;
339 rMin[1][2] = zWheelBackFace * tanThetaMid + halfGapBetweenWheels;
340 zMid[1] = rOuterCutoff * inv_tanThetaOuter - zWheelFrontFace;
343 const GeoLogVol* emecMotherLogical =
344 new GeoLogVol(emecMotherName, emecMotherShape,
LAr);
345 GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical =
new GeoFullPhysVol(emecMotherLogical);
347 if(!m_isTB) baseName += bPos?
"::Pos":
"::Neg";
350 std::string innerName = baseName +
"::Inner";
351 std::string LArName = innerName + (m_isTB?
"Module":
"Wheel");
353 std::vector<std::string> absorbers;
354 std::vector<std::string> electrodes;
356 if(m_innerWheelVariant ==
"Cone"){
358 absorbers.push_back(innerName +
"::Absorber");
359 electrodes.push_back(innerName +
"::Electrode");
360 }
else if(m_innerWheelVariant ==
"Slices"){
361 innerName +=
"Slice";
365 snprintf(buf, 4,
"%02d",
slice);
367 std::string
a = innerName + buf +
"::Absorber";
368 std::string
e = innerName + buf +
"::Electrode";
369 absorbers.push_back(
a);
370 electrodes.push_back(
e);
373 numberOfHalfWavesInner >
slice
378 <<
" goes wrong in EMECConstruction" );
382 innerName += (m_isTB?
"Module":
"Wheel");
383 absorbers.push_back(innerName +
"::Absorber");
384 electrodes.push_back(innerName +
"::Electrode");
388 << electrodes.size() <<
" electrode shapes created" );
391 double zBack = wheelThickness;
392 GeoPcon* innerShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
394 innerShape->addPlane(zBack , rMin[0][1], rMax[0][1]);
396 GeoLogVol* innerLogical =
new GeoLogVol (LArName,innerShape,
LAr);
397 GeoIntrusivePtr<GeoFullPhysVol> fullPV =
new GeoFullPhysVol(innerLogical);
399 emecMotherPhysical->add(
new GeoIdentifierTag(1));
400 emecMotherPhysical->add(refSystemTransform);
401 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
402 emecMotherPhysical->add(fullPV);
407 throw std::runtime_error(bPos?
"Cannot store EMEC_INNER_WHEEL_POS":
"Cannot store EMEC_INNER_WHEEL_NEG");
411 fullPV, absorbers, electrodes, multilayered_absorbers,
412 innerAbsorberMaterial, electrodeMaterial, Glue, Lead
417 std::string outerName = baseName +
"::Outer";
418 const std::string LArName = outerName + (m_isTB?
"Module":
"Wheel");
420 std::vector<std::string> absorbers;
421 std::vector<std::string> electrodes;
423 if(m_outerWheelVariant ==
"Cone"){
424 absorbers.push_back(outerName +
"FrontCone::Absorber");
425 absorbers.push_back(outerName +
"BackCone::Absorber");
426 electrodes.push_back(outerName +
"FrontCone::Electrode");
427 electrodes.push_back(outerName +
"BackCone::Electrode");
428 outerName +=
"Cones";
429 }
else if(m_outerWheelVariant ==
"Slices"){
430 outerName +=
"Slice";
434 snprintf(buf, 4,
"%02d",
slice);
435 std::string
a = outerName + buf +
"::Absorber";
436 std::string
e = outerName + buf +
"::Electrode";
437 absorbers.push_back(
a);
438 electrodes.push_back(
e);
441 numberOfHalfWavesOuter >
slice
446 <<
" goes wrong in EMECConstruction" );
450 outerName += (m_isTB?
"Module":
"Wheel");
451 absorbers.push_back(outerName +
"::Absorber");
452 electrodes.push_back(outerName +
"::Electrode");
456 << electrodes.size() <<
" electrode shapes created" );
458 double zBack = wheelThickness;
459 GeoPcon *outerShape =
new GeoPcon(phiPosition - phiSize, 2.*phiSize);
461 outerShape->addPlane(zMid[1] , rMin[1][1], rMax[1][1]);
462 outerShape->addPlane(zBack , rMin[1][2], rMax[1][2]);
464 GeoLogVol *outerLogical =
new GeoLogVol(LArName, outerShape,
LAr);
465 GeoIntrusivePtr<GeoFullPhysVol>fullPV =
new GeoFullPhysVol(outerLogical);
467 emecMotherPhysical->add(
new GeoIdentifierTag(1));
468 emecMotherPhysical->add(refSystemTransform);
469 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
470 emecMotherPhysical->add(fullPV);
475 throw std::runtime_error(bPos?
"Cannot store EMEC_OUTER_WHEEL_POS":
"Cannot store EMEC_OUTER_WHEEL_NEG");
479 fullPV, absorbers, electrodes, multilayered_absorbers,
480 outerAbsorberMaterial, electrodeMaterial, Glue, Lead
496 if(m_hasInnerWheel && !m_hasOuterWheel){
499 }
else if(m_hasOuterWheel && !m_hasInnerWheel){
506 if(DMpcons->size() == 0){
507 DMpcons = pAccessSvc->
getRecordsetPtr(
"EmecDMPCons",
"EmecDMPCons-00");
514 const std::string&
object = dmPcon->getString(
"PCONNAME");
515 if(
object ==
"FrontSupportMother"){
516 int zplane = dmPcon->getInt(
"NZPLANE");
518 else if(zplane == 1) front_shift -= dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
520 }
else if(
object ==
"BackSupportMother"){
521 int zplane = dmPcon->getInt(
"NZPLANE");
522 if(zplane == 0) back_shift -= 0.;
523 else if(zplane == 1) back_shift += dmPcon->getDouble(
"ZPOS")*
Gaudi::Units::mm;
527 front_shift += reftoactive;
528 back_shift += LArTotalThickness - reftoactive;
533 std::cout <<
"EMECConstruction: WARNING: cannot get front|back_shift from DB"
537 z0 = zWheelRefPoint + front_shift;
541 GeoIntrusivePtr<GeoPhysVol> physicalFSM = fsc->
GetEnvelope();
542 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
543 emecMotherPhysical->add(refSystemTransform);
544 emecMotherPhysical->add(physicalFSM);
547 z0 = zWheelRefPoint + back_shift;
551 GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->
GetEnvelope();
553 if(m_isTB) rotBSM = GeoTrf::RotateZ3D(
M_PI)*rotBSM;
554 emecMotherPhysical->add(refSystemTransform);
555 emecMotherPhysical->add(
new GeoTransform(
GeoTrf::Transform3D(GeoTrf::Translate3D(0., 0.,
z0)*rotBSM)));
556 emecMotherPhysical->add(physicalBSM);
559 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
563 GeoIntrusivePtr<GeoPhysVol>physicalOSM =
osc->GetEnvelope();
564 emecMotherPhysical->add(refSystemTransform);
565 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
566 emecMotherPhysical->add(physicalOSM);
569 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
573 GeoIntrusivePtr<GeoPhysVol>physicalISM = isc->
GetEnvelope();
574 emecMotherPhysical->add(refSystemTransform);
575 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
576 emecMotherPhysical->add(physicalISM);
579 z0 = zWheelRefPoint + LArTotalThickness * 0.5;
583 GeoIntrusivePtr<GeoPhysVol>physicalMSM = msc->
GetEnvelope();
584 emecMotherPhysical->add(refSystemTransform);
585 emecMotherPhysical->add(
new GeoTransform(GeoTrf::TranslateZ3D(
z0)));
586 emecMotherPhysical->add(physicalMSM);
590 return emecMotherPhysical;
600 GeoIntrusivePtr<GeoFullPhysVol>fullPV,
601 std::vector<std::string> &absorbers,
602 std::vector<std::string> &electrodes,
603 int multilayered_absorbers,
604 const GeoMaterial *Absorber,
const GeoMaterial *Electrode,
605 const GeoMaterial *Glue,
const GeoMaterial *Lead
609 for(
const auto&
name: absorbers){
610 GeoLogVol* log_volume =
new GeoLogVol(
name,
new GeoUnidentifiedShape(
"LArCustomShape",
name) , Absorber);
611 GeoIntrusivePtr<GeoPhysVol> phys_volume =
new GeoPhysVol(log_volume);
612 fullPV->add(
new GeoIdentifierTag(1));
613 fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
614 fullPV->add(phys_volume);
615 if(multilayered_absorbers > 0){
616 GeoIntrusivePtr<GeoPhysVol> glue_phys = phys_volume;
617 std::string lead_name =
name;
618 size_t repl = lead_name.find(
"Absorber");
619 if(std::string::npos != repl) lead_name.replace(repl, 8,
"Lead");
620 else throw std::runtime_error(lead_name +
": cannot find 'Absorber'");
621 if(multilayered_absorbers != 2){
622 std::string glue_name =
name;
623 glue_name.replace(repl, 8,
"Glue");
624 GeoLogVol* glue_log =
new GeoLogVol(glue_name,
new GeoUnidentifiedShape(
"LArCustomShape",glue_name), Glue);
625 glue_phys =
new GeoPhysVol(glue_log);
626 phys_volume->add(
new GeoIdentifierTag(1));
627 phys_volume->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
628 phys_volume->add(glue_phys);
630 GeoLogVol *lead_log =
new GeoLogVol(lead_name,
new GeoUnidentifiedShape(
"LArCustomShape",lead_name), Lead);
631 GeoIntrusivePtr<GeoPhysVol>lead_phys =
new GeoPhysVol(lead_log);
632 glue_phys->add(
new GeoIdentifierTag(1));
633 glue_phys->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
634 glue_phys->add(lead_phys);
638 for(
const auto&
name: electrodes){
639 GeoLogVol* log_volume =
new GeoLogVol(
name,
new GeoUnidentifiedShape(
"LArCustomShape",
name), Electrode);
640 GeoIntrusivePtr<GeoPhysVol> phys_volume =
new GeoPhysVol(log_volume);
641 fullPV->add(
new GeoIdentifierTag(1));
642 fullPV->add(
new GeoTransform(GeoTrf::Transform3D::Identity()));
643 fullPV->add(phys_volume);