ATLAS Offline Software
Loading...
Searching...
No Matches
LArFanSection.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2023 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include "LArWheelSolid.h"
6#include "LArFanSection.h"
8#include <iostream>
9#include <cassert>
10
11void LArFanSections::print(void) const
12{
13 std::cout << "LArFanSections at " << this << std::endl
14 << "Amin = " << Amin << ", Amax = " << Amax
15 << std::endl
16 << "Bmin = " << Bmin << ", Bmax = " << Bmax << std::endl
17 << "xmin = " << xmin << ", xmax = " << xmax
18 << "Cflat2 = " << Cflat2 << std::endl;
19}
20
22 G4double ri1, G4double ri2, G4double ro1, G4double ro2,
23 G4double Xmax, G4double z1, G4double z2
24)
25 : Amin ((ri2 - ri1) / (z2 - z1)),
26 Amax ((ro2 - ro1) / (z2 - z1)),
27 Bmin (ri1 - Amin * z1),
28 Bmax (ro1 - Amax * z1),
29 Amin2 (Amin*Amin),
30 Amax2 (Amax*Amax),
31 Bmin2 (Bmin*Bmin),
32 Bmax2 (Bmax*Bmax),
33 xmin (-Xmax),
34 xmax (Xmax),
35 Cflat2 (ro2*ro2),
36 ABmax (Amax*Bmax),
38{
39}
40
42 G4double &t1, G4double A, G4double B, G4double C, G4bool out
43) const
44{
45 // G4bool out is to be set true if the point is surface-outside
46 // then have to discard first intersection
47
48 const G4double D = B*B - A*C;
49 LWSDBG(8, std::cout << "check D=" << D << " out=" << out << std::endl);
50 if(D < 0.) return false;
51 G4double t2 = 0.;
52 if(A == 0) {
53 if(B == 0) {
54 LWSDBG(8, std::cout << "Case A=B=0" << std::endl);
55 return false;
56 }
57 t1= -C / (2 * B);
58 LWSDBG(8, std::cout << "t1=" << t1 << " - only one solution" << std::endl);
59 t2 = t1;
60 } else {
61 const G4double D1 = sqrt(D);
62 const G4double inv_A = 1.0 / A;
63 t1 = (-B + D1) * inv_A;
64 t2 = (-B - D1) * inv_A;
65 LWSDBG(8, std::cout << "t1=" << t1 << " t2=" << t2 << std::endl);
66 }
67
68 if(t1 > 0.){
69 if(t2 > 0.){
70 if(out){
71 if(t2 > t1) t1 = t2;
72 } else {
73 if(t2 < t1) t1 = t2;
74 }
75 } else if(t2 < 0.){
76 if(out) return false;
77 } else { // answer is t1
78 }
79 } else if(t1 < 0.){
80 if(t2 > 0.){
81 if(out) return false;
82 t1 = t2;
83 } else if(t2 < 0.){
84 return false;
85 } else {
86 return false;
87 }
88 } else {
89 if(t2 > 0.){
90 t1 = t2;
91 } else if(t2 < 0.){
92 return false;
93 } else {
94 return false;
95 }
96 }
97 return true;
98}
99
100// p must be not outside of the "FanBound"
101// if track crosses inner cone in valid (z, x) interval,
102// returns true, sets q to the cross point
104 const G4ThreeVector &p, const G4ThreeVector &v,
105 G4ThreeVector &q) const
106{
107 LWSDBG(7, std::cout << "fcl" << std::endl);
108 const G4double A = v.perp2() - m_fs->Amin2*v.z()*v.z();
109 const G4double B = p.x()*v.x() + p.y()*v.y()
110 - m_fs->Amin2*p.z()*v.z() - m_fs->ABmin*v.z();
111 const G4double C = p.perp2() - m_fs->Amin2*p.z()*p.z()
112 - 2.*m_fs->ABmin*p.z() - m_fs->Bmin2;
113
114 G4double t1(0.0);
115 const G4double out_dist = m_fs->Amin*p.z() + m_fs->Bmin - p.perp();
116 LWSDBG(8, std::cout << "fcl out_dist(p)=" << out_dist << " Tolerance=" << s_Tolerance << std::endl);
117 const G4bool out = out_dist >= 0.0;
118 if(check_D(t1, A, B, C, out)){
119 const G4double zz1 = p.z() + v.z() * t1;
120 if(zz1 < m_Zsect.front() || zz1 > m_Zsect.back()){
121 LWSDBG(8, std::cout << "fcl out on Z " << zz1 << std::endl);
122 return false;
123 }
124 const G4double xx1 = p.x() + v.x() * t1;
125 if(xx1 < m_fs->xmin || xx1 > m_fs->xmax){
126 LWSDBG(8, std::cout << "fcl out on X " << xx1 << std::endl);
127 return false;
128 }
129 if(out_dist == 0.){ // entry point is exactly on the cone
130 // here we got t1 > 0 from check_D, founded point seems to be in x and z ranges
131 // if the track leaves the surface, then the entry is the intersection,
132 // and the distance is 0
133 // if the track is on the surface, then there is no lower cone intersection
134
135 // estimate deviation of the track from the surface
136 // (exact calculations are too complicated)
137 const G4double xx2 = p.x() + v.x() * t1 * 0.5;
138 const G4double yy2 = p.y() + v.y() * t1 * 0.5;
139 const G4double dev = fabs(sqrt(xx2 *xx2 + yy2*yy2)
140 - m_fs->Amin*(p.z() + zz1)*0.5
141 - m_fs->Bmin);
142 if(dev < s_Tolerance){
143 LWSDBG(8, std::cout << "fcl on the surface" << std::endl);
144 return false;
145 } else {
146 LWSDBG(8, std::cout << "fcl out = in" << std::endl);
147 q = p;
148 return true;
149 }
150 }
151 q.setX(xx1);
152 q.setY(p.y() + v.y() * t1);
153 q.setZ(zz1);
154 LWSDBG(8, std::cout << "fcl got " << t1 << std::endl);
155 return true;
156 }
157 LWSDBG(8, std::cout << "fcl no intersection" << std::endl);
158 return false;
159}
160
161// p must be not outside of the "FanBound"
162// if track crosses outer cone in valid (z, x) interval,
163// returns true, adds to b the distance to the cross point,
164// sets q to the cross point
166 const G4ThreeVector &p, const G4ThreeVector &v,
167 G4ThreeVector &q) const
168{
169 LWSDBG(7, std::cout << "fcu" << std::endl);
170 G4double A = v.perp2();
171 G4double B = p.x()*v.x() + p.y()*v.y();
172 G4double C = p.perp2();
173
174 if(m_IsOuter){
175 const G4double &Af = A, &Bf = B;
176 const G4double Cf = C - m_fs->Cflat2;
177
178 G4double b1;
179 if(check_D(b1, Af, Bf, Cf, Cf >= 0.)){
180 const G4double zz1 = p.z() + v.z() * b1;
181 if(zz1 >= m_Zmid && zz1 <= m_Zsect.back()){
182 const G4double xx1 = p.x() + v.x() * b1;
183 if(xx1 < m_fs->xmin || xx1 > m_fs->xmax) return false;
184 q.setX(xx1);
185 q.setY(p.y() + v.y() * b1);
186 q.setZ(zz1);
187 return true;
188 }
189 }
190 LWSDBG(8, std::cout << "fcu no cyl intersection" << std::endl);
191 }
192
193 A -= m_fs->Amax2*v.z()*v.z();
194 B -= m_fs->Amax2*p.z()*v.z() + m_fs->ABmax*v.z();
195 C -= m_fs->Amax2*p.z()*p.z() + 2.*m_fs->ABmax*p.z() + m_fs->Bmax2;
196
197 G4double t1;
198 const G4bool out = m_fs->Amax*p.z() + m_fs->Bmax <= p.perp();
199 if(check_D(t1, A, B, C, out)){
200 const G4double zz1 = p.z() + v.z() * t1;
201 LWSDBG(8, std::cout << "fcu z = " << zz1 << ", lim: (" << m_Zsect.front() << ", " << m_Zmid << ")" << std::endl);
202 if(zz1 < m_Zsect.front() || zz1 > m_Zmid) return false;
203 const G4double xx1 = p.x() + v.x() * t1;
204 LWSDBG(8, std::cout << "fcu x = " << xx1 << ", lim: (" << m_fs->xmin << ", " << m_fs->xmax << ")" << std::endl);
205 if(xx1 < m_fs->xmin || xx1 > m_fs->xmax) return false;
206 q.setX(xx1);
207 q.setY(p.y() + v.y() * t1);
208 q.setZ(zz1);
209 return true;
210 }
211 LWSDBG(8, std::cout << "fcu no cone intersection" << std::endl);
212 return false;
213}
214
215/* p must be not outside "FanBound" */
217 const G4ThreeVector &p, const G4ThreeVector &v,
218 G4ThreeVector &q) const
219{
220 LWSDBG(6, std::cout << "in fep p" << MSG_VECTOR(p)<< ", v"<< MSG_VECTOR(v) << ", q" << MSG_VECTOR(q) << std::endl);
221
222/* by construction, cannot have true from both upper and lower */
223/* the only problem is the points on surface but "slightly outside" */
224/* fs_cross_* account for (x, z) range */
225// lower has to be checked first, since outer might find more distant
226// intersection in the acceptable (x, z) range
227 if(fs_cross_lower(p, v, q)) return ExitAtInner;
228 LWSDBG(6, std::cout << "after fs_cross_lower q" << MSG_VECTOR(q) << std::endl);
229 if(fs_cross_upper(p, v, q)) return ExitAtOuter;
230 LWSDBG(6, std::cout << "after fs_cross_upper q" << MSG_VECTOR(q) << std::endl);
231
233 G4double d;
234 if(v.x() > 0.) d = (m_fs->xmax - p.x()) / v.x();
235 else if(v.x() < 0.) d = (m_fs->xmin - p.x()) / v.x();
236 else d = kInfinity;
237
238 G4double dz;
239 FanBoundExit_t resultz = NoCross;
240 if(v.z() > 0.){
241 dz = (m_Zsect.back() - p.z()) / v.z();
242 resultz = ExitAtBack;
243 } else if(v.z() < 0.){
244 dz = (m_Zsect.front() - p.z()) / v.z();
245 resultz = ExitAtFront;
246 } else {
247 dz = kInfinity;
248 }
249 if(d > dz){
250 d = dz;
251 result = resultz;
252 }
253 q = p + v * d;
254 LWSDBG(7, std::cout << "fep side " << d << " " << result << " q" << MSG_VECTOR(q) << std::endl);
255 const G4double out_distlower = m_fs->Amin*q.z() + m_fs->Bmin - q.perp(); // > 0 - below lower cone
256 LWSDBG(7, std::cout << "fep out_distlower(q)=" << out_distlower << " Tolerance=" << s_Tolerance << std::endl);
257 if (out_distlower >= 0.0) {
258 // side intersection point is below lower cone
259 // initial point p was at exit boundary
260 q = p;
261 return NoCross;
262 }
263
264 if (m_IsOuter && q.z() >= m_Zmid && q.z() <= m_Zsect.back()+s_Tolerance && q.perp2() >= m_fs->Cflat2) {
265 // outside of upper cylinder
266 q = p;
267 return NoCross;
268 }
269 const G4double out_distupper = m_fs->Amax*q.z() + m_fs->Bmax - q.perp(); // < 0 - above upper cone
270 LWSDBG(7, std::cout << "fep out_distupper(q)=" << out_distupper << " Tolerance=" << s_Tolerance << std::endl);
271 if (out_distupper <= 0.0) {
272 // side intersection point is above upper cone
273 // initial point p was at exit boundary
274 q = p;
275 return NoCross;
276 }
277 assert((q - p).mag() < kInfinity);
278 return result;
279}
Scalar mag() const
mag method
#define LWSDBG(a, b)
void print(void) const
LArFanSections(G4double ri1, G4double ri2, G4double ro1, G4double ro2, G4double Xmax, G4double z1, G4double z2)
G4bool fs_cross_lower(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &q) const
static const G4double s_Tolerance
std::vector< G4double > m_Zsect
FanBoundExit_t find_exit_point(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &q) const
G4bool fs_cross_upper(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &q) const
LArFanSections * m_fs
G4bool check_D(G4double &b, G4double A, G4double B, G4double C, G4bool) const
struct color C
double xmin
Definition listroot.cxx:60
hold the test vectors and ease the comparison