Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-16 08:30:46

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 RE02DetectorConstruction.cc
0027 /// \brief Implementation of the RE02DetectorConstruction class
0028 
0029 #include "RE02DetectorConstruction.hh"
0030 
0031 #include "RE02NestedPhantomParameterisation.hh"
0032 
0033 #include "G4Box.hh"
0034 #include "G4Colour.hh"
0035 #include "G4LogicalVolume.hh"
0036 #include "G4Material.hh"
0037 #include "G4NistManager.hh"
0038 #include "G4PSCellFlux3D.hh"
0039 #include "G4PSEnergyDeposit3D.hh"
0040 #include "G4PSFlatSurfaceCurrent3D.hh"
0041 #include "G4PSFlatSurfaceFlux3D.hh"
0042 #include "G4PSNofStep3D.hh"
0043 #include "G4PSPassageCellFlux3D.hh"
0044 #include "G4PVParameterised.hh"
0045 #include "G4PVPlacement.hh"
0046 #include "G4SDChargedFilter.hh"
0047 #include "G4SDManager.hh"
0048 #include "G4SDParticleFilter.hh"
0049 #include "G4SDParticleWithEnergyFilter.hh"
0050 #include "G4SystemOfUnits.hh"
0051 #include "G4VisAttributes.hh"
0052 #include "G4ios.hh"
0053 
0054 //=======================================================================
0055 //  RE02DetectorConstruction
0056 //
0057 //  (Description)
0058 //
0059 //     Detector construction for example RE02.
0060 //
0061 //   [Geometry]
0062 //     The world volume is defined as 200 cm x 200 cm x 200 cm box with Air.
0063 //   Water phantom is defined as  200 mm x 200 mm x 400 mm box with Water.
0064 //   The water phantom is divided into 100 segments in x,y plane using
0065 //   replication,
0066 //   and then divided into 200 segments perpendicular to z axis using nested
0067 //   parameterised volume.
0068 //    These values are defined at constructor,
0069 //    e.g. the size of water phantom (fPhantomSize), and number of segmentation
0070 //   of water phantom (fNx, fNy, fNz).
0071 //
0072 //   By default, lead plates are inserted into the position of even order
0073 //   segments.
0074 //   NIST database is used for materials.
0075 //
0076 //
0077 //   [Scorer]
0078 //    Assignment of G4MultiFunctionalDetector and G4PrimitiveScorer
0079 //   is demonstrated in this example.
0080 //       -------------------------------------------------
0081 //       The collection names of defined Primitives are
0082 //        0       PhantomSD/totalEDep
0083 //        1       PhantomSD/protonEDep
0084 //        2       PhantomSD/protonNStep
0085 //        3       PhantomSD/chargedPassCellFlux
0086 //        4       PhantomSD/chargedCellFlux
0087 //        5       PhantomSD/chargedSurfFlux
0088 //        6       PhantomSD/gammaSurfCurr000
0089 //        7       PhantomSD/gammaSurfCurr001
0090 //        9       PhantomSD/gammaSurdCurr002
0091 //       10       PhantomSD/gammaSurdCurr003
0092 //      -------------------------------------------------
0093 //      Please see README for detail description.
0094 //
0095 //=======================================================================
0096 
0097 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0098 RE02DetectorConstruction::RE02DetectorConstruction() : G4VUserDetectorConstruction()
0099 {
0100   // Default size of water phantom,and segmentation.
0101   fPhantomSize.setX(200. * mm);
0102   fPhantomSize.setY(200. * mm);
0103   fPhantomSize.setZ(400. * mm);
0104   fNx = fNy = fNz = 100;
0105   fInsertLead = TRUE;
0106 }
0107 
0108 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0109 RE02DetectorConstruction::~RE02DetectorConstruction()
0110 {
0111   ;
0112 }
0113 
0114 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
0115 G4VPhysicalVolume* RE02DetectorConstruction::Construct()
0116 {
0117   //=====================
0118   // Material Definitions
0119   //=====================
0120   //
0121   //-------- NIST Materials ----------------------------------------------------
0122   //  Material Information imported from NIST database.
0123   //
0124   G4NistManager* NISTman = G4NistManager::Instance();
0125   G4Material* air = NISTman->FindOrBuildMaterial("G4_AIR");
0126   G4Material* water = NISTman->FindOrBuildMaterial("G4_WATER");
0127   G4Material* lead = NISTman->FindOrBuildMaterial("G4_Pb");
0128 
0129   //
0130   // Print all the materials defined.
0131   G4cout << G4endl << "The materials defined are : " << G4endl << G4endl;
0132   G4cout << *(G4Material::GetMaterialTable()) << G4endl;
0133 
0134   //============================================================================
0135   //      Definitions of Solids, Logical Volumes, Physical Volumes
0136   //============================================================================
0137 
0138   //-------------
0139   // World Volume
0140   //-------------
0141 
0142   G4ThreeVector worldSize = G4ThreeVector(200 * cm, 200 * cm, 200 * cm);
0143 
0144   G4Box* solidWorld =
0145     new G4Box("world", worldSize.x() / 2., worldSize.y() / 2., worldSize.z() / 2.);
0146   G4LogicalVolume* logicWorld = new G4LogicalVolume(solidWorld, air, "World", 0, 0, 0);
0147 
0148   //
0149   //  Must place the World Physical volume unrotated at (0,0,0).
0150   G4VPhysicalVolume* physiWorld = new G4PVPlacement(0,  // no rotation
0151                                                     G4ThreeVector(),  // at (0,0,0)
0152                                                     logicWorld,  // its logical volume
0153                                                     "World",  // its name
0154                                                     0,  // its mother  volume
0155                                                     false,  // no boolean operations
0156                                                     0);  // copy number
0157 
0158   //---------------
0159   // Water Phantom
0160   //---------------
0161 
0162   //................................
0163   // Mother Volume of Water Phantom
0164   //................................
0165 
0166   //--  Default size of water phantom is defined at constructor.
0167   G4ThreeVector phantomSize = fPhantomSize;
0168 
0169   G4Box* solidPhantom =
0170     new G4Box("phantom", phantomSize.x() / 2., phantomSize.y() / 2., phantomSize.z() / 2.);
0171   G4LogicalVolume* logicPhantom = new G4LogicalVolume(solidPhantom, water, "Phantom", 0, 0, 0);
0172 
0173   G4RotationMatrix* rot = new G4RotationMatrix();
0174   // rot->rotateY(30.*deg);
0175   G4ThreeVector positionPhantom;
0176   // G4VPhysicalVolume * physiPhantom =
0177   new G4PVPlacement(rot,  // no rotation
0178                     positionPhantom,  // at (x,y,z)
0179                     logicPhantom,  // its logical volume
0180                     "Phantom",  // its name
0181                     logicWorld,  // its mother  volume
0182                     false,  // no boolean operations
0183                     0);  // copy number
0184 
0185   //..............................................
0186   // Phantom segmentation using Parameterisation
0187   //..............................................
0188   //
0189   G4cout << "<-- RE02DetectorConstruction::Construct-------" << G4endl;
0190   G4cout << "  Water Phantom Size " << fPhantomSize / mm << G4endl;
0191   G4cout << "  Segmentation  (" << fNx << "," << fNy << "," << fNz << ")" << G4endl;
0192   G4cout << "  Lead plate at even copy # (0-False,1-True): " << IsLeadSegment() << G4endl;
0193   G4cout << "<---------------------------------------------" << G4endl;
0194   // Number of segmentation.
0195   // - Default number of segmentation is defined at constructor.
0196   G4int nxCells = fNx;
0197   G4int nyCells = fNy;
0198   G4int nzCells = fNz;
0199 
0200   G4ThreeVector sensSize;
0201   sensSize.setX(phantomSize.x() / (G4double)nxCells);
0202   sensSize.setY(phantomSize.y() / (G4double)nyCells);
0203   sensSize.setZ(phantomSize.z() / (G4double)nzCells);
0204   // i.e Voxel size will be 2.0 x 2.0 x 2.0 mm3 cube by default.
0205   //
0206 
0207   // Replication of Water Phantom Volume.
0208   // Y Slice
0209   G4String yRepName("RepY");
0210   G4VSolid* solYRep =
0211     new G4Box(yRepName, phantomSize.x() / 2., sensSize.y() / 2., phantomSize.z() / 2.);
0212   G4LogicalVolume* logYRep = new G4LogicalVolume(solYRep, water, yRepName);
0213   // G4PVReplica* yReplica =
0214   new G4PVReplica(yRepName, logYRep, logicPhantom, kYAxis, fNy, sensSize.y());
0215   // X Slice
0216   G4String xRepName("RepX");
0217   G4VSolid* solXRep =
0218     new G4Box(xRepName, sensSize.x() / 2., sensSize.y() / 2., phantomSize.z() / 2.);
0219   G4LogicalVolume* logXRep = new G4LogicalVolume(solXRep, water, xRepName);
0220   // G4PVReplica* xReplica =
0221   new G4PVReplica(xRepName, logXRep, logYRep, kXAxis, fNx, sensSize.x());
0222 
0223   //
0224   //..................................
0225   // Voxel solid and logical volumes
0226   //..................................
0227   // Z Slice
0228   G4String zVoxName("phantomSens");
0229   G4VSolid* solVoxel = new G4Box(zVoxName, sensSize.x() / 2., sensSize.y() / 2., sensSize.z() / 2.);
0230   fLVPhantomSens = new G4LogicalVolume(solVoxel, water, zVoxName);
0231   //
0232   //
0233   std::vector<G4Material*> phantomMat(2, water);
0234   if (IsLeadSegment()) phantomMat[1] = lead;
0235   //
0236   // Parameterisation for transformation of voxels.
0237   //  (voxel size is fixed in this example.
0238   //  e.g. nested parameterisation handles material and transfomation of voxels.)
0239   RE02NestedPhantomParameterisation* paramPhantom =
0240     new RE02NestedPhantomParameterisation(sensSize / 2., nzCells, phantomMat);
0241   // G4VPhysicalVolume * physiPhantomSens =
0242   new G4PVParameterised("PhantomSens",  // their name
0243                         fLVPhantomSens,  // their logical volume
0244                         logXRep,  // Mother logical volume
0245                         kUndefined,  // Are placed along this axis
0246                         nzCells,  // Number of cells
0247                         paramPhantom);  // Parameterisation.
0248   //   Optimization flag is avaiable for,
0249   //    kUndefined, kXAxis, kYAxis, kZAxis.
0250   //
0251 
0252   //===============================
0253   //   Visualization attributes
0254   //===============================
0255 
0256   G4VisAttributes* boxVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 1.0));
0257   logicWorld->SetVisAttributes(boxVisAtt);
0258   // logicWorld->SetVisAttributes(G4VisAttributes::GetInvisible());
0259 
0260   // Mother volume of WaterPhantom
0261   G4VisAttributes* phantomVisAtt = new G4VisAttributes(G4Colour(1.0, 1.0, 0.0));
0262   logicPhantom->SetVisAttributes(phantomVisAtt);
0263 
0264   // Replica
0265   G4VisAttributes* yRepVisAtt = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0));
0266   logYRep->SetVisAttributes(yRepVisAtt);
0267   G4VisAttributes* xRepVisAtt = new G4VisAttributes(G4Colour(0.0, 1.0, 0.0));
0268   logXRep->SetVisAttributes(xRepVisAtt);
0269 
0270   // Skip the visualization for those voxels.
0271   fLVPhantomSens->SetVisAttributes(G4VisAttributes::GetInvisible());
0272 
0273   return physiWorld;
0274 }
0275 
0276 void RE02DetectorConstruction::ConstructSDandField()
0277 {
0278   //================================================
0279   // Sensitive detectors : MultiFunctionalDetector
0280   //================================================
0281   //
0282   //  Sensitive Detector Manager.
0283   G4SDManager* pSDman = G4SDManager::GetSDMpointer();
0284   //
0285   // Sensitive Detector Name
0286   G4String phantomSDname = "PhantomSD";
0287 
0288   //------------------------
0289   // MultiFunctionalDetector
0290   //------------------------
0291   //
0292   // Define MultiFunctionalDetector with name.
0293   G4MultiFunctionalDetector* mFDet = new G4MultiFunctionalDetector(phantomSDname);
0294   pSDman->AddNewDetector(mFDet);  // Register SD to SDManager.
0295   fLVPhantomSens->SetSensitiveDetector(mFDet);  // Assign SD to the logical volume.
0296 
0297   //---------------------------------------
0298   // SDFilter : Sensitive Detector Filters
0299   //---------------------------------------
0300   //
0301   // Particle Filter for Primitive Scorer with filter name(fltName)
0302   // and particle name(particleName),
0303   // or particle names are given by add("particle name"); method.
0304   //
0305   G4String fltName, particleName;
0306   //
0307   //-- proton filter
0308   G4SDParticleFilter* protonFilter =
0309     new G4SDParticleFilter(fltName = "protonFilter", particleName = "proton");
0310   //
0311   //-- electron filter
0312   G4SDParticleFilter* electronFilter = new G4SDParticleFilter(fltName = "electronFilter");
0313   electronFilter->add(particleName = "e+");  // accept electrons.
0314   electronFilter->add(particleName = "e-");  // accept positorons.
0315   //
0316   //-- charged particle filter
0317   G4SDChargedFilter* chargedFilter = new G4SDChargedFilter(fltName = "chargedFilter");
0318 
0319   //------------------------
0320   // PS : Primitive Scorers
0321   //------------------------
0322   // Primitive Scorers are used with SDFilters according to your purpose.
0323   //
0324   //
0325   //-- Primitive Scorer for Energy Deposit.
0326   //      Total, by protons, by electrons.
0327   G4String psName;
0328   G4PSEnergyDeposit3D* scorer0 = new G4PSEnergyDeposit3D(psName = "totalEDep", fNx, fNy, fNz);
0329   G4PSEnergyDeposit3D* scorer1 = new G4PSEnergyDeposit3D(psName = "protonEDep", fNx, fNy, fNz);
0330   scorer1->SetFilter(protonFilter);
0331 
0332   //
0333   //-- Number of Steps for protons
0334   G4PSNofStep3D* scorer2 = new G4PSNofStep3D(psName = "protonNStep", fNx, fNy, fNz);
0335   scorer2->SetFilter(protonFilter);
0336 
0337   //
0338   //-- CellFlux for charged particles
0339   G4PSPassageCellFlux3D* scorer3 =
0340     new G4PSPassageCellFlux3D(psName = "chargedPassCellFlux", fNx, fNy, fNz);
0341   G4PSCellFlux3D* scorer4 = new G4PSCellFlux3D(psName = "chargedCellFlux", fNx, fNy, fNz);
0342   G4PSFlatSurfaceFlux3D* scorer5 =
0343     new G4PSFlatSurfaceFlux3D(psName = "chargedSurfFlux", fFlux_InOut, fNx, fNy, fNz);
0344   scorer3->SetFilter(chargedFilter);
0345   scorer4->SetFilter(chargedFilter);
0346   scorer5->SetFilter(chargedFilter);
0347 
0348   //
0349   //------------------------------------------------------------
0350   //  Register primitive scorers to MultiFunctionalDetector
0351   //------------------------------------------------------------
0352   mFDet->RegisterPrimitive(scorer0);
0353   mFDet->RegisterPrimitive(scorer1);
0354   mFDet->RegisterPrimitive(scorer2);
0355   mFDet->RegisterPrimitive(scorer3);
0356   mFDet->RegisterPrimitive(scorer4);
0357   mFDet->RegisterPrimitive(scorer5);
0358 
0359   //========================
0360   // More additional Primitive Scoreres
0361   //========================
0362   //
0363   //--- Surface Current for gamma with energy bin.
0364   // This example creates four primitive scorers.
0365   //  4 bins with energy   ---   Primitive Scorer Name
0366   //    1.     to  10 KeV,        gammaSurfCurr000
0367   //   10 keV  to 100 KeV,        gammaSurfCurr001
0368   //  100 keV  to   1 MeV,        gammaSurfCurr002
0369   //    1 MeV  to  10 MeV.        gammaSurfCurr003
0370   //
0371   for (G4int i = 0; i < 4; i++) {
0372     std::ostringstream name;
0373     name << "gammaSurfCurr" << std::setfill('0') << std::setw(3) << i;
0374     G4String psgName = name.str();
0375     G4double kmin = std::pow(10., (G4double)i) * keV;
0376     G4double kmax = std::pow(10., (G4double)(i + 1)) * keV;
0377     //-- Particle with kinetic energy filter.
0378     G4SDParticleWithEnergyFilter* pkinEFilter =
0379       new G4SDParticleWithEnergyFilter(fltName = "gammaE filter", kmin, kmax);
0380     pkinEFilter->add("gamma");  // Accept only gamma.
0381     pkinEFilter->show();  // Show accepting condition to stdout.
0382     //-- Surface Current Scorer which scores  number of tracks in unit area.
0383     G4PSFlatSurfaceCurrent3D* scorer =
0384       new G4PSFlatSurfaceCurrent3D(psgName, fCurrent_InOut, fNx, fNy, fNz);
0385     scorer->SetFilter(pkinEFilter);  // Assign filter.
0386     mFDet->RegisterPrimitive(scorer);  // Register it to MultiFunctionalDetector.
0387   }
0388 }