Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-06-25 07:54:44

0001 //
0002 // ********************************************************************
0003 // * License and Disclaimer                                           *
0004 // *                                                                  *
0005 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
0006 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
0007 // * conditions of the Geant4 Software License,  included in the file *
0008 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
0009 // * include a list of copyright holders.                             *
0010 // *                                                                  *
0011 // * Neither the authors of this software system, nor their employing *
0012 // * institutes,nor the agencies providing financial support for this *
0013 // * work  make  any representation or  warranty, express or implied, *
0014 // * regarding  this  software system or assume any liability for its *
0015 // * use.  Please see the license in the file  LICENSE  and URL above *
0016 // * for the full disclaimer and the limitation of liability.         *
0017 // *                                                                  *
0018 // * This  code  implementation is the result of  the  scientific and *
0019 // * technical work of the GEANT4 collaboration.                      *
0020 // * By using,  copying,  modifying or  distributing the software (or *
0021 // * any work based  on the software)  you  agree  to acknowledge its *
0022 // * use  in  resulting  scientific  publications,  and indicate your *
0023 // * acceptance of all terms of the Geant4 Software license.          *
0024 // ********************************************************************
0025 //
0026 /// \file TSDetectorConstruction.cc
0027 /// \brief Implementation of the TSDetectorConstruction class
0028 ///
0029 /// Construction of a target material (default = boron) surrounded by a
0030 ///     casing material (default = water) and a vacuum world (default =
0031 ///     target and casing fill world). The target + casing is brick
0032 ///     geometry with fTargetSections defining the number of divisions
0033 ///     in each dimension. The end sections in each dimension
0034 ///     is set to the casing. So a fTargetSections = G4ThreeVector(3, 3, 3)
0035 ///     would be one section of boron and 8 sections of water.
0036 ///
0037 /// The idea behind this geometry is just to create a simple geometry that
0038 ///     scatters and produces a lot neutrons with a minimal number of sections
0039 ///     (i.e. coarse meshing) such that the contention in operating on
0040 ///     the atomic hits maps is higher and round-off errors in the
0041 ///     thread-local hits maps are detectable (printed out in TSRunAction)
0042 ///     from the sheer number of floating point sum operations.
0043 ///
0044 /// Two scorers are implemented: EnergyDeposit and Number of steps
0045 ///     The energy deposit is to (possibly) show the round-off error seen
0046 ///     with thread-local hits maps. The # of steps scorer is to verify
0047 ///     the thread-safe and thread-local hits maps provide the same results.
0048 //
0049 //
0050 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0051 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0052 
0053 #include "TSDetectorConstruction.hh"
0054 
0055 #include "G4Box.hh"
0056 #include "G4Colour.hh"
0057 #include "G4LogicalVolume.hh"
0058 #include "G4Material.hh"
0059 #include "G4MultiFunctionalDetector.hh"
0060 #include "G4NistManager.hh"
0061 #include "G4PSEnergyDeposit.hh"
0062 #include "G4PSNofStep.hh"
0063 #include "G4PVPlacement.hh"
0064 #include "G4RunManager.hh"
0065 #include "G4SDManager.hh"
0066 #include "G4UnitsTable.hh"
0067 #include "G4UserLimits.hh"
0068 #include "G4VPhysicalVolume.hh"
0069 #include "G4VisAttributes.hh"
0070 
0071 using namespace CLHEP;
0072 
0073 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0074 
0075 TSDetectorConstruction* TSDetectorConstruction::fgInstance = 0;
0076 
0077 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0078 
0079 TSDetectorConstruction* TSDetectorConstruction::Instance()
0080 {
0081   return fgInstance;
0082 }
0083 
0084 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0085 
0086 TSDetectorConstruction::TSDetectorConstruction()
0087   : fWorldPhys(0),
0088     fWorldMaterialName("G4_Galactic"),
0089     fTargetMaterialName("G4_B"),
0090     fCasingMaterialName("G4_WATER"),
0091     fWorldDim(G4ThreeVector(0.5 * m, 0.5 * m, 0.5 * m)),
0092     fTargetDim(G4ThreeVector(0.5 * m, 0.5 * m, 0.5 * m)),
0093     fTargetSections(G4ThreeVector(5, 5, 5)),
0094     fMfdName("Target_MFD")
0095 {
0096   fgInstance = this;
0097 }
0098 
0099 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0100 
0101 TSDetectorConstruction::~TSDetectorConstruction()
0102 {
0103   fgInstance = 0;
0104 }
0105 
0106 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0107 
0108 G4VPhysicalVolume* TSDetectorConstruction::Construct()
0109 {
0110   return ConstructWorld(ConstructMaterials());
0111 }
0112 
0113 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0114 
0115 TSDetectorConstruction::MaterialCollection_t TSDetectorConstruction::ConstructMaterials()
0116 {
0117   MaterialCollection_t materials;
0118   G4NistManager* nist = G4NistManager::Instance();
0119 
0120   materials["World"] = nist->FindOrBuildMaterial(fWorldMaterialName);
0121   materials["Target"] = nist->FindOrBuildMaterial(fTargetMaterialName);
0122   materials["Casing"] = nist->FindOrBuildMaterial(fCasingMaterialName);
0123 
0124   return materials;
0125 }
0126 
0127 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0128 
0129 G4VPhysicalVolume* TSDetectorConstruction::ConstructWorld(const MaterialCollection_t& materials)
0130 {
0131   G4UserLimits* steplimit = new G4UserLimits(0.1 * (fTargetDim.z() / fTargetSections.z()));
0132   G4bool check_overlap = false;
0133 
0134   G4Box* world_solid =
0135     new G4Box("World", 0.5 * fWorldDim.x(), 0.5 * fWorldDim.y(), 0.5 * fWorldDim.z());
0136   G4LogicalVolume* world_log =
0137     new G4LogicalVolume(world_solid, materials.find("World")->second, "World");
0138   fWorldPhys =
0139     new G4PVPlacement(0, G4ThreeVector(0.), "World", world_log, 0, false, 0, check_overlap);
0140 
0141   G4int nz = fTargetSections.z();
0142   G4int ny = fTargetSections.y();
0143   G4int nx = fTargetSections.x();
0144 
0145   // spacing between sections
0146   G4double sx = fTargetDim.x() / fTargetSections.x();
0147   G4double sy = fTargetDim.y() / fTargetSections.y();
0148   G4double sz = fTargetDim.z() / fTargetSections.z();
0149 
0150   // G4cout << "World has dimensions : "
0151   //<< G4BestUnit(fWorldDim, "Length") << G4endl;
0152 
0153   //------------------------------------------------------------------------//
0154   // Set Visual Attributes
0155   //------------------------------------------------------------------------//
0156   G4VisAttributes* red = new G4VisAttributes(G4Color(1., 0., 0., 1.0));
0157   G4VisAttributes* green = new G4VisAttributes(G4Color(0., 1., 0., 0.25));
0158   G4VisAttributes* blue = new G4VisAttributes(G4Color(0., 0., 1., 0.1));
0159   G4VisAttributes* white = new G4VisAttributes(G4Color(1., 1., 1., 1.));
0160 
0161   white->SetVisibility(true);
0162   red->SetVisibility(true);
0163   green->SetVisibility(true);
0164   blue->SetVisibility(true);
0165 
0166   white->SetForceWireframe(true);
0167   red->SetForceSolid(true);
0168   green->SetForceSolid(true);
0169   blue->SetForceSolid(true);
0170 
0171   world_log->SetVisAttributes(white);
0172 
0173   for (G4int k = 0; k < nz; ++k)
0174     for (G4int j = 0; j < ny; ++j)
0175       for (G4int i = 0; i < nx; ++i) {
0176         // displacement of section
0177         G4double dx = 0.5 * sx + static_cast<G4double>(i) * sx - 0.5 * fWorldDim.x();
0178         G4double dy = 0.5 * sy + static_cast<G4double>(j) * sy - 0.5 * fWorldDim.y();
0179         G4double dz = 0.5 * sz + static_cast<G4double>(k) * sz - 0.5 * fWorldDim.z();
0180         G4ThreeVector td = G4ThreeVector(dx, dy, -dz);
0181         // make unique name
0182         std::stringstream ss_name;
0183         ss_name << "Target_" << i << "_" << j << "_" << k;
0184 
0185         G4Box* target_solid = new G4Box(ss_name.str(), 0.5 * sx, 0.5 * sy, 0.5 * sz);
0186 
0187         G4Material* target_material = 0;
0188         G4bool is_casing = true;
0189 
0190         if (j == 0 || j + 1 == ny || i == 0 || i + 1 == nx || (nz > 1 && (k == 0 || k + 1 == nz)))
0191           target_material = materials.find("Casing")->second;
0192         else {
0193           target_material = materials.find("Target")->second;
0194           is_casing = false;
0195         }
0196 
0197         G4LogicalVolume* target_log =
0198           new G4LogicalVolume(target_solid, target_material, ss_name.str());
0199 
0200         target_log->SetUserLimits(steplimit);
0201 
0202         new G4PVPlacement(0, td, ss_name.str(), target_log, fWorldPhys, true,
0203                           k * nx * ny + j * nx + i, check_overlap);
0204 
0205         fScoringVolumes.insert(target_log);
0206 
0207         if (is_casing)
0208           target_log->SetVisAttributes(blue);
0209         else {
0210           // making a checkerboard for kicks...
0211           G4bool even_z = (k % 2 == 0) ? true : false;
0212           G4bool even_y = (j % 2 == 0) ? true : false;
0213           G4bool even_x = (i % 2 == 0) ? true : false;
0214 
0215           G4VisAttributes* theColor = nullptr;
0216 
0217           if ((even_z)) {
0218             if ((even_y && even_x) || (!even_y && !even_x))
0219               theColor = red;
0220             else
0221               theColor = green;
0222           }
0223           else  // ! even_z
0224           {
0225             if ((!even_y && even_x) || (even_y && !even_x))
0226               theColor = red;
0227             else
0228               theColor = green;
0229           }
0230 
0231           target_log->SetVisAttributes(theColor);
0232         }
0233       }
0234 
0235   return fWorldPhys;
0236 }
0237 
0238 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0239 
0240 void TSDetectorConstruction::ConstructSDandField()
0241 {
0242   //------------------------------------------------//
0243   //            MultiFunctionalDetector             //
0244   //------------------------------------------------//
0245   // Define MultiFunctionalDetector with name.
0246   G4MultiFunctionalDetector* MFDet = new G4MultiFunctionalDetector(fMfdName);
0247   G4SDManager::GetSDMpointer()->AddNewDetector(MFDet);
0248   G4VPrimitiveScorer* edep = new G4PSEnergyDeposit("EnergyDeposit");
0249   MFDet->RegisterPrimitive(edep);
0250   G4VPrimitiveScorer* nstep = new G4PSNofStep("NumberOfSteps");
0251   MFDet->RegisterPrimitive(nstep);
0252 
0253   // add scoring volumes
0254   for (auto ite : fScoringVolumes) {
0255     SetSensitiveDetector(ite, MFDet);
0256   }
0257 }
0258 
0259 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......