102{
103 ISvcLocator *svcLocator = Gaudi::svcLocator();
104 SmartIF<StoreGateSvc>
detStore{svcLocator->service(
"DetectorStore")};
106 throw std::runtime_error("Error in EndcapCryostatConstruction, cannot access DetectorStore");
107 }
108
109
110 SmartIF<IRDBAccessSvc> pAccessSvc{svcLocator->service("RDBAccessSvc")};
111 if(!pAccessSvc.isValid()) {
112 throw std::runtime_error("EMECConstruction: cannot locate RDBAccessSvc!");
113 }
114
115 SmartIF<IGeoModelSvc> geoModelSvc{svcLocator->service("GeoModelSvc")};
116 if(!geoModelSvc.isValid()) {
117 throw std::runtime_error("EMECConstruction: cannot locate GeoModelSvc!");
118 }
119
120 DecodeVersionKey larVersionKey(geoModelSvc, "LAr");
121
122
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");
130 }
131 }
132
133 if(multilayered_absorbers > 0){
134 ATH_MSG_INFO(
"multi-layered version of absorbers activated, "
135 << "parameter value is " << multilayered_absorbers );
136 }
137
138 StoredMaterialManager* materialManager = nullptr;
139 if(StatusCode::SUCCESS !=
detStore->retrieve(materialManager, std::string(
"MATERIALS")))
return nullptr;
140
142
144
145 const GeoMaterial *LAr = materialManager->
getMaterial(
"std::LiquidArgon");
146 if(!LAr) throw std::runtime_error("Error in EMECConstruction, std::LiquidArgon is not found.");
147
148 const GeoMaterial* innerAbsorberMaterial = nullptr;
149 std::string innerAbsorberMaterial_name = "LAr::EMEC_Thickabs";
150 if(multilayered_absorbers > 0){
151 if(multilayered_absorbers != 2){
152
153 innerAbsorberMaterial_name = "std::Iron";
154 } else {
155 innerAbsorberMaterial_name = "LAr::EMEC_shell";
156 }
157 }
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()
163 );
164 }
165
166 const GeoMaterial* outerAbsorberMaterial = nullptr;
167 std::string outerAbsorberMaterial_name = "LAr::EMEC_Thinabs";
168 if(multilayered_absorbers > 0){
169 if(multilayered_absorbers != 2){
170
171 outerAbsorberMaterial_name = "std::Iron";
172 } else {
173 outerAbsorberMaterial_name = "LAr::EMEC_shell";
174 }
175 }
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()
181 );
182 }
183
184 const GeoMaterial *Glue = nullptr;
185 const GeoMaterial *Lead = nullptr;
186 if(multilayered_absorbers > 0){
187
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.");
192 }
193
194 const GeoMaterial* electrodeMaterial = materialManager->
getMaterial(
"LAr::KaptonC");
195 if(!electrodeMaterial) throw std::runtime_error("Error in EMECConstruction, LAr::KaptonC is not found.");
196
198
200
201
202 std::string baseName = "LAr::EMEC";
203
204 double phiPosition, phiSize;
205
207 phiPosition = Gaudi::Units::halfpi*Gaudi::Units::rad;
208 phiSize =
M_PI*Gaudi::Units::rad / 8. + 0.065*Gaudi::Units::rad;
209 }
210 else {
211 phiPosition =
M_PI*Gaudi::Units::rad;
212 phiSize =
M_PI*Gaudi::Units::rad;
213 }
214
215
216
217
218
219
220
221
222
223
224
225
226
228 pAccessSvc->getRecordsetPtr("CryoPcons", larVersionKey.tag(), larVersionKey.node());
229 if(cryoPcons->
size() == 0){
230 cryoPcons = pAccessSvc->getRecordsetPtr("CryoPcons", "CryoPcons-EMEC-00");
231 }
232
233
234
235
236
237
238
239
240 std::string emecMotherName = baseName + "::Mother";
241
242 GeoTransform *refSystemTransform = nullptr;
243 double zTrans = 0.*Gaudi::Units::mm;
244 double zMSTrans = 0.*Gaudi::Units::mm;
245
246 GeoPcon* emecMotherShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
248 if(currentRecord->getString("PCON") == "EMEC::Mother"){
249 if(!refSystemTransform){
251 zTrans = -3700.5*Gaudi::Units::mm;
252 zMSTrans = zTrans;
253 } else {
254 zTrans = currentRecord->getDouble("ZPLANE") - 3639.5*Gaudi::Units::mm;
255 zMSTrans = 0.*Gaudi::Units::mm;
256 }
257 refSystemTransform = new GeoTransform(GeoTrf::TranslateZ3D(zTrans));
258 }
259 emecMotherShape->addPlane(currentRecord->getDouble("ZPLANE") + zMSTrans,
260 currentRecord->getDouble("RMIN"),
261 currentRecord->getDouble("RMAX"));
262 }
263 }
264
266 pAccessSvc->getRecordsetPtr("EmecGeometry", larVersionKey.tag(), larVersionKey.node());
267 if(DB_EmecGeometry->
size() == 0){
268 DB_EmecGeometry = pAccessSvc->getRecordsetPtr("EmecGeometry", "EmecGeometry-00");
269 }
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;
275
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");
296
297
298 double zMid[2];
299 double rMin[2][3];
300 double rMax[2][3];
301 {
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));
306
307
308 rMax[0][0] = zWheelFrontFace * tanThetaMid - halfGapBetweenWheels;
309 rMax[0][1] = zWheelBackFace * tanThetaMid - halfGapBetweenWheels;
310
311 rMax[1][0] = zWheelFrontFace * tanThetaOuter;
312 rMax[1][1] = rOuterCutoff;
313 rMax[1][2] = rOuterCutoff;
314
315
316
317
318
319 rMin[0][0] = zWheelFrontFace * tanThetaInner;
320 rMin[0][1] = zWheelBackFace * tanThetaInner;
321 zMid[0] = 0;
322
323
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;
328 }
329
330 const GeoLogVol* emecMotherLogical =
331 new GeoLogVol(emecMotherName, emecMotherShape, LAr);
332 GeoIntrusivePtr<GeoFullPhysVol> emecMotherPhysical = new GeoFullPhysVol(emecMotherLogical);
333
334 if(!
m_isTB) baseName += bPos?
"::Pos":
"::Neg";
335
337 std::string innerName = baseName + "::Inner";
338 std::string LArName = innerName + (
m_isTB?
"Module":
"Wheel");
339
340 std::vector<std::string> absorbers;
341 std::vector<std::string> electrodes;
342
344 innerName += "Cone";
345 absorbers.push_back(innerName + "::Absorber");
346 electrodes.push_back(innerName + "::Electrode");
348 innerName += "Slice";
350 do {
351 absorbers.push_back(std::format("{}{:02d}::Absorber", innerName, slice));
352 absorbers.push_back(std::format("{}{:02d}::Electrode", innerName, slice));
354 } while(
355 numberOfHalfWavesInner > slice
356 && slice < 100
357 );
358 if(slice >= 100){
360 << " goes wrong in EMECConstruction" );
361 }
362 innerName += "s";
363 } else {
364 innerName += (
m_isTB?
"Module":
"Wheel");
365 absorbers.push_back(innerName + "::Absorber");
366 electrodes.push_back(innerName + "::Electrode");
367 }
370 << electrodes.size() << " electrode shapes created" );
371
372
373 double zBack = wheelThickness;
374 GeoPcon* innerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
375 innerShape->addPlane(0.*Gaudi::Units::mm, rMin[0][0], rMax[0][0]);
376 innerShape->addPlane(zBack , rMin[0][1], rMax[0][1]);
377
378 GeoLogVol* innerLogical = new GeoLogVol (LArName,innerShape, LAr);
379 GeoIntrusivePtr<GeoFullPhysVol> fullPV = new GeoFullPhysVol(innerLogical);
380
381 emecMotherPhysical->add(new GeoIdentifierTag(1));
382 emecMotherPhysical->add(refSystemTransform);
383 emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
384 emecMotherPhysical->add(fullPV);
385
386 StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
389 throw std::runtime_error(bPos? "Cannot store EMEC_INNER_WHEEL_POS": "Cannot store EMEC_INNER_WHEEL_NEG");
390 }
391
392 if (geoModelSvc->isEmecStandard()){
393 bool makeSlices;
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);
404 }
405 else {
406 place_custom_solids(fullPV, absorbers, electrodes, multilayered_absorbers,innerAbsorberMaterial, electrodeMaterial, Glue, Lead);
407 }
408 }
409
411 std::string outerName = baseName + "::Outer";
412 const std::string LArName = outerName + (
m_isTB?
"Module":
"Wheel");
413
414 std::vector<std::string> absorbers;
415 std::vector<std::string> electrodes;
416
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";
426 do {
427 absorbers.push_back(std::format("{}{:02d}::Absorber", outerName, slice));
428 absorbers.push_back(std::format("{}{:02d}::Electrode", outerName, slice));
430 } while(
431 numberOfHalfWavesOuter > slice
432 && slice < 100
433 );
434 if(slice >= 100){
436 << " goes wrong in EMECConstruction" );
437 }
438 outerName += "s";
439 } else {
440 outerName += (
m_isTB?
"Module":
"Wheel");
441 absorbers.push_back(outerName + "::Absorber");
442 electrodes.push_back(outerName + "::Electrode");
443 }
446 << electrodes.size() << " electrode shapes created" );
447
448 double zBack = wheelThickness;
449 GeoPcon *outerShape = new GeoPcon(phiPosition - phiSize, 2.*phiSize);
450 outerShape->addPlane(0.*Gaudi::Units::mm, rMin[1][0], rMax[1][0]);
451 outerShape->addPlane(zMid[1] , rMin[1][1], rMax[1][1]);
452 outerShape->addPlane(zBack , rMin[1][2], rMax[1][2]);
453
454 GeoLogVol *outerLogical = new GeoLogVol(LArName, outerShape, LAr);
455 GeoIntrusivePtr<GeoFullPhysVol>fullPV = new GeoFullPhysVol(outerLogical);
456
457 emecMotherPhysical->add(new GeoIdentifierTag(1));
458 emecMotherPhysical->add(refSystemTransform);
459 emecMotherPhysical->add(new GeoTransform(GeoTrf::TranslateZ3D(zWheelRefPoint+dWRPtoFrontFace)));
460 emecMotherPhysical->add(fullPV);
461
462 StoredPhysVol *sPhysVol = new StoredPhysVol(fullPV);
465 throw std::runtime_error(bPos? "Cannot store EMEC_OUTER_WHEEL_POS": "Cannot store EMEC_OUTER_WHEEL_NEG");
466 }
467 if (geoModelSvc->isEmecStandard()){
468 bool makeSlices;
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);
479
480 } else {
482 outerAbsorberMaterial, electrodeMaterial, Glue, Lead
483 );
484 }
485
486 }
487
488
489
490
491
494
495
505 }
506
508 pAccessSvc->getRecordsetPtr("EmecDMPCons", larVersionKey.tag(), larVersionKey.node());
509 if(DMpcons->
size() == 0){
510 DMpcons = pAccessSvc->getRecordsetPtr("EmecDMPCons", "EmecDMPCons-00");
511 }
512
513 double front_shift = 0.*Gaudi::Units::mm;
514 double back_shift = 0.*Gaudi::Units::mm;
515 try {
517 const std::string& object = dmPcon->getString("PCONNAME");
518 if(object == "FrontSupportMother"){
519 int zplane = dmPcon->getInt("NZPLANE");
520 if(zplane == 0) front_shift += dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
521 else if(zplane == 1) front_shift -= dmPcon->getDouble("ZPOS")*Gaudi::Units::mm;
522 else continue;
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;
527 else continue;
528 }
529 }
530 front_shift += reftoactive;
531 back_shift += LArTotalThickness - reftoactive;
532 }
533 catch (...){
534 front_shift = -50.*Gaudi::Units::mm;
535 back_shift = 580.*Gaudi::Units::mm;
536 std::cout << "EMECConstruction: WARNING: cannot get front|back_shift from DB"
537 << std::endl;
538 }
539
540 z0 = zWheelRefPoint + front_shift;
541 EMECSupportConstruction *fsc = nullptr;
542 if(
m_isTB) fsc =
new EMECSupportConstruction(FrontSupp, bPos,
true,
"LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
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);
548 delete fsc;
549
550 z0 = zWheelRefPoint + back_shift;
551 EMECSupportConstruction *bsc = nullptr;
552 if(
m_isTB) bsc =
new EMECSupportConstruction(BackSupp, bPos,
true,
"LAr::EMEC::", Gaudi::Units::halfpi*Gaudi::Units::rad);
553 else bsc = new EMECSupportConstruction(BackSupp, bPos);
554 GeoIntrusivePtr<GeoPhysVol>physicalBSM = bsc->GetEnvelope();
555 GeoTrf::Transform3D rotBSM(GeoTrf::RotateX3D(-
M_PI));
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);
560 delete bsc;
561
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);
571
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);
580 delete isc;
581
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);
590 delete msc;
591 }
592
593 return emecMotherPhysical;
594}
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
std::unique_ptr< IRDBRecord > IRDBRecord_ptr
virtual unsigned int size() const =0
static void place_custom_solids(GeoIntrusivePtr< GeoFullPhysVol >fullPV, std::vector< std::string > &absorbers, std::vector< std::string > &electrodes, int multilayered_absorbers, const GeoMaterial *Absorber, const GeoMaterial *Electrode, const GeoMaterial *Glue, const GeoMaterial *Lead)
virtual const GeoMaterial * getMaterial(const std::string &name)=0
::StatusCode StatusCode
StatusCode definition for legacy code.