LBNFTargetModule.cc
Go to the documentation of this file.
1 // Code that defines the volumes and placements of the target module (e.g. SAT)
2 // which includes some engineering details. John Back, March 2016.
3 
5 
6 #include "G4Material.hh"
7 #include "G4LogicalVolume.hh"
8 #include "G4PVPlacement.hh"
9 #include "G4RotationMatrix.hh"
10 #include "G4Sphere.hh"
11 #include "G4ThreeVector.hh"
12 #include "G4Tubs.hh"
13 #include "G4VPhysicalVolume.hh"
14 #include "G4UnionSolid.hh"
15 
16 #include "LBNERunManager.hh"
18 
19 #include <iostream>
20 #include <sstream>
21 
23 
24  std::cout << "Initialising the target module parameters for type = " << fTargetModuleType << std::endl;
25  std::cout << "Target radius = " << fTargetRadius << std::endl;
26  std::cout << "Target total original length = " << fTargetLength << std::endl;
27 
28  // Change the target object length if we have set the required number of interaction lengths
29  bool useLambda(false);
30 
31  if (fTargetNLambda > -1.0 && fTargetDensity > 0.0) {
32 
33  std::cout << "Updating target object length using interaction length info:" << std::endl;
35  std::cout << "Specific lambda = " << fTargetSpecificLambda*CLHEP::cm2/CLHEP::g
36  << ", rho = " << fTargetDensity*CLHEP::cm3/CLHEP::g << ", NLambda = "
37  << fTargetNLambda << " => target L = " << fTargetLength << std::endl;
38 
39  useLambda = true;
40 
41  }
42 
44 
46 
47  std::cout << "Checking length for SAT" << std::endl;
48 
49  double tolerance = 0.005*CLHEP::mm; // 5 micron tolerance
50  double diameter = fTargetRadius*2.0;
51  double NumNominal = fTargetLength/(diameter + tolerance);
52 
53  // If we have specified the number of interaction lengths, then
54  // find the required number of spheres using the full calculation
55  // given in LBNE-doc-9547 (Quynh) assuming a Gaussian beam
56  if (useLambda) {NumNominal = this->FindNTargetSpheres(1);}
57  std::cout << "Nominal number of spheres = " << NumNominal << std::endl;
58 
59  // Round to nearest integer
60  fNumTargetObjects = (int) (NumNominal + 0.5);
61  std::cout << "Number of spheres rounded to "<< fNumTargetObjects <<std::endl;
62 
63  // Update the total "useful" length of the SAT, i.e. the sum of the length of the spheres
65  std::cout << "SAT total length adjusted to " << fTargetLength << std::endl;
66 
67  }
68 
69  // The diameter thickness of the supporting rods, which also leaves a gap for He gas flow
70  // in the remaining azimuthal areas. For the cylinder target, we have just the gap, no rods
71  fTargetSupportD = 2.5*CLHEP::mm;
72  std::cout << "Target module support radial thickness = " << fTargetSupportD << std::endl;
73 
74  // Thickness of the titanium tube casings
75  fTargetCaseT = 1.0*CLHEP::mm;
76  std::cout << "Target module Ti casing thickness = " << fTargetCaseT << std::endl;
77 
78  // The He gas gap between the two inner and outer Ti cylindrical casings
79  fTargetHeGap = 4.0*CLHEP::mm;
80  std::cout << "Target module He gap between casings = " << fTargetHeGap << std::endl;
81 
82  // Inner radius of the outer casing
84  std::cout << "Target module inner radius of outer Ti casing = " << fTargetOutCaseInnerR << std::endl;
85 
86  // The length of the inner canister holding the spheres
87  fTargetInCaseUpL = 50.0*CLHEP::mm; // Could also use fTargetRadius if we want to scale the size to rSphere?
88  fTargetInCaseDnL = 5.0*CLHEP::mm;
90 
91  // The length of the outer target module canister
92  fTargetCaseDiffL = 5.0*CLHEP::mm;
94 
95  // Total length of the target module, including the end bulb of the outer canister
97  std::cout << "Target module total length = " << fTargetModuleTotL << std::endl;
98 
99  // Also update the target length outside the horn if we have specified the fraction.
100  // By default, this fraction is not set (=-1), with fTargetLengthOutsideHorn = 450.0 mm.
101  // The length includes the outer canister end regions
102  if (fTargetFracOutHornL > -1.0) {
103 
105  }
106 
107  std::cout << "TargetFracOutHornL = " << fTargetFracOutHornL
108  << ", TargetLengthOutsideHorn = " << fTargetLengthOutsideHorn << std::endl;
109  std::cout << "fTargetLengthOutsideExtra = " << fTargetLengthOutsideExtra << std::endl;
110 
111 }
112 
114 
115  std::cout << "Initialising the 2nd target module parameters for type = " << fTarget2ModuleType << std::endl;
116  std::cout << "Target2 radius = " << fTarget2Radius << std::endl;
117  std::cout << "Target2 total original length = " << fTarget2Length << std::endl;
118 
119  // Change the target object length if we have set the required number of interaction lengths
120  bool useLambda(false);
121 
122  if (fTarget2NLambda > -1.0 && fTarget2Density > 0.0) {
123 
124  std::cout << "Updating target 2 object length using interaction length info:" << std::endl;
126  std::cout << "Specific lambda = " << fTarget2SpecificLambda*CLHEP::cm2/CLHEP::g
127  << ", rho = " << fTarget2Density*CLHEP::cm3/CLHEP::g << ", NLambda = "
128  << fTarget2NLambda << " => target2 L = " << fTarget2Length << std::endl;
129 
130  useLambda = true;
131 
132  }
133 
134  fNumTarget2Objects = 1;
135 
137 
138  std::cout << "Checking length for 2nd SAT" << std::endl;
139 
140  double tolerance = 0.005*CLHEP::mm; // 5 micron tolerance
141  double diameter = fTarget2Radius*2.0;
142  double NumNominal = fTarget2Length/(diameter + tolerance);
143 
144  // If we have specified the number of interaction lengths, then
145  // find the required number of spheres using the full calculation
146  // given in LBNE-doc-9547 (Quynh) assuming a Gaussian beam
147  if (useLambda) {NumNominal = this->FindNTargetSpheres(2);}
148  std::cout << "Nominal number of spheres = " << NumNominal << std::endl;
149 
150  // Round to nearest integer
151  fNumTarget2Objects = (int) (NumNominal + 0.5);
152  std::cout << "Number of spheres rounded to "<< fNumTarget2Objects <<std::endl;
153 
154  // Update the total "useful" length of the SAT, i.e. the sum of the length of the spheres
156  std::cout << "SAT2 total length adjusted to " << fTarget2Length << std::endl;
157 
158  }
159 
160  // Inner radius of the outer casing
162  std::cout << "Target module 2 inner radius of outer Ti casing = " << fTarget2OutCaseInnerR << std::endl;
163 
164  // The length of the inner canister holding the spheres
166 
167  // The length of the outer target module canister
169 
170  // Total length of the target module, including the end bulb of the outer canister
172  std::cout << "Target module 2 total length = " << fTarget2ModuleTotL << std::endl;
173 
174  // Mirror image 180 degree rotation matrix: rotate around the y axis
175  fMirrorRotation = new G4RotationMatrix();
176  fMirrorRotation->rotateY(180.0*CLHEP::degree);
177 
178  // z displacement for the 2nd target module: depends on length of 1st module
179  fZModuleShift = fTargetModuleTotL + fTarget2OutCaseInnerR + fTargetCaseT + 1.0*CLHEP::mm;
180 
181 }
182 
183 G4double LBNEVolumePlacements::FindNTargetSpheres(int number) const {
184 
185  // Find the length of the target (in mm) that gives the required number of interaction lengths
186  // for the specified radius, assuming a Gaussian beam distribution based on the calculation
187  // given in LBNE-doc-9547 (Quynh).
188  // Performs the double integral of the effective interaction length for sigma = radius/3.
189  // Note that the beam parameters are defined after the geometry, so the user needs to make
190  // sure the beam sigmas are set to radius/3...
191 
192  double targetRadius = fTargetRadius;
193  double targetNLambda = fTargetNLambda;
194  double targetSpecificLambda = fTargetSpecificLambda;
195  double targetDensity = fTargetDensity;
196 
197  if (number == 2) {
198  targetRadius = fTarget2Radius;
199  targetNLambda = fTarget2NLambda;
200  targetSpecificLambda = fTarget2SpecificLambda;
201  targetDensity = fTarget2Density;
202  }
203 
204  std::cout << "Finding number of target spheres for NLambda = " << targetNLambda << std::endl;
205 
206  double xSigma = targetRadius/3.0;
207  double ySigma = targetRadius/3.0;
208  double x0(0.0), y0(0.0);
209 
210  /*
211  // This part is what we could do if the generator action is available during geometry construction:
212  LBNERunManager* theRunManager = dynamic_cast<LBNERunManager*>(G4RunManager::GetRunManager());
213  if (theRunManager) {
214 
215  const LBNEPrimaryGeneratorAction* PGA = static_cast<const LBNEPrimaryGeneratorAction*> (theRunManager->GetUserPrimaryGeneratorAction());
216 
217  if (PGA) {
218 
219  xSigma = PGA->GetBeamSigmaX();
220  ySigma = PGA->GetBeamSigmaY();
221  x0 = PGA->GetBeamOffsetX();
222  y0 = PGA->GetBeamOffsetY();
223 
224  } else {
225 
226  std::cout << "Primary generator pointer not found" << std::endl;
227  }
228 
229  }
230  */
231 
232  std::cout << "Assuming beam sigma_x = " << xSigma << ", sigma_y = " << ySigma << std::endl;
233  std::cout << "Assuming beam offset_x = " << x0 << ", offset_y = " << y0 << std::endl;
234 
235  int N(1000);
236  int N1(N+1);
237  double RSq = targetRadius*targetRadius;
238 
239  double xMin(-targetRadius);
240  double xMax(targetRadius);
241  double dx = (xMax - xMin)/(N*1.0);
242  double dy(dx);
243  double yMin(-targetRadius);
244 
245  double invXSigmaSq(0.0);
246  if (xSigma > 0.0) {invXSigmaSq = 1.0/(xSigma*xSigma);}
247  double invYSigmaSq(0.0);
248  if (ySigma > 0.0) {invYSigmaSq = 1.0/(ySigma*ySigma);}
249 
250  double norm(1.0);
251  if (xSigma > 0.0 && ySigma > 0.0) {
252  norm = 1.0/(M_PI*xSigma*ySigma);
253  }
254 
255  double result(0.0);
256 
257  int i(0), j(0);
258  for (i = 0; i < N1; i++) {
259 
260  double x = dx*i + xMin - x0;
261  double xSq = x*x;
262 
263  for (j = 0; j < N1; j++) {
264 
265  double y = dy*j + yMin - y0;
266  double ySq = y*y;
267 
268  double rSq = xSq + ySq;
269 
270  if (rSq < RSq) {
271 
272  double expPower = -0.5*(xSq*invXSigmaSq + ySq*invYSigmaSq);
273  double expTerm(0.0);
274  if (fabs(expPower) < 30.0) {expTerm = exp(expPower);}
275 
276  result += expTerm*sqrt(RSq - rSq);
277 
278  }
279 
280  } // j
281 
282  } // i
283 
284  // Normalisation
285  result *= norm*dx*dy;
286  std::cout << "Sphere double integral = " << result << std::endl;
287 
288  G4double nSpheres = targetNLambda*targetSpecificLambda/(targetDensity*result);
289  return nSpheres;
290 
291 }
292 
294 
295  std::cout << "Calling PlaceTargetModule" << number << std::endl;
296  // InitTargetModule should already be called by LBNEVolumePlacements::setEntireTargetDims()
297 
298  this->PlaceTargetOuterCan(number);
299  this->PlaceTargetInnerCan(number);
300  this->PlaceTargetSupport(number);
301  this->PlaceTargetObject(number);
302 
303 }
304 
306 
307  // Similar to TargetNoSplitM1 (and also TargetNoSplitHeContainer)
308  std::ostringstream cNumStrStr; cNumStrStr << number;
309  G4String numString = cNumStrStr.str();
310 
311  // The target hall mother volume
312  G4String outerCanName("Target");
313  outerCanName += numString; outerCanName += "OuterCan";
314 
315  const LBNEVolumePlacementData *mother = Find(outerCanName.data(), "TargetHallAndHorn1", "");
316  if (!mother) {return;}
317  double hallLength = mother->fParams[2];
318 
319  // The horn1 volume
320  const LBNEVolumePlacementData* horn1 = Find(outerCanName.data(), "Horn1PolyM1", "");
321  if (!horn1) {return;}
322 
323  // The outer canister volume
324  LBNEVolumePlacementData* canInfo = this->CreateTargetVol(outerCanName, number);
325 
326  G4ThreeVector position(0.0, 0.0, 0.0);
327 
328  // Correction for the placement of the upstream end section of the horn
329  G4double horn1Length = horn1->fParams[2];
330 
331  // This positions the downstream end of the target module at the upstream edge of the first horn
332  // which may require an additional ad-hoc z-shift correction
333  double targetModuleTotL = fTargetModuleTotL;
334  if (number == 2) {targetModuleTotL = fTarget2ModuleTotL;}
335 
336  position[2] = 0.5*hallLength - horn1Length - 0.5*targetModuleTotL;
337  // Take into account how much of the target needs to be inside the horn
338  G4double targetInHorn = targetModuleTotL - fTargetLengthOutsideHorn;
339  position[2] += targetInHorn;
340 
341  // Specify the rotation matrix for what will become the mother volume of the target module.
342  // All other internal volumes will respect this rotation
343  G4RotationMatrix* rotMatrix = 0;
344  if (number == 2) {
345  position[2] += fZModuleShift;
346  rotMatrix = fMirrorRotation;
347  }
348 
349  // If using the conceptual design horn set-up LBNFConceptDesignHorns::PlaceFinalLBNFConceptHornA()
350  // then we need to shift the target module further upstream relative to the mother volume Horn1PolyM1,
351  // owing to the larger gap downstream between the target end and the remaining hall/horn1 space.
352  // This positions the start of the target module very close to z = 0 m
353  if (fUseLBNFOptimConceptDesignHornA) {position[2] -= 31.0*CLHEP::cm;}
354 
355  new G4PVPlacement(rotMatrix, position, canInfo->fCurrent,
356  (outerCanName + "_P"), mother->fCurrent, false, 0, fCheckVolumeOverLapWC);
357 
358  // The helium gas inside the outer canister
359  G4String heName("Target");
360  heName += numString; heName += "OuterHeGas";
361  LBNEVolumePlacementData* heInfo = this->CreateTargetVol(heName, number);
362 
363  // Simply place this helium region inside its mother volume, TargetOuterCan
364  new G4PVPlacement((G4RotationMatrix*) 0, G4ThreeVector(0.0, 0.0, 0.0), heInfo->fCurrent,
365  (heName + "_P"), canInfo->fCurrent, false, 0, fCheckVolumeOverLapWC);
366 
367 
368 }
369 
371 
372  std::ostringstream cNumStrStr; cNumStrStr << number;
373  G4String numString = cNumStrStr.str();
374 
375  G4String innerCanName("Target");
376  innerCanName += numString; innerCanName += "InnerCan";
377 
378  G4String outerHeName("Target");
379  outerHeName += numString; outerHeName += "OuterHeGas";
380 
381  const LBNEVolumePlacementData* mother = Find(innerCanName, outerHeName, "");
382  if (!mother) {return;}
383 
384  // The inner canister volume
385  LBNEVolumePlacementData* canInfo = this->CreateTargetVol(innerCanName, number);
386 
387  double zShift = -0.5*fTargetCaseDiffL;
388  G4ThreeVector position(0.0, 0.0, zShift);
389 
390  new G4PVPlacement((G4RotationMatrix*) 0, position, canInfo->fCurrent,
391  (innerCanName + "_P"), mother->fCurrent, false, 0, fCheckVolumeOverLapWC);
392 
393  // The inner canister helium volume
394  G4String innerHeName("Target");
395  innerHeName += numString; innerHeName += "InnerHeGas";
396  LBNEVolumePlacementData* heInfo = this->CreateTargetVol(innerHeName, number);
397 
398  new G4PVPlacement((G4RotationMatrix*) 0, G4ThreeVector(0.0, 0.0, 0.0), heInfo->fCurrent,
399  (innerHeName + "_P"), canInfo->fCurrent, false, 0, fCheckVolumeOverLapWC);
400 
401 }
402 
404 
405  // We do not need the internal support rods for the cylinder, but we still keep
406  // the fTargetSupportD gap to allow for the He gas flow
407  int targetModuleType = fTargetModuleType;
408  if (number == 2) {targetModuleType = fTarget2ModuleType;}
409  if (targetModuleType == LBNEVolumePlacements::Cylinder) {return;}
410 
411  std::ostringstream cNumStrStr; cNumStrStr << number;
412  G4String numString = cNumStrStr.str();
413 
414  G4String supportName("Target");
415  supportName += numString; supportName += "Support";
416 
417  G4String innerHeName("Target");
418  innerHeName += numString; innerHeName += "InnerHeGas";
419 
420  // The target support rods are placed inside the inner He gas region
421  const LBNEVolumePlacementData* mother = Find(supportName, innerHeName, "");
422  if (!mother) {return;}
423 
424  // The support rods; place 3 of these separated by 120 degrees in the x-y plane
425  LBNEVolumePlacementData* rodInfo = this->CreateTargetVol(supportName, number);
426 
427  G4double x0 = 0.0;
428  G4double y0 = fTargetRadius + 0.5*fTargetSupportD;
429  if (number == 2) {y0 = fTarget2Radius + 0.5*fTargetSupportD;}
430 
431  int i(0);
432  for (i = 0; i < 3; i++) {
433 
434  G4double phi = -M_PI*120.0*i/180.0;
435  G4double cPhi = cos(phi);
436  G4double sPhi = sin(phi);
437  G4double x = x0*cPhi - y0*sPhi;
438  G4double y = y0*cPhi + x0*sPhi;
439  G4double z = 0.0;
440 
441  //std::cout<<"Target support rod: phi = "<<phi*180.0/M_PI<<", x = "<<x<<", y = "<<y<<std::endl;
442  G4ThreeVector position(x, y, z);
443 
444  std::ostringstream sNumStrStr; sNumStrStr << i;
445  new G4PVPlacement((G4RotationMatrix*) 0, position, rodInfo->fCurrent,
446  (supportName + "_P" + sNumStrStr.str()),
447  mother->fCurrent, false, 0, fCheckVolumeOverLapWC);
448 
449  }
450 
451 }
452 
454 
455  // Retrieve the mother volume for the spheres, which is the inner He gas regions
456  std::ostringstream cNumStrStr; cNumStrStr << number;
457  G4String numString = cNumStrStr.str();
458 
459  G4String label("Target"); label += numString;
460  int targetModuleType = fTargetModuleType;
461  if (number == 2) {targetModuleType = fTarget2ModuleType;}
462 
463  if (targetModuleType == LBNEVolumePlacements::Cylinder) {
464  label += "Cylinder";
465  } else {
466  label += "Sphere";
467  }
468 
469  G4String innerHeName("Target");
470  innerHeName += numString; innerHeName += "InnerHeGas";
471  const LBNEVolumePlacementData *mother = Find(label, innerHeName, "");
472  if (!mother) {return;}
473 
474  LBNEVolumePlacementData* placeInfo = this->CreateTargetVol(label, number);
475 
476  G4ThreeVector position(0.0, 0.0, 0.0);
477 
478  double targetRadius = fTargetRadius;
479  double targetInCaseL = fTargetInCaseL;
480  int numTargetObjects = fNumTargetObjects;
481  if (number == 2) {
482  targetRadius = fTarget2Radius;
483  targetInCaseL = fTarget2InCaseL;
484  numTargetObjects = fNumTarget2Objects;
485  }
486 
487  // Spherical array target set-up
488  if (targetModuleType == LBNEVolumePlacements::SAT) {
489 
490  // The start of the first sphere
491  double z0 = -0.5*targetInCaseL + fTargetInCaseUpL + targetRadius;
492  position[2] = z0;
493 
494  double tolerance = 0.005*CLHEP::mm;
495 
496  int iSph(0);
497  // Loop over all spheres
498  for (iSph = 0; iSph < numTargetObjects; iSph++) {
499 
500  position[2] = z0 + iSph*(targetRadius*2.0 + tolerance);
501 
502  std::ostringstream sNumStrStr; sNumStrStr << iSph;
503  new G4PVPlacement((G4RotationMatrix*) 0, position, placeInfo->fCurrent,
504  (label + "_P" + sNumStrStr.str()),
505  mother->fCurrent, false, iSph, fCheckVolumeOverLapWC);
506 
507  }
508 
509  } else if (targetModuleType == LBNEVolumePlacements::Cylinder) {
510 
511  // Just place the cylinder in the middle of the inner He gas volume
512  new G4PVPlacement((G4RotationMatrix*) 0, position, placeInfo->fCurrent,
513  (label + "_P"), mother->fCurrent, false, 0, fCheckVolumeOverLapWC);
514 
515  }
516 
517 }
518 
519 LBNEVolumePlacementData* LBNEVolumePlacements::CreateTargetVol(const G4String &volName, int number) {
520 
521  // Based on LBNEVolumePlacements::Create() but put here in order to reduce
522  // the huge size of that function...
523 
524  // Check to see if the volume has already been created
526  if (itDupl != fSubVolumes.end()) {
527  std::ostringstream mStrStr;
528  mStrStr << " Volume named " << volName << " Already defined. Fatal ";
529  G4String mStr(mStrStr.str());
530  G4Exception("LBNEVolumePlacements::Create", " ", FatalErrorInArgument, mStr.c_str());
531  }
532 
534  info.initialize();
535 
536  // Check that the volume name at least contains "Target". Otherwise ignore it
537  std::ostringstream cNumStrStr; cNumStrStr << number;
538  G4String numString = cNumStrStr.str();
539  G4String targetLabel("Target"); targetLabel += numString;
540 
541  if (!volName.contains("Target")) {return 0;}
542 
543  double targetRadius = fTargetRadius;
544  double targetLength = fTargetLength;
545  double targetOutCaseInnerR = fTargetOutCaseInnerR;
546  double targetOutCaseL = fTargetOutCaseL;
547  double targetModuleTotL = fTargetModuleTotL;
548  double targetInCaseL = fTargetInCaseL;
549  if (number == 2) {
550  targetRadius = fTarget2Radius;
551  targetLength = fTarget2Length;
552  targetOutCaseInnerR = fTarget2OutCaseInnerR;
553  targetOutCaseL = fTarget2OutCaseL;
554  targetModuleTotL = fTarget2ModuleTotL;
555  targetInCaseL = fTarget2InCaseL;
556  }
557 
558  //G4cout<<"CreateTargetVol: r = "<<targetRadius<<", L = "<<targetLength<<", OCIR = "<<targetOutCaseInnerR
559  // <<", OCL = "<<targetOutCaseL<<", ModTotL = "<<targetModuleTotL<<", ICL = "<<targetInCaseL<<G4endl;
560 
561  if (volName.contains("Sphere")) {
562 
563  // One of the target spheres
564  info.fParams[0] = 0.0;
565  info.fParams[1] = targetRadius;
566  info.fParams[2] = 0.0;
567  G4Sphere* aSphere = new G4Sphere(volName,
568  info.fParams[0], //inner radius = 0
569  info.fParams[1], //outer radius
570  0.0, 360.0*CLHEP::degree,
571  0.0, 180.0*CLHEP::degree); //Phi and Theta angles
572 
573  info.fCurrent = new G4LogicalVolume(aSphere, G4Material::GetMaterial(targetLabel), volName);
574 
575  } else if (volName.contains("Cylinder")) {
576 
577  // The target cylinder object
578  info.fParams[0] = 0.0;
579  info.fParams[1] = targetRadius;
580  info.fParams[2] = targetLength;
581  G4Tubs* aTube = new G4Tubs(volName, 0.0, targetRadius,
582  0.5*targetLength, // half-length
583  0.0, 360.0*CLHEP::degree); // Phi angle extent
584 
585  info.fCurrent = new G4LogicalVolume(aTube, G4Material::GetMaterial(targetLabel), volName);
586 
587  } else if (volName.contains("OuterCan")) {
588 
589  // The outer canister, containing the union of a tube with a downstream spherical "bulb"
590  double innerR = 0.0;
591  double outerR = targetOutCaseInnerR + fTargetCaseT;
592  double halfTubeL = 0.5*targetOutCaseL;
593 
594  // The cylindrical tube section
595  G4String tubeName(volName); tubeName += "Tube";
596  G4Tubs* aTube = new G4Tubs(tubeName, innerR, outerR,
597  halfTubeL, // half-length
598  0.0, 360.0*CLHEP::degree); // Phi angle extent
599 
600  // The end bulb section
601  G4String sphereName(volName); sphereName += "Sphere";
602  G4Sphere* aSphere = new G4Sphere(sphereName, innerR, outerR,
603  0.0, 360.0*CLHEP::degree,
604  0.0, 180.0*CLHEP::degree); //Phi and Theta angles
605 
606  // The union of the two volumes
607  G4UnionSolid* outerCan = new G4UnionSolid(volName, aTube, aSphere, 0, G4ThreeVector(0.0, 0.0, halfTubeL));
608 
609  info.fCurrent = new G4LogicalVolume(outerCan, G4Material::GetMaterial(std::string("Titanium")), volName);
610 
611  // Parameters: inner radius, outer radius, full length
612  info.fParams[0] = innerR;
613  info.fParams[1] = outerR;
614  info.fParams[2] = targetModuleTotL;
615 
616  } else if (volName.contains("OuterHeGas")) {
617 
618  // The outer canister, containing the union of a tube with a downstream spherical "bulb"
619  double innerR = 0.0;
620  double outerR = targetOutCaseInnerR;
621  double halfTubeL = 0.5*targetOutCaseL;
622 
623  // The cylindrical tube section
624  G4String tubeName(volName); tubeName += "Tube";
625  G4Tubs* aTube = new G4Tubs(tubeName, innerR, outerR,
626  halfTubeL, // half-length
627  0.0, 360.0*CLHEP::degree); // Phi angle extent
628 
629  // The end bulb section
630  G4String sphereName(volName); sphereName += "Sphere";
631  G4Sphere* aSphere = new G4Sphere(sphereName, innerR, outerR,
632  0.0, 360.0*CLHEP::degree,
633  0.0, 180.0*CLHEP::degree); //Phi and Theta angles
634 
635  // The union of the two volumes
636  G4UnionSolid* outerCan = new G4UnionSolid(volName, aTube, aSphere, 0, G4ThreeVector(0.0, 0.0, halfTubeL));
637 
638  info.fCurrent = new G4LogicalVolume(outerCan, G4Material::GetMaterial(std::string("HeliumTarget")), volName);
639 
640  // Parameters: inner radius, outer radius, full length
641  info.fParams[0] = innerR;
642  info.fParams[1] = outerR;
643  info.fParams[2] = targetModuleTotL - fTargetCaseT;
644 
645  } else if (volName.contains("InnerCan")) {
646 
647  // The inner, cylindrical canister of the target module
648  double innerR = 0.0;
649  double outerR = targetRadius + fTargetSupportD + fTargetCaseT;
650  double halfTubeL = 0.5*targetInCaseL;
651 
652  // The cylindrical tube section
653  G4String tubeName(volName); tubeName += "Tube";
654  G4Tubs* aTube = new G4Tubs(tubeName, innerR, outerR,
655  halfTubeL, // half-length
656  0.0, 360.0*CLHEP::degree); // Phi angle extent
657 
658  info.fCurrent = new G4LogicalVolume(aTube, G4Material::GetMaterial(std::string("Titanium")), volName);
659 
660  // Parameters: inner radius, outer radius, full length
661  info.fParams[0] = innerR;
662  info.fParams[1] = outerR;
663  info.fParams[2] = targetInCaseL;
664 
665  } else if (volName.contains("InnerHeGas")) {
666 
667  // The inner, cylindrical canister of the target module
668  double innerR = 0.0;
669  double outerR = targetRadius + fTargetSupportD;
670  double halfTubeL = 0.5*targetInCaseL;
671 
672  // The cylindrical tube section
673  G4String tubeName(volName); tubeName += "Tube";
674  G4Tubs* aTube = new G4Tubs(tubeName, innerR, outerR,
675  halfTubeL, // half-length
676  0.0, 360.0*CLHEP::degree); // Phi angle extent
677 
678  info.fCurrent = new G4LogicalVolume(aTube, G4Material::GetMaterial(std::string("HeliumTarget")), volName);
679 
680  // Parameters: inner radius, outer radius, full length
681  info.fParams[0] = innerR;
682  info.fParams[1] = outerR;
683  info.fParams[2] = targetInCaseL;
684 
685  } else if (volName.contains("Support")) {
686 
687  // The target cylinder object
688  double radius = 0.5*fTargetSupportD;
689  info.fParams[0] = 0.0;
690  info.fParams[1] = radius;
691  info.fParams[2] = targetInCaseL;
692  G4Tubs* aTube = new G4Tubs(volName, 0.0, radius,
693  0.5*targetInCaseL, // half-length
694  0.0, 360.0*CLHEP::degree); // Phi angle extent
695 
696  info.fCurrent = new G4LogicalVolume(aTube, G4Material::GetMaterial(std::string("Titanium")), volName);
697 
698  }
699 
700  // Keep track of the volume we've made
701  fSubVolumes.insert(std::pair<G4String, LBNEVolumePlacementData>(volName, info));
702 
703  return &(fSubVolumes.find(volName)->second);
704 
705 }
static QCString result
const LBNEVolumePlacementData * Find(const G4String &name, const char *motherName, const char *method) const
void PlaceTargetSupport(int number=1)
std::string string
Definition: nybbler.cc:12
double const tolerance
void PlaceTargetObject(int number=1)
intermediate_table::const_iterator const_iterator
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:45
std::map< G4String, LBNEVolumePlacementData > fSubVolumes
double y
void PlaceTargetModule(int number=1)
LBNEVolumePlacementData * CreateTargetVol(const G4String &volName, int number=1)
std::vector< double > fParams
double z
auto norm(Vector const &v)
Return norm of the specified vector.
void PlaceTargetOuterCan(int number=1)
G4RotationMatrix * fMirrorRotation
Definition: group.cpp:53
void PlaceTargetInnerCan(int number=1)
list x
Definition: train.py:276
G4double FindNTargetSpheres(int number=1) const
QTextStream & endl(QTextStream &s)