Geant4 11.2.2
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4TwistBoxSide.cc
Go to the documentation of this file.
1//
2// ********************************************************************
3// * License and Disclaimer *
4// * *
5// * The Geant4 software is copyright of the Copyright Holders of *
6// * the Geant4 Collaboration. It is provided under the terms and *
7// * conditions of the Geant4 Software License, included in the file *
8// * LICENSE and available at http://cern.ch/geant4/license . These *
9// * include a list of copyright holders. *
10// * *
11// * Neither the authors of this software system, nor their employing *
12// * institutes,nor the agencies providing financial support for this *
13// * work make any representation or warranty, express or implied, *
14// * regarding this software system or assume any liability for its *
15// * use. Please see the license in the file LICENSE and URL above *
16// * for the full disclaimer and the limitation of liability. *
17// * *
18// * This code implementation is the result of the scientific and *
19// * technical work of the GEANT4 collaboration. *
20// * By using, copying, modifying or distributing the software (or *
21// * any work based on the software) you agree to acknowledge its *
22// * use in resulting scientific publications, and indicate your *
23// * acceptance of all terms of the Geant4 Software license. *
24// ********************************************************************
25//
26// G4TwistBoxSide implementation
27//
28// Author: 18/03/2005 - O.Link ([email protected])
29// --------------------------------------------------------------------
30
31#include <cmath>
32
33#include "G4TwistBoxSide.hh"
36
37//=====================================================================
38//* constructors ------------------------------------------------------
39
41 G4double PhiTwist, // twist angle
42 G4double pDz, // half z lenght
43 G4double pTheta, // direction between end planes
44 G4double pPhi, // defined by polar and azimutal angles.
45 G4double pDy1, // half y length at -pDz
46 G4double pDx1, // half x length at -pDz,-pDy
47 G4double pDx2, // half x length at -pDz,+pDy
48 G4double pDy2, // half y length at +pDz
49 G4double pDx3, // half x length at +pDz,-pDy
50 G4double pDx4, // half x length at +pDz,+pDy
51 G4double pAlph, // tilt angle at +pDz
52 G4double AngleSide // parity
53 ) : G4VTwistSurface(name)
54{
55
56
57 fAxis[0] = kYAxis; // in local coordinate system
58 fAxis[1] = kZAxis;
59 fAxisMin[0] = -kInfinity ; // Y Axis boundary
60 fAxisMax[0] = kInfinity ; // depends on z !!
61 fAxisMin[1] = -pDz ; // Z Axis boundary
62 fAxisMax[1] = pDz ;
63
64 fDx1 = pDx1 ;
65 fDx2 = pDx2 ; // box
66 fDx3 = pDx3 ;
67 fDx4 = pDx4 ; // box
68
69 // this is an overhead. But the parameter naming scheme fits to the other surfaces.
70
71 if ( fDx1 != fDx2 || fDx3 != fDx4 )
72 {
73 std::ostringstream message;
74 message << "TwistedTrapBoxSide is not used as a the side of a box: "
75 << GetName() << G4endl
76 << " Not a box !";
77 G4Exception("G4TwistBoxSide::G4TwistBoxSide()", "GeomSolids0002",
78 FatalException, message);
79 }
80
81 fDy1 = pDy1 ;
82 fDy2 = pDy2 ;
83
84 fDz = pDz ;
85
86 fAlph = pAlph ;
87 fTAlph = std::tan(fAlph) ;
88
89 fTheta = pTheta ;
90 fPhi = pPhi ;
91
92 // precalculate frequently used parameters
93
94 fDx4plus2 = fDx4 + fDx2 ;
95 fDx4minus2 = fDx4 - fDx2 ;
96 fDx3plus1 = fDx3 + fDx1 ;
97 fDx3minus1 = fDx3 - fDx1 ;
98 fDy2plus1 = fDy2 + fDy1 ;
99 fDy2minus1 = fDy2 - fDy1 ;
100
101 fa1md1 = 2*fDx2 - 2*fDx1 ;
102 fa2md2 = 2*fDx4 - 2*fDx3 ;
103
104
105 fPhiTwist = PhiTwist ; // dphi
106 fAngleSide = AngleSide ; // 0,90,180,270 deg
107
108 fdeltaX = 2*fDz * std::tan(fTheta) * std::cos(fPhi); // dx in surface equation
109 fdeltaY = 2*fDz * std::tan(fTheta) * std::sin(fPhi); // dy in surface equation
110
111 fRot.rotateZ( AngleSide ) ;
112
113 fTrans.set(0, 0, 0); // No Translation
114 fIsValidNorm = false;
115
116 SetCorners();
117 SetBoundaries();
118}
119
120
121//=====================================================================
122//* Fake default constructor ------------------------------------------
123
125 : G4VTwistSurface(a)
126{
127}
128
129
130//=====================================================================
131//* destructor --------------------------------------------------------
132
134
135//=====================================================================
136//* GetNormal ---------------------------------------------------------
137
139 G4bool isGlobal)
140{
141 // GetNormal returns a normal vector at a surface (or very close
142 // to surface) point at tmpxx.
143 // If isGlobal=true, it returns the normal in global coordinate.
144 //
145
146 G4ThreeVector xx;
147 if (isGlobal)
148 {
149 xx = ComputeLocalPoint(tmpxx);
150 if ((xx - fCurrentNormal.p).mag() < 0.5 * kCarTolerance)
151 {
153 }
154 }
155 else
156 {
157 xx = tmpxx;
158 if (xx == fCurrentNormal.p)
159 {
160 return fCurrentNormal.normal;
161 }
162 }
163
164 G4double phi ;
165 G4double u ;
166
167 GetPhiUAtX(xx,phi,u) ; // phi,u for point xx close to surface
168
169 G4ThreeVector normal = NormAng(phi,u) ; // the normal vector at phi,u
170
171#ifdef G4TWISTDEBUG
172 G4cout << "normal vector = " << normal << G4endl ;
173 G4cout << "phi = " << phi << " , u = " << u << G4endl ;
174#endif
175
176 // normal = normal/normal.mag() ;
177
178 if (isGlobal)
179 {
181 }
182 else
183 {
184 fCurrentNormal.normal = normal.unit();
185 }
186 return fCurrentNormal.normal;
187}
188
189//=====================================================================
190//* DistanceToSurface -------------------------------------------------
191
193 const G4ThreeVector& gv,
194 G4ThreeVector gxx[],
195 G4double distance[],
196 G4int areacode[],
197 G4bool isvalid[],
198 EValidate validate)
199{
200
201 static const G4double pihalf = pi/2 ;
202 const G4double ctol = 0.5 * kCarTolerance;
203
204 G4bool IsParallel = false ;
205 G4bool IsConverged = false ;
206
207 G4int nxx = 0 ; // number of physical solutions
208
209 fCurStatWithV.ResetfDone(validate, &gp, &gv);
210
211 if (fCurStatWithV.IsDone())
212 {
213 for (G4int i=0; i<fCurStatWithV.GetNXX(); ++i)
214 {
215 gxx[i] = fCurStatWithV.GetXX(i);
216 distance[i] = fCurStatWithV.GetDistance(i);
217 areacode[i] = fCurStatWithV.GetAreacode(i);
218 isvalid[i] = fCurStatWithV.IsValid(i);
219 }
220 return fCurStatWithV.GetNXX();
221 }
222 else // initialize
223 {
224 for (G4int i=0; i<G4VSURFACENXX ; ++i)
225 {
226 distance[i] = kInfinity;
227 areacode[i] = sOutside;
228 isvalid[i] = false;
229 gxx[i].set(kInfinity, kInfinity, kInfinity);
230 }
231 }
232
235
236#ifdef G4TWISTDEBUG
237 G4cout << "Local point p = " << p << G4endl ;
238 G4cout << "Local direction v = " << v << G4endl ;
239#endif
240
241 G4double phi=0.,u=0.,q=0.; // parameters
242
243 // temporary variables
244
245 G4double tmpdist = kInfinity ;
246 G4ThreeVector tmpxx;
247 G4int tmpareacode = sOutside ;
248 G4bool tmpisvalid = false ;
249
250 std::vector<Intersection> xbuf ;
251 Intersection xbuftmp ;
252
253 // prepare some variables for the intersection finder
254
255 G4double L = 2*fDz ;
256
257 G4double phixz = fPhiTwist * ( p.x() * v.z() - p.z() * v.x() ) ;
258 G4double phiyz = fPhiTwist * ( p.y() * v.z() - p.z() * v.y() ) ;
259
260 // special case vz = 0
261
262 if ( v.z() == 0. )
263 {
264 if ( (std::fabs(p.z()) <= L) && (fPhiTwist != 0.0) ) // intersection possible in z
265 {
266 phi = p.z() * fPhiTwist / L ; // phi is determined by the z-position
267
268 q = (2.* fPhiTwist*((v.x() - fTAlph*v.y())*std::cos(phi)
269 + (fTAlph*v.x() + v.y())*std::sin(phi)));
270
271 if (q != 0.0)
272 {
273 u = (2*(-(fdeltaY*phi*v.x()) + fPhiTwist*p.y()*v.x()
274 + fdeltaX*phi*v.y() - fPhiTwist*p.x()*v.y())
275 + (fDx4plus2*fPhiTwist + 2*fDx4minus2*phi)
276 * (v.y()*std::cos(phi) - v.x()*std::sin(phi))) / q;
277 }
278 xbuftmp.phi = phi ;
279 xbuftmp.u = u ;
280 xbuftmp.areacode = sOutside ;
281 xbuftmp.distance = kInfinity ;
282 xbuftmp.isvalid = false ;
283
284 xbuf.push_back(xbuftmp) ; // store it to xbuf
285 }
286 else // no intersection possible
287 {
288 distance[0] = kInfinity;
289 gxx[0].set(kInfinity,kInfinity,kInfinity);
290 isvalid[0] = false ;
291 areacode[0] = sOutside ;
292 fCurStatWithV.SetCurrentStatus(0, gxx[0], distance[0],
293 areacode[0], isvalid[0],
294 0, validate, &gp, &gv);
295
296 return 0;
297 } // end std::fabs(p.z() <= L
298 } // end v.z() == 0
299 else // general solution for non-zero vz
300 {
301 G4double c[8],srd[7],si[7] ;
302
303 c[7] = -14400*(-2*phixz + 2*fTAlph*phiyz + fDx4plus2*fPhiTwist*v.z()) ;
304 c[6] = 28800*(phiyz + 2*fDz*v.x() - (fdeltaX + fDx4minus2)*v.z() + fTAlph*(phixz - 2*fDz*v.y() + fdeltaY*v.z())) ;
305 c[5] = -1200*(10*phixz - 48*fDz*v.y() + 24*fdeltaY*v.z() + fDx4plus2*fPhiTwist*v.z() - 2*fTAlph*(5*phiyz + 24*fDz*v.x() - 12*fdeltaX*v.z())) ;
306 c[4] = -2400*(phiyz + 10*fDz*v.x() - 5*fdeltaX*v.z() + fDx4minus2*v.z() + fTAlph*(phixz - 10*fDz*v.y() + 5*fdeltaY*v.z())) ;
307 c[3] = 24*(2*phixz - 200*fDz*v.y() + 100*fdeltaY*v.z() - fDx4plus2*fPhiTwist*v.z() - 2*fTAlph*(phiyz + 100*fDz*v.x() - 50*fdeltaX*v.z())) ;
308 c[2] = -16*(7*fTAlph* phixz + 7*phiyz - 6*fDz*v.x() + 6*fDz*fTAlph*v.y() + 3*(fdeltaX + fDx4minus2 - fdeltaY*fTAlph)*v.z()) ;
309 c[1] = 4*(9*phixz - 9*fTAlph*phiyz - 56*fDz*fTAlph*v.x() - 56*fDz*v.y() + 28*(fdeltaY + fdeltaX*fTAlph)*v.z()) ;
310 c[0] = 36*(2* fDz*(v.x() - fTAlph*v.y()) - fdeltaX*v.z() + fdeltaY*fTAlph*v.z()) ;
311
312#ifdef G4TWISTDEBUG
313 G4cout << "coef = " << c[0] << " "
314 << c[1] << " "
315 << c[2] << " "
316 << c[3] << " "
317 << c[4] << " "
318 << c[5] << " "
319 << c[6] << " "
320 << c[7] << G4endl ;
321#endif
322
323 G4JTPolynomialSolver trapEq ;
324 G4int num = trapEq.FindRoots(c,7,srd,si);
325
326 for (G4int i = 0 ; i<num ; ++i ) // loop over all mathematical solutions
327 {
328 if ( (si[i]==0.0) && (fPhiTwist != 0.0) ) // only real solutions
329 {
330#ifdef G4TWISTDEBUG
331 G4cout << "Solution " << i << " : " << srd[i] << G4endl ;
332#endif
333 phi = std::fmod(srd[i], pihalf) ;
334
335 u = (2*phiyz + 4*fDz*phi*v.y() - 2*fdeltaY*phi*v.z()
336 - fDx4plus2*fPhiTwist*v.z()*std::sin(phi)
337 - 2*fDx4minus2*phi*v.z()*std::sin(phi))
338 /(2*fPhiTwist*v.z()*std::cos(phi)
339 + 2*fPhiTwist*fTAlph*v.z()*std::sin(phi)) ;
340
341 xbuftmp.phi = phi ;
342 xbuftmp.u = u ;
343 xbuftmp.areacode = sOutside ;
344 xbuftmp.distance = kInfinity ;
345 xbuftmp.isvalid = false ;
346
347 xbuf.push_back(xbuftmp) ; // store it to xbuf
348
349#ifdef G4TWISTDEBUG
350 G4cout << "solution " << i << " = " << phi << " , " << u << G4endl ;
351#endif
352 } // end if real solution
353 } // end loop i
354 } // end general case
355
356
357 nxx = (G4int)xbuf.size() ; // save the number of solutions
358
359 G4ThreeVector xxonsurface ; // point on surface
360 G4ThreeVector surfacenormal ; // normal vector
361 G4double deltaX ; // distance between intersection point and
362 // point on surface
363 G4double theta ; // angle between track and surfacenormal
364 G4double factor ; // a scaling factor
365 G4int maxint = 30 ; // number of iterations
366
367
368 for (auto & k : xbuf)
369 {
370#ifdef G4TWISTDEBUG
371 G4cout << "Solution " << k << " : "
372 << "reconstructed phiR = " << xbuf[k].phi
373 << ", uR = " << xbuf[k].u << G4endl ;
374#endif
375
376 phi = k.phi ; // get the stored values for phi and u
377 u = k.u ;
378
379 IsConverged = false ; // no convergence at the beginning
380
381 for ( G4int i = 1 ; i<maxint ; ++i )
382 {
383 xxonsurface = SurfacePoint(phi,u) ;
384 surfacenormal = NormAng(phi,u) ;
385 tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
386 deltaX = ( tmpxx - xxonsurface ).mag() ;
387 theta = std::fabs(std::acos(v*surfacenormal) - pihalf) ;
388 if ( theta < 0.001 )
389 {
390 factor = 50 ;
391 IsParallel = true ;
392 }
393 else
394 {
395 factor = 1 ;
396 }
397
398#ifdef G4TWISTDEBUG
399 G4cout << "Step i = " << i << ", distance = " << tmpdist << ", " << deltaX << G4endl ;
400 G4cout << "X = " << tmpxx << G4endl ;
401#endif
402
403 GetPhiUAtX(tmpxx, phi, u) ; // the new point xx is accepted and phi/u replaced
404
405#ifdef G4TWISTDEBUG
406 G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
407#endif
408
409 if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
410
411 } // end iterative loop (i)
412
413 if ( std::fabs(tmpdist)<ctol ) tmpdist = 0. ;
414
415#ifdef G4TWISTDEBUG
416 G4cout << "refined solution " << phi << " , " << u << G4endl ;
417 G4cout << "distance = " << tmpdist << G4endl ;
418 G4cout << "local X = " << tmpxx << G4endl ;
419#endif
420
421 tmpisvalid = false ; // init
422
423 if ( IsConverged )
424 {
425 if (validate == kValidateWithTol)
426 {
427 tmpareacode = GetAreaCode(tmpxx);
428 if (!IsOutside(tmpareacode))
429 {
430 if (tmpdist >= 0) tmpisvalid = true;
431 }
432 }
433 else if (validate == kValidateWithoutTol)
434 {
435 tmpareacode = GetAreaCode(tmpxx, false);
436 if (IsInside(tmpareacode))
437 {
438 if (tmpdist >= 0) tmpisvalid = true;
439 }
440 }
441 else // kDontValidate
442 {
443 G4Exception("G4TwistBoxSide::DistanceToSurface()",
444 "GeomSolids0001", FatalException,
445 "Feature NOT implemented !");
446 }
447 }
448 else
449 {
450 tmpdist = kInfinity; // no convergence after 10 steps
451 tmpisvalid = false ; // solution is not vaild
452 }
453
454 // store the found values
455 k.xx = tmpxx ;
456 k.distance = tmpdist ;
457 k.areacode = tmpareacode ;
458 k.isvalid = tmpisvalid ;
459
460 } // end loop over physical solutions (variable k)
461
462 std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ; // sorting
463
464#ifdef G4TWISTDEBUG
465 G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
466 G4cout << G4endl << G4endl ;
467#endif
468
469 // erase identical intersection (within kCarTolerance)
470 xbuf.erase(std::unique(xbuf.begin(),xbuf.end(),EqualIntersection),xbuf.end());
471
472 // add guesses
473
474 auto nxxtmp = (G4int)xbuf.size() ;
475
476 if ( nxxtmp<2 || IsParallel )
477 {
478 // positive end
479#ifdef G4TWISTDEBUG
480 G4cout << "add guess at +z/2 .. " << G4endl ;
481#endif
482
483 phi = fPhiTwist/2 ;
484 u = 0. ;
485 xbuftmp.phi = phi ;
486 xbuftmp.u = u ;
487 xbuftmp.areacode = sOutside ;
488 xbuftmp.distance = kInfinity ;
489 xbuftmp.isvalid = false ;
490
491 xbuf.push_back(xbuftmp) ; // store it to xbuf
492
493#ifdef G4TWISTDEBUG
494 G4cout << "add guess at -z/2 .. " << G4endl ;
495#endif
496
497 phi = -fPhiTwist/2 ;
498 u = 0. ;
499
500 xbuftmp.phi = phi ;
501 xbuftmp.u = u ;
502 xbuftmp.areacode = sOutside ;
503 xbuftmp.distance = kInfinity ;
504 xbuftmp.isvalid = false ;
505
506 xbuf.push_back(xbuftmp) ; // store it to xbuf
507
508 for ( std::size_t k = nxxtmp ; k<xbuf.size() ; ++k )
509 {
510#ifdef G4TWISTDEBUG
511 G4cout << "Solution " << k << " : "
512 << "reconstructed phiR = " << xbuf[k].phi
513 << ", uR = " << xbuf[k].u << G4endl ;
514#endif
515
516 phi = xbuf[k].phi ; // get the stored values for phi and u
517 u = xbuf[k].u ;
518
519 IsConverged = false ; // no convergence at the beginning
520
521 for ( G4int i = 1 ; i<maxint ; ++i )
522 {
523 xxonsurface = SurfacePoint(phi,u) ;
524 surfacenormal = NormAng(phi,u) ;
525 tmpdist = DistanceToPlaneWithV(p, v, xxonsurface, surfacenormal, tmpxx);
526 deltaX = ( tmpxx - xxonsurface ).mag() ;
527 theta = std::fabs(std::acos(v*surfacenormal) - pihalf) ;
528 if ( theta < 0.001 )
529 {
530 factor = 50 ;
531 }
532 else
533 {
534 factor = 1 ;
535 }
536
537#ifdef G4TWISTDEBUG
538 G4cout << "Step i = " << i << ", distance = "
539 << tmpdist << ", " << deltaX << G4endl ;
540 G4cout << "X = " << tmpxx << G4endl ;
541#endif
542
543 GetPhiUAtX(tmpxx, phi, u) ;
544 // the new point xx is accepted and phi/u replaced
545
546#ifdef G4TWISTDEBUG
547 G4cout << "approximated phi = " << phi << ", u = " << u << G4endl ;
548#endif
549
550 if ( deltaX <= factor*ctol ) { IsConverged = true ; break ; }
551
552 } // end iterative loop (i)
553
554 if ( std::fabs(tmpdist)<ctol ) tmpdist = 0. ;
555
556#ifdef G4TWISTDEBUG
557 G4cout << "refined solution " << phi << " , " << u << G4endl ;
558 G4cout << "distance = " << tmpdist << G4endl ;
559 G4cout << "local X = " << tmpxx << G4endl ;
560#endif
561
562 tmpisvalid = false ; // init
563
564 if ( IsConverged )
565 {
566 if (validate == kValidateWithTol)
567 {
568 tmpareacode = GetAreaCode(tmpxx);
569 if (!IsOutside(tmpareacode))
570 {
571 if (tmpdist >= 0) tmpisvalid = true;
572 }
573 }
574 else if (validate == kValidateWithoutTol)
575 {
576 tmpareacode = GetAreaCode(tmpxx, false);
577 if (IsInside(tmpareacode))
578 {
579 if (tmpdist >= 0) tmpisvalid = true;
580 }
581 }
582 else // kDontValidate
583 {
584 G4Exception("G4TwistedBoxSide::DistanceToSurface()",
585 "GeomSolids0001", FatalException,
586 "Feature NOT implemented !");
587 }
588 }
589 else
590 {
591 tmpdist = kInfinity; // no convergence after 10 steps
592 tmpisvalid = false ; // solution is not vaild
593 }
594
595 // store the found values
596 xbuf[k].xx = tmpxx ;
597 xbuf[k].distance = tmpdist ;
598 xbuf[k].areacode = tmpareacode ;
599 xbuf[k].isvalid = tmpisvalid ;
600 } // end loop over physical solutions
601 } // end less than 2 solutions
602
603 // sort again
604 std::sort(xbuf.begin() , xbuf.end(), DistanceSort ) ; // sorting
605
606 // erase identical intersection (within kCarTolerance)
607 xbuf.erase(std::unique(xbuf.begin(),xbuf.end(),EqualIntersection),xbuf.end());
608
609#ifdef G4TWISTDEBUG
610 G4cout << G4endl << "list xbuf after sorting : " << G4endl ;
611 G4cout << G4endl << G4endl ;
612#endif
613
614 nxx = (G4int)xbuf.size() ; // determine number of solutions again.
615
616 for ( G4int i = 0 ; i<(G4int)xbuf.size() ; ++i )
617 {
618 distance[i] = xbuf[i].distance;
619 gxx[i] = ComputeGlobalPoint(xbuf[i].xx);
620 areacode[i] = xbuf[i].areacode ;
621 isvalid[i] = xbuf[i].isvalid ;
622
623 fCurStatWithV.SetCurrentStatus(i, gxx[i], distance[i], areacode[i],
624 isvalid[i], nxx, validate, &gp, &gv);
625
626#ifdef G4TWISTDEBUG
627 G4cout << "element Nr. " << i
628 << ", local Intersection = " << xbuf[i].xx
629 << ", distance = " << xbuf[i].distance
630 << ", u = " << xbuf[i].u
631 << ", phi = " << xbuf[i].phi
632 << ", isvalid = " << xbuf[i].isvalid
633 << G4endl ;
634#endif
635
636 } // end for( i ) loop
637
638#ifdef G4TWISTDEBUG
639 G4cout << "G4TwistBoxSide finished " << G4endl ;
640 G4cout << nxx << " possible physical solutions found" << G4endl ;
641 for ( G4int k= 0 ; k< nxx ; ++k )
642 {
643 G4cout << "global intersection Point found: " << gxx[k] << G4endl ;
644 G4cout << "distance = " << distance[k] << G4endl ;
645 G4cout << "isvalid = " << isvalid[k] << G4endl ;
646 }
647#endif
648
649 return nxx ;
650}
651
652//=====================================================================
653//* DistanceToSurface -------------------------------------------------
654
656 G4ThreeVector gxx[],
657 G4double distance[],
658 G4int areacode[])
659{
660 const G4double ctol = 0.5 * kCarTolerance;
661
663
664 if (fCurStat.IsDone())
665 {
666 for (G4int i=0; i<fCurStat.GetNXX(); ++i)
667 {
668 gxx[i] = fCurStat.GetXX(i);
669 distance[i] = fCurStat.GetDistance(i);
670 areacode[i] = fCurStat.GetAreacode(i);
671 }
672 return fCurStat.GetNXX();
673 }
674 else // initialize
675 {
676 for (G4int i=0; i<G4VSURFACENXX; ++i)
677 {
678 distance[i] = kInfinity;
679 areacode[i] = sOutside;
680 gxx[i].set(kInfinity, kInfinity, kInfinity);
681 }
682 }
683
685 G4ThreeVector xx; // intersection point
686 G4ThreeVector xxonsurface ; // interpolated intersection point
687
688 // the surfacenormal at that surface point
689 G4double phiR = 0. ;
690 G4double uR = 0. ;
691
692 G4ThreeVector surfacenormal ;
693 G4double deltaX ;
694
695 G4int maxint = 20 ;
696
697 for ( G4int i = 1 ; i<maxint ; ++i )
698 {
699 xxonsurface = SurfacePoint(phiR,uR) ;
700 surfacenormal = NormAng(phiR,uR) ;
701 distance[0] = DistanceToPlane(p, xxonsurface, surfacenormal, xx); // new XX
702 deltaX = ( xx - xxonsurface ).mag() ;
703
704#ifdef G4TWISTDEBUG
705 G4cout << "i = " << i << ", distance = " << distance[0]
706 << ", " << deltaX << G4endl ;
707 G4cout << "X = " << xx << G4endl ;
708#endif
709
710 // the new point xx is accepted and phi/psi replaced
711 GetPhiUAtX(xx, phiR, uR) ;
712
713 if ( deltaX <= ctol ) { break ; }
714 }
715
716 // check validity of solution ( valid phi,psi )
717
718 G4double halfphi = 0.5*fPhiTwist ;
719 G4double uMax = GetBoundaryMax(phiR) ;
720
721 if ( phiR > halfphi ) phiR = halfphi ;
722 if ( phiR < -halfphi ) phiR = -halfphi ;
723 if ( uR > uMax ) uR = uMax ;
724 if ( uR < -uMax ) uR = -uMax ;
725
726 xxonsurface = SurfacePoint(phiR,uR) ;
727 distance[0] = ( p - xx ).mag() ;
728 if ( distance[0] <= ctol ) { distance[0] = 0 ; }
729
730 // end of validity
731
732#ifdef G4TWISTDEBUG
733 G4cout << "refined solution " << phiR << " , " << uR << " , " << G4endl ;
734 G4cout << "distance = " << distance[0] << G4endl ;
735 G4cout << "X = " << xx << G4endl ;
736#endif
737
738 G4bool isvalid = true;
739 gxx[0] = ComputeGlobalPoint(xx);
740
741#ifdef G4TWISTDEBUG
742 G4cout << "intersection Point found: " << gxx[0] << G4endl ;
743 G4cout << "distance = " << distance[0] << G4endl ;
744#endif
745
746 fCurStat.SetCurrentStatus(0, gxx[0], distance[0], areacode[0],
747 isvalid, 1, kDontValidate, &gp);
748 return 1;
749}
750
751//=====================================================================
752//* GetAreaCode -------------------------------------------------------
753
754G4int G4TwistBoxSide::GetAreaCode(const G4ThreeVector& xx,
755 G4bool withTol)
756{
757 // We must use the function in local coordinate system.
758 // See the description of DistanceToSurface(p,v).
759
760 const G4double ctol = 0.5 * kCarTolerance;
761
762 G4double phi ;
763 G4double yprime ;
764 GetPhiUAtX(xx, phi,yprime ) ;
765
766 G4double fYAxisMax = GetBoundaryMax(phi) ; // Boundaries are symmetric
767 G4double fYAxisMin = - fYAxisMax ;
768
769#ifdef G4TWISTDEBUG
770 G4cout << "GetAreaCode: phi = " << phi << G4endl ;
771 G4cout << "GetAreaCode: yprime = " << yprime << G4endl ;
772 G4cout << "Intervall is " << fYAxisMin << " to " << fYAxisMax << G4endl ;
773#endif
774
775 G4int areacode = sInside;
776
777 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
778 {
779 G4int zaxis = 1;
780
781 if (withTol)
782 {
783 G4bool isoutside = false;
784
785 // test boundary of yaxis
786
787 if (yprime < fYAxisMin + ctol)
788 {
789 areacode |= (sAxis0 & (sAxisY | sAxisMin)) | sBoundary;
790 if (yprime <= fYAxisMin - ctol) isoutside = true;
791
792 }
793 else if (yprime > fYAxisMax - ctol)
794 {
795 areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary;
796 if (yprime >= fYAxisMax + ctol) isoutside = true;
797 }
798
799 // test boundary of z-axis
800
801 if (xx.z() < fAxisMin[zaxis] + ctol)
802 {
803 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
804
805 if ((areacode & sBoundary) != 0) areacode |= sCorner; // xx on corner.
806 else areacode |= sBoundary;
807 if (xx.z() <= fAxisMin[zaxis] - ctol) isoutside = true;
808
809 }
810 else if (xx.z() > fAxisMax[zaxis] - ctol)
811 {
812 areacode |= (sAxis1 & (sAxisZ | sAxisMax));
813
814 if ((areacode & sBoundary) != 0) areacode |= sCorner; // xx on corner.
815 else areacode |= sBoundary;
816 if (xx.z() >= fAxisMax[zaxis] + ctol) isoutside = true;
817 }
818
819 // if isoutside = true, clear inside bit.
820 // if not on boundary, add axis information.
821
822 if (isoutside)
823 {
824 G4int tmpareacode = areacode & (~sInside);
825 areacode = tmpareacode;
826 }
827 else if ((areacode & sBoundary) != sBoundary)
828 {
829 areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ);
830 }
831
832 }
833 else
834 {
835 // boundary of y-axis
836
837 if (yprime < fYAxisMin )
838 {
839 areacode |= (sAxis0 & (sAxisY | sAxisMin)) | sBoundary;
840 }
841 else if (yprime > fYAxisMax)
842 {
843 areacode |= (sAxis0 & (sAxisY | sAxisMax)) | sBoundary;
844 }
845
846 // boundary of z-axis
847
848 if (xx.z() < fAxisMin[zaxis])
849 {
850 areacode |= (sAxis1 & (sAxisZ | sAxisMin));
851 if ((areacode & sBoundary) != 0) areacode |= sCorner; // xx on corner.
852 else areacode |= sBoundary;
853
854 }
855 else if (xx.z() > fAxisMax[zaxis])
856 {
857 areacode |= (sAxis1 & (sAxisZ | sAxisMax)) ;
858 if ((areacode & sBoundary) != 0) areacode |= sCorner; // xx on corner.
859 else areacode |= sBoundary;
860 }
861
862 if ((areacode & sBoundary) != sBoundary)
863 {
864 areacode |= (sAxis0 & sAxisY) | (sAxis1 & sAxisZ);
865 }
866 }
867 return areacode;
868 }
869 else
870 {
871 G4Exception("G4TwistBoxSide::GetAreaCode()",
872 "GeomSolids0001", FatalException,
873 "Feature NOT implemented !");
874 }
875 return areacode;
876}
877
878//=====================================================================
879//* SetCorners() ------------------------------------------------------
880
881void G4TwistBoxSide::SetCorners()
882{
883
884 // Set Corner points in local coodinate.
885
886 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
887 {
888 G4double x, y, z;
889
890 // corner of Axis0min and Axis1min
891
892 x = -fdeltaX/2. + (fDx2 - fDy1*fTAlph)*std::cos(fPhiTwist/2.) - fDy1*std::sin(fPhiTwist/2.) ;
893 y = -fdeltaY/2. - fDy1*std::cos(fPhiTwist/2.) + (-fDx2 + fDy1*fTAlph)*std::sin(fPhiTwist/2.) ;
894 z = -fDz ;
895
896 SetCorner(sC0Min1Min, x, y, z);
897
898 // corner of Axis0max and Axis1min
899
900 x = -fdeltaX/2. + (fDx2 + fDy1*fTAlph)*std::cos(fPhiTwist/2.) + fDy1*std::sin(fPhiTwist/2.) ;
901 y = -fdeltaY/2. + fDy1*std::cos(fPhiTwist/2.) - (fDx2 + fDy1*fTAlph)*std::sin(fPhiTwist/2.) ;
902 z = -fDz ;
903
904 SetCorner(sC0Max1Min, x, y, z);
905
906 // corner of Axis0max and Axis1max
907
908 x = fdeltaX/2. + (fDx4 + fDy2*fTAlph)*std::cos(fPhiTwist/2.) - fDy2*std::sin(fPhiTwist/2.) ;
909 y = fdeltaY/2. + fDy2*std::cos(fPhiTwist/2.) + (fDx4 + fDy2*fTAlph)*std::sin(fPhiTwist/2.) ;
910 z = fDz ;
911
912 SetCorner(sC0Max1Max, x, y, z);
913
914 // corner of Axis0min and Axis1max
915
916 x = fdeltaX/2. + (fDx4 - fDy2*fTAlph)*std::cos(fPhiTwist/2.) + fDy2*std::sin(fPhiTwist/2.) ;
917 y = fdeltaY/2. - fDy2*std::cos(fPhiTwist/2.) + (fDx4 - fDy2*fTAlph)*std::sin(fPhiTwist/2.) ;
918 z = fDz ;
919
920 SetCorner(sC0Min1Max, x, y, z);
921
922 }
923 else
924 {
925 G4Exception("G4TwistBoxSide::SetCorners()",
926 "GeomSolids0001", FatalException,
927 "Method NOT implemented !");
928 }
929}
930
931//=====================================================================
932//* SetBoundaries() ---------------------------------------------------
933
934void G4TwistBoxSide::SetBoundaries()
935{
936 // Set direction-unit vector of boundary-lines in local coodinates.
937
938 G4ThreeVector direction;
939
940 if (fAxis[0] == kYAxis && fAxis[1] == kZAxis)
941 {
942 // sAxis0 & sAxisMin
944 direction = direction.unit();
945 SetBoundary(sAxis0 & (sAxisY | sAxisMin), direction,
947
948 // sAxis0 & sAxisMax
950 direction = direction.unit();
951 SetBoundary(sAxis0 & (sAxisY | sAxisMax), direction,
953
954 // sAxis1 & sAxisMin
956 direction = direction.unit();
957 SetBoundary(sAxis1 & (sAxisZ | sAxisMin), direction,
959
960 // sAxis1 & sAxisMax
962 direction = direction.unit();
963 SetBoundary(sAxis1 & (sAxisZ | sAxisMax), direction,
965
966 }
967 else
968 {
969 G4Exception("G4TwistBoxSide::SetCorners()",
970 "GeomSolids0001", FatalException,
971 "Feature NOT implemented !");
972 }
973}
974
975
976void G4TwistBoxSide::GetPhiUAtX( const G4ThreeVector& p, G4double& phi, G4double& u)
977{
978 // find closest point XX on surface for a given point p
979 // X0 is a point on the surface, d is the direction
980 // ( both for a fixed z = pz)
981
982 // phi is given by the z coordinate of p
983
984 phi = p.z()/(2*fDz)*fPhiTwist ;
985
986 u = -(fTAlph*(fDx4plus2*fPhiTwist + 2*fDx4minus2*phi)
987 + 2*(fdeltaY*phi + fdeltaX*fTAlph*phi
988 - fPhiTwist*(fTAlph*p.x() + p.y()))* std::cos(phi)
989 + 2*(-(fdeltaX*phi) + fdeltaY*fTAlph*phi + fPhiTwist*(p.x()
990 - fTAlph*p.y()))*std::sin(phi))/(2.*(fPhiTwist
991 + fPhiTwist*fTAlph*fTAlph)) ;
992}
993
994
995G4ThreeVector G4TwistBoxSide::ProjectPoint(const G4ThreeVector& p,
996 G4bool isglobal)
997{
998 // Get Rho at p.z() on Hyperbolic Surface.
999 G4ThreeVector tmpp;
1000 if (isglobal)
1001 {
1002 tmpp = fRot.inverse()*p - fTrans;
1003 }
1004 else
1005 {
1006 tmpp = p;
1007 }
1008
1009 G4double phi ;
1010 G4double u ;
1011
1012 GetPhiUAtX( tmpp, phi, u ) ;
1013 // calculate (phi, u) for a point p close the surface
1014
1015 G4ThreeVector xx = SurfacePoint(phi,u) ;
1016 // transform back to cartesian coordinates
1017
1018 if (isglobal)
1019 {
1020 return (fRot * xx + fTrans);
1021 }
1022 else
1023 {
1024 return xx;
1025 }
1026}
1027
1028void G4TwistBoxSide::GetFacets( G4int k, G4int n, G4double xyz[][3],
1029 G4int faces[][4], G4int iside )
1030{
1031 G4double phi ;
1032 G4double b ;
1033
1034 G4double z, u ; // the two parameters for the surface equation
1035 G4ThreeVector p ; // a point on the surface, given by (z,u)
1036
1037 G4int nnode ;
1038 G4int nface ;
1039
1040 // calculate the (n-1)*(k-1) vertices
1041
1042 G4int i,j ;
1043
1044 for ( i = 0 ; i<n ; ++i )
1045 {
1046 z = -fDz+i*(2.*fDz)/(n-1) ;
1047 phi = z*fPhiTwist/(2*fDz) ;
1048 b = GetValueB(phi) ;
1049
1050 for ( j = 0 ; j<k ; ++j )
1051 {
1052 nnode = GetNode(i,j,k,n,iside) ;
1053 u = -b/2 +j*b/(k-1) ;
1054 p = SurfacePoint(phi,u,true) ;
1055 // surface point in global coordinate system
1056
1057 xyz[nnode][0] = p.x() ;
1058 xyz[nnode][1] = p.y() ;
1059 xyz[nnode][2] = p.z() ;
1060
1061 if ( i<n-1 && j<k-1 ) // conterclock wise filling
1062 {
1063 nface = GetFace(i,j,k,n,iside) ;
1064 faces[nface][0] = GetEdgeVisibility(i,j,k,n,0,-1) * (GetNode(i ,j ,k,n,iside)+1) ; // fortran numbering
1065 faces[nface][1] = GetEdgeVisibility(i,j,k,n,1,-1) * (GetNode(i ,j+1,k,n,iside)+1) ;
1066 faces[nface][2] = GetEdgeVisibility(i,j,k,n,2,-1) * (GetNode(i+1,j+1,k,n,iside)+1) ;
1067 faces[nface][3] = GetEdgeVisibility(i,j,k,n,3,-1) * (GetNode(i+1,j ,k,n,iside)+1) ;
1068 }
1069 }
1070 }
1071}
@ FatalException
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
double G4double
Definition G4Types.hh:83
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4bool DistanceSort(const Intersection &a, const Intersection &b)
G4bool EqualIntersection(const Intersection &a, const Intersection &b)
#define G4VSURFACENXX
#define G4endl
Definition G4ios.hh:67
G4GLOB_DLL std::ostream G4cout
double z() const
Hep3Vector unit() const
double x() const
double y() const
void set(double x, double y, double z)
HepRotation inverse() const
HepRotation & rotateZ(double delta)
Definition Rotation.cc:87
G4int FindRoots(G4double *op, G4int degree, G4double *zeror, G4double *zeroi)
G4ThreeVector GetNormal(const G4ThreeVector &xx, G4bool isGlobal=false) override
G4int DistanceToSurface(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector gxx[], G4double distance[], G4int areacode[], G4bool isvalid[], EValidate validate=kValidateWithTol) override
~G4TwistBoxSide() override
G4TwistBoxSide(const G4String &name, G4double PhiTwist, G4double pDz, G4double pTheta, G4double pPhi, G4double pDy1, G4double pDx1, G4double pDx2, G4double pDy2, G4double pDx3, G4double pDx4, G4double pAlph, G4double AngleSide)
G4double GetDistance(G4int i) const
void SetCurrentStatus(G4int i, G4ThreeVector &xx, G4double &dist, G4int &areacode, G4bool &isvalid, G4int nxx, EValidate validate, const G4ThreeVector *p, const G4ThreeVector *v=nullptr)
G4ThreeVector GetXX(G4int i) const
void ResetfDone(EValidate validate, const G4ThreeVector *p, const G4ThreeVector *v=nullptr)
static const G4int sC0Min1Min
static const G4int sC0Min1Max
G4double DistanceToPlane(const G4ThreeVector &p, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
G4int GetNode(G4int i, G4int j, G4int m, G4int n, G4int iside)
static const G4int sOutside
G4ThreeVector ComputeGlobalDirection(const G4ThreeVector &lp) const
static const G4int sAxisMax
static const G4int sAxis0
G4int GetFace(G4int i, G4int j, G4int m, G4int n, G4int iside)
G4RotationMatrix fRot
G4int GetEdgeVisibility(G4int i, G4int j, G4int m, G4int n, G4int number, G4int orientation)
G4ThreeVector ComputeLocalDirection(const G4ThreeVector &gp) const
static const G4int sAxisMin
static const G4int sC0Max1Max
static const G4int sAxis1
G4bool IsInside(G4int areacode, G4bool testbitmode=false) const
G4ThreeVector fTrans
virtual void SetBoundary(const G4int &axiscode, const G4ThreeVector &direction, const G4ThreeVector &x0, const G4int &boundarytype)
G4ThreeVector ComputeLocalPoint(const G4ThreeVector &gp) const
void SetCorner(G4int areacode, G4double x, G4double y, G4double z)
G4ThreeVector GetCorner(G4int areacode) const
static const G4int sBoundary
static const G4int sAxisZ
G4bool IsOutside(G4int areacode) const
static const G4int sCorner
static const G4int sC0Max1Min
static const G4int sInside
virtual G4String GetName() const
CurrentStatus fCurStatWithV
static const G4int sAxisY
G4double DistanceToPlaneWithV(const G4ThreeVector &p, const G4ThreeVector &v, const G4ThreeVector &x0, const G4ThreeVector &n0, G4ThreeVector &xx)
G4ThreeVector ComputeGlobalPoint(const G4ThreeVector &lp) const
G4SurfCurNormal fCurrentNormal
CurrentStatus fCurStat
@ kYAxis
Definition geomdefs.hh:56
@ kZAxis
Definition geomdefs.hh:57