4 #include "HGCal/TBStandaloneSimulator/interface/DetectorConstruction.hh"
5 #include "HGCal/TBStandaloneSimulator/interface/DetectorMessenger.hh"
6 #include "HGCal/TBStandaloneSimulator/interface/HGCSSSimHit.hh"
9 #include "G4Material.hh"
10 #include "G4NistManager.hh"
11 #include "G4VSolid.hh"
14 #include "G4Polyhedra.hh"
15 #include "G4LogicalVolume.hh"
16 #include "G4PVPlacement.hh"
17 #include "G4PVReplica.hh"
18 #include "G4UniformMagField.hh"
19 #include "G4GeometryManager.hh"
20 #include "G4PhysicalVolumeStore.hh"
21 #include "G4LogicalVolumeStore.hh"
22 #include "G4SolidStore.hh"
23 #include "G4VisAttributes.hh"
24 #include "G4Colour.hh"
25 #include "G4PhysicalConstants.hh"
26 #include "G4SystemOfUnits.hh"
27 #include "G4FieldManager.hh"
28 #include "G4TransportationManager.hh"
29 #include "G4PhysicalConstants.hh"
34 DetectorConstruction::DetectorConstruction(
TBGeometry& geometry,
36 : m_geometry(geometry),
44 G4cout <<
"BEGIN(DetectorConstruction)" << G4endl;
46 vector<TBGeometry::Element> elements;
47 for(
size_t c = 0; c < m_geometry.size(); c++) {
49 if ( e.
imap[
"first"] ) elements.clear();
51 elements.push_back(e);
54 m_caloStruct.push_back( SamplingSection(elements) );
60 m_detectorMessenger =
new DetectorMessenger(
this);
62 G4cout <<
"END(DetectorConstruction)" << G4endl;
65 DetectorConstruction::~DetectorConstruction()
67 delete m_detectorMessenger;
71 void DetectorConstruction::DefineMaterials()
73 G4NistManager* nistManager = G4NistManager::Instance();
75 = nistManager->FindOrBuildMaterial(m_geometry.material(
"Abs"),
false);
76 m_materials[
"AbsHCAL"]
77 = nistManager->FindOrBuildMaterial(m_geometry.material(
"AbsHCAL"),
false);
78 m_materials[
"Al"] = nistManager->FindOrBuildMaterial(
"G4_Al",
false);
79 m_dEdx[
"Al"] = 0.4358;
80 m_materials[
"W"] = nistManager->FindOrBuildMaterial(
"G4_W",
false);
82 m_materials[
"Pb"] = nistManager->FindOrBuildMaterial(
"G4_Pb",
false);
84 m_materials[
"Cu"] = nistManager->FindOrBuildMaterial(
"G4_Cu",
false);
86 m_materials[
"Si"] = nistManager->FindOrBuildMaterial(
"G4_Si",
false);
87 m_dEdx[
"Si"] = 0.3876;
88 m_materials[
"Zn"] = nistManager->FindOrBuildMaterial(
"G4_Zn",
false);
90 m_materials[
"Air"] = nistManager->FindOrBuildMaterial(
"G4_AIR",
false);
92 m_materials[
"Fe"] = nistManager->FindOrBuildMaterial(
"G4_Fe",
false);
94 m_materials[
"Mn"] = nistManager->FindOrBuildMaterial(
"G4_Mn",
false);
95 m_dEdx[
"Mn"] = 1.062 ;
96 m_materials[
"C"] = nistManager->FindOrBuildMaterial(
"G4_C",
false);
98 m_materials[
"H"] = nistManager->FindOrBuildMaterial(
"G4_H",
false);
100 m_materials[
"Cl"] = nistManager->FindOrBuildMaterial(
"G4_Cl",
false);
102 m_materials[
"Cr"] = nistManager->FindOrBuildMaterial(
"G4_Cr",
false);
103 m_dEdx[
"Cr"] = 1.046;
104 m_materials[
"Ni"] = nistManager->FindOrBuildMaterial(
"G4_Ni",
false);
105 m_dEdx[
"Ni"] = 1.307;
111 G4Element* H =
new G4Element(
"Hydrogen",
"H", 1., 1.01*g/mole);
112 G4Element* C =
new G4Element(
"Carbon",
"C", 6., 12.01*g/mole);
113 G4Element* O =
new G4Element(
"Oxygen",
"O" , 8., 16.00*g/mole);
114 G4Element* Si =
new G4Element(
"Silicon",
"Si", 14.,28.09*g/mole);
116 m_materials[
"SiO2"] =
new G4Material(
"SiO2", 2.200*g/cm3, 2);
117 m_materials[
"SiO2"]->AddElement(Si, 1);
118 m_materials[
"SiO2"]->AddElement(O , 2);
119 m_dEdx[
"SiO2"] = 5.938;
122 m_materials[
"Epoxy"] =
new G4Material(
"Epoxy", 1.2*g/cm3, 2);
123 m_materials[
"Epoxy"]->AddElement(H, 2);
124 m_materials[
"Epoxy"]->AddElement(C, 2);
125 m_dEdx[
"Epoxy"] = 2.0;
128 m_materials[
"FR4"] =
new G4Material(
"FR4", 1.86*g/cm3, 2);
129 m_materials[
"FR4"]->AddMaterial(m_materials[
"SiO2"], 0.528);
130 m_materials[
"FR4"]->AddMaterial(m_materials[
"Epoxy"], 0.472);
131 m_dEdx[
"FR4"] = 0.528*m_dEdx[
"SiO2"] + 0.472*m_dEdx[
"Epoxy"];
134 m_materials[
"G10"] =
new G4Material(
"G10", 1.700 * g / cm3, 4);
135 m_materials[
"G10"]->AddElement(nistManager->FindOrBuildElement(14), 1);
136 m_materials[
"G10"]->AddElement(nistManager->FindOrBuildElement(8) , 2);
137 m_materials[
"G10"]->AddElement(nistManager->FindOrBuildElement(6) , 3);
138 m_materials[
"G10"]->AddElement(nistManager->FindOrBuildElement(1) , 3);
139 m_dEdx[
"PCB"] = 3.179;
141 m_materials[
"PCB"] = m_materials[
"G10"];
142 m_dEdx[
"PCB"] = m_dEdx[
"G10"];
145 m_materials[
"Brass"] =
new G4Material(
"Brass", 8.5 * g / cm3, 2);
146 m_materials[
"Brass"]->AddMaterial(m_materials[
"Cu"] , 70 * perCent);
147 m_materials[
"Brass"]->AddMaterial(m_materials[
"Zn"] , 30 * perCent);
148 m_dEdx[
"Brass"] = 0.7 * m_dEdx[
"Cu"] + 0.3 * m_dEdx[
"Zn"];
149 m_materials[
"Steel"] =
new G4Material(
"Steel", 7.87 * g / cm3, 3);
150 m_materials[
"Steel"]->AddMaterial(m_materials[
"Fe"] , 0.9843);
151 m_materials[
"Steel"]->AddMaterial(m_materials[
"Mn"], 0.014);
152 m_materials[
"Steel"]->AddMaterial(m_materials[
"C"], 0.0017);
153 m_dEdx[
"Steel"] = 0.9843 * m_dEdx[
"Fe"] + 0.014 * m_dEdx[
"Mn"] + 0.0017 * m_dEdx[
"C"];
154 m_materials[
"SSteel"] =
new G4Material(
"SSteel", 8.02 * g / cm3, 4);
155 m_materials[
"SSteel"]->AddMaterial(m_materials[
"Fe"] , 0.70);
156 m_materials[
"SSteel"]->AddMaterial(m_materials[
"Mn"], 0.01);
157 m_materials[
"SSteel"]->AddMaterial(m_materials[
"Cr"], 0.19);
158 m_materials[
"SSteel"]->AddMaterial(m_materials[
"Ni"], 0.10);
160 = 0.7 * m_dEdx[
"Fe"] + 0.01 * m_dEdx[
"Mn"] + 0.19 * m_dEdx[
"Cr"] + 0.1 * m_dEdx[
"Ni"];
161 m_materials[
"Scintillator"]
162 = nistManager->FindOrBuildMaterial(
"G4_POLYSTYRENE",
false);
163 m_dEdx[
"Scintillator"] = m_dEdx[
"C"];
164 G4cout << m_materials[
"Scintillator"] << G4endl;
165 m_materials[
"Polystyrole"] =
new G4Material(
"Polystyrole", 1.065 * g / cm3, 2);
166 m_materials[
"Polystyrole"]->AddMaterial(m_materials[
"H"] , 50 * perCent);
167 m_materials[
"Polystyrole"]->AddMaterial(m_materials[
"C"] , 50 * perCent);
168 m_dEdx[
"Polystyrole"] = 0.5 * m_dEdx[
"C"];
170 m_materials[
"PVC"] =
new G4Material(
"PVC", 1.350 * g / cm3, 3);
171 m_materials[
"PVC"]->AddMaterial(m_materials[
"H"] , 50 * perCent);
172 m_materials[
"PVC"]->AddMaterial(m_materials[
"C"] , 33.33 * perCent);
173 m_materials[
"PVC"]->AddMaterial(m_materials[
"Cl"] , 16.67 * perCent);
174 m_dEdx[
"PVC"] = 0.33 * m_dEdx[
"C"];
176 m_materials[
"CFMix"] =
new G4Material(
"CFMix", 0.120 * g / cm3, 3);
177 m_materials[
"CFMix"]->AddMaterial(m_materials[
"Air"] , 0.009);
178 m_materials[
"CFMix"]->AddMaterial(m_materials[
"PVC"] , 0.872);
179 m_materials[
"CFMix"]->AddMaterial(m_materials[
"Polystyrole"] , 0.119);
182 m_materials[
"Foam"] =
new G4Material(
"Foam", 0.0999 * g / cm3, 2);
183 m_materials[
"Foam"]->AddMaterial(m_materials[
"C"] , 0.856);
184 m_materials[
"Foam"]->AddMaterial(m_materials[
"H"] , 0.144);
185 m_dEdx[
"Foam"] = 1.749 * 0.856 * 0.0999 / 10.;
187 m_materials[
"WCu"] =
new G4Material(
"WCu", 14.979 * g / cm3, 2);
188 m_materials[
"WCu"]->AddMaterial(m_materials[
"W"] , 75 * perCent);
189 m_materials[
"WCu"]->AddMaterial(m_materials[
"Cu"] , 25 * perCent);
190 m_dEdx[
"WCu"] = 0.75 * m_dEdx[
"W"] + 0.25 * m_dEdx[
"Cu"];
192 m_materials[
"NeutMod"] =
new G4Material(
"NeutMod", 0.950 * g / cm3, 2);
193 m_materials[
"NeutMod"]->AddMaterial(m_materials[
"C"] , 0.85628);
194 m_materials[
"NeutMod"]->AddMaterial(m_materials[
"H"] , 0.14372);
195 m_dEdx[
"NeutMod"] = 1.749 * 0.86 * 0.950 / 10.;
200 void DetectorConstruction::UpdateCalorSize()
202 size_t nsections = m_caloStruct.size();
208 G4double units = getUnits(m_caloStruct[0].ele_name[0], efirst);
209 G4double center = (elast.
dmap[
"z"] + efirst.
dmap[
"z"]) * units / 2;
211 = (elast.
dmap[
"z"] - efirst.
dmap[
"z"]
212 + (elast.
dmap[
"thickness"] + efirst.
dmap[
"thickness"]) / 2) * units;
217 for(
size_t i = 0; i < nsections; i++) {
218 SamplingSection& section = m_caloStruct[i];
219 size_t nEle = section.n_elements;
220 for (
unsigned ie(0); ie < nEle; ++ie) {
226 bool isSensitive =
false;
227 if ( e.
imap.find(
"sensitive") != e.
imap.end() )
228 isSensitive = static_cast<bool>(e.
imap[
"sensitive"]);
230 G4double units = getUnits(section.ele_name[ie], e);
231 if ( e.
smap[
"shape"] ==
"cylinder" ) {
233 G4double maxR = getParameter(section.ele_name[ie],
234 e,
"maxRadius") * units;
235 if ( maxR > m_CalorSizeXY ) m_CalorSizeXY = maxR;
237 }
else if ( e.
smap[
"shape"] ==
"hexagon" ) {
239 m_CellSize = getParameter(section.ele_name[ie],
240 e,
"cellsize") * units;
241 assert(m_CellSize > 0);
244 G4double width = 2 * getParameter(section.ele_name[ie],
246 if ( width > m_CalorSizeXY ) m_CalorSizeXY = width;
248 }
else if ( e.
smap[
"shape"] ==
"square" ) {
250 G4double side = getParameter(section.ele_name[ie],
252 if ( side > m_CalorSizeXY ) m_CalorSizeXY = side;
258 std::string u = efirst.
smap[
"units"];
259 G4cout <<
" XY extent of detector: " << m_CalorSizeXY << u << G4endl;
260 G4cout <<
" Z extent of detector: " << m_CalorSizeZ << u << G4endl;
261 G4cout <<
" Z location of detector: " << center << u << G4endl;
262 G4cout <<
" cell size of detector: " << m_CellSize << u << G4endl;
266 G4VPhysicalVolume* DetectorConstruction::Construct()
270 G4GeometryManager::GetInstance()->OpenGeometry();
271 G4PhysicalVolumeStore::GetInstance()->Clean();
272 G4LogicalVolumeStore::GetInstance()->Clean();
273 G4SolidStore::GetInstance()->Clean();
278 G4double units = getUnits(
"World", world);
279 G4double expHall_x = world.
dmap[
"xside"] * units;
280 G4double expHall_y = world.
dmap[
"yside"] * units;
281 G4double expHall_z = world.
dmap[
"zside"] * units;
283 G4Box* experimentalHall_box =
new G4Box(
"expHall_box",
288 G4LogicalVolume* experimentalHall_log
289 =
new G4LogicalVolume(experimentalHall_box, m_materials[
"Air"],
292 G4VPhysicalVolume* experimentalHall_phys
293 =
new G4PVPlacement(0,
294 G4ThreeVector(0., 0., 0.),
295 experimentalHall_log,
303 m_WorldSizeXY = 0.99 * expHall_x;
304 m_WorldSizeZ = 0.99 * expHall_z;
305 m_solidWorld =
new G4Box(
"Wbox",
310 m_logicWorld =
new G4LogicalVolume(m_solidWorld,
313 m_logicWorld->SetVisAttributes(G4VisAttributes::Invisible);
316 G4double xpos = 0.*mm;
317 G4double ypos = 0.*mm;
318 G4double zpos = 0.*mm;
320 m_physWorld =
new G4PVPlacement(0,
321 G4ThreeVector(xpos, ypos, zpos),
324 experimentalHall_log,
329 return experimentalHall_phys;
332 void DetectorConstruction::buildSectorStack()
336 G4double totalLengthX0 = 0;
337 G4double totalLengthL0 = 0;
342 G4cout <<
"== buildSectorStack == " << G4endl;
343 G4cout <<
"number of sections: " << m_caloStruct.size()
346 for(
size_t i = 0; i < m_caloStruct.size(); i++) {
347 G4cout <<
" ==> section: " << i << G4endl;
348 const size_t nEle = m_caloStruct[i].n_elements;
349 G4cout <<
" number of elements/section: " << nEle << G4endl;
356 for (
size_t ie(0); ie < nEle; ++ie) {
358 SamplingSection& section = m_caloStruct[i];
361 G4double units = getUnits(section.ele_name[ie], element);
365 std::string eleName = element.
smap[
"material"];
366 sprintf(nameBuf,
"%s%d", eleName.c_str(), int(i + 1));
369 bool isSensitive =
static_cast<bool>(element.
imap[
"sensitive"]);
371 sprintf(nameBuf,
"%s%d_%d", eleName.c_str(), int(i + 1), idx);
374 std::string baseName(nameBuf);
376 G4double thick = element.
dmap[
"thickness"] * units;
377 G4cout <<
" \telement number: " << ie
378 <<
"\tname: " << nameBuf
379 <<
"\tthickness: " << thick <<
"mm" << G4endl;
382 solid = constructSolid(baseName, element);
386 G4LogicalVolume* logi =
new G4LogicalVolume(solid,
387 m_materials[eleName],
392 section.ele_X0[ie] = m_materials[eleName]->GetRadlen();
393 section.ele_dEdx[ie] = m_dEdx[eleName];
394 section.ele_L0[ie] = m_materials[eleName]->GetNuclearInterLength();
395 totalLengthX0 += thick / section.ele_X0[ie];
396 totalLengthL0 += thick / section.ele_L0[ie];
398 G4cout <<
" \t" << eleName
399 <<
" dEdx=" << section.ele_dEdx[ie]
400 <<
" X0=" << section.ele_X0[ie]
402 <<
" \tL0=" << section.ele_L0[ie]
404 <<
" \tTotX0=" << totalLengthX0
405 <<
" \tTotLambda=" << totalLengthL0 << G4endl;
408 if ( isSensitive ) m_logicSi.push_back(logi);
411 G4double xpos = getParameter(baseName, element,
"x") * units;
412 G4double ypos = getParameter(baseName, element,
"y") * units;
413 G4double zpos = getParameter(baseName, element,
"z") * units;
414 section.ele_vol[ie] =
416 G4ThreeVector(xpos, ypos, zpos),
419 m_logicWorld,
false, 0);
420 G4cout <<
" \tpositioning element at (" << xpos
421 <<
", " << ypos <<
", " << zpos <<
")"
425 if ( element.
smap[
"material"] ==
string(
"Air") )
426 logi->SetVisAttributes(G4VisAttributes::Invisible);
428 G4VisAttributes* simpleBoxVisAtt =
429 new G4VisAttributes(section.g4Colour(ie));
430 simpleBoxVisAtt->SetVisibility(
true);
431 logi->SetVisAttributes(simpleBoxVisAtt);
439 unsigned nlogicsi = m_logicSi.size();
440 G4Region* aRegion =
new G4Region(baseName +
"Reg");
441 m_logicSi[nlogicsi - 1]->SetRegion(aRegion);
442 aRegion->AddRootLogicalVolume(m_logicSi[nlogicsi - 1]);
449 void DetectorConstruction::SetMagField(G4double fieldValue)
452 if(fieldValue <= 0)
return;
455 G4FieldManager* fieldMgr
456 = G4TransportationManager::GetTransportationManager()->GetFieldManager();
457 if(m_magField)
delete m_magField;
458 m_magField =
new G4UniformMagField(G4ThreeVector(0., 0., fieldValue));
459 fieldMgr->SetDetectorField(m_magField);
460 fieldMgr->CreateChordFinder(m_magField);
461 fieldMgr->SetDetectorField(m_magField);
464 void DetectorConstruction::SetDetModel(G4int model)
466 if (model <= 0)
return;
467 G4cout <<
" -- Setting detector model to " << model << G4endl;
472 double DetectorConstruction::getParameter(std::string name,
480 G4cout <<
"** DetectorConstruction ** problem building "
481 <<
"detector element " << name << G4endl
482 <<
"** parameter " << param <<
" is missing. Check config file."
490 G4double DetectorConstruction::getUnits(std::string name,
495 units = e.
smap[
"units"];
497 G4cout <<
"** DetectorConstruction ** no units given for"
498 <<
"detector element " << name << G4endl;
505 else if ( units ==
"cm" )
511 G4VSolid* DetectorConstruction::constructSolid (std::string baseName,
514 G4double units = getUnits(baseName, e);
516 if ( e.
smap[
"shape"] ==
"cylinder" ) {
517 G4double minR = getParameter(baseName, e,
"minRadius") * units;
518 G4double maxR = getParameter(baseName, e,
"maxRadius") * units;
519 G4double thickness = getParameter(baseName, e,
"thickness") * units;
520 solid =
new G4Tubs(baseName +
"cyl",
521 minR, maxR, thickness / 2, 0.*deg, 360.0 * deg);
522 }
else if ( e.
smap[
"shape"] ==
"hexagon" ) {
523 G4double thickness = getParameter(baseName, e,
"thickness") * units;
524 G4double zPlane[2] = { -thickness / 2, thickness / 2};
527 G4double side = getParameter(baseName, e,
"side") * units;
528 double minRadius = (side / 2) * sqrt(3.0) / 2;
529 G4double rInner[2] = {0, 0};
530 G4double rOuter[2] = {minRadius, minRadius};
531 solid =
new G4Polyhedra(baseName +
"hexa",
537 }
else if ( e.
smap[
"shape"] ==
"square" ) {
538 G4double thickness = getParameter(baseName, e,
"thickness") * units;
539 G4double side = getParameter(baseName, e,
"side") * units;
540 solid =
new G4Box(baseName +
"box", side / 2, side / 2, thickness / 2);
542 G4cout <<
"** DetectorConstruction ** problem building "
543 <<
"detector element " << baseName << G4endl
544 <<
"** shape " << e.
smap[
"shape"] <<
" not yet implemented"
std::map< std::string, double > dmap
std::map< std::string, int > imap
std::map< std::string, std::string > smap