LBNEDownstrVolPlacements.cc
Go to the documentation of this file.
2 
3 #include "G4UIdirectory.hh"
4 #include "G4UIcmdWithAString.hh"
5 #include "G4UIcmdWithABool.hh"
6 #include "G4UIcmdWithAnInteger.hh"
7 #include "G4UIcmdWithADoubleAndUnit.hh"
8 #include "G4UIcmdWithoutParameter.hh"
9 #include "G4UnitsTable.hh"
10 
11 #include "G4Material.hh"
12 #include "G4Box.hh"
13 #include "G4Tubs.hh"
14 #include "G4Polycone.hh"
15 #include "G4Trap.hh"
16 #include "G4Cons.hh"
17 #include "G4Torus.hh"
18 #include "G4LogicalVolume.hh"
19 #include "G4ThreeVector.hh"
20 #include "G4PVPlacement.hh"
21 #include "G4SubtractionSolid.hh"
22 #include "G4UnionSolid.hh"
23 #include "G4VisAttributes.hh"
24 #include "globals.hh"
25 #include "G4Transform3D.hh"
26 #include "G4RotationMatrix.hh"
27 #include "G4PVReplica.hh"
28 #include "G4AssemblyVolume.hh"
29 #include "LBNEMagneticField.hh"
30 #include "G4PhysicalVolumeStore.hh"
31 #include "G4LogicalVolumeStore.hh"
32 #include "G4PVPlacement.hh"
33 #include "G4RegionStore.hh"
34 #include "G4SolidStore.hh"
35 #include "G4GeometryManager.hh"
36 #include "G4FieldManager.hh"
37 
38 #include "LBNERunManager.hh"
39 
40 #include "G4VisExtent.hh"
42 #include "LBNESurveyor.hh"
43 
44 //--- Second file for geometry: the first one (LBNEVolumePlacements) was getting to long --//
45 
46 void LBNEVolumePlacements::PlaceFinalDownstrTarget(G4PVPlacement *mother) {
47 
48  if (fUse1p2MW) {
50  return;
51  }
52 
53  Create("Horn1TargetDownstrHeContainer");
54  G4PVPlacement *vMTop = PlaceFinal(std::string("Horn1TargetDownstrHeContainer"), mother);
55  LBNEVolumePlacementData *plDowstrHe = Create("Horn1TargetDownstrHelium");
56  G4PVPlacement *vMHe = PlaceFinal(std::string("Horn1TargetDownstrHelium"), vMTop);
57  // Deal with alignment ring located in the dowstream part of the target. We assume here that
58  // they have been already defined while dealing with the Upstream target portion
59  // First alignment ring, locate flush with the end plate (within 1 mm ) , left and right
60  std::map<G4String, LBNEVolumePlacementData>::iterator itTmpRLeft = fSubVolumes.find(G4String("TargetAlignmentRingLeft"));
61  LBNEVolumePlacementData &infoTmpRLeft = itTmpRLeft->second;
62  std::map<G4String, LBNEVolumePlacementData>::iterator itTmpRRight = fSubVolumes.find(G4String("TargetAlignmentRingRight"));
63  LBNEVolumePlacementData &infoTmpRRight = itTmpRRight->second;
64  std::map<G4String, LBNEVolumePlacementData>::iterator itM1 = fSubVolumes.find(G4String("TargetUpstrDownstrHelium"));
65  LBNEVolumePlacementData *plM1 = &itM1 ->second;
66  std::map<G4String, LBNEVolumePlacementData>::iterator itMother = fSubVolumes.find(G4String("Horn1TargetDownstrHelium"));
67  LBNEVolumePlacementData *plMother = &itMother ->second;
68  G4ThreeVector posTmp;
69  posTmp[0] = 0.; // The alignment rings are always centered..
70  posTmp[1] = 0.; // We start upstream to keep the separation among rings.
71  posTmp[2] = -1.0*plM1->fParams[2]/2.0 + infoTmpRLeft.fParams[2]/2. + 1.0*CLHEP::mm; // 1 mm spacing Left and right have the same thickness.
72  int copyNumber = 0;
73  int copyNumberHere = 0;
74  bool transitionDone = false;
75  while (true) {
76  if (!transitionDone) {
77  posTmp[2] += fTargetAlignRingSpacing;
78  copyNumber++;
79  if (posTmp[2] > plM1->fParams[2]/2.0) {
80  transitionDone = true;
81  const double offset = posTmp[2] - plM1->fParams[2]/2.0;
82  posTmp[2] = -1.0*plMother->fParams[2]/2.0 + infoTmpRLeft.fParams[2]/2. + offset ;
83  }
84  } else {
85  std::ostringstream cNumStrStr; cNumStrStr << "_P" << copyNumber;
86  if (copyNumber == (fMaxNumAlignRings -1)) {
87  // retract the last one a bit by 5 mm to place the return cooling pipe.
88  posTmp[2] -= 10.0*CLHEP::mm;
89  }
90  new G4PVPlacement((G4RotationMatrix *) 0,
91  posTmp, infoTmpRLeft.fCurrent, G4String("TargetAlignmentRingLeft")+cNumStrStr.str(),
92  vMHe->GetLogicalVolume(), false, copyNumberHere, fCheckVolumeOverLapWC);
93  new G4PVPlacement((G4RotationMatrix *) 0,
94  posTmp, infoTmpRRight.fCurrent, G4String("TargetAlignmentRingRight")+ cNumStrStr.str(),
95  vMHe->GetLogicalVolume(), false, copyNumberHere, fCheckVolumeOverLapWC);
96  posTmp[2] += fTargetAlignRingSpacing;
97  copyNumber++; copyNumberHere++;
98  if ( copyNumber == fMaxNumAlignRings) break;
99  }
100  }
101  // Deal with the first, split, target segment.
102  LBNEVolumePlacementData *infoTargSegFirst = 0;
103  if (fTargetFinLengthSplitDwnstr > 0.3*CLHEP::mm) {
104  infoTargSegFirst = Create("Horn1TargetSegmentFirst");
105  G4PVPlacement *vTargSegFirst = PlaceFinal("Horn1TargetSegmentFirst", vMHe);
106  Create("Horn1TargetFinVertFirst");
107  LBNEVolumePlacementData * plCoolingTubeFirst = Create("Horn1TargetCoolingTubeFirst");
108  Create("Horn1TargetCoolingTubeFirstWater");
109  posTmp[0] = 0.; posTmp[1] = fTargetFinHeight/2.; posTmp[2] = 0.;
110  G4PVPlacement *vTubeUp = new G4PVPlacement((G4RotationMatrix *) 0,
111  posTmp, plCoolingTubeFirst->fCurrent,
112  G4String("Horn1TargetSegmentCoolingTubeFirst_PTop"),
113  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
114  posTmp[1] = -1.0*fTargetFinHeight/2.;
115  G4PVPlacement *vTubeDown = new G4PVPlacement((G4RotationMatrix *) 0,
116  posTmp, plCoolingTubeFirst->fCurrent,
117  G4String("Horn1TargetSegmentCoolingTubeFirst_PBottom"),
118  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
119  PlaceFinal("Horn1TargetCoolingTubeFirstWater", vTubeDown);
120  PlaceFinal("Horn1TargetCoolingTubeFirstWater", vTubeUp);
121  PlaceFinal("Horn1TargetFinVertFirst", vTargSegFirst);
122 //
123 // Oct. 29 2013 : add the 4 corners as well (overzealous, too much complexity already.. but makes vis. complete..
124 //
125  LBNEVolumePlacementData *plTargetFinCorDFUpLeft =
126  Create(G4String("TargetFinVertCornerDownstrFirstUpLeft"));
127  LBNEVolumePlacementData *plTargetFinCorDFUpRight =
128  Create(G4String("TargetFinVertCornerDownstrFirstUpRight"));
129  LBNEVolumePlacementData *plTargetFinCorDFDwnLeft =
130  Create(G4String("TargetFinVertCornerDownstrFirstDwnLeft"));
131  LBNEVolumePlacementData *plTargetFinCorDFDwnRight =
132  Create(G4String("TargetFinVertCornerDownstrFirstDwnRight"));
133 
134  posTmp[0] = -fTargetFinWidth/4.;
135  posTmp[1] = fTargetFinHeight/2. - fTargetCTubeOuterRadius/2. + 0.125*CLHEP::mm;
136  posTmp[2] = 0.;
137  new G4PVPlacement((G4RotationMatrix *) 0,
138  posTmp, plTargetFinCorDFUpLeft->fCurrent,
139  G4String("Horn1TargetFinVertCornerDownstrFirstUpLeft_P"),
140  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
141  posTmp[0] = fTargetFinWidth/4.; posTmp[1] = fTargetFinHeight/2. - fTargetCTubeOuterRadius/2. + 0.125*CLHEP::mm;
142  new G4PVPlacement((G4RotationMatrix *) 0,
143  posTmp, plTargetFinCorDFUpRight->fCurrent,
144  G4String("Horn1TargetFinVertCornerDownstrFirstUpRight_P"),
145  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
146 
147  posTmp[0] = -fTargetFinWidth/4.; posTmp[1] = -1.0*(fTargetFinHeight/2. - fTargetCTubeOuterRadius/2. + 0.125*CLHEP::mm);
148  new G4PVPlacement((G4RotationMatrix *) 0,
149  posTmp, plTargetFinCorDFDwnLeft->fCurrent,
150  G4String("Horn1TargetFinVertCornerDownstrFirstDwnLeft_P"),
151  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
152  posTmp[0] = fTargetFinWidth/4.; posTmp[1] = -1.0*(fTargetFinHeight/2. - fTargetCTubeOuterRadius/2. + 0.125*CLHEP::mm);
153  new G4PVPlacement((G4RotationMatrix *) 0,
154  posTmp, plTargetFinCorDFDwnRight->fCurrent,
155  G4String("Horn1TargetFinVertCornerDownstrFirstDwnRight_P"),
156  vTargSegFirst->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
157 
158  }
159  // Now place the previously defined standard target segment. Note: they already contain their cooling and
160  // real target.
161 // LBNEVolumePlacementData *plHorn1TargetSegment = Create("Horn1TargetSegment");
162  std::map<G4String, LBNEVolumePlacementData>::iterator itTargSeg = fSubVolumes.find(G4String("TargetUpstrDownstrSegment"));
163  LBNEVolumePlacementData *plTargetUpstrDownstrSegment= &itTargSeg->second;
164 
165  double zCoordTmp = (infoTargSegFirst == 0) ?
166  (-1.0*plDowstrHe->fParams[2]/2. + plTargetUpstrDownstrSegment->fParams[2]/2. + 0.005*CLHEP::mm) :
167  ( infoTargSegFirst->fPosition[2] + infoTargSegFirst->fParams[2]/2. +
168  plTargetUpstrDownstrSegment->fParams[2]/2. + 0.002*CLHEP::mm);
169  for (int iSeg=0; iSeg != fTargetNumFinsInHorn; iSeg++) { // Place with no misalignment
170  posTmp[0] = 0.; posTmp[1] = 0.;
171  posTmp[2] = zCoordTmp;
172 // std::cerr << " In Horn1, Positioning target segment " << iSeg << " at Z = zCoord " << zCoordTmp << std::endl;
173  std::ostringstream cNumStrStr; cNumStrStr << "_P" << iSeg;
174  new G4PVPlacement((G4RotationMatrix *) 0,
175  posTmp, plTargetUpstrDownstrSegment->fCurrent,
176  G4String("Horn1TargetSegment")+cNumStrStr.str(),
177  vMHe->GetLogicalVolume(), false, iSeg+100, fCheckVolumeOverLapWC);
178  zCoordTmp += (fTargetFinLength + fTargetFinSpacingLength);
179  }
180  // Now the end
181  LBNEVolumePlacementData *plCoolingTubeReturn = Create("Horn1TargetCoolingTubeDwnRetTit");
182  posTmp[0] = 0.; posTmp[1] = 0.;
183  posTmp[2] = plDowstrHe->fParams[2]/2 -
185  // Hopefully some roo to spare..
186  new G4PVPlacement(&plCoolingTubeReturn->fRotation,
187  posTmp, plCoolingTubeReturn->fCurrent,
188  G4String("Horn1TargetCoolingTubeDwnRetTit_PFront"),
189  vMHe->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
190  posTmp[2] = plDowstrHe->fParams[2]/2 - 0.5*fTargetCTubeReturnDownstrThickTitanium/2. - 1.3*CLHEP::mm;
191  new G4PVPlacement(&plCoolingTubeReturn->fRotation,
192  posTmp, plCoolingTubeReturn->fCurrent,
193  G4String("Horn1TargetCoolingTubeDwnRetTit_PBack"),
194  vMHe->GetLogicalVolume(), false, 0, fCheckVolumeOverLapWC);
195 
196  Create("Horn1TargetCoolingTubeDwnRetWater");
197  PlaceFinal("Horn1TargetCoolingTubeDwnRetWater", vMHe);
198 
199  Create("Horn1TargetDownstrHeContainerCap");
200  PlaceFinal("Horn1TargetDownstrHeContainerCap", vMHe);
201 }
202 //
203 // Horn1 calls and utilities.
204 //
205 
207 
208  if (fHorn1LongRescaleCnt != 0) {
209  G4Exception("LBNEVolumePlacements::RescaleHorn1Lengthwise", "",
210  FatalErrorInArgument, " This method can only be called once per job ");
211  }
215 
216  for (size_t k=0; k != fHorn1UpstrLengths.size(); ++k)
218  for (size_t k=0; k != fHorn1UpstrZPositions.size(); ++k)
220 
221  for (size_t k=0; k != fHorn1UpstrOuterIOTransLengths.size(); ++k)
223 
224  for (size_t k=0; k != fHorn1UpstrOuterIOTransPositions.size(); ++k)
226 
227  for (size_t k=0; k != fTargetHorn1Lengths.size(); ++k)
229  for (size_t k=0; k != fTargetHorn1ZPositions.size(); ++k)
230  fTargetHorn1ZPositions[k] *= fHorn1LongRescale; // This will be approximate...
231 
234 
235  // Now we deal with the inner conductor radial equations.
237  it != fHorn1Equations.end(); it++) it->SetLongRescaleFactor(fHorn1LongRescale);
238 
241 
242 // for (size_t k=0; k != fHorn1SectionLengths.size(); ++k)
243 // fHorn1SectionLengths[k] *= fHorn1LongRescale;
244 // fHorn1OuterTubeInnerLength *= fHorn1LongRescale; // ??????????????///
247 // fHorn1InnerTopUpstrLength *= fHorn1LongRescale; // ??????????? Check that all the rescale is consistently...
248 // fHorn1InnerTopDownstrLength *= fHorn1LongRescale;
249 
250 //
251 // Aug 18 2014., for simplified geometry.
253  (*it) *= fHorn1LongRescale;
254 
255 }
256 
257 void LBNEVolumePlacements::RescaleHorn1Radially() { // Note: not all variables are rescale here,
258  if (fHorn1RadialRescaleCnt != 0) {
259  G4Exception("LBNEVolumePlacements::RescaleHorn1Radially", "",
260  FatalErrorInArgument, " This method can only be called once per job ");
261  }
263  // Some of this work will be done via the LBNEHornRadialEquation
266 
267  for (size_t k=0; k != fHorn1UpstrOuterIOTransInnerRads.size(); ++k)
269  for (size_t k=0; k != fHorn1UpstrOuterIOTransThicks.size(); ++k)
271 
272  for (size_t k=0; k != fTargetHorn1InnerRadsUpstr.size(); ++k)
274  for (size_t k=0; k != fTargetHorn1InnerRadsDownstr.size(); ++k)
276  for (size_t k=0; k != fTargetHorn1TransThick.size(); ++k)
278 
279  for (size_t k=0; k != fHorn1UpstrInnerRadsUpstr.size(); ++k)
281  for (size_t k=0; k != fHorn1UpstrInnerRadsDownstr.size(); ++k)
283 
284  for (size_t k=0; k != fHorn1UpstrInnerRadsOuterUpstr.size(); ++k)
286  for (size_t k=0; k != fHorn1UpstrInnerRadsOuterDownstr.size(); ++k)
288 
289 // fHorn1TopUpstrInnerRad *= fHorn1RadialRescale; Recomputed in CreateHorn1TopLevelUpstr
290 
294 
296  // Now we deal with the inner conductor radial equations.
298  it != fHorn1Equations.end(); it++) it->SetRadialRescaleFactor(fHorn1RadialRescale);
299 
300 //
301 // Aug 18 2014., for simplified geometry.
302  for(std::vector<double>::iterator it = fMotherHorn1AllRads.begin(); it != fMotherHorn1AllRads.end(); it++)
303  (*it) *= fHorn1RadialRescale;
304 }
305 
307 
308  const double in = 2.54*CLHEP::cm;
309  fHorn1IOTransLength = 3.0*CLHEP::cm + 3.316*in + 0.005*CLHEP::mm;
310  // Drawing 8875.112 -MD-363097 The 3 cm is the MCZERO offset, per verbal discussion
311  // with J. Hylen. The 5 microns if to avoid G4 volume overlaps.
312 
313 // fHorn1RadialSafetyMargin = 2.9*CLHEP::mm; // per agreement between Jim H. and Alberto M., Aug. 22 2013.
314  fHorn1RadialSafetyMargin = 2.5*CLHEP::mm; // per agreement between Jim H. and Alberto M., Oct 4 2013
315 
316  fHorn1IOTransInnerRad = 2.520*in/2. - fHorn1RadialSafetyMargin/2. ; // last term is the
317  fHorn1IOTransOuterRad = 16.250*in/2.;
318 
319  fHorn1UpstrInnerRadsUpstr.resize(4);
320  fHorn1UpstrInnerRadsDownstr.resize(4);
323  fHorn1UpstrLengths.resize(4);
324  fHorn1UpstrZPositions.resize(4);
325 
326  fHorn1UpstrInnerRadsUpstr[0] = 1.572*in;
328  fHorn1UpstrInnerRadsDownstr[0] = 1.41*in;
330  fHorn1UpstrLengths[0] = 0.508*in - 0.100*CLHEP::mm;
331  fHorn1UpstrZPositions[0] = fHorn1UpstrLengths[0]/2. + 0.025; // With respect to the beginning of mother volume.
332 
335  fHorn1UpstrInnerRadsDownstr[1] = 1.288*in;
337  fHorn1UpstrLengths[1] = 0.639*in - 0.100*CLHEP::mm;
338  fHorn1UpstrZPositions[1] = fHorn1UpstrZPositions[0] + 0.025*CLHEP::mm + fHorn1UpstrLengths[0]/2 + fHorn1UpstrLengths[1]/2.;
339 
342  fHorn1UpstrInnerRadsDownstr[2] = 1.268*in;
344  fHorn1UpstrLengths[2] = 2.835*in - 0.100*CLHEP::mm; // Reduce a bit, too tight..
345  fHorn1UpstrZPositions[2] = fHorn1UpstrZPositions[1] + 0.025*CLHEP::mm + fHorn1UpstrLengths[1]/2 + fHorn1UpstrLengths[2]/2.;
346 
351  fHorn1UpstrLengths[3] = 0.479*in - 0.100*CLHEP::mm; // Nov 19 2013 : change from 0.40 inches to 0.479, per more
352  // accurate reading of drawing 363097
353  fHorn1UpstrZPositions[3] = fHorn1UpstrZPositions[2] + 0.025*CLHEP::mm + fHorn1UpstrLengths[2]/2 + fHorn1UpstrLengths[3]/2.;
354  //
355  // These are elements, approximated as tubes, of the Inner Outer transition piece of Horn1
356  //
361 
362  fHorn1UpstrOuterIOTransInnerRads[0] = 5.625*in;
363  fHorn1UpstrOuterIOTransThicks[0] = 0.30*in;
364  fHorn1UpstrOuterIOTransLengths[0] = 0.421*in;
366 
367  fHorn1UpstrOuterIOTransInnerRads[1] = 5.763*in;
368  fHorn1UpstrOuterIOTransThicks[1] = 0.32*in;
369  fHorn1UpstrOuterIOTransLengths[1] = 0.421*in;
372 
373  fHorn1UpstrOuterIOTransInnerRads[2] = 5.763*in;
374  fHorn1UpstrOuterIOTransThicks[2] = 0.4*in;
375  fHorn1UpstrOuterIOTransLengths[2] = 0.75*in;
378 
379  fHorn1UpstrOuterIOTransInnerRads[3] = 5.763*in;
380  fHorn1UpstrOuterIOTransThicks[3] = 2.26*in;
381  fHorn1UpstrOuterIOTransLengths[3] = fHorn1IOTransLength - 0.250*CLHEP::mm -
383 
384  fHorn1UpstrOuterIOTransPositions[3] = fHorn1IOTransLength - fHorn1UpstrOuterIOTransLengths[3]/2. - 0.01*CLHEP::mm;;
385 
386 // Outer dimension of the big tube that contains almost everything..
387 // Except the big connedtors rings downsream (max dim are 23.5 in
388 
389  fHorn1OuterTubeOuterRad = 13.750*in/2.0;
390  fHorn1OuterTubeInnerRad = 11.750*in/2.0; // checked with drawing 364094
391  //
392 
393  //
394  // Now the top level sections. Only two of them, alignable.
395  fHorn1TopUpstrOuterRad = 16.250*in/2. + 5.0*CLHEP::mm; // safety 5 mm, big radius..// Drawing 8875.112-MD 363097
396  fHorn1NeckLength = 1.568*in; // Drawing 8875.112-MD 363105
397  fHorn1NeckZPosition = 30.315*in + fHorn1NeckLength/2.; // Drawing 8875.112-MD 363105
398  // In Z Drawing coordinates.
399 
400  fHorn1TopDownstrOuterRad = fHorn1TopUpstrOuterRad; // Initialization finally fixed on March 18 2014...
401  // Should have been done 9 months ago!
402 
403  fHorn1TopDownstrLength = 133.752*in; // We will have to subtract the upstream length, once we know it
404  // This include the downstream bulkhead.
405  // Other quantities defined in CreateHorn1TopLevelUpstr..
406  // The first one goes up the downstream end of the IO transition peace
407  // and up the downstream end of the target. If the target is completly out of the horn,
408  // it is the part before the neck. (Drawing 8875.112-MD-363104)
409  // This is a tube, set by the inner conductor
410  // radius at the end of the target.
411  //
412  // Load the equations Drawing 8875.112-MD 363104, 363105
413 //
414  fHorn1Equations.clear();
415  LBNEHornRadialEquation e1(1.975805, -0.055858, -0.078740); fHorn1Equations.push_back(e1);
416  LBNEHornRadialEquation e2(1.818869, -0.055858, 0.); fHorn1Equations.push_back(e2);
417  LBNEHornRadialEquation eBlank(0., 0., 0.); fHorn1Equations.push_back(eBlank); // equation 3 not found on drawing.
418  LBNEHornRadialEquation e4(-5.619190, 0.180183, 0.); fHorn1Equations.push_back(e4);
419  LBNEHornRadialEquation e5(-5.462253, 0.180183, -0.078740); fHorn1Equations.push_back(e5);
420  LBNEHornRadialEquation e6(1.97805, -0.055858, 0.); fHorn1Equations.push_back(e6);
421  fHorn1Equations.push_back(eBlank); // equation 7 not found on drawing as well
422  LBNEHornRadialEquation e8(-5.462253, 0.180183, 0.); fHorn1Equations.push_back(e8);
423 
424  // The 2nd top lelvel section is the remaining part of that part, up to the end of the Horn1Hall Z location.
425  // This is just a tube.
426  //
427  fHorn1InnerCondMat = G4String("Aluminum");
428  fHorn1AllCondMat = G4String("Aluminum");
429  // Then, conical sections, all in a tube that has an inner radius of the neck, our radius
430  //
431  // To compute all that, we need to locate the target first..
432  // So, done at construction time.
433  //
434 
435 }
437  const double in = 2.54*CLHEP::cm;
438  fMotherHorn1AllRads.clear();
439  fMotherHorn1AllLengths.clear();
440  const double epsilR = 0.050*CLHEP::mm;
441  double zCurrent = 0.;
442  fMotherHorn1AllRads.push_back(fHorn1IOTransInnerRad - epsilR);
443  fMotherHorn1AllLengths.push_back(zCurrent);
444  fMotherHorn1AllRads.push_back(fHorn1IOTransInnerRad - epsilR);
445 // zCurrent += fHorn1IOTransLength; // Oversize ? ! Drawing 363092, 363097 says (2.436" + 3.2852" = 5.752 )
446  zCurrent += 5.752*in; ; // Correct...
447  fMotherHorn1AllLengths.push_back(zCurrent);
448  // Up to the neck, equation
449  const int numSectEq1 = 5;
450  const double lengthEq1 = 12.896*in/numSectEq1; // Drawin 363104
451  double zz1 = 3.316*in;
452  for(int iSect1 = 0; iSect1 != numSectEq1; iSect1++) {
453  zz1 += lengthEq1;
454  const double rr1 = fHorn1Equations[0].GetVal(zz1) - epsilR - 0.300*CLHEP::mm -0.050*CLHEP::mm*iSect1;// needs a bit more room here, these subsection are too straight..
455  zCurrent += lengthEq1;
456  fMotherHorn1AllRads.push_back(rr1);
457  fMotherHorn1AllLengths.push_back(zCurrent);
458 // std::cerr << " Polycone Mother, subsection 1 , zz1 " << zz1 << " zCurrent " << zCurrent << " rr1 " << rr1 << std::endl;
459  }
460  const int numSectEq2 = 8;
461  const double lengthEq2 = (4.9799*in + 9.2262*in)/numSectEq2; // Drawing 363104, 363105
462  for(int iSect2 = 0; iSect2 != numSectEq2; iSect2++) {
463  zz1 += lengthEq2;
464  const double rr2 = fHorn1Equations[1].GetVal(zz1) - epsilR - 0.8*CLHEP::mm - 0.1*CLHEP::mm*iSect2;// empirical, but it will need to be improved on for
465  // misalignment studies.
466  zCurrent += lengthEq2;
467  fMotherHorn1AllRads.push_back(rr2);
468  fMotherHorn1AllLengths.push_back(zCurrent);
469 // std::cerr << " Polycone Mother, subsection 2 , zz1 " << zz1 << " zCurrent " << zCurrent << " rr2 " << rr2 << std::endl;
470  }
471  // The neck + all the other sections, set to the neck.
472  const double neckRadius = 0.709*in/2.; // Drawing 363105
473  fMotherHorn1AllRads.push_back(neckRadius - epsilR);
474  fMotherHorn1AllLengths.push_back(zCurrent);
475  zCurrent += 1.568*in; zz1 += 1.568*in;
476  fMotherHorn1AllRads.push_back(neckRadius - epsilR);
477  fMotherHorn1AllLengths.push_back(zCurrent);
478 // std::cerr << " ... Just downstream of the neck, zz1 = " << zz1 << " zCurrent " << zCurrent << std::endl;
479  // Downstream of the neck.. Equation 4
480  const int numSectEq4 = 4;
481  const double lengthEq4 = (36.2709 - 31.8827)*in/numSectEq4; // Drawing 363105
482  for(int iSect4 = 0; iSect4 != numSectEq4; iSect4++) {
483  zz1 += lengthEq4;
484  double rr4 = fHorn1Equations[3].GetVal(zz1) - epsilR - 0.2*CLHEP::mm - 0.1*CLHEP::mm*iSect4;// empirical, but it will need to be improved on for
485  // misalignment studies.
486  if (iSect4 == 0) rr4 = (rr4 + neckRadius)/2.0; // take the average... Not really important, a realistic plug should nevr fit tightly.
487  zCurrent += lengthEq4;
488  fMotherHorn1AllRads.push_back(rr4);
489  fMotherHorn1AllLengths.push_back(zCurrent);
490 // std::cerr << " Polycone Mother, subsection 4 , zz1 " << zz1 << " zCurrent " << zCurrent << " rr4 " << rr4 << std::endl;
491  }
492  // Downstream of the neck.. Equation 5 Up to the downstream flange, drawing 363108, 363096
493  const int numSectEq5 = 20;
494  const double lengthEq5 = (117.126 - 36.27097)*in/numSectEq5; // Drawing 363105, 363108
495  double rLastParabolic = 0.;
496  for(int iSect5 = 0; iSect5 != numSectEq5; iSect5++) {
497  zz1 += lengthEq5;
498  const double rr5 = fHorn1Equations[4].GetVal(zz1) - epsilR - 1.0*CLHEP::mm - 0.1*CLHEP::mm*iSect5;// empirical, but it will need to be improved on for
499  // misalignment studies.
500  zCurrent += lengthEq5;
501  fMotherHorn1AllRads.push_back(rr5);
502  fMotherHorn1AllLengths.push_back(zCurrent);
503 // std::cerr << " Polycone Mother, subsection 5 , zz1 " << zz1 << " zCurrent " << zCurrent << " rr5 " << rr5 << std::endl;
504  rLastParabolic = rr5;
505  }
506  zCurrent += 14.244*in + 3.0*CLHEP::cm; // xx cm safe for misalignment Drawing 363093 and 363096
507  fMotherHorn1AllRads.push_back(rLastParabolic - epsilR);
508  fMotherHorn1AllLengths.push_back(zCurrent);
509  //
510  // Now the outer...
511  //
512  const double rOut = 16.25*in + 15.0*in + 2.5*CLHEP::cm;
513  fMotherHorn1AllRads.push_back(rOut);
514  fMotherHorn1AllLengths.push_back(zCurrent);
515  fMotherHorn1AllRads.push_back(rOut);
516  fMotherHorn1AllLengths.push_back(0.);
517  //
518  // dump this curve, so we can draw it.
519 // std::ofstream fileOutTmp("./RZCurve_1.txt");
520 // fileOutTmp << " Z R " << std::endl;
521 // for (size_t ii=0 ; ii != fMotherHorn1AllLengths.size(); ii++) {
522 // std::cerr << " Radius At at Z(StartHorn1) "<< fMotherHorn1AllLengths[ii]
523 // << " is " << fMotherHorn1AllRads[ii] << std::endl;
524 // fileOutTmp << " " << fMotherHorn1AllLengths[ii] << " " << fMotherHorn1AllRads[ii] << std::endl;
525 // }
526 // fileOutTmp.close();
527 // std::cerr << " And quit !!! ... " << std::endl; exit(2);
528 }
529 
531 
532  // A bit special, case, we have to compute the inner conductor radius..
533  // at the length of the target.
534 
535  const double in = 2.54*CLHEP::cm;
537  fHorn1LongRescale*(3.0*CLHEP::cm - 3.316*in + 7.0*CLHEP::mm);
538  // The last factor is a tweak, coming from the various safety marging and/or arbitrariness
539  // in defining the geometry.
540  // The transition Inner to Outer is now included in the Horn1TopLevelUpstr volume!!
542  //
543  // The above equation to determine fHorn1TopUpstrLength looks wrong based on Geantino analysis
544  // Why not simply:
545 
546  fHorn1TopUpstrLength = fTargetHeContTubeLengthInHorn + 7.0*CLHEP::mm;
547  //
548  // Wrong if the entire target is out of Horn1..
549  //
550  if (fUsePseudoNova) fHorn1TopUpstrLength = fHorn1IOTransLength + + 3.36*in + 60.0*CLHEP::mm + 3.0*CLHEP::mm; // The 60 mm
551  // is very arbitrary. It provide enough space for the weld of the I/O to the most upstream inner conductor
552  // piece. Note that, if the target is completly outside Horn1, the raison d'etre
553  // of the split Upst/Downstream part of the Horn1 goes away.. But the structure of the code
554  // was there, try to coopt it..
555  //
556 
557 
558 
559 // std::cerr << " CreateHorn1TopLevelUpstr : fHorn1IOTransLength " << fHorn1IOTransLength
560 // << " fTargetHeContTubeLengthInHorn " << fTargetHeContTubeLengthInHorn
561 // << " fHorn1TopUpstrLength " << fHorn1TopUpstrLength << " and quit " << std::endl;
562 // exit(2);
563  double zEnd = fHorn1TopUpstrLength - fHorn1LongRescale*3.0*CLHEP::cm; // Crappy convention again..
564  if (zEnd > fHorn1LongRescale*30.3150*in) { // Z (drawing coordinate system)
565  std::ostringstream messStrStr;
566  messStrStr << " Helium Tube target hitting the neck! zEnd " << zEnd << "\n";
567  G4String messStr(messStrStr.str());
568  G4Exception("LBNEVolumePlacements::CreateHorn1TopLevelUpstr", " ",
569  FatalErrorInArgument, messStr.c_str());
570  }
571  fHorn1TopUpstrInnerRad = fHorn1Equations[0].GetVal(zEnd) - 0.005*CLHEP::mm; // recaled radially before construction, if need be.
572  return this->Create("Horn1TopLevelUpstr");
573 }
574 // Checking the possible radial overlap at the downstream end of the target.
575 // The size and position of Horn1TopLevelUpstr and Horn1TargetDownstrHeContainer are fixed...
576 
578 
580  const double in = 2.54*CLHEP::cm;
581  const LBNEVolumePlacementData *plSmallRing;
582  const LBNEVolumePlacementData *plLargeRing;
583  plSmallRing = this->Find(G4String("Check"),
584  G4String("TargetNoSplitHeContainer"),
585  G4String("LBNEVolumePlacements::CheckHorn1InnerConductAndTargetRadii"));
586 
587  plLargeRing = this->Find(G4String("Check"),
588  G4String("Horn1PolyM1"),
589  G4String("LBNEVolumePlacements::CheckHorn1InnerConductAndTargetRadii"));
590 
591  const double xOffS = plSmallRing->fPosition[0] +
592  (plSmallRing->fParams[2]/2.)*plSmallRing->fRotation.xz(); // Assumed misaligned once (withe respect to perfectly
593  // aligned (HORN1. )
594  const double yOffS = plSmallRing->fPosition[1] +
595  (plSmallRing->fParams[2]/2.)*plSmallRing->fRotation.yz();
596 
597  // We take the full length, the clash is at the downstream end.
598 
599  double xOffL = plLargeRing->fPosition[0] +
600  (plLargeRing->fParams[2]/2.)*plLargeRing->fRotation.xz();
601 
602  double yOffL = plLargeRing->fPosition[1] +
603  (plLargeRing->fParams[2]/2.)*plLargeRing->fRotation.yz();
604  // Same, at the downstream end. But this is only approximate.
605  double maxLength = -100000.0*CLHEP::m;
607  if (*il > maxLength ) maxLength = *il;
608  xOffL = plLargeRing->fPosition[0] + maxLength*plLargeRing->fRotation.xz()/2.;
609 
610  yOffL = plLargeRing->fPosition[1] + maxLength*plLargeRing->fRotation.yz()/2.;
611  const double xOff = xOffS - xOffL;// now translated to ref. frame of the large ring.
612  const double yOff = yOffS - yOffL;
613 
614  const double rSmall = plSmallRing->fParams[1]; // Outer radius
615  // Compute the large radius based on equation 0, at the relevant Z
616  const double zMaxDC = fHorn1TopUpstrLength - 3.0*CLHEP::cm;
617  const double rMinEqn1 = fHorn1Equations[0].GetVal(zMaxDC); // Equation 1 or 0
618  const double rMinEqn2 = fHorn1Equations[1].GetVal(zMaxDC); // Equation 1 or 0
619  const double ratio0vs1 = std::min(1.0, (zMaxDC/(21.0888*in*fHorn1LongRescale)));
620  const double rLarge = rMinEqn2*ratio0vs1 + (1.0-ratio0vs1)*rMinEqn1;
621  // Equation 1 and 0, weighted by Z ; // Inner Radius
622 // std::cerr << " CheckHorn1InnerConductAndTargetRadii, zCoordEnd "
623 // << zCoordEnd << " rLarge " << rLarge << " rSmall " << rSmall << std::endl;
624 // std::cerr << " .. xOffS " << xOffS << " yOffS " << yOffS
625 // << " xOffL " << xOffL << " yOffL " << yOffL << std::endl;
626  G4String messHeader(" The downstream end target is touching (or nearly touching) the Horn1 inner conductor \n");
627  if ((std::abs(xOff) < 0.002*CLHEP::mm) && (std::abs(yOff) < 0.002*CLHEP::mm)) {
628  if (rSmall + fHorn1RadialSafetyMargin < rLarge) return;
629 
630  std::ostringstream messStrStr;
631  messStrStr << messHeader << " Helium Tube radius " << rSmall
632  << " Inner cond. radius " << rLarge << " \n";
633  messStrStr << messHeader << " Suggestion: Reduce fTargetLengthIntoHorn, currently set to " <<
634  fTargetLengthIntoHorn << " mm \n";
635  G4String messStr(messStrStr.str());
636  G4Exception("LBNEVolumePlacements::CheckHorn1InnerConductAndTargetRadii", " ",
637  FatalErrorInArgument, messStr.c_str());
638  } else { // Misalignment
639 // const double phic = std::atan2(yOff, xOff); // extremum in phis . We don't care where it is in phi..
640 // double rMaxDev = -1.0;
641 // for (int iQ=0; iQ!=4; iQ++) { //. but which quadrant? (Should be able to figure out this more simply..)
642 // const double xCrit = rSmall*std::sin(phic);
643 // const double yCrit = rSmall*std::cos(phic);
644 // const double rr = std::sqrt(xCrit*xCrit + yCrit*yCrit);
645 // if (rr > rMaxDev) rMaxDev = rr;
646 // }
647  const double rMaxDev = std::sqrt(xOff*xOff + yOff*yOff);
648 // std::cerr << " Misalignments detected in CheckHorn1InnerConductAndTargetRadii, phic " << phic
649 // << " rMaxDev " << rMaxDev << std::endl;
650  if ((rMaxDev + rSmall) < (rLarge - fHorn1RadialSafetyMargin)) return; // O.K>
651  std::ostringstream messStrStr;
652  messStrStr << messHeader << " Helium Tube radius " << rSmall
653  << " Inner cond. radius " << rLarge << " \n";
654  messStrStr << messHeader << " Tranvser Offset between the two rings " << xOff << " / " << yOff << "\n";
655  G4String messStr(messStrStr.str());
656  G4Exception("LBNEVolumePlacements::CheckHorn1InnerConductAndTargetRadii", " ",
657  FatalErrorInArgument, messStr.c_str());
658  }
659 }
660 
661 //
662 // Subdivide a conical section such that the radial equations are correct within a
663 // a tolerance of 5 microns. We assume that the number of subdivisions
664 // estimated at the upstream end of the section will
665 // be adequate over the entire section.
666 //
667 int LBNEVolumePlacements::GetNumberOfInnerHornSubSections(size_t eqn, double z1, double z2, int nMax) const {
668 
669  int numSubSect = 1;
670  double zEnd = z2;
671  const double zLengthTotal = z2 - z1;
672  double zLength = zLengthTotal;
673  while (true) {
674  const double r0 = fHorn1Equations[eqn].GetVal(z1);
675  const double r1 = fHorn1Equations[eqn].GetVal(zEnd);
676  const double rMid = fHorn1Equations[eqn].GetVal((z1 + zEnd)/2.);
677 // std::cerr << " GetNumberOfInnerHornSubSections z1 " << z1 << " zEnd " << zEnd <<
678 // " r0 " << r0 << " r1 " << r1 << " rMid " << rMid << std::endl;
679  if (std::abs(rMid - 0.5*(r0+r1)) < 0.050*CLHEP::mm) break; // 50 microns good enough for Gov. work.
680  // meachanical tolerance is one 5 mills, (127 microns)
681  zLength /=2.;
682  zEnd = z1 + zLength;
683  numSubSect++;
684  if (numSubSect > nMax) {
685  G4Exception("LBNEVolumePlacements::GetNumberOfInnerHornSubSections", " ", FatalErrorInArgument, " Crazy subdivision! ");
686  break;
687  }
688  }
689  return numSubSect;
690 }
691 //
692 // 2nd argument is in drawing coordinate system, the upstream coordinate of the beginning of the ring
693 // Third argument, in the reference frame of the mother volume, the long. center position
694 //
695 void LBNEVolumePlacements::Horn1InstallSpiderHanger(const G4String &nameStrH,
696  double zLocTweakedDC, double zPosMotherVolume,
697  G4PVPlacement *vMother ) {
698 
699  const double in = 2.54*CLHEP::cm;
700  G4String nameStr(nameStrH);nameStr += G4String("Ring");
701  const double length = 0.750*in*fHorn1LongRescale;
702  const int eqnNum = (zLocTweakedDC < (41.076*fHorn1LongRescale*in)) ? 5 : 7;
703  const double zSignLength = (eqnNum == 5) ? -1.0 : 1.0; // to avoid collision with the inner conductor outer radius
704  // at the upstream or downstream end
705  double rTmp1 = fHorn1Equations[eqnNum].GetVal(zLocTweakedDC + length*zSignLength)
706  + 0.0015*CLHEP::mm + fWaterLayerThickInHorns;
707  if (fHorn1RadiusBigEnough) {
708  const double rr = fHorn1Equations[eqnNum].GetVal(zLocTweakedDC + length*zSignLength);
709  if (rr < fHorn1RMinAllBG ) rTmp1 = fHorn1RMinAllBG + 0.0015*CLHEP::mm + fWaterLayerThickInHorns;
710  }
711  const double rTmp2 = rTmp1 + 0.24*in; // Deduced from 363104 and equation 6
712  G4Tubs *aTubs = new G4Tubs(nameStr, rTmp1, rTmp2,
713  length/2. , 0., 360.0*CLHEP::degree);
714  G4LogicalVolume *pCurrent = new G4LogicalVolume(aTubs, G4Material::GetMaterial(fHorn1InnerCondMat), nameStr);
715  G4ThreeVector posTmp; posTmp[0] = 0.; posTmp[1] = 0.;
716  posTmp[2] = zPosMotherVolume;
717  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrent, nameStr + std::string("_P"),
718  vMother->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
719 
720  //The connecting piece ring to the hangers.. There are three of them, at 120 degrees from each other.
721 
722  G4String nameStr2(nameStrH); nameStr2 += G4String("Riser");
723  const double heightRiser = 0.333*in - 0.020*CLHEP::mm;
724  const double widthH = 1.5*in; // See drawing 8875.112-MD 363115
725  const double thickH = 0.184*2*in;
726  G4Box *aBoxRiser = new G4Box(nameStr2, widthH/2., heightRiser/2.0, thickH/2.0);
727  G4LogicalVolume *pCurrentRiser =
728  new G4LogicalVolume(aBoxRiser, G4Material::GetMaterial(fHorn1InnerCondMat), nameStr2);
729 
730  G4String nameStr3(nameStrH); nameStr3 += G4String("Hanger");
731  const double heightH = fHorn1OuterTubeInnerRad - rTmp2 - 1.0*CLHEP::mm - heightRiser;
732  const double widthH2 = 1.0*in; // 363115 Note: we collapsed both hanger along the horizontal, transverse
733  // direction.
734  const double thickH2 = 0.031*in;
735  G4Box *aBoxHanger = new G4Box(nameStr3, widthH2/2., heightH/2.0, thickH2/2.0);
736  G4LogicalVolume *pCurrentHanger =
737  new G4LogicalVolume(aBoxHanger, G4Material::GetMaterial(fHorn1InnerCondMat), nameStr3);
738 
739  for (int iRot=0; iRot != 3; iRot++) {
740  std::ostringstream rnStrStr; rnStrStr << "_" << (iRot+1);
741  G4String rnStr(rnStrStr.str());
742  // Same Z position as above...
743  G4RotationMatrix * rMatPr = 0;
744  if (iRot == 1) {
745  rMatPr = new G4RotationMatrix;
746  rMatPr->rotateZ(2.0*M_PI/3.);
747  } else if (iRot == 2) {
748  rMatPr = new G4RotationMatrix;
749  rMatPr->rotateZ(-2.0*M_PI/3.);
750  }
751 
752  const double dHRiser = rTmp2 + 0.010*CLHEP::mm + heightRiser/2.;
753  posTmp[0] = 0.; posTmp[1] = dHRiser;
754  if (iRot != 0) {
755  posTmp[0] = dHRiser*rMatPr->xy();
756  posTmp[1] = dHRiser*rMatPr->yy();
757  }
758  if (iRot == 0) {
759  new G4PVPlacement(rMatPr, posTmp, pCurrentRiser, nameStr2 + std::string("_P") + rnStr,
760  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
761  } else {
762  new G4PVPlacement(G4Transform3D(*rMatPr, posTmp), pCurrentRiser, nameStr2 + std::string("_P") + rnStr,
763  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
764  }
765 // Now the hanger it self
766 
767  const double dHHanger = rTmp2 + 0.010*CLHEP::mm + 0.5*CLHEP::mm + heightRiser + heightH/2.;
768  posTmp[0] = 0.; posTmp[1] = dHHanger;
769  if (iRot != 0) {
770  posTmp[0] = dHHanger*rMatPr->xy();
771  posTmp[1] = dHHanger*rMatPr->yy();
772  }
773  // Same Z position as above...
774  if (iRot == 0) {
775  new G4PVPlacement(rMatPr, posTmp, pCurrentHanger, nameStr3 + std::string("_P") + rnStr,
776  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
777  } else {
778  new G4PVPlacement(G4Transform3D(*rMatPr, posTmp), pCurrentHanger, nameStr3 + std::string("_P") + rnStr,
779  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
780  }
781  } // on the 120 degree symmetry point.
782 }
783 //
784 // The set of equations that determine the radii of the inner conductor sections
785 //
786 //
787 // Horn2 code starts here...
789 
790  const double in = 2.54*CLHEP::cm;
791  fHorn2RadialRescale = 1.0;
793  fHorn2LongRescale = 1.0;
796 
797  fHorn2PartsLengths.resize(7);
798  fHorn2PartsRadii.resize(fHorn2PartsLengths.size());
799 
800  fHorn2OuterTubeOuterRadMax = 37.0*in/2.0; // Drawing 8875.112-MD 363385 Need an other drawing.
801  fHorn2OuterTubeOuterRad = 31.30*in/2.0; // Drawing 8875.112-MD 363385 Need an other drawing.
802  fHorn2OuterTubeInnerRad = 29.25*in/2.0;
803  fHorn2LongPosition = 6600.0*CLHEP::mm; // Drawing received fropm Alberto M., who received from Rich Stefanek, we think.
804  // From MCZero (our Zero in g4lbne ref. frame ), to the z=0. of drawing 8875.112Md 363383
805 
806  for(size_t k=0; k!= fHorn2PartsRadii.size(); ++k)
808 
809  fHorn2OffsetIOTr1 = 1.889*in; // Offset between the entrance of Horn2TopLevel - margin and Z=0, drawing...
810  fHorn2PartsLengths[0] = fHorn2OffsetIOTr1 + 5.861*in; // Drawing 8875.112-MD 363385
811  fHorn2LengthNominal = 142.91*in; // Drawing 8875.112-MD 363382, Revision E
812 
813  fHorn2PartsRadii[0] = (33.75 + 1.0)*in/2. ; // Info only, take the outer Radius
814 
815  fHorn2PartsLengths[1] = (24.061)*in; // Drawing 8875.112-MD 363386
816 // fHorn2PartsRadii[1] = (19.385 + 1.0)*in ; // Info only, take the outer Radius
817 
818  fHorn2PartsLengths[2] = (20.092)*in; // Drawing 8875.112-MD 363387
819 // fHorn2PartsRadii[2] = (10.70 + 1.0)*in ; //
820 
821  fHorn2PartsLengths[3] = (20.061)*in; // Drawing 8875.112-MD 363388
822 // fHorn2PartsRadii[3] = (13.293 + 1.0)*in ; // info only.
823 
824  fHorn2PartsLengths[4] = (24.030)*in; // Drawing 8875.112-MD 363389
825 // fHorn2PartsRadii[4] = (17.755 + 1.0)*in ; // info only.
826 
827  fHorn2PartsLengths[5] = (24.325)*in; // Drawing 8875.112-MD 363390
828 // fHorn2PartsRadii[4] = (21.341 + 1.0)*in ; // info only.
829 
830  fHorn2PartsLengths[6] = (21.054)*in; // Drawing 8875.112-MD 363390
831  fHorn2PartsRadii[6] = fHorn2OuterTubeOuterRadMax+ 1.0*in ; // info only.
832 // add 1/2 inch margin for misalignment.
833 
834  fHorn2LengthMargin = 0.5*in;
835 
837  for (size_t k=0; k!= fHorn2PartsLengths.size(); ++k) fHorn2Length +=fHorn2PartsLengths[k];
839 //
840 // std::cout << " Check of Horn2 lengths, Sum of indivuals parts + margin " << fHorn2Length
841 // << " nominal " << fHorn2LengthNominal << std::endl;
842 
843  int numSctTr = 3 + 2; // Number of tubes, otherwise. Approximate..
844  // Take 10 for the transition bulge, 2 for the outer flat part.
845  const double radIOTrOut = 2.184*in;
846  const double radIOTrIn = 1.869*in;
847  const double radIOTrAv = 0.5*(radIOTrOut + radIOTrIn);
848  const double deltaRadIOTr = radIOTrOut - radIOTrIn;
849  const double thetaIOTRStart = std::abs(fHorn2OffsetIOTr1 - radIOTrOut)/radIOTrOut; // approximate..
850  const double surfXSect = (M_PI - thetaIOTRStart)*(radIOTrOut*radIOTrOut - radIOTrIn*radIOTrIn);
851  const double surfXSectPart = surfXSect/(numSctTr-2);
852  const double bigRadIOTr = 12.756*in;
853  // Valid only for
854  fHorn2UpstrOuterIOTransLengths.resize(numSctTr);
855  fHorn2UpstrOuterIOTransRadsOne.resize(numSctTr);
856  fHorn2UpstrOuterIOTransRadsTwo.resize(numSctTr);
857  fHorn2UpstrOuterIOTransPositions.resize(numSctTr);
858 
859  fHorn2UpstrOuterIOTransLengths[1] = deltaRadIOTr - 0.010*CLHEP::mm;
860  fHorn2UpstrOuterIOTransPositions[1] = deltaRadIOTr/2.; // with respect to the start of the mother volume
861  const double heightTmp1 = surfXSectPart/fHorn2UpstrOuterIOTransLengths[1];
862  fHorn2UpstrOuterIOTransRadsOne[1] = bigRadIOTr - heightTmp1/2.;
863  fHorn2UpstrOuterIOTransRadsTwo[1] = bigRadIOTr + heightTmp1/2.;
864  const double zMaxElemZeroUpstr = deltaRadIOTr + 0.010*CLHEP::mm;
865  const double zMaxElemZeroDownstr = fHorn2OffsetIOTr1 - 0.010*CLHEP::mm;
866  fHorn2UpstrOuterIOTransLengths[0] = zMaxElemZeroDownstr - zMaxElemZeroUpstr;
867  fHorn2UpstrOuterIOTransPositions[0] = (zMaxElemZeroDownstr + zMaxElemZeroUpstr)/2.;
870  const double heightTmp0 = surfXSectPart/fHorn2UpstrOuterIOTransLengths[0];
871  fHorn2UpstrOuterIOTransRadsOne[0] = bigRadIOTr - heightTmp0/2. - radIOTrAv/sqrt(2.) ;
872  fHorn2UpstrOuterIOTransRadsTwo[0] = bigRadIOTr + heightTmp0/2. - radIOTrAv/sqrt(2.) ;
873  fHorn2UpstrOuterIOTransRadsOne[2] = bigRadIOTr - heightTmp0/2. + radIOTrAv/sqrt(2.) ;
874  fHorn2UpstrOuterIOTransRadsTwo[2] = bigRadIOTr + heightTmp0/2. + radIOTrAv/sqrt(2.) ;
875  // Top part.
876  fHorn2UpstrOuterIOTransLengths[3] = 0.45*in - 0.010*CLHEP::mm;
877  fHorn2UpstrOuterIOTransPositions[3] = radIOTrOut + fHorn2UpstrOuterIOTransLengths[3]/2. + 0.005*CLHEP::mm;
878  fHorn2UpstrOuterIOTransRadsOne[3] = bigRadIOTr + radIOTrIn ;
879  fHorn2UpstrOuterIOTransRadsTwo[3] = bigRadIOTr + radIOTrOut;
880  // Fange part
881  fHorn2UpstrOuterIOTransLengths[4] = 1.30*in - 0.010*CLHEP::mm;
882  fHorn2UpstrOuterIOTransPositions[4] = radIOTrOut + 0.0075*CLHEP::mm +
884  fHorn2UpstrOuterIOTransRadsOne[4] = bigRadIOTr + fHorn2UpstrOuterIOTransLengths[3]/2. + 0.005*CLHEP::mm ;
885  fHorn2UpstrOuterIOTransRadsTwo[4] = 33.75*in/2;
886 
887 
888  fHorn2InnerIOTransLength = 5.8610*in;
889 
890  //
891  // Load the equations Drawing 8875.112-MD 36385 - 363092
892 //
893  fHorn2Equations.clear();
894  LBNEHornRadialEquation e1(114.73006, -2.91414, 0.); fHorn2Equations.push_back(e1);
895  LBNEHornRadialEquation e2(22.68402, -0.54203, 0., false); fHorn2Equations.push_back(e2);
896  LBNEHornRadialEquation e3(-10.63139, 0.30058, 0., false); fHorn2Equations.push_back(e3); // linear.
897  LBNEHornRadialEquation e4(-56.92263, 1.44583, 0.); fHorn2Equations.push_back(e4);
898  LBNEHornRadialEquation e5(0.12835, 0.0932, 0., false); fHorn2Equations.push_back(e5);
899  LBNEHornRadialEquation e6(1.93227, 0.07398, 0., false); fHorn2Equations.push_back(e6); // 363390
900  LBNEHornRadialEquation e7(114.73007, -2.91414, -0.11811); fHorn2Equations.push_back(e7); // equation 7 found 0n 363386
901  // equation 7 on 363385 differs sliggtly.. in the noise...
902  LBNEHornRadialEquation e8(-56.92263, 1.44583, -0.11811); fHorn2Equations.push_back(e8);
903  LBNEHornRadialEquation e9(0.01064, 0.0932, 0., false); fHorn2Equations.push_back(e9);
904  LBNEHornRadialEquation e10(1.81456, 0.07398, 0., false); fHorn2Equations.push_back(e10); // 363389
905  LBNEHornRadialEquation eIO(10.9108, -0.1780, 0., false); fHorn2Equations.push_back(eIO); // 363385
906  // The 2nd top lelvel section is the remaining part of that part, up to the end of the Horn1Hall Z location.
907  // This is just a tube.
908  //
909 
910  // Then, conical sections, all in a tube that has an inner radius of the neck, our radius
911  //
912  // To compute all that, we need to locate the target first..
913  // So, done at construction time.
914  //
915 
916 }
918  if (fHorn2LongRescaleCnt != 0) {
919  G4Exception("LBNEVolumePlacements::RescaleHorn2Lengthwise", "",
920  FatalErrorInArgument, " This method can only be called once per job ");
921  }
923  for (size_t i=0; i!= fHorn2PartsLengths.size(); i++)
926  for (size_t i=0; i!= fHorn2UpstrOuterIOTransLengths.size(); i++)
928  for (size_t i=0; i!= fHorn2UpstrOuterIOTransPositions.size(); i++)
932  // Now we deal with the inner conductor radial equations.
934  it != fHorn2Equations.end(); it++) it->SetLongRescaleFactor(fHorn2LongRescale);
935 
938  // We also have to move the decay pipe snout, as Horn2 is longer..
940 
941 
942 }
943 
945 // If the user really want it call twice, so be it. Amit, Paul, March 27 2015...
946 // if (fHorn2RadialRescaleCnt != 0) {
947 // G4Exception("LBNEVolumePlacements::RescaleHorn2Radially", "",
948 // FatalErrorInArgument, " This method can only be called once per job ");
949 // }
951 // std::cerr << " LBNEVolumePlacements::RescaleHorn2Radially, fHorn2RadialRescale = " << fHorn2RadialRescale
952 // << "fHorn2RadialRescaleCst " << fHorn2RadialRescaleCst << std::endl;
953  for (size_t i=0; i!= fHorn2PartsRadii.size(); i++) {
955  }
959  for (size_t i=0; i!= fHorn2UpstrOuterIOTransRadsOne.size(); i++) {
961  }
962  for (size_t i=0; i!= fHorn2UpstrOuterIOTransRadsTwo.size(); i++) {
964  }
965 
966  // Now we deal with the inner conductor radial equations.
967 
968 
969 
971  it != fHorn2Equations.end(); it++) it->SetRadialRescaleFactor(fHorn2RadialRescale);
972 
973 }
974 
976 
977 // std::cerr << " LBNEVolumePlacements::RescaleHorn2Radially, fHorn2RadialRescale = " << fHorn2RadialRescale
978 // << "fHorn2RadialRescaleCst " << fHorn2RadialRescaleCst << std::endl;
979  for (size_t i=0; i!= fHorn2PartsRadii.size(); i++) {
981 // std::cerr << " LBNEVolumePlacements::RescaleHorn2Radially Old Rad " << oldRad
982 // << " New " << fHorn2PartsRadii[i] << std::endl;
983  }
987  for (size_t i=0; i!= fHorn2UpstrOuterIOTransRadsOne.size(); i++) {
989  }
990  for (size_t i=0; i!= fHorn2UpstrOuterIOTransRadsTwo.size(); i++) {
992  }
993 
994  // Now we deal with the inner conductor radial equations.
995 
997  it != fHorn2Equations.end(); it++) it->SetRadialRescaleFactorCst(fHorn2RadialRescaleCst);
998 }
999 
1000 void LBNEVolumePlacements::PlaceFinalHorn2(G4PVPlacement *vH2Hall) {
1001 
1002  const double in = 2.54*CLHEP::cm;
1003  LBNEVolumePlacementData *plInfoH2Top = this->Create("Horn2TopLevel");
1004  G4PVPlacement *vH2 = PlaceFinal("Horn2TopLevel", vH2Hall);
1005  std::string gasMaterial = fFillHornsWithArgon ? std::string("Argon") : std::string("Air");
1006 /* The Plug code */
1007  if(fConstructPlug){
1008  G4ThreeVector posTmp; posTmp[0] =0.; posTmp[1] =0.;
1009  G4Tubs* plugTube = new G4Tubs("Plug", fPlugInnerRadius, fPlugOuterRadius, fPlugLength*.5, 0., 360.*CLHEP::deg);
1010  G4LogicalVolume *plugl = new G4LogicalVolume(plugTube, G4Material::GetMaterial(fPlugMaterial.c_str()), "Plug");
1011  posTmp[2] = (plInfoH2Top->fParams[2]-fPlugLength)*.5-fPlugZPosition;
1012  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, plugl, "Plug_P",
1013  vH2->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1014  }
1015  /* end of The Plug code */
1016  double zPosPart = -1.0*plInfoH2Top->fParams[2]/2 + fHorn2LengthMargin;
1017 
1018 
1019  const double zShiftDrawingIOTrans = fHorn2PartsLengths[0]/2 - fHorn2InnerIOTransLength;
1020  fHorn2DeltaZEntranceToZOrigin = zShiftDrawingIOTrans + fHorn2LengthMargin;
1021 
1022  double zStartDrawing = 0.; // definition of z=0
1023 // std::cerr << " Horn2 Placements, zPostPart " << zPosPart << " Length of Horn2 Top level " << plInfoH2Top->fParams[2]
1024 // << " zShiftDrawingIOTrans " << zShiftDrawingIOTrans << " 1rst part length " << fHorn2PartsLengths[0] << std::endl;
1025  double H2InnerRadius=fPlugOuterRadius;
1026  if(!fConstructPlug)H2InnerRadius=0.;
1027  fHorn2ZEqnChanges.clear();
1028  for (size_t kPart=0; kPart!= fHorn2PartsLengths.size(); kPart++) {
1029  std::ostringstream nStrStr; nStrStr << "Horn2Part" << kPart;
1030  G4String nStr(nStrStr.str());
1031  G4Tubs* tubsPart = new G4Tubs(nStr, H2InnerRadius, fHorn2PartsRadii[kPart],
1032  (fHorn2PartsLengths[kPart]/2 - 0.002*CLHEP::mm ), 0., 360.0*CLHEP::degree);
1033  G4LogicalVolume *tubsL = new G4LogicalVolume(tubsPart, G4Material::GetMaterial(gasMaterial.c_str()), nStr);
1034  G4ThreeVector posTmp; posTmp[0] =0.; posTmp[1] =0.;
1035  zPosPart += fHorn2PartsLengths[kPart]/2;
1036  posTmp[2] = zPosPart;
1037  std::cerr << " At Horn2 big part " << kPart << "Radius " << fHorn2PartsRadii[kPart] << std::endl;
1038  G4PVPlacement *vPart = new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsL, nStr + std::string("_P"),
1039  vH2->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1040  zPosPart += fHorn2PartsLengths[kPart]/2;
1041  // Sub volumes for each part.
1042  switch (kPart) {
1043  case 0: // The Inner Outer Transition piece
1044  {
1045  //The inner part.
1046  const double zEndDrawing = fHorn2InnerIOTransLength;
1047  fHorn2ZEqnChanges.push_back(zEndDrawing); // To be used in the magnetic field class.
1048  int numSubSect = GetNumberOfInnerHorn2SubSections(6, zStartDrawing,
1049  zEndDrawing, 10); // These Z position are from the start of the inner conductor.
1050  const double deltaZ = (zEndDrawing - zStartDrawing)/numSubSect;
1051 // std::cerr << " Number of subsection for the IO transition of Horn2 " << numSubSect
1052 // << " deltaz " << deltaZ << std::endl;
1053  for (int iSub = 0; iSub != numSubSect; iSub++) {
1054  const double zzBegin = zStartDrawing + iSub*deltaZ;
1055  const double zzEnd = zzBegin + deltaZ;
1056  std::ostringstream nameStrStr; nameStrStr << "Horn2InnerPartIOTransSub" << iSub;
1057  G4String nameStr(nameStrStr.str());
1058  fHorn2IC.push_back(nameStr);
1059  const double rMin1 = fHorn2Equations[6].GetVal(zzBegin); // Equation 1
1060  const double rMin2 = fHorn2Equations[6].GetVal(zzEnd);
1061  const double rMax1 = fHorn2Equations[10].GetVal(zzBegin) + fWaterLayerThickInHorns + 0.0025;
1062  const double rMax2 = fHorn2Equations[10].GetVal(zzEnd) + fWaterLayerThickInHorns + 0.0025;
1063  G4Cons *aCons = new G4Cons(nameStr, rMin1, rMax1,rMin2, rMax2,
1064  (deltaZ - 0.005*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1065 
1066 
1067 
1068  G4LogicalVolume *pCurrent = new G4LogicalVolume(aCons, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1069  posTmp[0] = 0.; posTmp[1] = 0.;
1070  posTmp[2] = zzBegin + zShiftDrawingIOTrans + deltaZ/2.;
1071  G4PVPlacement *vSub = new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrent, nameStr + std::string("_P"),
1072  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1073 
1074  if (fWaterLayerThickInHorns > 0.002*CLHEP::mm) {
1075  nameStrStr.str(""); nameStrStr.clear(); nameStrStr << "Horn2InnerPartIOTransSub" << iSub << "Water";
1076  nameStr = nameStrStr.str();
1077  G4Cons *aConsW2 = new G4Cons(nameStr, rMax1 - fWaterLayerThickInHorns, rMax1-0.001*CLHEP::mm,
1078  rMax2 - fWaterLayerThickInHorns, rMax2-0.001*CLHEP::mm,
1079  (deltaZ - 0.0075*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1080  G4LogicalVolume *pCurrentW2 = new G4LogicalVolume(aConsW2, G4Material::GetMaterial(std::string("Water")), nameStr);
1081  posTmp[0] = 0.; posTmp[1] = 0.; posTmp[2] =0.;
1082  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrentW2, nameStr + std::string("_P"),
1083  vSub->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1084  }
1085  } // on the number of sub section of the Inner Outer transition
1086  // Outer parts
1087  for (size_t kOut=0; kOut != fHorn2UpstrOuterIOTransLengths.size(); kOut++) {
1088  std::ostringstream nStrStrTR3; nStrStrTR3 << "Horn2IOTransOuterPart" << kOut;
1089  G4String nStrTR3(nStrStrTR3.str());
1090  G4Tubs* tubsPartTR3 = new G4Tubs(nStr, fHorn2UpstrOuterIOTransRadsOne[kOut],
1092  fHorn2UpstrOuterIOTransLengths[kOut]/2., 0., 360.0*CLHEP::degree);
1093  G4LogicalVolume *tubsLTR3 = new G4LogicalVolume(tubsPartTR3, G4Material::GetMaterial(fHorn2AllCondMat), nStr);
1094  posTmp[0] =0.; posTmp[1] =0.;
1095  posTmp[2] = - fHorn2PartsLengths[kPart]/2 + fHorn2UpstrOuterIOTransPositions[kOut];
1096  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLTR3, nStrTR3 + std::string("_P"),
1097  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1098  }
1099  // The weld at the end. Shift it a bit upstream such that it does not interfere
1100  {
1101  G4String nStrTW4("Horn2IOTransWeld");
1102  fHorn2IC.push_back(nStrTW4);
1103  const double weldLength = 0.386*in;
1104  const double zzEnd = fHorn2LongRescale*5.8610*in - weldLength - 0.050*CLHEP::mm;
1105  const double radius = fHorn2Equations[10].GetVal(zzEnd) + fWaterLayerThickInHorns + 0.0025;
1106  const double thick = 0.0775*in;
1107  G4Tubs* tubsPartTW4 = new G4Tubs(nStrTW4, radius, (radius+thick), weldLength/2., 0., 360.0*CLHEP::degree);
1108  G4LogicalVolume *tubsLTW4 = new G4LogicalVolume(tubsPartTW4, G4Material::GetMaterial(fHorn2InnerCondMat), nStr);
1109  posTmp[0] = 0.; posTmp[1] =0.;
1110  posTmp[2] = fHorn2PartsLengths[kPart]/2 - weldLength/2. - 0.025*CLHEP::mm;
1111  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLTW4, nStrTW4 + std::string("_P"),
1112  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1113  }
1114  zStartDrawing += fHorn2InnerIOTransLength; // for the next section
1115  } // End of Transition piece
1116  break;
1117  case 2: // The neck. Must subdivide further, radial equation keeps changing.
1118  // There will be 5 parts .. Drawing 8875.112-MD 363387
1119 
1120  {
1121  const double lengthNeck = fHorn2LongRescale*2.411*in - 0.020*CLHEP::mm; // approximate. Equation not available in usual form
1122  fHorn2NeckLength = lengthNeck; // to compute the magnetic field
1123  const double zPosNeck = fHorn2LongRescale*(39.8193 - 29.800)*in; // with respect to the start of the mother volume
1124  fHorn2NeckZPosition = zPosNeck;
1125  // We start by the neck
1126  {
1127  G4String nStrPN2("Horn2Part2Neck");
1128  const double radiusInner = fHorn2RadialRescale*3.071*in/2. + fHorn2RadialRescaleCst;
1129  const double radiusOuter = fHorn2RadialRescale*3.465*in/2. + fWaterLayerThickInHorns + 0.0025 + fHorn2RadialRescaleCst;
1131  fHorn2NeckInnerRadius = radiusInner;
1132  G4Tubs* tubsPartPN2 = new G4Tubs(nStrPN2, radiusInner, radiusOuter, lengthNeck/2., 0., 360.0*CLHEP::degree );
1133  G4LogicalVolume *tubsLPN2 = new G4LogicalVolume(tubsPartPN2, G4Material::GetMaterial(fHorn2InnerCondMat), nStr);
1134  posTmp[0] = 0.; posTmp[1] =0.;
1135  posTmp[2] = -1.0*fHorn2PartsLengths[kPart]/2 + zPosNeck;
1136  fHorn2IC.push_back(nStrPN2);
1137  G4PVPlacement *vNeck = new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLPN2, nStrPN2 + std::string("_P"),
1138  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1139  if (fWaterLayerThickInHorns > 0.002*CLHEP::mm) {
1140  G4String nameStrW5(nStr); nameStrW5 += std::string("Water");
1141  G4Tubs* tubsPartW5 = new G4Tubs(nameStrW5, radiusOuter -0.001*CLHEP::mm - fWaterLayerThickInHorns ,
1142  radiusOuter - 0.001*CLHEP::mm ,
1143  lengthNeck/2. - 0.002*CLHEP::mm, 0., 360.0*CLHEP::degree);
1144  G4LogicalVolume *pCurrentW5 = new G4LogicalVolume(tubsPartW5, G4Material::GetMaterial(std::string("Water")), nameStrW5);
1145  posTmp[0] = 0.; posTmp[1] = 0.; posTmp[2] =0.;
1146  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrentW5, nameStrW5 + std::string("_P"),
1147  vNeck->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1148  }
1149  // std::cerr<< "Rescaled Horn2 Neck Radius is, outer " << fHorn2NeckOuterRadius << "Inner "<<fHorn2NeckInnerRadius<<std::endl;
1150 
1151  } // Neck part per se.
1152  {
1153  double zStartDrawingsSubP2[] = {29.800, 36.8888, 41.0248, 43.3660}; // Note the third number is compromise, corresponding
1154  // to the length of the neck going ~2 " to 2.41 "
1155  double zEndDrawingsSubP2[] = {36.8888, 38.6138, 43.3660, 49.820};
1156  size_t eqnInner[] = {6, 6, 7, 7};
1157  size_t eqnOuter[] = {0, 1, 2 ,3};
1158  // Now loop on these 4 subparts. (this gona a bit tedious...)
1159  for (size_t kSub=0; kSub!=4; kSub++) {
1160  const double zStartDrawingPP2 = fHorn2LongRescale*zStartDrawingsSubP2[kSub]*in;
1161  const double zEndDrawingPP2 = fHorn2LongRescale*zEndDrawingsSubP2[kSub]*in;
1162  fHorn2ZEqnChanges.push_back(zStartDrawingPP2);
1163  // Need to insert the neck one.. to get consistent set to compute the magnetic field.
1164  if (kSub == 1) fHorn2ZEqnChanges.push_back(zEndDrawingPP2);
1165  const double zShiftTmp = zStartDrawingPP2 - fHorn2LongRescale*zStartDrawingsSubP2[0]*in;
1166  int numSubSect = GetNumberOfInnerHorn2SubSections(eqnInner[kSub], zStartDrawingPP2, zEndDrawingPP2, 10);
1167  const double deltaZ = (zEndDrawingPP2 - zStartDrawingPP2)/numSubSect;
1168 // std::cerr << " Number of subsection for the middle part of Horn2 index " << kPart
1169 // << " Upstream of the neck, is " << numSubSect
1170 // << " deltaz " << deltaZ << std::endl;
1171  for (int iSub = 0; iSub != numSubSect; iSub++) {
1172  const double zzBegin = zStartDrawingPP2 + iSub*deltaZ;
1173  const double zzEnd = zzBegin + deltaZ;
1174  std::ostringstream nameStrStr;
1175  nameStrStr << "Horn2InnerPart" << kPart << "NeckkSub" << kSub << "iSub" << iSub;
1176  G4String nameStr(nameStrStr.str());
1177  fHorn2IC.push_back(nameStr);
1178  const double rMin1 = fHorn2Equations[eqnInner[kSub]].GetVal(zzBegin); // Equation 1
1179  const double rMin2 = fHorn2Equations[eqnInner[kSub]].GetVal(zzEnd);
1180  const double rMax1 = fHorn2Equations[eqnOuter[kSub]].GetVal(zzBegin) + fWaterLayerThickInHorns + 0.0025;
1181  const double rMax2 = fHorn2Equations[eqnOuter[kSub]].GetVal(zzEnd) + fWaterLayerThickInHorns + 0.0025;
1182 // std::cerr << " Pre/Post Neck, zzbegin " << zzBegin << " radii " <<
1183 // rMin1 << " / " << rMax1 << " / " << rMin2 <<" / " << rMax2 << std::endl;
1184  G4Cons *aCons = new G4Cons(nameStr, rMin1, rMax1,rMin2, rMax2,
1185  (deltaZ - 0.005*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1186 
1187  G4LogicalVolume *pCurrent = new G4LogicalVolume(aCons, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1188  posTmp[0] = 0.; posTmp[1] = 0.;
1189  posTmp[2] = -fHorn2PartsLengths[kPart]/2 + iSub*deltaZ + deltaZ/2. + zShiftTmp;
1190  G4PVPlacement *vSub = new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrent, nameStr + std::string("_P"),
1191  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1192 
1193  if (fWaterLayerThickInHorns > 0.002*CLHEP::mm) {
1194  G4String nameStrW6(nameStr); nameStrW6 += std::string("Water");
1195  G4Cons *aConsW6 = new G4Cons(nameStrW6, rMax1 - fWaterLayerThickInHorns, rMax1-0.001*CLHEP::mm,
1196  rMax2 - fWaterLayerThickInHorns, rMax2-0.001*CLHEP::mm,
1197  (deltaZ - 0.0075*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1198  G4LogicalVolume *pCurrentW6 = new G4LogicalVolume(aConsW6, G4Material::GetMaterial(std::string("Water")), nameStrW6);
1199  posTmp[0] = 0.; posTmp[1] = 0.; posTmp[2] =0.;
1200  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrentW6, nameStrW6 + std::string("_P"),
1201  vSub->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1202  }
1203  }
1204  } // Parts surrounding the neck.
1205  // Weld Only the downstream one. The upstream part is comprise in the previous volume
1206 // if (std::abs(fHorn2RadialRescaleCst) < 1.0e-10*CLHEP::mm) {
1207  {
1208  std::ostringstream nameStrStr; nameStrStr << "Horn2NeckPart" << kPart << "WeldDownstr";
1209  G4String nameStr(nameStrStr.str());
1210  fHorn2IC.push_back(nameStr);
1211  const double weldLength = 2.0 * 0.386*in; // double the length to include the part on the next volume
1212  const double zzEndForWeld = fHorn2LongRescale*zEndDrawingsSubP2[3]*in + 0.50*CLHEP::mm;
1213  const double radius = fHorn2Equations[3].GetVal(zzEndForWeld) + fWaterLayerThickInHorns + 0.025; // Using equation e8, drawing 363387
1214 // std::cerr << " Debugging bad Radial Cst.. zzEndForWeld " << zzEndForWeld << " radius " << radius
1215 // << " kPart " << kPart << " name " << nameStr << std::endl;
1216  const double thick = 0.0775*in;
1217  G4Tubs* tubsPartN2P2 = new G4Tubs(nameStr, radius, (radius+thick), weldLength/2., 0., 360.0*CLHEP::degree);
1218  G4LogicalVolume *tubsLN2P2 = new G4LogicalVolume(tubsPartN2P2, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1219  posTmp[0] = 0.; posTmp[1] =0.;
1220  posTmp[2] = fHorn2PartsLengths[kPart]/2 - weldLength - 0.025*CLHEP::mm;
1221  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLN2P2, nameStr + std::string("_P"),
1222  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1223  }
1224  zStartDrawing = fHorn2LongRescale*49.820*in;
1225  }
1226  break;
1227  } // end of case 2
1228  case 6: // the downstream end piece. simple tubes.
1229  {
1230  {
1231  G4String nameStr("Horn2DownstrPart6");
1232  const double length = fHorn2LongRescale*(21.054 - 1.25)*in - 0.020*CLHEP::mm;
1233  const double radInner = fHorn2RadialRescale*21.103*in/2. + fHorn2RadialRescaleCst;
1234  const double radOuter = fHorn2RadialRescale*21.853*in/2. + fHorn2RadialRescaleCst;
1235  G4Tubs* tubsDP6 = new G4Tubs(nameStr, radInner, radOuter, length/2., 0., 360.0*CLHEP::degree);
1236  G4LogicalVolume *tubsLDP6 = new G4LogicalVolume(tubsDP6, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1237  posTmp[0] = 0.; posTmp[1] =0.;
1238  posTmp[2] = -fHorn2PartsLengths[kPart]/2 + length/2. + 0.0125*CLHEP::mm;
1239  fHorn2IC.push_back(nameStr);
1240  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLDP6, nameStr + std::string("_P"),
1241  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1242  }
1243  // the flange/connector
1244 
1245  {
1246  G4String nameStr("Horn2DownstrPart6Flange");
1247  const double length = fHorn2LongRescale*(1.25)*in - 0.020*CLHEP::mm;
1248  const double radInner = fHorn2RadialRescale*21.103*in/2. + fHorn2RadialRescaleCst;
1249  const double radOuter = fHorn2RadialRescale*25.040*in/2. + fHorn2RadialRescaleCst;
1250  G4Tubs* tubsFL6 = new G4Tubs(nameStr, radInner, radOuter, length/2., 0., 360.0*CLHEP::degree);
1251  G4LogicalVolume *tubsLFL6 = new G4LogicalVolume(tubsFL6, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1252  posTmp[0] = 0.; posTmp[1] =0.;
1253  posTmp[2] = fHorn2PartsLengths[kPart]/2 - length/2. - 0.0125*CLHEP::mm;
1254  fHorn2IC.push_back(nameStr);
1255  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLFL6, nameStr + std::string("_P"),
1256  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1257 
1258  }
1259  break;
1260  }
1261  default:
1262  { // One set of conical sections. + weld at the end
1263  const double zEndDrawing = zStartDrawing + fHorn2PartsLengths[kPart];
1264  size_t eqnInner = 6; // kPart =1
1265  size_t eqnOuter = 0;
1266  if (kPart == 3 ) {
1267  eqnOuter = 3;
1268  fHorn2ZEqnChanges.push_back(zStartDrawing);
1269  eqnInner = 7;
1270  } else if (kPart == 4) {
1271  eqnOuter = 4;
1272  fHorn2ZEqnChanges.push_back(zStartDrawing);
1273  eqnInner = 8;
1274  } else if (kPart == 5) {
1275  eqnOuter = 5;
1276  fHorn2ZEqnChanges.push_back(zStartDrawing);
1277  eqnInner = 9;
1278  fHorn2ZEqnChanges.push_back(zEndDrawing);
1279  }
1280  int numSubSect = GetNumberOfInnerHorn2SubSections(eqnOuter, zStartDrawing,
1281  zEndDrawing, 10);
1282  const double deltaZ = (zEndDrawing - zStartDrawing)/numSubSect;
1283 // std::cerr << " Number of subsection for the generic part of Horn2 index " << kPart << " is " << numSubSect
1284 // << " deltaz " << deltaZ << std::endl;
1285  double zzEndForWeld = 0.;
1286  for (int iSub = 0; iSub != numSubSect; iSub++) {
1287  const double zzBegin = zStartDrawing + iSub*deltaZ;
1288  const double zzEnd = zzBegin + deltaZ;
1289  zzEndForWeld = zzEnd;
1290  std::ostringstream nameStrStr; nameStrStr << "Horn2InnerPart" << kPart << "Sub" << iSub;
1291  G4String nameStr(nameStrStr.str());
1292  fHorn2IC.push_back(nameStr);
1293  const double rMin1 = fHorn2Equations[eqnInner].GetVal(zzBegin); // Equation 1
1294  const double rMin2 = fHorn2Equations[eqnInner].GetVal(zzEnd);
1295  const double rMax1 = fHorn2Equations[eqnOuter].GetVal(zzBegin) + fWaterLayerThickInHorns + 0.0025;
1296  const double rMax2 = fHorn2Equations[eqnOuter].GetVal(zzEnd) + fWaterLayerThickInHorns + 0.0025;
1297  G4Cons *aCons = new G4Cons(nameStr, rMin1, rMax1,rMin2, rMax2,
1298  (deltaZ - 0.005*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1299 
1300  G4LogicalVolume *pCurrent = new G4LogicalVolume(aCons,
1301  G4Material::GetMaterial(std::string(fHorn2InnerCondMat)), nameStr);
1302  posTmp[0] = 0.; posTmp[1] = 0.;
1303  posTmp[2] = -fHorn2PartsLengths[kPart]/2 + iSub*deltaZ + deltaZ/2.;
1304  G4PVPlacement *vSub = new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrent, nameStr + std::string("_P"),
1305  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1306 
1307  if (fWaterLayerThickInHorns > 0.002*CLHEP::mm) {
1308  G4String nameStrW(nameStr); nameStrW += std::string("Water");
1309  G4Cons *aConsW7 = new G4Cons(nameStrW, rMax1 - fWaterLayerThickInHorns, rMax1-0.001*CLHEP::mm,
1310  rMax2 - fWaterLayerThickInHorns, rMax2-0.001*CLHEP::mm,
1311  (deltaZ - 0.0075*CLHEP::mm)/2., 0., 360.0*CLHEP::degree);
1312 
1313  G4LogicalVolume *pCurrentW7 = new G4LogicalVolume(aConsW7, G4Material::GetMaterial(std::string("Water")), nameStrW);
1314  posTmp[0] = 0.; posTmp[1] = 0.; posTmp[2] =0.;
1315  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrentW7, nameStrW + std::string("_P"),
1316  vSub->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1317  }
1318 
1319  }
1320  // The weld at the end. Shift it a bit upstream such that it does not interfere
1321  {
1322  std::ostringstream nameStrStr; nameStrStr << "Horn2InnerPart" << kPart << "Weld";
1323  G4String nameStr(nameStrStr.str());
1324  fHorn2IC.push_back(nameStr);
1325  const double weldLength = 2.0 * 0.386*in; // double to include the next one.. Perhaps a bit oversized.
1326  if (kPart == 1) zzEndForWeld -= weldLength - 0.50*CLHEP::mm; // oversizing a bit by moving while computing the radius
1327  else zzEndForWeld += 0.50*CLHEP::mm;
1328  const double radius = fHorn2Equations[eqnOuter].GetVal(zzEndForWeld) + fWaterLayerThickInHorns + 0.0025;
1329  const double thick = 0.0775*in;
1330 // std::cerr << " Debugging bad Radial Cst.. zzEndForWeld " << zzEndForWeld << " radius " << radius
1331 // << " kPart " << kPart << " name " << nameStr << std::endl;
1332  G4Tubs* tubsPartWe7 = new G4Tubs(nameStr, radius, (radius+thick), weldLength/2., 0., 360.0*CLHEP::degree);
1333  G4LogicalVolume *tubsLWe7 = new G4LogicalVolume(tubsPartWe7, G4Material::GetMaterial(fHorn2InnerCondMat), nameStr);
1334  posTmp[0] = 0.; posTmp[1] =0.;
1335  posTmp[2] = fHorn2PartsLengths[kPart]/2 - weldLength/2. - 0.025*CLHEP::mm;
1336  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLWe7, nameStr + std::string("_P"),
1337  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1338  }
1339 
1340  zStartDrawing += fHorn2PartsLengths[kPart]; // for the next section
1341  }
1342  } //end of special cases.
1343  // Outer tube (not for k=0 )
1344  if (kPart != 0) {
1345  std::ostringstream nStrStrOU; nStrStrOU << "Horn2OuterConductor" << kPart;
1346  G4String nStrOU(nStrStrOU.str());
1347  const double leffOU = (fHorn2PartsLengths[kPart] - 0.040*CLHEP::mm);
1348  G4Tubs* tubsPartOU = new G4Tubs(nStrOU, fHorn2OuterTubeInnerRad, fHorn2OuterTubeOuterRad,
1349  leffOU/2.0, 0., 360.0*CLHEP::degree);
1350  G4LogicalVolume *tubsLOU = new G4LogicalVolume(tubsPartOU, G4Material::GetMaterial(fHorn2AllCondMat), nStrOU);
1351  posTmp[0] =0.; posTmp[1] =0.; posTmp[2] =0.;
1352  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLOU, nStrOU + std::string("_P"),
1353  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1354  } else {
1355 
1356  // April 2 2014: per careful observations by Seongtae Park
1357  // Talk delivered on March 27 2014.
1358  // The I/O transition outer conductor does not completly covers the range.
1359  std::ostringstream nStrStrOU2; nStrStrOU2 << "Horn2OuterConductor" << kPart << "Extra";
1360  G4String nStrOU2(nStrStr.str());
1361  const double leffOU2 = fHorn2LongRescale*96.5*CLHEP::mm;
1362  G4Tubs* tubsPartOU2 = new G4Tubs(nStrOU2, fHorn2OuterTubeInnerRad, fHorn2OuterTubeOuterRad,
1363  leffOU2/2.0, 0., 360.0*CLHEP::degree);
1364  G4LogicalVolume *tubsLOU2 = new G4LogicalVolume(tubsPartOU2, G4Material::GetMaterial(fHorn2AllCondMat), nStrOU2);
1365  posTmp[0] =0.; posTmp[1] =0.;
1366  posTmp[2] = fHorn2PartsLengths[0]/2.0 - leffOU2/2.0 - 0.010*CLHEP::mm;
1367  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsLOU2, nStrOU2 + std::string("_P"),
1368  vPart->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1369 
1370  }
1371  // Eventual Hangers. only one set
1372  if (kPart == 3) this->Horn2InstallSpiderHanger(nStr, vPart);
1373 
1374  // More
1375  } // Loop over the parts, daughters of top level.
1376  // Final flange downstream flange Approximate Drawing 363382-E1 Length is still a guess..
1377  G4String nStr("Horn2DownstrOuterFlange");
1378  G4Tubs* tubsOF1 = new G4Tubs(nStr, fHorn2OuterTubeOuterRad + 1.0*CLHEP::mm,
1379  fHorn2OuterTubeOuterRadMax-1.0*CLHEP::mm, 0.50*in, 0., 360.0*CLHEP::degree);
1380  G4LogicalVolume *tubsL = new G4LogicalVolume(tubsOF1, G4Material::GetMaterial(fHorn2AllCondMat), nStr);
1381  G4ThreeVector posTmp; posTmp[0] =0.; posTmp[1] =0.;
1382  posTmp[2] = plInfoH2Top->fParams[2]/2 - fHorn2LongRescale*0.6*in; // approximate location
1383  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, tubsL, nStr + std::string("_P"),
1384  vH2->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1385 }
1386 
1388 
1389  // ref : Drawing number 2251-000-ME-487107 and phone converstion with Glenn Waver (MD/AD)
1390  const double in = 2.54*CLHEP::cm;
1391  G4PVPlacement* vTop = this->PlaceFinal(G4String("DecayPipeSnout"), tunnel);
1392  const LBNEVolumePlacementData *plInfoTop = this->Find(G4String("Snout"), G4String("DecayPipeSnout"),
1393  G4String("LBNEVolumePlacements::PlaceFinalDecayPipeSnout"));
1394  //
1395  // The window is tilted, true vertical. Pick the rotation. Create a rotated buffer volume
1396  //
1397  LBNERunManager *pRunManager=static_cast<LBNERunManager*> (LBNERunManager::GetRunManager());
1398  const LBNEDetectorConstruction *pDet =
1399  static_cast<const LBNEDetectorConstruction*> (pRunManager->GetUserDetectorConstruction());
1400  G4double angle = pDet->GetBeamlineAngle();
1401  G4RotationMatrix *beamAngleRot = new G4RotationMatrix;
1402  beamAngleRot->rotateX(-angle);
1403 // std::cerr << " Window angle, yz term " << beamAngleRot->yz() << " yy "
1404 // << beamAngleRot->yy() << " zz " << beamAngleRot->zz() << std::endl;
1405  double boxX = 50.0*in + 0.1*CLHEP::mm;
1406  double boxY = 48.0*in + 0.1*CLHEP::mm;
1407  double boxZ = 24.0*in + 0.1*CLHEP::mm;
1408  G4String boxCStr("DecayPipeUpstrWindowCont");
1409  G4Box* aBoxC = new G4Box(boxCStr, boxX/2., boxY/2., boxZ/2.);
1410  G4LogicalVolume *contL = new G4LogicalVolume(aBoxC, G4Material::GetMaterial("DecayPipeGas"), boxCStr);
1411  G4ThreeVector posTmp; posTmp[0] =0.; posTmp[1] =0.;
1412  posTmp[2] = -plInfoTop->fParams[2]/2 + boxZ/2. + 0.5*CLHEP::cm; // approximate location, but accurate enough
1413  posTmp[2] += 25.0*in*std::abs( beamAngleRot->yz()); // inclined! Shift a bit upstream
1414 // std::cerr << " Position of the rotated container " << posTmp[2] << std::endl;
1415  G4PVPlacement *vCont = new G4PVPlacement(beamAngleRot, posTmp, contL, boxCStr + std::string("_P"),
1416  vTop->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1417 // if air, we stop here, the aluminum window and the window itself don't exist.
1418 // (3.5 million bugs saving, I am told..)
1419 
1420  if (fDecayPipeGas == G4String("Air")) return;
1421  boxX -= 0.1*CLHEP::mm;
1422  boxY -= 0.1*CLHEP::mm;
1423  boxZ -= 0.1*CLHEP::mm;
1424  G4String boxFStr("DecayPipeUpstrWindowFrame");
1425  G4Box* aBoxF = new G4Box(boxFStr, boxX/2., boxY/2., boxZ/2.);
1426  G4LogicalVolume *frameL = new G4LogicalVolume(aBoxF, G4Material::GetMaterial("Aluminum"), boxFStr);
1427  posTmp[0] =0.; posTmp[1] =0.; posTmp[2] =0.;
1428  G4PVPlacement *vFrame = new G4PVPlacement((G4RotationMatrix *) 0, posTmp,
1429  frameL, boxFStr + std::string("_P"),
1430  vCont->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1431 
1432  G4String holeFStr("DecayPipeUpstrWindowHole");
1433  double holeRadius= fDecayPipeWindowRadiusAlum + 0.01*CLHEP::mm;
1434  G4Tubs* holeR = new G4Tubs(holeFStr, 0., holeRadius, boxZ/2., 0., 360.0*CLHEP::degree);
1435  // The upstream part is Air..
1436  G4LogicalVolume *holeL = new G4LogicalVolume(holeR, G4Material::GetMaterial("Air"),holeFStr);
1437  G4PVPlacement *vHole = new G4PVPlacement((G4RotationMatrix *) 0, posTmp,
1438  holeL, holeFStr + std::string("_P"),
1439  vFrame->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1440 //
1441  G4String windAlumStr("DecayPipeUpstrWindowAlum");
1442  G4Tubs* windAlum = new G4Tubs(windAlumStr, fDecayPipeWindowRadiusBeryl,
1443  fDecayPipeWindowRadiusAlum , fDecayPipeWindowThickAlum/2., 0., 360.0*CLHEP::degree);
1444  // The upstream part is Air..
1445  G4LogicalVolume *windAlumL = new G4LogicalVolume(windAlum, G4Material::GetMaterial("Aluminum"), windAlumStr);
1446  posTmp[2] = -boxZ/2. + 17.1*in + 3.0*CLHEP::mm; // first number picked up from drawing. We place the Alum a bit behind..
1447  new G4PVPlacement((G4RotationMatrix *) 0, posTmp,
1448  windAlumL, windAlumStr + std::string("_P"),
1449  vHole->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1450 
1451  G4String windBerylStr("DecayPipeUpstrWindowBeryl");
1452  G4Tubs* windBeryl = new G4Tubs(windBerylStr, 0.,
1453  fDecayPipeWindowRadiusBeryl , fDecayPipeWindowThickBeryl/2., 0., 360.0*CLHEP::degree);
1454  // The upstream part is Air..
1455  G4LogicalVolume *windBerylL = new G4LogicalVolume(windBeryl, G4Material::GetMaterial("Beryllium"), windBerylStr);
1456  posTmp[2] = -boxZ/2. + 17.1*in + 1.0*CLHEP::mm; // first number picked up from drawing.
1457  new G4PVPlacement((G4RotationMatrix *) 0, posTmp,
1458  windBerylL, windBerylStr + std::string("_P"),
1459  vHole->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1460 }
1461 // Clone for Horn1.. Could avoid a bit of code bloat, but that's not much...
1462 int LBNEVolumePlacements::GetNumberOfInnerHorn2SubSections(size_t eqn, double z1, double z2, int nMax) const {
1463 
1464  int numSubSect = 1;
1465  double zEnd = z2;
1466  const double zLengthTotal = z2 - z1;
1467  double zLength = zLengthTotal;
1468  while (true) {
1469  const double r0 = fHorn2Equations[eqn].GetVal(z1);
1470  const double r1 = fHorn2Equations[eqn].GetVal(zEnd);
1471  const double rMid = fHorn2Equations[eqn].GetVal((z1 + zEnd)/2.);
1472 // std::cerr << " GetNumberOfInnerHorn2SubSections z1 " << z1 << " zEnd " << zEnd <<
1473 // " r0 " << r0 << " r1 " << r1 << " rMid " << rMid << std::endl;
1474  if (std::abs(rMid - 0.5*(r0+r1)) < 0.050*CLHEP::mm) break; // 50 microns good enough for Gov. work.
1475  // meachanical tolerance is one 5 mills, (127 microns)
1476  zLength /=2.;
1477  zEnd = z1 + zLength;
1478  numSubSect++;
1479  if (numSubSect > nMax) {
1480  G4Exception("LBNEVolumePlacements::PlaceFinalHorn2", " ", FatalErrorInArgument, " Crazy subdivision! ");
1481  break;
1482  }
1483  }
1484  return numSubSect;
1485 }
1486 // Clone from Horn1 .. But simpler, less arguments because there is one set of such contraptions.
1487 
1488 void LBNEVolumePlacements::Horn2InstallSpiderHanger(const G4String &nameStrH, G4PVPlacement *vMother ) {
1489 
1490  const double in = 2.54*CLHEP::cm;
1491  G4String nameStr(nameStrH);nameStr += G4String("Ring");
1492  // Drawing 8875.112-MD 363388 and 363405
1493  const double length = 0.750*in*fHorn2LongRescale;
1494  const int eqnNum = 3;
1495  const double zLocDrawing = fHorn2LongRescale*60.4681*in;
1496  const double rTmp1 = fHorn2Equations[eqnNum].GetVal(zLocDrawing) + 0.015*CLHEP::mm + fWaterLayerThickInHorns;
1497 // const double rTmp2 = fHorn2RadialRescale*11.625*in + fWaterLayerThickInHorns + 0.015*CLHEP::mm; //
1498 // 11.625 inches is the outer diameter of this ring. Not it's radius. Arghh! Feb 4 2014, P. Lebrun
1499  const double rTmp2 = fHorn2RadialRescale*11.625*in/2.0 + fWaterLayerThickInHorns + 0.015*CLHEP::mm + fHorn2RadialRescaleCst; //
1500 // Re instate the error to study it.. Feb 19 2014
1501 // const double rTmp2 = fHorn2RadialRescale*11.625*in + fWaterLayerThickInHorns + 0.015*CLHEP::mm; //
1502 // std::cerr << " LBNEVolumePlacements::Horn2InstallSpiderHanger, radii of the rings.. " << rTmp1 << " " << rTmp2 << std::endl;
1503 // std::cerr << " .... Volume name ... " << nameStr << " ... Aud quit !!! " << std::endl; exit(2);
1504  G4Tubs *aTubs = new G4Tubs(nameStr, rTmp1, rTmp2, length/2. , 0., 360.0*CLHEP::degree);
1505  G4LogicalVolume *pCurrent = new G4LogicalVolume(aTubs, G4Material::GetMaterial(fHorn2AllCondMat), nameStr);
1506  G4ThreeVector posTmp; posTmp[0] = 0.; posTmp[1] = 0.;
1507  posTmp[2] = fHorn2LongRescale*in*(-0.0180); // computed from drawing 8875.112MD-363388
1508  new G4PVPlacement((G4RotationMatrix *) 0, posTmp, pCurrent, nameStr + std::string("_P"),
1509  vMother->GetLogicalVolume(), false, 1, fCheckVolumeOverLapWC);
1510 
1511  //The connecting piece ring to the hangers.. There are three of them, at 120 degrees from each other.
1512 
1513  G4String nameStr2(nameStrH); nameStr2 += G4String("Riser");
1514  const double heightRiser = 0.333*in - 0.020*CLHEP::mm;
1515  const double widthH = 1.5*in; // See drawing 8875.112-MD 363115
1516  const double thickH = 0.184*2*in;
1517  G4Box *aBoxRiser = new G4Box(nameStr2, widthH/2., heightRiser/2.0, thickH/2.0);
1518  G4LogicalVolume *pCurrentRiser =
1519  new G4LogicalVolume(aBoxRiser, G4Material::GetMaterial(fHorn2AllCondMat), nameStr2);
1520 
1521  G4String nameStr3(nameStrH); nameStr3 += G4String("Hanger");
1522  const double heightH = fHorn2OuterTubeInnerRad - rTmp2 - 1.0*CLHEP::mm - heightRiser;
1523  const double widthH2 = 1.0*in; // 363115 Note: we collapsed both hanger along the horizontal, transverse
1524  // direction.
1525  const double thickH2 = 0.031*in;
1526  G4Box *aBoxHanger = new G4Box(nameStr3, widthH2/2., heightH/2.0, thickH2/2.0);
1527  G4LogicalVolume *pCurrentHanger =
1528  new G4LogicalVolume(aBoxHanger, G4Material::GetMaterial(fHorn2AllCondMat), nameStr3);
1529 
1530  for (int iRot=0; iRot != 3; iRot++) {
1531  std::ostringstream rnStrStr; rnStrStr << "_" << (iRot+1);
1532  G4String rnStr(rnStrStr.str());
1533  // Same Z position as above...
1534  G4RotationMatrix * rMatPr = 0;
1535  if (iRot == 1) {
1536  rMatPr = new G4RotationMatrix;
1537  rMatPr->rotateZ(2.0*M_PI/3.);
1538  } else if (iRot == 2) {
1539  rMatPr = new G4RotationMatrix;
1540  rMatPr->rotateZ(-2.0*M_PI/3.);
1541  }
1542 
1543  const double dHRiser = rTmp2 + 0.010*CLHEP::mm + heightRiser/2.;
1544  posTmp[0] = 0.; posTmp[1] = dHRiser;
1545  if (iRot != 0) {
1546  posTmp[0] = dHRiser*rMatPr->xy();
1547  posTmp[1] = dHRiser*rMatPr->yy();
1548  }
1549  if (iRot == 0) {
1550  new G4PVPlacement(rMatPr, posTmp, pCurrentRiser, nameStr2 + std::string("_P") + rnStr,
1551  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
1552  } else {
1553  new G4PVPlacement(G4Transform3D(*rMatPr, posTmp), pCurrentRiser, nameStr2 + std::string("_P") + rnStr,
1554  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
1555  }
1556 // Now the hanger it self
1557 
1558  const double dHHanger = rTmp2 + 0.010*CLHEP::mm + 0.5*CLHEP::mm + heightRiser + heightH/2.;
1559  posTmp[0] = 0.; posTmp[1] = dHHanger;
1560  if (iRot != 0) {
1561  posTmp[0] = dHHanger*rMatPr->xy();
1562  posTmp[1] = dHHanger*rMatPr->yy();
1563  }
1564  // Same Z position as above...
1565  if (iRot == 0) {
1566  new G4PVPlacement(rMatPr, posTmp, pCurrentHanger, nameStr3 + std::string("_P") + rnStr,
1567  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
1568  } else {
1569  new G4PVPlacement(G4Transform3D(*rMatPr, posTmp), pCurrentHanger, nameStr3 + std::string("_P") + rnStr,
1570  vMother->GetLogicalVolume(), false, iRot, fCheckVolumeOverLapWC);
1571  }
1572  } // on the 120 degree symmetry point.
1573 }
1575  //
1576  // Pior to construct the long chase that contains both the target and the horns, we check the length of this mother volume
1577  // is sufficient. If not, we do not extend the tunnel, but reduce the decay pipe length. Paul L. Lebrun, Feb 2015.
1578  // Based on discussion with Alberto M., Feb 6 2015.
1579  //
1580  const double aH2AllLength = fHorn2Length + 4.0*fHorn2LengthMargin + 2.5*CLHEP::cm; // Last is the Amit's tracking plane
1581  // We assume here that the decay pipe snout will not be placed..
1582  const double aEndH2 = aH2AllLength + fHorn2LongPosition - fHorn2OffsetIOTr1; // See Placement of Horn2Hall
1583  if (aEndH2 > fDecayPipeLongPosition ) {
1584  const double delta = aEndH2 - fDecayPipeLongPosition + 1.0*CLHEP::cm; // Last if for good measure..
1585  fDecayPipeLongPosition += delta;
1586  fDecayPipeLength -= delta;
1587  std::cerr << " LBNEVolumePlacements::ExtendChaseLengthForHorn2, moving beginning of decay pipe downstream by "
1588  << delta/CLHEP::m << " meters " << std::endl;
1589  std::cerr << " New Decay length = " << fDecayPipeLength/CLHEP::m << " Starting at "
1590  << fDecayPipeLongPosition/CLHEP::m << " meters" << std::endl;
1591  }
1592 
1593 }
1594 
1595 double LBNEHornRadialEquation::inchDef = 2.54*CLHEP::cm;
1596 
1597 LBNEHornRadialEquation::LBNEHornRadialEquation(double rc, double zc, double rOffTmp, bool isParabolic):
1598 parabolic(isParabolic),
1599 rCoeff(rc),
1600 zCoeff(zc),
1601 rOff(rOffTmp),
1602 rResc(1.0),
1603 rRescCst(0.),
1604 zResc(1.0)
1605 { ; }
1606 
1607 double LBNEHornRadialEquation::GetVal(double z) const {
1608  // z = 0 above is by arbitrary choice the Z coordinate of the starting point of the Horn1TopLevelUpstr logical volume
1609  // We shift the drawing coordinate system
1610  // const double zD = z + 3.2852*inchDef*zResc; // Only valid for Horn1 !!!!!
1611 // By definition, drawing 8875.000-ME-363028 (Z=0 is ACTRNT)
1612 
1613  const double zR = z/inchDef; // back in inches.
1614  const double argR = rCoeff + zR*zCoeff/zResc;
1615  if (argR < 0.) {
1616  std::ostringstream mStrStr; mStrStr << " Negative argument, z = " << z
1617  << " argR " << argR << " zResc " << zResc << std::endl;
1618  G4String mStr(mStrStr.str());
1619  G4Exception("LBNEHornRadialEquation::GetVal", " ", FatalErrorInArgument, mStr.c_str());
1620  }
1621  const double radius = parabolic ? (std::sqrt(argR) + rOff) : argR;
1622 // return radius*zResc*inchDef; v3r0p10
1623  return (radius*rResc*inchDef + rRescCst); // Dec 16: add a constant term for this linear transform
1624 }
1625 
1627 
1628  //Test at the end of first section of Horn1 (8875.112-MD 363104)
1629  const double argZ = (3.2645 + 17.876 - 0.031);
1630  const double rTest = this->GetVal(argZ*25.4*CLHEP::mm*zResc);
1631  std::cerr << " LBNEHornRadialEquation::test1, argZ " << argZ << " rTest (mm) " << rTest << std::endl;
1632  std::cerr << " inchDef " << inchDef << " zCoeff " << zCoeff << " rCoeff " << rCoeff << " rOff " << rOff << std::endl;
1633  const double delta = 2.0*rTest - 1.6326*25.4*CLHEP::mm*rResc; // Actually, the drawing says 1.6 !!! mistake of 700 microns.
1634  std::cerr << " delta (mm) " << delta << " zResc " << zResc << " rResc " << rResc << std::endl;
1635  if (std::abs(delta) > 0.127*CLHEP::mm) { // 5 mill tolerance
1636  G4Exception("LBNEHornRadialEquation::test1", " ", FatalErrorInArgument,
1637  " Horn1 Equation 0 inconsistent with drawing 363104");
1638  }
1639 }
int GetNumberOfInnerHornSubSections(size_t eqn, double z1, double z2, int nMax) const
std::vector< G4double > fHorn2UpstrOuterIOTransRadsTwo
std::vector< double > fMotherHorn1AllLengths
std::vector< LBNEHornRadialEquation > fHorn1Equations
intermediate_table::iterator iterator
std::vector< G4double > fTargetHorn1ZPositions
int GetNumberOfInnerHorn2SubSections(size_t eqn, double z1, double z2, int nMax) const
void Horn1InstallSpiderHanger(const G4String &name, double zFromStartInnerConduct, double zPos, G4PVPlacement *vMother)
void PlaceFinalDownstrTarget1p2MW(G4PVPlacement *mother)
const LBNEVolumePlacementData * Find(const G4String &name, const char *motherName, const char *method) const
void Horn2InstallSpiderHanger(const G4String &name, G4PVPlacement *vMother)
std::string string
Definition: nybbler.cc:12
std::vector< G4double > fHorn1UpstrOuterIOTransPositions
std::vector< G4double > fHorn1UpstrOuterIOTransLengths
G4double fTargetCTubeReturnDownstrThickTitanium
intermediate_table::const_iterator const_iterator
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:45
std::vector< G4double > fHorn2UpstrOuterIOTransPositions
void PlaceFinalDownstrTarget(G4PVPlacement *mother)
std::vector< G4double > fHorn2ZEqnChanges
std::vector< G4double > fTargetHorn1InnerRadsUpstr
LBNEVolumePlacementData * CreateHorn1TopLevelUpstr()
std::map< G4String, LBNEVolumePlacementData > fSubVolumes
std::vector< G4double > fHorn1UpstrOuterIOTransInnerRads
std::vector< G4double > fHorn2PartsRadii
T abs(T value)
std::vector< G4String > fHorn2IC
std::vector< double > fParams
std::vector< G4double > fTargetHorn1Lengths
std::vector< LBNEHornRadialEquation > fHorn2Equations
std::vector< G4double > fHorn2PartsLengths
std::vector< G4double > fHorn2UpstrOuterIOTransLengths
double z
LBNEVolumePlacementData * Create(const G4String &name)
void PlaceFinalHorn2(G4PVPlacement *mother)
std::vector< G4double > fHorn1UpstrInnerRadsOuterUpstr
std::vector< G4double > fHorn1UpstrInnerRadsOuterDownstr
G4double fTargetCTubeReturnDownstrThickWater
std::vector< G4double > fHorn1UpstrOuterIOTransThicks
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::vector< G4double > fHorn1UpstrInnerRadsDownstr
std::vector< G4double > fTargetHorn1TransThick
std::vector< G4double > fHorn1UpstrZPositions
std::vector< G4double > fHorn1UpstrInnerRadsUpstr
G4PVPlacement * PlaceFinal(const G4String &name, G4VPhysicalVolume *mother)
std::vector< G4double > fHorn1UpstrLengths
std::vector< double > fMotherHorn1AllRads
void PlaceFinalDecayPipeSnout(G4PVPlacement *mother)
std::vector< G4double > fTargetHorn1InnerRadsDownstr
double GetVal(double z) const
std::vector< G4double > fHorn2UpstrOuterIOTransRadsOne
QTextStream & endl(QTextStream &s)