16#include "GeoModelKernel/GeoElement.h"
17#include "GeoModelKernel/GeoMaterial.h"
18#include "GeoModelKernel/GeoFullPhysVol.h"
19#include "GeoModelKernel/GeoPhysVol.h"
20#include "GeoModelKernel/GeoVPhysVol.h"
21#include "GeoModelKernel/GeoLogVol.h"
22#include "GeoModelKernel/GeoBox.h"
23#include "GeoModelKernel/GeoCons.h"
24#include "GeoModelKernel/GeoPcon.h"
25#include "GeoModelKernel/GeoGenericTrap.h"
26#include "GeoModelKernel/GeoNameTag.h"
27#include "GeoModelKernel/GeoTransform.h"
28#include "GeoModelKernel/GeoIdentifierTag.h"
29#include "GeoModelKernel/Units.h"
36#include "GaudiKernel/MsgStream.h"
37#include "GaudiKernel/ISvcLocator.h"
38#include "GaudiKernel/PhysicalConstants.h"
39#include "GaudiKernel/StatusCode.h"
44#define SI GeoModelKernelUnits
52 ISvcLocator *svcLocator = Gaudi::svcLocator();
53 SmartIF<StoreGateSvc> detStore{svcLocator->service(
"DetectorStore")};
54 if(!detStore.isValid()) {
55 throw std::runtime_error(
"Error in EndcapCryostatConstruction, cannot access DetectorStore");
60 SmartIF<IRDBAccessSvc> rdbAccess{svcLocator->service(
"RDBAccessSvc")};
61 if(!rdbAccess.isValid()){
62 throw std::runtime_error(
"EMECConstruction: cannot locate RDBAccessSvc!");
65 SmartIF<IGeoModelSvc> geoModelSvc{svcLocator->service(
"GeoModelSvc")};
66 if(!geoModelSvc.isValid()) {
67 throw std::runtime_error(
"EMECAccordionConstruction: cannot locate GeoModelSvc!");
71 IRDBRecordset_ptr DB_EmecGeometry = rdbAccess->getRecordsetPtr(
"EmecGeometry", larVersionKey.
tag(), larVersionKey.
node());
72 if(DB_EmecGeometry->
size() == 0){
73 DB_EmecGeometry = rdbAccess->getRecordsetPtr(
"EmecGeometry",
"EmecGeometry-00");
76 IRDBRecordset_ptr emecWheelParameters = rdbAccess->getRecordsetPtr(
"EmecWheelParameters", larVersionKey.
tag(), larVersionKey.
node());
77 if(emecWheelParameters->
size() == 0){
78 emecWheelParameters = rdbAccess->getRecordsetPtr(
"EmecWheelParameters",
"EmecWheelParameters-00");
82 IRDBRecordset_ptr emecMagicNumbers = rdbAccess->getRecordsetPtr(
"EmecMagicNumbers", larVersionKey.
tag(), larVersionKey.
node());
83 if(emecMagicNumbers->
size() == 0){
84 emecMagicNumbers = rdbAccess->getRecordsetPtr(
"EmecMagicNumbers",
"EmecMagicNumbers-00");
87 IRDBRecordset_ptr coldContraction = rdbAccess->getRecordsetPtr(
"ColdContraction", larVersionKey.
tag(), larVersionKey.
node());
88 if(coldContraction->
size() == 0){
89 coldContraction = rdbAccess->getRecordsetPtr(
"ColdContraction",
"ColdContraction-00");
93 if(emecFan->
size() == 0){
94 emecFan = rdbAccess->getRecordsetPtr(
"EmecFan",
"EmecFan-00");
103 m_innerLipWidth = (*emecMagicNumbers)[0]->getDouble(
"STRAIGHTSTARTSECTION") * SI::mm;
112 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong number of absorbers. (NABS = " + std::to_string(
m_innerNoAbsorbes) +
") for Inner Wheel, expected 256!");
115 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong number of waves. (NACC = " + std::to_string(
m_innerNoAbsorbes ) +
") for Inner Wheel, expected 6!");
118 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong width of absorber lips. (STRAIGHTSTARTSECTION = " + std::to_string(
m_innerNoAbsorbes/SI::mm) +
"), expected 2 mm!" );
121 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong width of absorber active zone. (ACTIVELENGTH = " + std::to_string(
m_innerWaveZoneWidth/SI::mm) +
"), expected 510 mm!");
138 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong number of absorbers. (NABS = " + std::to_string (
m_outerNoAbsorbes) +
") for Outer Wheel, expected 768!");
141 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setWheelParameters: wrong number of waves. (NACC = " + std::to_string(
m_outerNoAbsorbes) +
") for Outer Wheel, expected 9!" );
168 m_kContraction = (*coldContraction)[0]->getDouble(
"ABSORBERCONTRACTION");
182 double eleInvContraction = (*coldContraction)[0]->getDouble(
"ELECTRODEINVCONTRACTION");
194 const GeoShape* shape = innerWheel->getLogVol()->getShape();
195 if (shape->type() !=
"Pcon") {
196 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setInnerWheel: unexpected shape type '"+ shape->type() +
"', expected 'Pcon'!");
198 const GeoPcon* pcon =
static_cast<const GeoPcon*
>(shape);
199 auto nplanes = pcon->getNPlanes();
201 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setInnerWheel: wrong number of Z planes '" + std::to_string(nplanes) +
"', expected '2'!");
203 for (
unsigned int i = 0; i < nplanes; ++i)
220 const GeoShape* shape = outerWheel->getLogVol()->getShape();
221 if (shape->type() !=
"Pcon") {
222 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setOuterWheel: unexpected shape type '"+ shape->type() +
"', expected 'Pcon'!");
225 const GeoPcon* pcon =
static_cast<const GeoPcon*
>(shape);
226 auto nplanes = pcon->getNPlanes();
228 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setOuterWheel: wrong number of Z planes" + std::to_string(nplanes) +
"', expected '3'!" );
230 for (
unsigned int i = 0; i < nplanes; ++i)
248 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setInnerWheelSlices: Inner Wheel volume is not set!" );
280 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setOuterWheelSlices: Outer Wheel volume is not set!");
313 const GeoMaterial* material)
322 throw std::runtime_error(
"LArGeo::EMECAccordionConstruction::setMaterial: unexpected material name '" + name +
"'!");
332 double& llip1,
double& ylip1,
333 double& llip2,
double& ylip2)
const
382 double cosa =
A[k1].dot(
A[k2])/(
A[k1].norm()*
A[k2].norm());
383 double ang = std::acos(cosa)/(k2 - k1);
386 double rmin = B[1].norm();
387 double rmax =
A[14].norm();
388 wmin = 2.*rmin*std::sin(ang/2.);
389 wmax = 2.*rmax*std::sin(ang/2.);
392 llip1 = (
C[2] - D[2]).norm();
393 ylip1 = (D[2] - B[1]).norm() + llip1/2.;
396 llip2 = (
C[3] - D[3]).norm();
397 ylip2 = (D[3] - B[14]).norm() + llip2/2.;
406 double& llip1,
double& ylip1,
407 double& llip2,
double& ylip2)
const
468 double cosa =
A[k1].dot(
A[k2])/(
A[k1].norm()*
A[k2].norm());
469 double ang = std::acos(cosa)/(k2 - k1);
472 double rmin = B[1].norm();
473 double rmax =
A[19].norm();
474 wmin = 2.*rmin*std::sin(ang/2.);
475 wmax = 2.*rmax*std::sin(ang/2.);
478 llip1 = (
C[2] - D[2]).norm();
479 ylip1 = (D[2] - B[1]).norm() + llip1/2.;
482 llip2 = (
C[3] - D[3]).norm();
483 ylip2 = (D[3] - B[20]).norm() + llip2/2.;
492 double rmin,
double rmax,
double zdel,
497 double xmin = std::sqrt(wmin*wmin - zdel*zdel)/2.;
498 double dxmin = (thickness/2.)*(wmin/zdel);
501 double xmax = std::sqrt(wmax*wmax - zdel*zdel)/2.;
502 double dxmax = (thickness/2.)*(wmax/zdel);
503 double xtmp = (
xmax + dxmax);
504 double ymax = std::sqrt(rmax*rmax - xtmp*xtmp);
523 double zmax,
double rmax)
const
531 plane.
m_d = -plane.
m_n.dot(pmin);
541 double zmax,
double rmax,
544 GeoThreeVector pbot(std::min(corners[0].
x(), corners[1].
x()), corners[0].
y(), 0);
545 GeoThreeVector ptop(std::min(corners[2].
x(), corners[3].
x()), corners[3].
y(), 0);
548 double d = v.x()*pbot.y() - v.y()*pbot.x();
549 double r = ptop.norm();
550 double l = std::sqrt(
r*
r - d*d);
551 double wmin = std::sqrt(rmin*rmin - d*d);
552 double wmax = std::sqrt(rmax*rmax - d*d);
553 double ymin = ptop.y() - v.y()*(l - wmin);
554 double ymax = ptop.y() - v.y()*(l - wmax);
558 v = (pmax - pmin).normalized();
562 plane.
m_d = -plane.
m_n.dot(pmin);
575 double d1 = plane.
m_n.dot(p1) + plane.
m_d;
576 double d2 = plane.
m_n.dot(p2) + plane.
m_d;
577 return (d2*p1 - d1*p2)/(d2 - d1);
591 double pz1,
double pr1min,
double pr1max,
592 double pz2,
double pr2min,
double pr2max)
const
594 double z1 = pz1, r1min = pr1min, r1max = pr1max;
595 double z2 = pz2, r2min = pr2min, r2max = pr2max;
599 r1min -= (r2min - r1min);
600 r1max -= (r2max - r1max);
605 r2min += (r2min - r1min);
606 r2max += (r2max - r1max);
610 std::vector<GeoThreeVector> v3(8);
611 double kx = (icase == 2) ? 1 : -1;
614 for (
int i = 0; i < 8; ++i)
616 v3[i] =
GeoThreeVector(kx*corners[i].
x(), corners[i].
y(), corners[i].
z() + (z1 + z2)/2.);
644 v3[0] = (v3[0] + v3[4])/2.;
645 v3[1] = (v3[1] + v3[5])/2.;
646 v3[2] = (v3[2] + v3[6])/2.;
647 v3[3] = (v3[3] + v3[7])/2.;
652 v3[4] = (v3[0] + v3[4])/2.;
653 v3[5] = (v3[1] + v3[5])/2.;
654 v3[6] = (v3[2] + v3[6])/2.;
655 v3[7] = (v3[3] + v3[7])/2.;
667 std::vector<GeoTwoVector> v2(8);
668 for (
int i = 0; i < 8; i += 2)
670 double xmid = (v3[i + 1].x() + v3[i].
x())/2.;
671 double xdel = (v3[i + 1].x() - v3[i].
x())*xscale/2.;
675 return new GeoGenericTrap((pz2 - pz1)/2., v2);
692 dz, 0.*SI::deg, 360.*SI::deg);
712 dz, 0.*SI::deg, 360.*SI::deg);
725 double innerLipPosition1,
726 double innerLipLength2,
727 double innerLipPosition2)
729 double dx, dy, dz, xoffset, yoffset, zoffset;
736 dy = 0.5*innerLipLength1;
739 solid =
new GeoBox(dx, dy, dz);
752 solid =
new GeoBox(dx, dy, dz);
765 dy = 0.5*innerLipLength2;
768 solid =
new GeoBox(dx, dy, dz);
781 solid =
new GeoBox(dx, dy, dz);
798 double outerLipPosition1,
799 double outerLipLength2,
800 double outerLipPosition2)
802 double dx, dy, dz, xoffset, yoffset, zoffset;
809 dy = 0.5*outerLipLength1;
812 solid =
new GeoBox(dx, dy, dz);
825 solid =
new GeoBox(dx, dy, dz);
838 dy = 0.5*outerLipLength2;
841 solid =
new GeoBox(dx, dy, dz);
854 solid =
new GeoBox(dx, dy, dz);
879 int icase = (iblade%2 == 0) ? 2 : 3;
880 if (iblade == 1) icase = 1;
904 solid =
constructBlade(icase, innerElectrodeCorners, 1., z1, r1min, r1max, z2, r2min, r2max);
927 int icase = (iblade%2 == 0) ? 2 : 3;
928 if (iblade == 1) icase = 1;
953 solid =
constructBlade(icase, outerElectrodeCorners, 1., z1, r1min, r1max, z2, r2min, r2max);
994 if (!makeSlices)
return;
1011 if (!makeSlices)
return;
1033 GeoPhysVol* mother =
nullptr;
1036 for (
int iphi = 0; iphi < nphi; ++iphi)
1038 GeoTrf::RotateZ3D rotation(dphi*iphi - SI::halfpi);
1039 int copyNo = iphi + 1;
1044 if (makeSlices || makeSectors)
1049 GeoTrf::Translate3D translation(
x,
y,
z);
1050 mother->add(
new GeoIdentifierTag(copyNo));
1051 mother->add(
new GeoTransform(rotation*translation));
1059 GeoTrf::Translate3D translation(
x,
y,
z);
1061 m_innerWheel->add(
new GeoTransform(rotation*translation));
1068 for (
int iphi = 0; iphi < nphi; ++iphi)
1070 GeoTrf::RotateZ3D rotation(dphi*(iphi+0.5) - SI::halfpi);
1071 int copyNo = iphi + 1;
1076 if (makeSlices || makeSectors)
1081 GeoTrf::Translate3D translation(
x,
y,
z);
1082 mother->add(
new GeoIdentifierTag(copyNo));
1083 mother->add(
new GeoTransform(rotation*translation));
1091 GeoTrf::Translate3D translation(
x,
y,
z);
1093 m_innerWheel->add(
new GeoTransform(rotation*translation));
1111 GeoPhysVol* mother =
nullptr;
1114 for (
int iphi = 0; iphi < nphi; ++iphi)
1116 GeoTrf::RotateZ3D rotation(dphi*iphi - SI::halfpi);
1117 int copyNo = iphi + 1;
1122 if (makeSlices || makeSectors)
1127 GeoTrf::Translate3D translation(
x,
y,
z);
1128 mother->add(
new GeoIdentifierTag(copyNo));
1129 mother->add(
new GeoTransform(rotation*translation));
1137 GeoTrf::Translate3D translation(
x,
y,
z);
1139 m_outerWheel->add(
new GeoTransform(rotation*translation));
1146 for (
int iphi = 0; iphi < nphi; ++iphi)
1148 GeoTrf::RotateZ3D rotation(dphi*(iphi+0.5) - SI::halfpi);
1149 int copyNo = iphi + 1;
1154 if (makeSlices || makeSectors)
1159 GeoTrf::Translate3D translation(
x,
y,
z);
1160 mother->add(
new GeoIdentifierTag(copyNo));
1161 mother->add(
new GeoTransform(rotation*translation));
1169 GeoTrf::Translate3D translation(
x,
y,
z);
1171 m_outerWheel->add(
new GeoTransform(rotation*translation));
1185 bool makeSectors =
false;
1186 int innerNoSectors = 0;
1193 double innerUncutBladeWidthMin, innerUncutBladeWidthMax;
1194 double innerLipLength1, innerLipPosition1;
1195 double innerLipLength2, innerLipPosition2;
1197 innerLipLength1, innerLipPosition1,
1198 innerLipLength2, innerLipPosition2);
1208 double wmin, wmax, thickness, rmin, rmax, zdel;
1212 wmin = innerUncutBladeWidthMin;
1213 wmax = innerUncutBladeWidthMax;
1218 getBladeCorners(wmin, wmax, thickness, rmin, rmax, zdel, innerCorners);
1223 getBladeCorners(wmin, wmax, thickness, rmin, rmax, zdel, innerElectrodeCorners);
1233 constructInnerLips(innerLipLength1, innerLipPosition1, innerLipLength2, innerLipPosition2);
1259 bool makeSectors =
false;
1260 int outerNoSectors = 0;
1267 double outerUncutBladeWidthMin, outerUncutBladeWidthMax;
1268 double outerLipLength1, outerLipPosition1;
1269 double outerLipLength2, outerLipPosition2;
1271 outerLipLength1, outerLipPosition1,
1272 outerLipLength2, outerLipPosition2);
1282 double wmin, wmax, thickness, rmin, rmax, zdel;
1286 wmin = outerUncutBladeWidthMin;
1287 wmax = outerUncutBladeWidthMax;
1292 getBladeCorners(wmin, wmax, thickness, rmin, rmax, zdel, outerCorners);
1297 getBladeCorners(wmin, wmax, thickness, rmin, rmax, zdel, outerElectrodeCorners);
1307 constructOuterLips(outerLipLength1, outerLipPosition1, outerLipLength2, outerLipPosition2);
Declaration of EMECAccordionConstruction class.
GeoTrf::Vector3D GeoThreeVector
GeoTrf::Vector2D GeoTwoVector
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
static std::map< double, LArWheelSliceSolid * > solid
This is a helper class to query the version tags from GeoModelSvc and determine the appropriate tag a...
const std::string & tag() const
Return version tag.
const std::string & node() const
Return the version node.
virtual unsigned int size() const =0
void constructInnerLips(double innerLipLength1, double innerLipPosition1, double innerLipLength2, double innerLipPosition2)
void constructInnerWheelStructure(bool makeSlices=true)
double m_innerElectrodeThickness
std::array< GeoPhysVol *, s_innerNoBlades > m_innerElectrode
GeoShape * constructBlade(int icase, const GeoThreeVector corners[8], double xscale, double pz1, double pr1min, double pr1max, double pz2, double pr2min, double pr2max) const
std::string m_nameInnerWheel
static constexpr int s_outerNoBlades
std::array< double, s_outerNoBlades+1 > m_outerWheelRmin
std::array< double, 3 > m_rMaxOuter
std::array< GeoPhysVol *, s_innerNoBlades > m_innerSector
double m_innerGlueThickness
std::array< GeoPhysVol *, s_outerNoBlades > m_outerGlue
double m_innerSteelThickness
void getBladeCorners(double wmin, double wmax, double thickness, double rmin, double rmax, double zdel, GeoThreeVector corners[8]) const
const GeoMaterial * m_materialLead
std::array< double, s_innerNoBlades+1 > m_innerWheelRmax
double m_outerSteelThickness
double m_outerWaveZoneWidth
double m_innerAbsorberThickness
void constructOuterLips(double outerLipLength1, double outerLipPosition1, double outerLipLength2, double outerLipPosition2)
std::array< GeoThreeVector, s_outerNoBlades > m_outerAbsorberOffset
void getOuterAbsorberData(double &wmin, double &wmax, double &llip1, double &ylip1, double &llip2, double &ylip2) const
std::array< double, s_innerNoBlades+1 > m_innerWheelRmin
void placeOuterAccordion(int outerNoSectors, bool makeSlices, bool makeSectors)
double m_innerWheelRminIncrement
std::array< GeoThreeVector, s_innerNoBlades > m_innerAbsorberOffset
void placeInnerSlices(bool makeSlices)
GeoFullPhysVol * m_outerWheel
GeoFullPhysVol * m_innerWheel
GeoThreeVector IntersectionPoint(const GeoThreeVector &p1, const GeoThreeVector &p2, const CutPlane &plane) const
std::array< double, 2 > m_outerWheelRminIncrement
std::array< double, 2 > m_rMaxInner
void placeOuterSlices(bool makeSlices)
void constructOuterBlades(const GeoThreeVector outerCorners[8], const GeoThreeVector outerElectrodeCorners[8])
void setInnerWheelSlices()
std::array< GeoPhysVol *, s_innerNoBlades > m_innerSlice
std::array< GeoPhysVol *, s_innerNoBlades > m_innerGlue
const GeoMaterial * m_materialKapton
void getInnerAbsorberData(double &wmin, double &wmax, double &llip1, double &ylip1, double &llip2, double &ylip2) const
std::array< double, 2 > m_zWheelInner
std::array< double, s_outerNoBlades+1 > m_outerWheelZ
std::array< double, 3 > m_rMinOuter
std::array< GeoPhysVol *, s_outerNoBlades > m_outerSector
std::string m_nameSuffix[s_outerNoBlades]
std::array< GeoThreeVector, s_innerNoBlades > m_innerSliceOffset
void setInnerWheel(GeoFullPhysVol *innerWheel)
std::string m_nameOuterWheel
std::array< double, 2 > m_outerWheelRmaxIncrement
double m_outerQuaterWaveWidth
std::array< double, 2 > m_rMinInner
std::array< GeoThreeVector, s_innerNoBlades > m_innerElectrodeOffset
double m_outerLeadThickness
std::array< GeoPhysVol *, s_outerNoBlades > m_outerLead
void setOuterWheel(GeoFullPhysVol *outerWheel)
std::array< GeoPhysVol *, s_outerNoBlades > m_outerSlice
const GeoMaterial * m_materialGlue
void setOuterWheelSlices()
std::array< GeoPhysVol *, s_innerNoBlades > m_innerLead
double m_innerWaveZoneWidth
double m_innerQuaterWaveWidth
const GeoMaterial * m_materialSteel
std::array< GeoThreeVector, s_outerNoBlades > m_outerElectrodeOffset
void constructOuterSlices()
CutPlane getTopCutPlane(double zmin, double rmin, double zmax, double rmax, const GeoThreeVector corners[8]) const
std::array< GeoPhysVol *, s_outerNoBlades > m_outerAbsorber
std::array< GeoThreeVector, s_outerNoBlades > m_outerSliceOffset
std::array< GeoPhysVol *, s_innerNoBlades > m_innerAbsorber
double m_outerHalfWaveWidth
void placeInnerAccordion(int innerNoSectors, bool makeSlices, bool makeSectors)
std::string m_nameAbsorber
void setWheelParameters()
std::string m_nameElectrode
double m_outerAbsorberThickness
double m_outerElectrodeThickness
static constexpr int s_innerNoBlades
std::array< GeoPhysVol *, s_outerNoBlades > m_outerElectrode
double m_innerLeadThickness
void constructInnerSlices()
void setMaterial(const std::string &name, const GeoMaterial *material)
void constructOuterWheelStructure(bool makeSlices=true)
const GeoMaterial * m_materialLiquidArgon
void placeOuterGlueAndLead()
void constructInnerBlades(const GeoThreeVector innerCorners[8], const GeoThreeVector innerElectrodeCorners[8])
void placeInnerGlueAndLead()
double m_outerGlueThickness
CutPlane getBottomCutPlane(double zmin, double rmin, double zmax, double rmax) const
double m_innerWheelRmaxIncrement
double m_innerHalfWaveWidth
std::array< double, 3 > m_zWheelOuter
std::array< double, s_innerNoBlades+1 > m_innerWheelZ
std::array< double, s_outerNoBlades+1 > m_outerWheelRmax
void swap(ElementLinkVector< DOBJ > &lhs, ElementLinkVector< DOBJ > &rhs)
hold the test vectors and ease the comparison