ATLAS Offline Software
Loading...
Searching...
No Matches
LArWheelSolidDisToIn.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2022 CERN for the benefit of the ATLAS collaboration
3*/
4
5// DistanceToIn stuff for LArWheelSolid
6#include <cassert>
7#ifndef PORTABLE_LAR_SHAPE
9#else
10#endif
11#include "CLHEP/Units/PhysicalConstants.h"
12
14#include "LArWheelSolid.h"
15#include "LArFanSection.h"
16
17G4double LArWheelSolid::DistanceToIn(const G4ThreeVector &inputP) const
18{
19 LWSDBG(1, std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP) << std::endl);
20 if(m_BoundingShape->Inside(inputP) == kOutside) {
21 // here is an approximation - for the point outside m_BoundingShape
22 // the solid looks like a m_BoundingShape
23 // it's okay since the result could be underestimated
24 LWSDBG(2, std::cout << "Outside BS" << std::endl);
25 return m_BoundingShape->DistanceToIn(inputP);
26 }
27 G4ThreeVector p(inputP);
28
29 //
30 // DistanceToTheNearestFan:
31 // rotates point p to the localFan coordinates and returns fan number to out_fan_number parameter
32 // returns distance to fan as result
33 //
34
35 int p_fan = 0;
36 const G4double d = fabs(GetCalculator()->DistanceToTheNearestFan(p, p_fan));
37 if(d > m_FHTplusT){
38 const G4double result = d - m_FanHalfThickness;
39 LWSDBG(2, std::cout << "dti result = " << result << std::endl);
40 return result;
41 }
42 LWSDBG(2, std::cout << "already inside, return 0" << MSG_VECTOR(p) << std::endl);
43 return 0.;
44}
45
46G4double LArWheelSolid::DistanceToIn(const G4ThreeVector &inputP,
47 const G4ThreeVector &inputV) const
48{
49 LWSDBG(1, std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP)
50 << MSG_VECTOR(inputV) << std::endl);
51
52 G4double distance = 0.;
53 const EInside inside_BS = m_BoundingShape->Inside(inputP);
54 G4ThreeVector p(inputP);
55 if(inside_BS == kOutside) {
56 distance = m_BoundingShape->DistanceToIn(inputP, inputV);
57 if(distance == kInfinity) {
58 LWSDBG(2, std::cout << "Infinity distance to m_BoundingShape" << MSG_VECTOR(inputP) << MSG_VECTOR(inputV) << std::endl);
59 return kInfinity;
60 }
61 p += inputV * distance;
62 assert(m_BoundingShape->Inside(p) != kOutside);
63 LWSDBG(2, std::cout << "shift" << MSG_VECTOR(inputP) << std::endl);
64 }
65
66 const G4double phi0 = p.phi();
67 int p_fan = 0;
68 const G4double d = GetCalculator()->DistanceToTheNearestFan(p, p_fan);
69 if(fabs(d) < m_FHTminusT){
70 LWSDBG(2, std::cout << "already inside fan" << MSG_VECTOR(p) << std::endl);
71 // if initial point is on BS surface and inside fan volume it is a real surface
72 if(inside_BS == kSurface) {
73 LWSDBG(2, std::cout << "On BS surface" << std::endl);
74 return m_BoundingShape->DistanceToIn(inputP, inputV);
75 }
76 return distance;
77 }
78 G4ThreeVector v(inputV);
79 v.rotateZ(p.phi() - phi0);
80
81 const G4double d0 = distance_to_in(p, v, p_fan);
82 distance += d0;
83
84#ifdef DEBUG_LARWHEELSOLID
85 if(Verbose > 2){
86 if(Verbose > 3){
87 std::cout << MSG_VECTOR(inputP)
88 << " " << MSG_VECTOR(inputV) << std::endl;
89 }
90 std::cout << "dti: " << d0 << ", DTI: " << distance << std::endl;
91 }
92 if(Verbose > 3){
93 if(d0 < kInfinity){
94 G4ThreeVector p2 = inputP + inputV*distance;
95 EInside i = Inside(p2);
96 std::cout << "DTI hit at dist. " << distance << ", point "
97 << MSG_VECTOR(p2) << ", "
98 << inside(i) << std::endl;
99 } else {
100 std::cout << "got infinity from dti" << std::endl;
101 }
102 }
103#ifdef LWS_HARD_TEST_DTI
104 if(test_dti(inputP, inputV, distance)){
105 if(Verbose == 1){
106 std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP)
107 << MSG_VECTOR(inputV) << std::endl;
108 }
109 }
110 if(Verbose == 1){
111 std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP)
112 << MSG_VECTOR(inputV) << " " << distance << std::endl;
113 }
114#endif // ifdef LWS_HARD_TEST_DTI
115
116#endif // ifdef DEBUG_LARWHEELSOLID
117
118 return distance;
119}
120
121// This functions should be called in the case when we are sure that
122// points p (which sould be OUTSIDE of vertical fan) and out_point have
123// the surface of the vertical fan between them.
124// returns distance from point p to absorber surface
125// sets last parameter to the founded point
127 const G4ThreeVector &p, G4double dist_p, G4ThreeVector &B, int p_fan
128) const
129{
130 LWSDBG(6, std::cout << "iip from " << p << " to " << B
131 << " dir " << (B - p).unit()
132 << std::endl);
133
134 G4ThreeVector A, C, diff;
135 A = p;
136 G4double dist_c;
137 unsigned int niter = 0;
138 // assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(A)) > m_FHTplusT);
139 // assert(GetCalculator()->DistanceToTheNeutralFibre(A) == dist_p);
140 do {
141 C = A + B;
142 C *= 0.5;
143 dist_c = GetCalculator()->DistanceToTheNeutralFibre(C, p_fan);
144 if(dist_c * dist_p < 0. || fabs(dist_c) < m_FHTminusT){
145 B = C;
146 } else {
147 A = C;
148 }
149 niter ++;
150 diff = A - B;
151 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
152 assert(niter < s_IterationsLimit);
153 assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(B, p_fan)) < m_FHTplusT);
154 diff = p - B;
155 LWSDBG(7, std::cout << "iip result in " << niter << " = " << B
156 << " " << diff.mag() << std::endl);
157 return diff.mag();
158}
159
160// search for the nearest to the neutral fibre of the vertical fan point
161// on the segment between p_in and p_out
163 const G4ThreeVector &p_in, const G4double dist_p_in,
164 const G4ThreeVector &p_out, int p_fan
165) const
166{
167 LWSDBG(6, std::cout << "sfnp " << MSG_VECTOR(p_in) << " "
168 << MSG_VECTOR(p_out) << std::endl);
169
170 G4ThreeVector A, B, C, l, diff;
171 A = p_in;
172 B = p_out;
173 diff = B - A;
174 l = diff.unit() * s_IterationPrecision;
175 // this is to correctly take the sign of the distance into account
176 G4double sign = dist_p_in < 0.? -1. : 1.;
177 G4double d_prime;
178 G4double dist_c;
179 unsigned long niter = 0;
180 do {
181 C = A + B;
182 C *= 0.5;
183 dist_c = GetCalculator()->DistanceToTheNeutralFibre(C, p_fan);
184 if(dist_c * sign <= 0.){ // we are in coditions for in_iteration_process
185 LWSDBG(7, std::cout << "sfnp0 " << dist_c << std::endl);
186 return in_iteration_process(p_in, dist_p_in, C, p_fan);
187 }
188 // calculate sign of derivative of distance to the neutral fibre
189 // hope this substitution is acceptable
190 diff = C - l;
191 d_prime = (dist_c - GetCalculator()->DistanceToTheNeutralFibre(diff, p_fan)) * sign;
192 if(d_prime < 0.) A = C;
193 else B = C;
194 niter ++;
195 diff = A - B;
196 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
197 assert(niter < s_IterationsLimit);
198 if(fabs(dist_c) < m_FHTminusT){
199 LWSDBG(7, std::cout << "sfnp1 " << dist_c << std::endl);
200 return in_iteration_process(p_in, dist_p_in, C, p_fan);
201 }
202 // let's check at p_in and p_out
203 if(dist_p_in * sign < dist_c * sign){
204 C = p_in;
205 dist_c = dist_p_in;
206 }
207 G4double dist_p_out = GetCalculator()->DistanceToTheNeutralFibre(p_out, p_fan);
208 if(dist_p_out *sign < dist_c * sign) C = p_out;
209 if(fabs(dist_p_out) < m_FHTminusT){
210 LWSDBG(7, std::cout << "sfnp2 " << dist_p_out << std::endl);
211 return in_iteration_process(p_in, dist_p_in, C, p_fan);
212 }
213 return kInfinity;
214}
215
216G4double LArWheelSolid::distance_to_in(G4ThreeVector &p, const G4ThreeVector &v, int p_fan) const
217{
218 LWSDBG(4, std::cout << "dti: " << MSG_VECTOR(p) << " "
219 << MSG_VECTOR(v) << std::endl);
220
221 G4double distance = 0.;
222#ifdef LARWHEELSOLID_USE_FANBOUND
223 if(FanBound->Inside(p) == kOutside) {
224 const G4double d = FanBound->DistanceToIn(p, v);
225 p += v * d;
226 distance += d;
227 }
228#else
229 if(p.x() > m_fs->xmax) {
230 if(v.x() >= 0.) return kInfinity;
231 const G4double b = (m_fs->xmax - p.x()) / v.x();
232 const G4double y2 = p.y() + v.y() * b;
233 const G4double z2 = p.z() + v.z() * b;
234 p.set(m_fs->xmax, y2, z2);
235 distance += b;
236 } else if(p.x() < m_fs->xmin) {
237 if(v.x() <= 0.) return kInfinity;
238 const G4double b = (m_fs->xmin - p.x()) / v.x();
239 const G4double y2 = p.y() + v.y() * b;
240 const G4double z2 = p.z() + v.z() * b;
241 p.set(m_fs->xmin, y2, z2);
242 distance += b;
243 }
244#endif
245
246// here p is on surface of or inside the "FanBound",
247// distance corrected, misses are accounted for
248 LWSDBG(5, std::cout << "dti corrected: " << MSG_VECTOR(p) << std::endl);
249
250 G4double dist_p = GetCalculator()->DistanceToTheNeutralFibre(p, p_fan);
251 if(fabs(dist_p) < m_FHTminusT) {
252 LWSDBG(5, std::cout << "hit fan dist_p=" << dist_p << ", m_FHTminusT=" << m_FHTminusT << std::endl);
253 return distance;
254 }
255
256#ifdef CHECK_DIRTONORM_ANGLE_ON_SURFACE
257 if(fabs(dist_p) > m_FHTplusT) {
258 LWSDBG(5, std::cout << "outside fan dist_p=" << dist_p << ", m_FHTplusT=" << m_FHTplusT << std::endl);
259 } else {
260 LWSDBG(5, std::cout << "on fan surface dist_p=" << dist_p << ", m_FHTplusT=" << m_FHTplusT << ", m_FHTminusT=" << m_FHTminusT << std::endl);
261
262 const G4ThreeVector d = GetCalculator()->NearestPointOnNeutralFibre(p, p_fan);
263 // check dot product between normal and v
264 if ( (p-d).cosTheta(v) < -AngularTolerance ) {
265 // direction "v" definitely pointing inside
266 // return 0.0, it should be in "distance"
267 return distance;
268 }
269 }
270#endif
271
272 G4ThreeVector q;
273#ifdef LARWHEELSOLID_USE_FANBOUND
274 q = p + v * FanBound->DistanceToOut(p, v);
275#else
276 find_exit_point(p, v, q);
277#endif
278
279 G4int start = select_section(p.z());
280 G4int stop = select_section(q.z());
281 G4int step = -1;
282 if(stop > start) { step = 1; start ++; stop ++; }
283 LWSDBG(5, std::cout << "dti sections " << start << " " << stop
284 << " " << step << std::endl);
285 G4ThreeVector p1;
286 for(G4int i = start; i != stop; i += step){
287// v.z() can't be 0, otherwise start == stop, so the exit point could be only
288// at z border of the fan section
289 const G4double d1 = (m_Zsect[i] - p.z()) / v.z();
290 const G4double x1 = p.x() + v.x() * d1, y1 = p.y() + v.y() * d1;
291 p1.set(x1, y1, m_Zsect[i]);
292 G4double dist_p1 = GetCalculator()->DistanceToTheNeutralFibre(p1, p_fan);
293 LWSDBG(5, std::cout << i << ">" << p << " " << dist_p << " "
294 << p1 << " " << dist_p1 << std::endl);
295 G4double dd = kInfinity;
296 if(dist_p * dist_p1 < 0.){// it certanly cross current half-wave
297 dd = in_iteration_process(p, dist_p, p1, p_fan);
298 }
299 G4double d2 = search_for_nearest_point(p, dist_p, p1, p_fan);
300 LWSDBG(6, std::cout << i << "> dd=" << dd << ", d2=" << d2 << ", distance=" << distance << std::endl);
301 if(d2 < kInfinity){
302 return distance + d2; // this half-wave is intersected
303 } else if(dd < kInfinity){
304 return distance + dd;
305 }
306 distance += d1;
307 p.set(x1, y1, m_Zsect[i]);
308 dist_p = dist_p1;
309 }
310
311 G4double dist_q = GetCalculator()->DistanceToTheNeutralFibre(q, p_fan);
312 LWSDBG(5, std::cout << "dti exit point: " << MSG_VECTOR(q) << " "
313 << dist_q << std::endl);
314 G4double dd = kInfinity;
315 if(dist_p * dist_q < 0.){// it certanly cross current half-wave
316 dd = in_iteration_process(p, dist_p, q, p_fan);
317 }
318 G4double d2 = search_for_nearest_point(p, dist_p, q, p_fan);
319 if(d2 < kInfinity){
320 return distance + d2; // this half-wave is intersected
321 } else if(dd < kInfinity){
322 return distance + dd;
323 }
324 return kInfinity;
325}
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
#define LWSDBG(a, b)
void diff(const Jet &rJet1, const Jet &rJet2, std::map< std::string, double > varDiff)
Difference between jets - Non-Class function required by trigger.
Definition Jet.cxx:631
int sign(int a)
CLHEP::Hep3Vector NearestPointOnNeutralFibre(const CLHEP::Hep3Vector &p, int fan_number) const
double DistanceToTheNeutralFibre(const CLHEP::Hep3Vector &p, int fan_number) const
Calculates aproximate, probably underestimate, distance to the neutral fibre of the vertical fan.
double DistanceToTheNearestFan(CLHEP::Hep3Vector &p, int &out_fan_number) const
Determines the nearest to the input point fan.
static const G4double s_IterationPrecision2
static const G4double s_IterationPrecision
G4int select_section(const G4double &Z) const
G4double in_iteration_process(const G4ThreeVector &, G4double, G4ThreeVector &, int) const
std::vector< G4double > m_Zsect
G4double DistanceToIn(const G4ThreeVector &, const G4ThreeVector &) const
FanBoundExit_t find_exit_point(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &q) const
G4VSolid * m_BoundingShape
static const unsigned int s_IterationsLimit
virtual G4double distance_to_in(G4ThreeVector &, const G4ThreeVector &, int) const
EInside Inside(const G4ThreeVector &) const
LArFanSections * m_fs
G4double search_for_nearest_point(const G4ThreeVector &, const G4double, const G4ThreeVector &, int) const
G4double m_FHTminusT
G4double m_FanHalfThickness
const LArWheelCalculator * GetCalculator(void) const
G4double m_FHTplusT
struct color C
hold the test vectors and ease the comparison