Geant4 11.4.0
Toolkit for the simulation of the passage of particles through matter
Loading...
Searching...
No Matches
G4TwistedTubs.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// G4TwistedTubs implementation
27//
28// Author: Kotoyo Hoshina (Chiba University), 01.08.2002 - created.
29// Oliver Link (CERN), 13.11.2003 - Integration in Geant4
30// from original version in Jupiter-2.5.02 application.
31// --------------------------------------------------------------------
32
33#include "G4TwistedTubs.hh"
34
35#include "G4GeomTools.hh"
37#include "G4SystemOfUnits.hh"
39#include "G4VoxelLimits.hh"
40#include "G4AffineTransform.hh"
41#include "G4BoundingEnvelope.hh"
42#include "G4ClippablePolygon.hh"
44#include "G4QuickRand.hh"
45
46#include "G4VGraphicsScene.hh"
47#include "G4Polyhedron.hh"
48#include "G4VisExtent.hh"
49
50#include "G4AutoLock.hh"
51
52namespace
53{
54 G4Mutex polyhedronMutex = G4MUTEX_INITIALIZER;
55 G4Mutex twtubsMutex = G4MUTEX_INITIALIZER;
56}
57
58
59//=====================================================================
60//* constructors ------------------------------------------------------
61
63 G4double twistedangle,
64 G4double endinnerrad,
65 G4double endouterrad,
66 G4double halfzlen,
67 G4double dphi)
68 : G4VSolid(pname), fDPhi(dphi),
69 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
70 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
71{
72 if (endinnerrad < DBL_MIN)
73 {
74 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
75 FatalErrorInArgument, "Invalid end-inner-radius!");
76 }
77
78 G4double sinhalftwist = std::sin(0.5 * twistedangle);
79
80 G4double endinnerradX = endinnerrad * sinhalftwist;
81 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
82 - endinnerradX * endinnerradX );
83
84 G4double endouterradX = endouterrad * sinhalftwist;
85 G4double outerrad = std::sqrt( endouterrad * endouterrad
86 - endouterradX * endouterradX );
87
88 // temporary treatment!!
89 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
90 CreateSurfaces();
91}
92
94 G4double twistedangle,
95 G4double endinnerrad,
96 G4double endouterrad,
97 G4double halfzlen,
98 G4int nseg,
99 G4double totphi)
100 : G4VSolid(pname),
101 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
102 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
103{
104
105 if (nseg == 0)
106 {
107 std::ostringstream message;
108 message << "Invalid number of segments." << G4endl
109 << " nseg = " << nseg;
110 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
111 FatalErrorInArgument, message);
112 }
113 if (totphi == DBL_MIN || endinnerrad < DBL_MIN)
114 {
115 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
116 FatalErrorInArgument, "Invalid total-phi or end-inner-radius!");
117 }
118
119 G4double sinhalftwist = std::sin(0.5 * twistedangle);
120
121 G4double endinnerradX = endinnerrad * sinhalftwist;
122 G4double innerrad = std::sqrt( endinnerrad * endinnerrad
123 - endinnerradX * endinnerradX );
124
125 G4double endouterradX = endouterrad * sinhalftwist;
126 G4double outerrad = std::sqrt( endouterrad * endouterrad
127 - endouterradX * endouterradX );
128
129 // temporary treatment!!
130 fDPhi = totphi / nseg;
131 SetFields(twistedangle, innerrad, outerrad, -halfzlen, halfzlen);
132 CreateSurfaces();
133}
134
136 G4double twistedangle,
137 G4double innerrad,
138 G4double outerrad,
139 G4double negativeEndz,
140 G4double positiveEndz,
141 G4double dphi)
142 : G4VSolid(pname), fDPhi(dphi),
143 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
144 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
145{
146 if (innerrad < DBL_MIN)
147 {
148 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
149 FatalErrorInArgument, "Invalid end-inner-radius!");
150 }
151
152 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
153 CreateSurfaces();
154}
155
157 G4double twistedangle,
158 G4double innerrad,
159 G4double outerrad,
160 G4double negativeEndz,
161 G4double positiveEndz,
162 G4int nseg,
163 G4double totphi)
164 : G4VSolid(pname),
165 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr),
166 fFormerTwisted(nullptr), fInnerHype(nullptr), fOuterHype(nullptr)
167{
168 if (nseg == 0)
169 {
170 std::ostringstream message;
171 message << "Invalid number of segments." << G4endl
172 << " nseg = " << nseg;
173 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
174 FatalErrorInArgument, message);
175 }
176 if (totphi == DBL_MIN || innerrad < DBL_MIN)
177 {
178 G4Exception("G4TwistedTubs::G4TwistedTubs()", "GeomSolids0002",
179 FatalErrorInArgument, "Invalid total-phi or end-inner-radius!");
180 }
181
182 fDPhi = totphi / nseg;
183 SetFields(twistedangle, innerrad, outerrad, negativeEndz, positiveEndz);
184 CreateSurfaces();
185}
186
187//=====================================================================
188//* Fake default constructor ------------------------------------------
189
191 : G4VSolid(a),
192 fLowerEndcap(nullptr), fUpperEndcap(nullptr),
193 fLatterTwisted(nullptr), fFormerTwisted(nullptr),
194 fInnerHype(nullptr), fOuterHype(nullptr)
195{
196}
197
198//=====================================================================
199//* destructor --------------------------------------------------------
200
202{
203 delete fLowerEndcap;
204 delete fUpperEndcap;
205 delete fLatterTwisted;
206 delete fFormerTwisted;
207 delete fInnerHype;
208 delete fOuterHype;
209 delete fpPolyhedron; fpPolyhedron = nullptr;
210}
211
212//=====================================================================
213//* Copy constructor --------------------------------------------------
214
216 : G4VSolid(rhs), fPhiTwist(rhs.fPhiTwist),
217 fInnerRadius(rhs.fInnerRadius), fOuterRadius(rhs.fOuterRadius),
218 fDPhi(rhs.fDPhi), fZHalfLength(rhs.fZHalfLength),
219 fInnerStereo(rhs.fInnerStereo), fOuterStereo(rhs.fOuterStereo),
220 fTanInnerStereo(rhs.fTanInnerStereo), fTanOuterStereo(rhs.fTanOuterStereo),
221 fKappa(rhs.fKappa), fInnerRadius2(rhs.fInnerRadius2),
222 fOuterRadius2(rhs.fOuterRadius2), fTanInnerStereo2(rhs.fTanInnerStereo2),
223 fTanOuterStereo2(rhs.fTanOuterStereo2),
224 fLowerEndcap(nullptr), fUpperEndcap(nullptr), fLatterTwisted(nullptr), fFormerTwisted(nullptr),
225 fInnerHype(nullptr), fOuterHype(nullptr),
226 fCubicVolume(rhs.fCubicVolume), fSurfaceArea(rhs.fSurfaceArea)
227{
228 for (auto i=0; i<2; ++i)
229 {
230 fEndZ[i] = rhs.fEndZ[i];
231 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
232 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
233 fEndPhi[i] = rhs.fEndPhi[i];
234 fEndZ2[i] = rhs.fEndZ2[i];
235 }
236 CreateSurfaces();
237}
238
239
240//=====================================================================
241//* Assignment operator -----------------------------------------------
242
244{
245 // Check assignment to self
246 //
247 if (this == &rhs) { return *this; }
248
249 // Copy base class data
250 //
252
253 // Copy data
254 //
255 fPhiTwist= rhs.fPhiTwist;
256 fInnerRadius= rhs.fInnerRadius; fOuterRadius= rhs.fOuterRadius;
257 fDPhi= rhs.fDPhi; fZHalfLength= rhs.fZHalfLength;
258 fInnerStereo= rhs.fInnerStereo; fOuterStereo= rhs.fOuterStereo;
259 fTanInnerStereo= rhs.fTanInnerStereo; fTanOuterStereo= rhs.fTanOuterStereo;
260 fKappa= rhs.fKappa; fInnerRadius2= rhs.fInnerRadius2;
261 fOuterRadius2= rhs.fOuterRadius2; fTanInnerStereo2= rhs.fTanInnerStereo2;
262 fTanOuterStereo2= rhs.fTanOuterStereo2;
263 fLowerEndcap= fUpperEndcap= fLatterTwisted= fFormerTwisted= nullptr;
264 fInnerHype= fOuterHype= nullptr;
265 fCubicVolume= rhs.fCubicVolume; fSurfaceArea= rhs.fSurfaceArea;
266
267 for (auto i=0; i<2; ++i)
268 {
269 fEndZ[i] = rhs.fEndZ[i];
270 fEndInnerRadius[i] = rhs.fEndInnerRadius[i];
271 fEndOuterRadius[i] = rhs.fEndOuterRadius[i];
272 fEndPhi[i] = rhs.fEndPhi[i];
273 fEndZ2[i] = rhs.fEndZ2[i];
274 }
275
276 CreateSurfaces();
277 fRebuildPolyhedron = false;
278 delete fpPolyhedron; fpPolyhedron = nullptr;
279
280 return *this;
281}
282
283//=====================================================================
284//* ComputeDimensions -------------------------------------------------
285
287 const G4int /* n */ ,
288 const G4VPhysicalVolume* /* pRep */ )
289{
290 G4Exception("G4TwistedTubs::ComputeDimensions()",
291 "GeomSolids0001", FatalException,
292 "G4TwistedTubs does not support Parameterisation.");
293}
294
295//=====================================================================
296//* BoundingLimits ----------------------------------------------------
297
299 G4ThreeVector& pMax) const
300{
301 // Find bounding tube
302 G4double rmin = GetInnerRadius();
304
305 G4double zmin = std::min(GetEndZ(0), GetEndZ(1));
306 G4double zmax = std::max(GetEndZ(0), GetEndZ(1));
307
308 G4double dphi = 0.5*GetDPhi();
309 G4double sphi = std::min(GetEndPhi(0), GetEndPhi(1)) - dphi;
310 G4double ephi = std::max(GetEndPhi(0), GetEndPhi(1)) + dphi;
311 G4double totalphi = ephi - sphi;
312
313 // Find bounding box
314 if (dphi <= 0 || totalphi >= CLHEP::twopi)
315 {
316 pMin.set(-rmax,-rmax, zmin);
317 pMax.set( rmax, rmax, zmax);
318 }
319 else
320 {
321 G4TwoVector vmin,vmax;
322 G4GeomTools::DiskExtent(rmin, rmax, sphi, totalphi, vmin, vmax);
323 pMin.set(vmin.x(), vmin.y(), zmin);
324 pMax.set(vmax.x(), vmax.y(), zmax);
325 }
326
327 // Check correctness of the bounding box
328 //
329 if (pMin.x() >= pMax.x() || pMin.y() >= pMax.y() || pMin.z() >= pMax.z())
330 {
331 std::ostringstream message;
332 message << "Bad bounding box (min >= max) for solid: "
333 << GetName() << " !"
334 << "\npMin = " << pMin
335 << "\npMax = " << pMax;
336 G4Exception("G4TwistedTubs::BoundingLimits()", "GeomMgt0001",
337 JustWarning, message);
338 DumpInfo();
339 }
340}
341
342//=====================================================================
343//* CalculateExtent ---------------------------------------------------
344
345G4bool
347 const G4VoxelLimits& pVoxelLimit,
348 const G4AffineTransform& pTransform,
349 G4double& pMin, G4double& pMax) const
350{
351 G4ThreeVector bmin, bmax;
352
353 // Get bounding box
354 BoundingLimits(bmin,bmax);
355
356 // Find extent
357 G4BoundingEnvelope bbox(bmin,bmax);
358 return bbox.CalculateExtent(pAxis,pVoxelLimit,pTransform,pMin,pMax);
359}
360
361
362//=====================================================================
363//* Inside ------------------------------------------------------------
364
366{
367
368 const G4double halftol
370 // static G4int timerid = -1;
371 // G4Timer timer(timerid, "G4TwistedTubs", "Inside");
372 // timer.Start();
373
374
375 EInside outerhypearea = ((G4TwistTubsHypeSide *)fOuterHype)->Inside(p);
376 G4double innerhyperho = ((G4TwistTubsHypeSide *)fInnerHype)->GetRhoAtPZ(p);
377 G4double distanceToOut = p.getRho() - innerhyperho; // +ve: inside
378 EInside tmpinside;
379 if ((outerhypearea == kOutside) || (distanceToOut < -halftol))
380 {
381 tmpinside = kOutside;
382 }
383 else if (outerhypearea == kSurface)
384 {
385 tmpinside = kSurface;
386 }
387 else
388 {
389 if (distanceToOut <= halftol)
390 {
391 tmpinside = kSurface;
392 }
393 else
394 {
395 tmpinside = kInside;
396 }
397 }
398
399 return tmpinside;
400}
401
402//=====================================================================
403//* SurfaceNormal -----------------------------------------------------
404
406{
407 //
408 // return the normal unit vector to the Hyperbolical Surface at a point
409 // p on (or nearly on) the surface
410 //
411 // Which of the three or four surfaces are we closest to?
412 //
413
414
415 G4double distance = kInfinity;
416
417 G4VTwistSurface *surfaces[6];
418 surfaces[0] = fLatterTwisted;
419 surfaces[1] = fFormerTwisted;
420 surfaces[2] = fInnerHype;
421 surfaces[3] = fOuterHype;
422 surfaces[4] = fLowerEndcap;
423 surfaces[5] = fUpperEndcap;
424
425 G4ThreeVector xx;
426 G4ThreeVector bestxx;
427 G4int besti = -1;
428 for (auto i=0; i<6; ++i)
429 {
430 G4double tmpdistance = surfaces[i]->DistanceTo(p, xx);
431 if (tmpdistance < distance)
432 {
433 distance = tmpdistance;
434 bestxx = xx;
435 besti = i;
436 }
437 }
438
439 return surfaces[besti]->GetNormal(bestxx, true);
440}
441
442//=====================================================================
443//* DistanceToIn (p, v) -----------------------------------------------
444
446 const G4ThreeVector& v ) const
447{
448
449 // DistanceToIn (p, v):
450 // Calculate distance to surface of shape from `outside'
451 // along with the v, allowing for tolerance.
452 // The function returns kInfinity if no intersection or
453 // just grazing within tolerance.
454
455 //
456 // Calculate DistanceToIn(p,v)
457 //
458
459 EInside currentside = Inside(p);
460
461 if (currentside == kInside)
462 {
463 }
464 else
465 {
466 if (currentside == kSurface)
467 {
468 // particle is just on a boundary.
469 // If the particle is entering to the volume, return 0.
470 //
471 G4ThreeVector normal = SurfaceNormal(p);
472 if (normal*v < 0)
473 {
474 return 0;
475 }
476 }
477 }
478
479 // now, we can take smallest positive distance.
480
481 // Initialize
482 //
483 G4double distance = kInfinity;
484
485 // find intersections and choose nearest one.
486 //
487 G4VTwistSurface* surfaces[6];
488 surfaces[0] = fLowerEndcap;
489 surfaces[1] = fUpperEndcap;
490 surfaces[2] = fLatterTwisted;
491 surfaces[3] = fFormerTwisted;
492 surfaces[4] = fInnerHype;
493 surfaces[5] = fOuterHype;
494
495 G4ThreeVector xx;
496 G4ThreeVector bestxx;
497 for (const auto & surface : surfaces)
498 {
499 G4double tmpdistance = surface->DistanceToIn(p, v, xx);
500 if (tmpdistance < distance)
501 {
502 distance = tmpdistance;
503 bestxx = xx;
504 }
505 }
506 return distance;
507}
508
509//=====================================================================
510//* DistanceToIn (p) --------------------------------------------------
511
513{
514 // DistanceToIn(p):
515 // Calculate distance to surface of shape from `outside',
516 // allowing for tolerance
517
518 //
519 // Calculate DistanceToIn(p)
520 //
521
522 EInside currentside = Inside(p);
523
524 switch (currentside)
525 {
526 case (kInside) :
527 {}
528 case (kSurface) :
529 {
530 return 0;
531 }
532 case (kOutside) :
533 {
534 // Initialize
535 G4double distance = kInfinity;
536
537 // find intersections and choose nearest one.
538 G4VTwistSurface *surfaces[6];
539 surfaces[0] = fLowerEndcap;
540 surfaces[1] = fUpperEndcap;
541 surfaces[2] = fLatterTwisted;
542 surfaces[3] = fFormerTwisted;
543 surfaces[4] = fInnerHype;
544 surfaces[5] = fOuterHype;
545
546 G4ThreeVector xx;
547 G4ThreeVector bestxx;
548 for (const auto & surface : surfaces)
549 {
550 G4double tmpdistance = surface->DistanceTo(p, xx);
551 if (tmpdistance < distance)
552 {
553 distance = tmpdistance;
554 bestxx = xx;
555 }
556 }
557 return distance;
558 }
559 default :
560 {
561 G4Exception("G4TwistedTubs::DistanceToIn(p)", "GeomSolids0003",
562 FatalException, "Unknown point location!");
563 }
564 } // switch end
565
566 return kInfinity;
567}
568
569//=====================================================================
570//* DistanceToOut (p, v) ----------------------------------------------
571
573 const G4ThreeVector& v,
574 const G4bool calcNorm,
575 G4bool *validNorm,
576 G4ThreeVector *norm ) const
577{
578 // DistanceToOut (p, v):
579 // Calculate distance to surface of shape from `inside'
580 // along with the v, allowing for tolerance.
581 // The function returns kInfinity if no intersection or
582 // just grazing within tolerance.
583
584 //
585 // Calculate DistanceToOut(p,v)
586 //
587
588 EInside currentside = Inside(p);
589 if (currentside == kOutside)
590 {
591 }
592 else
593 {
594 if (currentside == kSurface)
595 {
596 // particle is just on a boundary.
597 // If the particle is exiting from the volume, return 0.
598 //
599 G4ThreeVector normal = SurfaceNormal(p);
600 if (normal*v > 0)
601 {
602 if (calcNorm)
603 {
604 *norm = normal;
605 *validNorm = true;
606 }
607 return 0;
608 }
609 }
610 }
611
612 // now, we can take smallest positive distance.
613
614 // Initialize
615 //
616 G4double distance = kInfinity;
617
618 // find intersections and choose nearest one.
619 //
620 G4VTwistSurface* surfaces[6];
621 surfaces[0] = fLatterTwisted;
622 surfaces[1] = fFormerTwisted;
623 surfaces[2] = fInnerHype;
624 surfaces[3] = fOuterHype;
625 surfaces[4] = fLowerEndcap;
626 surfaces[5] = fUpperEndcap;
627
628 G4int besti = -1;
629 G4ThreeVector xx;
630 G4ThreeVector bestxx;
631 for (auto i=0; i<6; ++i)
632 {
633 G4double tmpdistance = surfaces[i]->DistanceToOut(p, v, xx);
634 if (tmpdistance < distance)
635 {
636 distance = tmpdistance;
637 bestxx = xx;
638 besti = i;
639 }
640 }
641
642 if (calcNorm)
643 {
644 if (besti != -1)
645 {
646 *norm = (surfaces[besti]->GetNormal(p, true));
647 *validNorm = surfaces[besti]->IsValidNorm();
648 }
649 }
650
651 return distance;
652}
653
654
655//=====================================================================
656//* DistanceToOut (p) ----------------------------------------------
657
659{
660 // DistanceToOut(p):
661 // Calculate distance to surface of shape from `inside',
662 // allowing for tolerance
663
664 //
665 // Calculate DistanceToOut(p)
666 //
667
668 EInside currentside = Inside(p);
669
670 switch (currentside)
671 {
672 case (kOutside) :
673 {
674 }
675 case (kSurface) :
676 {
677 return 0;
678 }
679 case (kInside) :
680 {
681 // Initialize
682 G4double distance = kInfinity;
683
684 // find intersections and choose nearest one.
685 G4VTwistSurface* surfaces[6];
686 surfaces[0] = fLatterTwisted;
687 surfaces[1] = fFormerTwisted;
688 surfaces[2] = fInnerHype;
689 surfaces[3] = fOuterHype;
690 surfaces[4] = fLowerEndcap;
691 surfaces[5] = fUpperEndcap;
692
693 G4ThreeVector xx;
694 G4ThreeVector bestxx;
695 for (const auto & surface : surfaces)
696 {
697 G4double tmpdistance = surface->DistanceTo(p, xx);
698 if (tmpdistance < distance)
699 {
700 distance = tmpdistance;
701 bestxx = xx;
702 }
703 }
704 return distance;
705 }
706 default :
707 {
708 G4Exception("G4TwistedTubs::DistanceToOut(p)", "GeomSolids0003",
709 FatalException, "Unknown point location!");
710 }
711 } // switch end
712
713 return 0.;
714}
715
716//=====================================================================
717//* StreamInfo --------------------------------------------------------
718
719std::ostream& G4TwistedTubs::StreamInfo(std::ostream& os) const
720{
721 //
722 // Stream object contents to an output stream
723 //
724 G4long oldprc = os.precision(16);
725 os << "-----------------------------------------------------------\n"
726 << " *** Dump for solid - " << GetName() << " ***\n"
727 << " ===================================================\n"
728 << " Solid type: G4TwistedTubs\n"
729 << " Parameters: \n"
730 << " -ve end Z : " << fEndZ[0]/mm << " mm \n"
731 << " +ve end Z : " << fEndZ[1]/mm << " mm \n"
732 << " inner end radius(-ve z): " << fEndInnerRadius[0]/mm << " mm \n"
733 << " inner end radius(+ve z): " << fEndInnerRadius[1]/mm << " mm \n"
734 << " outer end radius(-ve z): " << fEndOuterRadius[0]/mm << " mm \n"
735 << " outer end radius(+ve z): " << fEndOuterRadius[1]/mm << " mm \n"
736 << " inner radius (z=0) : " << fInnerRadius/mm << " mm \n"
737 << " outer radius (z=0) : " << fOuterRadius/mm << " mm \n"
738 << " twisted angle : " << fPhiTwist/degree << " degrees \n"
739 << " inner stereo angle : " << fInnerStereo/degree << " degrees \n"
740 << " outer stereo angle : " << fOuterStereo/degree << " degrees \n"
741 << " phi-width of a piece : " << fDPhi/degree << " degrees \n"
742 << "-----------------------------------------------------------\n";
743 os.precision(oldprc);
744
745 return os;
746}
747
748
749//=====================================================================
750//* DiscribeYourselfTo ------------------------------------------------
751
753{
754 scene.AddSolid (*this);
755}
756
757//=====================================================================
758//* GetExtent ---------------------------------------------------------
759
761{
762 // Define the sides of the box into which the G4Tubs instance would fit.
763 //
764 G4ThreeVector pmin,pmax;
765 BoundingLimits(pmin,pmax);
766 return { pmin.x(),pmax.x(),
767 pmin.y(),pmax.y(),
768 pmin.z(),pmax.z() };
769}
770
771//=====================================================================
772//* CreatePolyhedron --------------------------------------------------
773
775{
776 // number of meshes
777 //
778 G4double absPhiTwist = std::abs(fPhiTwist);
779 G4double dA = std::max(fDPhi,absPhiTwist);
780 const G4int k =
782 const G4int n =
783 G4int(G4Polyhedron::GetNumberOfRotationSteps() * absPhiTwist / twopi) + 2;
784
785 const G4int nnodes = 4*(k-1)*(n-2) + 2*k*k ;
786 const G4int nfaces = 4*(k-1)*(n-1) + 2*(k-1)*(k-1) ;
787
788 auto ph = new G4Polyhedron;
789 typedef G4double G4double3[3];
790 typedef G4int G4int4[4];
791 auto xyz = new G4double3[nnodes]; // number of nodes
792 auto faces = new G4int4[nfaces] ; // number of faces
793 fLowerEndcap->GetFacets(k,k,xyz,faces,0) ;
794 fUpperEndcap->GetFacets(k,k,xyz,faces,1) ;
795 fInnerHype->GetFacets(k,n,xyz,faces,2) ;
796 fFormerTwisted->GetFacets(k,n,xyz,faces,3) ;
797 fOuterHype->GetFacets(k,n,xyz,faces,4) ;
798 fLatterTwisted->GetFacets(k,n,xyz,faces,5) ;
799
800 ph->createPolyhedron(nnodes,nfaces,xyz,faces);
801
802 delete[] xyz;
803 delete[] faces;
804
805 return ph;
806}
807
808//=====================================================================
809//* GetPolyhedron -----------------------------------------------------
810
812{
813 if (fpPolyhedron == nullptr ||
814 fRebuildPolyhedron ||
815 fpPolyhedron->GetNumberOfRotationStepsAtTimeOfCreation() !=
816 fpPolyhedron->GetNumberOfRotationSteps())
817 {
818 G4AutoLock l(&polyhedronMutex);
819 delete fpPolyhedron;
820 fpPolyhedron = CreatePolyhedron();
821 fRebuildPolyhedron = false;
822 l.unlock();
823 }
824 return fpPolyhedron;
825}
826
827//=====================================================================
828//* CreateSurfaces ----------------------------------------------------
829
830void G4TwistedTubs::CreateSurfaces()
831{
832 // create 6 surfaces of TwistedTub
833
834 G4ThreeVector x0(0, 0, fEndZ[0]);
835 G4ThreeVector n (0, 0, -1);
836
837 fLowerEndcap = new G4TwistTubsFlatSide("LowerEndcap",
838 fEndInnerRadius, fEndOuterRadius,
839 fDPhi, fEndPhi, fEndZ, -1) ;
840
841 fUpperEndcap = new G4TwistTubsFlatSide("UpperEndcap",
842 fEndInnerRadius, fEndOuterRadius,
843 fDPhi, fEndPhi, fEndZ, 1) ;
844
845 G4RotationMatrix rotHalfDPhi;
846 rotHalfDPhi.rotateZ(0.5*fDPhi);
847
848 fLatterTwisted = new G4TwistTubsSide("LatterTwisted",
849 fEndInnerRadius, fEndOuterRadius,
850 fDPhi, fEndPhi, fEndZ,
851 fInnerRadius, fOuterRadius, fKappa,
852 1 ) ;
853 fFormerTwisted = new G4TwistTubsSide("FormerTwisted",
854 fEndInnerRadius, fEndOuterRadius,
855 fDPhi, fEndPhi, fEndZ,
856 fInnerRadius, fOuterRadius, fKappa,
857 -1 ) ;
858
859 fInnerHype = new G4TwistTubsHypeSide("InnerHype",
860 fEndInnerRadius, fEndOuterRadius,
861 fDPhi, fEndPhi, fEndZ,
862 fInnerRadius, fOuterRadius,fKappa,
863 fTanInnerStereo, fTanOuterStereo, -1) ;
864 fOuterHype = new G4TwistTubsHypeSide("OuterHype",
865 fEndInnerRadius, fEndOuterRadius,
866 fDPhi, fEndPhi, fEndZ,
867 fInnerRadius, fOuterRadius,fKappa,
868 fTanInnerStereo, fTanOuterStereo, 1) ;
869
870
871 // set neighbour surfaces
872 //
873 fLowerEndcap->SetNeighbours(fInnerHype, fLatterTwisted,
874 fOuterHype, fFormerTwisted);
875 fUpperEndcap->SetNeighbours(fInnerHype, fLatterTwisted,
876 fOuterHype, fFormerTwisted);
877 fLatterTwisted->SetNeighbours(fInnerHype, fLowerEndcap,
878 fOuterHype, fUpperEndcap);
879 fFormerTwisted->SetNeighbours(fInnerHype, fLowerEndcap,
880 fOuterHype, fUpperEndcap);
881 fInnerHype->SetNeighbours(fLatterTwisted, fLowerEndcap,
882 fFormerTwisted, fUpperEndcap);
883 fOuterHype->SetNeighbours(fLatterTwisted, fLowerEndcap,
884 fFormerTwisted, fUpperEndcap);
885}
886
887
888//=====================================================================
889//* GetEntityType -----------------------------------------------------
890
892{
893 return {"G4TwistedTubs"};
894}
895
896//=====================================================================
897//* Clone -------------------------------------------------------------
898
900{
901 return new G4TwistedTubs(*this);
902}
903
904//=====================================================================
905//* GetLateralArea ----------------------------------------------------
906
908G4TwistedTubs::GetLateralArea(G4double a, G4double r, G4double z) const
909{
910 if (z == 0) { return 0.; }
911 G4double h = std::abs(z);
912 G4double area = h*a;
913 if (std::abs(a - r) > kCarTolerance)
914 {
915 G4double aa = a*a;
916 G4double hh = h*h;
917 G4double rr = r*r;
918 G4double cc = aa*hh/(rr - aa);
919 G4double k = std::sqrt(aa + cc)/cc;
920 G4double kh = k*h;
921 area = 0.5*a*(h*std::sqrt(1. + kh*kh) + std::asinh(kh)/k);
922 }
923 return GetDPhi()*area;
924}
925
926//=====================================================================
927//* GetPhiCutArea -----------------------------------------------------
928
930G4TwistedTubs::GetPhiCutArea(G4double a, G4double r, G4double z) const
931{
932 if (GetDPhi() >= CLHEP::twopi || r <= 0 || z == 0) { return 0.; }
933 G4double h = std::abs(z);
934 G4double area = h*a;
936 {
937 G4double sinw = std::sin(0.5*GetPhiTwist())*h/GetZHalfLength();
938 G4double p = sinw*r/h;
939 G4double q = sinw*r/a;
940 G4double pp = p*p;
941 G4double qq = q*q;
942 G4double pq = p*q;
943 G4double sqroot = std::sqrt(pp + qq + 1);
944 area = (pq*sqroot +
945 0.5*p*(pp + 3.)*std::atanh(q/sqroot) +
946 0.5*q*(qq + 3.)*std::atanh(p/sqroot) +
947 std::atan(sqroot/(pq)) - CLHEP::halfpi)*h*a/(3.*pq);
948 }
949 return area;
950}
951
952//=====================================================================
953//* GetCubicVolume ----------------------------------------------------
954
956{
957 if (fCubicVolume == 0)
958 {
959 G4AutoLock l(&twtubsMutex);
960 G4double DPhi = GetDPhi();
961 G4double Z0 = GetEndZ(0);
962 G4double Z1 = GetEndZ(1);
963 G4double Ain = GetInnerRadius();
964 G4double Aout = GetOuterRadius();
965 G4double R0in = GetEndInnerRadius(0);
966 G4double R1in = GetEndInnerRadius(1);
967 G4double R0out = GetEndOuterRadius(0);
968 G4double R1out = GetEndOuterRadius(1);
969
970 // V_hyperboloid = pi*h*(2*a*a + R*R)/3
971 fCubicVolume = (2.*(Z1 - Z0)*(Aout + Ain)*(Aout - Ain)
972 + Z1*(R1out + R1in)*(R1out - R1in)
973 - Z0*(R0out + R0in)*(R0out - R0in))*DPhi/6.;
974 l.unlock();
975 }
976 return fCubicVolume;
977}
978
979//=====================================================================
980//* GetSurfaceArea ----------------------------------------------------
981
983{
984 if (fSurfaceArea == 0)
985 {
986 G4AutoLock l(&twtubsMutex);
987 G4double dphi = GetDPhi();
988 G4double Ainn = GetInnerRadius();
989 G4double Aout = GetOuterRadius();
990 G4double Rinn0 = GetEndInnerRadius(0);
991 G4double Rout0 = GetEndOuterRadius(0);
992 G4double Rinn1 = GetEndInnerRadius(1);
993 G4double Rout1 = GetEndOuterRadius(1);
994 G4double z0 = GetEndZ(0);
995 G4double z1 = GetEndZ(1);
996
997 G4double base0 = 0.5*dphi*(Rout0*Rout0 - Rinn0*Rinn0); // lower base
998 G4double inner0 = GetLateralArea(Ainn, Rinn0, z0); // lower inner surface
999 G4double outer0 = GetLateralArea(Aout, Rout0, z0); // lower outer surface
1000 G4double cut0 = // lower phi cut
1001 GetPhiCutArea(Aout, Rout0, z0) - GetPhiCutArea(Ainn, Rinn0, z0);
1002
1003 G4double base1 = base0;
1004 G4double inner1 = inner0;
1005 G4double outer1 = outer0;
1006 G4double cut1 = cut0;
1007 if (std::abs(z0) != std::abs(z1))
1008 {
1009 base1 = 0.5*dphi*(Rout1*Rout1 - Rinn1*Rinn1); // upper base
1010 inner1 = GetLateralArea(Ainn, Rinn1, z1); // upper inner surface
1011 outer1 = GetLateralArea(Aout, Rout1, z1); // upper outer surface
1012 cut1 = // upper phi cut
1013 GetPhiCutArea(Aout, Rout1, z1) - GetPhiCutArea(Ainn, Rinn1, z1);
1014 }
1015 fSurfaceArea = base0 + base1 +
1016 ((z0*z1 < 0) ?
1017 (inner0 + inner1 + outer0 + outer1 + 2.*(cut0 + cut1)) :
1018 std::abs(inner0 - inner1 + outer0 - outer1 + 2.*(cut0 - cut1)));
1019 l.unlock();
1020 }
1021 return fSurfaceArea;
1022}
1023
1024//=====================================================================
1025//* GetPointOnSurface -------------------------------------------------
1026
1028{
1029
1030 G4double z = (fEndZ[1] - fEndZ[0])*G4QuickRand() + fEndZ[0] ;
1031 G4double phi , phimin, phimax ;
1032 G4double x , xmin, xmax ;
1033 G4double r , rmin, rmax ;
1034
1035 G4double a1 = fOuterHype->GetSurfaceArea() ;
1036 G4double a2 = fInnerHype->GetSurfaceArea() ;
1037 G4double a3 = fLatterTwisted->GetSurfaceArea() ;
1038 G4double a4 = fFormerTwisted->GetSurfaceArea() ;
1039 G4double a5 = fLowerEndcap->GetSurfaceArea() ;
1040 G4double a6 = fUpperEndcap->GetSurfaceArea() ;
1041
1042 G4double chose = (a1 + a2 + a3 + a4 + a5 + a6)*G4QuickRand() ;
1043
1044 if(chose < a1)
1045 {
1046
1047 phimin = fOuterHype->GetBoundaryMin(z) ;
1048 phimax = fOuterHype->GetBoundaryMax(z) ;
1049 phi = (phimax - phimin)*G4QuickRand() + phimin ;
1050
1051 return fOuterHype->SurfacePoint(phi,z,true) ;
1052 }
1053 if ( (chose >= a1) && (chose < a1 + a2 ) )
1054 {
1055
1056 phimin = fInnerHype->GetBoundaryMin(z) ;
1057 phimax = fInnerHype->GetBoundaryMax(z) ;
1058 phi = (phimax - phimin)*G4QuickRand() + phimin ;
1059
1060 return fInnerHype->SurfacePoint(phi,z,true) ;
1061 }
1062 if ( (chose >= a1 + a2 ) && (chose < a1 + a2 + a3 ) )
1063 {
1064
1065 xmin = fLatterTwisted->GetBoundaryMin(z) ;
1066 xmax = fLatterTwisted->GetBoundaryMax(z) ;
1067 x = (xmax - xmin)*G4QuickRand() + xmin ;
1068
1069 return fLatterTwisted->SurfacePoint(x,z,true) ;
1070 }
1071 if ( (chose >= a1 + a2 + a3 ) && (chose < a1 + a2 + a3 + a4 ) )
1072 {
1073
1074 xmin = fFormerTwisted->GetBoundaryMin(z) ;
1075 xmax = fFormerTwisted->GetBoundaryMax(z) ;
1076 x = (xmax - xmin)*G4QuickRand() + xmin ;
1077
1078 return fFormerTwisted->SurfacePoint(x,z,true) ;
1079 }
1080 if( (chose >= a1 + a2 + a3 + a4 )&&(chose < a1 + a2 + a3 + a4 + a5 ) )
1081 {
1082 rmin = GetEndInnerRadius(0) ;
1083 rmax = GetEndOuterRadius(0) ;
1084 r = std::sqrt((sqr(rmax)-sqr(rmin))*G4QuickRand() + sqr(rmin)) ;
1085
1086 phimin = fLowerEndcap->GetBoundaryMin(r) ;
1087 phimax = fLowerEndcap->GetBoundaryMax(r) ;
1088 phi = (phimax - phimin)*G4QuickRand() + phimin ;
1089
1090 return fLowerEndcap->SurfacePoint(phi,r,true) ;
1091 }
1092
1093 rmin = GetEndInnerRadius(1) ;
1094 rmax = GetEndOuterRadius(1) ;
1095 r = rmin + (rmax-rmin)*std::sqrt(G4QuickRand()) ;
1096
1097 phimin = fUpperEndcap->GetBoundaryMin(r) ;
1098 phimax = fUpperEndcap->GetBoundaryMax(r) ;
1099 phi = (phimax - phimin)*G4QuickRand() + phimin ;
1100
1101 return fUpperEndcap->SurfacePoint(phi,r,true) ;
1102}
G4TemplateAutoLock< G4Mutex > G4AutoLock
@ JustWarning
@ FatalException
@ FatalErrorInArgument
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
G4double G4QuickRand(uint32_t seed=0)
CLHEP::HepRotation G4RotationMatrix
#define G4MUTEX_INITIALIZER
std::mutex G4Mutex
CLHEP::Hep3Vector G4ThreeVector
CLHEP::Hep2Vector G4TwoVector
double G4double
Definition G4Types.hh:83
long G4long
Definition G4Types.hh:87
bool G4bool
Definition G4Types.hh:86
int G4int
Definition G4Types.hh:85
G4String G4GeometryType
Definition G4VSolid.hh:70
#define G4endl
Definition G4ios.hh:67
double x() const
double y() const
double z() const
double x() const
double y() const
double getRho() const
void set(double x, double y, double z)
HepRotation & rotateZ(double delta)
Definition Rotation.cc:87
G4AffineTransform is a class for geometric affine transformations. It supports efficient arbitrary ro...
G4BoundingEnvelope is a helper class to facilitate calculation of the extent of a solid within the li...
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimits, const G4Transform3D &pTransform3D, G4double &pMin, G4double &pMax) const
static G4bool DiskExtent(G4double rmin, G4double rmax, G4double startPhi, G4double delPhi, G4TwoVector &pmin, G4TwoVector &pmax)
G4double GetRadialTolerance() const
static G4GeometryTolerance * GetInstance()
G4TwistTubsFlatSide describes a flat boundary surface for a cylinder.
G4TwistTubsHypeSide describes hyperbolic boundary surface for a cylinder.
G4TwistTubsFlatSide describes a twisted boundary surface for a cylinder.
G4double DistanceToOut(const G4ThreeVector &p, const G4ThreeVector &v, const G4bool calcnorm=false, G4bool *validnorm=nullptr, G4ThreeVector *n=nullptr) const override
G4double GetOuterRadius() const
G4bool CalculateExtent(const EAxis pAxis, const G4VoxelLimits &pVoxelLimit, const G4AffineTransform &pTransform, G4double &pMin, G4double &pMax) const override
G4double GetZHalfLength() const
G4double GetPhiTwist() const
G4Polyhedron * CreatePolyhedron() const override
G4double DistanceToIn(const G4ThreeVector &p, const G4ThreeVector &v) const override
G4TwistedTubs & operator=(const G4TwistedTubs &rhs)
G4double GetEndInnerRadius() const
G4double GetEndOuterRadius() const
G4VSolid * Clone() const override
G4Polyhedron * GetPolyhedron() const override
~G4TwistedTubs() override
G4GeometryType GetEntityType() const override
G4double GetEndPhi(G4int i) const
G4TwistedTubs(const G4String &pname, G4double twistedangle, G4double endinnerrad, G4double endouterrad, G4double halfzlen, G4double dphi)
std::ostream & StreamInfo(std::ostream &os) const override
G4double GetSurfaceArea() override
G4double GetCubicVolume() override
void ComputeDimensions(G4VPVParameterisation *, const G4int, const G4VPhysicalVolume *) override
void BoundingLimits(G4ThreeVector &pMin, G4ThreeVector &pMax) const override
G4VisExtent GetExtent() const override
G4ThreeVector GetPointOnSurface() const override
void DescribeYourselfTo(G4VGraphicsScene &scene) const override
G4double GetEndZ(G4int i) const
G4ThreeVector SurfaceNormal(const G4ThreeVector &p) const override
G4double GetInnerRadius() const
EInside Inside(const G4ThreeVector &p) const override
G4double GetDPhi() const
virtual void AddSolid(const G4Box &)=0
G4VPVParameterisation ia an abstract base class for Parameterisation, able to compute the transformat...
G4VPhysicalVolume is an abstract base class for the representation of a positioned volume....
G4String GetName() const
G4VSolid(const G4String &name)
Definition G4VSolid.cc:59
void DumpInfo() const
G4double kCarTolerance
Definition G4VSolid.hh:418
G4VSolid & operator=(const G4VSolid &rhs)
Definition G4VSolid.cc:108
G4VTwistSurface is a base class for boundary surface of a G4VSolid.
virtual G4ThreeVector GetNormal(const G4ThreeVector &p, G4bool isGlobal)=0
void SetNeighbours(G4VTwistSurface *ax0min, G4VTwistSurface *ax1min, G4VTwistSurface *ax0max, G4VTwistSurface *ax1max)
G4bool IsValidNorm() const
virtual G4double DistanceTo(const G4ThreeVector &gp, G4ThreeVector &gxx)
virtual G4double DistanceToOut(const G4ThreeVector &gp, const G4ThreeVector &gv, G4ThreeVector &gxxbest)
G4VoxelLimits represents limitation/restrictions of space, where restrictions are only made perpendic...
static G4int GetNumberOfRotationSteps()
EAxis
Definition geomdefs.hh:54
EInside
Definition geomdefs.hh:67
@ kInside
Definition geomdefs.hh:70
@ kOutside
Definition geomdefs.hh:68
@ kSurface
Definition geomdefs.hh:69
T sqr(const T &x)
Definition templates.hh:128
#define DBL_MIN
Definition templates.hh:54