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