File indexing completed on 2026-04-10 07:50:36
0001 #include <sstream>
0002 #include <csignal>
0003 #include <array>
0004
0005 #include "G4Material.hh"
0006 #include "G4ThreeVector.hh"
0007 #include "G4LogicalVolume.hh"
0008 #include "G4PVPlacement.hh"
0009 #include "G4Box.hh"
0010 #include "G4Orb.hh"
0011
0012 #include "spath.h"
0013 #include "sstr.h"
0014 #include "ssys.h"
0015 #include "s_bb.h"
0016
0017 #include "SPlace.h"
0018
0019 #include "SLOG.hh"
0020
0021 #include "U4.hh"
0022 #include "U4Material.hh"
0023 #include "U4Surface.h"
0024 #include "U4SolidMaker.hh"
0025 #include "U4VolumeMaker.hh"
0026 #include "U4RotationMatrix.h"
0027 #include "U4Volume.h"
0028 #include "U4GDML.h"
0029 #include "U4ThreeVector.h"
0030
0031 #ifdef WITH_PMTSIM
0032 #include "PMTSim.hh"
0033 #endif
0034
0035
0036
0037 const plog::Severity U4VolumeMaker::LEVEL = SLOG::EnvLevel("U4VolumeMaker", "DEBUG");
0038 const char* U4VolumeMaker::GEOM = ssys::getenvvar("GEOM", "BoxOfScintillator");
0039 const char* U4VolumeMaker::METH = nullptr ;
0040
0041 std::string U4VolumeMaker::Desc()
0042 {
0043 std::stringstream ss ;
0044 ss << "U4VolumeMaker::Desc" ;
0045 ss << " GEOM " << ( GEOM ? GEOM : "-" ) ;
0046 ss << " METH " << ( METH ? METH : "-" ) ;
0047 #ifdef WITH_PMTSIM
0048 ss << " WITH_PMTSIM " ;
0049 #else
0050 ss << " not-WITH_PMTSIM " ;
0051 #endif
0052 std::string s = ss.str();
0053 return s ;
0054 }
0055
0056 std::string U4VolumeMaker::Desc( const G4ThreeVector& tla )
0057 {
0058 std::stringstream ss ;
0059 ss << " tla ("
0060 << " " << std::fixed << std::setw(10) << std::setprecision(3) << tla.x()
0061 << " " << std::fixed << std::setw(10) << std::setprecision(3) << tla.y()
0062 << " " << std::fixed << std::setw(10) << std::setprecision(3) << tla.z()
0063 << ") "
0064 ;
0065
0066 std::string s = ss.str();
0067 return s ;
0068 }
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089
0090
0091
0092
0093
0094
0095 const G4VPhysicalVolume* U4VolumeMaker::PV(){ return PV(GEOM); }
0096 const G4VPhysicalVolume* U4VolumeMaker::PV(const char* name)
0097 {
0098 std::cerr << "U4VolumeMaker::PV name " << name << std::endl ;
0099 LOG(LEVEL) << "[" << name ;
0100 const G4VPhysicalVolume* pv = nullptr ;
0101 if(pv == nullptr) pv = PVS_(name);
0102 if(pv == nullptr) pv = PVG_(name);
0103 if(pv == nullptr) pv = PVP_(name);
0104 if(pv == nullptr) pv = PVL_(name);
0105 if(pv == nullptr) pv = PV1_(name);
0106 LOG_IF(error, pv == nullptr) << "returning nullptr for name [" << name << "]" ;
0107 LOG(LEVEL) << "]" << name ;
0108 return pv ;
0109 }
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132 const char* U4VolumeMaker::PVG_WriteNames = "U4VolumeMaker_PVG_WriteNames" ;
0133 const char* U4VolumeMaker::PVG_WriteNames_Sub = "U4VolumeMaker_PVG_WriteNames_Sub" ;
0134
0135 const G4VPhysicalVolume* U4VolumeMaker::PVG_(const char* name)
0136 {
0137 METH = "PVG_" ;
0138 const char* gdmlpath = spath::GDMLPathFromGEOM(name) ;
0139 bool exists = gdmlpath && spath::Exists(gdmlpath) ;
0140
0141 const char* sub = spath::GEOMSub(name);
0142
0143 std::cerr
0144 << "U4VolumeMaker::PVG_"
0145 << " name " << name
0146 << " gdmlpath " << ( gdmlpath ? gdmlpath : "-" )
0147 << " sub " << ( sub ? sub : "-" )
0148 << " exists " << exists
0149 << std::endl
0150 ;
0151
0152
0153 const G4VPhysicalVolume* loaded = exists ? U4GDML::Read(gdmlpath) : nullptr ;
0154
0155 if(loaded && ssys::getenvbool(PVG_WriteNames))
0156 U4Volume::WriteNames( loaded, spath::Resolve("$TMP", PVG_WriteNames));
0157
0158 const G4VPhysicalVolume* pv = loaded ;
0159
0160 if( loaded && sub )
0161 {
0162 const G4VPhysicalVolume* pv_sub = U4Volume::FindPVSub( loaded, sub ) ;
0163 G4LogicalVolume* lv_sub = pv_sub->GetLogicalVolume();
0164 std::vector<G4LogicalVolume*> lvs = {lv_sub} ;
0165 pv = Wrap( name, lvs );
0166
0167 if(ssys::getenvbool(PVG_WriteNames_Sub))
0168 U4Volume::WriteNames( pv, spath::Resolve("$TMP", PVG_WriteNames_Sub));
0169 }
0170
0171 LOG(LEVEL)
0172 << " name " << name
0173 << " gdmlpath " << gdmlpath
0174 << " exists " << exists
0175 << " loaded " << loaded
0176 << " sub " << ( sub ? sub : "-" )
0177 << " pv " << pv
0178 ;
0179
0180 return pv ;
0181 }
0182
0183
0184
0185
0186
0187
0188
0189
0190
0191
0192
0193
0194
0195
0196
0197
0198
0199
0200 const G4VPhysicalVolume* U4VolumeMaker::PVP_(const char* name)
0201 {
0202 METH = "PVP_" ;
0203 const G4VPhysicalVolume* pv = nullptr ;
0204 #ifdef WITH_PMTSIM
0205 const char* geomlist = spath::GEOMList(name);
0206 std::vector<std::string> names ;
0207 if( geomlist == nullptr )
0208 {
0209 names.push_back(name);
0210 }
0211 else
0212 {
0213 sstr::Split(geomlist, ',', names );
0214 }
0215 int num_names = names.size();
0216
0217 LOG(LEVEL)
0218 << "[ WITH_PMTSIM"
0219 << " geomlist [" << ( geomlist ? geomlist : "-" ) << "] "
0220 << " name [" << name << "] "
0221 << " num_names " << num_names
0222 ;
0223
0224 std::vector<G4LogicalVolume*> lvs ; ;
0225
0226 for(int i=0 ; i < num_names ; i++)
0227 {
0228 const char* n = names[i].c_str();
0229 bool has_manager_prefix = PMTSim::HasManagerPrefix(n) ;
0230 LOG(LEVEL) << "[ WITH_PMTSIM n [" << n << "] has_manager_prefix " << has_manager_prefix ;
0231
0232 if(!has_manager_prefix) return nullptr ;
0233
0234
0235 G4LogicalVolume* lv = PMTSim::GetLV(n) ;
0236 LOG_IF(fatal, lv == nullptr ) << "PMTSim::GetLV returned nullptr for n [" << n << "]" ;
0237 assert( lv );
0238
0239 lvs.push_back(lv);
0240 }
0241
0242 pv = Wrap( name, lvs ) ;
0243
0244 LOG(LEVEL) << "]" ;
0245 #else
0246 LOG(info) << " not-WITH_PMTSIM name [" << name << "]" ;
0247 #endif
0248 return pv ;
0249 }
0250
0251
0252
0253
0254
0255
0256
0257
0258
0259
0260 const G4VPhysicalVolume* U4VolumeMaker::PVS_(const char* name)
0261 {
0262 METH = "PVS_" ;
0263 const G4VPhysicalVolume* pv = nullptr ;
0264 if( strcmp(name,"BoxOfScintillator" ) == 0) pv = BoxOfScintillator(1000.);
0265 else if(strcmp(name,"RaindropRockAirWater" ) == 0) pv = RaindropRockAirWater(false);
0266 else if(strcmp(name,"RaindropRockAirWaterSD" ) == 0) pv = RaindropRockAirWater(true);
0267 else if(strcmp(name,"BigWaterPool" ) == 0) pv = BigWaterPool();
0268 else if(sstr::StartsWith(name,"LocalFastenerAcrylicConstruction" )) pv = LocalFastenerAcrylicConstruction(name);
0269 else if(sstr::StartsWith(name,"Local" )) pv = Local(name);
0270 return pv ;
0271 }
0272 const G4VPhysicalVolume* U4VolumeMaker::PVL_(const char* name)
0273 {
0274 METH = "PVL_" ;
0275 if(!sstr::StartsWith(name, "List")) return nullptr ;
0276 std::vector<G4LogicalVolume*> lvs ;
0277 LV(lvs, name + strlen("List") );
0278 const G4VPhysicalVolume* pv = WrapLVGrid(lvs, 1, 1, 1 );
0279 return pv ;
0280 }
0281
0282
0283
0284
0285
0286
0287
0288
0289 const G4VPhysicalVolume* U4VolumeMaker::PV1_(const char* name)
0290 {
0291 METH = "PV1_" ;
0292 const char* matname_ = nullptr ;
0293 G4LogicalVolume* lv = LV(name, matname_) ;
0294 LOG_IF(error, lv == nullptr) << " failed to access lv for name " << name ;
0295 if(lv == nullptr) return nullptr ;
0296
0297 const G4VPhysicalVolume* pv = nullptr ;
0298 bool grid = strstr(name, "Grid") != nullptr ;
0299 bool cube = strstr(name, "Cube") != nullptr ;
0300 bool xoff = strstr(name, "Xoff") != nullptr ;
0301 bool yoff = strstr(name, "Yoff") != nullptr ;
0302 bool zoff = strstr(name, "Zoff") != nullptr ;
0303 bool simp = strstr(name, "Simple") != nullptr ;
0304
0305 if(grid) pv = WrapLVGrid( lv, 1, 1, 1 );
0306 else if(cube) pv = WrapLVCube( lv, 100., 100., 100. );
0307 else if(xoff) pv = WrapLVOffset( lv, 200., 0., 0. );
0308 else if(yoff) pv = WrapLVOffset( lv, 0., 200., 0. );
0309 else if(zoff) pv = WrapLVOffset( lv, 0., 0., 200. );
0310 else if(simp) pv = WrapLVSimple( lv );
0311 else pv = WrapLVCube( lv, 0., 0., 0. );
0312 return pv ;
0313 }
0314
0315
0316
0317
0318
0319
0320
0321
0322
0323
0324
0325
0326
0327
0328
0329 G4LogicalVolume* U4VolumeMaker::LV(const char* name, const char* matname_)
0330 {
0331 const G4VSolid* solid_ = U4SolidMaker::Make(name);
0332 LOG_IF(error, solid_==nullptr) << " failed to access solid for name " << name ;
0333 if(solid_ == nullptr) return nullptr ;
0334
0335 G4VSolid* solid = const_cast<G4VSolid*>(solid_);
0336 const char* matname = matname_ ? matname_ : U4Material::FindMaterialName(name) ;
0337 G4Material* material = U4Material::Get( matname ? matname : U4Material::VACUUM );
0338 G4LogicalVolume* lv = new G4LogicalVolume( solid, material, name, 0,0,0,true );
0339 return lv ;
0340 }
0341
0342
0343
0344
0345
0346
0347
0348
0349
0350
0351 void U4VolumeMaker::LV(std::vector<G4LogicalVolume*>& lvs , const char* names_, char delim )
0352 {
0353 std::vector<std::string> names ;
0354 sstr::Split(names_ , delim, names );
0355 unsigned num_names = names.size();
0356 LOG(LEVEL) << " names_ " << names_ << " num_names " << num_names ;
0357 assert( num_names > 1 );
0358
0359 for(unsigned i=0 ; i < num_names ; i++)
0360 {
0361 const char* name = names[i].c_str();
0362 const char* matname_ = nullptr ;
0363 G4LogicalVolume* lv = LV(name, matname_ ) ;
0364 assert(lv);
0365 lvs.push_back(lv);
0366 }
0367 }
0368
0369
0370
0371
0372
0373
0374
0375
0376
0377
0378
0379 const G4VPhysicalVolume* U4VolumeMaker::Wrap( const char* name, std::vector<G4LogicalVolume*>& items_lv )
0380 {
0381 const char* wrap = spath::GEOMWrap(name);
0382 LOG(LEVEL) << "[ name " << name << " GEOMWrap " << ( wrap ? wrap : "-" ) ;
0383 std::cerr << "U4VolumeMaker::Wrap " << "[ name " << name << " GEOMWrap " << ( wrap ? wrap : "-" ) << std::endl ;
0384 const G4VPhysicalVolume* pv = wrap == nullptr ? WrapRockWater( items_lv ) : WrapAroundItem( name, items_lv, wrap );
0385 LOG(LEVEL) << "] name " << name << " wrap " << ( wrap ? wrap : "-" ) << " pv " << ( pv ? "YES" : "NO" ) ;
0386 return pv ;
0387 }
0388
0389
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413 const G4VPhysicalVolume* U4VolumeMaker::WrapRockWater( std::vector<G4LogicalVolume*>& items_lv )
0414 {
0415 assert( items_lv.size() >= 1 );
0416 G4LogicalVolume* item_lv = items_lv[items_lv.size()-1] ;
0417
0418 LOG(LEVEL) << "[ items_lv.size " << items_lv.size() ;
0419 std::cerr << "[ items_lv.size " << items_lv.size() << std::endl ;
0420
0421 double rock_halfside = ssys::getenv_<double>(U4VolumeMaker_WrapRockWater_Rock_HALFSIDE , 1000.);
0422 double water_halfside = ssys::getenv_<double>(U4VolumeMaker_WrapRockWater_Water_HALFSIDE, 900. );
0423
0424
0425
0426 std::vector<double>* _boxscale = ssys::getenv_vec<double>(U4VolumeMaker_WrapRockWater_BOXSCALE, "1,1,1" );
0427 if(_boxscale) assert(_boxscale->size() == 3 );
0428 const double* boxscale = _boxscale ? _boxscale->data() : nullptr ;
0429
0430 LOG(LEVEL) << U4VolumeMaker_WrapRockWater_Rock_HALFSIDE << " " << rock_halfside ;
0431 LOG(LEVEL) << U4VolumeMaker_WrapRockWater_Water_HALFSIDE << " " << water_halfside ;
0432
0433 std::cerr << U4VolumeMaker_WrapRockWater_Rock_HALFSIDE << " " << rock_halfside << std::endl ;
0434 std::cerr << U4VolumeMaker_WrapRockWater_Water_HALFSIDE << " " << water_halfside << std::endl ;
0435
0436
0437 G4LogicalVolume* rock_lv = Box_(rock_halfside, "Rock", nullptr, boxscale );
0438 G4LogicalVolume* water_lv = Box_(water_halfside, "Water", nullptr, boxscale );
0439
0440
0441 const char* flip_axes = nullptr ;
0442 const G4VPhysicalVolume* item_pv = Place(item_lv, water_lv, flip_axes ); assert( item_pv );
0443
0444
0445 LOG(LEVEL) << std::endl << U4Volume::Traverse( item_pv );
0446
0447 std::vector<std::string>* vbs1 = nullptr ;
0448 vbs1 = ssys::getenv_vec<std::string>(U4VolumeMaker_WrapRockWater_BS1, "pyrex_vacuum_bs:hama_body_phys:hama_inner1_phys", ':' );
0449
0450 G4LogicalBorderSurface* bs1 = nullptr ;
0451 if(vbs1 && vbs1->size() == 3 )
0452 {
0453 const std::string& bs1n = (*vbs1)[0] ;
0454 const std::string& pv1 = (*vbs1)[1] ;
0455 const std::string& pv2 = (*vbs1)[2] ;
0456 bs1 = U4Surface::MakePerfectDetectorBorderSurface(bs1n.c_str(), pv1.c_str(), pv2.c_str(), item_pv );
0457
0458 LOG(error)
0459 << " attempt to add PerfectDetectorBorderSurface between volumes "
0460 << " bs1n " << bs1n
0461 << " pv1 " << pv1
0462 << " pv2 " << pv2
0463 << " bs1 " << ( bs1 ? "YES" : "NO" )
0464 << " using config from " << U4VolumeMaker_WrapRockWater_BS1
0465 ;
0466 }
0467
0468
0469
0470 const G4VPhysicalVolume* water_pv = Place(water_lv, rock_lv); assert( water_pv );
0471 const G4VPhysicalVolume* rock_pv = Place(rock_lv, nullptr );
0472
0473 G4LogicalBorderSurface* water_rock_bs = U4Surface::MakePerfectAbsorberBorderSurface("water_rock_bs", water_pv, rock_pv );
0474 assert( water_rock_bs );
0475 if(!water_rock_bs) std::raise(SIGINT);
0476
0477 LOG(LEVEL) << "]" ;
0478 return rock_pv ;
0479 }
0480
0481
0482
0483
0484
0485
0486
0487
0488
0489
0490
0491
0492
0493
0494
0495
0496
0497 NP* U4VolumeMaker::TRS = nullptr ;
0498
0499 const G4VPhysicalVolume* U4VolumeMaker::WrapAroundItem( const char* name, std::vector<G4LogicalVolume*>& items_lv, const char* prefix )
0500 {
0501 assert( items_lv.size() >= 1 );
0502
0503 NP* trs = MakeTransforms(name, prefix) ;
0504 TRS = trs ;
0505
0506 LOG(LEVEL)
0507 << " items_lv.size " << items_lv.size()
0508 << " prefix " << prefix
0509 << " trs " << ( trs ? trs->sstr() : "-" )
0510 ;
0511
0512
0513 double rock_halfside = ssys::getenv_<double>(U4VolumeMaker_WrapAroundItem_Rock_HALFSIDE, 20000.);
0514 double water_halfside = ssys::getenv_<double>(U4VolumeMaker_WrapAroundItem_Water_HALFSIDE, 19000.);
0515
0516 std::vector<double>* _rock_boxscale = ssys::getenv_vec<double>(U4VolumeMaker_WrapAroundItem_Rock_BOXSCALE, "1,1,1" );
0517 std::vector<double>* _water_boxscale = ssys::getenv_vec<double>(U4VolumeMaker_WrapAroundItem_Water_BOXSCALE, "1,1,1" );
0518
0519 if(_rock_boxscale) assert(_rock_boxscale->size() == 3 );
0520 if(_water_boxscale) assert(_water_boxscale->size() == 3 );
0521
0522 const double* rock_boxscale = _rock_boxscale ? _rock_boxscale->data() : nullptr ;
0523 const double* water_boxscale = _water_boxscale ? _water_boxscale->data() : nullptr ;
0524
0525 G4LogicalVolume* rock_lv = Box_(rock_halfside, "Rock" , nullptr, rock_boxscale );
0526 G4LogicalVolume* water_lv = Box_(water_halfside, "Water", nullptr, water_boxscale );
0527
0528 WrapAround(prefix, trs, items_lv, water_lv );
0529
0530
0531 const G4VPhysicalVolume* water_pv = Place(water_lv, rock_lv);
0532 assert( water_pv );
0533 if(!water_pv) std::raise(SIGINT);
0534
0535 const G4VPhysicalVolume* rock_pv = Place(rock_lv, nullptr );
0536
0537 return rock_pv ;
0538 }
0539
0540
0541
0542 NP* U4VolumeMaker::GetTransforms()
0543 {
0544 return TRS ;
0545 }
0546
0547
0548
0549
0550
0551
0552
0553
0554 void U4VolumeMaker::SaveTransforms( const char* savedir )
0555 {
0556 NP* TRS = U4VolumeMaker::TRS ;
0557 if(TRS) TRS->save(savedir, "TRS.npy") ;
0558 }
0559
0560
0561
0562
0563
0564
0565
0566
0567
0568
0569
0570 const G4VPhysicalVolume* U4VolumeMaker::WrapVacuum( G4LogicalVolume* item_lv )
0571 {
0572 double halfside = ssys::getenv_<double>(U4VolumeMaker_WrapVacuum_HALFSIDE, 1000.);
0573 LOG(LEVEL) << U4VolumeMaker_WrapVacuum_HALFSIDE << " " << halfside ;
0574
0575 G4LogicalVolume* vac_lv = Box_(halfside, U4Material::VACUUM );
0576
0577 const G4VPhysicalVolume* item_pv = Place(item_lv, vac_lv);
0578 assert( item_pv );
0579 if(!item_pv) std::raise(SIGINT);
0580
0581 const G4VPhysicalVolume* vac_pv = Place(vac_lv, nullptr );
0582
0583 return vac_pv ;
0584 }
0585
0586
0587
0588 const G4VPhysicalVolume* U4VolumeMaker::WrapLVSimple( G4LogicalVolume* item_lv )
0589 {
0590 double halfside = ssys::getenv_<double>(U4VolumeMaker_WrapLVSimple_HALFSIDE, 1000.);
0591 LOG(LEVEL) << U4VolumeMaker_WrapLVSimple_HALFSIDE << " " << halfside ;
0592
0593 G4LogicalVolume* vac_lv = Box_(halfside, U4Material::VACUUM );
0594
0595 const G4VPhysicalVolume* item_pv = Place(item_lv, vac_lv);
0596 assert( item_pv );
0597 if(!item_pv) std::raise(SIGINT);
0598
0599 const G4VPhysicalVolume* vac_pv = Place(vac_lv, nullptr );
0600
0601 return vac_pv ;
0602 }
0603
0604
0605
0606
0607
0608
0609
0610
0611
0612
0613
0614
0615
0616
0617
0618
0619
0620
0621
0622
0623
0624
0625
0626
0627
0628
0629
0630
0631
0632 const G4VPhysicalVolume* U4VolumeMaker::WrapLVGrid( G4LogicalVolume* lv, int nx, int ny, int nz )
0633 {
0634 std::vector<G4LogicalVolume*> lvs ;
0635 lvs.push_back(lv);
0636 return WrapLVGrid(lvs, nx, ny, nz ) ;
0637 }
0638
0639 const G4VPhysicalVolume* U4VolumeMaker::WrapLVGrid( std::vector<G4LogicalVolume*>& lvs, int nx, int ny, int nz )
0640 {
0641 unsigned num_lv = lvs.size();
0642
0643 int extent = std::max(std::max(nx, ny), nz);
0644 G4double sc = 500. ;
0645 G4double halfside = sc*extent*3. ;
0646
0647 LOG(LEVEL)
0648 << " num_lv " << num_lv
0649 << " (nx,ny,nz) (" << nx << "," << ny << " " << nz << ")"
0650 << " extent " << extent
0651 << " halfside " << halfside
0652 ;
0653
0654 const G4VPhysicalVolume* world_pv = WorldBox(halfside);
0655 G4LogicalVolume* world_lv = world_pv->GetLogicalVolume();
0656
0657 unsigned count = 0 ;
0658 for(int ix=-nx ; ix < nx+1 ; ix++)
0659 for(int iy=-ny ; iy < ny+1 ; iy++)
0660 for(int iz=-nz ; iz < nz+1 ; iz++)
0661 {
0662 G4LogicalVolume* ulv = lvs[count%num_lv] ;
0663 count += 1 ;
0664 assert( ulv );
0665
0666 const G4String& ulv_name_ = ulv->GetName();
0667 std::string ulv_name = ulv_name_ ;
0668 ulv_name += "_plc_" ;
0669
0670 const char* iname = GridName( ulv_name.c_str(), ix, iy, iz, "" );
0671 G4ThreeVector tla( sc*double(ix), sc*double(iy), sc*double(iz) );
0672
0673 LOG(LEVEL)
0674 << " G4PVPlacement "
0675 << " count " << std::setw(3) << count
0676 << Desc(tla)
0677 << iname
0678 ;
0679 const G4VPhysicalVolume* pv_n = new G4PVPlacement(0, tla, ulv ,iname,world_lv,false,0);
0680 assert( pv_n );
0681 if(!pv_n) std::raise(SIGINT);
0682 }
0683 return world_pv ;
0684 }
0685
0686
0687
0688
0689
0690
0691
0692
0693
0694
0695
0696
0697
0698
0699
0700
0701 const G4VPhysicalVolume* U4VolumeMaker::WrapLVOffset( G4LogicalVolume* lv, double tx, double ty, double tz )
0702 {
0703 double halfside = 3.*std::max( std::max( tx, ty ), tz );
0704 assert( halfside > 0. );
0705
0706 const G4VPhysicalVolume* world_pv = WorldBox(halfside);
0707 G4LogicalVolume* world_lv = world_pv->GetLogicalVolume();
0708
0709 AddPlacement(world_lv, lv, tx, ty, tz );
0710
0711 bool bmo = true ;
0712 if(bmo) AddPlacement( world_lv, "BoxMinusOrb", 0., 0., 0. );
0713
0714 return world_pv ;
0715 }
0716
0717
0718
0719
0720
0721
0722
0723
0724
0725
0726
0727
0728
0729
0730
0731
0732
0733
0734
0735
0736
0737
0738
0739
0740
0741
0742
0743
0744
0745
0746
0747
0748
0749
0750
0751
0752
0753
0754 const G4VPhysicalVolume* U4VolumeMaker::WrapLVCube( G4LogicalVolume* lv, double tx, double ty, double tz )
0755 {
0756 double halfside = 3.*std::max( std::max( tx, ty ), tz );
0757
0758 const G4VPhysicalVolume* world_pv = WorldBox(halfside);
0759 G4LogicalVolume* world_lv = world_pv->GetLogicalVolume();
0760 G4String name = lv->GetName();
0761
0762 for(unsigned i=0 ; i < 8 ; i++)
0763 {
0764 bool px = ((i & 0x1) != 0) ;
0765 bool py = ((i & 0x2) != 0) ;
0766 bool pz = ((i & 0x4) != 0) ;
0767 G4ThreeVector tla( px ? tx : -tx , py ? ty : -ty, pz ? tz : -tz );
0768 const char* iname = GridName(name.c_str(), int(px), int(py), int(pz), "" );
0769 const G4VPhysicalVolume* pv = new G4PVPlacement(0,tla,lv,iname,world_lv,false,0);
0770 assert( pv );
0771 if(!pv) std::raise(SIGINT);
0772 }
0773 return world_pv ;
0774 }
0775
0776
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 const G4VPhysicalVolume* U4VolumeMaker::AddPlacement( G4LogicalVolume* mother_lv, G4LogicalVolume* lv, double tx, double ty, double tz )
0791 {
0792 G4ThreeVector tla(tx,ty,tz);
0793 const char* pv_name = spath::Name( lv->GetName().c_str(), "_placement" );
0794 LOG(LEVEL) << Desc(tla) << " " << pv_name ;
0795 const G4VPhysicalVolume* pv = new G4PVPlacement(0,tla,lv,pv_name,mother_lv,false,0);
0796 return pv ;
0797 }
0798 const G4VPhysicalVolume* U4VolumeMaker::AddPlacement( G4LogicalVolume* mother, const char* name, double tx, double ty, double tz )
0799 {
0800 const char* matname_ = nullptr ;
0801 G4LogicalVolume* lv = LV(name, matname_);
0802 return AddPlacement( mother, lv, tx, ty, tz );
0803 }
0804
0805 const char* U4VolumeMaker::GridName(const char* prefix, int ix, int iy, int iz, const char* suffix)
0806 {
0807 std::stringstream ss ;
0808 ss << prefix << ix << "_" << iy << "_" << iz << suffix ;
0809 std::string s = ss.str();
0810 return strdup(s.c_str());
0811 }
0812
0813 const char* U4VolumeMaker::PlaceName(const char* prefix, int ix, const char* suffix)
0814 {
0815 std::stringstream ss ;
0816 if(prefix) ss << prefix ;
0817 ss << ix ;
0818 if(suffix) ss << suffix ;
0819 std::string s = ss.str();
0820 return strdup(s.c_str());
0821 }
0822
0823
0824
0825
0826
0827
0828
0829
0830
0831
0832
0833
0834
0835 const G4VPhysicalVolume* U4VolumeMaker::WorldBox( double halfside, const char* mat )
0836 {
0837 if(mat == nullptr) mat = U4Material::VACUUM ;
0838 return Box(halfside, mat, "World", nullptr );
0839 }
0840 const G4VPhysicalVolume* U4VolumeMaker::BoxOfScintillator( double halfside )
0841 {
0842 return BoxOfScintillator(halfside, "BoxOfScintillator", nullptr );
0843 }
0844 const G4VPhysicalVolume* U4VolumeMaker::BoxOfScintillator( double halfside, const char* prefix, G4LogicalVolume* mother_lv )
0845 {
0846 return Box(halfside, U4Material::SCINTILLATOR, "BoxOfScintillator", mother_lv);
0847 }
0848
0849
0850
0851 const G4VPhysicalVolume* U4VolumeMaker::Box(double halfside, const char* mat, const char* prefix, G4LogicalVolume* mother_lv )
0852 {
0853 if(prefix == nullptr) prefix = mat ;
0854 G4LogicalVolume* lv = Box_(halfside, mat, prefix);
0855 return Place(lv, mother_lv);
0856 }
0857
0858
0859 const G4VPhysicalVolume* U4VolumeMaker::Place( G4LogicalVolume* lv, G4LogicalVolume* mother_lv, const char* flip_axes )
0860 {
0861 const char* lv_name = lv->GetName().c_str() ;
0862 const char* pv_name = spath::Name(lv_name, "_pv") ;
0863
0864 U4RotationMatrix* flip = flip_axes ? U4RotationMatrix::Flip(flip_axes) : nullptr ;
0865 return new G4PVPlacement(flip,G4ThreeVector(), lv, pv_name, mother_lv, false, 0);
0866 }
0867
0868
0869 const G4VPhysicalVolume* U4VolumeMaker::LocalFastenerAcrylicConstruction(const char* name)
0870 {
0871 const char* PREFIX = "LocalFastenerAcrylicConstruction" ;
0872 assert( sstr::StartsWith(name,PREFIX ));
0873 int num = strlen(name) > strlen(PREFIX) ? std::atoi( name + strlen(PREFIX) ) : 8 ;
0874
0875 LOG(info)
0876 << " name " << ( name ? name : "-" )
0877 << " num " << num
0878 ;
0879
0880 G4double universe_halfside = 300.*mm ;
0881 const char* universe_material = "G4_AIR" ;
0882
0883 G4LogicalVolume* universe_lv = Box_(universe_halfside, universe_material );
0884 G4LogicalVolume* object_lv = LV(name, "G4_Pb" ) ;
0885
0886 const G4VPhysicalVolume* universe_pv = new G4PVPlacement(0,G4ThreeVector(), universe_lv , "universe_pv", nullptr,false,0);
0887 [[maybe_unused]] const G4VPhysicalVolume* object_pv = new G4PVPlacement(0,G4ThreeVector(), object_lv ,"object_pv", universe_lv,false,0);
0888 assert( object_pv );
0889
0890 return universe_pv ;
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 const G4VPhysicalVolume* U4VolumeMaker::Local(const char* name)
0936 {
0937 const char* PREFIX = "Local" ;
0938 assert( sstr::StartsWith(name,PREFIX ));
0939 const char* name_after_PREFIX = name + strlen(PREFIX);
0940
0941 G4LogicalVolume* object_lv = LV(name_after_PREFIX, "G4_Pb" ) ;
0942 const G4VSolid* const solid = object_lv->GetSolid();
0943
0944 G4ThreeVector pMin ;
0945 G4ThreeVector pMax ;
0946 solid->BoundingLimits(pMin, pMax);
0947
0948
0949 std::array<double,6> bb = {pMin.x(), pMin.y(), pMin.z(), pMax.x(), pMax.y(), pMax.z() };
0950 double extent = s_bb::Extent<double>(bb.data());
0951 double absmax = s_bb::AbsMax<double>(bb.data());
0952 LOG(info)
0953 << " name " << ( name ? name : "-" )
0954 << " name_after_PREFIX " << ( name_after_PREFIX ? name_after_PREFIX : "-" )
0955 << " bb " << s_bb::Desc<double>(bb.data())
0956 << " extent " << extent
0957 << " absmax " << absmax
0958 ;
0959
0960 G4double universe_halfside = 1.5*absmax*mm ;
0961 const char* universe_material = "G4_AIR" ;
0962
0963 G4LogicalVolume* universe_lv = Box_(universe_halfside, universe_material );
0964
0965 const G4VPhysicalVolume* universe_pv = new G4PVPlacement(0,G4ThreeVector(), universe_lv , "universe_pv", nullptr,false,0);
0966 [[maybe_unused]] const G4VPhysicalVolume* object_pv = new G4PVPlacement(0,G4ThreeVector(), object_lv ,"object_pv", universe_lv,false,0);
0967 assert( object_pv );
0968
0969 return universe_pv ;
0970 }
0971
0972
0973
0974
0975
0976
0977
0978
0979
0980
0981
0982
0983
0984
0985
0986
0987
0988
0989
0990
0991
0992
0993
0994
0995
0996
0997
0998
0999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021 void U4VolumeMaker::RaindropRockAirWater_Configure(
1022 std::vector<std::string>& mats,
1023 std::vector<double>& rindex,
1024 double& universe_halfside,
1025 double& container_halfside,
1026 double& medium_halfside,
1027 double& drop_radius,
1028 std::string& dropshape
1029 )
1030 {
1031 ssys::fill_evec(mats, U4VolumeMaker_RaindropRockAirWater_MATS, "VACUUM,G4_Pb,G4_AIR,G4_WATER", ',' ) ;
1032 ssys::fill_evec(rindex, U4VolumeMaker_RaindropRockAirWater_RINDEX, "0,0,1,1.333", ',' ) ;
1033
1034 double halfside = ssys::getenv_<double>(U4VolumeMaker_RaindropRockAirWater_HALFSIDE, 100.);
1035 double factor = ssys::getenv_<double>(U4VolumeMaker_RaindropRockAirWater_FACTOR, 1.);
1036 dropshape = ssys::getenvvar(U4VolumeMaker_RaindropRockAirWater_DROPSHAPE, "Orb");
1037
1038 LOG(LEVEL) << U4VolumeMaker_RaindropRockAirWater_MATS << " " << ssys::desc_vec(&mats) ;
1039 LOG(LEVEL) << U4VolumeMaker_RaindropRockAirWater_HALFSIDE << " " << halfside ;
1040 LOG(LEVEL) << U4VolumeMaker_RaindropRockAirWater_FACTOR << " " << factor ;
1041 LOG(LEVEL) << U4VolumeMaker_RaindropRockAirWater_DROPSHAPE << " " << dropshape ;
1042
1043 universe_halfside = 1.2*halfside*factor ;
1044 container_halfside = 1.1*halfside*factor ;
1045 medium_halfside = halfside*factor ;
1046 drop_radius = halfside/2. ;
1047 }
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 const G4VPhysicalVolume* U4VolumeMaker::RaindropRockAirWater(bool sd)
1075 {
1076 std::vector<std::string> mats ;
1077 std::vector<double> rindex ;
1078
1079 double universe_halfside ;
1080 double container_halfside ;
1081 double medium_halfside ;
1082 double drop_radius ;
1083 std::string dropshape ;
1084
1085 RaindropRockAirWater_Configure( mats, rindex, universe_halfside, container_halfside, medium_halfside, drop_radius, dropshape );
1086
1087 static const int N = 4 ;
1088 bool mats_expect = mats.size() == N ;
1089 bool rindex_expect = rindex.size() == N ;
1090
1091 LOG_IF(error, !mats_expect) << " unexpected mats.size " << mats.size() << " expecting " << N ;
1092 LOG_IF(error, !rindex_expect) << " unexpected rindex.size " << rindex.size() << " expecting " << N ;
1093 assert( mats_expect );
1094 assert( rindex_expect );
1095
1096 std::array<G4Material*, N> materials ;
1097
1098 for(int i=0 ; i < N ; i++)
1099 {
1100 const char* mat = mats[i].c_str() ;
1101 G4Material* material = U4Material::Get(mat) ;
1102 if( material == nullptr ) std::cerr
1103 << "U4Material::Get"
1104 << " FAILED FOR [" << mat << "]"
1105 << std::endl
1106 ;
1107 materials[i] = material ;
1108 }
1109
1110 G4Material* universe_material = materials[0] ;
1111 G4Material* container_material = materials[1] ;
1112 G4Material* medium_material = materials[2] ;
1113 G4Material* drop_material = materials[3] ;
1114
1115
1116 for(int i=0 ; i < N ; i++)
1117 {
1118 G4Material* mat = materials[i] ;
1119 assert(mat);
1120
1121 if(rindex[i] > 0. && !U4Material::HasMPT(mat) )
1122 {
1123 U4Material::SetMPT(mat,U4MaterialPropertiesTable::Create("RINDEX", rindex[i])) ;
1124 }
1125 }
1126
1127
1128 G4LogicalVolume* universe_lv = Box_(universe_halfside, universe_material );
1129 G4LogicalVolume* container_lv = Box_(container_halfside, container_material );
1130 G4LogicalVolume* medium_lv = Box_(medium_halfside, medium_material );
1131
1132 G4LogicalVolume* drop_lv = nullptr ;
1133 if( strcmp(dropshape.c_str(), "Orb") == 0 ) drop_lv = Orb_(drop_radius, drop_material );
1134 else if(strcmp(dropshape.c_str(), "Box") == 0 ) drop_lv = Box_(drop_radius, drop_material );
1135 LOG_IF(fatal, drop_lv == nullptr ) << " drop_lv NULL : dropshape must be one of Orb,Box not [" << dropshape << "]" ;
1136 assert( drop_lv );
1137
1138 const G4VPhysicalVolume* drop_pv = new G4PVPlacement(0,G4ThreeVector(), drop_lv ,"drop_pv", medium_lv,false,0);
1139 const G4VPhysicalVolume* medium_pv = new G4PVPlacement(0,G4ThreeVector(), medium_lv , "medium_pv", container_lv,false,0);
1140 const G4VPhysicalVolume* container_pv = new G4PVPlacement(0,G4ThreeVector(), container_lv , "container_pv", universe_lv,false,0);
1141 const G4VPhysicalVolume* universe_pv = new G4PVPlacement(0,G4ThreeVector(), universe_lv , "universe_pv", nullptr,false,0);
1142
1143 assert( drop_pv );
1144 assert( medium_pv );
1145 assert( container_pv );
1146 assert( universe_pv );
1147
1148 G4LogicalBorderSurface* medium_container_bs = U4Surface::MakePerfectAbsorberBorderSurface(
1149 "medium_container_bs", medium_pv, container_pv );
1150 assert( medium_container_bs );
1151 if(!medium_container_bs) std::raise(SIGINT);
1152
1153 if(sd)
1154 {
1155
1156
1157
1158 G4LogicalBorderSurface* medium_drop_bs = U4Surface::MakePerfectDetectorBorderSurface("medium_drop_bs", medium_pv, drop_pv );
1159 assert( medium_drop_bs );
1160 if(!medium_drop_bs) std::raise(SIGINT);
1161
1162 }
1163 return universe_pv ;
1164 }
1165
1166
1167
1168 const G4VPhysicalVolume* U4VolumeMaker::BigWaterPool()
1169 {
1170
1171 double m_heightWP = 43500 ;
1172 double m_deadWaterThickness = 100 ;
1173 double m_tyvekThickness = 2 ;
1174 double m_radWP = 21750 ;
1175
1176 G4Material* vetoWater = U4Material::Get("G4_WATER") ;
1177 G4VSolid* solidWaterPool = nullptr ;
1178 G4LogicalVolume* logicWaterPool = nullptr ;
1179
1180 const G4VPhysicalVolume* pTyvekFilm = nullptr ;
1181 const G4VPhysicalVolume* pWaterPool = nullptr ;
1182
1183 G4VSolid* solidTyvekFilm = nullptr ;
1184 G4LogicalVolume* logicAirGap = nullptr ;
1185 G4LogicalVolume* logicDeadWater = nullptr ;
1186 G4LogicalVolume* logicTyvekFilm = nullptr ;
1187
1188 G4Material* DeadWater = U4Material::Get("G4_WATER") ;
1189 G4Material* Tyvek = U4Material::Get("G4_WATER") ;
1190 G4Material* BufferMaterials = U4Material::Get("G4_WATER") ;
1191
1192 std::array<G4Material*,3> mats = {DeadWater, Tyvek, BufferMaterials };
1193
1194 for(int i=0 ; i < int(mats.size()) ; i++)
1195 {
1196 G4Material* mat = mats[i];
1197 std::cout
1198 << " i " << i
1199 << " mat " << std::hex << size_t(mat) << std::dec
1200 << " mpt " << U4Material::HasMPT(mat)
1201 << "\n"
1202 ;
1203
1204 if(!U4Material::HasMPT(mat)) U4Material::SetMPT(mat,U4MaterialPropertiesTable::Create("RINDEX", 1.333)) ;
1205 }
1206
1207
1208
1209
1210 {
1211 G4VSolid* solidDeadWater = new G4Tubs("sDeadWater_shell", 0., m_radWP, m_heightWP/2., 0.*deg, 360*deg);
1212 logicDeadWater = new G4LogicalVolume(solidDeadWater, DeadWater, "lDeadWater", 0, 0, 0);
1213 }
1214
1215
1216
1217 {
1218 double tyvek_btmZ = -m_heightWP/2 + m_deadWaterThickness - m_tyvekThickness;
1219 double tyvek_topZ = -tyvek_btmZ;
1220 double tyvek_outR = m_radWP - m_deadWaterThickness + m_tyvekThickness;
1221
1222
1223 static G4double zPlane[] = {tyvek_btmZ, tyvek_topZ};
1224 static G4double rInner[] = {0., 0.};
1225 static G4double rOuter[] = {tyvek_outR, tyvek_outR};
1226
1227 G4VSolid* solidTyvek_shell = new G4Polycone("sTyvek_shell",
1228 0,
1229 360*deg,
1230 2,
1231 zPlane,
1232 rInner,
1233 rOuter
1234 );
1235
1236
1237 solidTyvekFilm = solidTyvek_shell ;
1238 logicTyvekFilm = new G4LogicalVolume(solidTyvekFilm, Tyvek, "lTyvekFilm", 0, 0, 0);
1239 }
1240
1241
1242
1243
1244 {
1245 double vetoWater_btmZ = -m_heightWP/2 + m_deadWaterThickness;
1246 double vetoWater_topZ = m_heightWP/2 - m_deadWaterThickness;
1247 double vetoWater_outR = m_radWP - m_deadWaterThickness ;
1248
1249 static G4double zPlane[] = {vetoWater_btmZ, vetoWater_topZ};
1250 static G4double rInner[] = {0., 0.};
1251 static G4double rOuter[] = {vetoWater_outR, vetoWater_outR};
1252 solidWaterPool = new G4Polycone("sOuterWaterPool",
1253 0,
1254 360*deg,
1255 2,
1256 zPlane,
1257 rInner,
1258 rOuter
1259 );
1260
1261 logicWaterPool = new G4LogicalVolume(solidWaterPool,
1262 vetoWater,
1263 "lOuterWaterPool",
1264 0, 0, 0);
1265 }
1266
1267
1268
1269
1270 G4LogicalVolume* logicMaskVirtual = nullptr ;
1271 {
1272
1273
1274 G4double htop_thickness=8.*mm ;
1275 G4double htop_gap=2.*mm ;
1276
1277
1278 G4double MAGIC_virtual_thickness = 0.10*mm;
1279
1280 G4double requator_thickness=8.*mm ;
1281 G4double requator_gap=2.*mm ;
1282
1283 G4double mask_radiu_in = 254.*mm + requator_gap;
1284 G4double mask_radiu_out = mask_radiu_in + requator_thickness;
1285 G4double mask_radiu_virtual = mask_radiu_out + MAGIC_virtual_thickness;
1286
1287
1288 G4double htop_in = 184.*mm + htop_gap;
1289 G4double htop_out = htop_in + htop_thickness;
1290
1291
1292
1293 G4double height_in = 10*mm + 5.*mm;
1294 G4double height_out = height_in + 10*mm;
1295 G4double height_virtual = height_out + MAGIC_virtual_thickness;
1296
1297 G4double zPlane[] = {
1298 -height_virtual,
1299 htop_out + MAGIC_virtual_thickness
1300 };
1301 G4double rInner[] = {0.,
1302 0.};
1303 G4double rOuter[] = {mask_radiu_virtual,
1304 mask_radiu_virtual};
1305
1306 G4VSolid* SolidMaskVirtual = new G4Polycone(
1307 "sMask_virtual",
1308 0,
1309 360*deg,
1310 2,
1311 zPlane,
1312 rInner,
1313 rOuter
1314 );
1315
1316 logicMaskVirtual = new G4LogicalVolume(
1317 SolidMaskVirtual,
1318 BufferMaterials,
1319 "lMaskVirtual",
1320 0,
1321 0,
1322 0);
1323 }
1324
1325
1326
1327 new G4PVPlacement(0, G4ThreeVector(0, 0, 0),logicDeadWater,"pDeadWater",logicAirGap , false, 0);
1328
1329
1330 pTyvekFilm = new G4PVPlacement(0, G4ThreeVector(0, 0, 0),logicTyvekFilm,"pTyvekFilm",logicDeadWater , false, 0);
1331
1332
1333 pWaterPool = new G4PVPlacement(0, G4ThreeVector(0, 0, 0),logicWaterPool,"pWaterPool",logicTyvekFilm , false, 0);
1334
1335 U4Surface::MakePerfectAbsorberBorderSurface( "WaterPool_Tyvek_bs", pWaterPool, pTyvekFilm );
1336
1337
1338 {
1339
1340
1341 G4double x = -994.96197509765625 ;
1342 G4double y = 20447.890625 ;
1343 G4double z = 730.7440185546875 ;
1344 G4double theta = 1.53511662609056 ;
1345 G4double phi = 1.6194159277617648 ;
1346
1347 G4ThreeVector pos(x, y, z);
1348 G4RotationMatrix rot;
1349 rot.rotateY(theta);
1350 rot.rotateZ(phi);
1351 G4Transform3D trans(rot, pos);
1352 G4Transform3D& tr = trans ;
1353
1354
1355 auto _rot = tr.getRotation();
1356 auto _translation = tr.getTranslation();
1357 _translation.setR(20.502*m);
1358
1359 G4Transform3D tr_ideal(_rot, _translation);
1360
1361
1362 new G4PVPlacement(tr_ideal,logicMaskVirtual,"pMask",logicWaterPool , false, 0);
1363 }
1364
1365 return pTyvekFilm ;
1366
1367 }
1368
1369
1370
1371 G4Material* U4VolumeMaker::GetMaterial(const char* mat)
1372 {
1373 G4Material* material = U4Material::Get(mat);
1374 LOG_IF(fatal, material==nullptr) << " U4Material::Get failed for mat[" << ( mat ? mat : "-" ) << "]" ;
1375 assert(material);
1376 return material ;
1377 }
1378
1379 G4LogicalVolume* U4VolumeMaker::Orb_( double radius, const char* mat, const char* prefix )
1380 {
1381 if( prefix == nullptr ) prefix = mat ;
1382 G4Material* material = GetMaterial(mat) ;
1383 return Orb_(radius, material, prefix );
1384 }
1385 G4LogicalVolume* U4VolumeMaker::Orb_( double radius, G4Material* material, const char* prefix )
1386 {
1387 if( prefix == nullptr ) prefix = material->GetName().c_str() ;
1388 G4Orb* solid = new G4Orb( spath::Name(prefix,"_solid"), radius );
1389 G4LogicalVolume* lv = new G4LogicalVolume( solid, material, spath::Name(prefix,"_lv"));
1390 return lv ;
1391 }
1392 G4LogicalVolume* U4VolumeMaker::Box_( double halfside, const char* mat, const char* prefix, const double* scale )
1393 {
1394 if( prefix == nullptr ) prefix = mat ;
1395 G4Material* material = GetMaterial(mat) ;
1396 return Box_( halfside, material, prefix, scale );
1397 }
1398
1399 G4LogicalVolume* U4VolumeMaker::Box_( double halfside, G4Material* material, const char* prefix, const double* scale )
1400 {
1401 if( prefix == nullptr ) prefix = material->GetName().c_str() ;
1402 double hx = scale ? scale[0]*halfside : halfside ;
1403 double hy = scale ? scale[1]*halfside : halfside ;
1404 double hz = scale ? scale[2]*halfside : halfside ;
1405
1406 LOG(LEVEL) << " hx " << hx << " hy " << hy << " hz " << hz << " halfside " << halfside ;
1407
1408 G4Box* solid = new G4Box( spath::Name(prefix,"_solid"), hx, hy, hz );
1409 G4LogicalVolume* lv = new G4LogicalVolume( solid, material, spath::Name(prefix,"_lv"));
1410 return lv ;
1411 }
1412
1413
1414 NP* U4VolumeMaker::MakeTransforms( const char* name, const char* prefix )
1415 {
1416 const char* opts = "TR,tr,R,T,r,t" ;
1417 NP* trs = nullptr ;
1418
1419 if(strcmp(prefix, "AroundSphere")==0)
1420 {
1421 double radius = 17000. ;
1422 double item_arclen = 600. ;
1423 unsigned num_ring = 8 ;
1424 trs = SPlace::AroundSphere( opts, radius, item_arclen, num_ring );
1425 }
1426 else if(strcmp(prefix, "AroundCylinder")==0)
1427 {
1428 double radius = 17000. ;
1429 double halfheight = radius ;
1430 unsigned num_ring = 8 ;
1431 unsigned num_in_ring = 16 ;
1432 trs = SPlace::AroundCylinder(opts, radius, halfheight, num_ring, num_in_ring );
1433 }
1434 else if(strcmp(prefix, "AroundCircle")==0)
1435 {
1436 double radius = ssys::getenv_<double>(U4VolumeMaker_MakeTransforms_AroundCircle_radius, 1000.);
1437 unsigned numInRing = ssys::getenv_<unsigned>(U4VolumeMaker_MakeTransforms_AroundCircle_numInRing, 4u );
1438 double fracPhase = ssys::getenv_<double>(U4VolumeMaker_MakeTransforms_AroundCircle_fracPhase, 0.);
1439 trs = SPlace::AroundCircle(opts, radius, numInRing, fracPhase );
1440 }
1441 return trs ;
1442 }
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
1454
1455
1456
1457 void U4VolumeMaker::WrapAround( const char* prefix, const NP* trs, std::vector<G4LogicalVolume*>& lvs, G4LogicalVolume* mother_lv )
1458 {
1459 unsigned num_place = trs->shape[0] ;
1460 unsigned place_tr = trs->shape[1] ;
1461 unsigned place_values = place_tr*4*4 ;
1462 unsigned num_lv = lvs.size();
1463
1464
1465 assert( trs->has_shape(num_place,place_tr,4,4) );
1466 assert( place_tr == 6 );
1467 enum { _TR, _tr, _R, _T, _r, _t } ;
1468
1469 const double* tt = trs->cvalues<double>();
1470
1471 for(unsigned i=0 ; i < num_place ; i++)
1472 {
1473 const double* T = tt + place_values*i + _T*16 ;
1474 const double* R = tt + place_values*i + _R*16 ;
1475
1476
1477
1478 G4ThreeVector tla( T[12], T[13], T[14] );
1479
1480 LOG(LEVEL) << " i " << std::setw(7) << " tla " << U4ThreeVector::Desc(tla) ;
1481
1482 bool transpose = true ;
1483 U4RotationMatrix* rot = new U4RotationMatrix( R, transpose );
1484
1485 LOG(LEVEL) << " i " << std::setw(7) << " rot " << U4RotationMatrix::Desc(rot) ;
1486
1487 const char* iname = PlaceName(prefix, i, nullptr);
1488
1489 G4bool pMany_unused = false ;
1490 G4int pCopyNo = (i+1)*10 ;
1491 G4LogicalVolume* lv = lvs[i%num_lv] ;
1492
1493 const G4VPhysicalVolume* pv_n = new G4PVPlacement(rot, tla, lv, iname, mother_lv, pMany_unused, pCopyNo );
1494 assert( pv_n );
1495 if(!pv_n) std::raise(SIGINT);
1496
1497 }
1498 }
1499