ATLAS Offline Software
Loading...
Searching...
No Matches
LArWheelSolidDisToOut.cxx
Go to the documentation of this file.
1/*
2 Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
3*/
4
5#include <cassert>
6
8#include "LArWheelSolid.h"
9#include "LArFanSection.h"
10
11G4double LArWheelSolid::DistanceToOut(const G4ThreeVector &inputP) const
12{
13 LWSDBG(1, std::cout << TypeStr() << " DisToOut" << MSG_VECTOR(inputP) << std::endl);
14 if(m_BoundingShape->Inside(inputP) != kInside){
15 LWSDBG(2, std::cout << "DistanceToOut(p):"
16 << " point " << MSG_VECTOR(inputP)
17 << " is not inside of the m_BoundingShape."
18 << std::endl);
19 return 0.;
20 }
21 G4ThreeVector p( inputP );
22 int p_fan = 0;
23 const G4double d = m_FanHalfThickness - fabs(GetCalculator()->DistanceToTheNearestFan(p, p_fan));
24 if(d < s_Tolerance){
25 LWSDBG(2, std::cout << "already not inside " << MSG_VECTOR(p) << std::endl);
26 return 0.;
27 }
28 const G4double d0 = m_BoundingShape->DistanceToOut(inputP);
29 LWSDBG(2, std::cout << "dto " << d << " " << d0 << std::endl);
30 if(d > d0) return d0;
31 else return d;
32}
33
34G4double LArWheelSolid::DistanceToOut(const G4ThreeVector &inputP,
35 const G4ThreeVector &inputV,
36 const G4bool calcNorm,
37 G4bool* validNorm,
38 G4ThreeVector* sn) const
39{
40 LWSDBG(1, std::cout << TypeStr() << " DisToOut" << MSG_VECTOR(inputP)
41 << MSG_VECTOR(inputV) << std::endl);
42
43 const EInside inside_BS = m_BoundingShape->Inside(inputP);
44 if(inside_BS == kOutside){
45 LWSDBG(2, std::cout << "DistanceToOut(p):"
46 << " point " << MSG_VECTOR(inputP)
47 << " is outside of m_BoundingShape." << std::endl);
48 if(calcNorm) *validNorm = false;
49 return 0.;
50 }
51
52 // If here inside or on surface of BS
53 G4ThreeVector p(inputP);
54 int p_fan = 0;
55 const G4double adtnf_p = fabs(GetCalculator()->DistanceToTheNearestFan(p, p_fan));
56 if(adtnf_p >= m_FHTplusT) {
57 LWSDBG(2, std::cout << "DistanceToOut(p, v): point "
58 << MSG_VECTOR(inputP)
59 << " is outside of solid." << std::endl);
60 if(calcNorm) *validNorm = false;
61 return 0.;
62 }
63
64 G4ThreeVector v(inputV);
65 const G4double phi0 = p.phi() - inputP.phi();
66 v.rotateZ(phi0);
67
68#ifdef CHECK_DIRTONORM_ANGLE_ON_SURFACE
69 if(adtnf_p < FHTminusT) {
70 LWSDBG(5, std::cout << "inside fan point " << MSG_VECTOR(inputP) << ", FHTminusT=" << FHTminusT << std::endl);
71 } else {
72 LWSDBG(5, std::cout << "on fan surface adtnf_p=" << adtnf_p << ", m_FHTplusT=" << m_FHTplusT << ", FHTminusT=" << FHTminusT << std::endl);
73
74 const G4ThreeVector d = GetCalculator()->NearestPointOnNeutralFibre(p, p_fan);
75 // check dot product between normal and v
76 if ( (p-d).cosTheta(v) > AngularTolerance ) {
77 // direction "v" definitely pointing outside
78 // return 0.0
79 return 0.;
80 }
81 }
82#endif
83
84// former distance_to_out starts here
85 LWSDBG(4, std::cout << "dto: " << MSG_VECTOR(p) << " "
86 << MSG_VECTOR(v) << std::endl);
87
88 G4ThreeVector q(p);
89#ifdef LARWHEELSOLID_USE_BS_DTO
90 const G4double dto_bs = m_BoundingShape->DistanceToOut(
91 inputP, inputV, calcNorm, validNorm, sn
92 );
93 q = p + v * dto_bs;
94 if(q.y() < m_Ymin){
95 LWSDBG(5, std::cout << "dto exit point too low " << MSG_VECTOR(q) << std::endl);
96 const G4double dy = (m_Ymin - p.y()) / v.y();
97 q.setX(p.x() + v.x() * dy);
98 q.setY(m_Ymin);
99 q.setZ(p.z() + v.z() * dy);
100 }
101#else
102 FanBoundExit_t exit = find_exit_point(p, v, q);
103 LWSDBG(5, std::cout << "dto exit " << exit << std::endl);
104#endif
105 LWSDBG(5, std::cout << "dto exit point " << MSG_VECTOR(q) << std::endl);
106
107 G4double distance = 0.;
108 G4int start = select_section(p.z());
109 G4int stop = select_section(q.z());
110 G4int step = -1;
111 if(stop > start){ step = 1; start ++; stop ++; }
112 LWSDBG(5, std::cout << "dto sections " << start << " " << stop << " " << step << std::endl);
113
114 G4double tmp;
115 G4ThreeVector p1, C;
116
117 for(G4int i = start; i != stop; i += step){
118 const G4double d1 = (m_Zsect[i] - p.z()) / v.z();
119// v.z() can't be 0, otherwise start == stop, so the exit point could be only
120// at z border of the fan section
121 LWSDBG(5, std::cout << "at " << i << " dist to zsec = " << d1 << std::endl);
122 const G4double x1 = p.x() + v.x() * d1, y1 = p.y() + v.y() * d1;
123 p1.set(x1, y1, m_Zsect[i]);
124 const G4double dd = fabs(GetCalculator()->DistanceToTheNeutralFibre(p1, p_fan));
125 if(dd > m_FHTplusT){
126 tmp = out_iteration_process(p, p1, p_fan);
127 //while(search_for_most_remoted_point(p, out_section, C)){
128 if(search_for_most_remoted_point(p, p1, C, p_fan)){
129 tmp = out_iteration_process(p, C, p_fan);
130 }
131 distance += tmp;
132#ifndef LARWHEELSOLID_USE_BS_DTO
133 exit = NoCross;
134#endif
135 goto end_dto;
136 }
137 if(search_for_most_remoted_point(p, p1, C, p_fan)){
138 distance += out_iteration_process(p, C, p_fan);
139#ifndef LARWHEELSOLID_USE_BS_DTO
140 exit = NoCross;
141#endif
142 goto end_dto;
143 }
144 distance += d1;
145 p.set(x1, y1, m_Zsect[i]);
146 }
147
148 if(fabs(GetCalculator()->DistanceToTheNeutralFibre(q, p_fan)) > m_FHTplusT){
149 LWSDBG(5, std::cout << "q=" << MSG_VECTOR(q) << " outside fan cur distance=" << distance << ", m_FHTplusT=" << m_FHTplusT << std::endl);
150 tmp = out_iteration_process(p, q, p_fan);
151#ifndef LARWHEELSOLID_USE_BS_DTO
152 exit = NoCross;
153#endif
154 } else {
155 tmp = (q - p).mag();
156 }
157 //while(search_for_most_remoted_point(out, out1, C, p_fan)){
158 if(search_for_most_remoted_point(p, q, C, p_fan)){
159 tmp = out_iteration_process(p, C, p_fan);
160#ifndef LARWHEELSOLID_USE_BS_DTO
161 exit = NoCross;
162#endif
163 }
164 distance += tmp;
165// former distance_to_out ends here
166 end_dto:
167 LWSDBG(5, std::cout << "At end_dto distance=" << distance << std::endl);
168#ifdef LARWHEELSOLID_USE_BS_DTO
169 if(calcNorm && distance < dto_bs) *validNorm = false;
170#else
171 if(calcNorm){
172 LWSDBG(5, std::cout << "dto calc norm " << exit << std::endl);
173 switch(exit){
174 case ExitAtBack:
175 sn->set(0., 0., 1.);
176 *validNorm = true;
177 break;
178 case ExitAtFront:
179 sn->set(0., 0., -1.);
180 *validNorm = true;
181 break;
182 case ExitAtOuter:
183 q.rotateZ(-phi0);
184 sn->set(q.x(), q.y(), 0.);
185 if(q.z() <= m_Zmid) sn->setZ(- q.perp() * m_fs->Amax);
186 sn->setMag(1.0);
187 *validNorm = true;
188 break;
189 default:
190 *validNorm = false;
191 break;
192 }
193 }
194#endif
195
196#ifdef DEBUG_LARWHEELSOLID
197 if(Verbose > 2){
198 std::cout << "DTO: " << distance << " ";
199 if (*validNorm) {
200 std::cout << *validNorm << " " << MSG_VECTOR((*sn));
201 } else {
202 std::cout << "Norm is not valid";
203 }
204 std::cout << std::endl;
205 if(Verbose > 3){
206 G4ThreeVector p2 = inputP + inputV * distance;
207 EInside i = Inside(p2);
208 std::cout << "DTO hit at " << MSG_VECTOR(p2) << ", "
209 << inside(i) << std::endl;
210 }
211 }
212#ifdef LWS_HARD_TEST_DTO
213 if(test_dto(inputP, inputV, distance)){
214 if(Verbose == 1){
215 std::cout << TypeStr() << " DisToOut" << MSG_VECTOR(inputP)
216 << MSG_VECTOR(inputV) << std::endl;
217 }
218 }
219#endif
220#endif
221 return distance;
222}
223
224// This functions should be called in the case when we are sure that
225// point p is NOT OUTSIDE of vertical fan and point out is NOT INSIDE vertical fan
226// returns distance from point p to fan surface, sets last
227// parameter to the found point
228// may give wrong answer - see description
229G4double LArWheelSolid::out_iteration_process(const G4ThreeVector &p,
230 G4ThreeVector &B, const int p_fan) const
231{
232 LWSDBG(6, std::cout << "oip: " << p << " " << B);
233 assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(p, p_fan)) < m_FHTplusT);
234 assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(B, p_fan)) > m_FHTminusT);
235 G4ThreeVector A(p), C, diff;
236 unsigned int niter = 0;
237 do {
238 C = A + B;
239 C *= 0.5;
240 if(fabs(GetCalculator()->DistanceToTheNeutralFibre(C, p_fan)) < m_FHTplusT){
241 A = C;
242 } else {
243 B = C;
244 }
245 niter ++;
246 diff = A - B;
247 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
248 assert(fabs(GetCalculator()->DistanceToTheNeutralFibre(B, p_fan)) > m_FHTplusT);
249 assert(niter < s_IterationsLimit);
250 diff = p - B;
251 LWSDBG(7, std::cout << " -> " << B << " " << diff.mag());
252 LWSDBG(6, std::cout << std::endl);
253 return diff.mag();
254}
255
256// returns true if the point being outside vert. fan is found, also set C to
257// that point in this case
258// returns false if the whole track looks like being inside vert. fan
260 const G4ThreeVector &a, const G4ThreeVector &b, G4ThreeVector &C, const int p_fan
261) const
262{
263 LWSDBG(6, std::cout << "sfmrp " << a << " " << b << std::endl);
264 G4ThreeVector diff(b - a);
265
266 if(diff.mag2() <= s_IterationPrecision2) return false;
267 G4ThreeVector A(a), B(b), l(diff.unit() * s_IterationPrecision);
268 // find the most remoted point on the line AB
269 // and check if it is outside vertical fan
270 // small vector along the segment AB
271 G4double d1, d2;
272 unsigned int niter = 0;
273 // searching for maximum of (GetCalculator()->DistanceToTheNeutralFibre)^2 along AB
274 do {
275 C = A + B;
276 C *= 0.5;
278 if(fabs(d1) > m_FHTplusT){
279 // here out_iteration_process gives the answer
280 LWSDBG(7, std::cout << "sfmrp -> " << C << " " << fabs(d1)
281 << " " << (C - a).unit() << " "
282 << (C - a).mag() << std::endl);
283 return true;
284 }
285 // sign of derivative
286 //d1 = GetCalculator()->DistanceToTheNeutralFibre(C + l);
287 d2 = GetCalculator()->DistanceToTheNeutralFibre(C - l, p_fan);
288 if(d1 * d1 - d2 * d2 > 0.) A = C;
289 else B = C;
290 niter ++;
291 diff = A - B;
292 } while(diff.mag2() > s_IterationPrecision2 && niter < s_IterationsLimit);
293 // the line entirely lies inside fan
294 assert(niter < s_IterationsLimit);
295 return false;
296}
Scalar mag() const
mag method
const PlainObject unit() const
This is a plugin that makes Eigen look like CLHEP & defines some convenience methods.
static Double_t a
#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
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.
G4double out_iteration_process(const G4ThreeVector &, G4ThreeVector &, const int) const
static const G4double s_IterationPrecision2
static const G4double s_IterationPrecision
static const G4double s_Tolerance
G4int select_section(const G4double &Z) const
std::vector< G4double > m_Zsect
FanBoundExit_t find_exit_point(const G4ThreeVector &p, const G4ThreeVector &v, G4ThreeVector &q) const
G4VSolid * m_BoundingShape
static const unsigned int s_IterationsLimit
G4double DistanceToOut(const G4ThreeVector &, const G4ThreeVector &, const G4bool calcNorm=false, G4bool *validNorm=0, G4ThreeVector *n=0) const
EInside Inside(const G4ThreeVector &) const
LArFanSections * m_fs
G4bool search_for_most_remoted_point(const G4ThreeVector &, const G4ThreeVector &, G4ThreeVector &, const 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