LBNFMagneticFieldPolyconeHorn.cc
Go to the documentation of this file.
1 //----------------------------------------------------------------------
2 //LBNFMagneticFieldPolyconeHorn
3 // $Id
4 //----------------------------------------------------------------------
5 
7 
8 #include "G4VPhysicalVolume.hh"
9 #include "G4ios.hh"
10 #include "G4TransportationManager.hh"
11 #include "LBNEVolumePlacements.hh"
12 #include "LBNESurveyor.hh"
13 #include "Randomize.hh"
14 #include "LBNERunManager.hh"
15 #include <fstream>
16 
17 //magnetic field between conductors ====================================================
18 
20 hornNumber(iH), // indexed 0 to 4..
21 fHornCurrent(0.),
22 fEffectiveLength(0.),
23 fOuterRadius(1.0e9),
24 fOuterRadiusEff(1.0e9),
25 fSkinDepth(4.1*CLHEP::mm),
26 fSkinDepthInnerRad(1.0e10*CLHEP::mm), // Unrealistic high, because that was the default sometime ago.
27 fSkinDepthIIRInv(std::sqrt(2)/fSkinDepthInnerRad),
28 fDeltaEccentricityIO(0.),
29 fDeltaEllipticityI(0.),
30 fShift(2, 0.),
31 fShiftSlope(2,0.)
32 {
33 //
34 // Magnetic field for the simple Polycone horn. This field is attached to container volume
35 // LBNFSimpleHornxContainer, which is a box. The field is defined the Polycone, we keep our own geometry
36 // such we can implement field error in the future, should it be necessary..
37 //
38  const LBNEVolumePlacements *aPlacementHandler = LBNEVolumePlacements::Instance();
39  fZShiftDrawingCoordinate = 0.; // Check with Geantino here...
40  fZDCBegin.clear();
41  fRadsInnerC.clear();
42  fRadsOuterC.clear();
43  double zzMinTmp = 1.0e20;
44  double zzMaxTmp = -1.0e20;
45  fOuterRadius = aPlacementHandler->GetHornsPolyOuterRadius(hornNumber + 1);
47  if (aPlacementHandler->IsHornPnParabolic(hornNumber + 1)) {
48  size_t nPts = aPlacementHandler->GetHornParabolicNumInnerPts(iH);
49  const double epsil = 0.050*CLHEP::mm; // from LBNEVolumePlacements::UpdateParamsForHornMotherPolyNum
50  for (size_t k=0; k != nPts; k++) {
51  const double zzz = aPlacementHandler->GetHornParabolicRZCoord(iH, k) + fZShiftDrawingCoordinate + epsil;
52  zzMinTmp = std::min(zzMinTmp, zzz);
53  zzMaxTmp = std::max(zzMaxTmp, zzz);
54  fZDCBegin.push_back(zzz);
55  const double rIn = aPlacementHandler->GetHornParabolicRIn(iH, k) - epsil;
56  fRadsInnerC.push_back(rIn);
57  const double rOut = rIn + aPlacementHandler->GetHornParabolicThick(iH, k);
58  fRadsOuterC.push_back(rOut);
59  }
60  } else {
61  if ((hornNumber == 0) && aPlacementHandler->GetUseLBNFOptimConceptDesignHornA()) {
62  fZDCBegin = aPlacementHandler->GetHornsPolyInnerConductorZsHornARev2();
63  std::cerr << " First fZDCBegin for horn A " << fZDCBegin[0]+ fZShiftDrawingCoordinate << std::endl;
64  // We shift in global coordinate..
65  std::cerr << "LBNFMagneticFieldPolyconeHorn::LBNFMagneticFieldPolyconeHorn, CD HornA, fZShiftDrawingCoordinate "
67 // std::cerr << " And quit after Horn A " << std::endl; exit(2);
68  for (size_t k=0; k !=fZDCBegin.size(); k++) { fZDCBegin[k] += fZShiftDrawingCoordinate; }
71  for (size_t k=0; k != fRadsInnerC.size(); k++) { fRadsOuterC[k] += aPlacementHandler->GetThickICDRevisedHornA(); }
72  std::cerr << " .... /Rin/Rout map, global coordinate system " << std::endl;
73  for (size_t k=0; k !=fZDCBegin.size(); k++)
74  std::cerr << " " << k << " "
75  << fZDCBegin[k] << " " << fRadsInnerC[k] << " " << fRadsOuterC[k] << std::endl;
76  zzMinTmp = fZDCBegin[0];
77  zzMaxTmp = fZDCBegin[fZDCBegin.size()-1];
78  } else if ((hornNumber == 1) && aPlacementHandler->GetUseLBNFOptimConceptDesignHornB()) {
79  fZDCBegin = aPlacementHandler->GetHornsPolyInnerConductorZsHornBRev2();
80  // We shift in global coordinate..
81  std::cerr << "LBNFMagneticFieldPolyconeHorn::LBNFMagneticFieldPolyconeHorn, CD HornB, fZShiftDrawingCoordinate "
83  for (size_t k=0; k !=fZDCBegin.size(); k++) { fZDCBegin[k] += fZShiftDrawingCoordinate; }
86  for (size_t k=0; k != fRadsInnerC.size(); k++) { fRadsOuterC[k] += aPlacementHandler->GetThickICDRevisedHornB(); }
87  std::cerr << " .... /Rin/Rout map, global coordinate system " << std::endl;
88  for (size_t k=0; k !=fZDCBegin.size(); k++)
89  std::cerr << " " << k << " "
90  << fZDCBegin[k] << " " << fRadsInnerC[k] << " " << fRadsOuterC[k] << std::endl;
91 
92  zzMinTmp = fZDCBegin[0];
93  zzMaxTmp = fZDCBegin[fZDCBegin.size()-1];
94  } else if ((hornNumber == 2) && aPlacementHandler->GetUseLBNFOptimConceptDesignHornC()) {
95  fZDCBegin = aPlacementHandler->GetHornsPolyInnerConductorZsHornCRev2();
96  // We shift in global coordinate..
97  std::cerr << "LBNFMagneticFieldPolyconeHorn::LBNFMagneticFieldPolyconeHorn, CD HornC, fZShiftDrawingCoordinate "
99  for (size_t k=0; k !=fZDCBegin.size(); k++) { fZDCBegin[k] += fZShiftDrawingCoordinate; }
102  for (size_t k=0; k != fRadsInnerC.size(); k++) { fRadsOuterC[k] += aPlacementHandler->GetThickICDRevisedHornC(); }
103  std::cerr << " .... /Rin/Rout map, global coordinate system " << std::endl;
104  for (size_t k=0; k !=fZDCBegin.size(); k++)
105  std::cerr << " " << k << " "
106  << fZDCBegin[k] << " " << fRadsInnerC[k] << " " << fRadsOuterC[k] << std::endl;
107 
108  zzMinTmp = fZDCBegin[0];
109  zzMaxTmp = fZDCBegin[fZDCBegin.size()-1];
110  } else { // simplified geometry for the horns.
111  for (size_t k=0; k!= static_cast<size_t>(aPlacementHandler->GetUseHornsPolyNumInnerPts(hornNumber + 1)); k++) {
112  const double zzz = aPlacementHandler->GetHornsPolyInnerConductorZCoord(hornNumber + 1, k) + fZShiftDrawingCoordinate;
113  zzMinTmp = std::min(zzMinTmp, zzz);
114  zzMaxTmp = std::max(zzMaxTmp, zzz);
115  fZDCBegin.push_back(zzz);
116  double rIn = aPlacementHandler->GetHornsPolyInnerConductorRadius(hornNumber + 1, k);
117  double rOut = rIn + aPlacementHandler->GetHornsPolyInnerConductorThickness(hornNumber + 1, k);
118  fRadsInnerC.push_back(rIn);
119  fRadsOuterC.push_back(rOut);
120  }
121 // std::cerr << " k " << k << " z " << fZDCBegin[fZDCBegin.size()-1] << " InnerC " << rIn << " out " << rOut << std::endl;
122  }
123  }
124  fEffectiveLength = zzMaxTmp - zzMinTmp;
125 
126 // std::cerr << " And quit for now.. I say so.. " << std::endl; exit(2);
127 //
128 
129 // Use now the survey data (simulated for now.. ) to establish the coordinate transform..
130 //
131  LBNESurveyor *theSurvey= LBNESurveyor::Instance();
132  std::ostringstream hornIndexStrStr; hornIndexStrStr << hornNumber+1;
133  std::string hornIndexStr(hornIndexStrStr.str());
134  std::string upstrStr("Upstream");std::string downstrStr("Downstream");
135  std::string leftStr("Left"); std::string rightStr("Right");
136  std::string ballStr("BallHorn");
138  theSurvey->GetPoint(G4String(upstrStr + leftStr + ballStr + hornIndexStr));
140  theSurvey->GetPoint(G4String(upstrStr + rightStr + ballStr + hornIndexStr));
142  theSurvey->GetPoint(G4String(downstrStr + leftStr + ballStr + hornIndexStr));
144  theSurvey->GetPoint(G4String(downstrStr + rightStr + ballStr + hornIndexStr));
145  const G4ThreeVector pUpLeft = itUpLeft->GetPosition();
146  const G4ThreeVector pUpRight = itUpRight->GetPosition();
147  const G4ThreeVector pDwLeft = itDwLeft->GetPosition();
148  const G4ThreeVector pDwRight = itDwRight->GetPosition();
149  std::cerr << " For Horn " << hornNumber+1 << " pUpLeft "
150  << pUpLeft << " right " << pUpRight << " pDwLeft "
151  << pDwLeft << " effLength " << fEffectiveLength << std::endl;
152  fHornIsMisaligned = false;
153  for (size_t k=0; k!=2; k++) {
154  fShift[k] = -0.50*(pUpLeft[k] + pUpRight[k]); // minus sign comes from the global to local.
155  // Transverse shoft at the upstream entrance of Horn1
156  fShiftSlope[k] = 0.5*(pUpLeft[k] + pUpRight[k] - pDwLeft[k] - pDwRight[k])/fEffectiveLength;
157  if (std::abs(fShiftSlope[k]) > 1.0e-8) fHornIsMisaligned = true;
158  }
159  if (fHornIsMisaligned) {
160  std::ostringstream aNameStrStr; aNameStrStr << "LBNFSimpleHorn" << (hornNumber+1) << "Container";
161  std::string namePlacedVol(aNameStrStr.str());
162  if (hornNumber == 0) namePlacedVol = std::string("Horn1PolyM1");
163  const LBNEVolumePlacementData* plDat=
164  aPlacementHandler->Find("BFieldInitialization", namePlacedVol.c_str(), "BFieldInitialization");
166  std::cerr << " Horn " << hornNumber+1 << " is misaligned "
167  << " xz term " << fRotMatrixHornContainer[0][2] << " yz " << fRotMatrixHornContainer[1][2] << std::endl;
168 // fHornIsMisaligned = false;
169 // std::cerr << " !!!! Back door setting of the HornisMialigned, we will not rotate the field " << std::endl;
170  }
171 
172 //
173 // Open a file to study the value of the field for displaced trajectory...
174 //
175 // if (!fOutTraj.is_open()) {
176 // G4String fNameStr("./FieldTrajectories_Horn");
177 // if (amHorn1) fNameStr += G4String("1_1.txt");
178 // else fNameStr += G4String("2_1.txt");
179 // fOutTraj.open(fNameStr.c_str()); // we will place a GUI interface at a later stage...
180 // fOutTraj << " id x y z bx by " << std::endl;
181 // }
182 // if (hornNumber == 1) this->TestDivergence(0); Not to be done here, the correction term are not yet declared.
183 // See LBNEDetectorConstruction, at debug line "Defining Polycone Mag field, usedNumberOfHornsPoly"
184 //
185 // Build the field if the Quadrupole amplitude greater than 1.
186 //
187  fField3DMapCurrentEqualizer.clear(); // Optional fill below.. Once we know the parameters for the simulation..
188  fDebugIsOn = false;
192 }
193 
194 void LBNFMagneticFieldPolyconeHorn::GetFieldValue(const double Point[3],double *Bfield) const
195 {
196 // std::cerr << " LBNFMagneticFieldPolyconeHorn::GetFieldValue, z = " << Point[2] << std::endl;
197  for (size_t k=0; k!=3; ++k) Bfield[k] = 0.;
198  const double zGlobal = Point[2];
199  // Intialization of the coordinate transform.
200 // const LBNEVolumePlacements *aPlacementHandler = LBNEVolumePlacements::Instance(); // no longer needed here. See above..
201  std::vector<double> ptTrans(3,0.);
202  for (size_t k=0; k != 2; k++)
203  ptTrans[k] = Point[k] + fShift[k] + (zGlobal-fZDCBegin[0])*fShiftSlope[k];
204  if ((fCurrentEqualizerQuadAmpl > 1.) && (fField3DMapCurrentEqualizer.size() == 0)) {
205  fDebugIsOn = false; // O.K. for Now, until debugged.
207  fDebugIsOn = false;
208  }
209  if (fCurrentEqualizerQuadAmpl > 1.) {
210  // From field map..
211  double bFieldFromMap[3];
212  ptTrans[2] = zGlobal;
213  this->getFieldFrom3DMapCurrentEqualizer(&ptTrans[0], bFieldFromMap);
214  Bfield[0] = bFieldFromMap[0];
215  Bfield[1] = bFieldFromMap[1];
216  if (fHornIsMisaligned) {
217  std::vector<double> bFieldLocal(3);
218  for(size_t k=0; k != 3; k++) { bFieldLocal[k] = Bfield[k]; Bfield[k] = 0.; }
219  for (size_t k1=0; k1 !=3; k1++) {
220  for (size_t k2=0; k2 !=3; k2++) Bfield[k1] += fRotMatrixHornContainer[k1][k2]*bFieldLocal[k2];
221  }
222  }
223  return; // No Correction for skin depth effect. Will be included in the map, if need be...
224  }
225  G4double current = fHornCurrent/CLHEP::ampere/1000.;
226 // std::cerr << " LBNFMagneticFieldPolyconeHorn::GetFieldValue Z gobal " << Point[2]
227 // << " fZDCBegin, first " << fZDCBegin[0] << " last " << fZDCBegin[fZDCBegin.size() -1]
228 // << " for horn " << (hornNumber+1) << " current " << current << std::endl;
229  const double r = std::sqrt(ptTrans[0]*ptTrans[0] + ptTrans[1]*ptTrans[1]);
230  const double phi = std::atan2(Point[1], Point[0]);
231  if (r > fOuterRadius) return;
232 // if ( r < 1.0e-3) return; // The field should go smoothly to zero at the center of the horm No longer valid if Eccentricity
233 
234  double magBField = current / (5.*r/CLHEP::cm)/10*CLHEP::tesla; //B(kG)=i(kA)/[5*r(cm)], 1T=10kG
235  // Implement the azimuthal anisotropy due to imperfection of the current equalizer section.
236  const bool doCurrentEqualizerCorr = ((std::abs(fCurrentEqualizerQuadAmpl) > 1.0e-9) ||
237  (std::abs(fCurrentEqualizerOctAmpl) > 1.0e-9) );
238  if (doCurrentEqualizerCorr) {
239  double zFactAzi = 1.0e-6;
240  switch(hornNumber) {
241  case 0:
242  case 2:
243  zFactAzi = ((zGlobal - fZDCBegin[0]) > 0.) ? (zGlobal - fZDCBegin[0])/fCurrentEqualizerLongAbsLength : 1.0e-6;
244  break;
245  case 1:
246  zFactAzi = ((fZDCBegin[fZDCBegin.size() -1] - zGlobal) > 0.) ?
247  (fZDCBegin[fZDCBegin.size() -1] - zGlobal)/fCurrentEqualizerLongAbsLength : 1.0e-6;
248  break;
249  default:
250  zFactAzi = 1.0e-6; // undefined, only 3 horns
251  }
252  const double factCE = std::exp(-1.0*std::abs(zFactAzi)) * (fCurrentEqualizerQuadAmpl*std::sin(2.0*phi)
253  + fCurrentEqualizerOctAmpl*std::sin(4.0*phi));
254  magBField *= (1.0 + factCE);
255 // std::cerr << " ... Current Equalizer factor " << factCE << " Z " << zFactAzi << std::endl;
256  }
257 
258 
259  double radIC=0.;
260  double radOC=0.;
261  this->fillHornPolygonRadii(zGlobal, &radIC, &radOC);
262  if (std::abs(radIC) > 1.0e6) {
263  fEffectiveInnerRad = -1.0;
264  fEffectiveOuterRad = -1.0;
265 // std::cerr << " No effective radius at z " << zGlobal << std::endl;
266  return;
267  } else {
268 // std::cerr << " At zGlobal " << zGlobal << " zLocal " << ptTrans[2] << " radIC "
269 // << radIC << " radOC " << radOC << std::endl;
270  }
271  fEffectiveInnerRad = radIC;
272  fEffectiveOuterRad = radOC;
274  // Study of systematic effects. Define an effective radIC wich is large than the physics radIC.
275  // We assume here that the finite skin depth matter, and the current density is not
276  // uniform. Simply increase the radIC
277  if (r < radIC && (fDeltaEccentricityIO < 1.0e-20)) {
278  return; // zero field region (Amps law).
279  }
280  // We assume that the eccentricity is along the X axis. The resulting dipole will then be vertical. It does not depend on r
281  // ( the variable magField goes like 1/r )
282  // Ref: NuMI note # 710, December 14 2000.
283  //
284  double dipoleAtInnerInner = 0.;
285  if (std::abs(fDeltaEccentricityIO) > 1.0e-20) {
286  // July 22 2017: flip this sign.
287  dipoleAtInnerInner = (-1.0)*magBField*r*fDeltaEccentricityIO/(radOC*radOC - radIC*radIC);
288  if (r < radIC && (std::abs(fDeltaEccentricityIO) > 1.0e-20)) {
289  Bfield[0] = 0.;
290  Bfield[1] = dipoleAtInnerInner; // Is this realy indepedent of phi? Or an approximation
291  // We skip the eventual additional complexity of the mis-aligned horn..
292  return;
293  }
294  } else {
295  if (r < radIC) return;
296  }
297 // const double deltaRIC = radOC - radIC;
298 // Version from Dec 18-19 2013.
299 // radIC += deltaRIC*std::min(0.99, fSkinDepthCorrInnerRad);
300  //
301 // if ((r > radIC) && (r < radOC)) {
302 // const double surfCyl = radOC*radOC - radIC*radIC;
303 // const double deltaRSq = (r*r - radIC*radIC);
304 // magBField *= deltaRSq/surfCyl; // Assume uniform current density and apply Amps law.
305 // }
306 // Skin Depth effect, current disctribution in the conductor itself,
307 // and Version from Zarko's thesis. ( (MINOS Document 5694-v1) )
308 //
309  double magFieldPhi = magBField;
310  double magFieldR = 0.;
311 
312  double factRInAlum = 1.0;
313  if ((r > radIC) && (r < radOC)) {
314  const double surfCyl = radOC*radOC - radIC*radIC;
315  const double deltaRSq = (r*r - radIC*radIC);
316  factRInAlum = deltaRSq/surfCyl; // Inside the alumimum
317  fEffectiveSkinDepthFact = factRInAlum;
318  if (fSkinDepthInnerRad > 10.*CLHEP::mm) { // default assume very large skin depth, assume constant current
319  // current density .
320  magFieldPhi *= factRInAlum; // Assume uniform current density and apply Amps law.
321  } else { // Realistic skin depth.
322  magFieldPhi *= factRInAlum*getNormCurrDensityInnerC((r-radIC), (radOC-radIC))
323  /getNormCurrDensityInnerC((radOC-radIC), (radOC-radIC));
324  }
325  }
326 // Sin and cos factor bphi -> bx, by
327 // std::cerr << " ....check r " << r << " magFieldPhi "
328 // << magFieldPhi << " magBField " << magBField << std::endl;
329 //
330 // See informal document given to Alberto M and Laura F. regarding the solution of
331 // divergence equation, for the multipole expansion. Sept 29, 2016.
332 //
333  double r12Fact = 1.0;
334  if (std::abs(fDeltaEllipticityI) > 1.0e-20) {
335  // NuMi note 0710 and/or NuMI 0471
336  const double rDelta = sqrt((ptTrans[0] - fDeltaEccentricityIO)*(ptTrans[0] - fDeltaEccentricityIO) +
337  ptTrans[1]*ptTrans[1]);
340  double deltaMagFieldPhiEc = magBField * r12Fact * (fDeltaEccentricityIO / rDelta) * std::cos(phi);
341  double magFieldREc = magBField * r12Fact * (fDeltaEccentricityIO / rDelta) * std::sin(phi);
342  double deltaMagFieldPhiEl = magBField * r12Fact * fEffectiveInnerRad * (fDeltaEllipticityI /(r*r)) * std::cos(2.0*phi);
343  double magFieldREl = magBField * r12Fact * fEffectiveInnerRad * (fDeltaEllipticityI /(r * r)) * std::sin(2.0*phi);
344  // Reintroduce the bug, by setting
345 // factRInAlum = 1.;
346  magFieldPhi = factRInAlum*(magBField - deltaMagFieldPhiEl - deltaMagFieldPhiEc);
347  magFieldR = factRInAlum*(magFieldREl + magFieldREc);
348 // magFieldPhi = (magBField - deltaMagFieldPhiEl - deltaMagFieldPhiEc);
349 // magFieldR = (magFieldREl + magFieldREc);
350  // To be checked for ellipticity.
351  }
352  Bfield[0] = -magFieldPhi*ptTrans[1]/r + magFieldR*ptTrans[0]/r;
353  Bfield[1] = magFieldPhi*ptTrans[0]/r + magFieldR*ptTrans[1]/r;
354  //
355  // Analytical calculation, in cartesian coordinate, for the eccentricity.
356  //
357  if (std::abs(fDeltaEccentricityIO) > 1.0e-20) {
358  // Two Cartesian coordinate system, the first one, centered on Outer surface of the IC
359  // The second one, translated by delta, say to the left, and with critical radius radIn
360  const double ITot = magBField * r; // Up to a constant..
361  const double JTot = ITot/(radOC*radOC - radIC*radIC);
362  const double BField1Phi = (r < radOC) ? ( JTot * r) : (JTot * radOC*radOC/ r);
363  const double BField1X = -1.0*BField1Phi*std::sin(phi);
364  const double BField1Y = BField1Phi*std::cos(phi);
365  const double h1 = r * std::sin(phi);
366  const double l2 = fDeltaEccentricityIO + r*std::cos(phi);
367  const double r2 = std::sqrt(l2*l2 + h1*h1); // with respect to the displaced inner radius.
368  const double phi2 = std::atan2(h1, l2);
369  const double BField2Phi = (r2 < radIC) ? ( JTot * r2) : (JTot * radIC*radIC/ r2);
370  const double BField2X = -1.0*BField2Phi*std::sin(phi2);
371  const double BField2Y = BField2Phi*std::cos(phi2);
372  Bfield[0] = BField1X - BField2X;
373  Bfield[1] = BField1Y - BField2Y;
374  }
375 // std::cerr << " Bfield .. " << Bfield[0]/CLHEP::tesla << " / " << Bfield[1]/CLHEP::tesla
376 // << " r " << r << " radIC " << radIC << " radIC-eff " << fEffectiveInnerRad << std::endl;
377  if (doCurrentEqualizerCorr) {
378  const double kOfPhiEQ =
379  (+1.0) * ( 2.0*fCurrentEqualizerQuadAmpl*std::cos(2.0*phi) +
380  4.0*fCurrentEqualizerOctAmpl*std::cos(4.0*phi)) * std::log(r/radIC);
381  // See 2-page solution
382  // The sign has been flipped, because the sign of magBField has been flipped
383  //for the main component..
384  // Based on the arrow plot, and the divergence test.
385  Bfield[0] += (magFieldPhi*ptTrans[0]/r) * kOfPhiEQ;
386  Bfield[1] += (magFieldPhi*ptTrans[1]/r) * kOfPhiEQ;
387  // We don't bother iwth the dadial componenent, too small..
388  }
389 //
390 // Important correction.. May 27 2017... ( a bug from a long time ago !?)
391 // One needs to rotate the field as well.
392  if (fHornIsMisaligned) {
393  std::vector<double> bFieldLocal(3);
394  for(size_t k=0; k != 3; k++) { bFieldLocal[k] = Bfield[k]; Bfield[k] = 0.; }
395  for (size_t k1=0; k1 !=3; k1++) {
396  for (size_t k2=0; k2 !=3; k2++) Bfield[k1] += fRotMatrixHornContainer[k1][k2]*bFieldLocal[k2];
397  }
398 // std::cerr << " Misaligned Horn" << hornNumber+1 << ", rotation of the field ... " << std::endl;
399 // for(size_t k=0; k != 3; k++) std::cerr << " Component " << k
400 // << " local " << bFieldLocal[k] << " global " << Bfield[k] << std::endl;
401  }
402 }
404 // this->TestEccentricityBerkeley();
405  fDebugIsOn = true;
406  std::ostringstream fNameStr; fNameStr << "./FieldMapHornTmpV3" << (hornNumber +1);
407  if (std::abs(fDeltaEccentricityIO) > 1.0e-20) fNameStr << "Ecc.txt";
408  else fNameStr << ".txt";
409  std::string fName(fNameStr.str());
410  std::ofstream fOut(fName.c_str());
411 // const double zStart = fZShiftDrawingCoordinate;
412 // const double zEnd = zStart + fEffectiveLength + 1000. ;
413 // Study Horn A only.
414  const double zStart = 2219.;
415 // const double zEnd = 2200.0000001;
416  const double zEnd = 2219.0000001;
417  std::cerr << "LBNFMagneticFieldPolyconeHorn::dumpField .. fZShiftDrawingCoordinate "
418  << fZShiftDrawingCoordinate << " length " << fEffectiveLength
419  << " Z start/end " << zStart << "/" << zEnd << std::endl;
420 // if ((std::abs(fDeltaEllipticityI) < 1.0e-20) && (std::abs(fDeltaEccentricityIO) < 1.0e-20) ) {
421 // Splitting this method in two parts was a bad idea, as it prevented us to make maps with the exactly the same grid,
422 // but different option.. I'll leave the code there for now, in case we want to generate simple maps, but disable it..
423  if (std::abs(zEnd) < -1.e10) { // to ensure the same map.
424  fOut << " z zd r bphi br " << std::endl;
425  double rMax = fOuterRadius + 5.0*CLHEP::mm;
426 // if (amHorn1) std::cerr << " Horn1, Dumpfield, r Max = " << rMax << std::endl;
427 // else std::cerr << " Horn2, Dumpfield, r Max = " << rMax << std::endl;
428  const int numZStep = 200;
429  const int numRStep= 200;
430  const double zStep = (zEnd-zStart)/numZStep;
431  const double rStep = rMax/numRStep;
432  double point[3];
433  for (int iZ=0; iZ !=numZStep; iZ++) {
434  double z = zStart + iZ*zStep;
435  point[2] = z;
436  const double zLocD = point[2];
437  double radIC = 0.; double radOC = 0.;
438  this->fillHornPolygonRadii(zLocD, &radIC, &radOC);
439  double r = radIC - 0.25*CLHEP::mm;
440  // inside the conductor...
441  while (r < rMax/2.) {
442  const double phi = 2.0*M_PI*G4RandFlat::shoot();
443  point[0] = r*std::cos(phi);
444  point[1] = r*std::sin(phi);
445  double bf[3];
446  this->GetFieldValue(point, &bf[0]);
447  const double bphi = bf[0]*std::sin(phi) - bf[1]*std::cos(phi);
448  const double br = bf[0]*std::cos(phi) + bf[1]*std::sin(phi);
449  fOut << " " << z << " " << zLocD << " " << r << " "
450  << bphi/CLHEP::tesla << " " << br/CLHEP::tesla << std::endl;
451  if (r < (radIC + 5.0*CLHEP::mm)) r += 0.1*CLHEP::mm;
452  else r += rStep;
453  }
454  }
455  } else {
456  fOut << " z zd x y r bphi br bx by " << std::endl;
457 // if (amHorn1) std::cerr << " Horn1, Dumpfield, r Max = " << rMax << std::endl;
458 // else std::cerr << " Horn2, Dumpfield, r Max = " << rMax << std::endl;
459 // const int numZStep = 200;
460  const int numZStep = 1;
461  const int numRStep= 200;
462  const int numPhiStep= 100;
463  const double zStep = (zEnd-zStart)/numZStep;
464  double point[3];
465  const double rInit = 20.;
466 // const double rMax = radIC + 10.0*CLHEP::mm;
467  const double rMax = 50.0*CLHEP::mm;
468 // const double rMax = radIC - 0.1*CLHEP::mm;
469  const double rStep = (rMax - rInit)/numRStep;
470  for (int iZ=0; iZ !=numZStep; iZ++) {
471  double z = zStart + iZ*zStep;
472  point[2] = z;
473  const double zLocD = point[2];
474  double radIC = 0.; double radOC = 0.;
475  this->fillHornPolygonRadii(zLocD, &radIC, &radOC);
476  // inside the conductor...
477  double r = rInit;
478  while (r < rMax) {
479  for (size_t kPhi=0; kPhi!= (numPhiStep); kPhi++) {
480  const double phi = (2.0*M_PI*kPhi)/numPhiStep;
481  point[0] = r*std::cos(phi);
482  point[1] = r*std::sin(phi);
483  double bf[3];
484  this->GetFieldValue(point, &bf[0]);
485  const double bphi = bf[0]*std::sin(phi) - bf[1]*std::cos(phi);
486  const double br = bf[0]*std::cos(phi) + bf[1]*std::sin(phi);
487  fOut << " " << z << " " << zLocD << " " << point[0] << " " << point[1] << " " << r << " "
488  << bphi/CLHEP::tesla << " " << br/CLHEP::tesla
489  << " " << bf[0]/CLHEP::tesla << " " << bf[1]/CLHEP::tesla << std::endl;
490  }
491  r += rStep;
492  }
493  }
494  }
495  std::cerr << " And quit for now... " << std::endl; exit(2);
496  fOut.close();
497  //
498  // Provide the arrow plot to visualize the correction to the Current equalizer section..
499  //
500  std::ostringstream fNameAStr;
501  fNameAStr << "./FieldMapHorn" << (hornNumber +1)
502  << "_ArrowPlot_" << fNumZPtsForCE << "_" << fNumRPtsForCE << "_" << fNumPhiPtsForCE << "_V2.txt";
503  std::string fNameA(fNameAStr.str());
504  fOut.open(fNameA.c_str());
505  fOut << " x y r bx by " << std::endl;
506  const int numR = 20;
507  const int numPhi = 10.;
508  const double stepPhi = (M_PI/2.) / numPhi;
509  G4ThreeVector dir;
510  double pos[3];
511  size_t iPtZSel = fRadsInnerC.size()/2;
512  pos[2] = fZDCBegin[iPtZSel];
513  const double zLoc = pos[2];
514  double radICAr=0.; double radOCAr=0.;
515  this->fillHornPolygonRadii(zLoc, &radICAr, &radOCAr);
516  const double rStep = (fOuterRadius - radOCAr)/numR;
517 
518  double bField[3];
519  for (int iR = 0; iR != numR; iR++) {
520  double r = radOCAr + iR*rStep;
521  if (iR == 0) r = radOCAr + 5.0*CLHEP::mm;
522  else r = radOCAr + 2.0*CLHEP::mm + iR*rStep; // for graphical clarity ..
523  for (int iPhi = 0; iPhi != numPhi; iPhi++) {
524  const double phi = 0.3333*stepPhi + iPhi*stepPhi;
525  pos[0] = r * std::cos(phi); pos[1] = r * std::sin(phi);
526  this->GetFieldValue(pos, bField);
527  fOut << " " << pos[0] << " " << pos[1] << " " << r << " "
528  << bField[0]/CLHEP::tesla << " " << bField[1]/CLHEP::tesla << std::endl;
529  }
530  }
531  fOut.close();
532  //
533  // Special map to debug the CurrentEqualizer induced azimuthal variation in the current.
534 
535  if (fCurrentEqualizerQuadAmpl > 1.) {
536  std::ostringstream fNameBStr; fNameBStr << "./FieldMapHornCEQ_" << (hornNumber +1) << "_Debug.txt";
537  std::string fNameB(fNameBStr.str());
538  fOut.open(fNameB.c_str());
539  fOut << " x y z bx by bNorm br bphi" << std::endl;
540  const int numRCE = 50;
541  const int numPhiCE = 100.;
542  const double stepPhiCE = (2.0*M_PI) / numPhiCE;
543  double posCE[3];
545  double radIC; double radOC;
546  this->fillHornPolygonRadii(zGrid, &radIC, &radOC);
547  double bFieldCE[3];
548  for (int iZCE=0; iZCE != 10; iZCE++) {
549  posCE[2] = zGrid + (iZCE-1)*fField3DMapCurrentEqualizerZStep/5.;
550  const double rStepCE = (fOuterRadius - radOC- 2.5*CLHEP::mm)/numRCE;
551  for (int iR = 0; iR != numRCE; iR++) {
552  const double r = radOC -1.*CLHEP::mm + iR*rStepCE;
553  for (int iPhi = 0; iPhi != numPhiCE; iPhi++) {
554  const double phi = iPhi*stepPhiCE;
555  posCE[0] = r * std::cos(phi); posCE[1] = r * std::sin(phi);
556 // if ((iR == 15) && (iPhi > 20) && (iPhi < 25)) fDebugIsOn = true;
557 // if ((r < 225.) && (iPhi > 20) && (iPhi < 25)) fDebugIsOn = true;
558  if ((std::abs(r - 205.997) < 1.) && (std::abs(phi) < 1.0)) fDebugIsOn = true;
559  else fDebugIsOn = false;
560  this->GetFieldValue(posCE, bFieldCE);
561  const double bNorm = sqrt(bFieldCE[0]*bFieldCE[0] + bFieldCE[1]*bFieldCE[1]);
562  const double bR = bFieldCE[0]*std::cos(phi) + bFieldCE[1]*std::sin(phi);
563  const double bPhi = bFieldCE[1]*std::cos(phi) - bFieldCE[0]*std::sin(phi);
564 
565  fOut << " " << posCE[0] << " " << posCE[1] << " " << posCE[2] << " "
566  << bFieldCE[0]/CLHEP::tesla << " " << bFieldCE[1]/CLHEP::tesla << " " << bNorm/CLHEP::tesla
567  << " " << bR/CLHEP::tesla << " " << bPhi/CLHEP::tesla << std::endl;
568  }
569  }
570  }
571  }
572  fOut.close();
573 }
574 
575 void LBNFMagneticFieldPolyconeHorn::fillTrajectories(const double Point[3], double bx, double by) const {
576  if (!fOutTraj.is_open()) return;
577  LBNERunManager* pRunManager = dynamic_cast<LBNERunManager*>(G4RunManager::GetRunManager());
578  fOutTraj << " " << pRunManager->GetCurrentEvent()->GetEventID();
579  for (size_t k=0; k!= 3; k++) fOutTraj << " " << Point[k];
580  fOutTraj << " " << bx/CLHEP::tesla << " " << " " << by/CLHEP::tesla << std::endl;
581  // we flush, the destructor never called..
582  fOutTraj.flush();
583 }
584 
586 //
587 // Test that it satisfy Maxwell equation, div B = 0
588 //
589 // Since we compute in polar coordinate system, do it Cartesian..
590 //
591  G4ThreeVector dir;
592  double pos[3];
593  size_t iPtZSel = fRadsInnerC.size()/2;
594  pos[2] = fZDCBegin[iPtZSel];
595  double radIC=0.;
596  double radOC=0.;
597  radOC += 1.5*CLHEP::mm;
598  this->fillHornPolygonRadii(pos[2], &radIC, &radOC);
599  std::string fNameOut;
600  switch (opt) {
601  case 0:
602  dir = G4ThreeVector(std::sqrt(1.0-0.01), 0.1, 0.);
603  pos[0] = 1.1*radOC; pos[1] = 0.1;
604  fNameOut=std::string("./LBNFMagneticFieldPolyconeHorn_TestDivergence_X_v1.txt");
605  break;
606  case 1:
607  dir = G4ThreeVector(0.1, std::sqrt(1.0-0.01), 0.);
608  pos[1] = 1.1*radOC; pos[0] = 0.1;
609  fNameOut=std::string("./LBNFMagneticFieldPolyconeHorn_TestDivergence_Y_v1.txt");
610  break;
611  case 2:
612  dir = G4ThreeVector(0.480729, sqrt(1.0 - (0.480729*0.480729)), 0.);
613  pos[0] = 1.1*radIC/std::sqrt(2.); pos[1] = pos[0];
614  fNameOut=std::string("./LBNFMagneticFieldPolyconeHorn_TestDivergence_U_v1.txt");
615  break;
616  default:
617  std::cerr << "LBNFMagneticFieldPolyconeHorn::TestDivergence Valid switches so far are 0, 1 or 2" << std::endl;
618  exit(1);
619  }
620  std::ofstream fOut(fNameOut.c_str());
621  fOut << " x y r bx by b dbdx dbdy obnablab " << std::endl;
622  const double step = 0.002*CLHEP::mm;
623  double deltaMaxCart = 0.;
624  const double range = fOuterRadius - fRadsOuterC[iPtZSel]- 2.5*CLHEP::mm;
625  const int numPts = static_cast<int> (range/step);
626  std::cerr << " LBNFMagneticFieldPolyconeHorn::TestDivergence, number of pts "
627  << numPts << " Z location for scan " << pos[2] << " radii "
628  << radIC << " / " << fOuterRadius << std::endl;
629  double bFieldPrev[3]; double bField[3]; double posPrevious[3];
630  for (size_t kk=0; kk != 3; kk++) { posPrevious[kk] = pos[kk]; bFieldPrev[kk] = 0.; }
631  double dbVal[3]; dbVal[2] = 0.; // assume Bz = 0.
632  double bdlIntegral = 0.;
633  for (int iStep = 0; iStep != numPts; iStep++) {
634  this->GetFieldValue(pos, bField);
635  const double bNorm = std::sqrt( bField[0]*bField[0] + bField[1]*bField[1]);
636 
637  if (bNorm < 1.0e-10) {
638  for (size_t k=0; k!=3; k++) {
639  bFieldPrev[k] = 0.;
640  posPrevious[k] = pos[k];
641  pos[k] += step*dir[k];
642  }
643  continue;
644  }
645  bdlIntegral += bField[0]*step*dir[1] - bField[1]*step*dir[0];
646  const double phi = std::atan2(pos[1], pos[0]);
647  if (iStep != 0) {
648  dbVal[0] = std::cos(phi) * (bField[0] - bFieldPrev[0])/(pos[0] - posPrevious[0]);
649  dbVal[1] = std::sin(phi) * (bField[1] - bFieldPrev[1])/(pos[1] - posPrevious[1]);
650  const double dd = (1.0/bNorm)*(dbVal[0] + dbVal[1]);
651  fOut << " " << pos[0] << " " << pos[1] << " " << std::sqrt(pos[0]*pos[0] + pos[1]*pos[1])
652  << " " << bField[0]/CLHEP::tesla << " " << bField[1]/CLHEP::tesla
653  << " " << bNorm/CLHEP::tesla << " "
654  << dbVal[0]/bNorm << " " << dbVal[1]/bNorm << " " << dd << std::endl;
655  deltaMaxCart = std::max(std::abs(dd), deltaMaxCart);
656  }
657  for (size_t k=0; k!=3; k++) {
658  bFieldPrev[k] = bField[k];
659  posPrevious[k] = pos[k];
660  pos[k] += step*dir[k];
661  }
662  }
663  std::cerr << " LBNFMagneticFieldPolyconeHorn::TestDivergence, final max deviation (rel) "
664  << deltaMaxCart << " Integral bdl " << bdlIntegral/(CLHEP::tesla*CLHEP::meter) << std::endl;
665  fOut.close();
666 // std::cerr << " And quit for now " << std::endl; exit(2);
667 
668 }
670  const double Point[3], double *Bfield) const {
671 
672  if (fDebugIsOn) std::cerr << " LBNFMagneticFieldPolyconeHorn::getFieldFrom3DMapCurrentEqualizer xyz "
673  << Point[0] << " / " << Point[1] << " / " << Point[2] << std::endl;
674  for (int k=0; k !=3; k++) Bfield[k] = 0.;
675  if (fField3DMapCurrentEqualizer.size() == 0) return; // should not happen
676  if (Point[2] < fField3DMapCurrentEqualizerZMin) return;
677  const unsigned int iZ1 =
678  static_cast<unsigned int>(std::floor((Point[2] - fField3DMapCurrentEqualizerZMin)/fField3DMapCurrentEqualizerZStep));
679  if( iZ1 >= fNumZPtsForCE) return;
680  const unsigned int iZ2 = (iZ1 == (fNumZPtsForCE-1)) ? iZ1 : (iZ1 + 1);
681  if(fDebugIsOn) std::cerr << " ..... Z " << Point[2] << " indices " << iZ1 << " / " << iZ2 << std::endl;
682  double phi = std::atan2(Point[1], Point[0]);
683  if (phi < 0.) phi += 2.0*M_PI;
684  const unsigned int iQuadrant = (unsigned int) std::floor(2.0*phi/M_PI);
685  const double phiFirst = phi - iQuadrant*M_PI/2.;
686  const unsigned int iPhi1 =
687  static_cast<unsigned int>(phiFirst/fField3DMapCurrentEqualizerPhiStep);
688  const unsigned int iPhi2 = (iPhi1 == (fNumPhiPtsForCE-1)) ? 0 : (iPhi1 + 1);
689 
690  if (fDebugIsOn) std::cerr << " ..... phi " << phi << " phiFirst " << phiFirst
691  << " indices " << iPhi1 << " / " << iPhi2 << std::endl;
692  const double rSqRequested = Point[0]*Point[0] + Point[1]*Point[1];
693  const double rSqZ1 = rSqRequested - fField3DMapCurrentEqualizerRadSqAtZ[iZ1];
694  const double rSqZ2 = rSqRequested - fField3DMapCurrentEqualizerRadSqAtZ[iZ2];
695  if ((rSqZ1 < 0.) && (rSqZ2 < 0.)) return;
696  double radOCAtZ = 0.;
697  double radICAtZ = 0.; // irrelevant if no OC crossing betwen Z1 and Z2
698  if ((rSqZ1 < 0.) || (rSqZ2 < 0.)) {
699  this->fillHornPolygonRadii(Point[2], &radICAtZ, &radOCAtZ);
700  if (rSqRequested < (radOCAtZ*radOCAtZ)) return;
701  }
702  const unsigned int iR1Z1 = (rSqZ1 < 0.) ? 0 : std::floor(rSqZ1 /fField3DMapCurrentEqualizerRadSqRStepAtZ[iZ1]);
703  const unsigned int iR2Z1 = (rSqZ1 < 0.) ? 0 : ((iR1Z1 == (fNumRPtsForCE-1)) ? iR1Z1 : (iR1Z1 + 1));
704  const unsigned int iR1Z2 = (rSqZ2 < 0.) ? 0 : std::floor(rSqZ2 /fField3DMapCurrentEqualizerRadSqRStepAtZ[iZ2]);
705  const unsigned int iR2Z2 = (rSqZ2 < 0.) ? 0 : ((iR1Z2 == (fNumRPtsForCE-1)) ? iR1Z2 : (iR1Z2 + 1));
706  if ((iR1Z1 >= fNumRPtsForCE) || (iR1Z2 >= fNumRPtsForCE)) return;
707  // bilinear interposlation on the phiXRsq plane, the linear interpolation on Z
708  if (fDebugIsOn) std::cerr << " ..... RsQ, Z1 " << rSqZ1 << " at Z2 " << rSqZ2 << " indices "
709  << iR1Z1 << " / " << iR2Z1 << " / " << iR1Z2 << " / " << iR2Z2 << std::endl;
710 
711  const unsigned int ii1 = fNumZPtsForCE*(fNumRPtsForCE*iPhi1 + iR1Z1) + iZ1;
712  const unsigned int ii2 = fNumZPtsForCE*(fNumRPtsForCE*iPhi1 + iR2Z1) + iZ1;
713  const unsigned int ii3 = fNumZPtsForCE*(fNumRPtsForCE*iPhi2 + iR2Z1) + iZ1;
714  const unsigned int ii4 = fNumZPtsForCE*(fNumRPtsForCE*iPhi2 + iR1Z1) + iZ1;
715  const double ui = (iPhi2 == 0) ? (phiFirst - (fNumPhiPtsForCE - 1)*
718 
719  if (fDebugIsOn) std::cerr << " ..... ii indices " << ii1 << " / " << ii2 << " / " << ii3 << " / " << ii4
720  << " ui " << ui << std::endl;
721  double bxIz1 = 0.; double byIz1 = 0.;
722  // Same at the point iZ2..
723  //
724  const unsigned int jj1 = fNumZPtsForCE*(fNumRPtsForCE*iPhi1 + iR1Z2) + iZ2;
725  const unsigned int jj2 = fNumZPtsForCE*(fNumRPtsForCE*iPhi1 + iR2Z2) + iZ2;
726  const unsigned int jj3 = fNumZPtsForCE*(fNumRPtsForCE*iPhi2 + iR2Z2) + iZ2;
727  const unsigned int jj4 = fNumZPtsForCE*(fNumRPtsForCE*iPhi2 + iR1Z2) + iZ2;
728  double bxIz2 = 0.; double byIz2 = 0.;
729  if (((iR2Z1 == iR1Z1) || (iR2Z2 == iR1Z2)) && (iR1Z1 != 0) &&
730  (iR1Z2 != 0) && (iR2Z1 != 0) && (iR2Z2 != 0) ) { // only do the interpolation in phi . Far away from the IC,
731  // does not matter which interpolation table section we use.. Field too small.
732  std::map<unsigned int, std::pair<float, float> >::const_iterator itm1 =
733  fField3DMapCurrentEqualizer.find(ii1);
734  std::map<unsigned int, std::pair<float, float> >::const_iterator itm4 =
735  fField3DMapCurrentEqualizer.find(ii4);
736  const double bix1 = static_cast<double>(itm1->second.first);
737  const double biy1 = static_cast<double>(itm1->second.second);
738  const double bix4 = static_cast<double>(itm4->second.first);
739  const double biy4 = static_cast<double>(itm4->second.second);
740  bxIz1 = (1. - ui)*bix1 + ui*bix4;
741  byIz1 = (1. - ui)*biy1 + ui*biy4;
742  if (iZ1 == iZ2) {
743  Bfield[0] = bxIz1;
744  Bfield[1] = byIz1;
745  } else {
746  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm1 =
747  fField3DMapCurrentEqualizer.find(jj1);
748  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm4 =
749  fField3DMapCurrentEqualizer.find(jj4);
750  const double bjx1 = static_cast<double>(jtm1->second.first);
751  const double bjy1 = static_cast<double>(jtm1->second.second);
752  const double bjx4 = static_cast<double>(jtm4->second.first);
753  const double bjy4 = static_cast<double>(jtm4->second.second);
754  bxIz2 = (1. - ui)*bjx1 + ui*bjx4;
755  byIz2 = (1. - ui)*bjy1 + ui*bjy4;
756  const double v =
759  Bfield[0] = (1.0 - v)*bxIz1 + v*bxIz2;
760  Bfield[1] = (1.0 - v)*byIz1 + v*byIz2;
761  }
762  if (fDebugIsOn) std::cerr << " ....Phi/Z interpolation only. "
763  << " Bfield " << Bfield[0] << " / " << Bfield[1] << std::endl;
764  } else {
765  if (rSqZ1 < 0.) {
766  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm1 =
767  fField3DMapCurrentEqualizer.find(jj1);
768  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm2 =
769  fField3DMapCurrentEqualizer.find(jj2);
770  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm3 =
771  fField3DMapCurrentEqualizer.find(jj3);
772  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm4 =
773  fField3DMapCurrentEqualizer.find(jj4);
774  const double bjx1 = static_cast<double>(jtm1->second.first);
775  const double bjy1 = static_cast<double>(jtm1->second.second);
776  const double bjx2 = static_cast<double>(jtm2->second.first);
777  const double bjy2 = static_cast<double>(jtm2->second.second);
778  const double bjx3 = static_cast<double>(jtm3->second.first);
779  const double bjy3 = static_cast<double>(jtm3->second.second);
780  const double bjx4 = static_cast<double>(jtm4->second.first);
781  const double bjy4 = static_cast<double>(jtm4->second.second);
782  const double tj =
783  std::max(std::abs((rSqZ2 - radOCAtZ*radOCAtZ)/fField3DMapCurrentEqualizerRadSqRStepAtZ[iZ2]), 1.); // Approximate!.
784  bxIz2 = (1. - ui)*(1.0 - tj)*bjx1 + (1.0 - ui)*tj*bjx2 + ui*tj*bjx3 + (1.0 - tj)*ui*bjx4 ;
785  byIz2 = (1. - ui)*(1.0 - tj)*bjy1 + (1.0 - ui)*tj*bjy2 + ui*tj*bjy3 + (1.0 - tj)*ui*bjy4 ;
786  if (fDebugIsOn) {
787  std::cerr << " tj " << tj << " bjxs " << bjx1 << " / " << bjx2 << " / " << bjx3 << " / " << bjx4 << std::endl;
788  std::cerr << " bjys " << bjy1 << " / " << bjy2 << " / " << bjy3 << " / " << bjy4 << std::endl;
789  std::cerr << " bxIz2 " << bxIz2 << " byIz2 " << byIz2 << std::endl;
790  }
791  const double v =
794  Bfield[0] = v*bxIz2;
795  Bfield[1] = v*byIz2;
796  if (fDebugIsOn) std::cerr << " .... v " << v << " Bfield " << Bfield[0] << " / " << Bfield[1] << std::endl;
797  } else if (rSqZ2 < 0.) {
798  std::map<unsigned int, std::pair<float, float> >::const_iterator itm1 =
799  fField3DMapCurrentEqualizer.find(ii1);
800  std::map<unsigned int, std::pair<float, float> >::const_iterator itm2 =
801  fField3DMapCurrentEqualizer.find(ii2);
802  std::map<unsigned int, std::pair<float, float> >::const_iterator itm3 =
803  fField3DMapCurrentEqualizer.find(ii3);
804  std::map<unsigned int, std::pair<float, float> >::const_iterator itm4 =
805  fField3DMapCurrentEqualizer.find(ii4);
806  const double bix1 = static_cast<double>(itm1->second.first);
807  const double biy1 = static_cast<double>(itm1->second.second);
808  const double bix2 = static_cast<double>(itm2->second.first);
809  const double biy2 = static_cast<double>(itm2->second.second);
810  const double bix3 = static_cast<double>(itm3->second.first);
811  const double biy3 = static_cast<double>(itm3->second.second);
812  const double bix4 = static_cast<double>(itm4->second.first);
813  const double biy4 = static_cast<double>(itm4->second.second);
814  const double ti =
815  std::max(std::abs((rSqZ1 - radOCAtZ*radOCAtZ)/fField3DMapCurrentEqualizerRadSqRStepAtZ[iZ1]) , 1.);
816  bxIz1 = (1. - ui)*(1.0 - ti)*bix1 + (1.0 - ui)*ti*bix2 + ui*ti*bix3 + (1.0 - ti)*ui*bix4 ;
817  byIz1 = (1. - ui)*(1.0 - ti)*biy1 + (1.0 - ui)*ti*biy2 + ui*ti*biy3 + (1.0 - ti)*ui*biy4 ;
818  if (fDebugIsOn) {
819  std::cerr << " ui " << ui << " ti " << ti << std::endl;
820  std::cerr << " bixs " << bix1 << " / " << bix2 << " / " << bix3 << " / " << bix4 << std::endl;
821  std::cerr << " biys " << biy1 << " / " << biy2 << " / " << biy3 << " / " << biy4 << std::endl;
822  std::cerr << " bxIz1 " << bxIz1 << " byIz1 " << byIz1 << std::endl;
823  }
824  const double v =
827  Bfield[0] = (1.0 - v)*bxIz1;
828  Bfield[1] = (1.0 - v)*byIz1;
829  if (fDebugIsOn) std::cerr << " .... v " << v << " Bfield " << Bfield[0] << " / " << Bfield[1] << std::endl;
830 
831  } else {
832  std::map<unsigned int, std::pair<float, float> >::const_iterator itm1 =
833  fField3DMapCurrentEqualizer.find(ii1);
834  std::map<unsigned int, std::pair<float, float> >::const_iterator itm2 =
835  fField3DMapCurrentEqualizer.find(ii2);
836  std::map<unsigned int, std::pair<float, float> >::const_iterator itm3 =
837  fField3DMapCurrentEqualizer.find(ii3);
838  std::map<unsigned int, std::pair<float, float> >::const_iterator itm4 =
839  fField3DMapCurrentEqualizer.find(ii4);
840  const double bix1 = static_cast<double>(itm1->second.first);
841  const double biy1 = static_cast<double>(itm1->second.second);
842  const double bix2 = static_cast<double>(itm2->second.first);
843  const double biy2 = static_cast<double>(itm2->second.second);
844  const double bix3 = static_cast<double>(itm3->second.first);
845  const double biy3 = static_cast<double>(itm3->second.second);
846  const double bix4 = static_cast<double>(itm4->second.first);
847  const double biy4 = static_cast<double>(itm4->second.second);
848  const double ti =
850  bxIz1 = (1. - ui)*(1.0 - ti)*bix1 + (1.0 - ui)*ti*bix2 + ui*ti*bix3 + (1.0 - ti)*ui*bix4 ;
851  byIz1 = (1. - ui)*(1.0 - ti)*biy1 + (1.0 - ui)*ti*biy2 + ui*ti*biy3 + (1.0 - ti)*ui*biy4 ;
852  if (fDebugIsOn) {
853  std::cerr << " ui " << ui << " ti " << ti << std::endl;
854  std::cerr << " bixs " << bix1 << " / " << bix2 << " / " << bix3 << " / " << bix4 << std::endl;
855  std::cerr << " biys " << biy1 << " / " << biy2 << " / " << biy3 << " / " << biy4 << std::endl;
856  std::cerr << " bxIz1 " << bxIz1 << " byIz1 " << byIz1 << std::endl;
857  }
858  if (iZ1 == iZ2) {
859  Bfield[0] = bxIz1;
860  Bfield[1] = byIz1;
861  } else {
862  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm1 =
863  fField3DMapCurrentEqualizer.find(jj1);
864  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm2 =
865  fField3DMapCurrentEqualizer.find(jj2);
866  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm3 =
867  fField3DMapCurrentEqualizer.find(jj3);
868  std::map<unsigned int, std::pair<float, float> >::const_iterator jtm4 =
869  fField3DMapCurrentEqualizer.find(jj4);
870  const double bjx1 = static_cast<double>(jtm1->second.first);
871  const double bjy1 = static_cast<double>(jtm1->second.second);
872  const double bjx2 = static_cast<double>(jtm2->second.first);
873  const double bjy2 = static_cast<double>(jtm2->second.second);
874  const double bjx3 = static_cast<double>(jtm3->second.first);
875  const double bjy3 = static_cast<double>(jtm3->second.second);
876  const double bjx4 = static_cast<double>(jtm4->second.first);
877  const double bjy4 = static_cast<double>(jtm4->second.second);
878  const double tj =
880  bxIz2 = (1. - ui)*(1.0 - tj)*bjx1 + (1.0 - ui)*tj*bjx2 + ui*tj*bjx3 + (1.0 - tj)*ui*bjx4 ;
881  byIz2 = (1. - ui)*(1.0 - tj)*bjy1 + (1.0 - ui)*tj*bjy2 + ui*tj*bjy3 + (1.0 - tj)*ui*bjy4 ;
882  if (fDebugIsOn) {
883  std::cerr << " tj " << tj << " bjxs " << bjx1 << " / " << bjx2 << " / " << bjx3 << " / " << bjx4 << std::endl;
884  std::cerr << " bjys " << bjy1 << " / " << bjy2 << " / " << bjy3 << " / " << bjy4 << std::endl;
885  std::cerr << " bxIz2 " << bxIz2 << " byIz2 " << byIz2 << std::endl;
886  }
887  const double v =
890  Bfield[0] = (1.0 - v)*bxIz1 + v*bxIz2;
891  Bfield[1] = (1.0 - v)*byIz1 + v*byIz2;
892  if (fDebugIsOn) std::cerr << " .... v " << v << " Bfield " << Bfield[0] << " / " << Bfield[1] << std::endl;
893  }
894  } // both rSqZ1 and rSqZ2 positiv
895  }
896  if (iQuadrant == 0) return;
897  double bfQ[2]; bfQ[0] = Bfield[0]; bfQ[1] = Bfield[1];
898  switch (iQuadrant ) {
899  case 1:
900  Bfield[0] = -bfQ[1]; Bfield[1] = bfQ[0]; break;
901  case 2:
902  Bfield[0] = -bfQ[0]; Bfield[1] = -bfQ[1]; break;
903  case 3:
904  Bfield[0] = bfQ[1]; Bfield[1] = -bfQ[0]; break;
905  }
906  return;
907 }
909  //
910  if (fFileNameFieldMapForCE != std::string("?")) {
912  fDebugIsOn = false;
913 // this->dumpField();
914  return;
915  }
916 
917  if (fDebugIsOn) std::cerr << " LBNFMagneticFieldPolyconeHorn::fill3DMapCurrentEqualizer, starting .. " << std::endl;
918  const G4double current = fHornCurrent/CLHEP::ampere/1000.;
919  double magBField = current / (5./CLHEP::cm)/10*CLHEP::tesla; //B(kG)=i(kA)/[5*r(cm)], 1T=10kG
920  // The 1/r dependence is included in the map.
922  const double AQuad = fCurrentEqualizerQuadAmpl/100.; // temporary convention..
923  fNumZPtsForCE = 400; // a bit arbitrary...
924  fNumRPtsForCE = 200;
925  fNumPhiPtsForCE = 128;
928  fField3DMapCurrentEqualizerPhiStep = (M_PI/2.)/(fNumPhiPtsForCE-1); // Only one quadrant..
929  const int numWires = 500; // Really arbitrary..
930  const double phiWStep = 2.0*M_PI/numWires; // Over two pi, full sources.
931  for (unsigned int iZ = 0; iZ != fNumZPtsForCE; iZ++) {
932 // std::cerr << " At Z index " << iZ << std::endl;
934  double radIC=0.;
935  double radOC=0.;
936  this->fillHornPolygonRadii(z, &radIC, &radOC);
937  fField3DMapCurrentEqualizerRadSqAtZ.push_back(radOC*radOC);
938  double stepRadial = (fOuterRadius*fOuterRadius - radOC*radOC)/(fNumRPtsForCE-1);
939  fField3DMapCurrentEqualizerRadSqRStepAtZ.push_back(stepRadial);
940  double zFactAzi = 1.0e-6;
941  switch(hornNumber) {
942  case 0:
943  case 2:
944  zFactAzi = ((z - fZDCBegin[0]) > 0.) ? (z - fZDCBegin[0])/fCurrentEqualizerLongAbsLength : 1.0e-6;
945  break;
946  case 1:
947  zFactAzi = ((fZDCBegin[fZDCBegin.size() -1] - z) > 0.) ?
948  (fZDCBegin[fZDCBegin.size() -1] - z)/fCurrentEqualizerLongAbsLength : 1.0e-6;
949  break;
950  default:
951  zFactAzi = 1.0e-6; // undefined, only 3 horns
952  }
953  const double factCE = std::exp(-1.0*std::abs(zFactAzi));
954  if (fDebugIsOn) {
955  std::cerr << " At z = " << z << "radIC " << radIC << " radOC "
956  << radOC << " zFactAzi " << factCE << " " << magBField << std::endl;
957  std::cerr << " Size of the map " << fField3DMapCurrentEqualizer.size() << std::endl;
958  }
959  for (unsigned int iR=0; iR != fNumRPtsForCE; iR++) {
960  // Choose a quadratic spacing...
961  const double r = 1.0e-12 + sqrt(radOC*radOC + iR*stepRadial); // 1 microns to avoid numerics
962  for (unsigned int iPhi=0; iPhi != fNumPhiPtsForCE; iPhi++) {
963  const double phi = iPhi*fField3DMapCurrentEqualizerPhiStep;
964  const double xP = r * std::cos(phi);
965  const double yP = r * std::sin(phi);
966  double bX = 0.; double bY = 0.;
967  // Discretize the current density on the conductor. Normalize to the unform current density,
968  //
969  double sumCurrent = 0.;
970  for (int iW=0; iW != numWires; iW++) {
971  const double phiW = 1.0e-4 + phiWStep*(iW-1);
972  const double xW = radOC*std::cos(phiW);
973  const double yW = radOC*std::sin(phiW);
974  const double xWf = xP - xW;
975  const double yWf = yP - yW;
976  const double phiff = atan2(yWf, xWf);
977  const double radff = std::sqrt(xWf*xWf + yWf*yWf);
978  const double iDens = 1.0 + AQuad*factCE*std::abs(sin(2.0*phiW));
979  sumCurrent += iDens;
980  const double iDensByR = iDens/radff;
981  bX -= iDensByR*std::sin(phiff);
982  bY += iDensByR*std::cos(phiff);
983  if (std::isnan(bX) || std::isnan(bY) || std::isinf(bX) || std::isinf(bY)) {
984  std::cerr << " Numerics problem, xP " << xP << " yP " << yP << " iW "
985  << iW << " xWf " << xWf << " yWf " << yWf << std::endl;
986  std::cerr << " And quit here ! " << std::endl;
987  exit(2);
988  }
989  }
990  if (sumCurrent < 1.0e-10) { bX = 0.; bY = 0.; } else {
991  bX *=magBField/sumCurrent; bY *= magBField/sumCurrent;
992  }
993  const unsigned int ii = fNumZPtsForCE*(fNumRPtsForCE*iPhi + iR) + iZ;
994  fField3DMapCurrentEqualizer.emplace(ii,
995  std::pair<float, float>(static_cast<float>(bX), static_cast<float>(bY)));
996  } // On phi;
997  } // on R
998  } // on Z
999  /*
1000  std::cerr << " ... size of final Field map .. " << fField3DMapCurrentEqualizer.size() << std::endl;//
1001  std::map<unsigned int, std::pair<float, float> >::const_iterator itCheck0 =
1002  fField3DMapCurrentEqualizer.find(84029);
1003  std::cerr << " Check map at location 84029 " << itCheck0->second.first << " / " << itCheck0->second.second << std::endl;
1004  std::map<unsigned int, std::pair<float, float> >::const_iterator itCheck1 =
1005  fField3DMapCurrentEqualizer.find(84009);
1006  std::cerr << " Check map at location 84009 " << itCheck1->second.first << " / " << itCheck1->second.second << std::endl;
1007  std::map<unsigned int, std::pair<float, float> >::const_iterator itCheck2 =
1008  fField3DMapCurrentEqualizer.find(86009);
1009  std::cerr << " Check map at location 86009 " << itCheck2->second.first << " / " << itCheck2->second.second << std::endl;
1010 
1011  */
1012  fDebugIsOn = false;
1013 // this->dumpField();
1014  //
1015  // Write the map out ..
1016  //
1018 // std::cerr << " And quit !. " << std::endl; exit(2);
1019 
1020 }
1021 
1023 
1024  std::ostringstream fNameOutStrStr;
1025  fNameOutStrStr << "./FieldMapCEQ_Horn_" << (hornNumber +1)
1026  << "_LAbs_" << static_cast<int>(fCurrentEqualizerLongAbsLength)
1027  << "_Quad_" << static_cast<int>(fCurrentEqualizerQuadAmpl)
1028  << "_NZ_" << fNumZPtsForCE << "_NR_" << fNumRPtsForCE
1029  << "_NP_" << fNumPhiPtsForCE << ".dat";
1030  std::string fNameOutStr(fNameOutStrStr.str());
1031  std::ofstream fOutDat (fNameOutStr.c_str(), std::ios::out | std::ios::binary);
1032  const char *pTmp1 = (const char*) &fCurrentEqualizerLongAbsLength;
1033  fOutDat.write(pTmp1, sizeof(double));
1034  const char *pTmp2 = (const char*) &fCurrentEqualizerQuadAmpl;
1035  fOutDat.write(pTmp2, sizeof(double));
1036  char *pTmp = (char*) &fNumZPtsForCE;
1037  fOutDat.write(pTmp, sizeof(unsigned int));
1038  pTmp = (char*) &fNumRPtsForCE;
1039  fOutDat.write(pTmp, sizeof(unsigned int));
1040  pTmp = (char*) &fNumPhiPtsForCE;
1041  fOutDat.write(pTmp, sizeof(unsigned int));
1042  size_t lTotMap = fField3DMapCurrentEqualizer.size();
1043  pTmp = (char*) &lTotMap;
1044  fOutDat.write(pTmp, sizeof(size_t));
1045  for (std::map<unsigned int, std::pair<float, float> >::const_iterator it = fField3DMapCurrentEqualizer.begin();
1046  it != fField3DMapCurrentEqualizer.end(); it++) {
1047  unsigned int ii = it->first;
1048  pTmp = (char*) &ii;
1049  fOutDat.write(pTmp, sizeof(unsigned int));
1050  float bb[2];
1051  bb[0] = it->second.first;
1052  bb[1] = it->second.second;
1053  pTmp = (char*) &bb[0];
1054  fOutDat.write(pTmp, 2*sizeof(float));
1055  }
1056  fOutDat.close();
1057 
1058 }
1059 
1061 
1062  std::ifstream fInDat(fFileNameFieldMapForCE.c_str(), std::ios::in | std::ios::binary);
1063  if (!fInDat.is_open()) {
1064  std::string msg(" LBNFMagneticFieldPolyconeHorn::readFieldMapCurrentEqualizer, could not open file ");
1065  msg += fFileNameFieldMapForCE;
1066  G4Exception("LBNFMagneticFieldPolyconeHorn::readFieldMapCurrentEqualizer", " ", RunMustBeAborted, msg.c_str());
1067  }
1068  char *pTmp1 = (char*) &fCurrentEqualizerLongAbsLength;
1069  fInDat.read(pTmp1, sizeof(double));
1070  char *pTmp2 = (char*) &fCurrentEqualizerQuadAmpl;
1071  fInDat.read(pTmp2, sizeof(double));
1072  char *pTmp = (char*) &fNumZPtsForCE;
1073  fInDat.read(pTmp, sizeof(unsigned int));
1074  pTmp = (char*) &fNumRPtsForCE;
1075  fInDat.read(pTmp, sizeof(unsigned int));
1076  pTmp = (char*) &fNumPhiPtsForCE;
1077  fInDat.read(pTmp, sizeof(unsigned int));
1078  size_t lTotMap = 0;
1079  pTmp = (char*) &lTotMap;
1080  fInDat.read(pTmp, sizeof(size_t));
1081  std::cerr << " LBNFMagneticFieldPolyconeHorn::readFieldMapCurrentEqualizer "
1082  << std::endl << " ...... Size of map in file "
1083  << lTotMap << " Grid " << fNumZPtsForCE << " / " << fNumRPtsForCE << " / " << fNumPhiPtsForCE << std::endl;
1084  for (size_t i=0; i!= lTotMap; i++) {
1085  unsigned int ii = 0;
1086  pTmp = (char*) &ii;
1087  fInDat.read(pTmp, sizeof(unsigned int));
1088  float bb[2];
1089  pTmp = (char*) &bb[0];
1090  fInDat.read(pTmp, 2*sizeof(float));
1091  fField3DMapCurrentEqualizer.emplace(ii, std::pair<float, float>(bb[0], bb[1]));
1092  }
1095  fField3DMapCurrentEqualizerPhiStep = (M_PI/2.)/(fNumPhiPtsForCE-1); // Only one quadrant..
1098  for (unsigned int iZ = 0; iZ != fNumZPtsForCE; iZ++) {
1099 // std::cerr << " At Z index " << iZ << std::endl;
1101  double radIC=0.;
1102  double radOC=0.;
1103  this->fillHornPolygonRadii(z, &radIC, &radOC);
1104  fField3DMapCurrentEqualizerRadSqAtZ.push_back(radOC*radOC);
1105  double stepRadial = (fOuterRadius*fOuterRadius - radOC*radOC)/(fNumRPtsForCE-1);
1106  fField3DMapCurrentEqualizerRadSqRStepAtZ.push_back(stepRadial);
1107  }
1108  fInDat.close();
1109  this->dumpField();
1110  std::cerr << " And quit !. " << std::endl; exit(2);
1111 
1112 }
1114 //
1115 // July 25 2017..
1116 //
1117 // Alberto M. suggested the following exercise: Let us take the algorithm in the GetFieldValue method,
1118 // fill in the radOC and radIC value such that it corresponds to the problem ??? (needs reference )
1119 //
1120  std::vector<double> Bfield(2, 0.);
1121  std::vector<double> BfieldB(2, 0.);
1122  const double radOC = 6.0*CLHEP::mm;
1123  const double radIC = 2.0*CLHEP::mm;
1124  const double aBer = radIC;
1125  const double deltaE = radIC;
1126  std::ofstream fOut("./TestEccentricityBerkelyV1.txt");
1127  fOut << " x y Bx By BxB ByB " << std::endl;
1128  const int numStepY = 50;
1129  const double stepY = 2*(radIC - 0.01)/numStepY;
1130  const int numStepX = 200;
1131  const double stepX = 3*radOC/numStepX;
1132  G4double current = fHornCurrent/CLHEP::ampere/1000.;
1133  const double magBField = current / (5./CLHEP::cm)/10*CLHEP::tesla; //B(kG)=i(kA)/[5*r(cm)], 1T=10kG
1134 // double magBField = current / (5.*r/CLHEP::cm)/10*CLHEP::tesla; //B(kG)=i(kA)/[5*r(cm)], 1T=10kG ..
1135 // from GetFieldValue
1136  const double magBFieldB = 2.0*M_PI*magBField; // adjusted.. Pretty sure the constant above is correct!.
1137  for (int iy =0; iy != numStepY+1; iy++) {
1138  const double y = (iy == numStepY) ? 0. : -radIC + 0.5*stepY + iy*stepY;
1139  // last loop around is for the test along the X axis
1140  for (int ix =0; ix != numStepX; ix++) {
1141  const double x = -1.5*radOC + 0.5*stepX + ix*stepX;
1142  const double r = std::sqrt(x*x + y*y);
1143  const double phi = std::atan2(y, x);
1144  // cloned from GetFieldValue..
1145 
1146  // Two Cartesian coordinate system, the first one, centered on Outer surface of the IC
1147  // The second one, translated by delta, say to the left, and with critical radius radIn
1148 // const double ITot = magBField * r; // Up to a constant.. We don't multiply by r, see above the
1149  const double ITot = magBField; // Up to a constant.. We don't multiply by r, see above the
1150  // definition of constant magBField..
1151  const double JTot = ITot/(radOC*radOC - radIC*radIC);
1152  const double BField1Phi = (r < radOC) ? ( JTot * r) : (JTot * radOC*radOC/ r);
1153  const double BField1X = -1.0*BField1Phi*std::sin(phi);
1154  const double BField1Y = BField1Phi*std::cos(phi);
1155  const double h1 = r * std::sin(phi);
1156 // const double l2 = fDeltaEccentricityIO + r*std::cos(phi);
1157  const double l2 = (-1.0*deltaE) + r*std::cos(phi); // sign convention on delta change..
1158  const double r2 = std::sqrt(l2*l2 + h1*h1); // with respect to the displaced inner radius.
1159  const double phi2 = std::atan2(h1, l2);
1160  const double BField2Phi = (r2 < radIC) ? ( JTot * r2) : (JTot * radIC*radIC/ r2);
1161  const double BField2X = -1.0*BField2Phi*std::sin(phi2);
1162  const double BField2Y = BField2Phi*std::cos(phi2);
1163  Bfield[0] = BField1X - BField2X;
1164  Bfield[1] = BField1Y - BField2Y;
1165 
1166  // Now the BerKeley soution..
1167  BfieldB[0] = 0.;
1168  BfieldB[1] = 0.;
1169  const double r1 = r2; // notation in the Berkeley book
1170  if (r1 < radIC) {
1171  BfieldB[1] = magBFieldB/ (16.0*M_PI*aBer);
1172  } else {
1173  // valid only along the X - axis
1174  if (iy == numStepY) {
1175  if (std::abs(x) > radOC) {
1176  BfieldB[1] = (8.0*x - 9.0*aBer)*magBFieldB/(16.0*M_PI*x*(x - aBer));
1177  } else if ((((2.0*aBer <= x) && (x <= radOC))) || (((-radOC <= x) && (x <= 0)))) {
1178  BfieldB[1] = (x*x -aBer*x -aBer*aBer)*magBFieldB/(16.0*M_PI*aBer*aBer*(x - aBer));
1179  } else {
1180  std::cerr << " Unexpected case in LBNFMagneticFieldPolyconeHorn::TestEccentricityBerkeley " <<
1181  " x " << x << " y " << y << " r1 " << r1 << " iy " << iy<< std::endl;
1182  exit(2);
1183  }
1184  }
1185  }
1186  fOut << " " << x << " " << y << " "
1187  << Bfield[0] << " " << Bfield[1] << " " << BfieldB[0] << " " << BfieldB[1] << std::endl;
1188  }
1189  }
1190  fOut.close();
1191  std::cerr << " And quit for now.. " << std::endl; exit(2);
1192 
1193 }
1194 
1196  std::cerr << " Closing Output Trajectory file in LBNFMagneticFieldPolyconeHorn " << std::endl;
1197  if (fOutTraj.is_open()) fOutTraj.close();
1198 }
1199 
1200 
std::vector< double > fField3DMapCurrentEqualizerRadSqRStepAtZ
void fillTrajectories(const double Point[3], double bx, double by) const
void msg(const char *fmt,...)
Definition: message.cpp:107
const LBNEVolumePlacementData * Find(const G4String &name, const char *motherName, const char *method) const
bool GetUseLBNFOptimConceptDesignHornB() const
std::string string
Definition: nybbler.cc:12
std::vector< LBNESurveyedPt >::const_iterator GetPoint(const std::string &aName) const
static LBNEVolumePlacements * Instance()
opt
Definition: train.py:196
void getFieldFrom3DMapCurrentEqualizer(const double Point[3], double *Bfield) const
bool GetUseLBNFOptimConceptDesignHornC() const
STL namespace.
std::vector< double > GetHornsPolyInnerConductorRadiiHornARev2() const
intermediate_table::const_iterator const_iterator
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:45
double GetHornsPolyInnerConductorZCoord(size_t iH, size_t numPts) const
bool GetUseLBNFOptimConceptDesignHornA() const
double GetHornParabolicRZCoord(size_t iH, size_t k) const
double GetThickICDRevisedHornB() const
virtual void GetFieldValue(const double Point[3], double *Bfield) const
double y
T abs(T value)
std::vector< double > GetHornsPolyInnerConductorZsHornARev2() const
static LBNESurveyor * Instance()
std::vector< double > GetHornsPolyInnerConductorRadiiHornBRev2() const
double GetHornsPolyOuterRadius(size_t iH) const
double GetHornsPolyZStartPos(size_t iH) const
std::vector< double > GetHornsPolyInnerConductorRadiiHornCRev2() const
double GetHornsPolyInnerConductorThickness(size_t iH, size_t numPts) const
double z
static Entry * current
static int max(int a, int b)
bool IsHornPnParabolic(size_t numHorn) const
double getNormCurrDensityInnerC(double deltaR, double rOut) const
QString read()
void fillHornPolygonRadii(double z, double *rIn, double *rOut) const
int GetUseHornsPolyNumInnerPts(size_t i) const
T min(sqlite3 *const db, std::string const &table_name, std::string const &column_name)
Definition: statistics.h:55
std::vector< double > GetHornsPolyInnerConductorZsHornCRev2() const
double GetHornsPolyInnerConductorRadius(size_t iH, size_t numPts) const
std::vector< double > fField3DMapCurrentEqualizerRadSqAtZ
double GetThickICDRevisedHornC() const
double GetHornParabolicThick(size_t iH, size_t k) const
double GetThickICDRevisedHornA() const
list x
Definition: train.py:276
double GetHornParabolicRIn(size_t iH, size_t k) const
std::map< unsigned int, std::pair< float, float > > fField3DMapCurrentEqualizer
size_t GetHornParabolicNumInnerPts(size_t iH) const
QTextStream & endl(QTextStream &s)
std::vector< double > GetHornsPolyInnerConductorZsHornBRev2() const