// // ******************************************************************** // * License and Disclaimer * // * * // * The Geant4 software is copyright of the Copyright Holders of * // * the Geant4 Collaboration. It is provided under the terms and * // * conditions of the Geant4 Software License, included in the file * // * LICENSE and available at http://cern.ch/geant4/license . These * // * include a list of copyright holders. * // * * // * Neither the authors of this software system, nor their employing * // * institutes,nor the agencies providing financial support for this * // * work make any representation or warranty, express or implied, * // * regarding this software system or assume any liability for its * // * use. Please see the license in the file LICENSE and URL above * // * for the full disclaimer and the limitation of liability. * // * * // * This code implementation is the result of the scientific and * // * technical work of the GEANT4 collaboration. * // * By using, copying, modifying or distributing the software (or * // * any work based on the software) you agree to acknowledge its * // * use in resulting scientific publications, and indicate your * // * acceptance of all terms of the Geant4 Software license. * // ******************************************************************** // // /// \file B1/src/DetectorConstruction.cc /// \brief Implementation of the B1::DetectorConstruction class #include "DetectorConstruction.hh" #include "G4Box.hh" #include "G4Orb.hh" #include "G4LogicalVolume.hh" #include "G4NistManager.hh" #include "G4PVPlacement.hh" #include "G4SystemOfUnits.hh" #include "Randomize.hh" namespace B1 { //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... G4VPhysicalVolume* DetectorConstruction::Construct() { // Get nist material manager G4NistManager* nist = G4NistManager::Instance(); // Envelope parameters G4double env_sizeXY = 3*cm, env_sizeZ = 30*cm; G4Material* env_mat = nist->FindOrBuildMaterial("G4_AIR"); // Option to switch on/off the overlap check G4bool checkOverlaps = false; // World G4double world_sizeXY = 1.2 * env_sizeXY; G4double world_sizeZ = 1.2 * env_sizeZ; G4Material* world_mat = nist->FindOrBuildMaterial("G4_AIR"); auto solidWorld = new G4Box("World", 0.5*world_sizeXY, 0.5*world_sizeXY, 0.5*world_sizeZ); auto logicWorld = new G4LogicalVolume(solidWorld, world_mat, "World"); auto physWorld = new G4PVPlacement(nullptr, G4ThreeVector(), logicWorld, "World", nullptr, false, 0, checkOverlaps); // Envelope auto solidEnv = new G4Box("Envelope", 0.5*env_sizeXY, 0.5*env_sizeXY, 0.5*env_sizeZ); auto logicEnv = new G4LogicalVolume(solidEnv, env_mat, "Envelope"); new G4PVPlacement(nullptr, G4ThreeVector(), logicEnv, "Envelope", logicWorld, false, 0, checkOverlaps); // Construct detector constexpr G4int NP = 30000; // required number of spheres constexpr G4int NSLICE = 200; // number of slices constexpr G4double r = 0.5*mm; // radius of a sphere constexpr G4double DMIN = 2*r; // min distance between two spheres // Construct logical volume for Box G4double dx = 1*cm, dy = 1*cm, dz = 10*cm; // box dimentions G4Material* box_material = nist->FindOrBuildMaterial("G4_AIR"); auto box = new G4Box("Box", dx, dy, dz); auto box_logical = new G4LogicalVolume(box, box_material, "Box"); new G4PVPlacement(0, G4ThreeVector(), box_logical, "Box", logicEnv, false, 0, checkOverlaps); // Generate positions inside Box G4ThreeVector bmin, bmax; box->BoundingLimits(bmin, bmax); // get bounding box std::vector positions[NSLICE]; G4int nspheres = 0; G4double delz = 2*dz/NSLICE; // width of a slice while (nspheres < NP) { G4double x = bmin.x() + (bmax.x() - bmin.x())*G4UniformRand(); G4double y = bmin.y() + (bmax.y() - bmin.y())*G4UniformRand(); G4double z = bmin.z() + (bmax.z() - bmin.z())*G4UniformRand(); G4ThreeVector p(x, y, z); // check position G4bool accept = true; if (box->Inside(p) != kInside) continue; if (box->DistanceToOut(p) < 0.5*DMIN) continue; G4int icurr = (z - bmin.z())/delz; // current slice G4int iprev = (icurr == 0) ? icurr : icurr - 1; // previous slice G4int inext = (icurr == NSLICE - 1) ? icurr : icurr + 1; // next slice for (auto islice = iprev; islice <= inext; ++islice) { std::vector& pos = positions[islice]; G4int size = pos.size(); for (auto k = 0; k < size; ++k) { if ((pos[k] - p).mag() < DMIN) { accept = false; break; } } if (accept == false) break; } if (accept == true) { nspheres++; if (nspheres%1000 == 0) G4cout << "nspheres = " << nspheres << G4endl; positions[icurr].push_back(p); // add position to the list } } // create a logical volume for Spheres G4Material* sph_material = nist->FindOrBuildMaterial("G4_WATER"); auto sphere = new G4Orb("Sphere", r); auto sph_logical = new G4LogicalVolume(sphere, sph_material, "Sphere"); // create physical volumes for spheres for (auto islice = 0; islice < NSLICE; ++islice) { std::vector& pos = positions[islice]; G4int size = pos.size(); for (auto k = 0; k < size; ++k) { new G4PVPlacement(0, pos[k], sph_logical, "Sphere", box_logical, false, 0, checkOverlaps); } } // create physical volume for Box fScoringVolume = box_logical; // // always return the physical World // return physWorld; } //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo...... } // namespace B1