ATLAS Offline Software
Loading...
Searching...
No Matches
EMBAccordionDetails.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2025 CERN for the benefit of the ATLAS collaboration
3*/
4
12#include "GaudiKernel/ISvcLocator.h"
13#include "GaudiKernel/Bootstrap.h"
14#include "GaudiKernel/PhysicalConstants.h"
15#include "GaudiKernel/ServiceHandle.h"
17#include <cmath>
18
20
21public:
25 int phiGap(double radius, double xhit, double yhit) const;
26
30 void getRPhi();
31
35 double phi0(double radius) const;
36
40 double Distance_Ele(const double &x, const double &y,
41 const int &PhiC, int &Num_Straight, const int &Num_Coude,
42 double &xl);
46 double Distance_Abs(const double &x, const double &y,
47 const int &nabs, const int &Num_Straight, const int &Num_Coude);
48
49 double gam0;
50 double Rmin;
51 double Rmax;
52 double dR;
53 double Rphi[5000];
54 int NRphi;
55 int Nbrt;
56 int Nbrt1;
57 double rint_eleFib ; //2.78
58 double delta[15]; // zig-zag angles
59 double rc[15] ; // R and
60 double phic[15] ; // phi positions of center of fold for first absorber
61 double xc[15]; // corresponding x,y values
62 double yc[15];
65 double zMinBarrel;
66 double zMaxBarrel;
68 int NCellTot; // either 64 or 1024 for TestBeam or Atlas
69 int NCellMax; // 1024
70
73
74 ServiceHandle<StoreGateSvc> detStore{"DetectorStore","DetectorStore"};
75};
76
78{
79 const double dl=0.001;
80 const double inv_dl = 1 / dl;
81 double cenx[15],ceny[15];
82 std::vector<double> sum1(5000);
83 std::vector<double> sumx(5000);
84 NRphi=5000;
85 Rmin=1500.;
86 dR=0.10;
87 Rmax=0.;
88
89 const double rint= rint_eleFib;
90 const double inv_rint = 1. / rint;
91 const double dt=dl * inv_rint;
92 const double inv_dt = 1. / dt;
93
94 for (int i=0;i<NRphi;i++) {
95 sum1[i]=0.;
96 sumx[i]=0.;
97 }
98 for (int i=0;i<15;i++) {
99 cenx[i]=rc[i]*cos(phic[i]);
100 ceny[i]=rc[i]*sin(phic[i]);
101 }
102
103 for (int i=0; i<15; i++) {
104
105// fold
106 double phi0,phi1;
107 if (i==0) {
108 phi0=-M_PI/2.;
109 phi1=-M_PI/2.+delta[0];
110 }
111 else if (i==14) {
112 phi0=-M_PI+delta[13];
113 phi1=-M_PI/2.;
114 }
115 else {
116 if (i%2==1) {
117 phi0=delta[i];
118 phi1=M_PI-delta[i-1];
119 }
120 else {
121 phi0=-M_PI+delta[i-1];
122 phi1=-delta[i];
123 }
124 }
125 int nstep=int((phi1-phi0) * inv_dt)+1;
126 for (int ii=0;ii<nstep;ii++) {
127 double phi=phi0+dt*((double)ii);
128 double x=cenx[i]+rint*cos(phi);
129 double y=ceny[i]+rint*sin(phi);
130 double radius=sqrt(x*x+y*y);
131 if (radius>Rmax) Rmax=radius;
132 double phid=atan(y/x);
133 int ir=((int) ((radius-Rmin)/dR) );
134 if (ir>=0 && ir < NRphi) {
135 sum1[ir]+=1.;
136 sumx[ir]+=phid;
137 }
138 }
139
140// straight section
141 if (i<14) {
142 double dx=cenx[i+1]-cenx[i];
143 double dy=ceny[i+1]-ceny[i];
144 double along=dx*dx+dy*dy-4.*rint*rint;
145 along=sqrt(along);
146 double x0=0.5*(cenx[i+1]+cenx[i]);
147 double y0=0.5*(ceny[i+1]+ceny[i]);
148 double phi;
149 if (i%2==0) phi=M_PI/2-delta[i];
150 else phi=-M_PI/2.+delta[i];
151 double x1=x0-0.5*along*cos(phi);
152 double y1=y0-0.5*along*sin(phi);
153 int nstep=int(along * inv_dl)+1;
154 for (int ii=0;ii<nstep;ii++) {
155 double x=x1+dl*((double)ii)*cos(phi);
156 double y=y1+dl*((double)ii)*sin(phi);
157 double radius=sqrt(x*x+y*y);
158 if (radius>Rmax) Rmax=radius;
159 double phid=atan(y/x);
160 int ir=((int) ((radius-Rmin)/dR) );
161 if (ir>=0 && ir < NRphi) {
162 sum1[ir]+=1.;
163 sumx[ir]+=phid;
164 }
165 }
166 }
167 }
168 for (int i=0; i<NRphi; i++) {
169 if (sum1[i]>0) {
170 Rphi[i]=sumx[i]/sum1[i];
171 }
172 else Rphi[i]=0.;
173 }
174}
175
176
177// ======================================================================================
178// compute number (0 to 1023) of closest electrode according to nominal
179// accordion geometry
180int EMBAccordionDetails::Clockwork::phiGap(double radius, double xhit, const double yhit) const
181{
182 const double m2pi = 2.0*Gaudi::Units::pi;
183 double phi_0=phi0(radius)+gam0; // from -M_PI to M_PI
184 double phi_hit=atan2(yhit,xhit); // from -M_PI to M_PI
185 double dphi=phi_hit-phi_0;
186// bring back to 0-2pi
187 if (dphi<0) dphi=dphi+m2pi;
188 if (dphi>=m2pi) dphi=dphi-m2pi;
189 dphi=dphi*(1024/m2pi);
190 int ngap=((int) dphi);
191 return ngap;
192}
193
194
195
197 : m_c(new Clockwork())
198{
199 ISvcLocator *svcLocator = Gaudi::svcLocator();
200
201 SmartIF<IGeoModelSvc> geoModel{svcLocator->service("GeoModelSvc")};
202 if(!geoModel.isValid())
203 throw std::runtime_error("Error in HECDetectorManager, cannot access GeoModelSvc");
204
205 SmartIF<IGeoDbTagSvc> geoDbTagSvc{svcLocator->service("GeoDbTagSvc")};
206 if(!geoDbTagSvc.isValid())
207 throw std::runtime_error("Error in HECDetectorManager, cannot access GeoDbTagSvc");
208
209 SmartIF<IRDBAccessSvc> rdbAccess{svcLocator->service(geoDbTagSvc->getParamSvcName())};
210 if(!rdbAccess.isValid())
211 throw std::runtime_error("Error in HECDetectorManager, cannot access RDBAccessSvc");
212
213 if(m_c->detStore.retrieve().isFailure())
214 throw std::runtime_error("Error in HECDetectorManager, cannot access DetectorStore");
215
216 std::string detectorKey, detectorNode;
217
218 if(geoDbTagSvc->getSqliteReader()==nullptr) {
219 std::string AtlasVersion = geoModel->atlasVersion();
220 std::string LArVersion = geoModel->LAr_VersionOverride();
221
222 detectorKey = LArVersion.empty() ? AtlasVersion : LArVersion;
223 detectorNode = LArVersion.empty() ? "ATLAS" : "LAr";
224 }
225
226 IRDBRecordset_ptr barrelGeometry = rdbAccess->getRecordsetPtr("BarrelGeometry",detectorKey,detectorNode);
227 if (barrelGeometry->size()==0) {
228 throw std::runtime_error("Cannot find the BarrelGeometry Table");
229 }
230
231 IRDBRecordset_ptr barrelLongDiv = rdbAccess->getRecordsetPtr("BarrelLongDiv",detectorKey,detectorNode);
232 if (barrelLongDiv->size()==0) {
233 throw std::runtime_error("Cannot find the BarrelLongDiv Table");
234 }
235
236 // number of straight sections (should be 14)
237 m_c->Nbrt = (*barrelGeometry)[0]->getInt("NBRT");
238 // Number of ZIGs + 1 i.e. 15 = number of folds
239 m_c->Nbrt1 = m_c->Nbrt + 1;
240 // phi of first absorber
241 m_c->gam0 = (*barrelGeometry)[0]->getDouble("PHIFIRST");
242 // radius of curvature of neutral fiber in the folds
243 m_c->rint_eleFib = (*barrelGeometry)[0]->getDouble("RINT")*Gaudi::Units::cm;
244
245 // r,phi positions of the centre of the folds (nominal geometry)
246 for (int idat = 0; idat < m_c->Nbrt1 ; idat++)
247 {
248 m_c->rc[idat] = (*barrelGeometry)[0]->getDouble("RHOCEN",idat)*Gaudi::Units::cm;
249 m_c->phic[idat] = (*barrelGeometry)[0]->getDouble("PHICEN",idat)*Gaudi::Units::deg;
250 m_c->delta[idat] = (*barrelGeometry)[0]->getDouble("DELTA",idat)*Gaudi::Units::deg;
251 m_c->xc[idat] = m_c->rc[idat]*cos(m_c->phic[idat]);
252 m_c->yc[idat] = m_c->rc[idat]*sin(m_c->phic[idat]);
253 }
254 //
255 m_c->rMinAccordion = (*barrelGeometry)[0]->getDouble("RIN_AC")*Gaudi::Units::cm;
256 m_c->rMaxAccordion = (*barrelGeometry)[0]->getDouble("ROUT_AC")*Gaudi::Units::cm;
257 m_c->etaMaxBarrel = (*barrelGeometry)[0]->getDouble("ETACUT");
258 m_c->zMinBarrel = (*barrelLongDiv)[0]->getDouble("ZMAXACT")*Gaudi::Units::cm;
259 m_c->zMaxBarrel = (*barrelLongDiv)[0]->getDouble("ZMINACT")*Gaudi::Units::cm;
260 // === GU 11/06/2003 total number of cells in phi
261 // to distinguish 1 module (testbeam case) from full Atlas
262 m_c->NCellTot = (*barrelGeometry)[0]->getInt("NCELMX");
263 m_c->NCellMax=1024;
264
265 //====================================================
266
267 m_c->getRPhi();
268
269}
270
274
276 return m_c->gam0;
277}
278
279
280double EMBAccordionDetails::Clockwork::phi0(double radius) const
281{
282 int ir;
283 if (radius < Rmin) ir=0;
284 else {
285 if (radius > Rmax) radius=Rmax-0.0001;
286 ir=((int) ((radius-Rmin)/dR) );
287 }
288 return Rphi[ir];
289}
290
291
293 if (m_c->absorberStraightSection==nullptr) {
294 const GeoStraightAccSection* sa = nullptr;
295
296 StatusCode status = m_c->detStore->retrieve(sa,"STRAIGHTABSORBERS");
297 if (status != StatusCode::SUCCESS) throw std::runtime_error ("Cannot locate Straight Absorbers");
298
299 m_c->absorberStraightSection = sa;
300
301 }
302 return m_c->absorberStraightSection;
303
304}
305
306
308 if (m_c->electrodeStraightSection==nullptr) {
309 const GeoStraightAccSection* sa = nullptr;
310
311 StatusCode status = m_c->detStore->retrieve(sa,"STRAIGHTELECTRODES");
312 if (status != StatusCode::SUCCESS) throw std::runtime_error ("Cannot locate Straight Electrodes");
313
314 m_c->electrodeStraightSection=sa;
315
316 }
317 return m_c->electrodeStraightSection;
318
319}
320
321
322
323//======================================================================================
324//
325// Here INTRINSIC Distance_to_electrode determination (G.P.)
326//
327// This retuns an ALGEBRICDistEle value, the distance from electrode
328//neutral fiber TOWARDS the Sub_Step in LAr (measured on a local perpendicular
329//vector unit oriented upwards i.e. following increasing Phi values).
330//
331// This is done in THE INTRINSIC LOCAL Z > 0. half_barrel part ("stac_phys1")
332//
333// inputs: xhit,yhit = x,y positions in local half barrel
334// PhiCell = electrode number in phi (0 to 1023 for Atlas case)
335// Num_Straight = number (0 to 13) of the straight section
336// Num_Coude = number (0 to 14) of closest fold
337//
338// output: Function value = algebric distance to electrode
339// xl = normalized lenght along electrode straight section (between +-1)
340
341#ifdef READY
342double EMBAccordionDetails::Clockwork::Distance_Ele(const double & xhit,
343 const double &yhit, const int &PhiCell, int &Num_Straight,
344 const int &Num_Coude, double &xl)
345{
346 double dx, dy, dr;
347 double DistEle = 0.;
348//
349// FrameWork is consistent with the one used to PhiCell determination
350// e.g. it assumes HERE to be the LOCAL one of "stac_phys1",
351// (mother of ACCordion volumes) from which Z> 0. and Z < 0. half_barrel
352// parts are then defined.
353//
354// One needs POINTERS to Electrode neutral fibers
355// either for straight parts or for folds
356//
357// Fold Center ccoordinates
358 double Xc[2];
359 Xc[0] = m_coudeelec->XCentCoude(Num_Coude, PhiCell);
360 Xc[1] = m_coudeelec->YCentCoude(Num_Coude, PhiCell);
361 double radfold = sqrt(Xc[0]*Xc[0]+Xc[1]*Xc[1]);
362 double radhit = sqrt(xhit*xhit+yhit*yhit);
363
364// check if the assumed straight number is the correct one
365// (this can be wrong when we are close to a fold and there is sagging)
366 if (Num_Coude == Num_Straight && radhit <radfold) {
367 if (Num_Straight>0) Num_Straight = Num_Straight-1;
368// std::cout << "radhit,radfold " << radhit << " " << radfold << " change straight by +1" << std::endl;
369 }
370 if (Num_Coude == (Num_Straight+1) && radhit > radfold) {
371 if (Num_Straight<12) Num_Straight = Num_Straight+1;
372// std::cout << "radhit,radfold " << radhit << " " << radfold << " change straight by -1" << std::endl;
373 }
374
375// u unit 2D_Vector along straight part of the electrode neutral fiber
376 double u[2];
377 u[0] = m_electrode->Cosu(Num_Straight, PhiCell);
378 u[1] = m_electrode->Sinu(Num_Straight, PhiCell);
379// Middle m_coordinates of this straight part of the electrode neutral fiber
380 double Xm[2];
381 Xm[0] = m_electrode->XCentEle(Num_Straight, PhiCell);
382 Xm[1] = m_electrode->YCentEle(Num_Straight, PhiCell);
383// m_Hit Vector components
384 dx = xhit - Xm[0]; dy = yhit - Xm[1];
385
386// First compute algebric distance m_hit (2D) the 2D_projection of the
387// m_Hit Vector on this electrode neutral fiber.
388 double m_hit = dx*u[0] + dy*u[1];
389
390//
391// Flat of Fold Region ?
392//
393 double Half_Elec;
394 Half_Elec = m_electrode->HalfLength(Num_Straight,PhiCell);
395
396 if(fabs(m_hit) < Half_Elec) {
397// Flat Region
398 DistEle = u[0]*dy - u[1]*dx;
399 xl=m_hit/Half_Elec;
400 }
401 else {
402// Fold region
403// c_Hit Vector components and its length
404 dx = xhit - Xc[0]; dy = yhit - Xc[1]; dr = sqrt( dx*dx + dy*dy);
405 DistEle = (Num_Coude%2 == 0) ? (rint_eleFib-dr) : (dr - rint_eleFib);
406 if (Num_Coude==Num_Straight) xl=-1.;
407 else xl=+1;
408 } // end of Fold Regions
409
410 return DistEle;
411
412} // end of the function Distance_Ele
413
414#endif
#define M_PI
Scalar phi() const
phi method
Definition of the abstract IRDBAccessSvc interface.
std::shared_ptr< IRDBRecordset > IRDBRecordset_ptr
Definition of the abstract IRDBRecord interface.
Definition of the abstract IRDBRecordset interface.
#define y
#define x
ServiceHandle< StoreGateSvc > detStore
double Distance_Ele(const double &x, const double &y, const int &PhiC, int &Num_Straight, const int &Num_Coude, double &xl)
Compute the distance to the electrode.
double phi0(double radius) const
phi of first absorber as function of radius for nominal accordion geometry (before sagging).
const GeoStraightAccSection * electrodeStraightSection
double Distance_Abs(const double &x, const double &y, const int &nabs, const int &Num_Straight, const int &Num_Coude)
Compute the distance to the absorber.
void getRPhi()
initialization routine
int phiGap(double radius, double xhit, double yhit) const
compute number (0 to 1023) of closest electrode according to nominal accordion geometry
const GeoStraightAccSection * absorberStraightSection
const GeoStraightAccSection * getElectrodeSections() const
Electrode position details:
const GeoStraightAccSection * getAbsorberSections() const
Absorber position details:
double phiFirstAbsorber() const
Phi of the first absorber.
Record of All Electrode Straight Pieces.
virtual unsigned int size() const =0
int ir
counter of the current depth
Definition fastadd.cxx:49
@ u
Enums for curvilinear frames.
Definition ParamDefs.h:77