Geant4 Cross Reference

Cross-Referencing   Geant4
Geant4/examples/advanced/stim_pixe_tomography/src/DetectorConstruction.cc

Version: [ ReleaseNotes ] [ 1.0 ] [ 1.1 ] [ 2.0 ] [ 3.0 ] [ 3.1 ] [ 3.2 ] [ 4.0 ] [ 4.0.p1 ] [ 4.0.p2 ] [ 4.1 ] [ 4.1.p1 ] [ 5.0 ] [ 5.0.p1 ] [ 5.1 ] [ 5.1.p1 ] [ 5.2 ] [ 5.2.p1 ] [ 5.2.p2 ] [ 6.0 ] [ 6.0.p1 ] [ 6.1 ] [ 6.2 ] [ 6.2.p1 ] [ 6.2.p2 ] [ 7.0 ] [ 7.0.p1 ] [ 7.1 ] [ 7.1.p1 ] [ 8.0 ] [ 8.0.p1 ] [ 8.1 ] [ 8.1.p1 ] [ 8.1.p2 ] [ 8.2 ] [ 8.2.p1 ] [ 8.3 ] [ 8.3.p1 ] [ 8.3.p2 ] [ 9.0 ] [ 9.0.p1 ] [ 9.0.p2 ] [ 9.1 ] [ 9.1.p1 ] [ 9.1.p2 ] [ 9.1.p3 ] [ 9.2 ] [ 9.2.p1 ] [ 9.2.p2 ] [ 9.2.p3 ] [ 9.2.p4 ] [ 9.3 ] [ 9.3.p1 ] [ 9.3.p2 ] [ 9.4 ] [ 9.4.p1 ] [ 9.4.p2 ] [ 9.4.p3 ] [ 9.4.p4 ] [ 9.5 ] [ 9.5.p1 ] [ 9.5.p2 ] [ 9.6 ] [ 9.6.p1 ] [ 9.6.p2 ] [ 9.6.p3 ] [ 9.6.p4 ] [ 10.0 ] [ 10.0.p1 ] [ 10.0.p2 ] [ 10.0.p3 ] [ 10.0.p4 ] [ 10.1 ] [ 10.1.p1 ] [ 10.1.p2 ] [ 10.1.p3 ] [ 10.2 ] [ 10.2.p1 ] [ 10.2.p2 ] [ 10.2.p3 ] [ 10.3 ] [ 10.3.p1 ] [ 10.3.p2 ] [ 10.3.p3 ] [ 10.4 ] [ 10.4.p1 ] [ 10.4.p2 ] [ 10.4.p3 ] [ 10.5 ] [ 10.5.p1 ] [ 10.6 ] [ 10.6.p1 ] [ 10.6.p2 ] [ 10.6.p3 ] [ 10.7 ] [ 10.7.p1 ] [ 10.7.p2 ] [ 10.7.p3 ] [ 10.7.p4 ] [ 11.0 ] [ 11.0.p1 ] [ 11.0.p2 ] [ 11.0.p3, ] [ 11.0.p4 ] [ 11.1 ] [ 11.1.1 ] [ 11.1.2 ] [ 11.1.3 ] [ 11.2 ] [ 11.2.1 ] [ 11.2.2 ] [ 11.3.0 ]

  1 //
  2 // ********************************************************************
  3 // * License and Disclaimer                                           *
  4 // *                                                                  *
  5 // * The  Geant4 software  is  copyright of the Copyright Holders  of *
  6 // * the Geant4 Collaboration.  It is provided  under  the terms  and *
  7 // * conditions of the Geant4 Software License,  included in the file *
  8 // * LICENSE and available at  http://cern.ch/geant4/license .  These *
  9 // * include a list of copyright holders.                             *
 10 // *                                                                  *
 11 // * Neither the authors of this software system, nor their employing *
 12 // * institutes,nor the agencies providing financial support for this *
 13 // * work  make  any representation or  warranty, express or implied, *
 14 // * regarding  this  software system or assume any liability for its *
 15 // * use.  Please see the license in the file  LICENSE  and URL above *
 16 // * for the full disclaimer and the limitation of liability.         *
 17 // *                                                                  *
 18 // * This  code  implementation is the result of  the  scientific and *
 19 // * technical work of the GEANT4 collaboration.                      *
 20 // * By using,  copying,  modifying or  distributing the software (or *
 21 // * any work based  on the software)  you  agree  to acknowledge its *
 22 // * use  in  resulting  scientific  publications,  and indicate your *
 23 // * acceptance of all terms of the Geant4 Software license.          *
 24 // ********************************************************************
 25 //
 26 //
 27 //
 28 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 29 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 30 
 31 #include "DetectorConstruction.hh"
 32 
 33 #include "G4AutoDelete.hh"
 34 #include "G4Box.hh"
 35 #include "G4Colour.hh"
 36 #include "G4Ellipsoid.hh"
 37 #include "G4GeometryManager.hh"
 38 #include "G4GlobalMagFieldMessenger.hh"
 39 #include "G4LogicalVolume.hh"
 40 #include "G4Material.hh"
 41 #include "G4NistManager.hh"
 42 #include "G4PVPlacement.hh"
 43 #include "G4PhysicalConstants.hh"
 44 #include "G4PhysicalVolumeStore.hh"
 45 #include "G4RunManager.hh"
 46 #include "G4Sphere.hh"
 47 #include "G4SystemOfUnits.hh"
 48 #include "G4UniformMagField.hh"
 49 #include "G4UnitsTable.hh"
 50 #include "G4UserLimits.hh"
 51 #include "G4VisAttributes.hh"
 52 
 53 #include "DetectorMessenger.hh"
 54 
 55 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
 56 
 57 DetectorConstruction::DetectorConstruction()
 58   : G4VUserDetectorConstruction(),
 59     fAbsorberMaterial(nullptr),
 60     fWorldMaterial(nullptr),
 61     fSolidWorld(nullptr),
 62     fLogicWorld(nullptr),
 63     fPhysiWorld(nullptr),
 64     fSolidAbsorber(nullptr),
 65     fLogicAbsorber(nullptr),
 66     fPhysiAbsorber(nullptr),
 67     material1(nullptr),
 68     material2(nullptr),
 69     material3(nullptr),
 70     material4(nullptr),
 71     material5(nullptr),
 72     material6(nullptr),
 73     material_GDP(nullptr),
 74     ellipse1(nullptr),
 75     logicEllipse1(nullptr),
 76     physiEllipse1(nullptr),
 77     ellipse2(nullptr),
 78     logicEllipse2(nullptr),
 79     physiEllipse2(nullptr),
 80     ellipse3(nullptr),
 81     logicEllipse3(nullptr),
 82     physiEllipse3(nullptr),
 83     ellipse4(nullptr),
 84     logicEllipse4(nullptr),
 85     physiEllipse4(nullptr),
 86     ellipse5(nullptr),
 87     logicEllipse5(nullptr),
 88     physiEllipse5(nullptr),
 89     ellipse6(nullptr),
 90     logicEllipse6(nullptr),
 91     physiEllipse6(nullptr),
 92     solid_GDP(nullptr),
 93     logic_GDP(nullptr),
 94     physi_GDP(nullptr),
 95     fDetectorMessenger(nullptr)
 96 {
 97   phantom_type = 1;
 98 
 99   DefineMaterials();
100 
101   if (phantom_type == 1) {
102     // default parameter values of the box
103     fAbsorberThickness = 40. * um;
104     fAbsorberSizeYZ = 40. * um;
105 
106     //    SetAbsorberMaterial("G4_Cu");
107     SetAbsorberMaterial("Body_10times");
108     //    SetAbsorberMaterial("Body_real");
109   }
110   fXposAbs = 0. * cm;
111   ComputeGeomParameters();
112 
113   // materials
114   SetWorldMaterial("G4_Galactic");
115 
116   // create commands for interactive definition of the box
117   fDetectorMessenger = new DetectorMessenger(this);
118 }
119 
120 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
121 
122 DetectorConstruction::~DetectorConstruction()
123 {
124   delete fDetectorMessenger;
125 }
126 
127 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
128 
129 void DetectorConstruction::DefineMaterials()
130 {
131   //
132   // define Elements
133   //
134   auto H = new G4Element("Hydrogen", "H", 1, 1.01 * g / mole);
135   auto C = new G4Element("Carbon", "C", 6, 12.01 * g / mole);
136   auto N = new G4Element("Nitrogen", "N", 7, 14.01 * g / mole);
137   auto O = new G4Element("Oxygen", "O", 8, 16.00 * g / mole);
138   auto P = new G4Element("Phosphorus", "P", 15, 30.97 * g / mole);
139   auto S = new G4Element("Sulphur", "S", 16, 32.07 * g / mole);
140   auto Cl = new G4Element("Chlorine", "Cl", 17, 35.45 * g / mole);
141   auto K = new G4Element("Potassium", "K", 19, 39.10 * g / mole);
142   auto Ca = new G4Element("Calcium", "Ca", 20, 40.08 * g / mole);
143   auto Ti = new G4Element("Titanium", "Ti", 22, 47.87 * g / mole);
144   auto Ge = new G4Element("Germanium", "Ge", 32., 72.59 * g / mole);
145 
146   //
147   // define biological materials
148   //
149   auto BioMaterial = new G4Material("C10H17O3N2", 1.218 * g / cm3, 4);
150   BioMaterial->AddElement(C, 10);
151   BioMaterial->AddElement(H, 17);
152   BioMaterial->AddElement(O, 3);
153   BioMaterial->AddElement(N, 2);
154 
155   // FIRST ELLIPSOID  : external surface of the worm ("skin")
156   // Original (real) composition in dry mass (the worm is dehydrated by
157   // lyophilization) Each element content is defined by its mass fraction (must
158   // be normalised to 1)
159   auto Skin_real = new G4Material("Skin_real", 0.49729 * g / cm3, 5);
160   Skin_real->AddElement(P, 0.47 * perCent);
161   Skin_real->AddElement(S, 0.21 * perCent);
162   Skin_real->AddElement(Cl, 0.05 * perCent);
163   Skin_real->AddElement(K, 0.48 * perCent);
164   Skin_real->AddMaterial(BioMaterial, 98.79 * perCent);
165 
166   // Skin1: mass fractions of mineral elements 1O times more than original
167   // (real) mass fractions
168   auto Skin_10times = new G4Material("Skin_10times", 0.49729 * g / cm3, 5);
169   Skin_10times->AddElement(P, 4.71 * perCent);
170   Skin_10times->AddElement(S, 2.10 * perCent);
171   Skin_10times->AddElement(Cl, 0.46 * perCent);
172   Skin_10times->AddElement(K, 4.77 * perCent);
173   Skin_10times->AddMaterial(BioMaterial, 87.96 * perCent);
174 
175   // SECOND ELLIPSOID : "body" of the worm, limited by the internal surface of
176   // the "skin" Original (real) composition in dry mass (the worm is dehydrated
177   // by lyophilization) Each element content is defined by its mass fraction
178   // (must be normalised to 1)
179   auto Body_real = new G4Material("Body_real", 0.40853 * g / cm3, 2);
180   Body_real->AddElement(P, 0.72 * perCent);
181   Body_real->AddMaterial(BioMaterial, 99.28 * perCent);
182 
183   // Body_10times: mass fractions of mineral elements 1O times more than
184   // original (real) mass fractions
185   auto Body_10times = new G4Material("Body_10times", 0.40853 * g / cm3, 2);
186   Body_10times->AddElement(P, 7.23 * perCent);
187   Body_10times->AddMaterial(BioMaterial, 92.77 * perCent);
188 
189   // THIRD ELLIPSOID : Nucleus of cell 1 (contained inside ellipsoid 2)
190   // Original (real) composition in dry mass (the worm is dehydrated by
191   // lyophilization) Each element content is defined by its mass fraction (must
192   // be normalised to 1)
193   auto Cell1_real = new G4Material("Cell1_real", 0.66262 * g / cm3, 3);
194   Cell1_real->AddElement(P, 0.57 * perCent);
195   Cell1_real->AddElement(Ca, 1.55 * perCent);
196   Cell1_real->AddMaterial(BioMaterial, 97.88 * perCent);
197 
198   // Cell1_10times: mass fractions of mineral elements 1O times more than
199   // original (real) mass fractions
200   auto Cell1_10times = new G4Material("Cell1_10times", 0.66262 * g / cm3, 3);
201   Cell1_10times->AddElement(P, 5.66 * perCent);
202   Cell1_10times->AddElement(Ca, 15.49 * perCent);
203   Cell1_10times->AddMaterial(BioMaterial, 78.85 * perCent);
204 
205   // FOURTH ELLIPSOID : Nucleus of cell 2 (contained inside ellipsoid 2)
206   // Original (real) composition in dry mass (the worm is dehydrated by
207   // lyophilization) Each element content is defined by its mass fraction (must
208   // be normalised to 1)
209   auto Cell2_real = new G4Material("Cell2_real", 0.60227 * g / cm3, 3);
210   Cell2_real->AddElement(P, 0.61 * perCent);
211   Cell2_real->AddElement(Ca, 1.44 * perCent);
212   Cell2_real->AddMaterial(BioMaterial, 97.95 * perCent);
213 
214   // Cell2_10times: mass fractions of mineral elements 1O times more than
215   // original (real) mass fractions
216   auto Cell2_10times = new G4Material("Cell2_10times", 0.60227 * g / cm3, 3);
217   Cell2_10times->AddElement(P, 6.10 * perCent);
218   Cell2_10times->AddElement(Ca, 14.45 * perCent);
219   Cell2_10times->AddMaterial(BioMaterial, 79.45 * perCent);
220 
221   // FIFTH ELLIPSOID: intestine of the worm
222   // Original (real) composition in dry mass (the worm is dehydrated by
223   // lyophilization) Each element content is defined by its mass fraction (must
224   // be normalised to 1)
225   auto Intestine_real = new G4Material("Intestine_real", 0.54058 * g / cm3, 4);
226   Intestine_real->AddElement(S, 0.12 * perCent);
227   Intestine_real->AddElement(Cl, 0.02 * perCent);
228   Intestine_real->AddElement(K, 0.20 * perCent);
229   Intestine_real->AddMaterial(BioMaterial, 99.66 * perCent);
230 
231   // Intestine_10times: mass fractions of mineral elements 1O times more than
232   // original (real) mass fractions
233   auto Intestine_10times = new G4Material("Intestine_10times", 0.54058 * g / cm3, 4);
234   Intestine_10times->AddElement(S, 1.17 * perCent);
235   Intestine_10times->AddElement(Cl, 0.23 * perCent);
236   Intestine_10times->AddElement(K, 1.99 * perCent);
237   Intestine_10times->AddMaterial(BioMaterial, 96.61 * perCent);
238 
239   // SIXTH ELLIPSOID: Nucleus of cell Ti (contained inside ellipsoid 5)
240   // Original (real) composition in dry mass (the worm is dehydrated by
241   // lyophilization) Each element content is defined by its mass fraction (must
242   // be normalised to 1)
243   auto CellTi_real = new G4Material("CellTi_real", 0.75138 * g / cm3, 5);
244   CellTi_real->AddElement(S, 0.11 * perCent);
245   CellTi_real->AddElement(Cl, 0.02 * perCent);
246   CellTi_real->AddElement(K, 0.18 * perCent);
247   CellTi_real->AddElement(Ti, 0.05 * perCent);
248   CellTi_real->AddMaterial(BioMaterial, 99.64 * perCent);
249 
250   // CellTi_200times: mass fractions of mineral elements 1O times more than
251   // original (real) mass fractions except for Ti which is multiplied by 200
252   // times
253   auto CellTi_200times = new G4Material("CellTi_200times", 0.75138 * g / cm3, 5);
254   CellTi_200times->AddElement(S, 1.05 * perCent);
255   CellTi_200times->AddElement(Cl, 0.22 * perCent);
256   CellTi_200times->AddElement(K, 1.79 * perCent);
257   CellTi_200times->AddElement(Ti, 10.89 * perCent);  // Ti density 200 times
258   CellTi_200times->AddMaterial(BioMaterial, 86.05 * perCent);
259 
260   // CellTi_1000times: mass fractions of mineral elements 10 times more than
261   // original (real) mass fractions except for Ti which is multiplied by 1000
262   // times
263   auto CellTi_1000times = new G4Material("CellTi_1000times", 0.75138 * g / cm3, 5);
264   CellTi_1000times->AddElement(S, 1.05 * perCent);
265   CellTi_1000times->AddElement(Cl, 0.22 * perCent);
266   CellTi_1000times->AddElement(K, 1.79 * perCent);
267   CellTi_1000times->AddElement(Ti, 54.47 * perCent);  // Ti density 1000 times
268   CellTi_1000times->AddMaterial(BioMaterial, 42.47 * perCent);
269 
270   //
271   // define simple materials  Cl-doped polystyrene capsules (PS)
272   //
273   // Polystyrene
274   auto Cl_Polystyrene = new G4Material("Cl-doped Polystyrene", 1.18425 * g / cm3, 3);
275   Cl_Polystyrene->AddElement(C, 97);
276   Cl_Polystyrene->AddElement(H, 97);
277   Cl_Polystyrene->AddElement(Cl, 6);
278 
279   // Ge-doped glow discharge polymer (GDP)
280   auto GDP = new G4Material("GDP", 1.08 * g / cm3, 3);
281   GDP->AddElement(C, 76430);
282   GDP->AddElement(H, 107002);
283   GDP->AddElement(Ge, 744);
284 
285   //
286   // define a material from elements.
287   //
288   auto H2O = new G4Material("Water", 1.000 * g / cm3, 2);
289   H2O->AddElement(H, 2);
290   H2O->AddElement(O, 1);
291   H2O->GetIonisation()->SetMeanExcitationEnergy(78 * eV);
292 
293   auto Air = new G4Material("Air", 1.290 * mg / cm3, 2);
294   Air->AddElement(N, 0.7);
295   Air->AddElement(O, 0.3);
296 
297   //
298   // example of vacuum
299   //
300   G4double density = universe_mean_density;  // from PhysicalConstants.h
301   G4double pressure = 3.e-18 * pascal;
302   G4double temperature = 2.73 * kelvin;
303   new G4Material("Galactic", 1, 1.01 * g / mole, density, kStateGas, temperature, pressure);
304 }
305 
306 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
307 
308 void DetectorConstruction::ComputeGeomParameters()
309 {
310   if (phantom_type == 1) {
311     // Compute derived parameters of the box
312     fXstartAbs = fXposAbs - 0.5 * fAbsorberThickness;
313     fXendAbs = fXposAbs + 0.5 * fAbsorberThickness;
314 
315     G4double xmax = std::max(std::abs(fXstartAbs), std::abs(fXendAbs));
316     fWorldSizeX = 4 * xmax;
317     fWorldSizeYZ = 2 * fAbsorberSizeYZ;
318 
319     if (nullptr != fPhysiWorld) {
320       ChangeGeometry();
321     }
322   }
323   else if (phantom_type == 2) {
324     fWorldSizeX = 1 * mm;
325     fWorldSizeYZ = 1 * mm;
326   }
327   else if (phantom_type == 3) {
328     fWorldSizeX = 1.5 * mm;
329     fWorldSizeYZ = 1.5 * mm;
330   }
331 }
332 
333 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
334 
335 G4VPhysicalVolume* DetectorConstruction::Construct()
336 {
337   if (nullptr != fPhysiWorld) {
338     return fPhysiWorld;
339   }
340   // World
341   //
342   fSolidWorld = new G4Box("World",  // its name
343                           fWorldSizeX / 2, fWorldSizeYZ / 2, fWorldSizeYZ / 2);  // its size
344 
345   fLogicWorld = new G4LogicalVolume(fSolidWorld,  // its solid
346                                     fWorldMaterial,  // its material
347                                     "World");  // its name
348 
349   fPhysiWorld = new G4PVPlacement(nullptr,  // no rotation
350                                   G4ThreeVector(0., 0., 0.),  // at (0,0,0)
351                                   fLogicWorld,  // its logical volume
352                                   "World",  // its name
353                                   nullptr,  // its mother  volume
354                                   false,  // no boolean operation
355                                   0);  // copy number
356   if (phantom_type == 1) {
357     Construct_Phantom1();
358   }
359   else if (phantom_type == 2) {
360     Construct_Phantom2();
361   }
362   else if (phantom_type == 3) {
363     Construct_Phantom3();
364   }
365 
366   //    fLogicWorld->SetVisAttributes (G4VisAttributes::GetInvisible());
367 
368   // always return the physical World
369   //
370   return fPhysiWorld;
371 }
372 
373 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
374 
375 void DetectorConstruction::PrintGeomParameters()
376 {
377   if (phantom_type == 1) {
378     G4cout << "\n" << fWorldMaterial << G4endl;
379     G4cout << "\n" << fAbsorberMaterial << G4endl;
380 
381     G4cout << "\n The  WORLD   is made of " << G4BestUnit(fWorldSizeX, "Length") << " of "
382            << fWorldMaterial->GetName();
383     G4cout << ". The transverse size (YZ) of the world is " << G4BestUnit(fWorldSizeYZ, "Length")
384            << G4endl;
385     G4cout << " The ABSORBER is made of " << G4BestUnit(fAbsorberThickness, "Length") << " of "
386            << fAbsorberMaterial->GetName();
387     G4cout << ". The transverse size (YZ) is " << G4BestUnit(fAbsorberSizeYZ, "Length") << G4endl;
388     G4cout << " X position of the middle of the absorber " << G4BestUnit(fXposAbs, "Length");
389     G4cout << G4endl;
390   }
391   else if (phantom_type == 2) {
392     G4cout << "The upper part of C.elegans is made of 6 ellipsoids" << G4endl;
393   }
394   else if (phantom_type == 3) {
395     G4cout << "A microsphere inertial confinement fusion target is contructed, made of: " << G4endl;
396     G4cout << "\n" << material_GDP << G4endl;
397   }
398 }
399 
400 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
401 
402 void DetectorConstruction::SetAbsorberMaterial(const G4String& materialChoice)
403 {
404   // search the material by its name
405   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
406 
407   if (pttoMaterial && fAbsorberMaterial != pttoMaterial) {
408     fAbsorberMaterial = pttoMaterial;
409     if (fLogicAbsorber) {
410       fLogicAbsorber->SetMaterial(fAbsorberMaterial);
411     }
412     G4RunManager::GetRunManager()->PhysicsHasBeenModified();
413   }
414 }
415 
416 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
417 
418 void DetectorConstruction::SetWorldMaterial(const G4String& materialChoice)
419 {
420   // search the material by its name
421   G4Material* pttoMaterial = G4NistManager::Instance()->FindOrBuildMaterial(materialChoice);
422 
423   if (pttoMaterial && fWorldMaterial != pttoMaterial) {
424     fWorldMaterial = pttoMaterial;
425     if (fLogicWorld) {
426       fLogicWorld->SetMaterial(fWorldMaterial);
427     }
428     G4RunManager::GetRunManager()->PhysicsHasBeenModified();
429   }
430 }
431 
432 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
433 
434 void DetectorConstruction::SetAbsorberThickness(G4double val)
435 {
436   fAbsorberThickness = val;
437   ComputeGeomParameters();
438 }
439 
440 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
441 
442 void DetectorConstruction::SetAbsorberSizeYZ(G4double val)
443 {
444   fAbsorberSizeYZ = val;
445   ComputeGeomParameters();
446 }
447 
448 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
449 
450 void DetectorConstruction::SetWorldSizeX(G4double val)
451 {
452   fWorldSizeX = val;
453   ComputeGeomParameters();
454 }
455 
456 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
457 
458 void DetectorConstruction::SetWorldSizeYZ(G4double val)
459 {
460   fWorldSizeYZ = val;
461   ComputeGeomParameters();
462 }
463 
464 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
465 
466 void DetectorConstruction::SetAbsorberXpos(G4double val)
467 {
468   fXposAbs = val;
469 }
470 
471 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
472 
473 void DetectorConstruction::ConstructSDandField()
474 {
475   if (fFieldMessenger.Get() == nullptr) {
476     // Create global magnetic field messenger.
477     // Uniform magnetic field is then created automatically if
478     // the field value is not zero.
479     G4ThreeVector fieldValue = G4ThreeVector();
480     auto msg = new G4GlobalMagFieldMessenger(fieldValue);
481     // msg->SetVerboseLevel(1);
482     G4AutoDelete::Register(msg);
483     fFieldMessenger.Put(msg);
484   }
485 }
486 
487 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
488 
489 void DetectorConstruction::ChangeGeometry()
490 {
491   if (phantom_type == 1) {
492     fSolidWorld->SetXHalfLength(fWorldSizeX * 0.5);
493     fSolidWorld->SetYHalfLength(fWorldSizeYZ * 0.5);
494     fSolidWorld->SetZHalfLength(fWorldSizeYZ * 0.5);
495 
496     fSolidAbsorber->SetXHalfLength(fAbsorberThickness * 0.5);
497     fSolidAbsorber->SetYHalfLength(fAbsorberSizeYZ * 0.5);
498     fSolidAbsorber->SetZHalfLength(fAbsorberSizeYZ * 0.5);
499   }
500 }
501 
502 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
503 
504 void DetectorConstruction::SetPhantomType(G4int value)
505 {
506   phantom_type = value;
507   ComputeGeomParameters();
508 }
509 
510 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
511 
512 void DetectorConstruction::Construct_Phantom1()
513 {
514   fSolidAbsorber =
515     new G4Box("Absorber", fAbsorberThickness / 2, fAbsorberSizeYZ / 2, fAbsorberSizeYZ / 2);
516 
517   fLogicAbsorber = new G4LogicalVolume(fSolidAbsorber,  // its solid
518                                        fAbsorberMaterial,  // its material
519                                        "Absorber");  // its name
520 
521   G4RotationMatrix rm;
522   G4double angle = 0 * deg;
523   rm.rotateZ(angle);
524 
525   fPhysiAbsorber = new G4PVPlacement(G4Transform3D(rm, G4ThreeVector(fXposAbs * um, 0., 0.)),
526                                      fLogicAbsorber,  // its logical volume
527                                      "Absorber",  // its name
528                                      fLogicWorld,  // its mother
529                                      false,  // no boolean operation
530                                      0);  // copy number
531 
532   auto logVisAtt = new G4VisAttributes(G4Colour(0.670588, 0.333333, 0.862745));
533   logVisAtt->SetForceSolid(true);
534   fLogicAbsorber->SetVisAttributes(logVisAtt);
535 
536   PrintGeomParameters();
537 }
538 
539 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
540 
541 void DetectorConstruction::Construct_Phantom2()
542 {
543   G4NistManager* nist = G4NistManager::Instance();
544   // PHANTOM 3: C. ELEGANS WORM **********************************
545   // made of 6 ellipsoids
546 
547   // FIRST ELLIPSOID  : external surface of the worm ("skin")
548 
549   material1 = nist->FindOrBuildMaterial("Skin_10times");
550   G4ThreeVector center1 =
551     G4ThreeVector(fXposAbs, 0,
552                   0);  // position of the center of the first ellipsoid is (fXposAbs,0,0)
553   // if we change fXposAbs, all the phantom will be translated along X axis
554   // as the position of the center of all other ellipsoids is defined according
555   // to fXposAbs
556   G4double halfx1 = 20.61 * um;  // Semiaxis in X
557   G4double halfy1 = 21.42 * um;  // Semiaxis in Y
558   G4double halfz1 = 187.82 * um;  // Semiaxis in Z
559   G4double pzTopCut1 = 187.82 * um;  // here the top of the ellipsoid is not cut away
560   G4double pzBottomCut1 = 0 * um;  // here the bottom of the ellipsoid is cut
561                                    // away below z = 0 (original configuration)
562   // G4double pzBottomCut1 = 18.07*um;  // test with position of the slice of
563   // interest for vis.mac visualisation of the slice z = 18.07 µm
564 
565   ellipse1 = new G4Ellipsoid("Ellipse1", halfx1, halfy1, halfz1, pzBottomCut1,
566                              pzTopCut1);  // cut ellipsoid (original configuration)
567 
568   logicEllipse1 = new G4LogicalVolume(ellipse1,  // its solid
569                                       material1,  // its material
570                                       "Ellipse1");  // its name
571 
572   physiEllipse1 = new G4PVPlacement(nullptr,  // no rotation
573                                     center1,  // its position
574                                     logicEllipse1,  // its logical volume
575                                     "Ellipse1",  // its name
576                                     fLogicWorld,  // its mother
577                                     false,  // no boolean operation
578                                     0);  // copy number
579 
580   // SECOND ELLIPSOID : "body" of the worm, limited by the internal surface of
581   // the "skin"
582   material2 = nist->FindOrBuildMaterial("Body_10times");
583   G4ThreeVector center2 = G4ThreeVector(-0.39 * um, 0, 0);  // position according to ellipsoid 1
584   G4double halfx2 = 18.61 * um;  // Semiaxis in X
585   G4double halfy2 = 19.01 * um;  //  Semiaxis in Y
586   G4double halfz2 = 186.64 * um;  // Semiaxis in Z
587 
588   G4double pzTopCut2 = 186.64 * um;  // here the top of the ellipsoid is not cut away
589   G4double pzBottomCut2 = 0 * um;  // here the bottom of the ellipsoid is cut
590                                    // away below z = 0 (original configuration)
591   // G4double pzBottomCut2 = 18.07*um; // test with position of the slice of
592   // interest for vis.mac visualisation of the slice z = 18.07 µm
593 
594   // Ellipse2 = new G4Ellipsoid("Ellipse2",halfx2,halfy2,halfz2); // test with
595   // entire ellipsoid
596   ellipse2 = new G4Ellipsoid("Ellipse2", halfx2, halfy2, halfz2, pzBottomCut2,
597                              pzTopCut2);  // cut ellipsoid
598 
599   logicEllipse2 = new G4LogicalVolume(ellipse2,  // its solid
600                                       material2,  // its material
601                                       "Ellipse2");  // its name
602 
603   physiEllipse2 = new G4PVPlacement(nullptr,  // no rotation
604                                     center2,  // its position
605                                     logicEllipse2,  // its logical volume
606                                     "Ellipse2",  // its name
607                                     logicEllipse1,  // its mother
608                                     false,  // no boolean operation
609                                     0);  // copy number
610 
611   // THIRD ELLIPSOID : Nucleus of cell 1 (contained inside ellipsoid 2)
612   material3 = nist->FindOrBuildMaterial("Cell1_10times");
613   G4ThreeVector center3 =
614     G4ThreeVector(2.36 * um, -7.09 * um, 18.07 * um);  // position according to ellipsoid 2
615   G4double halfx3 = 1.95 * um;  // Semiaxis in X
616   G4double halfy3 = 3.23 * um;  // Semiaxis in Y
617   G4double halfz3 = 4.32 * um;  // Semiaxis in Z
618 
619   // if we want to visualize slice at z = 18.07 µm using vis.mac,
620   // we should cut all the ellipsoids (cut away all parts below 18.07 µm)
621   // Visualization test: the lower part of ellipse 3 is cut off
622   // G4double pzTopCut3 =4.32 *um;  // Visualization test
623   // G4double pzBottomCut3 = 0*um;  // Visualization test: cut at zero before
624   // moving ellipsoid 3
625   // // to position defined just above => it will be cut at 18.07 µm after
626   // moving
627 
628   ellipse3 = new G4Ellipsoid("Ellipse3", halfx3, halfy3, halfz3);  // entire ellipsoid
629   // ellipse3 = new
630   // G4Ellipsoid("Ellipse3",halfx3,halfy3,halfz3,pzBottomCut3,pzTopCut3); //
631   // Visualization test
632 
633   logicEllipse3 = new G4LogicalVolume(ellipse3,  // its solid
634                                       material3,  // its material
635                                       "Ellipse3");  // its name
636 
637   physiEllipse3 = new G4PVPlacement(nullptr,  // no rotation
638                                     center3,  // its position
639                                     logicEllipse3,  // its logical volume
640                                     "Ellipse3",  // its name
641                                     logicEllipse2,  // its mother
642                                     false,  // no boolean operation
643                                     0);  // copy number
644 
645   // FOURTH ELLIPSOID : Nucleus of cell 2 (contained inside ellipsoid 2)
646   material4 = nist->FindOrBuildMaterial("Cell2_10times");
647   G4ThreeVector center4 =
648     G4ThreeVector(8.66 * um, -3.15 * um, 18.07 * um);  // position according to ellipsoid 2
649   G4double halfx4 = 2.08 * um;  // Semiaxis in X
650   G4double halfy4 = 2.46 * um;  // Semiaxis in Y
651   G4double halfz4 = 4.32 * um;  // Semiaxis in Z
652 
653   // means the lower part of ellipse 4 was cut off
654   // G4double pzTopCut4 = 4.32*um;
655   // G4double pzBottomCut4 = 0*um;// Visualization test: cut at zero before
656   // moving ellipsoid 4
657   // // to position defined just above => it will be cut at 18.07 µm after
658   // moving
659 
660   ellipse4 = new G4Ellipsoid("Ellipse4", halfx4, halfy4, halfz4);  // entire ellipsoid
661   // Ellipse4 = new
662   // G4Ellipsoid("Ellipse4",halfx4,halfy4,halfz4,pzBottomCut4,pzTopCut4); //
663   // Visualization test
664 
665   logicEllipse4 = new G4LogicalVolume(ellipse4,  // its solid
666                                       material4,  // its material
667                                       "Ellipse4");  // its name
668 
669   physiEllipse4 = new G4PVPlacement(nullptr,  // no rotation
670                                     center4,  // its position
671                                     logicEllipse4,  // its logical volume
672                                     "Ellipse4",  // its name
673                                     logicEllipse2,  // its mother
674                                     false,  // no boolean operation
675                                     0);  // copy number
676 
677   // FIFTH ELLIPSOID: intestine of the worm
678   // Original (real) composition in dry mass (the worm is dehydrated by
679   // lyophilization) Each element content is defined by its mass fraction (must
680   // be normalised to 1)
681   material5 = nist->FindOrBuildMaterial("Intestine_10times");
682   G4ThreeVector center5 =
683     G4ThreeVector(1.64 * um, 0.61 * um, 0 * um);  // position according to ellipsoid 2
684   G4RotationMatrix rm5;
685   G4double angle5 = -58.986 * deg;  // ellipse 5 is rotated around z axis
686                                     // (rotation defined according to ellipse 2)
687   // G4double angle5=0*deg;
688   rm5.rotateZ(angle5);
689 
690   G4double halfx5 = 3.67 * um;  // Semiaxis in X
691   G4double halfy5 = 16.48 * um;  // Semiaxis in Y
692   G4double halfz5 = 28.68 * um;  // Semiaxis in Z
693 
694   G4double pzTopCut5 = 28.68 * um;  // here the top of the ellipsoid is not cut away
695   G4double pzBottomCut5 = 0 * um;  // here the bottom of the ellipsoid is cut
696                                    // away below z = 0 // original configuration
697   // G4double pzBottomCut5 =18.07*um; // position of the slice of interest    //
698   // Visualization test
699 
700   // ellipse5 = new G4Ellipsoid("Ellipse5",halfx5,halfy5,halfz5); // entire
701   // ellipsoid // Visualization test
702   ellipse5 = new G4Ellipsoid("Ellipse5", halfx5, halfy5, halfz5, pzBottomCut5,
703                              pzTopCut5);  // original configuration
704 
705   logicEllipse5 = new G4LogicalVolume(ellipse5,  // its solid
706                                       material5,  // its material
707                                       "Ellipse5");  // its name
708 
709   physiEllipse5 = new G4PVPlacement(G4Transform3D(rm5, center5),  // rotation
710                                     logicEllipse5,  // its logical volume
711                                     "Ellipse5",  // its name
712                                     logicEllipse2,  // its mother
713                                     false,  // no boolean operation
714                                     0);  // copy number
715 
716   // SIXTH ELLIPSOID: Nucleus of cell Ti (contained inside ellipsoid 5)
717   // Original (real) composition in dry mass (the worm is dehydrated by
718   // lyophilization) Each element content is defined by its mass fraction (must
719   // be normalised to 1)
720 
721   material6 = nist->FindOrBuildMaterial("CellTi_1000times");
722   G4ThreeVector center6 =
723     G4ThreeVector(0.005 * um, 5.83 * um, 18.07 * um);  // position according to ellipsoid 5
724   G4double halfx6 = 1.62 * um;  // Semiaxis in X
725   G4double halfy6 = 1.95 * um;  // Semiaxis in Y
726   G4double halfz6 = 1.62 * um;  // Semiaxis in Z
727 
728   // means the lower part of ellipse 6 was cut off
729   // G4double pzTopCut6 = 1.62*um;
730   // G4double pzBottomCut6 = 0*um;  // Visualization test: cut at zero before
731   // moving ellipsoid 6
732   // // to position defined just above => it will be cut at 18.07 µm after
733   // moving. As ellipsoid 6 is contained in ellipsoid 5, it has been rotated at
734   // the same time as ellipsoid 5. We want to counterbalance this rotation and
735   // put ellipsoid 6 in the right direction (not rotated at all). So we must
736   // rotate ellipsoid 6 of the opposite angle as ellipsoid 5
737   G4RotationMatrix rm6;
738   G4double angle6 = 58.986 * deg;  // ellipsoid 6 is rotated around z axis
739                                    // (rotation defined according to ellipse 5)
740   // G4double angle6= 0*deg;
741   rm6.rotateZ(angle6);
742   ellipse6 = new G4Ellipsoid("Ellipse6", halfx6, halfy6, halfz6);  // entire ellipsoid
743   // ellipse6 = new
744   // G4Ellipsoid("Ellipse6",halfx6,halfy6,halfz6,pzBottomCut6,pzTopCut6);    //
745   // Visualization test
746   logicEllipse6 = new G4LogicalVolume(ellipse6,  // its solid
747                                       material6,  // its material
748                                       "Ellipse6");  // its name
749 
750   physiEllipse6 =
751     new G4PVPlacement(G4Transform3D(rm6, center6),  // So now ellipsoid 6 is vertical again
752                                                     // (appears not rotated at all)
753                       logicEllipse6,  // its logical volume
754                       "Ellipse6",  // its name
755                       logicEllipse5,  // its mother
756                       false,  // no boolean operation
757                       0);  // copy number
758 
759   /* logicEllipse1->SetUserLimits(new G4UserLimits(0.5*um,DBL_MAX,DBL_MAX,0));
760 
761   logicEllipse2->SetUserLimits(new G4UserLimits(0.5*um,DBL_MAX,DBL_MAX,0)); */
762 
763   // As the material composing the C. elegans worm is very transparent to
764   // photons, the default steps in Geant4 (distance between pre-step and
765   // post-step point) are too long. To perform a more precise simulation,
766   // maximal values are defined for step length in each volume, according to its
767   // size and configuration.
768 
769   logicEllipse1->SetUserLimits(new G4UserLimits(0.2 * um));
770   logicEllipse2->SetUserLimits(new G4UserLimits(0.3 * um));
771   logicEllipse3->SetUserLimits(new G4UserLimits(0.4 * um));
772   logicEllipse4->SetUserLimits(new G4UserLimits(0.4 * um));
773   logicEllipse5->SetUserLimits(new G4UserLimits(0.7 * um));
774   logicEllipse6->SetUserLimits(new G4UserLimits(0.3 * um));
775   // fLogicWorld->SetUserLimits(new G4UserLimits(1*um)); // world does not have
776   // to be simulated as precisely
777 
778   //    fLogicWorld ->SetVisAttributes(new
779   //    G4VisAttributes(G4Colour(1.0,1.0,1.0)));
780   logicEllipse1->SetVisAttributes(new G4VisAttributes(G4Colour(1.0, 0.8, 1.0, 0.5)));
781   logicEllipse2->SetVisAttributes(new G4VisAttributes(G4Colour(1.0, 0.5, 1.0, 0.5)));
782   //    logicEllipse3 ->SetVisAttributes(new
783   //    G4VisAttributes(G4Colour(0.0,1.0,1.0))); logicEllipse4
784   //    ->SetVisAttributes(new G4VisAttributes(G4Colour(0.5,0.3,0.5)));
785   logicEllipse5->SetVisAttributes(new G4VisAttributes(G4Colour(0.5, 0.5, 1.0, 0.5)));
786   //    logicEllipse6 ->SetVisAttributes(new
787   //    G4VisAttributes(G4Colour(0.5,0.8,0.2)));
788 
789   auto logVisAtt3 = new G4VisAttributes(G4Colour(0.0, 1.0, 1.0));
790   logVisAtt3->SetForceSolid(true);
791   logicEllipse3->SetVisAttributes(logVisAtt3);
792 
793   auto logVisAtt4 = new G4VisAttributes(G4Colour(0.5, 0.3, 0.5));
794   logVisAtt4->SetForceSolid(true);
795   logicEllipse4->SetVisAttributes(logVisAtt4);
796 
797   auto logVisAtt6 = new G4VisAttributes(G4Colour(0.5, 0.8, 0.2));
798   logVisAtt6->SetForceSolid(true);
799   logicEllipse6->SetVisAttributes(logVisAtt6);
800 
801   PrintGeomParameters();
802 }
803 
804 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo.....
805 
806 void DetectorConstruction::Construct_Phantom3()
807 {
808   G4NistManager* nist = G4NistManager::Instance();
809   material_GDP = nist->FindOrBuildMaterial("GDP");
810 
811   G4double pRmin = 171 * um;  // thickness = 25 um
812   G4double pRmax = 196 * um;
813 
814   //    G4double pRmin = 146.8*um;  // thickness = 10 um
815   //    G4double pRmax = 156.8*um;
816 
817   //    G4double pRmin = 293.6*um;  // thickness = 20 um
818   //    G4double pRmax = 313.6*um;
819 
820   solid_GDP = new G4Sphere("GDP",  // name
821                            pRmin, pRmax, 0., 2 * pi, 0., pi);
822 
823   logic_GDP = new G4LogicalVolume(solid_GDP,  // its solid
824                                   material_GDP,  // its material
825                                   "GDP");  // its name
826 
827   physi_GDP = new G4PVPlacement(nullptr,  // no rotation
828                                 G4ThreeVector(fXposAbs, 0., 0.),  // its position
829                                 logic_GDP,  // its logical volume
830                                 "GDP",  // its name
831                                 fLogicWorld,  // its mother
832                                 false,  // no boolean operation
833                                 0);  // copy number
834 
835   logic_GDP->SetUserLimits(new G4UserLimits(1 * um));
836 
837   auto logVisAtt = new G4VisAttributes(G4Colour(0.670588, 0.333333, 0.862745, 0.5));
838   //    new G4VisAttributes(G4Colour(0.670588, 0.333333, 0.862745));
839   logVisAtt->SetForceSolid(true);
840   //  logVisAtt->SetVisibility(true);
841 
842   logic_GDP->SetVisAttributes(logVisAtt);
843 
844   PrintGeomParameters();
845 }
846 
847 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
848