File indexing completed on 2026-04-10 07:50:33
0001 #include <cstring>
0002 #include <csignal>
0003 #include "sstr.h"
0004 #include "ssys.h"
0005 #include "s_bb.h"
0006 #include "NP.hh"
0007
0008 #include "G4SystemOfUnits.hh"
0009 #include "G4Polycone.hh"
0010 #include "G4Sphere.hh"
0011 #include "G4Box.hh"
0012 #include "G4Tubs.hh"
0013 #include "G4Cons.hh"
0014 #include "G4SubtractionSolid.hh"
0015 #include "G4ThreeVector.hh"
0016 #include "G4Orb.hh"
0017 #include "G4UnionSolid.hh"
0018 #include "G4IntersectionSolid.hh"
0019 #include "G4Ellipsoid.hh"
0020 #include "G4MultiUnion.hh"
0021 #include "G4CutTubs.hh"
0022 #include "G4Torus.hh"
0023
0024 using CLHEP::pi ;
0025 using CLHEP::mm ;
0026
0027 #include "U4SolidMaker.hh"
0028 #include "U4SolidTree.hh"
0029 #include "SLOG.hh"
0030
0031 namespace
0032 {
0033 inline const G4VSolid* EnsureVoxelizedMultiUnion(const G4VSolid* solid)
0034 {
0035 const auto* mu = dynamic_cast<const G4MultiUnion*>(solid);
0036 if(mu && mu->GetNumberOfSolids() > 0 && mu->GetVoxels().GetCountOfVoxels() == 0)
0037 {
0038 const_cast<G4MultiUnion*>(mu)->Voxelize();
0039 }
0040 return solid ;
0041 }
0042 }
0043
0044 const plog::Severity U4SolidMaker::LEVEL = SLOG::EnvLevel("U4SolidMaker", "DEBUG");
0045
0046 const char* U4SolidMaker::NAMES = R"LITERAL(
0047 JustOrbOrbUnion
0048 JustOrbOrbIntersection
0049 JustOrbOrbDifference
0050 JustOrb
0051 ThreeOrbUnion
0052 SphereIntersectBox
0053 SphereWithPhiSegment
0054 SphereWithPhiCutDEV
0055 GeneralSphereDEV
0056 SphereWithThetaSegment
0057 AdditionAcrylicConstruction
0058 XJfixtureConstruction
0059 AltXJfixtureConstruction
0060 AltXJfixtureConstructionU
0061 XJanchorConstruction
0062 SJReceiverConstruction
0063 BoxMinusTubs0
0064 BoxMinusTubs1
0065 BoxMinusOrb
0066 UnionOfHemiEllipsoids
0067 PolyconeWithMultipleRmin
0068 PolyconeWithPhiCut
0069 PolyconeWithPhiCutHalf
0070 AnnulusBoxUnion
0071 AnnulusTwoBoxUnion
0072 AnnulusTwoBoxUnionContiguous
0073 AnnulusOtherTwoBoxUnion
0074 AnnulusCrossTwoBoxUnion
0075 AnnulusFourBoxUnion
0076 CylinderFourBoxUnion
0077 BoxFourBoxUnion
0078 BoxCrossTwoBoxUnion
0079 BoxThreeBoxUnion
0080 OrbOrbMultiUnion
0081 OrbGridMultiUnion
0082 BoxGridMultiUnion
0083 BoxFourBoxContiguous
0084 LHCbRichSphMirr
0085 LHCbRichFlatMirr
0086 LocalFastenerAcrylicConstruction
0087 AltLocalFastenerAcrylicConstruction
0088 AnotherLocalFastenerAcrylicConstruction
0089 WaterDistributer
0090 AltWaterDistributer
0091 WaterDistributorPartIIIUnion
0092 OuterReflectorOrbSubtraction
0093 R12860_PMTSolid
0094 LProfileSectorPolycone
0095 )LITERAL";
0096
0097
0098 const char* U4SolidMaker::Name( const char* prefix, unsigned idx )
0099 {
0100 std::stringstream ss ;
0101 ss << prefix << idx ;
0102 std::string s = ss.str();
0103 return strdup(s.c_str()) ;
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115 G4VSolid* U4SolidMaker::PrimitiveClone( const G4VSolid* src, const char* prefix, unsigned idx)
0116 {
0117 const char* name = Name(prefix, idx );
0118 G4VSolid* clone = U4SolidTree::PrimitiveClone(src, name);
0119 return clone ;
0120 }
0121
0122 bool U4SolidMaker::StartsWith( const char* n, const char* q )
0123 {
0124 return strlen(q) >= strlen(n) && strncmp(q, n, strlen(n)) == 0 ;
0125 }
0126
0127 bool U4SolidMaker::CanMake(const char* qname)
0128 {
0129 bool found = false ;
0130 std::stringstream ss(NAMES) ;
0131 std::string name ;
0132 while (!found && std::getline(ss, name)) if(!name.empty() && StartsWith(name.c_str(), qname)) found = true ;
0133 LOG(LEVEL) << " qname " << qname << " found " << found ;
0134 return found ;
0135 }
0136
0137 const G4VSolid* PolyconeWithMultipleRmin(const char* name);
0138
0139
0140 const G4VSolid* U4SolidMaker::Make(const char* qname)
0141 {
0142 std::string meta ;
0143 return U4SolidMaker::Make(qname, meta);
0144 }
0145 const G4VSolid* U4SolidMaker::Make(const char* qname, std::string& meta )
0146 {
0147 if(strcmp(qname, "NAMES") == 0 )
0148 {
0149 std::cout << NAMES ;
0150 return nullptr ;
0151 }
0152
0153 const G4VSolid* solid = nullptr ;
0154 if( StartsWith("JustOrbOrbUnion",qname)) solid = JustOrbOrbUnion(qname);
0155 else if(StartsWith("JustOrbOrbIntersection",qname)) solid = JustOrbOrbIntersection(qname);
0156 else if(StartsWith("JustOrbOrbDifference",qname)) solid = JustOrbOrbDifference(qname);
0157 else if(StartsWith("JustOrb",qname)) solid = JustOrb(qname);
0158 else if(StartsWith("ThreeOrbUnion",qname)) solid = ThreeOrbUnion(qname);
0159 else if(StartsWith("SphereWithPhiSegment",qname)) solid = SphereWithPhiSegment(qname);
0160 else if(StartsWith("SphereWithPhiCutDEV",qname)) solid = SphereWithPhiCutDEV(qname);
0161 else if(StartsWith("GeneralSphereDEV",qname)) solid = GeneralSphereDEV(qname, meta);
0162 else if(StartsWith("SphereWithThetaSegment",qname)) solid = SphereWithThetaSegment(qname);
0163 else if(StartsWith("AdditionAcrylicConstruction",qname)) solid = AdditionAcrylicConstruction(qname);
0164 else if(StartsWith("XJfixtureConstruction", qname)) solid = XJfixtureConstruction(qname);
0165 else if(StartsWith("AltXJfixtureConstructionU", qname)) solid = AltXJfixtureConstructionU(qname);
0166 else if(StartsWith("AltXJfixtureConstruction", qname)) solid = AltXJfixtureConstruction(qname);
0167 else if(StartsWith("XJanchorConstruction", qname)) solid = XJanchorConstruction(qname) ;
0168 else if(StartsWith("SJReceiverConstruction", qname)) solid = SJReceiverConstruction(qname) ;
0169 else if(StartsWith("BoxMinusTubs0",qname)) solid = BoxMinusTubs0(qname);
0170 else if(StartsWith("BoxMinusTubs1",qname)) solid = BoxMinusTubs1(qname);
0171 else if(StartsWith("BoxMinusOrb",qname)) solid = BoxMinusOrb(qname);
0172 else if(StartsWith("UnionOfHemiEllipsoids", qname)) solid = UnionOfHemiEllipsoids(qname);
0173 else if(StartsWith("PolyconeWithMultipleRmin", qname)) solid = PolyconeWithMultipleRmin(qname) ;
0174 else if(StartsWith("PolyconeWithPhiCutHalf", qname)) solid = PolyconeWithPhiCutHalf(qname) ;
0175 else if(StartsWith("PolyconeWithPhiCut", qname)) solid = PolyconeWithPhiCut(qname) ;
0176 else if(StartsWith("AnnulusBoxUnion", qname)) solid = AnnulusBoxUnion(qname) ;
0177 else if(StartsWith("AnnulusTwoBoxUnion", qname)) solid = AnnulusTwoBoxUnion(qname) ;
0178 else if(StartsWith("AnnulusOtherTwoBoxUnion", qname)) solid = AnnulusOtherTwoBoxUnion(qname) ;
0179 else if(StartsWith("AnnulusCrossTwoBoxUnion", qname)) solid = AnnulusCrossTwoBoxUnion(qname) ;
0180 else if(StartsWith("AnnulusFourBoxUnion", qname)) solid = AnnulusFourBoxUnion(qname) ;
0181 else if(StartsWith("CylinderFourBoxUnion", qname)) solid = CylinderFourBoxUnion(qname) ;
0182 else if(StartsWith("BoxFourBoxUnion", qname)) solid = BoxFourBoxUnion(qname) ;
0183 else if(StartsWith("BoxCrossTwoBoxUnion", qname)) solid = BoxCrossTwoBoxUnion(qname) ;
0184 else if(StartsWith("BoxThreeBoxUnion", qname)) solid = BoxThreeBoxUnion(qname) ;
0185 else if(StartsWith("OrbOrbMultiUnion", qname)) solid = OrbOrbMultiUnion(qname) ;
0186 else if(StartsWith("OrbGridMultiUnion", qname)) solid = OrbGridMultiUnion(qname) ;
0187 else if(StartsWith("BoxGridMultiUnion", qname)) solid = BoxGridMultiUnion(qname) ;
0188 else if(StartsWith("BoxFourBoxContiguous", qname)) solid = BoxFourBoxContiguous(qname) ;
0189 else if(StartsWith("LHCbRichSphMirr", qname)) solid = LHCbRichSphMirr(qname) ;
0190 else if(StartsWith("LHCbRichFlatMirr", qname)) solid = LHCbRichFlatMirr(qname) ;
0191 else if(StartsWith("SphereIntersectBox", qname)) solid = SphereIntersectBox(qname) ;
0192 else if(StartsWith("LocalFastenerAcrylicConstruction", qname)) solid = LocalFastenerAcrylicConstruction(qname) ;
0193 else if(StartsWith("AltLocalFastenerAcrylicConstruction", qname)) solid = AltLocalFastenerAcrylicConstruction(qname) ;
0194 else if(StartsWith("BltLocalFastenerAcrylicConstruction", qname)) solid = BltLocalFastenerAcrylicConstruction(qname) ;
0195 else if(StartsWith("WaterDistributer", qname)) solid = WaterDistributer(qname) ;
0196 else if(StartsWith("AltWaterDistributer", qname)) solid = AltWaterDistributer(qname) ;
0197 else if(StartsWith("WaterDistributorPartIIIUnion", qname)) solid = WaterDistributorPartIIIUnion(qname);
0198 else if(StartsWith("OuterReflectorOrbSubtraction", qname)) solid = OuterReflectorOrbSubtraction(qname);
0199 else if(StartsWith("R12860_PMTSolid", qname)) solid = R12860_PMTSolid(qname);
0200 else if(StartsWith("LProfileSectorPolycone",qname)) solid = LProfileSectorPolycone(qname);
0201 LOG(LEVEL) << " qname " << qname << " solid " << solid ;
0202 LOG_IF(error, solid==nullptr) << " Failed to create solid for qname " << qname << " CHECK U4SolidMaker::Make " ;
0203 return EnsureVoxelizedMultiUnion(solid) ;
0204 }
0205
0206
0207
0208
0209
0210
0211 const G4VSolid* U4SolidMaker::JustOrb(const char* name)
0212 {
0213 return new G4Orb(name, 100.) ;
0214 }
0215
0216
0217 const G4VSolid* U4SolidMaker::JustOrbOrbUnion( const char* name){ return JustOrbOrb_(name, 'U') ; }
0218 const G4VSolid* U4SolidMaker::JustOrbOrbIntersection(const char* name){ return JustOrbOrb_(name, 'I') ; }
0219 const G4VSolid* U4SolidMaker::JustOrbOrbDifference( const char* name){ return JustOrbOrb_(name, 'D') ; }
0220
0221 const G4VSolid* U4SolidMaker::JustOrbOrb_(const char* name, char op)
0222 {
0223 G4Orb* l = new G4Orb("l", 100.) ;
0224 G4Orb* r = new G4Orb("r", 100.) ;
0225 G4VSolid* oo = nullptr ;
0226 switch(op)
0227 {
0228 case 'U': oo = new G4UnionSolid( name, l, r, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm ) ) ; break ;
0229 case 'I': oo = new G4IntersectionSolid(name, l, r, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm ) ) ; break ;
0230 case 'D': oo = new G4SubtractionSolid( name, l, r, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm ) ) ; break ;
0231 }
0232 return oo ;
0233 }
0234
0235
0236
0237
0238
0239
0240 const G4VSolid* U4SolidMaker::SphereWithPhiCutDEV(const char* name)
0241 {
0242 double radius = ssys::getenvfloat("U4SolidMaker_SphereWithPhiCutDEV_radius", 20.f) ;
0243 double phi_start = ssys::getenvfloat("U4SolidMaker_SphereWithPhiCutDEV_phi_start", 0.f) ;
0244 double phi_delta = ssys::getenvfloat("U4SolidMaker_SphereWithPhiCutDEV_phi_delta", 0.5f) ;
0245
0246 G4String pName = name ;
0247 G4double pRmin = 0. ;
0248 G4double pRmax = radius ;
0249 G4double pSPhi = phi_start*pi ;
0250 G4double pDPhi = phi_delta*pi ;
0251 G4double pSTheta = 0. ;
0252 G4double pDTheta = pi ;
0253
0254 return new G4Sphere(pName, pRmin, pRmax, pSPhi, pDPhi, pSTheta, pDTheta );
0255 }
0256
0257
0258
0259
0260 const G4VSolid* U4SolidMaker::GeneralSphereDEV(const char* name, std::string& meta )
0261 {
0262 const char* radiusMode = ssys::getenvvar("U4SolidMaker_GeneralSphereDEV_radiusMode");
0263 double innerRadius = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_innerRadius", 50.f) ;
0264 double outerRadius = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_outerRadius", 100.f) ;
0265
0266
0267 const char* phiMode = ssys::getenvvar("U4SolidMaker_GeneralSphereDEV_phiMode");
0268 double phiStart = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_phiStart", 0.f) ;
0269 double phiDelta = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_phiDelta", 2.0f) ;
0270
0271
0272 const char* thetaMode = ssys::getenvvar("U4SolidMaker_GeneralSphereDEV_thetaMode");
0273 double thetaStart = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_thetaStart", 0.f) ;
0274 double thetaDelta = ssys::getenvfloat("U4SolidMaker_GeneralSphereDEV_thetaDelta", 0.5f) ;
0275
0276
0277 NP::SetMeta<std::string>( meta, "creator", "U4SolidMaker::GeneralSphereDEV" );
0278 NP::SetMeta<std::string>( meta, "name", name );
0279
0280 NP::SetMeta<std::string>( meta, "radiusMode", radiusMode );
0281 NP::SetMeta<float>( meta, "innerRadius", float(innerRadius) );
0282 NP::SetMeta<float>( meta, "outerRadius", float(outerRadius) );
0283
0284 NP::SetMeta<std::string>( meta, "phiMode", phiMode );
0285 NP::SetMeta<float>( meta, "phiStart", float(phiStart) );
0286 NP::SetMeta<float>( meta, "phiDelta", float(phiDelta) );
0287
0288 NP::SetMeta<std::string>( meta, "thetaMode", thetaMode );
0289 NP::SetMeta<float>( meta, "thetaStart", float(thetaStart) );
0290 NP::SetMeta<float>( meta, "thetaDelta", float(thetaDelta) );
0291
0292
0293 G4String pName = name ;
0294 G4double pRmin = innerRadius*mm ;
0295 G4double pRmax = outerRadius*mm ;
0296 G4double pSPhi = phiStart*pi ;
0297 G4double pDPhi = phiDelta*pi ;
0298 G4double pSTheta = thetaStart*pi ;
0299 G4double pDTheta = thetaDelta*pi ;
0300
0301 return new G4Sphere(pName, pRmin, pRmax, pSPhi, pDPhi, pSTheta, pDTheta );
0302 }
0303
0304
0305
0306
0307
0308
0309
0310
0311
0312
0313
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325 const G4VSolid* U4SolidMaker::SphereWithPhiSegment(const char* name)
0326 {
0327 double phi_start = ssys::getenvfloat("U4SolidMaker_SphereWithPhiSegment_phi_start", 0.f) ;
0328 double phi_delta = ssys::getenvfloat("U4SolidMaker_SphereWithPhiSegment_phi_delta", 0.5f) ;
0329
0330 LOG(info)
0331 << " (inputs are scaled by pi) "
0332 << " phi_start " << phi_start
0333 << " phi_delta " << phi_delta
0334 << " phi_start+phi_delta " << phi_start+phi_delta
0335 << " phi_start*pi " << phi_start*pi
0336 << " phi_delta*pi " << phi_delta*pi
0337 << " (phi_start+phi_delta)*pi " << (phi_start+phi_delta)*pi
0338 ;
0339
0340 G4String pName = name ;
0341 G4double pRmin = 0. ;
0342 G4double pRmax = 100. ;
0343 G4double pSPhi = phi_start*pi ;
0344 G4double pDPhi = phi_delta*pi ;
0345 G4double pSTheta = 0. ;
0346 G4double pDTheta = pi ;
0347
0348 return new G4Sphere(pName, pRmin, pRmax, pSPhi, pDPhi, pSTheta, pDTheta );
0349 }
0350
0351
0352
0353
0354
0355
0356 const G4VSolid* U4SolidMaker::SphereWithThetaSegment(const char* name)
0357 {
0358 double theta_start = ssys::getenvfloat("U4SolidMaker_SphereWithThetaSegment_theta_start", 0.f) ;
0359 double theta_delta = ssys::getenvfloat("U4SolidMaker_SphereWithThetaSegment_theta_delta", 0.5f) ;
0360
0361 LOG(info)
0362 << " (inputs are scaled by pi) "
0363 << " theta_start " << theta_start
0364 << " theta_delta " << theta_delta
0365 << " theta_start+theta_delta " << theta_start+theta_delta
0366 << " theta_start*pi " << theta_start*pi
0367 << " theta_delta*pi " << theta_delta*pi
0368 << " (theta_start+theta_delta)*pi " << (theta_start+theta_delta)*pi
0369 ;
0370
0371 G4String pName = name ;
0372 G4double pRmin = 0. ;
0373 G4double pRmax = 100. ;
0374 G4double pSPhi = 0.*pi ;
0375 G4double pDPhi = 2.*pi ;
0376 G4double pSTheta = theta_start*pi ;
0377 G4double pDTheta = theta_delta*pi ;
0378
0379 return new G4Sphere(pName, pRmin, pRmax, pSPhi, pDPhi, pSTheta, pDTheta );
0380 }
0381
0382
0383 const G4VSolid* U4SolidMaker::AdditionAcrylicConstruction(const char* name)
0384 {
0385 G4VSolid* simple = nullptr ;
0386 G4VSolid* solidAddition_down = nullptr ;
0387 G4VSolid* solidAddition_up = nullptr ;
0388 G4VSolid* uni_acrylic1 = nullptr ;
0389
0390 double ZNodes3[3];
0391 double RminNodes3[3];
0392 double RmaxNodes3[3];
0393 ZNodes3[0] = 5.7*mm; RminNodes3[0] = 0*mm; RmaxNodes3[0] = 450.*mm;
0394 ZNodes3[1] = 0.0*mm; RminNodes3[1] = 0*mm; RmaxNodes3[1] = 450.*mm;
0395 ZNodes3[2] = -140.0*mm; RminNodes3[2] = 0*mm; RmaxNodes3[2] = 200.*mm;
0396
0397 bool replace_poly = true ;
0398 bool skip_sphere = true ;
0399
0400 simple = new G4Tubs("simple", 0*mm, 450*mm, 200*mm, 0.0*deg,360.0*deg);
0401 solidAddition_down = replace_poly ? simple : new G4Polycone("solidAddition_down",0.0*deg,360.0*deg,3,ZNodes3,RminNodes3,RmaxNodes3);
0402
0403 solidAddition_up = new G4Sphere("solidAddition_up",0*mm,17820*mm,0.0*deg,360.0*deg,0.0*deg,180.*deg);
0404 uni_acrylic1 = skip_sphere ? solidAddition_down : new G4SubtractionSolid("uni_acrylic1",solidAddition_down,solidAddition_up,0,G4ThreeVector(0*mm,0*mm,+17820.0*mm));
0405
0406 G4VSolid* solidAddition_up1 = nullptr ;
0407 G4VSolid* solidAddition_up2 = nullptr ;
0408 G4VSolid* uni_acrylic2 = nullptr ;
0409 G4VSolid* uni_acrylic3 = nullptr ;
0410
0411 G4VSolid* uni_acrylic2_initial = nullptr ;
0412
0413
0414 double zshift = 0*mm ;
0415
0416 solidAddition_up1 = new G4Tubs("solidAddition_up1",120*mm,208*mm,15.2*mm,0.0*deg,360.0*deg);
0417 uni_acrylic2 = new G4SubtractionSolid("uni_acrylic2",uni_acrylic1,solidAddition_up1,0,G4ThreeVector(0.*mm,0.*mm,zshift));
0418 uni_acrylic2_initial = uni_acrylic2 ;
0419
0420
0421 solidAddition_up2 = new G4Tubs("solidAddition_up2",0,14*mm,52.5*mm,0.0*deg,360.0*deg);
0422
0423 for(int i=0;i<8;i++)
0424 {
0425 uni_acrylic3 = new G4SubtractionSolid("uni_acrylic3",uni_acrylic2,solidAddition_up2,0,G4ThreeVector(164.*cos(i*pi/4)*mm,164.*sin(i*pi/4)*mm,-87.5));
0426 uni_acrylic2 = uni_acrylic3;
0427 }
0428
0429
0430 LOG(info)
0431 << " solidAddition_down " << solidAddition_down
0432 << " solidAddition_up " << solidAddition_up
0433 << " solidAddition_up1 " << solidAddition_up1
0434 << " solidAddition_up2 " << solidAddition_up2
0435 << " uni_acrylic2_initial " << uni_acrylic2_initial
0436 << " uni_acrylic1 " << uni_acrylic1
0437 << " uni_acrylic2 " << uni_acrylic2
0438 << " uni_acrylic3 " << uni_acrylic3
0439 ;
0440
0441
0442
0443
0444 return uni_acrylic2_initial ;
0445 }
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456
0457
0458
0459
0460
0461
0462
0463
0464
0465
0466
0467
0468
0469
0470
0471
0472
0473
0474
0475
0476
0477
0478
0479
0480
0481
0482
0483
0484 const G4VSolid* U4SolidMaker::ThreeOrbUnion(const char* name)
0485 {
0486 long mode = sstr::ExtractLong(name, 0);
0487 LOG(LEVEL) << " mode " << mode ;
0488
0489 G4Orb* a = new G4Orb("a", 100. );
0490 G4Orb* b = new G4Orb("b", 100. );
0491 G4Orb* c = new G4Orb("c", 100. );
0492
0493 const G4VSolid* solid = nullptr ;
0494 if( mode == 0 )
0495 {
0496 G4UnionSolid* ab = new G4UnionSolid( "ab", a, b, 0, G4ThreeVector( 10., 0., 0. ) );
0497 G4UnionSolid* ab_c = new G4UnionSolid( "ab_c", ab, c, 0, G4ThreeVector( 20., 0., 0. ) );
0498 solid = ab_c ;
0499 }
0500 else if( mode == 1 )
0501 {
0502 G4UnionSolid* ab = new G4UnionSolid( "ab", a, b, 0, G4ThreeVector( 10., 0., 0. ) );
0503 G4UnionSolid* c_ab = new G4UnionSolid( "c_ab", c, ab, 0, G4ThreeVector( 20., 0., 0. ) );
0504 solid = c_ab ;
0505 }
0506 return solid ;
0507 }
0508
0509
0510
0511
0512
0513
0514
0515
0516
0517
0518
0519
0520
0521
0522
0523
0524
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540
0541
0542
0543
0544
0545
0546
0547
0548
0549
0550
0551
0552
0553
0554
0555
0556
0557
0558
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570
0571
0572
0573
0574
0575
0576
0577
0578
0579
0580
0581
0582
0583
0584
0585
0586
0587
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615 const G4VSolid* U4SolidMaker::AltXJfixtureConstruction(const char* name)
0616 {
0617 return AltXJfixtureConstruction_(name, "");
0618 }
0619 const G4VSolid* U4SolidMaker::AltXJfixtureConstructionU(const char* name)
0620 {
0621 return AltXJfixtureConstruction_(name, "ulxo");
0622 }
0623
0624 const G4VSolid* U4SolidMaker::AltXJfixtureConstruction_(const char* name, const char* opt)
0625 {
0626 G4VSolid* u ;
0627 G4VSolid* l ;
0628 G4VSolid* x ;
0629 G4VSolid* o ;
0630 G4VSolid* i ;
0631
0632 G4VSolid* ul ;
0633 G4VSolid* ulx ;
0634 G4VSolid* ulxo ;
0635 G4VSolid* ulxoi ;
0636
0637
0638 G4double l_uncoincide = 1. ;
0639
0640 u = new G4Box("u", 15.*mm, 65.*mm, 23/2.*mm);
0641 l = new G4Box("l", 15.*mm, 40.*mm, (17+l_uncoincide)/2.*mm);
0642 ul = new G4UnionSolid("ul", u, l, 0, G4ThreeVector(0.*mm, 0.*mm, (-40.+l_uncoincide)/2*mm ) ) ;
0643
0644 G4double zs = 10/2.*mm ;
0645 x = new G4Box("x", 62.*mm, 11.5*mm, 13/2.*mm);
0646 ulx = new G4UnionSolid("ulx", ul, x, 0, G4ThreeVector(0.*mm, 0.*mm, zs )) ;
0647
0648 o = new G4Tubs("o", 0.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0649 ulxo = new G4UnionSolid("ulxo_CSG_CONTIGUOUS", ulx, o, 0, G4ThreeVector(0.*mm, 0.*mm, zs )) ;
0650 if( strstr(opt, "ulxo")) return ulxo ;
0651
0652 G4double i_uncoincide = 1. ;
0653
0654
0655
0656
0657 i = new G4Tubs("i", 0.*mm, 25.*mm, 13./2*mm + i_uncoincide/2.*mm , 0.*deg, 360.*deg);
0658 ulxoi = new G4SubtractionSolid("ulxoi", ulxo, i, 0, G4ThreeVector(0.*mm, 0.*mm, zs+i_uncoincide/2.*mm )) ;
0659
0660
0661
0662
0663 return ulxoi ;
0664 }
0665 const int U4SolidMaker::XJfixtureConstruction_debug_mode = ssys::getenvint("U4SolidMaker__XJfixtureConstruction_debug_mode", 0 ) ;
0666
0667
0668
0669
0670
0671
0672
0673
0674 const G4VSolid* U4SolidMaker::XJfixtureConstruction(const char* name)
0675 {
0676 G4VSolid* solidXJfixture_down1;
0677 G4VSolid* solidXJfixture_down2;
0678 G4VSolid* solidXJfixture_down3;
0679 G4VSolid* solidXJfixture_down_uni1;
0680 G4VSolid* solidXJfixture_down_uni2;
0681 G4VSolid* solidXJfixture_down_uni3;
0682 G4VSolid* solidXJfixture_down_uni4;
0683
0684
0685 G4VSolid* solidXJfixture_up1;
0686 G4VSolid* solidXJfixture_up2;
0687 G4VSolid* solidXJfixture_up_uni;
0688
0689 G4VSolid* solidXJfixture;
0690
0691
0692 solidXJfixture_down1 = new G4Tubs("solidXJfixture_down1", 25.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0693 solidXJfixture_down2 = new G4Box("solidXJfixture_down2", 10.*mm, 11.5*mm, 13/2.*mm);
0694 solidXJfixture_down_uni1 = new G4UnionSolid("solidXJfixture_down_uni1", solidXJfixture_down1, solidXJfixture_down2, 0, G4ThreeVector(52.*mm, 0.*mm, 0.*mm));
0695 solidXJfixture_down_uni2 = new G4UnionSolid("solidXJfixture_down_uni2", solidXJfixture_down_uni1, solidXJfixture_down2, 0, G4ThreeVector(-52.*mm, 0.*mm, 0.*mm));
0696 solidXJfixture_down3 = new G4Box("solidXJfixture_down3", 15.*mm, 15.*mm, 13/2.*mm);
0697 solidXJfixture_down_uni3 = new G4UnionSolid("solidXJfixture_down_uni3", solidXJfixture_down_uni2, solidXJfixture_down3, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0698 solidXJfixture_down_uni4 = new G4UnionSolid("solidXJfixture_down_uni4", solidXJfixture_down_uni3, solidXJfixture_down3, 0, G4ThreeVector(0.*mm, -50.*mm, 0.*mm));
0699
0700
0701
0702
0703 solidXJfixture_up1 = new G4Box("solidXJfixture_up1", 15.*mm, 40.*mm, 17/2.*mm);
0704 solidXJfixture_up2 = new G4Box("solidXJfixture_up2", 15.*mm, 65*mm, 5.*mm);
0705 solidXJfixture_up_uni = new G4UnionSolid("solidXJfixture_up_uni", solidXJfixture_up1, solidXJfixture_up2, 0, G4ThreeVector(0.*mm, 0.*mm, 13.5*mm));
0706
0707
0708
0709
0710 solidXJfixture = new G4UnionSolid("solidXJfixture", solidXJfixture_down_uni4, solidXJfixture_up_uni, 0, G4ThreeVector(0.*mm, 0.*mm, -25.*mm));
0711
0712
0713
0714
0715
0716 G4VSolid* solidXJfixture_twiddle = new G4UnionSolid("solidXJfixture_twiddle", solidXJfixture_up_uni, solidXJfixture_down_uni4, 0, G4ThreeVector(0.*mm, 0.*mm, 25.*mm));
0717 G4VSolid* celtic_cross_sub_altar = new G4SubtractionSolid("solidXJfixture_celtic_cross_sub_altar", solidXJfixture_down_uni4, solidXJfixture_up_uni, 0, G4ThreeVector(0.*mm, 0.*mm, -25.*mm));
0718 G4VSolid* solidXJfixture_split = new G4UnionSolid("solidXJfixture_split", solidXJfixture_down_uni4, solidXJfixture_up_uni, 0, G4ThreeVector(0.*mm, 0.*mm, -50.*mm));
0719
0720
0721 G4VSolid* solid = solidXJfixture ;
0722
0723 int debug_mode = XJfixtureConstruction_debug_mode ;
0724 if( debug_mode > 0 )
0725 {
0726 switch(debug_mode)
0727 {
0728 case 0: solid = solidXJfixture ; break ;
0729 case 1: solid = solidXJfixture_down1 ; break ;
0730 case 2: solid = solidXJfixture_down2 ; break ;
0731 case 3: solid = solidXJfixture_down_uni1 ; break ;
0732 case 4: solid = solidXJfixture_down_uni2 ; break ;
0733 case 5: solid = solidXJfixture_down3 ; break ;
0734 case 6: solid = solidXJfixture_down_uni3 ; break ;
0735 case 7: solid = solidXJfixture_down_uni4 ; break ;
0736 case 8: solid = solidXJfixture_up1 ; break ;
0737 case 9: solid = solidXJfixture_up2 ; break ;
0738 case 10: solid = solidXJfixture_up_uni ; break ;
0739 case 11: solid = celtic_cross_sub_altar ; break ;
0740 case 12: solid = solidXJfixture_split ; break ;
0741 case 13: solid = solidXJfixture_twiddle ; break ;
0742 }
0743 LOG(info)
0744 << "U4SolidMaker__XJfixtureConstruction_debug_mode " << debug_mode
0745 << " solid.GetName " << ( solid ? solid->GetName() : "-" )
0746 ;
0747 assert(solid);
0748 }
0749 return solid ;
0750 }
0751
0752 const G4VSolid* U4SolidMaker::AnnulusBoxUnion(const char* name)
0753 {
0754
0755 G4VSolid* down1 = new G4Tubs("down1", 25.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0756 G4VSolid* down3 = new G4Box("down3", 15.*mm, 15.*mm, 13/2.*mm);
0757 G4VSolid* uni13 = new G4UnionSolid("uni13", down1, down3, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0758 return uni13 ;
0759 }
0760
0761
0762
0763
0764
0765
0766
0767
0768
0769
0770
0771
0772
0773
0774
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790
0791
0792
0793
0794
0795
0796
0797
0798
0799 const G4VSolid* U4SolidMaker::AnnulusTwoBoxUnion(const char* name)
0800 {
0801 const char* suffix = nullptr ;
0802 if( strstr(name, "Contiguous")) suffix = "_CSG_CONTIGUOUS" ;
0803 else if(strstr(name, "Discontiguous")) suffix = "_CSG_DISCONTIGUOUS" ;
0804
0805 bool toplist = strstr(name, "List") != nullptr ;
0806
0807 const char* listname = sstr::Concat("tub_bpy_bny", suffix );
0808
0809 double innerRadius = 0.*mm ;
0810 double bpy_scale_z = 2. ;
0811 double bny_scale_z = 4. ;
0812
0813 LOG(LEVEL)
0814 << " name " << name
0815 << " suffix " << suffix
0816 << " listname " << listname
0817 << " innerRadius " << innerRadius
0818 << " bpy_scale_z " << bpy_scale_z
0819 << " bny_scale_z " << bny_scale_z
0820 ;
0821
0822 G4VSolid* tub = new G4Tubs("tub", 0.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0823
0824 G4VSolid* bpy = new G4Box("bpy", 15.*mm, 15.*mm, bpy_scale_z*13/2.*mm);
0825 G4VSolid* tub_bpy = new G4UnionSolid( "tub_bpy", tub, bpy, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0826
0827 G4VSolid* bny = new G4Box("bny", 15.*mm, 15.*mm, bny_scale_z*13/2.*mm);
0828 G4VSolid* tub_bpy_bny = new G4UnionSolid(listname, tub_bpy, bny, 0, G4ThreeVector(0.*mm, -50.*mm, 0.*mm));
0829
0830 double uncoincide = 1. ;
0831 G4VSolid* itu = new G4Tubs("itu", 0.*mm, 25.*mm, (uncoincide+13./2)*mm, 0.*deg, 360.*deg);
0832 G4VSolid* tub_bpy_bny_itu = new G4SubtractionSolid("tub_bpy_bny_itu", tub_bpy_bny, itu );
0833
0834 return toplist ? tub_bpy_bny : tub_bpy_bny_itu ;
0835 }
0836
0837
0838
0839 const G4VSolid* U4SolidMaker::AnnulusOtherTwoBoxUnion(const char* name)
0840 {
0841 G4VSolid* down1 = new G4Tubs("down1", 25.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0842 G4VSolid* down2 = new G4Box("down2", 10.*mm, 11.5*mm, 13/2.*mm);
0843 G4VSolid* down_uni1 = new G4UnionSolid("down_uni1", down1 , down2, 0, G4ThreeVector(52.*mm, 0.*mm, 0.*mm));
0844 G4VSolid* down_uni2 = new G4UnionSolid("down_uni2", down_uni1, down2, 0, G4ThreeVector(-52.*mm, 0.*mm, 0.*mm));
0845 return down_uni2 ;
0846 }
0847
0848
0849 const G4VSolid* U4SolidMaker::AnnulusCrossTwoBoxUnion(const char* name)
0850 {
0851 G4VSolid* down1 = new G4Tubs("down1", 25.*mm, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0852 G4VSolid* down2 = new G4Box("down2", 10.*mm, 11.5*mm, 13/2.*mm);
0853 G4VSolid* down_uni1 = new G4UnionSolid("down_uni1", down1 , down2, 0, G4ThreeVector(52.*mm, 0.*mm, 0.*mm));
0854
0855 G4VSolid* down3 = new G4Box("down3", 15.*mm, 15.*mm, 13/2.*mm);
0856 G4VSolid* down_uni3 = new G4UnionSolid("down_uni3", down_uni1, down3, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0857
0858 return down_uni3 ;
0859 }
0860
0861
0862
0863
0864
0865
0866
0867
0868
0869
0870 const G4VSolid* U4SolidMaker::AnnulusFourBoxUnion_(const char* name, G4double inner_radius )
0871 {
0872
0873 G4VSolid* down1 = new G4Tubs("down1", inner_radius, 45.*mm, 13./2*mm, 0.*deg, 360.*deg);
0874 G4VSolid* down2 = new G4Box("down2", 10.*mm, 11.5*mm, 13/2.*mm);
0875 G4VSolid* down_uni1 = new G4UnionSolid("down_uni1", down1 , down2, 0, G4ThreeVector(52.*mm, 0.*mm, 0.*mm));
0876 G4VSolid* down_uni2 = new G4UnionSolid("down_uni2", down_uni1, down2, 0, G4ThreeVector(-52.*mm, 0.*mm, 0.*mm));
0877 G4VSolid* down3 = new G4Box("down3", 15.*mm, 15.*mm, 13/2.*mm);
0878 G4VSolid* down_uni3 = new G4UnionSolid("down_uni3", down_uni2, down3, 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0879 G4VSolid* down_uni4 = new G4UnionSolid("down_uni4", down_uni3, down3, 0, G4ThreeVector(0.*mm, -50.*mm, 0.*mm));
0880 return down_uni4 ;
0881 }
0882
0883 const G4VSolid* U4SolidMaker::AnnulusFourBoxUnion(const char* name){ return AnnulusFourBoxUnion_(name, 25.*mm ); }
0884 const G4VSolid* U4SolidMaker::CylinderFourBoxUnion(const char* name){ return AnnulusFourBoxUnion_(name, 0.*mm ); }
0885
0886
0887
0888
0889
0890
0891
0892
0893
0894
0895
0896
0897
0898
0899
0900
0901
0902
0903
0904
0905
0906
0907
0908
0909
0910
0911
0912
0913
0914
0915
0916
0917
0918
0919
0920
0921
0922
0923
0924
0925
0926
0927
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938 const G4VSolid* U4SolidMaker::BoxFourBoxUnion_(const char* name, const char* opt )
0939 {
0940 G4VSolid* cbo = new G4Box("cbo", 45.*mm, 45.*mm, 45.*mm );
0941 G4VSolid* xbo = new G4Box("xbo", 10.*mm, 11.5*mm, 13/2.*mm);
0942 G4VSolid* ybo = new G4Box("ybo", 15.*mm, 15.*mm, 13/2.*mm);
0943
0944 bool px = strstr(opt, "+X");
0945 bool nx = strstr(opt, "-X");
0946 bool py = strstr(opt, "+Y");
0947 bool ny = strstr(opt, "-Y");
0948
0949 G4VSolid* comb = nullptr ;
0950 unsigned idx = 0 ;
0951
0952 if(true)
0953 {
0954 comb = PrimitiveClone(cbo,"cbo",idx) ;
0955 idx += 1 ;
0956 }
0957 if(px)
0958 {
0959 comb = new G4UnionSolid(Name("cpx",idx), comb, PrimitiveClone(xbo,"bpx",idx+1), 0, G4ThreeVector(52.*mm, 0.*mm, 0.*mm));
0960 idx += 2 ;
0961 }
0962 if(nx)
0963 {
0964 comb = new G4UnionSolid(Name("cnx",idx), comb, PrimitiveClone(xbo,"bnx",idx+1), 0, G4ThreeVector(-52.*mm, 0.*mm, 0.*mm));
0965 idx += 2 ;
0966 }
0967 if(py)
0968 {
0969 comb = new G4UnionSolid(Name("cpy",idx), comb, PrimitiveClone(ybo,"bpy",idx+1), 0, G4ThreeVector(0.*mm, 50.*mm, 0.*mm));
0970 idx += 2 ;
0971 }
0972 if(ny)
0973 {
0974 comb = new G4UnionSolid(Name("cny",idx), comb, PrimitiveClone(ybo,"bny",idx+1), 0, G4ThreeVector(0.*mm, -50.*mm, 0.*mm));
0975 idx += 2 ;
0976 }
0977
0978 return comb ;
0979 }
0980
0981 const G4VSolid* U4SolidMaker::BoxFourBoxUnion(const char* name ){ return BoxFourBoxUnion_(name, "+X,-X,+Y,-Y") ; }
0982 const G4VSolid* U4SolidMaker::BoxCrossTwoBoxUnion(const char* name ){ return BoxFourBoxUnion_(name, "+X,+Y") ; }
0983 const G4VSolid* U4SolidMaker::BoxThreeBoxUnion(const char* name ){ return BoxFourBoxUnion_(name, "+X,+Y,-Y") ; }
0984
0985
0986
0987 const G4VSolid* U4SolidMaker::BoxFourBoxContiguous_(const char* name, const char* opt )
0988 {
0989 G4VSolid* cbo = new G4Box("cbo", 45.*mm, 45.*mm, 45.*mm );
0990 G4VSolid* xbo = new G4Box("xbo", 10.*mm, 11.5*mm, 13/2.*mm);
0991 G4VSolid* ybo = new G4Box("ybo", 15.*mm, 15.*mm, 13/2.*mm);
0992
0993 bool px = strstr(opt, "+X");
0994 bool nx = strstr(opt, "-X");
0995 bool py = strstr(opt, "+Y");
0996 bool ny = strstr(opt, "-Y");
0997
0998 G4VSolid* item ;
0999 unsigned idx = 0 ;
1000 G4MultiUnion* comb = new G4MultiUnion(name);
1001 G4RotationMatrix rot(0, 0, 0);
1002
1003 if(true)
1004 {
1005 G4ThreeVector pos(0.*mm, 0.*mm, 0.*mm);
1006 G4Transform3D tr(rot, pos);
1007 item = PrimitiveClone(cbo,"cbo",idx) ;
1008 comb->AddNode(*item, tr);
1009 idx+=1 ;
1010 }
1011 if(px)
1012 {
1013 G4ThreeVector pos(52.*mm, 0.*mm, 0.*mm);
1014 G4Transform3D tr(rot, pos);
1015 item = PrimitiveClone(xbo,"bpx",idx) ;
1016 comb->AddNode(*item, tr);
1017 idx+=1 ;
1018 }
1019 if(nx)
1020 {
1021 G4ThreeVector pos(-52.*mm, 0.*mm, 0.*mm);
1022 G4Transform3D tr(rot, pos);
1023 item = PrimitiveClone(xbo,"bnx",idx) ;
1024 comb->AddNode(*item, tr);
1025 idx += 1 ;
1026 }
1027 if(py)
1028 {
1029 G4ThreeVector pos(0.*mm, 50.*mm, 0.*mm);
1030 G4Transform3D tr(rot, pos);
1031 item = PrimitiveClone(ybo,"bpy",idx) ;
1032 comb->AddNode(*item, tr);
1033 idx += 1 ;
1034 }
1035 if(ny)
1036 {
1037 G4ThreeVector pos(0.*mm, -50.*mm, 0.*mm);
1038 G4Transform3D tr(rot, pos);
1039 item = PrimitiveClone(ybo,"bny",idx) ;
1040 comb->AddNode(*item, tr);
1041 idx += 1 ;
1042 }
1043 return comb ;
1044 }
1045
1046
1047 const G4VSolid* U4SolidMaker::BoxFourBoxContiguous(const char* name ){ return BoxFourBoxContiguous_(name, "-X,+X,+Y,-Y") ; }
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125 G4VSolid* U4SolidMaker::Uncoincide_Box_Box_Union( const G4VSolid* bbu )
1126 {
1127 LOG(info) << " bbu.GetName " << bbu->GetName() ;
1128
1129 const G4BooleanSolid* bs = dynamic_cast<const G4BooleanSolid*>(bbu) ;
1130
1131 const G4VSolid* a = bs->GetConstituentSolid(0) ;
1132 const G4VSolid* _b = bs->GetConstituentSolid(1) ;
1133 const G4DisplacedSolid* _b_disp = dynamic_cast<const G4DisplacedSolid*>(_b) ;
1134 G4ThreeVector b_tla = _b_disp->GetObjectTranslation();
1135 const G4VSolid* b = _b_disp->GetConstituentMovedSolid() ;
1136
1137 LOG(info) << " a.GetName " << a->GetName() ;
1138 LOG(info) << " _b.GetName " << _b->GetName() ;
1139 LOG(info) << " _b_disp.GetName " << _b_disp->GetName() ;
1140 LOG(info) << " b.GetName " << b->GetName() ;
1141 LOG(info) << " b_tla " << Desc(&b_tla) ;
1142
1143 const G4Box* a_box = dynamic_cast<const G4Box*>(a);
1144 const G4Box* b_box = dynamic_cast<const G4Box*>(b);
1145 LOG(info) << " a_box " << Desc(a_box) ;
1146 LOG(info) << " b_box " << Desc(b_box) ;
1147
1148 G4ThreeVector new_tla(b_tla);
1149
1150 std::string new_name = bs->GetName() ;
1151
1152 G4Box* new_a = new G4Box(a->GetName(), a_box->GetXHalfLength(), a_box->GetYHalfLength(), a_box->GetZHalfLength() );
1153 G4Box* new_b = new G4Box(b->GetName(), b_box->GetXHalfLength(), b_box->GetYHalfLength(), b_box->GetZHalfLength() );
1154
1155 int shift_axis = OneAxis(&b_tla);
1156 LOG(info) << " shift_axis " << shift_axis ;
1157
1158
1159
1160 enum { A, B, UNKNOWN } ;
1161 int smaller = UNKNOWN ;
1162
1163 for(int axis=0 ; axis < 3 ; axis++)
1164 {
1165 if(axis == shift_axis) continue ;
1166 double ah = HalfLength(a_box, axis);
1167 double bh = HalfLength(b_box, axis);
1168 if(ah == bh) continue ;
1169 smaller = ah < bh ? A : B ;
1170 }
1171
1172 LOG(info) << " smaller " << smaller ;
1173
1174
1175 double uncoincide = 1.*mm ;
1176 if(smaller != UNKNOWN )
1177 {
1178 G4Box* smaller_box = smaller == A ? new_a : new_b ;
1179 LOG(info) << " smaller_box.GetName " << smaller_box->GetName() ;
1180
1181 ChangeBoxHalfLength( smaller_box, shift_axis, uncoincide/2. );
1182
1183 ChangeThreeVector( &new_tla , shift_axis, uncoincide/2. ) ;
1184 }
1185 else
1186 {
1187 LOG(fatal) << " failed to uncoincide " ;
1188 }
1189
1190 G4UnionSolid* new_bbu = new G4UnionSolid( new_name, new_a, new_b, 0, new_tla );
1191 return new_bbu ;
1192 }
1193
1194
1195 double U4SolidMaker::HalfLength( const G4Box* box, int axis )
1196 {
1197 double value = 0. ;
1198 switch(axis)
1199 {
1200 case X: value = box->GetXHalfLength() ; break ;
1201 case Y: value = box->GetYHalfLength() ; break ;
1202 case Z: value = box->GetZHalfLength() ; break ;
1203 }
1204 return value ;
1205 }
1206
1207 void U4SolidMaker::ChangeThreeVector( G4ThreeVector* v, int axis, double delta )
1208 {
1209 if( v == nullptr ) return ;
1210 switch(axis)
1211 {
1212 case X: v->setX(v->x() + delta) ; break ;
1213 case Y: v->setY(v->y() + delta) ; break ;
1214 case Z: v->setZ(v->z() + delta) ; break ;
1215 }
1216 }
1217 void U4SolidMaker::ChangeBoxHalfLength( G4Box* box, int axis, double delta )
1218 {
1219 switch(axis)
1220 {
1221 case X: box->SetXHalfLength(box->GetXHalfLength() + delta) ; break ;
1222 case Y: box->SetYHalfLength(box->GetYHalfLength() + delta) ; break ;
1223 case Z: box->SetZHalfLength(box->GetZHalfLength() + delta) ; break ;
1224 }
1225 }
1226
1227
1228
1229
1230
1231
1232 int U4SolidMaker::OneAxis( const G4ThreeVector* v )
1233 {
1234 double x = v ? v->x() : 0. ;
1235 double y = v ? v->y() : 0. ;
1236 double z = v ? v->z() : 0. ;
1237 int axis = ERR ;
1238 if( x != 0. && y == 0. && z == 0. ) axis = X ;
1239 if( x == 0. && y != 0. && z == 0. ) axis = Y ;
1240 if( x == 0. && y == 0. && z != 0. ) axis = Z ;
1241 return axis ;
1242 }
1243
1244
1245
1246 std::string U4SolidMaker::Desc( const G4Box* box )
1247 {
1248 std::stringstream ss ;
1249 ss
1250 << "("
1251 << std::fixed << std::setw(10) << std::setprecision(3) << box->GetXHalfLength() << " "
1252 << std::fixed << std::setw(10) << std::setprecision(3) << box->GetYHalfLength() << " "
1253 << std::fixed << std::setw(10) << std::setprecision(3) << box->GetZHalfLength()
1254 << ") "
1255 << box->GetName()
1256 ;
1257 std::string s = ss.str();
1258 return s ;
1259 }
1260
1261 std::string U4SolidMaker::Desc( const G4ThreeVector* v )
1262 {
1263 std::stringstream ss ;
1264 ss
1265 << "("
1266 << std::fixed << std::setw(10) << std::setprecision(3) << (v ? v->x() : 0. ) << " "
1267 << std::fixed << std::setw(10) << std::setprecision(3) << (v ? v->y() : 0. ) << " "
1268 << std::fixed << std::setw(10) << std::setprecision(3) << (v ? v->z() : 0. )
1269 << ") "
1270 ;
1271 std::string s = ss.str();
1272 return s ;
1273 }
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313 const int U4SolidMaker::XJanchorConstruction_debug_mode = ssys::getenvint("U4SolidMaker__XJanchorConstruction_debug_mode", 0 ) ;
1314
1315 const G4VSolid* U4SolidMaker::XJanchorConstruction(const char* name)
1316 {
1317 bool do_uncoincide = false ;
1318 bool do_noball = false ;
1319
1320 switch(XJanchorConstruction_debug_mode)
1321 {
1322 case 0: do_uncoincide = false ; do_noball = false ; break ;
1323 case 1: do_uncoincide = true ; do_noball = false ; break ;
1324 case 2: do_uncoincide = false ; do_noball = true ; break ;
1325 case 3: do_uncoincide = true ; do_noball = true ; break ;
1326 }
1327
1328 double uncoincide = do_uncoincide ? 1. : 0. ;
1329
1330 LOG(info)
1331 << " U4SolidMaker__XJanchorConstruction_debug_mode " << XJanchorConstruction_debug_mode
1332 << " do_uncoincide " << do_uncoincide
1333 << " uncoincide " << uncoincide
1334 << " do_noball " << do_noball
1335 ;
1336
1337
1338 G4VSolid* solidXJanchor_up;
1339 G4VSolid* solidXJanchor_down;
1340 G4VSolid* solidXJanchor_ball;
1341
1342 solidXJanchor_up = new G4Tubs("solidXJanchor_up", 0.*mm, 25.*mm, (13.+uncoincide)/2*mm, 0.*deg, 360.*deg);
1343 solidXJanchor_down = new G4Cons("solidXJanchor_down", 0.*mm, 47.*mm, 0.*mm, 73.*mm, 10.*mm, 0.*deg, 360.*deg);
1344 solidXJanchor_ball = new G4Sphere("solidXJanchor_ball", 0.*mm, 17820.*mm, 0.*deg, 360.*deg, 0.*deg, 180.*deg);
1345
1346 G4SubtractionSolid* solidXJanchor_sub_ = new G4SubtractionSolid("solidXJanchor_sub",solidXJanchor_down, solidXJanchor_ball, 0, G4ThreeVector(0.*mm, 0*mm, 17820.*mm));
1347 G4VSolid* solidXJanchor_sub = do_noball ? solidXJanchor_down : (G4VSolid*)solidXJanchor_sub_ ;
1348
1349 G4UnionSolid* solidXJanchor = new G4UnionSolid("solidXJanchor",solidXJanchor_sub, solidXJanchor_up, 0, G4ThreeVector(0.*mm, 0*mm,(-16.5 + uncoincide/2)*mm));
1350
1351 return solidXJanchor ;
1352 }
1353
1354
1355
1356
1357 const G4VSolid* U4SolidMaker::SJReceiverConstruction(const char* name)
1358 {
1359 #ifdef DIRTY
1360 G4VSolid* solidSJReceiver_up ;
1361 G4VSolid* solidSJReceiver_down ;
1362 G4VSolid* solidSJReceiver_box ;
1363 G4VSolid* solidSJReceiver_ball ;
1364
1365
1366 solidSJReceiver_up = new G4Tubs("solidXJanchor_up", 0.*mm, 25.*mm, 13./2*mm, 0.*deg, 360.*deg);
1367 solidSJReceiver_down = new G4Cons("solidSJReceiver_down", 0.*mm, 73.*mm, 0.*mm, 47.*mm, 10.*mm, 0.*deg, 360.*deg);
1368
1369 solidSJReceiver_box = new G4Box("solidSJReceiver_box", 17780.*mm, 17780.*mm, 17780.*mm);
1370 solidSJReceiver_ball = new G4Sphere("solidSJReceiver_ball", 0.*mm, 17700.*mm, 0.*deg, 360.*deg, 0.*deg, 180.*deg);
1371 G4SubtractionSolid* solidSphere_sub = new G4SubtractionSolid("solidSphere_sub", solidSJReceiver_box, solidSJReceiver_ball);
1372 G4SubtractionSolid* solidSJReceiver_sub = new G4SubtractionSolid("solidSJReceiver_sub",solidSJReceiver_down, solidSJReceiver_ball, 0, G4ThreeVector(0.*mm, 0*mm, 17699.938*mm));
1373 G4UnionSolid* solidSJReceiver = new G4UnionSolid("solidSJReceiver",solidSJReceiver_sub, solidSJReceiver_up, 0, G4ThreeVector(0.*mm, 0*mm,16.5*mm));
1374 #else
1375 G4VSolid* solidSJReceiver_up ;
1376 G4VSolid* solidSJReceiver_down ;
1377 G4VSolid* solidSJReceiver_ball ;
1378
1379 solidSJReceiver_up = new G4Tubs("solidXJanchor_up", 0.*mm, 25.*mm, 13./2*mm, 0.*deg, 360.*deg);
1380 solidSJReceiver_down = new G4Cons("solidSJReceiver_down", 0.*mm, 73.*mm, 0.*mm, 47.*mm, 10.*mm, 0.*deg, 360.*deg);
1381 solidSJReceiver_ball = new G4Sphere("solidSJReceiver_ball", 0.*mm, 17700.*mm, 0.*deg, 360.*deg, 0.*deg, 180.*deg);
1382 G4SubtractionSolid* solidSJReceiver_sub = new G4SubtractionSolid("solidSJReceiver_sub",solidSJReceiver_down, solidSJReceiver_ball, 0, G4ThreeVector(0.*mm, 0*mm, 17699.938*mm));
1383 G4UnionSolid* solidSJReceiver = new G4UnionSolid("solidSJReceiver",solidSJReceiver_sub, solidSJReceiver_up, 0, G4ThreeVector(0.*mm, 0*mm,16.5*mm));
1384 #endif
1385 return solidSJReceiver ;
1386 }
1387
1388
1389
1390
1391 const G4VSolid* U4SolidMaker::BoxMinusTubs0(const char* name)
1392 {
1393 double tubs_hz = 15.2*mm ;
1394 double zshift = 0*mm ;
1395 G4VSolid* box = new G4Box("box", 250*mm, 250*mm, 100*mm );
1396 G4VSolid* tubs = new G4Tubs("tubs",120*mm,208*mm,tubs_hz,0.0*deg,360.0*deg);
1397 G4VSolid* box_minus_tubs = new G4SubtractionSolid(name,box,tubs,0,G4ThreeVector(0.*mm,0.*mm,zshift));
1398 return box_minus_tubs ;
1399 }
1400
1401 const G4VSolid* U4SolidMaker::BoxMinusTubs1(const char* name)
1402 {
1403 double tubs_hz = 15.2*mm ;
1404 G4VSolid* box = new G4Box("box", 250*mm, 250*mm, 100*mm );
1405 G4VSolid* tubs = new G4Tubs("tubs",120*mm,208*mm,tubs_hz,0.0*deg,360.0*deg);
1406 G4VSolid* box_minus_tubs = new G4SubtractionSolid(name,box,tubs);
1407 return box_minus_tubs ;
1408 }
1409
1410 const G4VSolid* U4SolidMaker::BoxMinusOrb(const char* name)
1411 {
1412 double radius = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_radius", 130.f) ;
1413
1414 double sx = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_sx", 100.f) ;
1415 double sy = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_sy", 100.f) ;
1416 double sz = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_sz", 100.f) ;
1417
1418 double dx = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_dx", 0.f) ;
1419 double dy = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_dy", 0.f) ;
1420 double dz = ssys::getenvfloat("U4SolidMaker_BoxMinusOrb_dz", 0.f) ;
1421
1422 G4VSolid* box = new G4Box("box", sx, sy, sz );
1423 G4VSolid* orb = new G4Orb("orb", radius );
1424
1425 G4VSolid* box_minus_orb = new G4SubtractionSolid(name,box,orb,nullptr, G4ThreeVector(dx, dy, dz) );
1426 return box_minus_orb ;
1427 }
1428
1429
1430 const G4VSolid* U4SolidMaker::PolyconeWithMultipleRmin(const char* name)
1431 {
1432 double ZUpper4[4];
1433 double RminUpper4[4];
1434 double RmaxUpper4[4];
1435 ZUpper4[0] = 0*mm; RminUpper4[0] = 43.*mm; RmaxUpper4[0] = 195.*mm;
1436 ZUpper4[1] = -15*mm; RminUpper4[1] = 43.*mm; RmaxUpper4[1] = 195.*mm;
1437 ZUpper4[2] = -15*mm; RminUpper4[2] = 55.5*mm; RmaxUpper4[2] = 70.*mm;
1438 ZUpper4[3] = -101*mm; RminUpper4[3] = 55.5*mm; RmaxUpper4[3] = 70.*mm;
1439
1440 G4VSolid* base_steel = new G4Polycone("base_steel",0.0*deg,360.0*deg,4,ZUpper4,RminUpper4,RmaxUpper4);
1441 return base_steel ;
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457
1458
1459
1460
1461
1462
1463
1464 const G4VSolid* U4SolidMaker::PolyconeWithPhiCut(const char* name)
1465 {
1466 const int N = 2 ;
1467
1468 double ZPlane[N] = { -50*mm , 50*mm } ;
1469 double Rmin[N] = { 0*mm , 0*mm } ;
1470 double Rmax[N] = { 200*mm , 200*mm } ;
1471
1472 double phiStart = 30.0*deg ;
1473 double phiDelta = 30.0*deg ;
1474 G4VSolid* polycone = new G4Polycone(name,phiStart,phiDelta,Z,ZPlane,Rmin,Rmax);
1475 return polycone ;
1476 }
1477
1478
1479
1480
1481
1482
1483
1484
1485
1486
1487
1488
1489
1490
1491
1492
1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
1506 const G4VSolid* U4SolidMaker::PolyconeWithPhiCutHalf(const char* name)
1507 {
1508 const int N = 2 ;
1509 double ZPlane[N] = { -50*mm , 50*mm } ;
1510 double Rmin[N] = { 0*mm , 0*mm } ;
1511 double Rmax[N] = { 200*mm , 200*mm } ;
1512
1513 double phiStart = 0.0*deg ;
1514 double phiDelta = 180.0*deg ;
1515 G4VSolid* polycone = new G4Polycone(name,phiStart,phiDelta,Z,ZPlane,Rmin,Rmax);
1516 return polycone ;
1517 }
1518
1519
1520
1521
1522
1523
1524
1525
1526 const G4VSolid* U4SolidMaker::UnionOfHemiEllipsoids(const char* name )
1527 {
1528 assert( strstr( name, "UnionOfHemiEllipsoids" ) != nullptr );
1529
1530 std::vector<long> vals ;
1531 sstr::Extract(vals, name);
1532 long iz = vals.size() > 0 ? vals[0] : 0 ;
1533
1534 std::cout
1535 << "U4SolidMaker::UnionOfHemiEllipsoids"
1536 << " name " << name
1537 << " vals.size " << vals.size()
1538 << " iz " << iz
1539 << std::endl
1540 ;
1541
1542
1543 double rx = 150. ;
1544 double ry = 150. ;
1545 double rz = 100. ;
1546
1547 double z2 = rz ;
1548 double z1 = 0. ;
1549 double z0 = -rz ;
1550
1551 G4VSolid* upper = new G4Ellipsoid("upper", rx, ry, rz, z1, z2 );
1552 G4VSolid* lower = new G4Ellipsoid("lower", rx, ry, rz, z0, z1 );
1553
1554 G4VSolid* solid = nullptr ;
1555 if( iz == 0 )
1556 {
1557 solid = new G4UnionSolid(name, upper, lower );
1558 }
1559 else
1560 {
1561 double zoffset = double(iz) ;
1562 G4ThreeVector tlate(0., 0., zoffset) ;
1563 solid = new G4UnionSolid(name, upper, lower, nullptr, tlate );
1564 }
1565 return solid ;
1566 }
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583
1584 const G4VSolid* U4SolidMaker::OrbOrbMultiUnion(const char* name )
1585 {
1586 long num = sstr::ExtractLong(name, 1) ;
1587 G4MultiUnion* comb = new G4MultiUnion(name);
1588
1589 G4RotationMatrix rot(0, 0, 0);
1590 G4Orb* orb = new G4Orb("Orb", 50.) ;
1591
1592 for(long i=-num ; i <= num ; i++)
1593 {
1594 G4ThreeVector tlate( double(i)*100.*mm, 0.*mm, 0.*mm);
1595 G4Transform3D tr(rot, tlate) ;
1596 comb->AddNode( *orb, tr );
1597 }
1598
1599 return comb ;
1600 }
1601
1602
1603
1604
1605
1606
1607
1608
1609
1610
1611
1612
1613
1614
1615
1616
1617 const G4VSolid* U4SolidMaker::GridMultiUnion_(const char* name, G4VSolid* item, double gridspace, int nx, int ny, int nz )
1618 {
1619 G4MultiUnion* grid = new G4MultiUnion(name);
1620
1621 for(int i=-nx ; i <= nx ; i++ )
1622 for(int j=-ny ; j <= ny ; j++ )
1623 for(int k=-nz ; k <= nz ; k++ )
1624 {
1625 G4ThreeVector pos(double(i)*gridspace*mm, double(j)*gridspace*mm, double(k)*gridspace*mm );
1626 LOG(info) << pos ;
1627
1628 G4RotationMatrix rot(0, 0, 0);
1629 G4Transform3D tr(rot, pos);
1630 grid->AddNode(*item, tr);
1631
1632 }
1633
1634 grid->Voxelize();
1635 return grid ;
1636 }
1637
1638
1639
1640
1641
1642
1643
1644
1645
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665 const G4VSolid* U4SolidMaker::OrbGridMultiUnion(const char* name)
1666 {
1667 std::vector<long> vals ;
1668 sstr::Extract(vals, name);
1669
1670 assert( vals.size() == 2 );
1671
1672 double radius(vals[0]) ;
1673 double gridscale(vals[1]) ;
1674
1675 LOG(info)
1676 << " name " << name
1677 << " radius " << radius
1678 << " gridscale " << gridscale
1679 ;
1680
1681 G4VSolid* item = new G4Orb("orb", radius*mm );
1682
1683 int nx = 3 ;
1684 int ny = 3 ;
1685 int nz = 3 ;
1686
1687 return GridMultiUnion_(name, item, gridscale, nx, ny, nz );
1688 }
1689
1690
1691
1692
1693
1694
1695
1696
1697
1698
1699
1700
1701
1702
1703 const G4VSolid* U4SolidMaker::BoxGridMultiUnion(const char* name)
1704 {
1705 std::vector<long> vals ;
1706 sstr::Extract(vals, name);
1707
1708 assert( vals.size() == 2 );
1709
1710 double halfside(vals[0]) ;
1711 double gridscale(vals[1]) ;
1712
1713 LOG(info)
1714 << " name " << name
1715 << " halfside " << halfside
1716 << " gridscale " << gridscale
1717 ;
1718
1719 G4VSolid* item = new G4Box("box", halfside*mm, halfside*mm, halfside*mm );
1720
1721 int nx = 3 ;
1722 int ny = 3 ;
1723 int nz = 3 ;
1724
1725 return GridMultiUnion_(name, item, gridscale, nx, ny, nz );
1726 }
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
1738
1739
1740
1741
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752
1753
1754
1755
1756
1757
1758
1759
1760
1761
1762
1763
1764
1765
1766
1767
1768
1769
1770
1771
1772
1773
1774
1775 const G4VSolid* U4SolidMaker::LHCbRichSphMirr(const char* qname)
1776 {
1777 long mode = sstr::ExtractLong(qname, 0);
1778 LOG(LEVEL) << " qname " << qname << " mode " << mode ;
1779
1780
1781
1782 const G4double InnerRadius = 3650.0 * CLHEP::mm;
1783 const G4double Thickness = 1.5 * CLHEP::mm;
1784 const G4double OuterRadius = InnerRadius + Thickness ;
1785
1786 const G4double SegmentSizeX = 1500.0 * CLHEP::mm;
1787 const G4double SegmentSizeZ = SegmentSizeX ;
1788 const G4double SegmentSizeY = 650.0 * CLHEP::mm;
1789
1790
1791
1792 const G4double DeltaExtendedFactor = 1.2;
1793 const G4double DeltaTheta = 2 * asin(SegmentSizeX/(2.0*InnerRadius)) * DeltaExtendedFactor * CLHEP::rad;
1794 const G4double DeltaPhi = 2 * asin(SegmentSizeY/(2.0*InnerRadius) )* DeltaExtendedFactor * CLHEP::rad;
1795 const G4double ThetaStart = (0.5 * CLHEP::pi * CLHEP::rad) - (0.5 * DeltaTheta) ;
1796 const G4double PhiStart = -0.5 * DeltaPhi ;
1797 const G4double SubLargeSize = 5000 * CLHEP::mm;
1798 const G4double SubHalfSizeX = SubLargeSize;
1799 const G4double SubHalfSizeY = SubLargeSize;
1800 const G4double SubHalfSizeZ = SubLargeSize;
1801 const G4double SubPosX = 0.0 * CLHEP::mm;
1802 const G4double SubPosY = 0.0 * CLHEP::mm;
1803 const G4double SubUpPosY = (0.5 * SegmentSizeY) + SubHalfSizeY;
1804 const G4double SubDownPosY = -1.0 * SubUpPosY ;
1805 const G4double SubPosZ = 0.0 * CLHEP::mm;
1806 const G4double SubRightPosZ =(0.5 * SegmentSizeX) + SubHalfSizeZ;
1807 const G4double SubLeftPosZ = -1.0* SubRightPosZ;
1808
1809
1810
1811
1812
1813 G4Sphere* SphFullSph = new G4Sphere ("SphFullSphDEV",InnerRadius,
1814 OuterRadius,PhiStart,
1815 DeltaPhi, ThetaStart,
1816 DeltaTheta);
1817 G4Box * SphSubBox = new G4Box("SphSubBox",SubHalfSizeX,
1818 SubHalfSizeY, SubHalfSizeZ);
1819 G4RotationMatrix SubBoxRot;
1820 G4ThreeVector SubBoxTPos ( SubPosX,SubUpPosY,SubPosZ);
1821 G4ThreeVector SubBoxBPos ( SubPosX,SubDownPosY,SubPosZ);
1822 G4ThreeVector SubBoxLPos ( SubPosX,SubPosY,SubLeftPosZ);
1823 G4ThreeVector SubBoxRPos ( SubPosX,SubPosY,SubRightPosZ);
1824 G4Transform3D SubBoxTTrans( SubBoxRot, SubBoxTPos);
1825 G4Transform3D SubBoxBTrans( SubBoxRot, SubBoxBPos);
1826 G4Transform3D SubBoxLTrans( SubBoxRot, SubBoxLPos);
1827 G4Transform3D SubBoxRTrans( SubBoxRot, SubBoxRPos);
1828 G4SubtractionSolid* TSph = new G4SubtractionSolid("SphTSph",SphFullSph,
1829 SphSubBox , SubBoxTTrans);
1830 G4SubtractionSolid* BSph = new G4SubtractionSolid("SphBSphBox",TSph,
1831 SphSubBox , SubBoxBTrans);
1832 G4SubtractionSolid* LSph = new G4SubtractionSolid("SphLSphBox",BSph,
1833 SphSubBox , SubBoxLTrans);
1834 G4SubtractionSolid* RSph = new G4SubtractionSolid("SphRSphBox",LSph,
1835 SphSubBox , SubBoxRTrans);
1836
1837
1838 const G4VSolid* simple = nullptr ;
1839 if( mode == 1 )
1840 {
1841 G4double MiddleRadius = (InnerRadius + OuterRadius)/2. ;
1842
1843 G4Orb* inner = new G4Orb("inner", InnerRadius );
1844 G4Orb* outer = new G4Orb("outer", OuterRadius );
1845 G4SubtractionSolid* shell = new G4SubtractionSolid("shell", outer, inner );
1846
1847 G4double sag_max = SagittaMax( InnerRadius, OuterRadius, SegmentSizeY, SegmentSizeZ );
1848 G4double SagMax = 80.*mm ;
1849 bool sag_max_expect = SagMax > sag_max ;
1850 assert( sag_max_expect );
1851 if(!sag_max_expect) std::raise(SIGINT);
1852 G4double FullDepthX = Thickness + SagMax ;
1853
1854 G4Box* cutbox = new G4Box("cutbox", FullDepthX/2. , SegmentSizeY/2. , SegmentSizeZ/2. );
1855 simple = new G4IntersectionSolid("simple_CSG_EXBB", shell, cutbox, 0, G4ThreeVector(MiddleRadius, 0., 0.) ) ;
1856 }
1857
1858
1859 const G4VSolid* solid = nullptr ;
1860 switch(mode)
1861 {
1862 case 0: solid = RSph ; break ;
1863 case 1: solid = simple ; break ;
1864 }
1865 assert(solid);
1866 return solid ;
1867 }
1868
1869
1870
1871
1872
1873
1874
1875
1876
1877
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889
1890
1891
1892
1893
1894
1895
1896
1897
1898
1899
1900
1901
1902
1903
1904
1905
1906
1907 G4double U4SolidMaker::Sagitta( G4double radius, G4double chord )
1908 {
1909 G4double sagitta = radius - sqrt( radius*radius - chord*chord/4. ) ;
1910 return sagitta ;
1911 }
1912
1913 G4double U4SolidMaker::SagittaMax( G4double radius, G4double sy, G4double sz )
1914 {
1915 G4double sag_sy = Sagitta( radius, sy );
1916 G4double sag_sz = Sagitta( radius, sz );
1917 G4double sag_max = std::max( sag_sy, sag_sz );
1918 return sag_max ;
1919 }
1920
1921 G4double U4SolidMaker::SagittaMax( G4double InnerRadius, G4double OuterRadius, G4double sy, G4double sz )
1922 {
1923 G4double sag_inner = SagittaMax( InnerRadius, sy, sz );
1924 G4double sag_outer = SagittaMax( OuterRadius, sy, sz );
1925 G4double sag_max = std::max( sag_inner, sag_outer );
1926
1927 LOG(LEVEL)
1928 << " InnerRadius " << InnerRadius
1929 << " OuterRadius " << OuterRadius
1930 << " sag_max " << sag_max
1931 << std::endl
1932 << " sag_inner : SaggitaMax(" << InnerRadius << "," << sy << "," << sz << ")" << sag_inner
1933 << std::endl
1934 << " sag_outer : SaggitaMax(" << OuterRadius << "," << sy << "," << sz << ")" << sag_outer
1935 << std::endl
1936 ;
1937
1938 return sag_max ;
1939 }
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
1954
1955
1956
1957
1958
1959
1960
1961
1962
1963
1964
1965
1966
1967
1968
1969
1970
1971
1972
1973
1974
1975
1976
1977
1978
1979
1980
1981
1982
1983
1984
1985
1986
1987
1988
1989
1990
1991
1992
1993
1994
1995
1996
1997
1998
1999
2000
2001
2002
2003
2004
2005
2006
2007
2008
2009
2010 const G4VSolid* U4SolidMaker::LHCbRichFlatMirr(const char* qname)
2011 {
2012 long mode = sstr::ExtractLong(qname, 0);
2013 LOG(LEVEL) << " qname " << qname << " mode " << mode ;
2014
2015
2016
2017
2018
2019
2020
2021 const G4double InnerRadius = 5000.0 * CLHEP::m;
2022 const G4double Thickness = 6.0 * CLHEP::mm;
2023 const G4double OuterRadius = InnerRadius + Thickness ;
2024 const G4double MiddleRadius = (InnerRadius + OuterRadius)/2. ;
2025
2026
2027 const G4double SegmentSizeX = 1480.0 * CLHEP::mm;
2028 const G4double SegmentSizeZ = SegmentSizeX ;
2029
2030 const G4double SegmentSizeY = 880.0 * CLHEP::mm;
2031
2032
2033
2034
2035
2036
2037
2038
2039
2040
2041
2042
2043
2044
2045
2046
2047
2048
2049 const G4double DeltaTheta = asin(SegmentSizeX/InnerRadius) * CLHEP::rad;
2050 const G4double DeltaPhi = asin(SegmentSizeY/InnerRadius) * CLHEP::rad;
2051 const G4double StartTheta = (0.5 * CLHEP::pi * CLHEP::rad) - (0.5* DeltaTheta);
2052 const G4double StartPhi = -0.5 * DeltaPhi;
2053
2054 LOG(LEVEL)
2055 << " DeltaTheta " << DeltaTheta
2056 << " SegmentSizeX " << SegmentSizeX
2057 << " InnerRadius " << InnerRadius
2058 << " SegmentSizeX/InnerRadius " << SegmentSizeX/InnerRadius
2059 << " asin(SegmentSizeX/InnerRadius) " << asin(SegmentSizeX/InnerRadius)
2060 << " CLHEP::rad " << CLHEP::rad
2061 << " StartTheta " << StartTheta
2062 ;
2063
2064
2065 LOG(LEVEL)
2066 << " DeltaPhi " << DeltaPhi
2067 << " SegmentSizeY " << SegmentSizeY
2068 << " InnerRadius " << InnerRadius
2069 << " SegmentSizeY/InnerRadius " << SegmentSizeY/InnerRadius
2070 << " asin(SegmentSizeY/InnerRadius) " << asin(SegmentSizeY/InnerRadius)
2071 << " CLHEP::rad " << CLHEP::rad
2072 << " StartPhi " << StartPhi
2073 ;
2074
2075
2076
2077
2078
2079
2080
2081
2082
2083
2084
2085
2086 G4Sphere* RichTbR1FlatFull = new G4Sphere ("RichTbR1FlatFullDEV",InnerRadius,OuterRadius,StartPhi,DeltaPhi, StartTheta,DeltaTheta);
2087
2088
2089
2090 G4VSolid* solid = nullptr ;
2091 if( mode == 0 )
2092 {
2093 solid = RichTbR1FlatFull ;
2094 }
2095 else
2096 {
2097 LOG(LEVEL) << " constructing the flat mirror using intersection box rather than attemping to describe with miniscule thetacut and phicut angles" ;
2098
2099
2100 G4double sag_max = SagittaMax( InnerRadius, OuterRadius, SegmentSizeY, SegmentSizeZ );
2101 G4double SagMax = 1.*mm ;
2102 assert( SagMax > sag_max );
2103 G4double FullDepthX = Thickness + SagMax ;
2104
2105
2106 LOG(LEVEL)
2107 << " sag_max " << sag_max
2108 << " SagMax " << SagMax
2109 << " FullDepthX " << FullDepthX
2110 ;
2111
2112 G4Orb* outer = new G4Orb("outer",OuterRadius);
2113 G4Orb* inner = new G4Orb("inner",InnerRadius);
2114 G4SubtractionSolid* shell = new G4SubtractionSolid("shell", outer, inner );
2115 G4Box* box = new G4Box("box", FullDepthX/2. , SegmentSizeY/2. , SegmentSizeZ/2. );
2116
2117 std::string rootname = qname ;
2118 rootname += "_CSG_EXBB" ;
2119 solid = new G4IntersectionSolid( rootname, shell, box, 0, G4ThreeVector( MiddleRadius, 0., 0. ));
2120 }
2121
2122 return solid ;
2123 }
2124
2125
2126
2127
2128 const G4VSolid* U4SolidMaker::SphereIntersectBox(const char* qname)
2129 {
2130 G4double phiStart = 0. ;
2131 G4double phiDelta = 2. ;
2132 G4double thetaStart = 0. ;
2133 G4double thetaDelta = 1. ;
2134 G4Sphere* sph = new G4Sphere("sph", 95.*mm, 105.*mm, phiStart*CLHEP::pi, phiDelta*CLHEP::pi, thetaStart*CLHEP::pi, thetaDelta*CLHEP::pi );
2135 G4Box* box = new G4Box("box", 20.*mm, 20.*mm, 20.*mm );
2136 G4IntersectionSolid* sph_box = new G4IntersectionSolid("sph_box_CSG_EXBB", sph, box, 0, G4ThreeVector(0.*mm, 0.*mm, 100.*mm ) );
2137 return sph_box ;
2138 }
2139
2140
2141
2142
2143
2144
2145
2146
2147
2148
2149
2150
2151
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163 const G4VSolid* U4SolidMaker::LocalFastenerAcrylicConstruction(const char* name)
2164 {
2165 const char* PREFIX = "LocalFastenerAcrylicConstruction" ;
2166 assert( sstr::StartsWith(name,PREFIX ));
2167 int num_column = strlen(name) > strlen(PREFIX) ? std::atoi( name + strlen(PREFIX) ) : 8 ;
2168
2169 LOG(info)
2170 << " name " << ( name ? name : "-" )
2171 << " num_column " << num_column
2172 ;
2173
2174
2175 const char* screw_name = "screw_HINT_LISTNODE_PRIM_CONTIGUOUS" ;
2176
2177
2178 G4VSolid* uni_Addition(nullptr);
2179 {
2180 G4Tubs *IonRing = new G4Tubs("IonRing",123*mm,206.2*mm,7*mm,0.0*deg,360.0*deg);
2181 G4Tubs* screw = new G4Tubs(screw_name,0,13*mm,50.*mm,0.0*deg,360.0*deg);
2182 uni_Addition = IonRing;
2183 for(int i=0;i<num_column;i++)
2184 {
2185 G4ThreeVector tlate(164.*cos(i*pi/4)*mm, 164.*sin(i*pi/4)*mm,-65.0*mm);
2186 G4UnionSolid* uni1 = new G4UnionSolid("uni1",uni_Addition, screw, 0, tlate);
2187 uni_Addition = uni1;
2188 }
2189 }
2190 return uni_Addition ;
2191 }
2192
2193
2194
2195
2196
2197
2198
2199
2200
2201
2202
2203
2204
2205 const G4VSolid* U4SolidMaker::AltLocalFastenerAcrylicConstruction(const char* name)
2206 {
2207 [[maybe_unused]] const char* PREFIX = "AltLocalFastenerAcrylicConstruction" ;
2208 assert( sstr::StartsWith(name,PREFIX ));
2209 long num_column = sstr::ExtractLong(name, 1) ;
2210
2211 LOG(info)
2212 << " name " << ( name ? name : "-" )
2213 << " num_column " << num_column
2214 ;
2215
2216 assert( num_column > 0 );
2217
2218 G4Tubs* IonRing = new G4Tubs("IonRing",123*mm,206.2*mm,7*mm,0.0*deg,360.0*deg);
2219
2220 G4MultiUnion* muni = new G4MultiUnion(name);
2221 G4Tubs* screw = new G4Tubs("screw",0,13*mm,50.*mm,0.0*deg,360.0*deg);
2222
2223 G4RotationMatrix rot(0, 0, 0);
2224 for(long i=0;i<num_column;i++)
2225 {
2226 G4ThreeVector tlate(164.*cos(i*pi/4)*mm, 164.*sin(i*pi/4)*mm,-65.0*mm);
2227 G4Transform3D tr(rot, tlate) ;
2228 muni->AddNode( *screw, tr );
2229 }
2230
2231 G4UnionSolid* uni1 = new G4UnionSolid(name, IonRing, muni, 0, G4ThreeVector(0.,0.,0.));
2232 return uni1 ;
2233 }
2234
2235
2236
2237
2238
2239
2240
2241
2242
2243
2244
2245
2246
2247
2248
2249
2250 const G4VSolid* U4SolidMaker::BltLocalFastenerAcrylicConstruction(const char* name)
2251 {
2252 [[maybe_unused]] const char* PREFIX = "BltLocalFastenerAcrylicConstruction" ;
2253 assert( sstr::StartsWith(name,PREFIX ));
2254 const size_t num_column = sstr::ExtractSize(name, 1) ;
2255
2256 LOG(info)
2257 << " name " << ( name ? name : "-" )
2258 << " num_column " << num_column
2259 ;
2260
2261 assert( num_column > 0 );
2262
2263 G4Tubs* IonRing = new G4Tubs("IonRing",123*mm,206.2*mm,7*mm,0.0*deg,360.0*deg);
2264
2265 G4Tubs* screw = new G4Tubs("screw",0,13*mm,50.*mm,0.0*deg,360.0*deg);
2266
2267 std::vector<G4ThreeVector> tlate(num_column, G4ThreeVector(0, 0, 0));
2268 for(size_t i=0;i<num_column;i++) tlate[i] = G4ThreeVector(164.*cos(i*pi/4)*mm, 164.*sin(i*pi/4)*mm,-65.0*mm);
2269
2270 G4VSolid* muni = screw ;
2271 for(size_t i=1 ; i < num_column ; i++) muni = new G4UnionSolid( name, muni, screw, 0, tlate[i] ) ;
2272
2273 G4UnionSolid* uni1 = new G4UnionSolid(name, IonRing, muni, 0, tlate[0] );
2274 return uni1 ;
2275 }
2276
2277
2278
2279 const G4VSolid* U4SolidMaker::WaterDistributer(const char* name_)
2280 {
2281 G4MultiUnion* multiUnion = new G4MultiUnion(name_);
2282
2283 double TubeR_type_I = 38 * mm;
2284 double TubeR_type_II = 70 * mm;
2285 double holeR = TubeR_type_I ;
2286
2287
2288
2289 G4double distance = 120 *cm;
2290 G4double TubeR_I = TubeR_type_I;
2291 G4double TubeR_II = TubeR_type_II;
2292 G4double TubeR_III = TubeR_type_I;
2293
2294 G4double holeRadius = holeR;
2295
2296 G4String name = multiUnion->GetName() ;
2297 G4String name_I = name + "_I" ;
2298 G4String name_II = name + "_II" ;
2299 G4String name_III = name + "_III" ;
2300
2301 G4VSolid* solid_I = WaterDistributerHelper(name_I.c_str(),distance, TubeR_I);
2302 G4VSolid* solid_II = WaterDistributerHelper(name_II.c_str(),distance, TubeR_II);
2303 G4VSolid* solid_III = WaterDistributerHelper(name_III.c_str(),distance, TubeR_III);
2304
2305 G4ThreeVector positionI(0, 23.5*cm, 0);
2306 G4ThreeVector positionII(0, 0, 0);
2307 G4ThreeVector positionIII(0, - 23.5*cm, 0);
2308
2309 G4RotationMatrix* rotation = new G4RotationMatrix();
2310
2311 G4Transform3D trI = G4Transform3D(*rotation, positionI);
2312 G4Transform3D trII = G4Transform3D(*rotation, positionII);
2313 G4Transform3D trIII = G4Transform3D(*rotation, positionIII);
2314
2315 multiUnion->AddNode(*solid_II, trII);
2316 multiUnion->AddNode(*solid_I, trI);
2317 multiUnion->AddNode(*solid_III, trIII);
2318
2319 for (int i = 0; i < 8; i++) {
2320
2321 G4Tubs* hole = new G4Tubs("Hole_" + std::to_string(i), 0, holeRadius, (23.5) * cm, 0, 360 * deg);
2322
2323 G4double theta = i * 45 * deg;
2324 G4RotationMatrix* rotation = new G4RotationMatrix();
2325 rotation->rotateX(90 * deg);
2326
2327 G4ThreeVector position(-distance * cos(theta), 0, distance * sin(theta));
2328 G4Transform3D tr = G4Transform3D(*rotation, position);
2329
2330 multiUnion->AddNode(*hole, tr);
2331 }
2332
2333 multiUnion->Voxelize();
2334
2335 return multiUnion ;
2336 }
2337
2338
2339
2340
2341
2342
2343
2344
2345
2346
2347
2348
2349
2350
2351
2352
2353
2354
2355
2356
2357
2358
2359
2360
2361
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373 G4VSolid* U4SolidMaker::WaterDistributerHelper(const char* name, double distance, double TubeR)
2374 {
2375 G4double rMax = TubeR;
2376 G4double rMin = 0;
2377 G4double dz = distance * tan(22.5 * deg);
2378 G4double sPhi = 0.0;
2379 G4double dPhi = 2 * M_PI;
2380
2381
2382 G4MultiUnion* multiUnion = new G4MultiUnion(name);
2383
2384
2385 G4double rotationAngle = 22.5 * deg;
2386 for (int i = 0; i < 8; i++) {
2387
2388 G4double theta_i = rotationAngle;
2389 G4double theta_j = rotationAngle;
2390 G4ThreeVector pLowNorm(sin(theta_i), 0, -cos(theta_j));
2391 G4ThreeVector pHighNorm(sin(theta_i), 0, cos(theta_j));
2392
2393 G4CutTubs* cutTube = new G4CutTubs(
2394 "CutTube_" + std::to_string(i), rMin, rMax, dz, sPhi, dPhi, pLowNorm, pHighNorm);
2395
2396
2397
2398 G4double theta = i * 45 * deg;
2399 G4RotationMatrix* rotation = new G4RotationMatrix();
2400 rotation->rotateY(45 * i * deg);
2401
2402 G4RotationMatrix* rotation_hole = new G4RotationMatrix();
2403 rotation_hole->rotateX(90 * deg);
2404
2405 G4ThreeVector position(-distance * cos(theta), 0, distance * sin(theta));
2406 G4Transform3D tr = G4Transform3D(*rotation, position);
2407
2408
2409
2410
2411
2412
2413 multiUnion->AddNode(*cutTube, tr);
2414 }
2415
2416
2417 multiUnion->Voxelize();
2418
2419 return multiUnion ;
2420 }
2421
2422
2423
2424
2425
2426
2427
2428
2429
2430
2431
2432
2433
2434 const G4VSolid* U4SolidMaker::AltWaterDistributer(const char* name_)
2435 {
2436 G4MultiUnion* multiUnion = new G4MultiUnion(name_);
2437
2438 double TubeR_type_I = 38 * mm;
2439 double TubeR_type_II = 70 * mm;
2440 double holeR = TubeR_type_I ;
2441
2442 G4double distance = 120 *cm;
2443 G4double TubeR_I = TubeR_type_I;
2444 G4double TubeR_II = TubeR_type_II;
2445 G4double TubeR_III = TubeR_type_I;
2446
2447 G4double holeRadius = holeR;
2448
2449 G4double y_positionI = 23.5*cm ;
2450 G4double y_positionII = 0 ;
2451 G4double y_positionIII = -23.5*cm ;
2452
2453 bool do_I = true ;
2454 bool do_II = false ;
2455 bool do_III = false ;
2456
2457 if(do_I) AltWaterDistributerHelper(multiUnion, distance, TubeR_I, y_positionI );
2458 if(do_II) AltWaterDistributerHelper(multiUnion, distance, TubeR_II, y_positionII );
2459 if(do_III) AltWaterDistributerHelper(multiUnion, distance, TubeR_III, y_positionIII );
2460
2461 for (int i = 0; i < 8; i++) {
2462
2463 G4Tubs* hole = new G4Tubs("Hole_" + std::to_string(i), 0, holeRadius, (23.5) * cm, 0, 360 * deg);
2464
2465 G4double theta = i * 45 * deg;
2466 G4RotationMatrix* rotation = new G4RotationMatrix();
2467 rotation->rotateX(90 * deg);
2468
2469 G4ThreeVector position(-distance * cos(theta), 0, distance * sin(theta));
2470 G4Transform3D tr = G4Transform3D(*rotation, position);
2471
2472 multiUnion->AddNode(*hole, tr);
2473 }
2474
2475 multiUnion->Voxelize();
2476
2477 return multiUnion ;
2478 }
2479
2480
2481 void U4SolidMaker::AltWaterDistributerHelper(G4MultiUnion* multiUnion, double distance, double TubeR, double yoffset )
2482 {
2483 G4double rMax = TubeR;
2484 G4double rMin = 0;
2485 G4double dz = distance * tan(22.5 * deg);
2486 G4double sPhi = 0.0;
2487 G4double dPhi = 2 * M_PI;
2488
2489
2490
2491 G4double rotationAngle = 22.5 * deg;
2492 for (int i = 0; i < 8; i++) {
2493
2494 G4double theta_i = rotationAngle;
2495 G4double theta_j = rotationAngle;
2496 G4ThreeVector pLowNorm(sin(theta_i), 0, -cos(theta_j));
2497 G4ThreeVector pHighNorm(sin(theta_i), 0, cos(theta_j));
2498
2499 G4CutTubs* cutTube = new G4CutTubs(
2500 "CutTube_" + std::to_string(i), rMin, rMax, dz, sPhi, dPhi, pLowNorm, pHighNorm);
2501
2502
2503
2504 G4double theta = i * 45 * deg;
2505 G4RotationMatrix* rotation = new G4RotationMatrix();
2506 rotation->rotateY(45 * i * deg);
2507
2508 G4RotationMatrix* rotation_hole = new G4RotationMatrix();
2509 rotation_hole->rotateX(90 * deg);
2510
2511 G4ThreeVector position(-distance * cos(theta), yoffset, distance * sin(theta));
2512 G4Transform3D tr = G4Transform3D(*rotation, position);
2513
2514
2515
2516
2517
2518 multiUnion->AddNode(*cutTube, tr);
2519 }
2520 }
2521
2522
2523
2524
2525
2526
2527
2528
2529
2530
2531
2532 const G4VSolid* U4SolidMaker::WaterDistributorPartIIIUnion(const char* name_)
2533 {
2534
2535
2536
2537 double flange_r_inner = 66.5*mm;
2538 double flange_r_outer = 125.*mm;
2539 int numZplanes_flange = 4;
2540 G4double zPlane_flange[] = {-50 *mm, -25 *mm , -25 *mm, 0 *mm};
2541 G4double rInner_flange[] = {0 , 0, 0, 0};
2542 G4double rOuter_flange[] = {flange_r_inner, flange_r_inner, flange_r_outer , flange_r_outer};
2543 auto solidFlange = new G4Polycone("sBotChimneySSEnclosure_Flange",
2544 0, 360*deg,
2545 numZplanes_flange, zPlane_flange, rInner_flange, rOuter_flange);
2546
2547 double dz1 = 529/2 * mm;
2548 double theta1 = 27*deg;
2549 G4ThreeVector pLowNorm1( sin(theta1), 0, -cos(theta1) );
2550 G4ThreeVector pHighNorm1( -sin(theta1), 0, cos(theta1) );
2551 auto cutTube1 = new G4CutTubs("CutTube1", 0, 66.5 * cos(theta1), dz1, 0, 360*deg, pLowNorm1, pHighNorm1);
2552
2553 double dz2 = 1125.25/2 * mm;
2554 double theta2 = -16*deg;
2555 G4ThreeVector pLowNorm2( sin(theta2), 0, -cos(theta2) );
2556 G4ThreeVector pHighNorm2( -sin(theta2), 0, cos(theta2) );
2557 auto cutTube2 = new G4CutTubs("CutTube2", 0, 66.5 * cos(theta2), dz2, 0, 360*deg, pLowNorm2, pHighNorm2);
2558
2559 double r_tube = 66.5 * mm;
2560 double r_main1 = 283 * mm;
2561 double phi_start1 = 180 * deg;
2562 double phi_delta1 = 135 * deg;
2563 auto torus1 = new G4Torus("torus1", 0, r_tube, r_main1, phi_start1, phi_delta1);
2564
2565 double r_main2 = 352 * mm;
2566 double phi_start2 = 45 * deg;
2567 double phi_delta2 = 45 * deg;
2568 auto torus2 = new G4Torus("torus2", 0, r_tube, r_main2, phi_start2, phi_delta2);
2569
2570
2571 G4VSolid* solids[] = {solidFlange, cutTube1, cutTube2, torus1, torus2};
2572
2573
2574 double rotX_angles[] = {0*deg, 0*deg, 0*deg, -90*deg, 90*deg};
2575 double rotY_angles[] = {0*deg, 27*deg, -16*deg, 180*deg, 0*deg};
2576
2577
2578 double offset1 = dz1 * cos(27*deg);
2579 double offset2 = dz2 * cos(-16*deg);
2580
2581
2582 G4ThreeVector positions[] = {
2583 G4ThreeVector(0, 0, -19120),
2584 G4ThreeVector(-120, 0, -19120 - 50*mm - offset1),
2585 G4ThreeVector(-240 + dz2 * sin(16*deg), 0, -19120 - 50*mm - offset1 * 2 - offset2),
2586 G4ThreeVector(70 - r_main1, 0, -20724),
2587 G4ThreeVector(70 - 449 - 283, 0, -21181)
2588 };
2589
2590
2591
2592
2593
2594 G4MultiUnion* unionSolid = new G4MultiUnion("WaterDistributorPartIIIUnion");
2595
2596 for (int i = 0; i < 5; ++i) {
2597
2598 G4RotationMatrix rotation;
2599 if (rotX_angles[i] != 0) {
2600 rotation.rotateX(rotX_angles[i]);
2601 }
2602 if (rotY_angles[i] != 0) {
2603 rotation.rotateY(rotY_angles[i]);
2604 }
2605
2606
2607 G4Transform3D transform(rotation, positions[i]);
2608 unionSolid->AddNode(*solids[i], transform);
2609 }
2610
2611 unionSolid->Voxelize();
2612
2613
2614
2615
2616
2617 return unionSolid ;
2618 }
2619
2620
2621
2622
2623
2624
2625
2626
2627
2628
2629
2630
2631
2632
2633
2634
2635
2636
2637
2638
2639
2640
2641
2642
2643
2644
2645
2646
2647
2648
2649
2650
2651
2652
2653
2654
2655
2656
2657
2658
2659
2660
2661
2662
2663
2664
2665
2666
2667
2668
2669
2670
2671
2672
2673
2674
2675
2676
2677
2678
2679
2680
2681
2682
2683
2684
2685
2686
2687
2688
2689
2690
2691
2692
2693
2694
2695
2696
2697
2698
2699
2700
2701
2702
2703
2704
2705
2706
2707
2708
2709
2710
2711
2712
2713
2714
2715
2716
2717
2718 std::vector<PlacedSolid> U4SolidMaker::MakeLowerWaterDistributorCurvedCutTubes(double m_lowerchimney_rotangle) {
2719 std::vector<PlacedSolid> cutTubes;
2720
2721 double UNCOINCIDE_MM = ssys::getenvdouble(U4SolidMaker__MakeLowerWaterDistributorCurvedCutTubes_UNCOINCIDE_MM, 0 );
2722
2723 double rMin = 0;
2724
2725 double sPhi = 0;
2726 double dPhi = 360*deg;
2727
2728
2729
2730 double dz1 = 529/2 * mm;
2731 double theta1 = 27*deg;
2732 G4ThreeVector pLowNorm1( sin(theta1), 0, -cos(theta1) );
2733 G4ThreeVector pHighNorm1( -sin(theta1), 0, cos(theta1) );
2734 auto cutTube1 = new G4CutTubs("CutTube1", rMin, 66.5 * cos(theta1), dz1, sPhi, dPhi, pLowNorm1, pHighNorm1);
2735
2736
2737 double dz2 = 1125.25/2 * mm;
2738 double theta2 = -16*deg;
2739 G4ThreeVector pLowNorm2( sin(theta2), 0, -cos(theta2) );
2740 G4ThreeVector pHighNorm2( -sin(theta2), 0, cos(theta2) );
2741 auto cutTube2 = new G4CutTubs("CutTube2", rMin, 66.5 * cos(theta2), dz2, sPhi, dPhi, pLowNorm2, pHighNorm2);
2742
2743 double offset1 = dz1 * cos(27*deg);
2744 double offset2 = dz2 * cos(-16*deg);
2745
2746 double cos_rot = cos(m_lowerchimney_rotangle);
2747 double sin_rot = sin(m_lowerchimney_rotangle);
2748 double sin_theta2 = sin(16*deg);
2749
2750
2751 G4RotationMatrix rot_cutTube1;
2752 rot_cutTube1.rotateY(27*deg);
2753 rot_cutTube1.rotateZ(-m_lowerchimney_rotangle);
2754
2755 G4ThreeVector trans_cutTube1(-120 * cos_rot, 120 * sin_rot, -19120 - 50*mm - offset1);
2756
2757 cutTubes.push_back({
2758 cutTube1,
2759 trans_cutTube1,
2760 rot_cutTube1,
2761 0,
2762 "lCutTube1",
2763 "pCutTube1"
2764 });
2765
2766
2767 G4RotationMatrix rot_cutTube2;
2768 rot_cutTube2.rotateY(-16*deg);
2769 rot_cutTube2.rotateZ(-m_lowerchimney_rotangle);
2770
2771 G4ThreeVector trans_cutTube2(
2772 2 * (-120 * cos_rot) + dz2 * sin_theta2 * cos_rot,
2773 2 * (120 * sin_rot) - dz2 * sin_theta2 * sin_rot,
2774 -19120 - 50*mm - offset1 * 2 - offset2 + UNCOINCIDE_MM*mm
2775 );
2776
2777
2778 cutTubes.push_back({
2779 cutTube2,
2780 trans_cutTube2,
2781 rot_cutTube2,
2782 1,
2783 "lCutTube2",
2784 "pCutTube2"
2785 });
2786
2787
2788 std::array<double,3> tr1 = {trans_cutTube1.x(), trans_cutTube1.y(), trans_cutTube1.z() };
2789 std::array<double,3> tr2 = {trans_cutTube2.x(), trans_cutTube2.y(), trans_cutTube2.z() };
2790
2791 LOG(info)
2792 << "\n"
2793 << "[" << U4SolidMaker__MakeLowerWaterDistributorCurvedCutTubes_UNCOINCIDE_MM << "]"
2794 << "\n"
2795 << std::setw(60) << " UNCOINCIDE_MM " << std::fixed << std::setw(10) << std::setprecision(3) << UNCOINCIDE_MM
2796 << "\n"
2797 << std::setw(60) << " offset1 " << std::fixed << std::setw(10) << std::setprecision(3) << offset1
2798 << "\n"
2799 << std::setw(60) << " offset2 " << std::fixed << std::setw(10) << std::setprecision(3) << offset2
2800 << "\n"
2801 << std::setw(60) << " offset1*2 + offset2 " << std::fixed << std::setw(10) << std::setprecision(3) << (offset1*2.+offset2)
2802 << "\n"
2803 << std::setw(60) << " offset1*2 + offset2*2 " << std::fixed << std::setw(10) << std::setprecision(3) << (offset1*2.+offset2*2.)
2804 << "\n"
2805 << " trans_cutTube1 " << s_bb::Desc_<double,3>(tr1.data())
2806 << "\n"
2807 << " trans_cutTube2 " << s_bb::Desc_<double,3>(tr2.data())
2808 ;
2809
2810 return cutTubes;
2811 }
2812
2813
2814
2815
2816
2817
2818
2819
2820
2821
2822
2823
2824 const G4VSolid* U4SolidMaker::OuterReflectorOrbSubtraction(const char* name_)
2825 {
2826 G4String name = name_ ;
2827
2828 double m_radOuterWater = 20.50*m - 26*mm;
2829 double m_thicknessReflector = 2*mm;
2830 double m_radOuterReflector = m_radOuterWater + m_thicknessReflector;
2831
2832
2833 double radOuterReflector = ssys::getenvfloat(U4SolidMaker__OuterReflectorOrbSubtraction_radOuterReflector, m_radOuterReflector );
2834 G4VSolid* solid_output = new G4Orb(name_, radOuterReflector );
2835
2836
2837 double m_lowerchimney_rotangle = 0. ;
2838
2839
2840 auto cutTubes = MakeLowerWaterDistributorCurvedCutTubes(m_lowerchimney_rotangle);
2841
2842 for (size_t i = 0; i < cutTubes.size(); ++i) {
2843 const auto& tube = cutTubes[i];
2844 G4Transform3D transform(tube.rot, tube.pos);
2845
2846 solid_output = new G4SubtractionSolid(
2847 name + "_cutTube" + std::to_string(i+1),
2848 solid_output,
2849 tube.solid,
2850 transform
2851 );
2852 }
2853
2854 G4String solid_output_name = solid_output->GetName();
2855
2856 LOG(info)
2857 << "\n"
2858 << "m_radOuterReflector " << m_radOuterReflector
2859 << "\n"
2860 << " [" << U4SolidMaker__OuterReflectorOrbSubtraction_radOuterReflector << "]"
2861 << "\n"
2862 << " radOuterReflector " << radOuterReflector
2863 << "\n"
2864 << " solid_output_name " << solid_output_name
2865 ;
2866
2867 return solid_output ;
2868 }
2869
2870
2871
2872
2873
2874
2875
2876
2877
2878
2879
2880
2881
2882
2883
2884 struct R12860_PMTSolid_Maker
2885 {
2886 R12860_PMTSolid_Maker(double R1, double R1z, double R2, double R3, double H, double H3);
2887
2888 G4VSolid* GetSolid(G4String solidname, double thickness=0.0, char X='\0' );
2889
2890 double m_R1;
2891 double m_R1z;
2892 double m_R1p;
2893 double m_R2;
2894 double m_R3;
2895 double m_theta;
2896 double m_hypotenuse ;
2897 double m_H;
2898 double m_H_1_2;
2899
2900 double m_H3;
2901
2902 double m_delta_torlerance;
2903
2904 };
2905
2906
2907
2908
2909 R12860_PMTSolid_Maker::R12860_PMTSolid_Maker(
2910 double R1,
2911 double R1z,
2912 double R2,
2913 double R3,
2914 double H,
2915 double H3
2916 )
2917 :
2918 m_R1(R1),
2919 m_R1z(R1z),
2920 m_R2(R2),
2921 m_R3(R3),
2922 m_H(H),
2923 m_H3(H3)
2924 {
2925 m_H_1_2 = m_H - m_R1z - m_H3;
2926 m_theta = atan((m_R2+m_R3)/(m_H_1_2));
2927 m_hypotenuse = sqrt(pow(m_H_1_2,2)+pow(m_R2+m_R3,2)) ;
2928 m_R1p = m_hypotenuse - m_R2;
2929
2930 m_delta_torlerance = 1E-2*mm;
2931
2932
2933 }
2934
2935
2936
2937
2938
2939
2940
2941
2942
2943
2944
2945
2946
2947
2948
2949
2950
2951
2952
2953
2954
2955
2956
2957
2958
2959
2960
2961
2962
2963
2964
2965
2966
2967
2968
2969
2970
2971
2972
2973
2974
2975
2976
2977
2978
2979
2980
2981
2982
2983
2984
2985
2986
2987
2988
2989
2990
2991
2992
2993
2994
2995
2996
2997 G4VSolid* R12860_PMTSolid_Maker::GetSolid(G4String solidname, double thickness, char X)
2998 {
2999
3000 double r1t = m_R1 + thickness;
3001 double r1zt = m_R1z + thickness;
3002 double r2t = m_R2 - thickness;
3003 double r3t = m_R3 + thickness;
3004 double r1zp = (m_R1p+thickness);
3005 double r4t = r1zp * sin(m_theta);
3006
3007 double h1t = r1zp * cos(m_theta);
3008 double h2t = r2t * cos(m_theta);
3009
3010 double h3t = m_H3 + thickness;
3011
3012
3013 double scarf_radius = r4t+m_delta_torlerance ;
3014 double scarf_halfheight = h2t/2+m_delta_torlerance ;
3015
3016 double endtube_radius = r3t+m_delta_torlerance ;
3017 double endtube_halfheight = h3t/2+m_delta_torlerance ;
3018
3019
3020 std::cout
3021 << " thickness : " << std::setw(10) << thickness << "\n"
3022 << " m_delta_torlerance : " << std::setw(10) << m_delta_torlerance << "\n"
3023 << " m_R1 : " << std::setw(10) << m_R1 << " (input ellipse width)" << "\n"
3024 << " r1t : " << std::setw(10) << r1t << " (m_R1 + thickness)" << "\n"
3025 << " m_R1z : " << std::setw(10) << m_R1z << " (input ellipse height)" << "\n"
3026 << " r1zt : " << std::setw(10) << r1zt << " (m_R1z + thickness)" << "\n"
3027 << " m_R2 : " << std::setw(10) << m_R2 << " (input torus circle radius)" << "\n"
3028 << " m_R3 : " << std::setw(10) << m_R3 << " (input endtube radius)" << "\n"
3029 << " m_H : " << std::setw(10) << m_H << " (input total height)" << "\n"
3030 << " m_H3 : " << std::setw(10) << m_H3 << " (input endtube height)" << "\n"
3031 << " m_H_1_2 : " << std::setw(10) << m_H_1_2 << " (m_H - m_R1z - m_H3)" << "\n"
3032 << " m_theta : " << std::setw(10) << m_theta << " (ellipse ^ torus centers)" << "\n"
3033 << " m_hypotenuse : " << std::setw(10) << m_hypotenuse << " (dist from ellipse to torus center)" << "\n"
3034 << " m_R1p : " << std::setw(10) << m_R1p << " (m_hypotenuse - m_R2)" << "\n"
3035 << " r1zp : " << std::setw(10) << r1zp << " (m_R1p + thickness)" << "\n"
3036 << " r4t : " << std::setw(10) << r4t << " (r1zp*sin(m_theta))" << "\n"
3037 << " scarf_radius : " << std::setw(10) << scarf_radius << " (r4t+m_delta_torlerance)" << "\n"
3038 << " r2t : " << std::setw(10) << r2t << " (m_R2 - thickness)" << "\n"
3039 << " h1t : " << std::setw(10) << h1t << " (r1zp*cos(m_theta)) above neck height " << "\n"
3040 << " h2t : " << std::setw(10) << h2t << " (r2t*cos(m_theta)) neck h" << "\n"
3041 << " scarf_halfheight : " << std::setw(10) << scarf_halfheight << " (h2t/2+m_delta_torlerance)" << "\n"
3042 << " endtube_radius : " << std::setw(10) << endtube_radius << " (r3t+m_delta_torlerance)" << "\n"
3043 << " h3t : " << std::setw(10) << h3t << " (m_H3 + thickness)" << "\n"
3044 << " endtube_halfheight : " << std::setw(10) << endtube_halfheight << " (h3t/2+m_delta_torlerance)" << "\n"
3045 ;
3046
3047
3048
3049
3050 G4cout << "r1t: " << r1t/mm << " mm" << G4endl;
3051 G4cout << "r4t: " << r4t/mm << " mm" << G4endl;
3052 G4cout << "r2t: " << r2t/mm << " mm" << G4endl;
3053 G4cout << "r3t: " << r3t/mm << " mm" << G4endl;
3054 G4cout << "h1t: " << h1t/mm << " mm" << G4endl;
3055 G4cout << "h2t: " << h2t/mm << " mm" << G4endl;
3056 G4cout << "h3t: " << h3t/mm << " mm" << G4endl;
3057
3058
3059
3060
3061
3062
3063
3064
3065
3066
3067
3068
3069 G4Ellipsoid* pmttube_solid_sphere = new G4Ellipsoid(
3070 solidname+"_1_Ellipsoid",
3071 r1t,
3072 r1t,
3073 r1zt
3074 );
3075
3076
3077
3078 G4Tubs* pmttube_solid_tube = new G4Tubs(
3079 solidname+"_2_Tube",
3080 0*mm,
3081 scarf_radius,
3082 scarf_halfheight,
3083 0*deg,
3084 360*deg);
3085
3086 std::cout
3087 << " symbol : pmttube_solid_tube(scarf)" << "\n"
3088 << " name : " << pmttube_solid_tube->GetName() << "\n"
3089 << " r4t : " << r4t << "\n"
3090 << " h2t/2 : " << h2t/2 << "\n"
3091 ;
3092
3093 G4Torus* pmttube_solid_torus = new G4Torus(
3094 solidname+"_2_Torus",
3095 0*mm,
3096 r2t+m_delta_torlerance,
3097 (r2t+r3t),
3098 -0.01*deg,
3099 360.01*deg);
3100
3101 std::cout
3102 << " symbol : pmttube_solid_torus(scarfSub) " << "\n"
3103 << " name : " << pmttube_solid_torus->GetName() << "\n"
3104 << " r2t : " << r2t << "\n"
3105 << " r2t+r3t : " << r2t+r3t << "\n"
3106 ;
3107
3108
3109
3110
3111
3112 [[maybe_unused]] G4VSolid* pmttube_solid_part2 = nullptr ;
3113
3114 G4VSolid* neck = nullptr ;
3115
3116 if( X == 'U' )
3117 {
3118 pmttube_solid_part2 = new G4UnionSolid(
3119 solidname+"_part2",
3120 pmttube_solid_tube,
3121 pmttube_solid_torus,
3122 0,
3123 G4ThreeVector(0,0,-h2t/2)
3124 );
3125
3126 neck = pmttube_solid_part2 ;
3127 }
3128 else if( X == 'K' )
3129 {
3130 neck = pmttube_solid_tube ;
3131 }
3132 else if( X == 'P' )
3133 {
3134 G4double phiStart = 0.00*deg ;
3135 G4double phiTotal = 360.00*deg ;
3136 G4int numZPlanes = 2 ;
3137 G4double zPlane[] = { -scarf_halfheight, scarf_halfheight } ;
3138 G4double rInner[] = { 0.0 , 0.0 } ;
3139 G4double rOuter[] = { endtube_radius , scarf_radius } ;
3140
3141 G4Polycone* polycone_neck = new G4Polycone(
3142 solidname+"_part2",
3143 phiStart,
3144 phiTotal,
3145 numZPlanes,
3146 zPlane,
3147 rInner,
3148 rOuter
3149 );
3150
3151 neck = polycone_neck ;
3152 }
3153 else
3154 {
3155 pmttube_solid_part2 = new G4SubtractionSolid(
3156 solidname+"_part2",
3157 pmttube_solid_tube,
3158 pmttube_solid_torus,
3159 0,
3160 G4ThreeVector(0,0,-h2t/2)
3161 );
3162 neck = pmttube_solid_part2 ;
3163 }
3164
3165 std::cout
3166 << " symbol : pmttube_solid_part2 " << "\n"
3167 << " name : " << ( pmttube_solid_part2 ? pmttube_solid_part2->GetName() : "-" ) << "\n"
3168 << " -h2t/2 : " << -h2t/2 << "(neck-torus-dz)\n"
3169 ;
3170
3171
3172
3173
3174
3175
3176 G4Tubs* pmttube_solid_end_tube = new G4Tubs(
3177 solidname+"_3_EndTube",
3178 0*mm,
3179 endtube_radius,
3180 endtube_halfheight,
3181 0*deg,
3182 360*deg);
3183
3184
3185
3186
3187 G4UnionSolid* pmttube_solid_1_2 = new G4UnionSolid(
3188 solidname+"_1_2",
3189 pmttube_solid_sphere,
3190 neck,
3191 0,
3192 G4ThreeVector(0, 0, -(h1t+h2t/2))
3193 );
3194
3195 std::cout
3196 << " symbol : pmttube_solid_1_2(bulb+neck) \n"
3197 << " name : " << pmttube_solid_1_2->GetName() << "\n"
3198 << " neck_dz : " << -(h1t+h2t/2) << "\n"
3199 << " total_torus_dz : " << -h2t/2 + -(h1t+h2t/2) << "\n"
3200 ;
3201
3202
3203 [[maybe_unused]] G4UnionSolid* pmttube_solid_1_2_3 = new G4UnionSolid(
3204 solidname,
3205 pmttube_solid_1_2,
3206 pmttube_solid_end_tube,
3207 0,
3208 G4ThreeVector(0,0,
3209 -(m_H_1_2+h3t*0.50))
3210 );
3211
3212 std::cout
3213 << " symbol : pmttube_solid_1_2_3((bulb+neck)+endtube) \n"
3214 << " name : " << pmttube_solid_1_2_3->GetName() << "\n"
3215 << " endtube_dz : " << -(m_H_1_2+h3t*0.50) << "\n"
3216 ;
3217
3218
3219 return pmttube_solid_1_2_3;
3220 }
3221
3222
3223
3224 const G4VSolid* U4SolidMaker::R12860_PMTSolid(const char* name_)
3225 {
3226 const char* PREFIX = "R12860_PMTSolid" ;
3227 assert( sstr::StartsWith(name_,PREFIX ));
3228 const char* suffix = name_ + strlen(PREFIX);
3229 G4String solidname = name_ ;
3230
3231
3232
3233 double m_pmt_r, m_pmt_h, m_z_equator ;
3234
3235 m_pmt_r = 101.*mm;
3236 m_pmt_h = 220.*mm;
3237 m_z_equator = 75.5*mm;
3238
3239 R12860_PMTSolid_Maker* m_pmtsolid_maker = new R12860_PMTSolid_Maker(
3240 m_pmt_r,
3241 m_z_equator,
3242 23*mm,
3243 42.5*mm,
3244 m_pmt_h,
3245 62.*mm
3246 );
3247
3248
3249
3250
3251 double thickness = 1E-3*mm ;
3252
3253 bool with_suffix = suffix && ( suffix[0] == 'U' || suffix[0] == 'K' || suffix[0] == 'P' ) ;
3254
3255 return m_pmtsolid_maker->GetSolid(solidname + "_pmt_solid", thickness, ( with_suffix ? suffix[0] : '\0' ) );
3256 }
3257
3258
3259
3260
3261
3262
3263
3264
3265
3266
3267 struct EMFCoil
3268 {
3269 static const double EMF_RC_32[32] ;
3270 static G4Polycone* BuildLProfileSectorPolycone( const std::string& solidName, double Rout_mm, double L_mm, double t_mm, double phiStart, double phiTotal, bool flangeUp = false );
3271 static const G4VSolid* Example(int i);
3272 };
3273
3274 const double EMFCoil::EMF_RC_32[32] = {
3275 3.843, 6.509, 9.185, 11.029,
3276 13.210, 14.924, 16.325, 17.495,
3277 18.465, 19.284, 19.953, 20.502,
3278 20.931, 21.241, 21.450, 21.559,
3279 21.559, 21.450, 21.240, 20.930,
3280 20.501, 19.951, 19.282, 18.463,
3281 17.495, 16.325, 14.924, 13.210,
3282 11.053, 9.185, 6.509, 3.843
3283 };
3284
3285
3286
3287 G4Polycone* EMFCoil::BuildLProfileSectorPolycone(
3288 const std::string& solidName,
3289 double Rout_mm,
3290 double L_mm,
3291 double t_mm,
3292 double phiStart,
3293 double phiTotal,
3294 bool flangeUp
3295 ){
3296
3297 const double H = L_mm;
3298
3299 const int NZ = 4;
3300
3301 double zPlane[NZ];
3302 double rMin[NZ];
3303 double rMax[NZ];
3304
3305 if (!flangeUp) {
3306
3307 zPlane[0] = -H*0.5;
3308 zPlane[1] = -H*0.5 + t_mm;
3309 zPlane[2] = -H*0.5 + t_mm;
3310 zPlane[3] = +H*0.5;
3311
3312
3313 rMin[0] = Rout_mm - L_mm;
3314 rMin[1] = Rout_mm - L_mm;
3315
3316
3317 rMin[2] = Rout_mm - t_mm;
3318 rMin[3] = Rout_mm - t_mm;
3319 } else {
3320
3321 zPlane[0] = -H*0.5;
3322 zPlane[1] = -H*0.5 + (H - t_mm);
3323 zPlane[2] = -H*0.5 + (H - t_mm);
3324 zPlane[3] = +H*0.5;
3325
3326 rMin[0] = Rout_mm - t_mm;
3327 rMin[1] = Rout_mm - t_mm;
3328 rMin[2] = Rout_mm - L_mm;
3329 rMin[3] = Rout_mm - L_mm;
3330 }
3331
3332
3333 for (int i = 0; i < NZ; ++i) rMax[i] = Rout_mm;
3334
3335
3336 for (int i = 0; i < NZ; ++i)
3337 {
3338 std::cout
3339 << "EMFCoil::BuildLProfileSectorPolycone"
3340 << " i " << std::setw(2) << i
3341 << " z " << std::setw(10) << zPlane[i]
3342 << " rMin " << std::setw(10) << rMin[i]
3343 << " rMax " << std::setw(10) << rMax[i]
3344 << "\n"
3345 ;
3346 }
3347
3348 return new G4Polycone(
3349 solidName.c_str(),
3350 phiStart * rad,
3351 phiTotal * rad,
3352 NZ, zPlane, rMin, rMax
3353 );
3354 }
3355
3356
3357
3358 const G4VSolid* EMFCoil::Example(int i)
3359 {
3360
3361 const double L_leg_mm = 56.0;
3362 const double t_mm = 4.0;
3363 const double eps_r_mm = 2.0;
3364
3365 const double R0_m = EMF_RC_32[i] + eps_r_mm * 1e-3;
3366
3367 double phiS = 89.60*deg ;
3368 double phiE = 134.72*deg ;
3369
3370 const double PHI_EPS = 0.01 * deg;
3371 const double s = phiS + PHI_EPS;
3372 const double e = phiE - PHI_EPS;
3373 const double dphi = e - s;
3374
3375 std::string solidName = "example" ;
3376 double Rout_mm = R0_m * 1000.0 ;
3377 double L_mm = L_leg_mm ;
3378 double phiStart = s ;
3379 double phiTotal = dphi ;
3380 bool flangeUp = false ;
3381
3382 return BuildLProfileSectorPolycone(solidName, Rout_mm, L_mm, t_mm, phiStart, phiTotal, flangeUp );
3383 }
3384
3385
3386 const G4VSolid* U4SolidMaker::LProfileSectorPolycone( const char* )
3387 {
3388 return EMFCoil::Example(16);
3389 }