Deprecated/UpgradeASCIITests/G4TankSimulatorASCII/G4TankConstruction.cc
Go to the documentation of this file.
1 #include "G4TankConstruction.h"
2 
3 #include <fwk/RunController.h>
4 #include <fwk/CentralConfig.h>
5 
6 #include <sdet/SDetector.h>
7 
8 #include <utl/CoordinateSystem.h>
9 #include <utl/Point.h>
10 #include <utl/TabulatedFunction.h>
11 #include <utl/Reader.h>
12 
13 #include <vector>
14 //#include <iostream>
15 #include <sstream>
16 
17 using sdet::SDetector;
19 using utl::Point;
21 using utl::Branch;
22 
23 using namespace fwk;
24 
25 using std::vector;
26 //using std::cout;
27 //using std::cerr;
28 //using std::endl;
29 
30 using std::ostringstream;
31 
32 using namespace G4TankSimulatorASCII;
33 
34 // declare variables that static members above refer to.
35 double G4TankConstruction::fExpHall_x, G4TankConstruction::fExpHall_y;
36 double G4TankConstruction::fExpHall_z;
37 
38 double G4TankConstruction::fTankRadius;
39 double G4TankConstruction::fTankHalfHeight;
40 double G4TankConstruction::fTankThickness;
41 double G4TankConstruction::fTankPos_x;
42 double G4TankConstruction::fTankPos_y;
43 double G4TankConstruction::fTankPos_z;
44 
45 utl::Point G4TankConstruction::fPmt1;
46 utl::Point G4TankConstruction::fPmt2;
47 utl::Point G4TankConstruction::fPmt3;
48 
49 double G4TankConstruction::fFaceRadius, G4TankConstruction::fFaceRadiusz;
50 double G4TankConstruction::fFaceActiveRadius, G4TankConstruction::fHeightz;
51 double G4TankConstruction::fPmtRmin, G4TankConstruction::fPmtRmax;
52 double G4TankConstruction::fPmtRzmin, G4TankConstruction::fPmtRzmax;
53 double G4TankConstruction::fInterfaceRmin, G4TankConstruction::fInterfaceRzmin;
54 double G4TankConstruction::fInterfaceRmax, G4TankConstruction::fInterfaceRzmax;
55 double G4TankConstruction::fInterfaceThickness, G4TankConstruction::fGlassThickness;
56 double G4TankConstruction::fDomeThickness;
57 double G4TankConstruction::fDomeRmin, G4TankConstruction::fDomeRmax;
58 double G4TankConstruction::fDomeRzmin, G4TankConstruction::fDomeRzmax;
59 double G4TankConstruction::fMinPhi, G4TankConstruction::fMaxPhi;
60 double G4TankConstruction::fMinTheta, G4TankConstruction::fMaxTheta;
61 double G4TankConstruction::fSolarPanelLength, G4TankConstruction::fSolarPanelWidth;
62 double G4TankConstruction::fSolarPanelThickness;
63 double G4TankConstruction::fSolarPanelX, G4TankConstruction::fSolarPanelY;
64 double G4TankConstruction::fSolarPanelZ, G4TankConstruction::fSolarPanelTiltAngle;
65 double G4TankConstruction::fElecBoxLength, G4TankConstruction::fElecBoxWidth;
66 double G4TankConstruction::fElecBoxThickness;
67 double G4TankConstruction::fElecBoxX, G4TankConstruction::fElecBoxY;
68 double G4TankConstruction::fElecBoxZ, G4TankConstruction::fElecBoxTiltAngle;
69 
70 TabulatedFunction G4TankConstruction::fPmtfaceRINDEX;
71 TabulatedFunction G4TankConstruction::fInterfaceRINDEX;
72 TabulatedFunction G4TankConstruction::fPmtdomeRINDEX;
73 TabulatedFunction G4TankConstruction::fPmtfaceABSORPTION;
74 TabulatedFunction G4TankConstruction::fInterfaceABSORPTION;
75 TabulatedFunction G4TankConstruction::fPmtdomeABSORPTION;
76 double G4TankConstruction::fSIGMA_ALPHA;
77 TabulatedFunction G4TankConstruction::fLinerREFLECTIVITY;
78 TabulatedFunction G4TankConstruction::fLinerSPECULARLOBECONSTANT;
79 TabulatedFunction G4TankConstruction::fLinerSPECULARSPIKECONSTANT;
80 TabulatedFunction G4TankConstruction::fLinerBACKSCATTERCONSTANT;
81 TabulatedFunction G4TankConstruction::fLinerTYVEK_RINDEX;
82 TabulatedFunction G4TankConstruction::fLinerABSORPTION;
83 TabulatedFunction G4TankConstruction::fWaterABSORPTION;
84 TabulatedFunction G4TankConstruction::fWaterRINDEX;
85 
86 // Older versions of Geant4 do not have the G4Ellipsoid defined
87 
88 G4TankConstruction::G4TankConstruction() : expHall_phys(0)
89 {
93 
94  // disable solar panel, electronics box, and ground for now:
95 
96  fSolarPanelEnable = false;
97  fElecBoxEnable = false;
98  fGroundEnable = false;
99  fASCIIEnable = true;
100 
101  Water = NULL;
102  Pyrex = NULL;
103  Pyrex1 = NULL;
104  Lucite = NULL;
105  Interface = NULL;
106  HDPE = NULL;
107  linerOpticalMPT = NULL;
108  Polystyrene = NULL;
109  theIron=NULL;
110  Plastic=NULL;
111 
112  return;
113 }
114 
116 
118 {
119  // The "experimental hall" in which the detector
120  // is contained:
121 
122  fExpHall_x = 5.0*m;
123  fExpHall_y = 5.0*m;
124  fExpHall_z = 5.0*m;
125 
126  // The position of the center of the tank
127  // in the local Geant4 coordinate system
128 
129  fTankPos_x = 0.0*m;
130  fTankPos_y = 0.0*m;
131  fTankPos_z = 0.0*m;
132 }
133 
135 {
136  vector<double>::iterator tfIt;
137  G4double alpha;
138  // Get the pointer to the current detector
139  G4TankSimulator* const theTankSimulator =
140  dynamic_cast<G4TankSimulator*>(&RunController::GetInstance().GetModule("G4TankSimulatorASCII"));
141 
142  const sdet::Station* theCurrentDetectorStation =
143  theTankSimulator->GetCurrentDetectorStation();
144  if (!theCurrentDetectorStation) return; // no point getting data yet
145 
146  // Set tank properties
147 
148  fTankRadius =
149  theCurrentDetectorStation->GetRadius()*m;
150  fTankHalfHeight =
151  theCurrentDetectorStation->GetHeight()*0.5*m;
152  fTankThickness =
153  theCurrentDetectorStation->GetThickness()*m;
154 
155  // Set pmt position (relative to the center of the tank)
156 
157  fPmt1 = theCurrentDetectorStation->GetPMT(1).GetPosition(); // converted to G4 units later
158  fPmt2 = theCurrentDetectorStation->GetPMT(2).GetPosition(); // converted to G4 units later
159  fPmt3 = theCurrentDetectorStation->GetPMT(3).GetPosition(); // converted to G4 units later
160 
161  // Set pmt optical properties
162  // For now, assume that all three pmts have the same properties
163 
164  fPmtfaceRINDEX =
165  theCurrentDetectorStation->GetPMT(1).GetFaceRefractionIndex();
166  for (tfIt = fPmtfaceRINDEX.XBegin(); tfIt != fPmtfaceRINDEX.XEnd(); tfIt++)
167  (*tfIt) *= eV;
169  theCurrentDetectorStation->GetPMT(1).GetRTVRefractionIndex();
170  for (tfIt = fInterfaceRINDEX.XBegin(); tfIt != fInterfaceRINDEX.XEnd();
171  tfIt++) (*tfIt) *= eV;
172  fPmtdomeRINDEX =
173  theCurrentDetectorStation->GetPMT(1).GetDomeRefractionIndex();
174  for (tfIt = fPmtdomeRINDEX.XBegin(); tfIt != fPmtdomeRINDEX.XEnd(); tfIt++)
175  (*tfIt) *= eV;
176 
177  // These parameters specify the pmt geometry ( already converted to G4 units )
178 
189  fDomeRmax = fFaceRadius + fInterfaceThickness + fDomeThickness;
190  fDomeRzmax = fFaceRadiusz + fInterfaceThickness + fDomeThickness;
191 
192  // Taking into account that the radius of the photocathode is fFaceActiveRadius
193  if ( fFaceActiveRadius/mm >= 114. )
194  {
195  fFaceActiveRadius = 113.926112814*mm;
196  fHeightz = 0.;
197  }
198  else if ( fFaceActiveRadius/mm > 97.27 )
199  {
200  alpha = acos(1./62.*(fFaceActiveRadius/mm-133.*sin(47.*deg)+62.*cos(43.*deg)));
201  fHeightz = 62.*sin(alpha)*mm;
202  }
203  else
204  {
205  alpha = asin(fFaceActiveRadius/mm/133.);
206  fHeightz = (133.*cos(alpha)-(133.-62.)*cos(47.*deg))*mm;
207  }
208 
209  // Set liner properties
210 
211  fSIGMA_ALPHA = theCurrentDetectorStation->GetLinerSigmaAlpha();
212 
213  fLinerREFLECTIVITY = theCurrentDetectorStation->GetLinerReflectivity();
214  for (tfIt = fLinerREFLECTIVITY.XBegin(); tfIt != fLinerREFLECTIVITY.XEnd();
215  tfIt++) (*tfIt) *= eV;
216  fLinerSPECULARLOBECONSTANT = theCurrentDetectorStation->GetLinerSpecularLobe();
217  for (tfIt = fLinerSPECULARLOBECONSTANT.XBegin();
218  tfIt != fLinerSPECULARLOBECONSTANT.XEnd(); tfIt++) (*tfIt) *= eV;
219  fLinerSPECULARSPIKECONSTANT = theCurrentDetectorStation->GetLinerSpecularSpike();
220  for (tfIt = fLinerSPECULARSPIKECONSTANT.XBegin();
221  tfIt != fLinerSPECULARSPIKECONSTANT.XEnd(); tfIt++) (*tfIt) *= eV;
222 
223  // Set water properties
224 
225  fWaterABSORPTION = theCurrentDetectorStation->GetWaterAbsorptionLength();
226  for (tfIt = fWaterABSORPTION.XBegin(); tfIt != fWaterABSORPTION.XEnd();
227  tfIt++) (*tfIt) *= eV;
228  for (tfIt = fWaterABSORPTION.YBegin(); tfIt != fWaterABSORPTION.YEnd();
229  tfIt++) (*tfIt) *= m;
230  fWaterRINDEX = theCurrentDetectorStation->GetWaterRefractionIndex();
231  for (tfIt = fWaterRINDEX.XBegin(); tfIt != fWaterRINDEX.XEnd(); tfIt++)
232  (*tfIt) *= eV;
233  return;
234 }
235 
237 {
238  CentralConfig* theConfig = CentralConfig::GetInstance();
239 
240  Branch TopBranch = theConfig->GetTopBranch("G4TankSimulatorASCII");
241 
242 
243  Branch ASCIIEnableB = TopBranch.GetChild("ASCIIEnable");
244  ASCIIEnableB.GetData(fASCIIEnable);
245 
246  //cout<<"Getting parameters from XML file..."<<endl;
247 
248  unsigned int size;
249 
250  vector<double> pmt_pp;
251  vector<double> pmt_face_abs;
252  vector<double> pmt_interface_abs;
253  vector<double> pmt_dome_abs;
254 
255  TopBranch.GetChild("pmt_momentum_bins").GetData(pmt_pp);
256  TopBranch.GetChild("pmtface_AbsLength").GetData(pmt_face_abs);
257  TopBranch.GetChild("interface_AbsLength").GetData(pmt_interface_abs);
258  TopBranch.GetChild("dome_AbsLength").GetData(pmt_dome_abs);
259  TopBranch.GetChild("interface_thickness").GetData(fInterfaceThickness);
260  TopBranch.GetChild("pmtface_thickness").GetData(fGlassThickness);
263 
264  size = pmt_pp.size();
265 
266  if ( pmt_face_abs.size() != size ||
267  pmt_interface_abs.size() != size ||
268  pmt_dome_abs.size() != size )
269  {
270  ostringstream errMsg;
271  errMsg<<"TabulatedFunction size mismatch for pmt properties";
272  ERROR(errMsg);
273 
274  throw utl::OutOfBoundException(errMsg.str());
275  }
276 
277  for (unsigned int i = 0; i < size; ++i)
278  {
279  fPmtfaceABSORPTION.PushBack( pmt_pp[i]*eV, pmt_face_abs[i]*m );
280  fInterfaceABSORPTION.PushBack( pmt_pp[i]*eV, pmt_interface_abs[i]*m );
281  fPmtdomeABSORPTION.PushBack( pmt_pp[i]*eV, pmt_dome_abs[i]*m );
282  }
283 
284  TopBranch.GetChild("face_radius").GetData(fFaceRadius);
285  TopBranch.GetChild("face_radius_z").GetData(fFaceRadiusz);
286  TopBranch.GetChild("face_active_radius").GetData(fFaceActiveRadius);
287  fFaceRadius*=m;
288  fFaceRadiusz*=m;
290 
291  vector<double> liner_pp;
292  vector<double> liner_rindex;
293  vector<double> liner_abs;
294  vector<double> liner_backscatter;
295 
296  TopBranch.GetChild("liner_momentum_bins").GetData(liner_pp);
297  TopBranch.GetChild("liner_Rindex").GetData(liner_rindex);
298  TopBranch.GetChild("liner_AbsLength").GetData(liner_abs);
299  TopBranch.GetChild("backScatter").GetData(liner_backscatter);
300  TopBranch.GetChild("dome_thickness").GetData(fDomeThickness);
301  fDomeThickness *= m;
302 
303  size = liner_pp.size();
304 
305  if ( liner_rindex.size() != size ||
306  liner_abs.size() != size ||
307  liner_backscatter.size() != size )
308  {
309  ostringstream errMsg;
310  errMsg<<"Tabulated function size mismatch for liner properties";
311  ERROR(errMsg);
312 
313  throw utl::OutOfBoundException(errMsg.str());
314  }
315 
316  for (unsigned int i = 0; i < size; ++i)
317  {
318  fLinerTYVEK_RINDEX.PushBack( liner_pp[i]*eV, liner_rindex[i] );
319  fLinerABSORPTION.PushBack( liner_pp[i]*eV, liner_abs[i]*m );
320  fLinerBACKSCATTERCONSTANT.PushBack( liner_pp[i]*eV, liner_backscatter[i] );
321  }
322  return;
323 }
324 
325 G4VPhysicalVolume *G4TankConstruction::Construct(void)
326 {
327  if(!expHall_phys){
328  CreateElements();
329  CreateMaterials();
330  return CreateTank();
331  }else{
332  return expHall_phys;
333  }
334 }
336 {
337  G4double a;
338  G4String name, symbol;
339  G4int z;
340 
341  // Elements
342  //---------
343 
344  a = 14.01*g/mole;
345  elN = new G4Element(name = "Nitrogen", symbol = "N", z = 7, a);
346  a = 16.00*g/mole;
347  elO = new G4Element(name = "Oxygen", symbol = "O", z = 8, a);
348  a = 29.98*g/mole;
349  elAl = new G4Element(name = "Aluminum", symbol = "Al", z = 13, a);
350  a = 55.85*g/mole;
351  elFe = new G4Element(name = "Iron", symbol = "Fe", z = 26, a);
352  a = 1.01*g/mole;
353  elH = new G4Element(name = "Hydrogen", symbol = "H", z = 1, a);
354  a = 28.09*g/mole;
355  elSi = new G4Element(name = "Silicon", symbol = "Si", z = 14, a);
356  a = 10.811*g/mole;
357  elB = new G4Element(name = "Boron", symbol = "B", z = 5, a);
358  a = 22.98977*g/mole;
359  elNa = new G4Element(name = "Sodium", symbol = "Na", z = 11, a);
360  a = 12.0107*g/mole;
361  elC = new G4Element(name = "Carbon", symbol = "C", z = 6, a);
362 }
363 
365 {
366  CreateAir();
367  CreateWater();
368  CreateVacuum();
369  CreatePyrex();
370  CreatePyrex1();
371  CreateLucite();
372  CreateInterface();
373  CreateHDPE();
374  CreateLiner();
375  CreateAluminium();
376  CreateDirt();
377 
379  CreateIron();
380  CreatePlastic();
381 
382  return;
383 }
384 
385 G4VPhysicalVolume *G4TankConstruction::CreateTank(void)
386 {
388  CreateHall();
389  AssembleTank();
390  return expHall_phys;
391 }
392 
394 {
395  // Air
396  //----
397  G4String name;
398  G4double density = 1.29e-03*g/cm3;
399  G4int nel;
400  Air = new G4Material(name = "Air_G4Tank", density, nel = 2);
401  Air->AddElement(elN, 0.7);
402  Air->AddElement(elO, 0.3);
403 
404  // Add material property table for Air to simulate empty tank
405  double airPP[2] = { 2.08*eV, 4.20*eV };
406  double airRINDEX[2] = { 1.000273, 1.000273 };
407  double airABSLENGTH[2] = { 10000.0*m, 10000.0*m };
408 
409  airMPT = new G4MaterialPropertiesTable();
410  airMPT->AddProperty("RINDEX", airPP, airRINDEX, 2);
411  airMPT->AddProperty("ABSLENGTH", airPP, airABSLENGTH, 2);
412 
413  Air->SetMaterialPropertiesTable(airMPT);
414  return;
415 }
416 
418 {
419 
420  // Water
421  //------
422  G4String name;
423  G4double density = 1.0*g/cm3;
424  G4int nel;
425 
426  if (Water != NULL) {
427  delete Water;
428  delete waterMPT;
429  }
430  Water = new G4Material(name = "Water", density, nel = 2);
431  Water->AddElement(elH, 2);
432  Water->AddElement(elO, 1);
433 
434  // Set water material properties
435 
436  waterMPT = new G4MaterialPropertiesTable();
437 
438  // water rindex
439 
440  int index;
441  int num = fWaterRINDEX.GetNPoints();
442 
443  double* array_ppWATER = new double[num+1];
444  double* array_waterRINDEX = new double[num+1];
445 
446  for ( index = 0; index < num; index++ )
447  {
448  array_ppWATER[index] = fWaterRINDEX[index].X();
449  array_waterRINDEX[index] = fWaterRINDEX[index].Y();
450  }
451 
452  waterMPT->AddProperty("RINDEX", array_ppWATER, array_waterRINDEX, num);
453 
454  // water abs. length
455 
457 
458  double* array_ppwaterABSORPTION = new double[num+1];
459  double* array_waterABSORPTION = new double[num+1];
460 
461  for ( index = 0; index < num; index++ )
462  {
463  array_ppwaterABSORPTION[index] = fWaterABSORPTION[index].X();
464  array_waterABSORPTION[index] = fWaterABSORPTION[index].Y();
465  }
466 
467  waterMPT->AddProperty("ABSLENGTH", array_ppwaterABSORPTION, array_waterABSORPTION, num);
468 
469  //cout<<"Water Material Properties:"<<endl;
470  //waterMPT->DumpTable();
471 
472  Water->SetMaterialPropertiesTable(waterMPT);
473 
474  delete[] array_ppWATER;
475  delete[] array_waterRINDEX;
476  delete[] array_ppwaterABSORPTION;
477  delete[] array_waterABSORPTION;
478  return;
479 }
480 
482 {
483  // Vacuum
484  //-------
485  G4String name;
486  G4double a = 1.* g / mole;
487  G4double density = universe_mean_density;
488  G4int z;
489 
490  // ATTENTION: change from STP to avoid the warning...
491  Vacuum = new G4Material(name = "Vacuum", z = 1, a, density,
492  kStateUndefined, STP_Temperature,
493  STP_Pressure);
494  return;
495 }
496 
498 {
499  // Borosilicate glass (Pyrex) for the active pmt faces
500  //----------------------------------------------------
501  /*
502  NOTE : The "face" is actually an ellipsoidal surface
503  The active area (photocathode) covers 90% of it.
504  The refractive index is the same as the dome
505  refractive index. The absorption length is set
506  so that no photons propagate through the
507  photocathode.
508  */
509 
510  // from PDG:
511  // 80% SiO2 + 13% B2O2 + 7% Na2O
512  // by fractional mass?
513 
514  G4String name;
515  G4double density = 2.23*g/cm3;
516  G4int nel, natoms, ncomponents;
517 
518  if (Pyrex != NULL) {
519  delete SiO2;
520  delete B2O2;
521  delete Na2O;
522  delete Pyrex;
523  delete pmtfaceMPT;
524  }
525 
526  SiO2 = new G4Material(name = "SiO2", density, nel = 2);
527  SiO2->AddElement(elSi, natoms = 1);
528  SiO2->AddElement(elO, natoms = 2);
529 
530  B2O2 = new G4Material(name = "B2O2", density, nel = 2);
531  B2O2->AddElement(elB, natoms = 2);
532  B2O2->AddElement(elO, natoms = 2);
533 
534  Na2O = new G4Material(name = "Na2O", density, nel = 2);
535  Na2O->AddElement(elNa, natoms = 2);
536  Na2O->AddElement(elO, natoms = 1);
537 
538  Pyrex = new G4Material(name = "Pyrex", density, ncomponents = 3);
539  Pyrex->AddMaterial(SiO2, 0.80);
540  Pyrex->AddMaterial(B2O2, 0.13);
541  Pyrex->AddMaterial(Na2O, 0.07);
542 
543  // Fill material properties table for pmt face
544 
545  pmtfaceMPT = new G4MaterialPropertiesTable();
546 
547  // pmt face rindex
548 
549  int index;
550  int num = fPmtfaceRINDEX.GetNPoints();
551 
552  double* array_pmtfaceRINDEX_PP = new double[num+1];
553  double* array_pmtfaceRINDEX = new double[num+1];
554 
555  // debug
556  //fout<<"PMT face rindex:"<<endl;
557 
558  for ( index = 0; index < num; index++ )
559  {
560  array_pmtfaceRINDEX_PP[index] = fPmtfaceRINDEX[index].X();
561  array_pmtfaceRINDEX[index] = fPmtfaceRINDEX[index].Y();
562  }
563 
564  pmtfaceMPT->AddProperty("RINDEX", array_pmtfaceRINDEX_PP, array_pmtfaceRINDEX, num);
565 
566  // Fill and add pmt face absorption length
567 
569 
570  double* array_pmtfaceABSORPTION_PP = new double[num+1];
571  double* array_pmtfaceABSORPTION = new double[num+1];
572 
573  // debug
574  //fout<<"PMT face abs. length:"<<endl;
575 
576  for ( index = 0; index < num; index++ )
577  {
578  // debug
579  //fout<< fPmtfaceABSORPTION[index].X() <<" "<< fPmtfaceABSORPTION[index].Y() <<endl;
580 
581  array_pmtfaceABSORPTION_PP[index] = fPmtfaceABSORPTION[index].X();
582  array_pmtfaceABSORPTION[index] = fPmtfaceABSORPTION[index].Y();
583  }
584 
585  pmtfaceMPT->AddProperty("ABSLENGTH", array_pmtfaceABSORPTION_PP, array_pmtfaceABSORPTION, num);
586 
587 
588  //cout<<"PMT Face Material Properties:"<<endl;
589  //pmtfaceMPT->DumpTable();
590 
591  Pyrex->SetMaterialPropertiesTable(pmtfaceMPT);
592 
593  delete[] array_pmtfaceRINDEX_PP;
594  delete[] array_pmtfaceRINDEX;
595  delete[] array_pmtfaceABSORPTION_PP;
596  delete[] array_pmtfaceABSORPTION;
597  return;
598 }
599 
601 {
602  // Borosilicate glass (Pyrex1) for the inactive part of the pmt faces
603  //-------------------------------------------------------------------
604  /*
605  NOTE : The inactive part of the "face" is about 10% of
606  the total ellipsoidal surface seen by the photons.
607  The refractive index is the same as the dome
608  refractive index. The absorption length is set
609  so that photons can propagate through this part.
610  To simplify things we use the same absorption length
611  as for the dome.
612  */
613 
614  G4String name;
615  G4double density = 2.23 * g / cm3;
616  G4int nel, natoms;
617 
618  if (Pyrex1 != NULL) {
619  delete SiO2;
620  delete B2O2;
621  delete Na2O;
622  delete Pyrex1;
623  delete pmtfaceMPT1;
624  }
625  SiO2 = new G4Material(name = "SiO2", density, nel = 2);
626  SiO2->AddElement(elSi, natoms = 1);
627  SiO2->AddElement(elO, natoms = 2);
628 
629  B2O2 = new G4Material(name = "B2O2", density, nel = 2);
630  B2O2->AddElement(elB, natoms = 2);
631  B2O2->AddElement(elO, natoms = 2);
632 
633  Na2O = new G4Material(name = "Na2O", density, nel = 2);
634  Na2O->AddElement(elNa, natoms = 2);
635  Na2O->AddElement(elO, natoms = 1);
636 
637  int ncomponents;
638  Pyrex1 = new G4Material(name = "Pyrex1", density, ncomponents = 3);
639  Pyrex1->AddMaterial(SiO2, 0.80);
640  Pyrex1->AddMaterial(B2O2, 0.13);
641  Pyrex1->AddMaterial(Na2O, 0.07);
642 
643  pmtfaceMPT1 = new G4MaterialPropertiesTable();
644 
645  // Fill material properties table for non sensitive pmt face
646 
647  // non-sensitive pmt face rindex = sensitive pmt face rindex
648 
649  int index;
650  int num = fPmtfaceRINDEX.GetNPoints();
651 
652  double* array_pmtface1RINDEX_PP = new double[num+1];
653  double* array_pmtface1RINDEX = new double[num+1];
654 
655  for ( index = 0; index < num; index++ )
656  {
657  array_pmtface1RINDEX_PP[index] = fPmtfaceRINDEX[index].X();
658  array_pmtface1RINDEX[index] = fPmtfaceRINDEX[index].Y();
659  }
660 
661  pmtfaceMPT1->AddProperty("RINDEX", array_pmtface1RINDEX_PP, array_pmtface1RINDEX, num);
662 
663 
664  // Fill and add non-sensitive pmt face absorption length = dome absorption length
665 
667 
668  double* array_pmtface1ABSORPTION_PP = new double[num+1];
669  double* array_pmtface1ABSORPTION = new double[num+1];
670 
671  for ( index = 0; index < num; index++ )
672  {
673  array_pmtface1ABSORPTION_PP[index] = fPmtdomeABSORPTION[index].X();
674  array_pmtface1ABSORPTION[index] = fPmtdomeABSORPTION[index].Y();
675  }
676 
677  pmtfaceMPT1->AddProperty("ABSLENGTH", array_pmtface1ABSORPTION_PP, array_pmtface1ABSORPTION, num);
678 
679  Pyrex1->SetMaterialPropertiesTable(pmtfaceMPT1);
680 
681  delete[] array_pmtface1RINDEX_PP;
682  delete[] array_pmtface1RINDEX;
683  delete[] array_pmtface1ABSORPTION_PP;
684  delete[] array_pmtface1ABSORPTION;
685  return;
686 }
687 
689 {
690  // Lucite (for the pmt domes)
691  G4double density = 1.20*g/cm3;
692  G4String name;
693  G4int nel, natoms;
694 
695  if (Lucite != NULL) {
696  delete CH3;
697  delete CH2;
698  delete C;
699  delete CO2;
700  delete Lucite;
701  delete pmtdomeMPT;
702  }
703 
704  CH3 = new G4Material(name = "CH3", density, nel = 2);
705  CH3->AddElement(elC, natoms = 1);
706  CH3->AddElement(elH, natoms = 3);
707 
708  CH2 = new G4Material(name = "CH2", density, nel = 2);
709  CH2->AddElement(elC, natoms = 1);
710  CH2->AddElement(elH, natoms = 2);
711 
712  C = new G4Material(name = "C", density, nel = 1);
713  C->AddElement(elC, natoms = 1);
714 
715  CO2 = new G4Material(name = "CO2", density, nel = 2);
716  CO2->AddElement(elC, natoms = 1);
717  CO2->AddElement(elO, natoms = 2);
718 
719  /*
720  NOTE : Do not know the fractional mass comp.
721  of lucite, only the molecular composition.
722  Perhaps it is a standard material defined in g4.
723  for now define by number of atoms.
724  It really doesn't matter at this point
725  anyway, since we are more concerned about
726  the optical properties.
727  */
728 
729  Lucite = new G4Material(name="Lucite", density, nel=3);
730  Lucite->AddElement(elC, natoms=4);
731  Lucite->AddElement(elH, natoms=8);
732  Lucite->AddElement(elO, natoms=2);
733 
734  pmtdomeMPT = new G4MaterialPropertiesTable();
735 
736  // pmt dome rindex
737 
738  int index;
739  int num = fPmtdomeRINDEX.GetNPoints();
740 
741  double *array_pmtdomeRINDEX_PP = new double[num+1];
742  double *array_pmtdomeRINDEX = new double[num+1];
743 
744  for ( index = 0; index < num; index++ )
745  {
746  array_pmtdomeRINDEX_PP[index] = fPmtdomeRINDEX[index].X();
747  array_pmtdomeRINDEX[index] = fPmtdomeRINDEX[index].Y();
748  }
749 
750  pmtdomeMPT->AddProperty("RINDEX", array_pmtdomeRINDEX_PP, array_pmtdomeRINDEX, num);
751 
752  // pmt dome absorption length
753 
755 
756  double *array_pmtdomeABSORPTION_PP = new double[num+1];
757  double *array_pmtdomeABSORPTION = new double[num+1];
758 
759  for ( index = 0; index < num; index++ )
760  {
761  array_pmtdomeABSORPTION_PP[index] = fPmtdomeABSORPTION[index].X();
762  array_pmtdomeABSORPTION[index] = fPmtdomeABSORPTION[index].Y();
763  }
764 
765  pmtdomeMPT->AddProperty("ABSLENGTH", array_pmtdomeABSORPTION_PP, array_pmtdomeABSORPTION, num);
766 
767  //cout<<"PMT Dome Material Properties:"<<endl;
768  //pmtdomeMPT->DumpTable();
769 
770  Lucite->SetMaterialPropertiesTable(pmtdomeMPT);
771 
772  delete[] array_pmtdomeRINDEX_PP;
773  delete[] array_pmtdomeRINDEX;
774  delete[] array_pmtdomeABSORPTION_PP;
775  delete[] array_pmtdomeABSORPTION;
776  return;
777 }
778 
780 {
781  // Interface for production tanks is Wacker SilGel 612 (Registered trademark
782  // of Wacker Group
783  G4String name;
784  G4int nel, natoms;
785  G4double density = 0.97*g/cm3; // guess - not explicitly set by Troy
786 
787  if (Interface != NULL) {
788  delete Interface;
789  delete interfaceMPT;
790  }
791  Interface = new G4Material(name = "Interface", density, nel = 3);
792  Interface->AddElement(elC, natoms = 4);
793  Interface->AddElement(elH, natoms = 8);
794  Interface->AddElement(elO, natoms = 2);
795 
796  interfaceMPT = new G4MaterialPropertiesTable();
797 
798  // interface rindex
799 
800  int index;
801  int num = fInterfaceRINDEX.GetNPoints();
802 
803  double* array_interfaceRINDEX_PP = new double[num+1];
804  double* array_interfaceRINDEX = new double[num+1];
805 
806  for ( index = 0; index < num; index++ )
807  {
808  array_interfaceRINDEX_PP[index] = fInterfaceRINDEX[index].X();
809  array_interfaceRINDEX[index] = fInterfaceRINDEX[index].Y();
810  }
811 
812  interfaceMPT->AddProperty("RINDEX", array_interfaceRINDEX_PP, array_interfaceRINDEX, num);
813 
814  // interface abs. length
815 
817 
818  double* array_interfaceABSORPTION_PP = new double[num+1];
819  double* array_interfaceABSORPTION = new double[num+1];
820 
821  for ( index = 0; index < num; index++ )
822  {
823  array_interfaceABSORPTION_PP[index] = fInterfaceABSORPTION[index].X();
824  array_interfaceABSORPTION[index] = fInterfaceABSORPTION[index].Y();
825  }
826 
827  interfaceMPT->AddProperty("ABSLENGTH", array_interfaceABSORPTION_PP, array_interfaceABSORPTION, num);
828 
829  //cout<<"Interface Material Properties:"<<endl;
830  //interfaceMPT->DumpTable();
831 
832  Interface->SetMaterialPropertiesTable(interfaceMPT);
833 
834  delete[] array_interfaceRINDEX_PP;
835  delete[] array_interfaceRINDEX;
836  delete[] array_interfaceABSORPTION_PP;
837  delete[] array_interfaceABSORPTION;
838  return;
839 }
841 {
842 
843  // HDPE (for tank walls)
844  //----------------------
845 
846  G4double density = 0.94*g/cm3;
847  G4int nel, natoms;
848  G4String name;
849  vector<double>::iterator It;
850 
851  if (HDPE != NULL) {
852  delete HDPE;
853  delete linerMPT;
854  }
855 
856  HDPE = new G4Material(name = "HDPE", density, nel = 2);
857  HDPE->AddElement(elC, natoms = 2);
858  HDPE->AddElement(elH, natoms = 4);
859 
860  linerMPT = new G4MaterialPropertiesTable();
861 
862  // liner abs. length
863 
864  int index;
865  int num = fLinerABSORPTION.GetNPoints();
866 
867  double* array_linerABSORPTION_PP = new double[num+1];
868  double* array_linerABSORPTION = new double[num+1];
869 
870  for ( index = 0; index < num; index++ )
871  {
872  array_linerABSORPTION_PP[index] = fLinerABSORPTION[index].X();
873  array_linerABSORPTION[index] = fLinerABSORPTION[index].Y();
874  }
875 
876  linerMPT->AddProperty("ABSLENGTH", array_linerABSORPTION_PP, array_linerABSORPTION, num);
877 
878  //cout<<"Liner Material Properties:"<<endl;
879  //linerMPT->DumpTable();
880 
881  HDPE->SetMaterialPropertiesTable(linerMPT);
882 
883  delete[] array_linerABSORPTION_PP;
884  delete[] array_linerABSORPTION;
885  return;
886 }
887 
889 {
890  // Optical surface properties
891  //---------------------------
892 
893 
894  // Define the optical model and set optical properties of the surfaces
895  //--------------------------------------------------------------------
896 
897  /*
898  Note that diffuse reflection is implicitly defined, since:
899  SPECULARSPIKECONSTANT+SPECULARLOBECONSTANT+BACKSCATTERCONSTANT=
900  1-DIFFUSEL0BECONSTANT
901  Set index of refraction on the small dielectric interface to 0 so that
902  all the light will undergo total internal reflection (or absorption).
903  It is done in this weird way because the only surface that works (at the
904  moment) for the unified model is the ground surface, and for such a
905  surface a transmission coefficient is always calculated if total internal
906  reflection does not occur. Thus, the only way to ensure all the
907  (non-absorbed) light is reflected back is to choose groundbackpainted
908  finish with the index of refraction for the thin dielectric material
909  set to 0. Note that groundbackpainted with some other index of
910  refraction doesn't work because light reflected off the back (painted)
911  surface undergoes only Lambertian reflection.. This will be fixed up
912  in the future..
913  */
914 
915  if (linerOpticalMPT != NULL) delete linerOpticalMPT;
916  linerOpticalMPT = new G4MaterialPropertiesTable();
917 
918  int index;
920  double* array_linerSPECULARLOBECONSTANT_PP = new double[num+1];
921  double* array_linerSPECULARLOBECONSTANT = new double[num+1];
922 
923  for ( index = 0; index < num; index++ )
924  {
925  array_linerSPECULARLOBECONSTANT_PP[index] = fLinerSPECULARLOBECONSTANT[index].X();
926  array_linerSPECULARLOBECONSTANT[index] = fLinerSPECULARLOBECONSTANT[index].Y();
927  }
928 
929  linerOpticalMPT->AddProperty("SPECULARLOBECONSTANT",
930  array_linerSPECULARLOBECONSTANT_PP,
931  array_linerSPECULARLOBECONSTANT, num);
932 
933 
935  double* array_linerSPECULARSPIKECONSTANT_PP = new double[num+1];
936  double* array_linerSPECULARSPIKECONSTANT = new double[num+1];
937 
938  for ( index = 0; index < num; index++ )
939  {
940  array_linerSPECULARSPIKECONSTANT_PP[index] = fLinerSPECULARSPIKECONSTANT[index].X();
941  array_linerSPECULARSPIKECONSTANT[index] = fLinerSPECULARSPIKECONSTANT[index].Y();
942  }
943 
944  linerOpticalMPT->AddProperty("SPECULARSPIKECONSTANT",
945  array_linerSPECULARSPIKECONSTANT_PP,
946  array_linerSPECULARSPIKECONSTANT, num);
947 
948 
950  double* array_linerREFLECTIVITY_PP = new double[num+1];
951  double* array_linerREFLECTIVITY = new double[num+1];
952 
953  for ( index = 0; index < num; index++ )
954  {
955  array_linerREFLECTIVITY_PP[index] = fLinerREFLECTIVITY[index].X();
956  array_linerREFLECTIVITY[index] = fLinerREFLECTIVITY[index].Y();
957  }
958 
959 
960  linerOpticalMPT->AddProperty("REFLECTIVITY",
961  array_linerREFLECTIVITY_PP,
962  array_linerREFLECTIVITY, num);
963 
964 
966  double* array_linerBACKSCATTERCONSTANT_PP = new double[num+1];
967  double* array_linerBACKSCATTERCONSTANT = new double[num+1];
968 
969  for ( index = 0; index < num; index++ )
970  {
971  array_linerBACKSCATTERCONSTANT_PP[index] = fLinerBACKSCATTERCONSTANT[index].X();
972  array_linerBACKSCATTERCONSTANT[index] = fLinerBACKSCATTERCONSTANT[index].Y();
973  }
974 
975  linerOpticalMPT->AddProperty("BACKSCATTERCONSTANT",
976  array_linerBACKSCATTERCONSTANT_PP,
977  array_linerBACKSCATTERCONSTANT, num);
978 
980  double* array_TYVEK_RINDEX_PP = new double[num+1];
981  double* array_TYVEK_RINDEX = new double[num+1];
982 
983  for ( index = 0; index < num; index++ )
984  {
985  array_TYVEK_RINDEX_PP[index] = fLinerTYVEK_RINDEX[index].X();
986  array_TYVEK_RINDEX[index] = fLinerTYVEK_RINDEX[index].Y();
987  }
988 
989  //cout<<"Liner Optical Properties:"<<endl;
990  //linerOpticalMPT->DumpTable();
991  linerOpticalMPT->AddProperty("RINDEX",
992  array_TYVEK_RINDEX_PP,
993  array_TYVEK_RINDEX, num);
994 
995  OpLinerSurface = new G4OpticalSurface("WallSurface");
996 
997  OpLinerSurface->SetModel(unified);
998  OpLinerSurface->SetType(dielectric_dielectric);
999  OpLinerSurface->SetFinish(groundbackpainted);
1000  OpLinerSurface->SetSigmaAlpha(fSIGMA_ALPHA);
1001 
1002  OpLinerSurface->SetMaterialPropertiesTable(linerOpticalMPT);
1003 
1004  delete[] array_linerSPECULARLOBECONSTANT_PP;
1005  delete[] array_linerSPECULARLOBECONSTANT;
1006 
1007  delete[] array_linerSPECULARSPIKECONSTANT_PP;
1008  delete[] array_linerSPECULARSPIKECONSTANT;
1009 
1010  delete[] array_linerREFLECTIVITY_PP;
1011  delete[] array_linerREFLECTIVITY;
1012 
1013  delete[] array_linerBACKSCATTERCONSTANT_PP;
1014  delete[] array_linerBACKSCATTERCONSTANT;
1015 
1016  delete[] array_TYVEK_RINDEX_PP;
1017  delete[] array_TYVEK_RINDEX;
1018 
1019  return;
1020 
1021 }
1022 
1023 
1025 {
1026  // Aluminum for electronics boxes and (possibly) solar panel
1027  //----------------------------------------------------------
1028 
1029  G4double density = 2.700*g/cm3;
1030  G4double a = 29.98*g/mole;
1031  G4String name;
1032  G4int z;
1033  Al = new G4Material(name = "Aluminum", z = 13, a, density);
1034  return;
1035 }
1036 
1038 {
1039  // Dirt for the ground
1040  //--------------------
1041  G4String name;
1042  G4int ncomponents;
1043  double fractionmass;
1044  G4double density = 1.2 * g / cm3;
1045  Dirt = new G4Material(name = "Dirt", density, ncomponents = 4);
1046  Dirt->AddElement(elO, fractionmass = 51.0*perCent);
1047  Dirt->AddElement(elSi, fractionmass = 35.2*perCent);
1048  Dirt->AddElement(elAl, fractionmass = 8.2*perCent);
1049  Dirt->AddElement(elFe, fractionmass = 5.6*perCent);
1050 }
1051 
1052 
1053 
1055 {
1056 
1057  G4String name;
1058  G4double density = 1.06*g/cm3;
1059  G4int nel;
1060 
1061  if (Polystyrene != NULL) {
1062  delete Polystyrene;
1063  }
1064 
1065  Polystyrene = new G4Material(name = "Polystyrene", density, nel = 2);
1066  Polystyrene->AddElement(elH, 1);
1067  Polystyrene->AddElement(elC, 1);
1068 
1069 }
1070 
1071 void G4TankConstruction::CreatePlastic(void) // To be changed to PVC
1072 {
1073 
1074  G4String name;
1075  G4double density = 0.7*g/cm3;
1076  G4int nel;
1077 
1078  if (Plastic != NULL) {
1079  delete Plastic;
1080  }
1081 
1082  Plastic = new G4Material(name = "Plastic", density, nel = 2);
1083  Plastic->AddElement(elH, 1);
1084  Plastic->AddElement(elC, 1);
1085 
1086 }
1087 
1089 {
1090  if (theIron!=NULL){
1091  delete theIron;
1092  }
1093  G4double density = 7.800*g/cm3;
1094  G4double a = 55.845*g/mole;
1095  G4String name;
1096  G4int z;
1097  theIron = new G4Material(name = "Iron", z = 26, a, density);
1098  return;
1099 }
1100 
1102 {
1103  G4double top_TankThickness = (fTankThickness/2);
1104  G4double fGroundThickness = fExpHall_z/4; // arbitrary but probably okay
1105 
1106  expHall_box = new G4Box("World", fExpHall_x, fExpHall_y, fExpHall_z);
1107  ground_solid = new G4Tubs("ground_solid", 0, fExpHall_x, fGroundThickness,
1108  0.0*deg, 360.0*deg);
1109  tank_solid = new G4Tubs("tank_solid", 0.0*m, fTankRadius, fTankHalfHeight,
1110  0.0*deg, 360.0*deg);
1111  top_solid = new G4Tubs("top_solid",
1112  0.0*m, fTankRadius + fTankThickness, top_TankThickness,
1113  0.0*deg, 360.0*deg);
1114  side_solid = new G4Tubs("side_solid",
1116  0.0*deg, 360.0*deg);
1117 
1118  inner_solid = new G4Ellipsoid("inner_solid", fPmtRmin, fPmtRmin, fPmtRzmin, -fPmtRzmin, 0.);
1119 
1120  // Active photocathode covered area
1121  pmt_aux = new G4Ellipsoid("pmt_aux", fPmtRmax, fPmtRmax, fPmtRzmax, -fPmtRzmax, -fHeightz);
1122 
1123  pmt_solid = new G4SubtractionSolid("pmt_solid", pmt_aux, inner_solid);
1124  pmt_aux1 = new G4Ellipsoid("pmt_aux1", fPmtRmax, fPmtRmax, fPmtRzmax, -fHeightz, 0.);
1125  pmt_solid1 = new G4SubtractionSolid("pmt_solid1", pmt_aux1, inner_solid);
1126 
1127  interface_in_aux = new G4Ellipsoid("interface_in_aux", fInterfaceRmin, fInterfaceRmin,
1129  interface_out_aux = new G4Ellipsoid("interface_out_aux", fInterfaceRmax, fInterfaceRmax,
1131  interface_solid = new G4SubtractionSolid("interface_solid", interface_out_aux, interface_in_aux);
1132  dome_in_aux = new G4Ellipsoid("dome_in_aux", fDomeRmin, fDomeRmin, fDomeRzmin, -fDomeRzmin, 0.);
1133  dome_out_aux = new G4Ellipsoid("dome_out_aux", fDomeRmax, fDomeRmax, fDomeRzmax, -fDomeRzmax, 0.0*cm);
1134  dome_solid = new G4SubtractionSolid("dome_solid", dome_out_aux, dome_in_aux);
1135 
1136  return;
1137 }
1138 
1140 {
1141  // Experimental hall
1142  //------------------
1143 
1144  expHall_log = new G4LogicalVolume(expHall_box, Air, "World", 0, 0, 0);
1145 
1146  expHall_phys = new G4PVPlacement(0, G4ThreeVector(), "World", expHall_log, 0,
1147  false, 0);
1148 
1149  expHall_log->SetVisAttributes(G4VisAttributes::Invisible);
1150 
1151  // Ground around the detector
1152  // --------------------------
1153 
1154  if (fGroundEnable)
1155  {
1156  double fGroundThickness = fExpHall_z/4; // arbitrary but probably okay
1157 
1158  ground_log = new G4LogicalVolume(ground_solid, Dirt, "ground_solid");
1159 
1160  ground_phys = new G4PVPlacement(0,
1161  G4ThreeVector(0, 0,- fGroundThickness),
1162  "ground", ground_log, expHall_phys, false, 0);
1163  }
1164  return;
1165 }
1166 
1168 {
1169  G4SDManager *SDMan = G4SDManager::GetSDMpointer();
1170  G4String SDName;
1171 
1172  // Water tank
1173  //-----------
1174 
1175  tank_log = new G4LogicalVolume(tank_solid, Water, "tank_log", 0, 0, 0);
1176 
1177  tank_phys = new G4PVPlacement(0, G4ThreeVector(fTankPos_x, fTankPos_y, fTankPos_z +
1179  "tank", tank_log, expHall_phys, false, 0);
1180 
1181  // Top, bottom, side walls
1182  //------------------------
1183 
1184  top_log = new G4LogicalVolume(top_solid, HDPE, "top_log", 0, 0, 0);
1185  bottom_log = new G4LogicalVolume(top_solid, HDPE, "bottom_log", 0, 0, 0);
1186  side_log = new G4LogicalVolume(side_solid, HDPE, "side_log", 0, 0, 0);
1187 
1188  top_phys = new G4PVPlacement(0, G4ThreeVector(fTankPos_x, fTankPos_y,
1189  fTankPos_z + 2.*fTankHalfHeight +
1190  (fTankThickness)/2.0 + fTankThickness),
1191  "top", top_log, expHall_phys, false, 0);
1192  bottom_phys = new G4PVPlacement(0,G4ThreeVector(fTankPos_x, fTankPos_y,
1194  "bottom", bottom_log, expHall_phys, false, 0);
1195  side_phys = new G4PVPlacement(0,G4ThreeVector(fTankPos_x, fTankPos_y, fTankPos_z +
1197  "side", side_log, expHall_phys, false, 0);
1198 
1199  //the tank liner
1200  topsurface =
1201  new G4LogicalBorderSurface("topsurface", tank_phys, top_phys,
1202  OpLinerSurface);
1203  bottomsurface =
1204  new G4LogicalBorderSurface("bottomsurface", tank_phys, bottom_phys,
1205  OpLinerSurface);
1206  sidesurface =
1207  new G4LogicalBorderSurface("sidesurface", tank_phys, side_phys,
1208  OpLinerSurface);
1209 
1210  // PMTs and such
1211  //--------------
1212  // the interior volume of the pmt
1213 
1214  // Half the tank's height is used for the z-coordinate since the PMT volumes
1215  // are placed in the logical volume of the water, not the world volume
1216  double dome1_x = fPmt1.GetX(fPmt1.GetCoordinateSystem())*m;
1217  double dome1_y = fPmt1.GetY(fPmt1.GetCoordinateSystem())*m;
1218  double dome1_z = fTankHalfHeight;
1219 
1220  double dome2_x = fPmt2.GetX(fPmt2.GetCoordinateSystem())*m;
1221  double dome2_y = fPmt2.GetY(fPmt2.GetCoordinateSystem())*m;
1222  double dome2_z = fTankHalfHeight;
1223 
1224  double dome3_x = fPmt3.GetX(fPmt3.GetCoordinateSystem())*m;
1225  double dome3_y = fPmt3.GetY(fPmt3.GetCoordinateSystem())*m;
1226  double dome3_z = fTankHalfHeight;
1227 
1228  inner_log = new G4LogicalVolume(inner_solid, Vacuum, "inner_log", 0, 0, 0);
1229 
1230  inner1_phys = new G4PVPlacement(0,
1231  G4ThreeVector(dome1_x, dome1_y, dome1_z), inner_log,
1232  "inner1", tank_log, false, 0);
1233  inner2_phys = new G4PVPlacement(0,
1234  G4ThreeVector(dome2_x, dome2_y, dome2_z), inner_log,
1235  "inner2", tank_log, false, 0);
1236  inner3_phys = new G4PVPlacement(0,
1237  G4ThreeVector(dome3_x, dome3_y, dome3_z), inner_log,
1238  "inner3", tank_log, false, 0);
1239  /*
1240  Why 3 different logical volumes?
1241  because the sensitive detectors are registered
1242  by logical volume
1243  */
1244 
1245  // Sensitive surface of pmt faces
1246 
1247  pmt1_log = new G4LogicalVolume(pmt_solid, Pyrex, "pmt1_log", 0, 0, 0);
1248  pmt2_log = new G4LogicalVolume(pmt_solid, Pyrex, "pmt2_log", 0, 0, 0);
1249  pmt3_log = new G4LogicalVolume(pmt_solid, Pyrex, "pmt3_log", 0, 0, 0);
1250 
1251  pmt1_phys = new G4PVPlacement(0, G4ThreeVector(dome1_x, dome1_y, dome1_z),
1252  pmt1_log,"pmt1", tank_log, false, 0);
1253  pmt2_phys = new G4PVPlacement(0, G4ThreeVector(dome2_x, dome2_y, dome2_z),
1254  pmt2_log,"pmt2", tank_log, false, 0);
1255  pmt3_phys = new G4PVPlacement(0, G4ThreeVector(dome3_x, dome3_y, dome3_z),
1256  pmt3_log,"pmt3", tank_log, false, 0);
1257 
1258  // Non-sensitive surface of pmt faces
1259 
1260  pmt1_log1 = new G4LogicalVolume(pmt_solid1, Pyrex1, "pmt1_log1", 0, 0, 0);
1261  pmt2_log1 = new G4LogicalVolume(pmt_solid1, Pyrex1, "pmt2_log1", 0, 0, 0);
1262  pmt3_log1 = new G4LogicalVolume(pmt_solid1, Pyrex1, "pmt3_log1", 0, 0, 0);
1263 
1264  pmt1_phys1 = new G4PVPlacement(0, G4ThreeVector(dome1_x, dome1_y, dome1_z),
1265  pmt1_log1,"pmt11", tank_log, false, 0);
1266  pmt2_phys1 = new G4PVPlacement(0, G4ThreeVector(dome2_x, dome2_y, dome2_z),
1267  pmt2_log1,"pmt21", tank_log, false, 0);
1268  pmt3_phys1 = new G4PVPlacement(0, G4ThreeVector(dome3_x, dome3_y, dome3_z),
1269  pmt3_log1,"pmt31", tank_log, false, 0);
1270 
1271  // The dome/face interface
1272 
1273  interface1_log = new G4LogicalVolume(interface_solid, Interface, "interface1_log",
1274  0, 0, 0);
1275  interface2_log = new G4LogicalVolume(interface_solid, Interface, "interface2_log",
1276  0, 0, 0);
1277  interface3_log = new G4LogicalVolume(interface_solid, Interface, "interface3_log",
1278  0, 0, 0);
1279 
1280  interface1_phys = new G4PVPlacement(0, G4ThreeVector(dome1_x, dome1_y, dome1_z),
1281  interface1_log,"interface1", tank_log, false, 0);
1282  interface2_phys = new G4PVPlacement(0, G4ThreeVector(dome2_x, dome2_y, dome2_z),
1283  interface2_log,"interface2", tank_log, false, 0);
1284  interface3_phys = new G4PVPlacement(0, G4ThreeVector(dome3_x, dome3_y, dome3_z),
1285  interface3_log,"interface3", tank_log, false, 0);
1286 
1287  // PMT domes
1288  dome1_log = new G4LogicalVolume(dome_solid, Lucite, "dome1_log", 0, 0, 0);
1289  dome2_log = new G4LogicalVolume(dome_solid, Lucite, "dome2_log", 0, 0, 0);
1290  dome3_log = new G4LogicalVolume(dome_solid, Lucite, "dome3_log", 0, 0, 0);
1291 
1292  dome1_phys = new G4PVPlacement(0, G4ThreeVector(dome1_x, dome1_y, dome1_z),
1293  dome1_log, "dome1", tank_log, false, 0);
1294  dome2_phys = new G4PVPlacement(0, G4ThreeVector(dome2_x, dome2_y, dome2_z),
1295  dome2_log, "dome2", tank_log, false, 0);
1296  dome3_phys = new G4PVPlacement(0, G4ThreeVector(dome3_x, dome3_y, dome3_z),
1297  dome3_log, "dome3", tank_log, false, 0);
1298 
1299  // Register the PMT's as sensitive detectors
1300  /*
1301  Note that each PMT must be given a unique index. If programmer
1302  screws up and gives the same index to 2 (or more) PMT's
1303  then photoelectrons will be double counted in that PMT.
1304  Perhaps there is a better way to do this.
1305  */
1306 
1307  SDName = "/Tank/pmt1";
1308  G4TankPMTAction *PMT1SD = new G4TankPMTAction(SDName, 1);
1309 
1310  SDName= "/Tank/pmt2";
1311  G4TankPMTAction *PMT2SD = new G4TankPMTAction(SDName, 2);
1312 
1313  SDName= "/Tank/pmt3";
1314  G4TankPMTAction *PMT3SD = new G4TankPMTAction(SDName, 3);
1315 
1316  SDMan->AddNewDetector(PMT1SD);
1317  SDMan->AddNewDetector(PMT2SD);
1318  SDMan->AddNewDetector(PMT3SD);
1319 
1320  pmt1_log->SetSensitiveDetector(PMT1SD);
1321  pmt2_log->SetSensitiveDetector(PMT2SD);
1322  pmt3_log->SetSensitiveDetector(PMT3SD);
1323 
1324 
1325  // Solar panel
1326  // -----------
1327 
1328  if (fSolarPanelEnable)
1329  {
1330  solarPanel_solid = new G4Box("SolarPanel", fSolarPanelThickness/2, fSolarPanelWidth/2,
1331  fSolarPanelLength/2);
1332 
1333  solarPanel_log = new G4LogicalVolume(solarPanel_solid,
1334  Al, // ** MAY BE CHANGED
1335  "solarPanel_log");
1336  G4RotationMatrix *solarPanelRot = new G4RotationMatrix();
1337  solarPanelRot->rotate(M_PI/2, G4ThreeVector(0, 0, 1));
1338  solarPanelRot->rotate(fSolarPanelTiltAngle, G4ThreeVector(0, 1, 0));
1339 
1340  solarPanel_phys = new G4PVPlacement(solarPanelRot,
1341  G4ThreeVector(fSolarPanelX, fSolarPanelY,
1342  fSolarPanelZ),
1343  "solarPanel",solarPanel_log, expHall_phys,
1344  false, 0);
1345  }
1346 
1347  // Chunk of Aluminum representing electronics box
1348  //-----------------------------------------------
1349 
1350  if (fElecBoxEnable)
1351  {
1352  elecBox_solid = new G4Box("ElecBox", fElecBoxThickness/2, fElecBoxWidth/2,
1353  fElecBoxLength/2);
1354 
1355  elecBox_log = new G4LogicalVolume(elecBox_solid,
1356  Al, // ** MAY BE CHANGED
1357  "elecBox_log");
1358  G4RotationMatrix *elecBoxRot = new G4RotationMatrix();
1359  elecBoxRot->rotate(M_PI/2, G4ThreeVector(0, 0, 1));
1360  elecBoxRot->rotate(fElecBoxTiltAngle, G4ThreeVector(0, 1, 0));
1361 
1362  elecBox_phys = new G4PVPlacement(elecBoxRot,
1363  G4ThreeVector(fElecBoxX, fElecBoxY, fElecBoxZ),
1364  "elecBox",elecBox_log, expHall_phys, false, 0);
1365  }
1366 
1367  // ASCII scintillator
1368  //-----------------------------------------------
1369  if ( fASCIIEnable )
1370  {
1375 
1376  fScinLength= 1800.*CLHEP::mm ;
1377  fScinWidth= 80*CLHEP::mm;
1378  fnScinBars= 27;
1379  fScinHeight= 10.*CLHEP::mm;
1380 
1381  fScinPos_x = 0.0*CLHEP::m;
1382  fScinPos_y = 0.0*CLHEP::m;
1383 
1384  double Width=double(fnScinBars)*fScinWidth;
1385 
1386  G4VPhysicalVolume *pMother=expHall_phys;
1387  double zPosScin= fScinHeightAboveGround ;
1388 
1389  // Enclosure (PVC)
1391  enclosure_log = new G4LogicalVolume(enclosure_solid, Plastic, "enclosure_log", 0, 0, 0);
1392  enclosure_phys = new G4PVPlacement(0, G4ThreeVector(fScinPos_x, fScinPos_y, zPosScin),
1393  "enclosure", enclosure_log,pMother, false, 0 );
1394 
1395 
1396  // Scintillator
1397  scin_solid= new G4Box("scin_solid",fScinLength/2,fScinWidth/2.,fScinHeight/2.);
1398  scin_log = new G4LogicalVolume(scin_solid, Polystyrene, "scin_log", 0, 0, 0);
1399  for (int ibar=0;ibar<fnScinBars;ibar++)
1400  {
1401  double Y=-Width/2.+fScinWidth*(double(ibar)+0.5);
1402  scin_phys = new G4PVPlacement(0, G4ThreeVector(0,Y,0),
1403  "scin", scin_log, enclosure_phys, true, ibar );
1404  }
1405 
1406  //Shield ( Above/Below enclosure for light tightness)
1407  shield_solid= new G4Box("shield_solid",fScinLength/2+fEnclosureThickness, Width/2.+fEnclosureThickness, fShieldThickness/2. );
1408  shield_log = new G4LogicalVolume(shield_solid, theIron, "shield_log", 0, 0, 0);
1409 
1410  for (int i=0;i<2;i++)
1411  {
1412  double sign=(i==0?1.:-1.);
1413  double zPos= zPosScin + sign*( fScinHeight/2. + fEnclosureThickness + fShieldThickness/2. );
1414  shield_phys[i] = new G4PVPlacement(0, G4ThreeVector(fScinPos_x, fScinPos_y, zPos ),
1415  (i==0?"shieldTop0":"shieldBot"), shield_log, pMother, true, i );
1416  }
1417 
1418  //Shield ( for air circulation)
1419  double zPos= zPosScin + fScinHeight/2. + fEnclosureThickness + fShieldThickness + fSpacerThickness + fShieldThickness/2. ;
1420  shield_phys[2] = new G4PVPlacement(0, G4ThreeVector(fScinPos_x, fScinPos_y, zPos ),
1421  "shieldTop1", shield_log, pMother, true, 2 );
1422 
1423  // Register scintillator bars as sensitive detectors
1424  G4String Name = "/Tank/ASCII_scin";
1425  G4ASCIIAction *ASCII_SCIN = new G4ASCIIAction(Name);
1426  SDMan->AddNewDetector(ASCII_SCIN);
1427  scin_log->SetSensitiveDetector(ASCII_SCIN);
1428 
1429  }
1430 
1431  return;
1432 }
1433 
1434 
1436 {
1437  SetDetectorParameters(); // updates G4TankConstruction data tables
1438 
1439  // clean up old geometry list
1440  G4GeometryManager::GetInstance()->OpenGeometry();
1441  G4PhysicalVolumeStore::GetInstance()->Clean();
1442  G4LogicalVolumeStore::GetInstance()->Clean();
1443  G4SolidStore::GetInstance()->Clean();
1444 
1445  // update material properties (deleting out of date materials and
1446  // replacing them with new ones).
1447  CreateWater();
1448  CreatePyrex();
1449  CreateLucite();
1450  CreateInterface();
1451  CreateHDPE();
1452  CreateLiner();
1453 
1455  CreateIron();
1456  CreatePlastic();
1457 
1458 
1459  // assemble objects with new sizes and materials
1460  G4RunManager::GetRunManager()->DefineWorldVolume(CreateTank(), true);
1461 }
const double eV
Definition: GalacticUnits.h:35
unsigned int GetNPoints() const
constexpr double mm
Definition: AugerUnits.h:113
constexpr double perCent
Definition: AugerUnits.h:282
Point object.
Definition: Point.h:32
const utl::TabulatedFunction & GetDomeRefractionIndex() const
Refraction index for the PMT dome.
constexpr double cm3
Definition: AugerUnits.h:119
Detector description interface for Station-related data.
ArrayIterator XEnd()
end of array of X
CoordinateSystemPtr GetCoordinateSystem() const
Get the coordinate system of the current internal representation.
Definition: BasicVector.h:234
Class to hold collection (x,y) points and provide interpolation between them.
const utl::TabulatedFunction & GetLinerSpecularLobe() const
Tyvek liner specular lobe constant as a function of photon energy.
const PMT & GetPMT(const int id) const
Get specified PMT by id.
void PushBack(const double x, const double y)
Branch GetChild(const std::string &childName) const
Get child of this Branch by child name.
Definition: Branch.cc:211
TransformerConstructor< DerivedCSPolicy > CoordinateSystem
The normal coordinate system type.
const utl::TabulatedFunction & GetWaterAbsorptionLength() const
Water absorption length as a function of photon energy.
Exception for reporting variable out of valid range.
constexpr double deg
Definition: AugerUnits.h:140
Class representing a document branch.
Definition: Branch.h:107
const utl::TabulatedFunction & GetLinerReflectivity() const
Tyvek liner reflectivity as a function of photon energy.
constexpr double mole
Definition: AugerUnits.h:262
double GetX(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:206
const utl::Point & GetPosition() const
PMT position.
double GetRadius() const
Radius of the tank (water only)
double GetHeight() const
Height of the tank (water only)
constexpr double g
Definition: AugerUnits.h:200
void GetData(bool &b) const
Overloads of the GetData member template function.
Definition: Branch.cc:644
const utl::TabulatedFunction & GetLinerSpecularSpike() const
Tyvek liner specular spike constant as a function of photon energy.
ArrayIterator YBegin()
begin of array of Y
double GetY(const CoordinateSystemPtr &coordinateSystem) const
Definition: BasicVector.h:209
ArrayIterator XBegin()
begin of array of X
double GetThickness() const
Thickness of the tank walls.
constexpr double cm
Definition: AugerUnits.h:117
const utl::TabulatedFunction & GetWaterRefractionIndex() const
Water refraction index as a function of photon energy.
std::string Name()
Definition: TypeId.h:35
Detector description interface for SDetector-related data.
Definition: SDetector.h:42
Main configuration utility.
Definition: CentralConfig.h:51
ArrayIterator YEnd()
end of array of Y
class that handles PMT hits
Definition: G4ASCIIAction.h:29
const utl::TabulatedFunction & GetFaceRefractionIndex() const
Refraction index for the PMT face.
double GetLinerSigmaAlpha() const
Tyvek liner sigma_alpha roughness parameter.
double Y(const double x) const
Get or interpolate the Y value that corresponds to parameter x.
#define ERROR(message)
Macro for logging error messages.
Definition: ErrorLogger.h:165
constexpr double m
Definition: AugerUnits.h:121
const utl::TabulatedFunction & GetRTVRefractionIndex() const
Refraction index for the interface between PMT face and dome (RTV)
utl::Branch GetTopBranch(const std::string &id)
Get top branch for moduleConfigLink with given id (XML files)

, generated on Tue Sep 26 2023.