ATLAS Offline Software
Loading...
Searching...
No Matches
LArWheelSliceSolidDisToIn.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 LArWheelSliceSolid
6#include <cassert>
7#ifndef PORTABLE_LAR_SHAPE
9#endif
10#include "CLHEP/Units/PhysicalConstants.h"
11
13#include "LArWheelSliceSolid.h"
14
15G4double LArWheelSliceSolid::DistanceToIn(const G4ThreeVector &inputP) const
16{
17 LWSDBG(1, std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP) << std::endl);
18 if(m_BoundingShape->Inside(inputP) == kOutside) {
19 // here is an approximation - for the point outside m_BoundingShape
20 // the solid looks like a m_BoundingShape
21 // it's okay since the result could be underestimated
22 LWSDBG(2, std::cout << "Outside BS" << std::endl);
23 return m_BoundingShape->DistanceToIn(inputP);
24 }
25 G4ThreeVector p(inputP);
26
27 //
28 // DistanceToTheNearestFan:
29 // rotates point p to the localFan coordinates and returns fan number to out_fan_number parameter
30 // returns distance to fan as result
31 //
32
33 int p_fan = 0;
34 const G4double d = fabs(GetCalculator()->DistanceToTheNearestFan(p, p_fan));
35 if(d > m_FHTplusT){
36 const G4double result = d - m_FanHalfThickness;
37 LWSDBG(2, std::cout << "dti result = " << result << std::endl);
38 return result;
39 }
40 LWSDBG(2, std::cout << "already inside, return 0" << MSG_VECTOR(p) << std::endl);
41 return 0.;
42}
43
44G4double LArWheelSliceSolid::DistanceToIn(const G4ThreeVector &inputP,
45 const G4ThreeVector &inputV) const
46{
47 LWSDBG(1, std::cout << TypeStr() << " DisToIn" << MSG_VECTOR(inputP)
48 << MSG_VECTOR(inputV) << std::endl);
49
50 G4double distance = 0.;
51 const EInside inside_BS = m_BoundingShape->Inside(inputP);
52 G4ThreeVector p(inputP);
53 if(inside_BS == kOutside) {
54 distance = m_BoundingShape->DistanceToIn(inputP, inputV);
55 if(distance == kInfinity) {
56 LWSDBG(2, std::cout << "Infinity distance to m_BoundingShape"
57 << MSG_VECTOR(inputP) << MSG_VECTOR(inputV)
58 << 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_LARWHEELSLICESOLID
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_LARWHEELSLICESOLID
117
118 return distance;
119}
120
121G4double LArWheelSliceSolid::distance_to_in(G4ThreeVector &p, const G4ThreeVector &v, int p_fan) const
122{
123 LWSDBG(4, std::cout << "dti: " << MSG_VECTOR(p) << " "
124 << MSG_VECTOR(v) << std::endl);
125
126 G4double distance = 0.;
127
128 if(p.x() > m_Xmax) {
129 if(v.x() >= 0.) return kInfinity;
130 const G4double b = (m_Xmax - p.x()) / v.x();
131 const G4double y2 = p.y() + v.y() * b;
132 const G4double z2 = p.z() + v.z() * b;
133 p.set(m_Xmax, y2, z2);
134 distance += b;
135 } else if(p.x() < m_Xmin) {
136 if(v.x() <= 0.) return kInfinity;
137 const G4double b = (m_Xmin - p.x()) / v.x();
138 const G4double y2 = p.y() + v.y() * b;
139 const G4double z2 = p.z() + v.z() * b;
140 p.set(m_Xmin, y2, z2);
141 distance += b;
142 }
143
144// here p is on surface of or inside the "FanBound",
145// distance corrected, misses are accounted for
146 LWSDBG(5, std::cout << "dti corrected: " << MSG_VECTOR(p) << std::endl);
147
148 G4double dist_p = GetCalculator()->DistanceToTheNeutralFibre(p, p_fan);
149 if(fabs(dist_p) < m_FHTminusT) {
150 LWSDBG(5, std::cout << "hit fan dist_p=" << dist_p << ", m_FHTminusT=" << m_FHTminusT << std::endl);
151 return distance;
152 }
153
154 G4ThreeVector q;
155 q = p + v * m_BoundingShape->DistanceToOut(p, v);
156 G4double dist_q = GetCalculator()->DistanceToTheNeutralFibre(q, p_fan);
157 LWSDBG(5, std::cout << "dti exit point: " << MSG_VECTOR(q) << " "
158 << dist_q << std::endl);
159 G4double dd = kInfinity;
160 if(dist_p * dist_q < 0.){// it certanly cross current half-wave
161 dd = in_iteration_process(p, dist_p, q, p_fan);
162 }
163 G4double d2 = search_for_nearest_point(p, dist_p, q, p_fan);
164 if(d2 < kInfinity){
165 return distance + d2; // this half-wave is intersected
166 } else if(dd < kInfinity){
167 return distance + dd;
168 }
169 return kInfinity;
170}
171
172// This functions should be called in the case when we are sure that
173// points p (which sould be OUTSIDE of vertical fan) and out_point have
174// the surface of the vertical fan between them.
175// returns distance from point p to absorber surface
176// sets last parameter to the founded point
178 const G4ThreeVector &p, G4double dist_p, G4ThreeVector &B, int p_fan
179) const
180{
181 LWSDBG(6, std::cout << "iip from " << p << " to " << B
182 << " dir " << (B - p).unit()
183 << std::endl);
184
185 G4ThreeVector A, C, diff;
186 A = p;
187 G4double dist_c;
188 unsigned int niter = 0;
189 // assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(A)) > m_FHTplusT);
190 // assert(GetCalculator()->DistanceToTheNeutralFibre(A) == dist_p);
191 do {
192 C = A + B;
193 C *= 0.5;
194 dist_c = GetCalculator()->DistanceToTheNeutralFibre(C, p_fan);
195 if(dist_c * dist_p < 0. || fabs(dist_c) < m_FHTminusT){
196 B = C;
197 } else {
198 A = C;
199 }
200 niter ++;
201 diff = A - B;
202 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
203 assert(niter < s_IterationsLimit);
204 assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(B, p_fan)) < m_FHTplusT);
205 diff = p - B;
206 LWSDBG(7, std::cout << "iip result in " << niter << " = " << B
207 << " " << diff.mag() << std::endl);
208 return diff.mag();
209}
210
211// search for the nearest to the neutral fibre of the vertical fan point
212// on the segment between p_in and p_out
214 const G4ThreeVector &p_in, const G4double dist_p_in,
215 const G4ThreeVector &p_out, int p_fan
216) const
217{
218 LWSDBG(6, std::cout << "sfnp " << MSG_VECTOR(p_in) << " "
219 << MSG_VECTOR(p_out) << std::endl);
220
221 G4ThreeVector A, B, C, l, diff;
222 A = p_in;
223 B = p_out;
224 diff = B - A;
225 l = diff.unit() * s_IterationPrecision;
226 // this is to correctly take the sign of the distance into account
227 G4double sign = dist_p_in < 0.? -1. : 1.;
228 G4double d_prime;
229 G4double dist_c;
230 unsigned long niter = 0;
231 do {
232 C = A + B;
233 C *= 0.5;
234 dist_c = GetCalculator()->DistanceToTheNeutralFibre(C, p_fan);
235 if(dist_c * sign <= 0.){ // we are in coditions for in_iteration_process
236 LWSDBG(7, std::cout << "sfnp0 " << dist_c << std::endl);
237 return in_iteration_process(p_in, dist_p_in, C, p_fan);
238 }
239 // calculate sign of derivative of distance to the neutral fibre
240 // hope this substitution is acceptable
241 diff = C - l;
242 d_prime = (dist_c - GetCalculator()->DistanceToTheNeutralFibre(diff, p_fan)) * sign;
243 if(d_prime < 0.) A = C;
244 else B = C;
245 niter ++;
246 diff = A - B;
247 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
248 assert(niter < s_IterationsLimit);
249 if(fabs(dist_c) < m_FHTminusT){
250 LWSDBG(7, std::cout << "sfnp1 " << dist_c << std::endl);
251 return in_iteration_process(p_in, dist_p_in, C, p_fan);
252 }
253 // let's check at p_in and p_out
254 if(dist_p_in * sign < dist_c * sign){
255 C = p_in;
256 dist_c = dist_p_in;
257 }
258 G4double dist_p_out = GetCalculator()->DistanceToTheNeutralFibre(p_out, p_fan);
259 if(dist_p_out *sign < dist_c * sign) C = p_out;
260 if(fabs(dist_p_out) < m_FHTminusT){
261 LWSDBG(7, std::cout << "sfnp2 " << dist_p_out << std::endl);
262 return in_iteration_process(p_in, dist_p_in, C, p_fan);
263 }
264 return kInfinity;
265}
266
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)
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_IterationPrecision
static const unsigned int s_IterationsLimit
const LArWheelCalculator * GetCalculator(void) const
virtual G4double distance_to_in(G4ThreeVector &, const G4ThreeVector &, int) const
G4double search_for_nearest_point(const G4ThreeVector &, const G4double, const G4ThreeVector &, int) const
G4double DistanceToIn(const G4ThreeVector &, const G4ThreeVector &) const
static const G4double s_IterationPrecision2
EInside Inside(const G4ThreeVector &) const
G4String TypeStr(void) const
G4double in_iteration_process(const G4ThreeVector &, G4double, G4ThreeVector &, int) const
struct color C
hold the test vectors and ease the comparison