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

, generated on Tue Sep 26 2023.