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