Belle II Software development
GeoARICHCreator.cc
1/**************************************************************************
2 * basf2 (Belle II Analysis Software Framework) *
3 * Author: The Belle II Collaboration *
4 * *
5 * See git log for contributors and copyright holders. *
6 * This file is licensed under LGPL-3.0, see LICENSE.md. *
7 **************************************************************************/
8
9#include <arich/geometry/GeoARICHCreator.h>
10#include <arich/dbobjects/tessellatedSolidStr.h>
11
12#include <geometry/Materials.h>
13#include <geometry/CreatorFactory.h>
14#include <geometry/utilities.h>
15#include <framework/gearbox/Unit.h>
16#include <framework/logging/Logger.h>
17#include <arich/simulation/SensitiveDetector.h>
18#include <arich/simulation/SensitiveAero.h>
19#include <simulation/background/BkgSensitiveDetector.h>
20#include <arich/dbobjects/ARICHPositionElement.h>
21
22#include <cmath>
23#include <boost/format.hpp>
24#include <boost/foreach.hpp>
25#include <boost/algorithm/string.hpp>
26
27// Geant4
28#include <G4LogicalVolume.hh>
29#include <G4PVPlacement.hh>
30#include <G4AssemblyVolume.hh>
31#include <G4UnionSolid.hh>
32#include <G4LogicalSkinSurface.hh>
33#include <G4OpticalSurface.hh>
34
35// Geant4 Shapes
36#include <G4Box.hh>
37#include <G4Tubs.hh>
38#include <G4Trap.hh>
39#include <G4Torus.hh>
40#include <G4TessellatedSolid.hh>
41#include <G4TriangularFacet.hh>
42
43#include <G4SubtractionSolid.hh>
44#include <G4Region.hh>
45#include <G4Material.hh>
46
47using namespace std;
48using namespace boost;
49using namespace CLHEP;
50
51namespace Belle2 {
57 using namespace geometry;
58
59 namespace arich {
60
61 //-----------------------------------------------------------------
62 // Register the Creator
63 //-----------------------------------------------------------------
64
65 geometry::CreatorFactory<GeoARICHCreator> GeoARICHFactory("ARICHCreator");
66
67 //-----------------------------------------------------------------
68 // Implementation
69 //-----------------------------------------------------------------
70
71 GeoARICHCreator::GeoARICHCreator(): m_isBeamBkgStudy(0)
72 {
73 m_sensitive = NULL;
74 m_sensitiveAero = NULL;
75 }
76
78 {
79 delete m_sensitive;
80 delete m_sensitiveAero;
81 G4LogicalSkinSurface::CleanSurfaceTable();
82
83 }
84
85
86 void GeoARICHCreator::createGeometry(G4LogicalVolume& topVolume, GeometryTypes)
87 {
88
92
93 // print geometry configuration
94 // m_config.print();
95
96 //Build envelope
97 G4Tubs* envelopeTube = new G4Tubs("Envelope", m_config.getMasterVolume().getInnerRadius(),
99 G4Material* material = Materials::get(m_config.getMasterVolume().getMaterial());
100
101 // check of material and its refractive index
102 if (!material) { B2FATAL("Material ARICH_Air required for ARICH master volume could not be found");}
103 if (!getAvgRINDEX(material))
104 B2WARNING("Material ARICH_Air required by ARICH master volume has no specified refractive index. Continuing, but no photons in ARICH will be propagated.");
105
106 // create and place
107 G4LogicalVolume* masterLV = new G4LogicalVolume(envelopeTube, material, "ARICH.masterVolume");
108 setVisibility(*masterLV, false);
109
110 // Set up region for production cuts
111 G4Region* aRegion = new G4Region("ARICHEnvelope");
112 masterLV->SetRegion(aRegion);
113 aRegion->AddRootLogicalVolume(masterLV);
114
115 G4RotationMatrix rotMaster;
116 double rot_x = m_config.getMasterVolume().getRotationX();
117 double rot_y = m_config.getMasterVolume().getRotationY();
118 double rot_z = m_config.getMasterVolume().getRotationZ();
119 double tr_x = m_config.getMasterVolume().getPosition().X();
120 double tr_y = m_config.getMasterVolume().getPosition().Y();
121 double tr_z = m_config.getMasterVolume().getPosition().Z();
122
130 B2WARNING("ARICH global displacement parameters from DB will be taken into account.");
131 }
132 rotMaster.rotateX(rot_x);
133 rotMaster.rotateY(rot_y);
134 rotMaster.rotateZ(rot_z);
135
136 G4ThreeVector transMaster(tr_x, tr_y, tr_z);
137
138 new G4PVPlacement(G4Transform3D(rotMaster, transMaster), masterLV, "ARICH.MasterVolume", &topVolume, false, 1);
139
141
142 // Z shift for placing volumes in ARICH master volume
143 double zShift = 0;
144
145 // build photon detector logical volume
146 G4LogicalVolume* detPlaneLV = buildDetectorPlane(m_config);
147 G4LogicalVolume* detSupportPlateLV = buildDetectorSupportPlate(m_config);
148
149 // Build merger PCB logical volume
150 G4LogicalVolume* mergerLV = buildMergerPCBEnvelopePlane(m_config);
151
152 // Build the cables envelop with effective material describing cables
153 G4LogicalVolume* cablesLV = buildCables(m_config.getCablesEnvelope());
154
155 // Build cooling system assembly envelope plane
156 //G4LogicalVolume* coolingLV = buildCoolingEnvelopePlane(m_config.getCoolingGeometry());
157
158 // Build aerogel logical volume
159 G4LogicalVolume* aeroPlaneLV;
161 aeroPlaneLV = buildAerogelPlane(m_config);
162 } else {
163 B2INFO("GeoARICHCreator: using simple cosmic test geometry.");
164 aeroPlaneLV = buildSimpleAerogelPlane(m_config);
165 }
166
167 G4RotationMatrix rotDetPlane;
168 rotDetPlane.rotateX(m_config.getDetectorPlane().getRotationX());
169 rotDetPlane.rotateY(m_config.getDetectorPlane().getRotationY());
170 rotDetPlane.rotateZ(m_config.getDetectorPlane().getRotationZ());
171
172 //
173 // For the moment rotation of merger PCB board envelope is not foreseen.
174 //
175 G4RotationMatrix rotMergerPlane;
176 rotMergerPlane.rotateX(0.0);
177 rotMergerPlane.rotateY(0.0);
178 rotMergerPlane.rotateZ(0.0);
179
180 //
181 // For the moment rotation of cables envelope is not foreseen.
182 //
183 G4RotationMatrix rotCablesPlane;
184 rotCablesPlane.rotateX(0.0);
185 rotCablesPlane.rotateY(0.0);
186 rotCablesPlane.rotateZ(0.0);
187
188 G4RotationMatrix rotCoolingPlane;
189 rotCoolingPlane.rotateX(0.0);
190 rotCoolingPlane.rotateY(0.0);
191 rotCoolingPlane.rotateZ(0.0);
192
193 G4RotationMatrix rotAeroPlane;
194 rotAeroPlane.rotateX(m_config.getAerogelPlane().getRotationX());
195 rotAeroPlane.rotateY(m_config.getAerogelPlane().getRotationY());
196 rotAeroPlane.rotateZ(m_config.getAerogelPlane().getRotationZ());
197
198 G4ThreeVector transDetPlane(m_config.getDetectorPlane().getPosition().X(), m_config.getDetectorPlane().getPosition().Y(),
199 m_config.getDetectorPlane().getPosition().Z() + zShift);
200
201 G4ThreeVector transDetSupportPlate(m_config.getDetectorPlane().getPosition().X(), m_config.getDetectorPlane().getPosition().Y(),
203
204 G4ThreeVector transMergerPlate(m_config.getMergerGeometry().getEnvelopeCenterPosition().X() * mm,
207
208 G4ThreeVector transCablesPlate(m_config.getCablesEnvelope().getEnvelopeCenterPosition().X(),
211
212 G4ThreeVector transCoolingPlate(m_config.getCoolingGeometry().getEnvelopeCenterPosition().X() * mm,
215
216 G4ThreeVector transAeroPlane(m_config.getAerogelPlane().getPosition().X(),
218 m_config.getAerogelPlane().getPosition().Z() + zShift);
219
220
221 new G4PVPlacement(G4Transform3D(rotDetPlane, transDetPlane), detPlaneLV, "ARICH.detPlane", masterLV, false, 1);
222 new G4PVPlacement(G4Transform3D(rotDetPlane, transDetSupportPlate), detSupportPlateLV, "ARICH.detSupportPlane", masterLV, false, 1);
223 if (mergerLV) new G4PVPlacement(G4Transform3D(rotMergerPlane, transMergerPlate), mergerLV, "ARICH.mergerPlane", masterLV, false, 1);
224 new G4PVPlacement(G4Transform3D(rotCablesPlane, transCablesPlate), cablesLV, "ARICH.cablesPlane", masterLV, false, 1);
225 //new G4PVPlacement(G4Transform3D(rotCoolingPlane, transCoolingPlate), coolingLV, "ARICH.coolingPlane", masterLV, false, 1);
226 new G4PVPlacement(G4Transform3D(rotAeroPlane, transAeroPlane), aeroPlaneLV, "ARICH.aeroPlane", masterLV, false, 1);
227
228 /*
229 // build and place cooling test plates
230 G4LogicalVolume* coolingTestPlatesLV = buildCoolingTestPlate(m_config.getCoolingGeometry());
231 double coolingTestPlateAngle = 0.0;
232 double coolingTestPlateR = 0.0;
233 for (unsigned i = 0; i < m_config.getCoolingGeometry().getCoolingTestPlatePosR().size(); i++) {
234 coolingTestPlateAngle = m_config.getCoolingGeometry().getCoolingTestPlatePosPhi().at(i) * deg;
235 coolingTestPlateR = m_config.getCoolingGeometry().getCoolingTestPlatePosR().at(i) * mm;
236 G4RotationMatrix rotCoolingTestPlate;
237 rotCoolingTestPlate.rotateZ(coolingTestPlateAngle);
238 G4ThreeVector transCoolingTestPlate(coolingTestPlateR * cos(coolingTestPlateAngle),
239 coolingTestPlateR * sin(coolingTestPlateAngle),
240 m_config.getCoolingGeometry().getCoolingTestPlatePosZ0().at(i) * mm + zShift);
241 new G4PVPlacement(G4Transform3D(rotCoolingTestPlate, transCoolingTestPlate), coolingTestPlatesLV, "ARICH.coolingTestPlates",
242 masterLV, false, i);
243 }
244 */
245
246 // build and place mirrors
247 G4LogicalVolume* mirrorLV = buildMirror(m_config);
248 int nMirrors = m_config.getMirrors().getNMirrors();
249 int mirStart = m_config.getMirrors().getStartAngle();
250 int mirZPos = m_config.getMirrors().getZPosition();
251 int mirRad = m_config.getMirrors().getRadius();
252
253 double angl = mirStart;
254 double dphi = 2 * M_PI / nMirrors;
255 if (m_config.useMirrorDisplacement()) B2WARNING("ARICH mirrors displacement parameters from DB will be used.");
256 for (int i = 1; i < nMirrors + 1; i++) {
257 double mrot_x = 0;
258 double mrot_y = 0;
259 double mrot_z = angl;
260 double mtr_x = mirRad * cos(angl);
261 double mtr_y = mirRad * sin(angl);
262 double mtr_z = mirZPos + zShift;
265 mrot_x += displ.getAlpha();
266 mrot_y += displ.getBeta();
267 mrot_z += displ.getGamma();
268 mtr_x += displ.getX();
269 mtr_y += displ.getY();
270 mtr_z += displ.getZ();
271 }
272 G4RotationMatrix rotMirror;
273 rotMirror.rotateX(mrot_x);
274 rotMirror.rotateY(mrot_y);
275 rotMirror.rotateZ(mrot_z);
276 G4ThreeVector transMirror(mtr_x, mtr_y, mtr_z);
277 new G4PVPlacement(G4Transform3D(rotMirror, transMirror), mirrorLV, "ARICH.mirrorPlate", masterLV, false, i);
278 angl += dphi;
279 }
280
281 // build additional components of support structure
282
283 const ARICHGeoSupport& supportPar = m_config.getSupportStructure();
284 std::vector<G4LogicalVolume*> shieldLV(2);
285 std::vector<double> shieldZ(2);
286 int nTubes = supportPar.getNTubes();
287 for (int i = 0; i < nTubes; i++) {
288 G4Tubs* tube = new G4Tubs(supportPar.getTubeName(i), supportPar.getTubeInnerR(i), supportPar.getTubeOuterR(i),
289 supportPar.getTubeLength(i) / 2., 0, 2.*M_PI);
290 G4Material* tubeMaterial = Materials::get(supportPar.getTubeMaterial(i));
291
292 if (supportPar.getTubeName(i) == "ARICH.NeutronShield1") {
293 shieldLV[0] = new G4LogicalVolume(tube, tubeMaterial, supportPar.getTubeName(i));
294 shieldZ[0] = supportPar.getTubeZPosition(i) + supportPar.getTubeLength(i) / 2.;
295 continue;
296 } else if (supportPar.getTubeName(i) == "ARICH.NeutronShield2") {
297 shieldLV[1] = new G4LogicalVolume(tube, tubeMaterial, supportPar.getTubeName(i));
298 shieldZ[1] = supportPar.getTubeZPosition(i) + supportPar.getTubeLength(i) / 2.;
299 continue;
300 }
301
302 G4LogicalVolume* tubeLV = new G4LogicalVolume(tube, tubeMaterial, supportPar.getTubeName(i));
303
304 new G4PVPlacement(G4Transform3D(G4RotationMatrix(), G4ThreeVector(0, 0,
305 supportPar.getTubeZPosition(i) + supportPar.getTubeLength(i) / 2. + zShift)), tubeLV, supportPar.getTubeName(i), masterLV, false,
306 1);
307 }
308
309 const std::vector<double> wedge1 = supportPar.getWedge(1);
310 const std::vector<double> wedge2 = supportPar.getWedge(2);
311 G4Material* wedge1Material = Materials::get(supportPar.getWedgeMaterial(1));
312 G4Material* wedge2Material = Materials::get(supportPar.getWedgeMaterial(2));
313 G4AssemblyVolume* assemblyWedge1 = new G4AssemblyVolume();
314 G4AssemblyVolume* assemblyWedge2 = new G4AssemblyVolume();
315 makeJoint(wedge1Material, wedge1, assemblyWedge1);
316 makeJoint(wedge2Material, wedge2, assemblyWedge2);
317
318 G4Transform3D Tr;
319 int nWedge = supportPar.getNWedges();
320 for (int i = 0; i < nWedge; i++) {
321 G4RotationMatrix Rx;
322 int wgtype = supportPar.getWedgeType(i);
323 double phi = supportPar.getWedgePhi(i);
324 Rx.rotateZ(phi);
325 double r = supportPar.getWedgeR(i);
326 double z = supportPar.getWedgeZ(i);
327 G4ThreeVector Tb(r * cos(phi), r * sin(phi), z);
328
329 if (shieldLV[0]) {
330 z -= shieldZ[0];
331 Tb.setZ(z);
332 Tr = G4Transform3D(Rx, Tb);
333 if (wgtype == 1) assemblyWedge1->MakeImprint(shieldLV[0], Tr);
334 else if (wgtype == 2) assemblyWedge2->MakeImprint(shieldLV[0], Tr);
335 continue;
336 }
337
338 Tr = G4Transform3D(Rx, Tb);
339 if (wgtype == 1) assemblyWedge1->MakeImprint(masterLV, Tr);
340 else if (wgtype == 2) assemblyWedge2->MakeImprint(masterLV, Tr);
341 else B2ERROR("GeoARICHCreator: invalid support wedge type!");
342 }
343
344 // place neutron shield volumes
345 if (shieldLV[0])
346 new G4PVPlacement(G4Transform3D(G4RotationMatrix(), G4ThreeVector(0, 0, shieldZ[0])), shieldLV[0], "ARICH.NeutronShield1", masterLV,
347 false, 1);
348 if (shieldLV[1])
349 new G4PVPlacement(G4Transform3D(G4RotationMatrix(), G4ThreeVector(0, 0, shieldZ[1])), shieldLV[1], "ARICH.NeutronShield2", masterLV,
350 false, 1);
351
352 // place mirror holders, for now skip
353 /*
354 double mirSupX = 17.;
355 double mirSupY = 14.;
356 double mirSupLen = 131;
357 double mirSupLen1 = 201;
358
359 std::vector<G4TwoVector> polygon;
360 polygon.assign(12, G4TwoVector());
361 polygon[11] = G4TwoVector(-mirSupX / 2., -mirSupY / 2.);
362 polygon[10] = G4TwoVector(-mirSupX / 2., 2.);
363 polygon[9] = G4TwoVector(-mirSupX / 4., 2. - 0.75);
364 polygon[8] = G4TwoVector(-mirSupX / 4., 5. - 0.75);
365 polygon[7] = G4TwoVector(-mirSupX / 2., 5);
366 polygon[6] = G4TwoVector(-mirSupX / 2., mirSupY / 2.);
367 polygon[5] = G4TwoVector(mirSupX / 2., mirSupY / 2.);
368 polygon[4] = G4TwoVector(mirSupX / 2., 6);
369 polygon[3] = G4TwoVector(mirSupX / 4., 6. - 0.75);
370 polygon[2] = G4TwoVector(mirSupX / 4., 2. - 0.75);
371 polygon[1] = G4TwoVector(mirSupX / 2., 2.);
372 polygon[0] = G4TwoVector(mirSupX / 2., -mirSupY / 2.);
373
374 std::vector<G4ExtrudedSolid::ZSection> zsections;
375 zsections.push_back(G4ExtrudedSolid::ZSection(-mirSupLen / 2., G4TwoVector(0, 0), 1));
376 zsections.push_back(G4ExtrudedSolid::ZSection(mirSupLen / 2., G4TwoVector(0, 0), 1));
377
378 G4ExtrudedSolid* shape = new G4ExtrudedSolid("bla", polygon, zsections);
379 G4LogicalVolume* shapeLV = new G4LogicalVolume(shape, wedge1Material, "mirrorsupport");
380
381 G4Box* shape1 = new G4Box("shape1", mirSupX / 2., 2. / 2., mirSupLen1 / 2.);
382 G4LogicalVolume* shape1LV = new G4LogicalVolume(shape1, wedge1Material, "mirrorholder");
383
384 G4AssemblyVolume* mirroHolder = new G4AssemblyVolume();
385 G4RotationMatrix Rh;
386 G4ThreeVector Th(0, 0, 0);
387 Tr = G4Transform3D(Rh, Th);
388 mirroHolder->AddPlacedVolume(shapeLV, Tr);
389
390 Th.setZ(-35.0);
391 Th.setY(-mirSupY / 2. - 1.);
392 Tr = G4Transform3D(Rh, Th);
393 mirroHolder->AddPlacedVolume(shape1LV, Tr);
394
395 double rholder = m_config.getDetectorPlane().getSupportOuterR() - mirSupY / 2.;
396
397 angl = dphi / 2.;
398 for (int i = 1; i < nMirrors + 1; i++) {
399 G4RotationMatrix rotMirror;
400 rotMirror.rotateX(M_PI);
401 rotMirror.rotateZ(-M_PI / 2. + angl);
402 G4ThreeVector transMirror(rholder * cos(angl), rholder * sin(angl), mirZPos + zShift);
403 Tr = G4Transform3D(rotMirror, transMirror);
404 mirroHolder->MakeImprint(masterLV, Tr);
405 angl += dphi;
406 }
407 */
408
409 // temporary for simple cosmic test
410 // if using simple configuration, place scinitilators
412 int nBoxes = supportPar.getNBoxes();
413 for (int i = 0; i < nBoxes; i++) {
414 ARICHGeoSupport::box box = supportPar.getBox(i);
415 G4Box* scintBox = new G4Box("scintBox", box.size[0] * 10. / 2., box.size[1] * 10. / 2., box.size[2] * 10. / 2.);
416 G4Material* scintMaterial = Materials::get(box.material);
417 G4LogicalVolume* scintLV = new G4LogicalVolume(scintBox, scintMaterial, box.name);
418 scintLV->SetSensitiveDetector(m_sensitiveAero);
419 G4RotationMatrix rotScint;
420 rotScint.rotateX(box.rotation[0]);
421 rotScint.rotateY(box.rotation[1]);
422 rotScint.rotateZ(box.rotation[2]);
423 ROOT::Math::XYZVector transScintTV(box.position[0], box.position[1], box.position[2]);
424 transScintTV = m_config.getMasterVolume().pointToGlobal(transScintTV);
425 B2INFO("GeoARICHCreator: Scintilator " << box.name << " placed at global: " << transScintTV.X() << " " << transScintTV.Y() << " " <<
426 transScintTV.Z());
427 G4ThreeVector transScint(box.position[0] * 10., box.position[1] * 10., box.position[2] * 10.);
428 new G4PVPlacement(G4Transform3D(rotScint, transScint), scintLV, "scintilator", masterLV, false, 1);
429 }
430 }
431
433
434 delete assemblyWedge1;
435 delete assemblyWedge2;
436
437 return;
438
439 }
440
441
443 {
444
445 const ARICHGeoAerogelPlane& aeroGeo = detectorGeo.getAerogelPlane();
446
447 const std::vector<double>& params = aeroGeo.getSimpleParams();
448
449 // support plane
450 double rin = aeroGeo.getSupportInnerR();
451 double rout = aeroGeo.getSupportOuterR();
452 double thick = aeroGeo.getSupportThickness();
453 string supportMat = aeroGeo.getSupportMaterial();
454 double wallHeight = aeroGeo.getWallHeight();
455 G4Material* supportMaterial = Materials::get(supportMat);
456 G4Material* gapMaterial = Materials::get("Air"); // Air without refractive index (to kill photons, to mimic black paper around tile)
457
458 // master volume
459 G4Tubs* aerogelTube = new G4Tubs("aerogelTube", rin, rout, (thick + wallHeight) / 2., 0, 2 * M_PI);
460 G4LogicalVolume* aerogelPlaneLV = new G4LogicalVolume(aerogelTube, gapMaterial, "ARICH.AaerogelPlane");
461
462 // support plate
463 G4Tubs* supportTube = new G4Tubs("aeroSupportTube", rin, rout, thick / 2., 0, 2 * M_PI);
464 G4LogicalVolume* supportTubeLV = new G4LogicalVolume(supportTube, supportMaterial, "ARICH.AerogelSupportPlate");
465 //supportTubeLV->SetSensitiveDetector(m_sensitiveAero);
466
467 unsigned nLayer = aeroGeo.getNLayers();
468
469 // loop over layers
470 double zLayer = 0;
471 for (unsigned iLayer = 1; iLayer < nLayer + 1; iLayer++) {
472 double layerThick = aeroGeo.getLayerThickness(iLayer);
473 std::stringstream tileName;
474 tileName << "aerogelTile_" << iLayer;
475
476 G4Box* tileShape = new G4Box(tileName.str(), params[0] * 10. / 2., params[1] * 10. / 2., layerThick / 2.);
477
478 G4Material* aeroMaterial = Materials::get(aeroGeo.getLayerMaterial(iLayer));
479
480 G4LogicalVolume* tileLV = new G4LogicalVolume(tileShape, aeroMaterial, string("ARICH.") + tileName.str());
481
482 G4ThreeVector transTile(params[2] * 10., params[3] * 10., (thick + layerThick - wallHeight) / 2. + zLayer);
483 G4RotationMatrix Ra;
484 Ra.rotateZ(params[4]);
485 new G4PVPlacement(G4Transform3D(Ra, transTile), tileLV, string("ARICH.") + tileName.str(), aerogelPlaneLV, false, iLayer);
486
487 zLayer += layerThick;
488 }
489
490 new G4PVPlacement(G4Translate3D(0., 0., -wallHeight / 2.), supportTubeLV, "ARICH.AerogelSupportPlate", aerogelPlaneLV, false, 1);
491
492 return aerogelPlaneLV;
493 }
494
495 G4LogicalVolume* GeoARICHCreator::buildAerogelPlane(const ARICHGeometryConfig& detectorGeo)
496 {
498 return buildAerogelPlaneAveragedOverLayers(detectorGeo);
499 else if (detectorGeo.getAerogelPlane().getFullAerogelMaterialDescriptionKey() == 1)
501 else
502 B2ERROR("GeoARICHCreator::buildAerogelPlane --> getFullAerogelMaterialDescriptionKey() is wrong");
503 return NULL;
504 }
505
507 {
508
509 //cout<<"GeoARICHCreator::buildAerogelPlaneAveragedOverLayers(const ARICHGeometryConfig& detectorGeo)"<<endl;
510
511 const ARICHGeoAerogelPlane& aeroGeo = detectorGeo.getAerogelPlane();
512
513 // support plane
514 double rin = aeroGeo.getSupportInnerR();
515 double rout = aeroGeo.getSupportOuterR();
516 double thick = aeroGeo.getSupportThickness();
517 double wallThick = aeroGeo.getWallThickness();
518 double wallHeight = aeroGeo.getWallHeight();
519 string supportMat = aeroGeo.getSupportMaterial();
520 G4Material* supportMaterial = Materials::get(supportMat);
521 G4Material* gapMaterial = Materials::get("Air"); // Air without refractive index (to kill photons, to mimic black paper around tile)
522 G4Material* imgMaterial = Materials::get("ARICH_Air");
523 // master volume
524
525 //double imgTubeLen = 0.5; // if changed, change position of aerogel plane also in main function!!
526 double imgTubeLen = aeroGeo.getImgTubeThickness();
527 G4Tubs* aerogelTube = new G4Tubs("aerogelTube", rin, rout, (thick + wallHeight + imgTubeLen) / 2., 0, 2 * M_PI);
528 G4LogicalVolume* aerogelPlaneLV = new G4LogicalVolume(aerogelTube, gapMaterial, "ARICH.AaerogelPlane");
529
530 // support plate
531 G4Tubs* supportTube = new G4Tubs("aeroSupportTube", rin, rout, thick / 2., 0, 2 * M_PI);
532 G4LogicalVolume* supportTubeLV = new G4LogicalVolume(supportTube, supportMaterial, "ARICH.AerogelSupportPlate");
533 //supportTubeLV->SetSensitiveDetector(m_sensitiveAero);
534
535 // imaginary tube after aerogel layers (used as volume to which tracks are extrapolated by ext module)
536 G4Tubs* imgTube = new G4Tubs("imgTube", rin, rout, imgTubeLen / 2., 0, 2 * M_PI);
537 G4LogicalVolume* imgTubeLV = new G4LogicalVolume(imgTube, imgMaterial, "ARICH.AerogelImgPlate");
538 imgTubeLV->SetSensitiveDetector(m_sensitiveAero);
539
540
541 // read radiuses of aerogel slot aluminum walls
542 std::vector<double> wallR;
543 unsigned nRing = aeroGeo.getNRings();
544 for (unsigned iRing = 1; iRing < nRing + 1; iRing++) {
545 wallR.push_back(aeroGeo.getRingRadius(iRing));
546 }
547
548 unsigned nLayer = aeroGeo.getNLayers();
549 double tileGap = aeroGeo.getTileGap();
550 G4Transform3D transform = G4Translate3D(0., 0., (thick - imgTubeLen) / 2.);
551
552 for (unsigned iRing = 0; iRing < nRing; iRing++) {
553
554 // aluminum walls between tile rings (r wall)
555 std::stringstream wallName;
556 wallName << "supportWallR_" << iRing + 1;
557 G4Tubs* supportWall = new G4Tubs(wallName.str().c_str(), wallR[iRing], wallR[iRing] + wallThick, wallHeight / 2., 0, 2 * M_PI);
558 G4LogicalVolume* supportWallLV = new G4LogicalVolume(supportWall, supportMaterial, string("ARICH.") + wallName.str().c_str());
559
560 new G4PVPlacement(transform, supportWallLV, string("ARICH.") + wallName.str().c_str(), aerogelPlaneLV, false, 0);
561
562 if (iRing == 0) continue;
563
564 // place phi aluminum walls
565 double dphi = aeroGeo.getRingDPhi(iRing);
566
567 wallName.str("");
568 wallName << "supportWallPhi_" << iRing + 1;
569 G4Box* wall = new G4Box(wallName.str(), (wallR[iRing] - wallR[iRing - 1] - wallThick) / 2. - 1., thick / 2., wallHeight / 2.);
570 G4LogicalVolume* wallLV = new G4LogicalVolume(wall, supportMaterial, string("ARICH.") + wallName.str());
571 double r = (wallR[iRing - 1] + wallThick + wallR[iRing]) / 2.;
572 double zLayer = 0;
573
574 // loop over layers
575 int iSlot = 1;
576 for (unsigned iLayer = 1; iLayer < nLayer + 1; iLayer++) {
577 double iphi = 0;
578 double layerThick = aeroGeo.getLayerThickness(iLayer);
579
580 std::stringstream tileName;
581 tileName << "aerogelTile_" << iRing << "_" << iLayer;
582
583 G4Tubs* tileShape = new G4Tubs(tileName.str(), wallR[iRing - 1] + wallThick + tileGap, wallR[iRing] - tileGap, layerThick / 2.,
584 (tileGap + wallThick / 2.) / wallR[iRing], dphi - (2.*tileGap + wallThick) / wallR[iRing]);
585
586 G4Material* aeroMaterial = Materials::get(aeroGeo.getLayerMaterial(iLayer));
587 G4LogicalVolume* tileLV = new G4LogicalVolume(tileShape, aeroMaterial, string("ARICH.") + tileName.str());
588
589 while (iphi < 2 * M_PI - 0.0001) {
590 G4ThreeVector trans(r * cos(iphi), r * sin(iphi), (thick - imgTubeLen) / 2.);
591 G4RotationMatrix Ra;
592 Ra.rotateZ(iphi);
593
594 if (iLayer == 1) new G4PVPlacement(G4Transform3D(Ra, trans), wallLV, string("ARICH.") + wallName.str(), aerogelPlaneLV, false,
595 iSlot);
596
597 G4ThreeVector transTile(0, 0, (thick + layerThick - wallHeight - imgTubeLen) / 2. + zLayer);
598 new G4PVPlacement(G4Transform3D(Ra, transTile), tileLV, string("ARICH.") + tileName.str(), aerogelPlaneLV, false, iSlot);
599 iphi += dphi;
600 iSlot++;
601 }
602 zLayer += layerThick;
603 }
604 }
605
606 new G4PVPlacement(G4Translate3D(0., 0., -(wallHeight + imgTubeLen) / 2.), supportTubeLV, "ARICH.AerogelSupportPlate",
607 aerogelPlaneLV,
608 false, 1);
609
610 new G4PVPlacement(G4Translate3D(0., 0., (wallHeight + thick) / 2.), imgTubeLV, "ARICH.AerogelImgPlate", aerogelPlaneLV, false, 1);
611
612 return aerogelPlaneLV;
613
614 }
615
617 {
618
619 //cout << "GeoARICHCreator::buildAerogelPlaneWithIndividualTilesProp(const ARICHGeometryConfig& detectorGeo)" << endl;
620
621 const ARICHGeoAerogelPlane& aeroGeo = detectorGeo.getAerogelPlane();
622
623 // support plane
624 double rin = aeroGeo.getSupportInnerR();
625 double rout = aeroGeo.getSupportOuterR();
626 double thick = aeroGeo.getSupportThickness();
627 double wallThick = aeroGeo.getWallThickness();
628 // Maximum total (up and down) thickness of the aerogel tiles
629 double maxTotalAerogelThick = aeroGeo.getMaximumTotalTileThickness();
630 //cout<<"maxTotalAerogelThick "<<maxTotalAerogelThick<<endl
631 // <<"wallHeight "<<wallHeight<<endl;
632 // In case of individual thickness of the tiles we need to define compensation
633 // volume with ARICH air. This volume situated between aerogel tile and image plane (imgTube).
634 // Minimum thickness of the compensation volume with ARICH air
635 double compensationARICHairVolumeThick_min = aeroGeo.getCompensationARICHairVolumeThick_min(); // mm
636 // Please note redefinition of wallHeight value
637 double wallHeight = maxTotalAerogelThick + compensationARICHairVolumeThick_min;
638
639 string supportMat = aeroGeo.getSupportMaterial();
640 G4Material* supportMaterial = Materials::get(supportMat);
641
642 G4Material* gapMaterial =
643 Materials::get("Air"); // Air without refractive index (to kill photons, to mimic black paper around tile)
644 G4Material* imgMaterial = Materials::get("ARICH_Air"); // Air with defined optical properties to propagate cherenkov photons
645
646 // master volume
647 double imgTubeLen = aeroGeo.getImgTubeThickness(); // if changed, change position of aerogel plane also in main function!!
648 G4Tubs* aerogelTube = new G4Tubs("aerogelTube", rin, rout, (thick + wallHeight + imgTubeLen) / 2., 0, 2 * M_PI);
649 G4LogicalVolume* aerogelPlaneLV = new G4LogicalVolume(aerogelTube, gapMaterial, "ARICH.AaerogelPlane");
650
651 // support plate
652 G4Tubs* supportTube = new G4Tubs("aeroSupportTube", rin, rout, thick / 2., 0, 2 * M_PI);
653 G4LogicalVolume* supportTubeLV = new G4LogicalVolume(supportTube, supportMaterial, "ARICH.AerogelSupportPlate");
654 //supportTubeLV->SetSensitiveDetector(m_sensitiveAero);
655
656 // imaginary tube after aerogel layers (used as volume to which tracks are extrapolated by ext module)
657 G4Tubs* imgTube = new G4Tubs("imgTube", rin, rout, imgTubeLen / 2., 0, 2 * M_PI);
658 G4LogicalVolume* imgTubeLV = new G4LogicalVolume(imgTube, imgMaterial, "ARICH.AerogelImgPlate");
659 imgTubeLV->SetSensitiveDetector(m_sensitiveAero);
660
661 // read radiuses of aerogel slot aluminum walls
662 std::vector<double> wallR;
663 unsigned nRing = aeroGeo.getNRings();
664 for (unsigned iRing = 1; iRing < nRing + 1; iRing++) {
665 wallR.push_back(aeroGeo.getRingRadius(iRing));
666 }
667
668 unsigned nLayer = aeroGeo.getNLayers();
669 double tileGap = aeroGeo.getTileGap();
670 G4Transform3D transform = G4Translate3D(0., 0., (thick - imgTubeLen) / 2.);
671
672 for (unsigned iRing = 0; iRing < nRing; iRing++) {
673
674 // Aluminum walls between tile rings (r wall)
675 std::stringstream wallName;
676 wallName << "supportWallR_" << iRing + 1;
677 //cout<<"wallName = "<<wallName.str().c_str()<<endl;
678 G4Tubs* supportWall = new G4Tubs(wallName.str().c_str(), wallR[iRing], wallR[iRing] + wallThick, wallHeight / 2., 0, 2 * M_PI);
679 G4LogicalVolume* supportWallLV = new G4LogicalVolume(supportWall, supportMaterial, string("ARICH.") + wallName.str().c_str());
680 new G4PVPlacement(transform, supportWallLV, string("ARICH.") + wallName.str().c_str(), aerogelPlaneLV, false, 0);
682
683 // There are only 4 rings of aerogel - the first one is only for mechanical support
684 if (iRing == 0) continue;
685
686 // dphi - distance between centers of two consecutive aluminum walls (diaphragm) in one ring
687 double dphi = aeroGeo.getRingDPhi(iRing);
688
689 // Aluminum walls (diaphragm) between two neighboring tile in one ring (phi wall)
690 wallName.str("");
691 wallName << "supportWallPhi_" << iRing + 1;
692 G4Box* wall = new G4Box(wallName.str(), (wallR[iRing] - wallR[iRing - 1] - wallThick) / 2. - 1., thick / 2., wallHeight / 2.);
693 G4LogicalVolume* wallLV = new G4LogicalVolume(wall, supportMaterial, string("ARICH.") + wallName.str());
694 double r = (wallR[iRing - 1] + wallThick + wallR[iRing]) / 2.;
696
697 // loop over layers
698 int icopyNumber = 0;
699 for (unsigned iLayer = 1; iLayer < nLayer + 1; iLayer++) {
700 //int iSlot = 1;
701 double iphi = 0;
702
703 int iicolumn = 0;
704 // loop over phi (over tile slots from same ring)
705 while (iphi < 2 * M_PI - 0.0001) {
706
707 // Define layer thickness as -1 in case it will not be defined
708 // below in the code with a appropriate value - Geant4 will trigger error
709 double layerThick = -1.0;
710 double tileUpThick = -1.0;
711 double tileDownThick = -1.0;
712 //cout<<" double layerThick = aeroGeo.getLayerThickness(iLayer) = "<<layerThick<<endl;
713
714 // Define material and thickness
715 G4Material* aeroMaterial = NULL;
716 int ati_ring = iRing;
717 int ati_column = iicolumn + 1;
718 int ati_layerN = iLayer - 1;
719
720 //cout<<setw(5)<<ati_layerN<<setw(5)<<ati_ring<<setw(5)<<ati_column<<endl;
721 if (detectorGeo.getAerogelPlane().getFullAerogelMaterialDescriptionKey() == 1) {
722 aeroMaterial = Materials::get(aeroGeo.getTileMaterialName(ati_ring, ati_column, ati_layerN).c_str());
723 } else {
724 B2ERROR("GeoARICHCreator::buildAerogelPlaneWithIndividualTilesProp --> getFullAerogelMaterialDescriptionKey() is wrong");
725 }
726 //cout<<"-----------------"<<endl
727 // <<"iLayer = "<<iLayer<<endl
728 // <<aeroMaterial->GetName()<<endl;
729 //cout<<setw(5)<<ati_layerN<<setw(5)<<ati_ring<<setw(5)<<ati_column<<endl;
730 //aeroMaterial->GetMaterialPropertiesTable()->DumpTable();
731 //zcout<<"ooooooooooooooooo"<<endl;
732 layerThick = aeroGeo.getTileThickness(ati_ring, ati_column, ati_layerN);
733 tileUpThick = aeroGeo.getTileThickness(ati_ring, ati_column, 0);
734 tileDownThick = aeroGeo.getTileThickness(ati_ring, ati_column, 1);
735
736 // Placement of the aluminum walls (diaphragm) between two neighboring tile in one ring (phi wall)
737 // please note that we place single wall for two aerogel layers
738 G4ThreeVector trans(r * cos(iphi), r * sin(iphi), (thick - imgTubeLen) / 2.);
739 G4RotationMatrix Ra;
740 Ra.rotateZ(iphi);
741 if (iLayer == 1) {
742 new G4PVPlacement(G4Transform3D(Ra, trans), //transformation
743 wallLV, //its logical
744 string("ARICH.") + wallName.str(), //name
745 aerogelPlaneLV, //mother logical
746 false, //always false
747 icopyNumber); //should be set to 0 for the first volume of a given type.
749
750 // In case of individual thickness
751 // (if aeroGeo.getFullAerogelMaterialDescriptionKey() == 1) or
752 // (if aeroGeo.getFullAerogelMaterialDescriptionKey() == 2)
753 // of the tiles we need to define compensation volume with ARICH air.
754 // This volume situated between aerogel tile and image plane (imgTube).
755 // This volume have same shape as earogel tile but different thickness.
756 // Build Compensation tiles only one time
757 // Compensation tile shape
758 double compTileUpThick = wallHeight - tileUpThick - tileDownThick;
759 std::stringstream compTileName;
760 //compTileName << "aerogelCompTile_" << ati_layerN << "_" << ati_ring << "_" << ati_column;
761 // In the end of the name we have Layer(L), Ring(R), Slot/Column(S) id's
762 // L : 1-2
763 // R : 1-4
764 // S : 1-22 @ R = 1
765 // S : 1-28 @ R = 2
766 // S : 1-34 @ R = 3
767 // S : 1-40 @ R = 4
768 compTileName << "aerogelCompTile_" << iLayer << "_" << ati_ring << "_" << ati_column;
769 //cout<<compTileName.str()<<endl;
770 G4Tubs* compTileShape = new G4Tubs(compTileName.str(), //name
771 wallR[iRing - 1] + wallThick + tileGap, //Rmin
772 wallR[iRing] - tileGap, //Rmax
773 compTileUpThick / 2.0, //Thikness
774 (tileGap + wallThick / 2.0) / wallR[iRing], //phi start
775 dphi - (2.0 * tileGap + wallThick) / wallR[iRing]); //delta phi
776
777 // Logical volume of the compensation tiles
778 G4LogicalVolume* compTileLV = new G4LogicalVolume(compTileShape, //Its solid
779 imgMaterial, //G4 material
780 string("ARICH.") + compTileName.str()); //name
781
782 // Placement of the compensation tiles
783 G4ThreeVector transCompTile(0, 0, (thick + wallHeight - compTileUpThick - imgTubeLen) / 2.0);
784 G4RotationMatrix compRa;
785 compRa.rotateZ(iphi);
786 new G4PVPlacement(G4Transform3D(compRa, transCompTile), //transformation
787 compTileLV, //its logical
788 string("ARICH.") + compTileName.str(), //name
789 aerogelPlaneLV, //mother logical
790 false, //always false
791 0); //should be set to 0 for the first volume of a given type.
792 }
793
794 // Tile shape
795 std::stringstream tileName;
796 tileName << "aerogelTile_" << iLayer << "_" << ati_ring << "_" << ati_column;
797 //cout<<tileName.str()<<endl;
798 G4Tubs* tileShape = new G4Tubs(tileName.str(), //name
799 wallR[iRing - 1] + wallThick + tileGap, //Rmin
800 wallR[iRing] - tileGap, //Rmax
801 layerThick / 2.0, //Thikness
802 (tileGap + wallThick / 2.0) / wallR[iRing], //phi start
803 dphi - (2.0 * tileGap + wallThick) / wallR[iRing]); //delta phi
804
805 // Logical volume of the aerogel tiles
806 G4LogicalVolume* tileLV = new G4LogicalVolume(tileShape, //Its solid
807 aeroMaterial, //G4 material
808 string("ARICH.") + tileName.str()); //name
809
810 // Placement of the aerogel tiles
811 double zLayer = 0.0;
812 if (iLayer == 2)
813 zLayer = tileUpThick;
814 G4ThreeVector transTile(0, 0, (thick + layerThick - wallHeight - imgTubeLen) / 2.0 + zLayer);
815 new G4PVPlacement(G4Transform3D(Ra, transTile), //transformation
816 tileLV, //its logical
817 string("ARICH.") + tileName.str(), //name
818 aerogelPlaneLV, //mother logical
819 false, //always false
820 0); //should be set to 0 for the first volume of a given type.
822
823 iphi += dphi;
824 //iSlot++;
825 icopyNumber++;
826 iicolumn++;
827 }
828 }
829 }
830
831 // Placement of the support tube
832 new G4PVPlacement(G4Translate3D(0., 0., -(wallHeight + imgTubeLen) / 2.), //transformation
833 supportTubeLV, //its logical
834 "ARICH.AerogelSupportPlate", //name
835 aerogelPlaneLV, //mother logical
836 false, //always false
837 0); //should be set to 0 for the first volume of a given type.
838
839 // Placement of the imaginary tube after aerogel layers (used as volume to which tracks are extrapolated by ext module)
840 new G4PVPlacement(G4Translate3D(0., 0., (wallHeight + thick) / 2.), //transformation
841 imgTubeLV, //its logical
842 "ARICH.AerogelImgPlate", //name
843 aerogelPlaneLV, //mother logical
844 false, //always false
845 0); //should be set to 0 for the first volume of a given type.
846
847 return aerogelPlaneLV;
848
849 }
850
851 G4LogicalVolume* GeoARICHCreator::buildHAPD(const ARICHGeoHAPD& hapdGeo)
852 {
853
854 // get module materials
855 string wallMat = hapdGeo.getWallMaterial();
856 string winMat = hapdGeo.getWinMaterial();
857 string apdMat = hapdGeo.getAPDMaterial();
858 string fillMat = hapdGeo.getFillMaterial();
859 string febMat = hapdGeo.getFEBMaterial();
860 G4Material* wallMaterial = Materials::get(wallMat);
861 G4Material* windowMaterial = Materials::get(winMat);
862 G4Material* apdMaterial = Materials::get(apdMat);
863 G4Material* fillMaterial = Materials::get(fillMat);
864 G4Material* febMaterial = Materials::get(febMat);
865 G4Material* moduleFill = Materials::get("ARICH_Air");
866
867 // check that module window material has specified refractive index
868 double wref = getAvgRINDEX(windowMaterial);
869 if (!wref) B2WARNING("Material '" << winMat <<
870 "', required for ARICH photon detector window as no specified refractive index. Continuing, but no photons in ARICH will be detected.");
871
872 // get module dimensions
873 const double hapdSizeX = hapdGeo.getSizeX();
874 const double hapdSizeY = hapdGeo.getSizeY();
875 const double hapdSizeZ = hapdGeo.getSizeZ();
876 const double wallThick = hapdGeo.getWallThickness();
877 const double winThick = hapdGeo.getWinThickness();
878 const double apdSizeX = hapdGeo.getAPDSizeX();
879 const double apdSizeY = hapdGeo.getAPDSizeY();
880 const double apdSizeZ = hapdGeo.getAPDSizeZ();
881 const double botThick = wallThick;
882 const double modHeight = hapdGeo.getModuleSizeZ();
883
884 // module master volume
885 G4Box* moduleBox = new G4Box("moduleBox", hapdSizeX / 2., hapdSizeY / 2., modHeight / 2.);
886 G4LogicalVolume* lmoduleBox = new G4LogicalVolume(moduleBox, moduleFill, "ARICH.HAPDModule");
887
888 // build HAPD box
889 G4Box* hapdBox = new G4Box("hapdBox", hapdSizeX / 2., hapdSizeY / 2., hapdSizeZ / 2.);
890 G4LogicalVolume* lhapdBox = new G4LogicalVolume(hapdBox, fillMaterial, "ARICH.HAPD");
891
892 // build HAPD walls
893 G4Box* tempBox2 = new G4Box("tempBox2", hapdSizeX / 2. - wallThick, hapdSizeY / 2. - wallThick,
894 hapdSizeZ / 2. + 0.1); // Dont't care about "+0.1", needs to be there.
895 G4SubtractionSolid* moduleWall = new G4SubtractionSolid("Box-tempBox", hapdBox, tempBox2);
896 G4LogicalVolume* lmoduleWall = new G4LogicalVolume(moduleWall, wallMaterial, "ARICH.HAPDWall");
897 setColor(*lmoduleWall, "rgb(1.0,0.0,0.0,1.0)");
898 new G4PVPlacement(G4Transform3D(), lmoduleWall, "ARICH.HAPDWall", lhapdBox, false, 1);
899
900 // build HAPD window
901 G4Box* winBox = new G4Box("winBox", hapdSizeX / 2. - wallThick, hapdSizeY / 2. - wallThick, winThick / 2.);
902 G4LogicalVolume* lmoduleWin = new G4LogicalVolume(winBox, windowMaterial, "ARICH.HAPDWindow");
903 setColor(*lmoduleWin, "rgb(0.7,0.7,0.7,1.0)");
904 lmoduleWin->SetSensitiveDetector(m_sensitive);
905 G4Transform3D transform = G4Translate3D(0., 0., (-hapdSizeZ + winThick) / 2.);
906 new G4PVPlacement(transform, lmoduleWin, "ARICH.HAPDWindow", lhapdBox, false, 1);
907
908 // build module bottom
909 G4Box* botBox = new G4Box("botBox", hapdSizeX / 2. - wallThick, hapdSizeY / 2. - wallThick, botThick / 2.);
910 G4LogicalVolume* lmoduleBot = new G4LogicalVolume(botBox, wallMaterial, "ARICH.HAPDBottom");
911 setColor(*lmoduleBot, "rgb(0.0,1.0,0.0,1.0)");
912 G4Transform3D transform1 = G4Translate3D(0., 0., (hapdSizeZ - botThick) / 2.);
913 new G4PVPlacement(transform1, lmoduleBot, "ARICH.HAPDBottom", lhapdBox, false, 1);
914
915 // build apd
916 G4Box* apdBox = new G4Box("apdBox", apdSizeX / 2., apdSizeY / 2., apdSizeZ / 2.);
917 G4LogicalVolume* lApd = new G4LogicalVolume(apdBox, apdMaterial, "ARICH.HAPDApd");
918 if (m_isBeamBkgStudy) lApd->SetSensitiveDetector(new BkgSensitiveDetector("ARICH", 1));
919
920 // add APD surface optical properties
921 Materials& materials = Materials::getInstance();
922
923 G4OpticalSurface* optSurf = materials.createOpticalSurface(hapdGeo.getAPDSurface());
924
925 new G4LogicalSkinSurface("apdSurface", lApd, optSurf);
926 G4Transform3D transform2 = G4Translate3D(0., 0., (hapdSizeZ - apdSizeZ) / 2. - botThick);
927 new G4PVPlacement(transform2, lApd, "ARICH.HAPDApd", lhapdBox, false, 1);
928
929 // build FEB
930 double febSizeX = hapdGeo.getFEBSizeX();
931 double febSizeY = hapdGeo.getFEBSizeY();
932 double febSizeZ = hapdGeo.getFEBSizeZ();
933 G4Box* febBox = new G4Box("febBox", febSizeX / 2., febSizeY / 2., febSizeZ / 2.);
934 G4LogicalVolume* lfeb = new G4LogicalVolume(febBox, febMaterial, "ARICH.HAPDFeb");
935 if (m_isBeamBkgStudy) lfeb->SetSensitiveDetector(new BkgSensitiveDetector("ARICH"));
936 setColor(*lfeb, "rgb(0.0,0.6,0.0,1.0)");
937 G4Transform3D transform3 = G4Translate3D(0., 0., (modHeight - febSizeZ) / 2.);
938 new G4PVPlacement(transform3, lfeb, "ARICH.HAPDFeb", lmoduleBox, false, 1);
939 G4Transform3D transform4 = G4Translate3D(0., 0., - (modHeight - hapdSizeZ) / 2.);
940 new G4PVPlacement(transform4, lhapdBox, "ARICH.HAPD", lmoduleBox, false, 1);
941
942 return lmoduleBox;
943
944 }
945
946 G4LogicalVolume* GeoARICHCreator::buildDetectorPlane(const ARICHGeometryConfig& detectorGeo)
947 {
948
949 const ARICHGeoHAPD& hapdGeo = detectorGeo.getHAPDGeometry();
950 G4LogicalVolume* hapdLV = buildHAPD(hapdGeo);
951
952 const ARICHGeoDetectorPlane& detGeo = detectorGeo.getDetectorPlane();
953
954 G4Tubs* detTube = new G4Tubs("detTube", detGeo.getRingR(1) - hapdGeo.getSizeX() * 1.4 / 2.,
955 detGeo.getRingR(detGeo.getNRings()) + hapdGeo.getSizeX() * 1.4 / 2., hapdGeo.getModuleSizeZ() / 2., 0, 2 * M_PI);
956 G4LogicalVolume* detPlaneLV = new G4LogicalVolume(detTube, Materials::get("ARICH_Air"), "ARICH.detectorPlane");
957
958 unsigned nSlots = detGeo.getNSlots();
959
960 for (unsigned iSlot = 1; iSlot < nSlots + 1; iSlot++) {
961 if (!m_modInfo->isInstalled(iSlot)) continue;
962 double r = detGeo.getSlotR(iSlot);
963 double phi = detGeo.getSlotPhi(iSlot);
964 G4ThreeVector trans(r * cos(phi), r * sin(phi), 0);
965 G4RotationMatrix Ra;
966 Ra.rotateZ(phi);
967 G4ThreeVector trans1(r * cos(phi), r * sin(phi), 0.0);
968 new G4PVPlacement(G4Transform3D(Ra, trans1), hapdLV, "ARICH.HAPDModule", detPlaneLV, false, iSlot);
969 }
970
971 return detPlaneLV;
972
973 }
974
975 G4LogicalVolume* GeoARICHCreator::buildMerger(const ARICHGeoMerger& mergerGeo)
976 {
977
978 // This is a screw hole on the merger board.
979 // This high precision of the geometry description is needed
980 // only for the correct placement of the merger cooling bodies.
981 // Volume to subtract (screw hole on the merger board)
982 double screwholeR = mergerGeo.getMergerPCBscrewholeR() * mm;
983 double screwholedY = mergerGeo.getMergerPCBscrewholePosdY() * mm;
984 double screwholedX1 = mergerGeo.getMergerPCBscrewholePosdX1() * mm;
985 double screwholedX2 = mergerGeo.getMergerPCBscrewholePosdX2() * mm;
986
987 G4VSolid* screwHoleTubeSubtracted_solid = new G4Tubs("screwHoleTubeSubtracted_solid",
988 0.0,
989 screwholeR,
990 mergerGeo.getThickness() * mm / 2.0,
991 0, 360.0 * deg);
992
993 // Volume to add (merger box)
994 G4Box* merger_solid = new G4Box("merger_solid",
995 mergerGeo.getSizeW() * mm / 2.0,
996 mergerGeo.getSizeL() * mm / 2.0,
997 mergerGeo.getThickness() * mm / 2.0);
998
999 G4RotationMatrix Ra_sub;
1000 G4ThreeVector Ta_sub;
1001 G4Transform3D Tr_sub;
1002 Ta_sub.setX(-mergerGeo.getSizeW() * mm / 2.0 + screwholedX1);
1003 Ta_sub.setY(mergerGeo.getSizeL() * mm / 2.0 - screwholedY);
1004 Ta_sub.setZ(0.0);
1005 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1006 G4SubtractionSolid* substraction_solid = new G4SubtractionSolid("substraction_solid", merger_solid, screwHoleTubeSubtracted_solid,
1007 Tr_sub);
1008 Ta_sub.setX(mergerGeo.getSizeW() * mm / 2.0 - screwholedX2);
1009 Ta_sub.setY(mergerGeo.getSizeL() * mm / 2.0 - screwholedY);
1010 Ta_sub.setZ(0.0);
1011 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1012 substraction_solid = new G4SubtractionSolid("substraction_solid", substraction_solid, screwHoleTubeSubtracted_solid, Tr_sub);
1013 Ta_sub.setX(mergerGeo.getSizeW() * mm / 2.0 - screwholedX2);
1014 Ta_sub.setY(-mergerGeo.getSizeL() * mm / 2.0 + screwholedY);
1015 Ta_sub.setZ(0.0);
1016 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1017 substraction_solid = new G4SubtractionSolid("substraction_solid", substraction_solid, screwHoleTubeSubtracted_solid, Tr_sub);
1018 Ta_sub.setX(-mergerGeo.getSizeW() * mm / 2.0 + screwholedX1);
1019 Ta_sub.setY(-mergerGeo.getSizeL() * mm / 2.0 + screwholedY);
1020 Ta_sub.setZ(0.0);
1021 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1022 substraction_solid = new G4SubtractionSolid("substraction_solid", substraction_solid, screwHoleTubeSubtracted_solid, Tr_sub);
1023
1024 return new G4LogicalVolume(substraction_solid, Materials::get(mergerGeo.getMergerPCBMaterialName()), "ARICH.mergerPCB");
1025 }
1026
1027
1028 G4LogicalVolume* GeoARICHCreator::buildMergerCooling(unsigned iType)
1029 {
1030
1031 if (!m_mergerCooling) {
1032 B2WARNING("ARICH geometry: no data available for merger " << iType << " cooling body geometry. Cooling body will not be placed.");
1033 return NULL;
1034 }
1035
1036 std::stringstream shpName;
1037 shpName << "TessellatedSolid_" << + iType;
1038
1039 G4TessellatedSolid* volume_solid = new G4TessellatedSolid(shpName.str().c_str());
1040
1041 G4ThreeVector point_1;
1042 G4ThreeVector point_2;
1043 G4ThreeVector point_3;
1044
1045 tessellatedSolidStr mergerCoolingStr = m_mergerCooling->getMergerCoolingBodiesInfo(iType);
1046
1047 if (mergerCoolingStr.nCells == 0) {
1048 B2WARNING("ARICH geometry: no data available for merger " << iType << " cooling body geometry. Cooling body will not be placed.");
1049 return NULL;
1050 }
1051
1052 for (unsigned int i = 0; i < mergerCoolingStr.nCells; i++) {
1053 //
1054 point_1.setX(mergerCoolingStr.posV1[0][i]);
1055 point_1.setY(mergerCoolingStr.posV1[1][i]);
1056 point_1.setZ(mergerCoolingStr.posV1[2][i]);
1057 //
1058 point_2.setX(mergerCoolingStr.posV2[0][i]);
1059 point_2.setY(mergerCoolingStr.posV2[1][i]);
1060 point_2.setZ(mergerCoolingStr.posV2[2][i]);
1061 //
1062 point_3.setX(mergerCoolingStr.posV3[0][i]);
1063 point_3.setY(mergerCoolingStr.posV3[1][i]);
1064 point_3.setZ(mergerCoolingStr.posV3[2][i]);
1065 //
1066 G4TriangularFacet* facet = new G4TriangularFacet(point_1, point_2, point_3, ABSOLUTE);
1067 volume_solid->AddFacet((G4VFacet*) facet);
1068 delete facet;
1069 }
1070
1071 volume_solid->SetSolidClosed(true);
1072 std::stringstream volName;
1073 volName << "ARICH.mergerCooling_" << + iType;
1074 G4LogicalVolume* volume_logical = new G4LogicalVolume(volume_solid,
1075 Materials::get(m_mergerCooling->getMergerCoolingBodiesMaterialName()), volName.str().c_str());
1076
1077 setColor(*volume_logical, "rgb(0.6,0.0,0.2,1.0)"); //From the top (farther from IP, downstream)
1078
1079 return volume_logical;
1080 }
1081
1082 G4LogicalVolume* GeoARICHCreator::buildMergerEnvelope(const ARICHGeoMerger& mergerGeo, int iType)
1083 {
1084 // Volume to add single merger and merger cooling body envelope box
1085 G4Box* singlemergerenvelope_solid = new G4Box("singlemergerenvelope_solid",
1086 mergerGeo.getSingleMergerEnvelopeSizeW() * mm / 2.0,
1087 mergerGeo.getSingleMergerEnvelopeSizeL() * mm / 2.0,
1088 mergerGeo.getSingleMergerEnvelopeThickness() * mm / 2.0);
1089 std::stringstream volName;
1090 volName << "ARICH.singleMergerEnvelope_" << + iType;
1091 return new G4LogicalVolume(singlemergerenvelope_solid, Materials::get("ARICH_Air"), volName.str().c_str());
1092 }
1093
1095 {
1096
1097 const ARICHGeoMerger& mergerGeo = detectorGeo.getMergerGeometry();
1098
1099 if (mergerGeo.getSingleMergerEnvelopeSizeW() < 1e-9) {
1100 B2WARNING("GeoARICHCreator: Merger and merger cooling geometry will not be build as it is not availible in geometry configuration (ARICHGeometryConfig with ClasDef>4 is needed).");
1101 return NULL;
1102 }
1103
1104 G4Tubs* envelope_solid = new G4Tubs("envelope_solid", mergerGeo.getEnvelopeInnerRadius() * mm,
1105 mergerGeo.getEnvelopeOuterRadius() * mm, mergerGeo.getEnvelopeThickness() * mm / 2.0, 0.0, 2.0 * M_PI);
1106
1107 G4LogicalVolume* envelope_logical = new G4LogicalVolume(envelope_solid, Materials::get("ARICH_Air"), "ARICH.mergerEnvelope");
1108
1109
1110 G4LogicalVolume* merger_logical = buildMerger(mergerGeo);
1111 G4LogicalVolume* mergerCooling_logical[12] = {NULL};
1112 G4LogicalVolume* mergerEnvelope_logical[12] = {NULL};
1113 G4ThreeVector TaPCB(mergerGeo.getSingleMergeEnvelopePosition().X() * mm, mergerGeo.getSingleMergeEnvelopePosition().Y() * mm,
1114 mergerGeo.getSingleMergeEnvelopePosition().Z() * mm);
1115 G4RotationMatrix RaPCB;
1116 G4ThreeVector TaMergerCooling(mergerGeo.getSingleMergeEnvelopePosition().X() * mm,
1117 mergerGeo.getSingleMergeEnvelopePosition().Y() * mm, -mergerGeo.getSingleMergeEnvelopePosition().Z() * mm);
1118 G4RotationMatrix RaMergerCooling;
1119 RaMergerCooling.rotateY(180 * deg);
1120 RaMergerCooling.rotateZ(-90 * deg);
1121
1122 // build 12 different merger+cooling body volumes
1123 for (int iType = 1; iType < 13; iType++) {
1124 mergerCooling_logical[iType - 1] = buildMergerCooling(iType);
1125 mergerEnvelope_logical[iType - 1 ] = buildMergerEnvelope(mergerGeo, iType); //Single merger and merger cooling body envelope box
1126 setColor(*mergerEnvelope_logical[iType - 1], "rgb(0.0,0.0,1.0,1.0)");
1127
1128 new G4PVPlacement(G4Transform3D(RaPCB, TaPCB), //Transformation
1129 merger_logical, //its logical volume
1130 "ARICH.mergerPCB", //its name
1131 mergerEnvelope_logical[iType - 1], //its mother volume
1132 false, //no boolean operation
1133 iType); //copy number
1134
1135 if (mergerCooling_logical[iType - 1] == NULL) continue;
1136
1137 new G4PVPlacement(G4Transform3D(RaMergerCooling, TaMergerCooling), //Transformation
1138 mergerCooling_logical[iType - 1], //its logical volume
1139 "ARICH.mergerCooling", //its name
1140 mergerEnvelope_logical[iType - 1], //its mother volume
1141 false, //no boolean operation
1142 iType); //copy number
1143 }
1144
1145 // place all 72 merger+cooling body packages
1146 for (unsigned iSlot = 0; iSlot < mergerGeo.getMergerSlotID().size(); iSlot++) {
1147
1148 int type = 1; // if no merger cooling is available...
1149 if (m_mergerCooling) type = (int)m_mergerCooling->getMergerCoolingPositionID().at(iSlot);
1150
1151 //Placement of the single volume envelope
1152 G4ThreeVector Ta(mergerGeo.getMergerPosR().at(iSlot) * mm * cos(mergerGeo.getMergerAngle().at(iSlot) * deg),
1153 mergerGeo.getMergerPosR().at(iSlot) * mm * sin(mergerGeo.getMergerAngle().at(iSlot) * deg),
1154 mergerGeo.getSingleMergerenvelopeDeltaZ().at(iSlot) * mm);
1155 G4RotationMatrix Ra;
1156 Ra.rotateZ(mergerGeo.getMergerAngle().at(iSlot) * deg + mergerGeo.getMergerOrientation().at(iSlot) * deg);
1157 new G4PVPlacement(G4Transform3D(Ra, Ta), //Transformation
1158 mergerEnvelope_logical[type - 1], //its logical volume
1159 "ARICH.singleMergerEnvelope", //its name
1160 envelope_logical, //its mother volume
1161 false, //no boolean operation
1162 iSlot); //copy number
1163 }
1164
1165 return envelope_logical;
1166
1167 }
1168
1169 G4LogicalVolume* GeoARICHCreator::buildCables(const ARICHGeoCablesEnvelope& cablesGeo)
1170 {
1171
1172 G4Tubs* cablesEnvelope_solid = new G4Tubs("cablesEnvelope_solid",
1173 cablesGeo.getEnvelopeInnerRadius(),
1174 cablesGeo.getEnvelopeOuterRadius(),
1175 cablesGeo.getEnvelopeThickness() / 2.0,
1176 0.0,
1177 2.0 * M_PI);
1178 G4LogicalVolume* cablesEnvelope_logical = new G4LogicalVolume(cablesEnvelope_solid,
1180 "ARICH.cablesEnvelope");
1181
1182 return cablesEnvelope_logical;
1183
1184 }
1185
1186 G4LogicalVolume* GeoARICHCreator::buildFEBCoolingBody(const ARICHGeoFEBCooling& coolingv2Geo)
1187 {
1188
1189 //FEB aluminum cooling envelope for single object
1190 double feb_alcooling_singleObjectEnvelope_sizeX = (2 * coolingv2Geo.getSmallSquareSize() + coolingv2Geo.getBigSquareSize() + 2.0) *
1191 mm;
1192 double feb_alcooling_singleObjectEnvelope_sizeY = feb_alcooling_singleObjectEnvelope_sizeX * mm;
1193 double feb_alcooling_singleObjectEnvelope_sizeZ = (coolingv2Geo.getSmallSquareThickness() + coolingv2Geo.getRectangleThickness()) *
1194 mm;
1195
1196 double feb_alcooling_box1_sizeX = coolingv2Geo.getSmallSquareSize() * mm;
1197 double feb_alcooling_box1_sizeY = feb_alcooling_box1_sizeX;
1198 double feb_alcooling_box1_sizeZ = coolingv2Geo.getSmallSquareThickness() * mm;
1199
1200 double feb_alcooling_box2_sizeX = coolingv2Geo.getBigSquareSize() * mm;
1201 double feb_alcooling_box2_sizeY = feb_alcooling_box2_sizeX;
1202 double feb_alcooling_box2_sizeZ = coolingv2Geo.getBigSquareThickness() * mm;
1203
1204 double feb_alcooling_box3_sizeX = coolingv2Geo.getRectangleW() * mm;
1205 double feb_alcooling_box3_sizeY = coolingv2Geo.getRectangleL() * mm;
1206 double feb_alcooling_box3_sizeZ = coolingv2Geo.getRectangleThickness() * mm;
1207
1208 double feb_alcooling_box1_X0 = feb_alcooling_box2_sizeX / 2.0 + feb_alcooling_box1_sizeX / 2.0;
1209 double feb_alcooling_box1_Y0 = feb_alcooling_box2_sizeY / 2.0 + feb_alcooling_box1_sizeY / 2.0;
1210 double feb_alcooling_box1_Z0 = 0.0 * mm;
1211
1212 //double feb_alcooling_box2_X0 = 0.0*mm;
1213 //double feb_alcooling_box2_Y0 = 0.0*mm;
1214 //double feb_alcooling_box2_Z0 = 0.0*mm;
1215
1216 double feb_alcooling_box3_X0 = coolingv2Geo.getRectangleDistanceFromCenter() / sqrt(2.0) * mm;
1217 double feb_alcooling_box3_Y0 = feb_alcooling_box3_X0;
1218 double feb_alcooling_box3_Z0 = feb_alcooling_box1_sizeZ / 2.0 + feb_alcooling_box3_sizeZ / 2.0;
1219 double feb_alcooling_box3_angle = 45.0 * deg;
1220
1221 G4RotationMatrix Ra;
1222 G4ThreeVector Ta;
1223 G4Transform3D Tr;
1224
1225 //
1226 // Define single FEB aluminum cooling envelope
1227 //
1228 G4VSolid* feb_alcoolingEnvelope_solid = new G4Box("feb_alcoolingEnvelope_solid",
1229 feb_alcooling_singleObjectEnvelope_sizeX / 2.0,
1230 feb_alcooling_singleObjectEnvelope_sizeY / 2.0,
1231 feb_alcooling_singleObjectEnvelope_sizeZ / 2.0);
1232 G4LogicalVolume* feb_alcoolingEnvelope_logical = new G4LogicalVolume(feb_alcoolingEnvelope_solid, Materials::get("Air"),
1233 "feb_alcoolingEnvelope_logical");
1234
1235 G4VSolid* feb_alcooling_box1_solid = new G4Box("feb_alcooling_box1_solid", feb_alcooling_box1_sizeX / 2.0,
1236 feb_alcooling_box1_sizeY / 2.0, feb_alcooling_box1_sizeZ / 2.0);
1237 G4VSolid* feb_alcooling_box2_solid = new G4Box("feb_alcooling_box2_solid", feb_alcooling_box2_sizeX / 2.0,
1238 feb_alcooling_box2_sizeY / 2.0, feb_alcooling_box2_sizeZ / 2.0);
1239 G4VSolid* feb_alcooling_box3_solid = new G4Box("feb_alcooling_box3_solid", feb_alcooling_box3_sizeX / 2.0,
1240 feb_alcooling_box3_sizeY / 2.0, feb_alcooling_box3_sizeZ / 2.0);
1241
1242 //
1243 //Box 1 A
1244 //
1245 Ta.setX(feb_alcooling_box1_X0);
1246 Ta.setY(feb_alcooling_box1_Y0);
1247 Ta.setZ(feb_alcooling_box1_Z0);
1248 Tr = G4Transform3D(Ra, Ta);
1249 G4UnionSolid* feb_alcooling_assembly01_solid = new G4UnionSolid("feb_alcooling_assembly01_solid", feb_alcooling_box2_solid,
1250 feb_alcooling_box1_solid, Tr);
1251 //
1252 //Box 1 B
1253 //
1254 Ta.setX(-feb_alcooling_box1_X0);
1255 Ta.setY(-feb_alcooling_box1_Y0);
1256 Ta.setZ(feb_alcooling_box1_Z0);
1257 Tr = G4Transform3D(Ra, Ta);
1258 G4UnionSolid* feb_alcooling_assembly02_solid = new G4UnionSolid("feb_alcooling_assembly02_solid", feb_alcooling_assembly01_solid,
1259 feb_alcooling_box1_solid, Tr);
1260 //
1261 //Box 3 A
1262 //
1263 Ta.setX(feb_alcooling_box3_X0);
1264 Ta.setY(feb_alcooling_box3_Y0);
1265 Ta.setZ(feb_alcooling_box3_Z0);
1266 Ra.rotateZ(-feb_alcooling_box3_angle);
1267 Tr = G4Transform3D(Ra, Ta);
1268 G4UnionSolid* feb_alcooling_assembly03_solid = new G4UnionSolid("feb_alcooling_assembly03_solid", feb_alcooling_assembly02_solid,
1269 feb_alcooling_box3_solid, Tr);
1270 Ra.rotateZ(feb_alcooling_box3_angle);
1271 //
1272 //Box 3 B
1273 //
1274 Ta.setX(-feb_alcooling_box3_X0);
1275 Ta.setY(-feb_alcooling_box3_Y0);
1276 Ta.setZ(feb_alcooling_box3_Z0);
1277 Ra.rotateZ(-feb_alcooling_box3_angle);
1278 Tr = G4Transform3D(Ra, Ta);
1279 G4UnionSolid* feb_alcooling_assembly_solid = new G4UnionSolid("feb_alcooling_assembly_solid", feb_alcooling_assembly03_solid,
1280 feb_alcooling_box3_solid, Tr);
1281 Ra.rotateZ(feb_alcooling_box3_angle);
1282
1283 G4LogicalVolume* feb_alcooling_assembly_logical = new G4LogicalVolume(feb_alcooling_assembly_solid, Materials::get("Al"),
1284 "feb_alcooling_assembly_logical");
1285 Ta.setX(0.0);
1286 Ta.setY(0.0);
1287 Ta.setZ(-feb_alcooling_box3_sizeZ / 2.0);
1288
1289 Tr = G4Transform3D(Ra, Ta);
1290 new G4PVPlacement(Tr, //Transformation
1291 feb_alcooling_assembly_logical, //its logical volume
1292 "feb_alcooling_assembly", //its name
1293 feb_alcoolingEnvelope_logical, //its mother volume
1294 false, //no boolean operation
1295 0); //copy number
1296
1297 return feb_alcoolingEnvelope_logical;
1298 }
1299
1300 G4LogicalVolume* GeoARICHCreator::buildCoolingTube(const unsigned i_volumeID, const ARICHGeoCooling& coolingGeo)
1301 {
1302
1303 B2ASSERT("ARICH cooling geometry ID (G4Tube) is wrong : coolingGeo.getCoolingGeometryID.at(i_volumeID) != 1",
1304 coolingGeo.getCoolingGeometryID().at(i_volumeID) == 1);
1305 G4Tubs* coolingTube_solid = new G4Tubs("coolingTube_solid",
1306 coolingGeo.getRmin() * mm,
1307 coolingGeo.getRmax() * mm,
1308 coolingGeo.getCoolingL().at(i_volumeID) * mm / 2.0,
1309 0.0,
1310 2.0 * M_PI);
1311 return new G4LogicalVolume(coolingTube_solid, Materials::get(coolingGeo.getCoolingPipeMaterialName()), "ARICH.coolingTube");
1312
1313 }
1314
1315 G4LogicalVolume* GeoARICHCreator::buildCoolingTorus(const unsigned i_volumeID, const ARICHGeoCooling& coolingGeo)
1316 {
1317
1318 B2ASSERT("ARICH cooling geometry ID (G4Torus) is wrong : coolingGeo.getCoolingGeometryID.at(i_volumeID) != 2",
1319 coolingGeo.getCoolingGeometryID().at(i_volumeID) == 2);
1320
1321 double pSPhi = coolingGeo.getCoolingPosPhi().at(i_volumeID) * deg - coolingGeo.getCoolingL().at(
1322 i_volumeID) / coolingGeo.getCoolingPosR().at(i_volumeID) / 2.0;
1323 //double pDPhi = coolingGeo.getCoolingPosPhi().at(i_volumeID)*deg + coolingGeo.getCoolingL().at(i_volumeID) / coolingGeo.getCoolingPosR().at(i_volumeID) / 2.0;
1324 double pDPhi = coolingGeo.getCoolingL().at(i_volumeID) / coolingGeo.getCoolingPosR().at(i_volumeID);
1325
1326 G4Torus* coolingTorus_solid = new G4Torus("coolingTorus_solid", // name
1327 coolingGeo.getRmin(), // pRmin
1328 coolingGeo.getRmax(), // pRmax
1329 coolingGeo.getCoolingPosR().at(i_volumeID), // pRtor
1330 pSPhi, // pSPhi
1331 pDPhi); // pDPhi
1332
1333 return new G4LogicalVolume(coolingTorus_solid, Materials::get(coolingGeo.getCoolingPipeMaterialName()), "ARICH.coolingTorus");
1334
1335 }
1336
1338 {
1339
1340 G4Tubs* coolingEnvelope_solid = new G4Tubs("coolingEnvelope_solid",
1341 coolingGeo.getEnvelopeInnerRadius(),
1342 coolingGeo.getEnvelopeOuterRadius(),
1343 coolingGeo.getEnvelopeThickness() / 2.0,
1344 0.0,
1345 2.0 * M_PI);
1346 G4LogicalVolume* coolingEnvelope_logical = new G4LogicalVolume(coolingEnvelope_solid,
1347 Materials::get("Air"),
1348 "ARICH.coolingEnvelope");
1349
1350 unsigned nComponents = coolingGeo.getCoolingGeometryID().size();
1351
1352 for (unsigned i = 0; i < nComponents; i++) {
1353 double r = coolingGeo.getCoolingPosR().at(i) * mm;
1354 double phi = coolingGeo.getCoolingPosPhi().at(i) * deg;
1355 G4ThreeVector Ta;
1356 G4RotationMatrix Ra;
1357 G4LogicalVolume* coolingComponentLV;
1358 if (coolingGeo.getCoolingGeometryID().at(i) == 1) {
1359 //<!-- 1 -> G4Tubs --> build a tube
1360 Ta.set(r * cos(phi), r * sin(phi), 0);
1361 //First need to rotate around y axis
1362 //to make the tube parallel with x axis
1363 Ra.rotateY(90.0 * deg);
1364 Ra.rotateZ(coolingGeo.getCoolinRotationAngle().at(i) * deg);
1365 coolingComponentLV = buildCoolingTube(i, coolingGeo);
1366 } else if (coolingGeo.getCoolingGeometryID().at(i) == 2) {
1367 //<!-- 2 -> G4Torus --> build a torus
1368 coolingComponentLV = buildCoolingTorus(i, coolingGeo);
1369 } else {
1370 B2FATAL("ARICH cooling geometry component ID is wrong");
1371 }
1372 new G4PVPlacement(G4Transform3D(Ra, Ta), //Transformation
1373 coolingComponentLV, //its logical volume
1374 "ARICH.cooling", //its name
1375 coolingEnvelope_logical, //its mother volume
1376 false, //no boolean operation
1377 i); //copy number
1378 }
1379
1380 return coolingEnvelope_logical;
1381
1382 }
1383
1385 {
1386
1387 G4Box* coolingTestPlateEnvelop_solid = new G4Box("coolingTestPlateEnvelop_solid",
1388 coolingGeo.getCoolingTestPlateslengths().X() / 2.0 * mm,
1389 coolingGeo.getCoolingTestPlateslengths().Y() / 2.0 * mm,
1390 coolingGeo.getCoolingTestPlateslengths().Z() / 2.0 * mm);
1391 G4LogicalVolume* coolingTestPlateEnvelop_logical = new G4LogicalVolume(coolingTestPlateEnvelop_solid, Materials::get("Air"),
1392 "ARICH.coolingTestPlateEnvelop");
1393
1394 G4Box* coolingTestPlate_solid = new G4Box("coolingTestPlate_solid",
1395 coolingGeo.getCoolingTestPlateslengths().X() / 2.0 * mm,
1396 coolingGeo.getCoolingTestPlateslengths().Y() / 2.0 * mm,
1397 coolingGeo.getCoolingTestPlateslengths().Z() / 2.0 * mm);
1398
1399 // Volume to subtract
1400 G4VSolid* coldTubeSubtracted_solid = new G4Tubs("coldTubeSubtracted_solid",
1401 0.0,
1402 coolingGeo.getColdTubeSubtractedR() * mm,
1403 (coolingGeo.getCoolingTestPlateslengths().X() + 1) / 2.0 * mm,
1404 0, 360.0 * deg);
1405
1406 // Volume to add (cold tube)
1407 G4VSolid* coldTube_solid = new G4Tubs("coldTube_solid",
1408 (coolingGeo.getColdTubeR() - coolingGeo.getColdTubeWallThickness()) * mm,
1409 coolingGeo.getColdTubeR() * mm,
1410 coolingGeo.getCoolingTestPlateslengths().X() / 2.0 * mm,
1411 0, 360.0 * deg);
1412 G4LogicalVolume* coldTube_logical = new G4LogicalVolume(coldTube_solid, Materials::get(coolingGeo.getColdTubeMaterialName()),
1413 "ARICH.coldTube");
1414
1415 G4RotationMatrix Ra_sub;
1416 G4ThreeVector Ta_sub;
1417 G4Transform3D Tr_sub;
1418 Ta_sub.setX(0.0);
1419 Ta_sub.setY((coolingGeo.getCoolingTestPlateslengths().Y() / 2.0 - coolingGeo.getColdTubeSpacing()) * mm);
1420 Ta_sub.setZ((coolingGeo.getCoolingTestPlateslengths().Z() / 2.0 - coolingGeo.getDepthColdTubeInPlate()) * mm);
1421 Ra_sub.rotateY(90.0 * deg);
1422 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1423 G4SubtractionSolid* substraction_solid = new G4SubtractionSolid("substraction_solid", coolingTestPlate_solid,
1424 coldTubeSubtracted_solid, Tr_sub);
1425 for (int i = 1; i < coolingGeo.getColdTubeNumber(); i++) {
1426 Ta_sub.setX(0.0);
1427 Ta_sub.setY((coolingGeo.getCoolingTestPlateslengths().Y() / 2.0 - coolingGeo.getColdTubeSpacing() - coolingGeo.getColdTubeSpacing()
1428 * 2 * i) * mm);
1429 Ta_sub.setZ((coolingGeo.getCoolingTestPlateslengths().Z() / 2.0 - coolingGeo.getDepthColdTubeInPlate()) * mm);
1430 Tr_sub = G4Transform3D(Ra_sub, Ta_sub);
1431 substraction_solid = new G4SubtractionSolid("substraction_solid", substraction_solid, coldTubeSubtracted_solid, Tr_sub);
1432 }
1433
1434 G4LogicalVolume* coolingTestPlate_logical = new G4LogicalVolume(substraction_solid,
1435 Materials::get(coolingGeo.getCoolingTestPlateMaterialName()), "ARICH.coolingTestPlate");
1436
1437 new G4PVPlacement(G4Transform3D(), //Transformation
1438 coolingTestPlate_logical, //its logical volume
1439 "ARICH.coolingTestPlate", //its name
1440 coolingTestPlateEnvelop_logical, //its mother volume
1441 false, //no boolean operation
1442 0); //copy number
1443 //Add cold tubes
1444 G4RotationMatrix Ra;
1445 G4ThreeVector Ta;
1446 G4Transform3D Tr;
1447 Ra.rotateY(90.0 * deg);
1448 for (int i = 0; i < coolingGeo.getColdTubeNumber(); i++) {
1449 Ta.setX(0.0);
1450 Ta.setY((coolingGeo.getCoolingTestPlateslengths().Y() / 2.0 - coolingGeo.getColdTubeSpacing() - coolingGeo.getColdTubeSpacing() *
1451 2 * i) * mm);
1452 Ta.setZ((coolingGeo.getCoolingTestPlateslengths().Z() / 2.0 - coolingGeo.getDepthColdTubeInPlate()) * mm);
1453 Tr = G4Transform3D(Ra, Ta);
1454 new G4PVPlacement(Tr, //Transformation
1455 coldTube_logical, //its logical volume
1456 "ARICH.coldTube", //its name
1457 coolingTestPlateEnvelop_logical, //its mother volume
1458 false, //no boolean operation
1459 0); //copy number
1460 }
1461
1462 return coolingTestPlateEnvelop_logical;
1463
1464 }
1465
1467 {
1468
1469 const ARICHGeoDetectorPlane& detGeo = detectorGeo.getDetectorPlane();
1470
1471 G4Tubs* supportTube = new G4Tubs("supportTube", detGeo.getSupportInnerR(), detGeo.getSupportOuterR(),
1472 (detGeo.getSupportThickness() + detGeo.getSupportBackWallHeight()) / 2., 0, 2 * M_PI);
1473 G4Material* supportMaterial = Materials::get(detGeo.getSupportMaterial());
1474 G4LogicalVolume* detSupportLV = new G4LogicalVolume(supportTube, supportMaterial, "ARICH.detectorSupportPlate");
1475
1476 G4Tubs* supportPlate = new G4Tubs("supportPlate", detGeo.getSupportInnerR(), detGeo.getSupportOuterR(),
1477 detGeo.getSupportThickness() / 2., 0, 2 * M_PI);
1478
1479 G4Box* hole = new G4Box("hole", detGeo.getModuleHoleSize() / 2., detGeo.getModuleHoleSize() / 2.,
1480 detGeo.getSupportThickness() / 2.); // +1 for thickness for subtraction solid
1481 G4LogicalVolume* holeLV = new G4LogicalVolume(hole, Materials::get("Air"), "ARICH.detectorSupportHole");
1482
1483 int nRings = detGeo.getNRings();
1484 std::vector<G4LogicalVolume*> hapdBackRadialWallLV;
1485 double backWallThick = detGeo.getSupportBackWallThickness();
1486 double backWallHeight = detGeo.getSupportBackWallHeight();
1487
1488 G4LogicalVolume* hapdSupportPlateLV = new G4LogicalVolume(supportPlate, supportMaterial, "hapdSupport");
1489
1490 std::vector<double> wallR;
1491 wallR.assign(nRings + 1, 0);
1492 std::vector<double> thickR;
1493 thickR.assign(nRings + 1, 0);
1494
1495 for (int i = 1; i < nRings; i++) {
1496 double rm1 = detGeo.getRingR(i);
1497 double rp1 = detGeo.getRingR(i + 1);
1498 wallR[i] = (rp1 + rm1) / 2.;
1499 if (i == 1) {
1500 wallR[0] = rm1 - (rp1 - rm1) / 2.;
1501 }
1502 if (i == nRings - 1) {
1503 wallR[i + 1] = rp1 + (rp1 - rm1) / 2.;
1504 }
1505 }
1506
1507 for (int i = 0; i < nRings + 1; i++) {
1508 std::stringstream ringName1;
1509 ringName1 << "backWall_" << i;
1510 thickR[i] = backWallThick;
1511 if (i == nRings) {
1512 thickR[i] = 2.*backWallThick;
1513 wallR[i] = detGeo.getSupportOuterR() - thickR[i] / 2.;
1514 }
1515 G4Tubs* backTube = new G4Tubs("hapdBackRing", wallR[i] - thickR[i] / 2., wallR[i] + thickR[i] / 2., backWallHeight / 2., 0,
1516 2 * M_PI);
1517 G4LogicalVolume* hapdBackTubeLV = new G4LogicalVolume(backTube, supportMaterial, "backTube");
1518 G4Transform3D transform3 = G4Translate3D(0., 0., detGeo.getSupportThickness() / 2.);
1519 new G4PVPlacement(transform3, hapdBackTubeLV, "backTube", detSupportLV, false, 1);
1520 if (i == 0) continue;
1521
1522 G4Box* backRadial = new G4Box("backRadialBox", (wallR[i] - wallR[i - 1] - thickR[i] / 2. - thickR[i - 1] / 2.) / 2. - 1.,
1523 backWallThick / 2., backWallHeight / 2.);
1524 hapdBackRadialWallLV.push_back(new G4LogicalVolume(backRadial, supportMaterial, ringName1.str().c_str()));
1525 }
1526
1527 G4SubtractionSolid* substraction = NULL;
1528 unsigned nSlots = detGeo.getNSlots();
1529
1530 if (nSlots > detectorGeo.getFEBCoolingGeometry().getFebcoolingv2GeometryID().size()) {
1531 B2WARNING("GeoARICHCreator: No FEB colling body geometry available so they will not be placed (ARICHGeometryConfig with ClasDef>4 is needed).");
1532 return detSupportLV;
1533 }
1534
1535 // drill holes in support plate
1536 // add FEB cooling bodies
1537 for (unsigned iSlot = 1; iSlot < nSlots + 1; iSlot++) {
1538 unsigned iRing = detGeo.getSlotRing(iSlot);
1539 double r = (wallR[iRing] + wallR[iRing - 1]) / 2. - (thickR[iRing] - thickR[iRing - 1]) / 2.;
1540
1541 double phi = detGeo.getSlotPhi(iSlot);
1542 G4ThreeVector trans(r * cos(phi), r * sin(phi), 0);
1543 G4RotationMatrix Ra;
1544 Ra.rotateZ(phi);
1545
1546 new G4PVPlacement(G4Transform3D(Ra, trans), holeLV, "hole", hapdSupportPlateLV, false, iSlot);
1547 if (substraction) substraction = new G4SubtractionSolid("Box+CylinderMoved", substraction, hole, G4Transform3D(Ra, trans));
1548 else substraction = new G4SubtractionSolid("Box+CylinderMoved", supportPlate, hole, G4Transform3D(Ra, trans));
1549
1550 phi = phi + detGeo.getRingDPhi(iRing) / 2.;
1551 G4ThreeVector transBack(r * cos(phi), r * sin(phi), detGeo.getSupportThickness() / 2.);
1552 G4RotationMatrix RaBack;
1553 RaBack.rotateZ(phi);
1554 new G4PVPlacement(G4Transform3D(RaBack, transBack), hapdBackRadialWallLV[iRing - 1], "hapdBack", detSupportLV, false, iSlot);
1555
1556 // add FEB cooling bodies
1557 G4ThreeVector febCoolingTa;
1558 G4Transform3D febCoolingTr;
1559 febCoolingTa.setX(r * cos(detGeo.getSlotPhi(iSlot)));
1560 febCoolingTa.setY(r * sin(detGeo.getSlotPhi(iSlot)));
1561
1562 double supportTube_envelope_dZ = (detGeo.getSupportThickness() + detGeo.getSupportBackWallHeight());
1563 double febCooling_envelope_dZ = (detectorGeo.getFEBCoolingGeometry().getBigSquareThickness() +
1565 double febCooling_envelope_Z0 = -supportTube_envelope_dZ / 2.0 + febCooling_envelope_dZ / 2.0 + detGeo.getSupportThickness();
1566 febCoolingTa.setZ(febCooling_envelope_Z0);
1567
1568 int febcoolingv2GeometryID = detectorGeo.getFEBCoolingGeometry().getFebcoolingv2GeometryID().at(iSlot - 1);
1569
1570 if (febcoolingv2GeometryID == 2) Ra.rotateZ(90.0 * deg);
1571
1572 febCoolingTr = G4Transform3D(Ra, febCoolingTa);
1573
1574 if (febcoolingv2GeometryID != 0) {
1575 G4LogicalVolume* febCoolingLV = buildFEBCoolingBody(detectorGeo.getFEBCoolingGeometry());
1576
1577 new G4PVPlacement(febCoolingTr, //Transformation
1578 febCoolingLV, //its logical volume
1579 "febCoolingLV", //its name
1580 detSupportLV, //its mother volume
1581 false, //no boolean operation
1582 iSlot); //copy number
1583 }
1584 }
1585
1586 // G4LogicalVolume* hapdSupportPlateLV = new G4LogicalVolume(substraction, supportMaterial, "hapdSupport");
1587
1588 G4Transform3D transform3 = G4Translate3D(0., 0., - backWallHeight / 2.);
1589 new G4PVPlacement(transform3, hapdSupportPlateLV, "supportPlate", detSupportLV, false, 1);
1590
1591 // place electronics side neutron shield - for now hardcoded here, pending for more proper implementation!
1592 G4Box* shieldBox1 = new G4Box("shieldBox1", 20. / 2., 75. / 2., backWallHeight / 2.);
1593 G4Box* shieldBox2 = new G4Box("shieldBox2", 55. / 2., 40. / 2., backWallHeight / 2.);
1594 G4LogicalVolume* shield1 = new G4LogicalVolume(shieldBox1, Materials::get("BoratedPoly"), "ARICH.FWDShield1");
1595 G4LogicalVolume* shield2 = new G4LogicalVolume(shieldBox2, Materials::get("BoratedPoly"), "ARICH.FWDShield2");
1596 double dphi = 2 * M_PI / 36.;
1597 double r1 = wallR[0] - 15.;
1598 double r2 = wallR[0] - 15. - 20. / 2. - 55. / 2.;
1599 for (int i = 0; i < 36; i++) {
1600 double phi = (i + 0.5) * dphi;
1601 G4RotationMatrix rot;
1602 rot.rotateZ(phi);
1603 G4ThreeVector trans(r1 * cos(phi), r1 * sin(phi), detGeo.getSupportThickness() / 2.);
1604 G4ThreeVector trans1(r2 * cos(phi), r2 * sin(phi), detGeo.getSupportThickness() / 2.);
1605 new G4PVPlacement(G4Transform3D(rot, trans), shield1, "ARICH.FWDShield1", detSupportLV, false, i);
1606 new G4PVPlacement(G4Transform3D(rot, trans1), shield2, "ARICH.FWDShield2", detSupportLV, false, i);
1607 }
1608
1609 return detSupportLV;
1610 }
1611
1612
1613 G4LogicalVolume* GeoARICHCreator::buildMirror(const ARICHGeometryConfig& detectorGeo)
1614 {
1615
1616 const ARICHGeoMirrors& mirrGeo = detectorGeo.getMirrors();
1617
1618 // read m_config
1619 string mirrMat = mirrGeo.getMaterial();
1620 G4Material* mirrorMaterial = Materials::get(mirrMat);
1621
1622 double mThick = mirrGeo.getPlateThickness();
1623 double mLength = mirrGeo.getPlateLength();
1624 double mWidth = mirrGeo.getPlateWidth();
1625
1626 G4Box* mirrPlate = new G4Box("mirrPlate", mThick / 2., mLength / 2., mWidth / 2.);
1627
1628 G4LogicalVolume* lmirror = new G4LogicalVolume(mirrPlate, mirrorMaterial, "ARICH.mirrorPlate");
1629
1630 Materials& materials = Materials::getInstance();
1631
1632 G4OpticalSurface* optSurf = materials.createOpticalSurface(mirrGeo.getMirrorSurface());
1633 new G4LogicalSkinSurface("mirrorSurface", lmirror, optSurf);
1634
1635 return lmirror;
1636
1637 }
1638
1639 double GeoARICHCreator::getAvgRINDEX(G4Material* material)
1640 {
1641 G4MaterialPropertiesTable* mTable = material->GetMaterialPropertiesTable();
1642 if (!mTable) return 0;
1643 G4MaterialPropertyVector* mVector = mTable->GetProperty("RINDEX");
1644 if (!mVector) return 0;
1645 G4bool b;
1646 return mVector->GetValue(2 * Unit::eV / Unit::MeV, b);
1647 }
1648
1649 void GeoARICHCreator::makeJoint(G4Material* supportMaterial, const std::vector<double>& par, G4AssemblyVolume* assemblyWedge)
1650 {
1651
1652 int size = par.size();
1653 if (size < 4 || size > 8) B2ERROR("GeoARICHCreator::makeJoint: invalid number of joint wedge parameters");
1654 double lenx = par.at(0);
1655 double leny = par.at(1);
1656 double lenz = par.at(2);
1657 double thick = par.at(3);
1658
1659 G4Box* wedgeBox1 = new G4Box("wedgeBox1", thick / 2., lenx / 2., leny / 2.);
1660 G4Box* wedgeBox2 = new G4Box("wedgeBox2", lenz / 2., lenx / 2., thick / 2.);
1661
1662 G4LogicalVolume* wedgeBox1LV = new G4LogicalVolume(wedgeBox1, supportMaterial, "ARICH.supportWedge");
1663 G4LogicalVolume* wedgeBox2LV = new G4LogicalVolume(wedgeBox2, supportMaterial, "ARICH.supportWedge");
1664
1665 G4RotationMatrix Rm;
1666 G4ThreeVector Ta(0, 0, 0);
1667 G4Transform3D Tr;
1668 Tr = G4Transform3D(Rm, Ta);
1669
1670 assemblyWedge->AddPlacedVolume(wedgeBox1LV, Tr);
1671
1672 Ta.setX(lenz / 2. + thick / 2.);
1673 Ta.setZ(leny / 2. - thick / 2.);
1674 Tr = G4Transform3D(Rm, Ta);
1675 assemblyWedge->AddPlacedVolume(wedgeBox2LV, Tr);
1676
1677 if (size == 4) return;
1678 double edge = par.at(4);
1679
1680 G4Box* wedgeBox3 = new G4Box("wedgeBox3", lenz / 2., edge / 2., thick / 2.);
1681 G4LogicalVolume* wedgeBox3LV = new G4LogicalVolume(wedgeBox3, supportMaterial, "ARICH.supportWedge");
1682
1683 Ta.setZ(leny / 2. - thick - thick / 2.);
1684 Tr = G4Transform3D(Rm, Ta);
1685 assemblyWedge->AddPlacedVolume(wedgeBox3LV, Tr);
1686
1687 G4Trap* wedgeBoxTmp = new G4Trap("wedgeBoxTmp", thick, leny - 2 * thick, lenz, edge);
1688 G4LogicalVolume* wedgeBox4LV;
1689 if (size == 8) {
1690 G4Tubs* wedgeBoxTmp1 = new G4Tubs("wedgeBoxTmp1", 0.0, par.at(5), thick, 0, 2.*M_PI);
1691 G4RotationMatrix rotHole;
1692 G4ThreeVector transHole(par.at(6), par.at(7), 0);
1693 G4SubtractionSolid* wedgeBox4 = new G4SubtractionSolid("wedgeBox4", wedgeBoxTmp, wedgeBoxTmp1, G4Transform3D(rotHole, transHole));
1694 wedgeBox4LV = new G4LogicalVolume(wedgeBox4, supportMaterial, "ARICH.supportWedge");
1695 } else wedgeBox4LV = new G4LogicalVolume(wedgeBoxTmp, supportMaterial, "ARICH.supportWedge");
1696
1697 Rm.rotateX(-M_PI / 2.);
1698 Ta.setX(thick / 2. + edge / 4. + lenz / 4.);
1699 Ta.setZ(-thick / 2. - edge / 2.);
1700 Tr = G4Transform3D(Rm, Ta);
1701 assemblyWedge->AddPlacedVolume(wedgeBox4LV, Tr);
1702
1703 }
1704
1705 // simple geometry for beamtest setup
1706 /* void GeoARICHCreator::createSimple(const GearDir& content, G4LogicalVolume& topVolume)
1707 {
1708
1709 B2INFO("ARICH simple (beamtest) geometry will be built.")
1710 GearDir envelopeParams(content, "Envelope");
1711 double xSize = envelopeParams.getLength("xSize") / Unit::mm;
1712 double ySize = envelopeParams.getLength("ySize") / Unit::mm;
1713 double zSize = envelopeParams.getLength("zSize") / Unit::mm;
1714 string envMat = envelopeParams.getString("material");
1715 G4Material* envMaterial = Materials::get(envMat);
1716
1717 G4Box* envBox = new G4Box("envBox", xSize / 2., ySize / 2., zSize / 2.);
1718 G4LogicalVolume* lenvBox = new G4LogicalVolume(envBox, envMaterial, "ARICH.envelope");
1719 new G4PVPlacement(G4Transform3D(), lenvBox, "ARICH.envelope", &topVolume, false, 1);
1720 setVisibility(*lenvBox, false);
1721 ARICHGeometryPar* m_arichgp = ARICHGeometryPar::Instance();
1722 m_arichgp->Initialize(content);
1723 GearDir moduleParam(content, "Detector/Module");
1724 G4LogicalVolume* detModule = buildModule(moduleParam);
1725
1726 double detZpos = content.getLength("Detector/Plane/zPosition") / Unit::mm;
1727 double detThick = content.getLength("Detector/Module/moduleZSize") / Unit::mm;
1728 int nModules = m_arichgp->getNMCopies();
1729 for (int i = 1; i <= nModules; i++) {
1730 G4ThreeVector origin = m_arichgp->getOriginG4(i); origin.setZ(detZpos + detThick / 2.);
1731 double angle = m_arichgp->getModAngle(i);
1732 G4RotationMatrix Ra;
1733 Ra.rotateZ(angle);
1734 G4Transform3D trans = G4Transform3D(Ra, origin);
1735 new G4PVPlacement(G4Transform3D(Ra, origin), detModule, "detModule", lenvBox, false, i);
1736 }
1737
1738 // place aerogel tiles
1739 GearDir aerogelParam(content, "Aerogel");
1740 double sizeX = aerogelParam.getLength("tileXSize") / Unit::mm;
1741 double sizeY = aerogelParam.getLength("tileYSize") / Unit::mm;
1742 double posX = aerogelParam.getLength("tileXPos") / Unit::mm;
1743 double posY = aerogelParam.getLength("tileYPos") / Unit::mm;
1744 int ilayer = 0;
1745 BOOST_FOREACH(const GearDir & layer, aerogelParam.getNodes("Layers/Layer")) {
1746 double posZ = layer.getLength("zPosition");
1747 double sizeZ = layer.getLength("thickness");
1748 string tileMat = layer.getString("material");
1749 G4Material* tileMaterial = Materials::get(tileMat);
1750 double rInd = getAvgRINDEX(tileMaterial);
1751 m_arichgp->setAeroRefIndex(ilayer, rInd);
1752 m_arichgp->setAerogelZPosition(ilayer, posZ);
1753 m_arichgp->setAerogelThickness(ilayer, sizeZ);
1754
1755 G4MaterialPropertiesTable* mTable = tileMaterial->GetMaterialPropertiesTable();
1756 G4MaterialPropertyVector* mVector = mTable->GetProperty("RAYLEIGH");
1757 double lambda0 = 400;
1758 double e0 = 1240. / lambda0 * Unit::eV / Unit::MeV;
1759 G4bool b;
1760 m_arichgp->setAeroTransLength(ilayer, mVector->GetValue(e0, b)*Unit::mm);
1761 G4Box* tileBox = new G4Box("tileBox", sizeX / 2., sizeY / 2., sizeZ / 2. / Unit::mm);
1762 G4LogicalVolume* lTile = new G4LogicalVolume(tileBox, tileMaterial, "Tile", 0, m_sensitiveAero);
1763 setColor(*lTile, "rgb(0.0, 1.0, 1.0,1.0)");
1764 G4Transform3D trans = G4Translate3D(posX, posY, posZ / Unit::mm + sizeZ / 2. / Unit::mm);
1765 ilayer++;
1766 new G4PVPlacement(trans, lTile, "ARICH.tile", lenvBox, false, ilayer);
1767 }
1768
1769 // place mirrors
1770 GearDir mirrorsParam(content, "Mirrors");
1771 double height = mirrorsParam.getLength("height") / Unit::mm;
1772 double width = mirrorsParam.getLength("width") / Unit::mm;
1773 double thickness = mirrorsParam.getLength("thickness") / Unit::mm;
1774 string mirrMat = mirrorsParam.getString("material");
1775 G4Material* mirrMaterial = Materials::get(mirrMat);
1776 G4Box* mirrBox = new G4Box("mirrBox", thickness / 2., height / 2., width / 2.);
1777 G4LogicalVolume* lmirror = new G4LogicalVolume(mirrBox, mirrMaterial, "mirror");
1778
1779 Materials& materials = Materials::getInstance();
1780 GearDir surface(mirrorsParam, "Surface");
1781 G4OpticalSurface* optSurf = materials.createOpticalSurface(surface);
1782 new G4LogicalSkinSurface("mirrorsSurface", lmirror, optSurf);
1783 int iMirror = 0;
1784 BOOST_FOREACH(const GearDir & mirror, mirrorsParam.getNodes("Mirror")) {
1785 double xpos = mirror.getLength("xPos") / Unit::mm;
1786 double ypos = mirror.getLength("yPos") / Unit::mm;
1787 double zpos = mirror.getLength("zPos") / Unit::mm;
1788 double angle = mirror.getAngle("angle") / Unit::rad;
1789 G4ThreeVector origin(xpos, ypos, zpos + width / 2.);
1790 G4RotationMatrix Ra;
1791 Ra.rotateZ(angle);
1792 G4Transform3D trans = G4Transform3D(Ra, origin);
1793 new G4PVPlacement(G4Transform3D(Ra, origin), lmirror, "ARICH.mirror", lenvBox, false, iMirror);
1794 iMirror++;
1795 }
1796 }
1797 */
1798
1799 } // namespace aricih
1801} // namespace belleII
Geometry parameters of HAPD.
const std::vector< double > & getSimpleParams() const
Get parameters of simple aerogel configuration.
bool isSimple() const
Use simple aerogel configuration.
double getLayerThickness(unsigned iLayer) const
Get thickness of tiles in i-th aerogel layer.
double getSupportThickness() const
Get support-plate thickness.
unsigned getNRings() const
Get number of aluminum wall rings (should be number of tile rings + 1).
double getSupportOuterR() const
Get support-plate outer radius.
double getCompensationARICHairVolumeThick_min() const
Get minimum thickness of the compensation volume with ARICH air.
double getImgTubeThickness() const
Get imaginary tube thikness just after aerogel layers used as volume to which tracks are extrapolated...
double getWallHeight() const
Get height of aluminum walls between aerogel tiles.
double getRingDPhi(unsigned iRing) const
Get phi (angle) distance between "phi" aluminum wall between aerogel tiles in i-th tile ring.
double getRotationY() const
Get angle of rotation around Y axis.
double getRotationZ() const
Get angle of rotation around Z axis.
double getTileThickness(int ring, int column, int layerN) const
Get thickness of individual tile.
const std::string & getLayerMaterial(unsigned iLayer) const
Get material name of tiles in i-th aerogel layer.
const std::string & getSupportMaterial() const
Get material of support plate.
double getWallThickness() const
Get thickness of aluminum walls between aerogel tiles.
double getRingRadius(unsigned iRing) const
Get radius of i-th aluminum ring between aerogel tiles (inner radius of ring).
unsigned getNLayers() const
Get number of aerogel layers.
ROOT::Math::XYZVector getPosition() const
Get position vector of aerogel plane in ARICH local frame.
double getSupportInnerR() const
Get support-plate inner radius.
int getFullAerogelMaterialDescriptionKey() const
Get full aerogel material description key.
std::string getTileMaterialName(int ring, int column, int layerN) const
Get material name of individual tile.
double getMaximumTotalTileThickness() const
Get maximum total thickness of the aerogel tiles tile_up + tile_down for all the slots.
double getTileGap() const
Get gap between aerogel tile and aluminum wall.
double getRotationX() const
Get angle of rotation around X axis.
Geometry parameters of cable envelope.
const std::string & getCablesEffectiveMaterialName() const
Returns Effective material name describing cables.
double getEnvelopeOuterRadius() const
Returns Outer radius of cables envelop.
ROOT::Math::XYZVector getEnvelopeCenterPosition() const
Returns position vector (ROOT::Math::XYZVector) of cables envelop.
double getEnvelopeInnerRadius() const
Returns Inner radius of cables envelop.
double getEnvelopeThickness() const
Returns Thickness of cables envelop.
Geometry parameters of cooling system.
double getColdTubeWallThickness() const
Get cold tube wall thickness.
const std::vector< double > & getCoolinRotationAngle() const
Get vector of azimuthal angle of rotation aroud Z - axis of the cooling system object in polar coordi...
const std::vector< double > & getCoolingPosPhi() const
Get vector of azimuthal angle of the cooling system object center in polar coordinate system in deg.
double getEnvelopeOuterRadius() const
Get outer radius of cooling system assembly envelope.
const std::vector< double > & getCoolingGeometryID() const
Get vector of cooling system object geometry ID.
double getColdTubeSpacing() const
Get distance from center of the cold tube to edge of cooling plate.
const std::string & getCoolingPipeMaterialName() const
Get material name of cooling pipe.
double getColdTubeR() const
Get radius of cold tubes.
const std::vector< double > & getCoolingL() const
Get vector of lengs of the cooling system object with given geometry ID.
const std::vector< double > & getCoolingPosR() const
Get vector of radial distance (r, pho) of the cooling system object center in polar coordinate system...
const std::string & getColdTubeMaterialName() const
Get material name of cold tube.
const std::string & getCoolingTestPlateMaterialName() const
Get material name of cooling test plates.
ROOT::Math::XYZVector getEnvelopeCenterPosition() const
Get position vector (ROOT::Math::XYZVector) of cooling system assembly envelope.
double getRmax() const
Get size of cooling system pipe : outer radius in mm.
double getEnvelopeInnerRadius() const
Get inner radius of cooling system assembly envelope.
ROOT::Math::XYZVector getCoolingTestPlateslengths() const
Get sizes vector (ROOT::Math::XYZVector) of cooling test plates.
double getRmin() const
Get size of cooling system pipe : inner radius in mm.
double getDepthColdTubeInPlate() const
Get depth of the cold tube in the cooling plate.
double getEnvelopeThickness() const
Get thickness of cooling system assembly envelope.
double getColdTubeSubtractedR() const
Get outer radius of subtracted tubes for cold tube.
int getColdTubeNumber() const
Get number of cold tubes in one plate.
Geometry parameters of ARICH photon detector plane.
unsigned getNSlots() const
Get total number of module slots.
unsigned getSlotRing(unsigned slotID) const
Get ring number of slot with slot ID.
double getSupportBackWallHeight() const
Get height of the aluminum walls between modules on the electronics side of aluminum support plate.
double getSlotR(unsigned modID) const
Get radial position of module with given module ID number.
double getSupportBackWallThickness() const
Get thickness of aluminum walls between modules on the electronics side of aluminum support plate.
double getSupportThickness() const
Get support plate thickness.
unsigned getNRings() const
Get number of module slot rings.
double getSupportOuterR() const
Get support plate outer radius.
double getSupportZPosition() const
Get Z position of support plate (start point in Z).
double getRingDPhi(unsigned iRing) const
Get phi (angle) distance between module slots in i-th ring.
double getRotationY() const
Get angle of rotation around Y axis.
double getRotationZ() const
Get angle of rotation around Z axis.
double getSlotPhi(unsigned modID) const
Get phi (angle) position of module with given module ID number.
double getModuleHoleSize() const
Get size of module hole in support plate.
const std::string & getSupportMaterial() const
Get material of support plate.
ROOT::Math::XYZVector getPosition() const
Get center point.
double getSupportInnerR() const
Get support plate inner radius.
double getRingR(unsigned iRing) const
Get radius of i-th module slot ring (radius of center point).
double getRotationX() const
Get angle of rotation around X axis.
Geometry parameters of Cooling System - version2 (v2).
double getBigSquareThickness() const
Returns thickness of the big square in mm.
double getBigSquareSize() const
Returns size of the big square in mm.
double getSmallSquareSize() const
Returns size of the small square in mm.
double getRectangleThickness() const
Returns thickness of the rectangle in mm.
double getSmallSquareThickness() const
Returns thickness of the small square in mm.
const std::vector< double > & getFebcoolingv2GeometryID() const
Returns vector of feb cooling configuration/geometry ID.
double getRectangleW() const
Returns width of the rectangle in mm.
double getRectangleL() const
Returns length of the rectangle in mm.
double getRectangleDistanceFromCenter() const
Returns distance from center of the rectangle in mm.
double getGamma() const
Returns rotation angle around z.
double getX() const
Returns translation in x.
double getAlpha() const
Returns rotation angle around x.
double getZ() const
Returns translation in z.
double getY() const
Returns translation in y.
double getBeta() const
Returns rotation angle around y.
Geometry parameters of HAPD.
Definition: ARICHGeoHAPD.h:24
double getSizeZ() const
Returns HAPD size in z.
Definition: ARICHGeoHAPD.h:174
const std::string & getFEBMaterial() const
Returns FEB material name.
Definition: ARICHGeoHAPD.h:289
double getAPDSizeZ() const
Returns APD size in z.
Definition: ARICHGeoHAPD.h:204
double getWinThickness() const
Returns window thickness.
Definition: ARICHGeoHAPD.h:186
const std::string & getAPDMaterial() const
Returns APD material name.
Definition: ARICHGeoHAPD.h:283
const GeoOpticalSurface & getAPDSurface() const
Returns APD reflective optical surface.
Definition: ARICHGeoHAPD.h:295
const std::string & getWallMaterial() const
Returns wall (casing) material name.
Definition: ARICHGeoHAPD.h:265
const std::string & getFillMaterial() const
Returns fill (inside) material name.
Definition: ARICHGeoHAPD.h:271
double getSizeX() const
Returns HAPD size in x.
Definition: ARICHGeoHAPD.h:162
double getSizeY() const
Returns HAPD size in y.
Definition: ARICHGeoHAPD.h:168
double getFEBSizeY() const
Returns FEB size in y.
Definition: ARICHGeoHAPD.h:216
double getWallThickness() const
Returns wall thickness.
Definition: ARICHGeoHAPD.h:180
double getFEBSizeZ() const
Returns FEB size in z.
Definition: ARICHGeoHAPD.h:222
const std::string & getWinMaterial() const
Returns window material name.
Definition: ARICHGeoHAPD.h:277
double getModuleSizeZ() const
Returns module size in z (HAPD + FEB height)
Definition: ARICHGeoHAPD.h:228
double getAPDSizeY() const
Returns APD size in y.
Definition: ARICHGeoHAPD.h:198
double getFEBSizeX() const
Returns FEB size in x.
Definition: ARICHGeoHAPD.h:210
double getAPDSizeX() const
Returns APD size in x.
Definition: ARICHGeoHAPD.h:192
ROOT::Math::XYZVector pointToGlobal(const ROOT::Math::XYZVector &point) const
Transform local point into global Belle II coordinate system via rotation and translation.
double getRotationY() const
Get angle of rotation around Y axis.
double getRotationZ() const
Get angle of rotation around Z axis.
double getOuterRadius() const
Get ARICH master volume outer radius.
double getInnerRadius() const
Get ARICH master volume inner radius.
const std::string & getMaterial() const
Get material of ARICH master volume.
ROOT::Math::XYZVector getPosition() const
Get position of ARICH master volume center point in global Belle II coordinates.
double getLength() const
Get ARICH master volume length.
double getRotationX() const
Get angle of rotation around X axis.
Geometry parameters of Merger PCB.
const std::vector< double > & getSingleMergerenvelopeDeltaZ() const
Returns vector of Z position of the single merger and merger cooling body envelope inside global merg...
double getMergerPCBscrewholeR() const
Returns merger PCB screw hole radius.
double getSingleMergerEnvelopeThickness() const
Returns single merger PCB and merger cooling envelop thickness.
double getSizeW() const
Returns merger PCB width.
double getMergerPCBscrewholePosdX1() const
Returns merger PCB screw hole position from the bottom edge.
double getEnvelopeOuterRadius() const
Returns Outer radius of merger PCB assembly envelope.
const std::vector< double > & getMergerSlotID() const
Returns vector of merger boards slot numbers.
double getMergerPCBscrewholePosdX2() const
Returns merger PCB screw hole position from the top edge.
const std::vector< double > & getMergerAngle() const
Returns vector of merger boarts azimuthal angles in polar coordinate system in deg.
double getThickness() const
Returns merger PCB thickness.
ROOT::Math::XYZVector getSingleMergeEnvelopePosition() const
Returns position vector (ROOT::Math::XYZVector) of merger PCB inside the single merger envelope.
ROOT::Math::XYZVector getEnvelopeCenterPosition() const
Returns position vector (ROOT::Math::XYZVector) of merger PCB assembly envelope.
const std::vector< double > & getMergerOrientation() const
Returns vector of merger boarts orientations in deg.
const std::vector< double > & getMergerPosR() const
Returns vector of merger boards distances from the center in mm.
const std::string & getMergerPCBMaterialName() const
Returns merger PCB material name.
double getSingleMergerEnvelopeSizeW() const
Returns single merger PCB and merger cooling envelop width.
double getEnvelopeInnerRadius() const
Returns Inner radius of merger PCB assembly envelope.
double getSingleMergerEnvelopeSizeL() const
Returns single merger PCB and merger cooling envelop length.
double getSizeL() const
Returns merger PCB lenght.
double getEnvelopeThickness() const
Returns Thickness of merger PCB assembly envelope.
double getMergerPCBscrewholePosdY() const
Returns merger PCB screw hole position from the left and right sides.
const ARICHPositionElement & getDisplacementElement(int mirrorID) const
Returns displacement parameters for given mirror plate.
Geometry parameters of HAPD.
const GeoOpticalSurface & getMirrorSurface() const
Returns mirror reflective optical surface.
double getZPosition() const
Get nominal Z position of mirror plates (center point in ARICH local frame)
unsigned getNMirrors() const
Get number of mirror plates.
double getPlateWidth() const
Get width of mirror plate.
const std::string & getMaterial() const
Get material name of mirror plates.
double getPlateLength() const
Get length of mirror plate.
double getRadius() const
Get nominal radius at which mirror plates are placed (center of plate)
double getStartAngle() const
Get phi angle of position of the first mirror plate.
double getPlateThickness() const
Get thickness of mirror plate.
Geometry parameters of ARICH support structures and neutron shield.
double getWedgeR(unsigned i) const
Get radius at which i-th wedge is placed.
double getWedgePhi(unsigned i) const
Get phi angle at which i-th wedge is placed.
const std::vector< double > getWedge(unsigned i) const
Get parameters of wedge.
double getTubeInnerR(unsigned i) const
Get tube inner radius.
double getTubeLength(unsigned i) const
Get tube length.
double getTubeOuterR(unsigned i) const
Get tube outer radius.
double getWedgeZ(unsigned i) const
Get Z position of i-th wedge.
unsigned getNTubes() const
Get number of tube volumes to be placed.
const std::string & getTubeMaterial(unsigned i) const
Get material of i-th tube.
int getWedgeType(unsigned i) const
Get type of i-th wedge.
unsigned getNWedges() const
Get number of wedges to be placed.
double getTubeZPosition(unsigned i) const
Get tube Z position.
const std::string & getWedgeMaterial(unsigned i) const
Get material of i-th wedge.
box getBox(unsigned i) const
Get box paramaters.
const std::string & getTubeName(unsigned i) const
Get name of i-th tube.
unsigned getNBoxes() const
Get number of box volumes.
The Class for ARICH Geometry Parameters.
const ARICHGeoAerogelPlane & getAerogelPlane() const
Get geometry configuration of aerogel plane.
const ARICHGeoMerger & getMergerGeometry() const
Get Merger PCB geometry parameters.
static void useGeantUnits()
Use Geant4 units when returning geometry parameters.
const ARICHGeoGlobalDisplacement & getGlobalDisplacement() const
Get global displacement parameters.
const ARICHGeoFEBCooling & getFEBCoolingGeometry() const
Get ARICH FEB cooling system (v2) geometry parameters.
bool useMirrorDisplacement() const
Get whether mirror displacement is used.
const ARICHGeoMasterVolume & getMasterVolume() const
Get ARICH master volume geometry configuration.
const ARICHGeoCooling & getCoolingGeometry() const
Get ARICH cooling system geometry parameters.
const ARICHGeoMirrors & getMirrors() const
Get mirrors geometry configuration.
const ARICHGeoCablesEnvelope & getCablesEnvelope() const
Get ARICH cables envelop geometry parameters.
static void useBasf2Units()
Use basf2 units when returning geometry parameters.
const ARICHGeoHAPD & getHAPDGeometry() const
Get HAPD geometry parameters.
bool useGlobalDisplacement() const
Get whether global displacement is used.
const ARICHGeoDetectorPlane & getDetectorPlane() const
Get geometry configuration of HAPD plane.
const ARICHGeoMirrorDisplacement & getMirrorDisplacement() const
Get mirror displacement parameters.
const ARICHGeoSupport & getSupportStructure() const
Get ARICH support structure geometry configuration.
Position element for ARICH.
The Class for BeamBackground Sensitive Detector.
static const double eV
[electronvolt]
Definition: Unit.h:112
static const double MeV
[megaelectronvolt]
Definition: Unit.h:114
G4LogicalVolume * buildSimpleAerogelPlane(const ARICHGeometryConfig &detectorGeo)
build simple aerogel plane (for cosmic test)
G4LogicalVolume * buildHAPD(const ARICHGeoHAPD &hapdPar)
build the HAPD modules
void makeJoint(G4Material *supportMaterial, const std::vector< double > &pars, G4AssemblyVolume *assemblyWedge)
build joints of the ARICH support structure
virtual ~GeoARICHCreator()
The destructor of the GeoARICHreator class.
OptionalDBObjPtr< ARICHGeoMergerCooling > m_mergerCooling
merger cooling bodies geometry from the DB
G4LogicalVolume * buildMergerPCBEnvelopePlane(const ARICHGeometryConfig &detectorGeo)
build merger PCB assembly envelope plane
G4LogicalVolume * buildFEBCoolingBody(const ARICHGeoFEBCooling &coolingv2Geo)
build FEB cooling bodies (cooling system update after phase 2)
G4LogicalVolume * buildCoolingTorus(const unsigned i_volumeID, const ARICHGeoCooling &coolingGeo)
build cooling tube (G4Torus)
G4LogicalVolume * buildAerogelPlaneAveragedOverLayers(const ARICHGeometryConfig &detectorGeo)
build aerogel plane with average properties of aerogel per layer
G4LogicalVolume * buildCables(const ARICHGeoCablesEnvelope &cablesGeo)
build the cables envelop with effective material describing cables
G4LogicalVolume * buildMergerCooling(unsigned iType)
build merger cooling bodies (cooling system update after phase 2)
double getAvgRINDEX(G4Material *material)
get refractive index of the material
G4LogicalVolume * buildCoolingTube(const unsigned i_volumeID, const ARICHGeoCooling &coolingGeo)
build cooling tube (G4Tubs)
void createGeometry(G4LogicalVolume &topVolume, geometry::GeometryTypes type)
Create detector geometry.
G4LogicalVolume * buildDetectorSupportPlate(const ARICHGeometryConfig &detectorGeo)
build detector support plate
DBObjPtr< ARICHModulesInfo > m_modInfo
information on installed modules from the DB
G4LogicalVolume * buildAerogelPlane(const ARICHGeometryConfig &detectorGeo)
build aerogel plane
GeoARICHCreator()
Constructor of the GeoARICHCreator class.
SensitiveAero * m_sensitiveAero
pointer to sensitive aerogel - used instead of tracking
G4LogicalVolume * buildDetectorPlane(const ARICHGeometryConfig &detectorGeo)
build detector plane
ARICHGeometryConfig m_config
geometry configuration
G4LogicalVolume * buildCoolingEnvelopePlane(const ARICHGeoCooling &coolingGeo)
build cooling system assembly envelope plane
int m_isBeamBkgStudy
flag the beam background study
G4LogicalVolume * buildMergerEnvelope(const ARICHGeoMerger &mergerGeo, int type)
build single merger and merger cooling body envelope logical volume
G4LogicalVolume * buildMerger(const ARICHGeoMerger &mergerGeo)
build the merger PCB logical volume
SensitiveDetector * m_sensitive
pointer to sensitive detector
G4LogicalVolume * buildAerogelPlaneWithIndividualTilesProp(const ARICHGeometryConfig &detectorGeo)
with individual properties of aerogel tiles
G4LogicalVolume * buildMirror(const ARICHGeometryConfig &detectorGeo)
build mirrors
G4LogicalVolume * buildCoolingTestPlate(const ARICHGeoCooling &coolingGeo)
build cooling test plates
This is optional (temporary) class that provides information on track parameters on aerogel plane,...
Definition: SensitiveAero.h:22
The Class for ARICH Sensitive Detector.
Thin wrapper around the Geant4 Material system.
Definition: Materials.h:48
static G4Material * get(const std::string &name)
Find given material.
Definition: Materials.h:63
static Materials & getInstance()
Get a reference to the singleton instance.
Definition: Materials.cc:85
G4OpticalSurface * createOpticalSurface(const gearbox::Interface &parameters)
Create an optical surface from parameters, will abort on error.
Definition: Materials.cc:295
int doBeamBackgroundStudy() const
returns 1 if beam background study (to add additional sensitive modules, detect neutrons,...
double sqrt(double a)
sqrt for double
Definition: beamHelpers.h:28
void setVisibility(G4LogicalVolume &volume, bool visible)
Helper function to quickly set the visibility of a given volume.
Definition: utilities.cc:108
void setColor(G4LogicalVolume &volume, const std::string &color)
Set the color of a logical volume.
Definition: utilities.cc:100
GeometryTypes
Flag indiciating the type of geometry to be used.
Abstract base class for different kinds of events.
STL namespace.
Struct to hold parameters of box volumes (examples, scintilators for cosmic test)
std::string material
material
double rotation[3]
rotation coordinates
double position[3]
position coordinates
double size[3]
size coordinates
Structure which holds apexes of the tessellation volumes.
std::vector< std::vector< double > > posV1
x, y, z of apex1.
std::vector< std::vector< double > > posV3
x, y, z of apex3.
std::vector< std::vector< double > > posV2
x, y, z of apex2.
unsigned int nCells
number of cells