Public Member Functions | Private Member Functions | Private Attributes | List of all members
LBNEMagneticFieldHorn Class Reference

#include <LBNEMagneticField.hh>

Inheritance diagram for LBNEMagneticFieldHorn:

Public Member Functions

 LBNEMagneticFieldHorn (bool isHorn1)
 
 ~LBNEMagneticFieldHorn ()
 
virtual void GetFieldValue (const double Point[3], double *Bfield) const
 
void SetHornCurrent (G4double ihorn)
 
G4double GetHornCurrent () const
 
void SetSkinDepthInnerRad (G4double f)
 
double GetEffectiveInnerRad () const
 
double GetEffectiveOuterRad () const
 
double GetEffectiveSkinDepthFact () const
 
void dumpField () const
 

Private Member Functions

void fillHorn1PolygonRadii (double z, double *rIn, double *rOut) const
 
void fillTrajectories (const double Point[3], double bx, double by) const
 
double getNormCurrDensityInnerC (double deltaR, double rOut) const
 

Private Attributes

G4bool amHorn1
 
G4double fHornCurrent
 
G4bool fCoordinateSet
 
bool fHornIsMisaligned
 
G4RotationMatrix fRotMatrixHornContainer
 
std::vector< double > fShift
 
std::vector< double > fShiftSlope
 
G4double fZShiftDrawingCoordinate
 
G4double fZShiftUpstrWorldToLocal
 
G4double fEffectiveLength
 
G4double fHornNeckOuterRadius
 
G4double fHornNeckInnerRadius
 
G4double fOuterRadius
 
G4double fOuterRadiusEff
 
G4double fSkinDepth
 
std::vector< size_t > fEqnIndicesOuter
 
std::vector< size_t > fEqnIndicesInner
 
std::vector< double > fZDCBegin
 
std::vector< double > fZDCEnd
 
G4double fNeckRadius
 
G4double fSkinDepthInnerRad
 
G4double fSkinDepthIIRInv
 
std::ofstream fOutTraj
 
double fEffectiveInnerRad
 
double fEffectiveOuterRad
 
double fEffectiveSkinDepthFact
 
bool fUseHorn1Polycone
 
std::vector< double > fRadsInnerC
 
std::vector< double > fRadsOuterC
 

Detailed Description

Definition at line 17 of file LBNEMagneticField.hh.

Constructor & Destructor Documentation

LBNEMagneticFieldHorn::LBNEMagneticFieldHorn ( bool  isHorn1)
explicit

Definition at line 18 of file LBNEMagneticField.cc.

18  :
19 amHorn1(isOne),
20 fHornCurrent(0.),
21 fCoordinateSet(false),
22 fShift(2, 0.),
23 fShiftSlope(2,0.),
27 fHornNeckOuterRadius(-1.0e13),
28 fHornNeckInnerRadius(-1.0e13),
29 fOuterRadius(1.0e9),
30 fOuterRadiusEff(1.0e9),
31 fSkinDepth(4.1*CLHEP::mm),
32 fSkinDepthInnerRad(1.0e10*CLHEP::mm) // Unrealistic high, because that was the default sometime ago.
33 
34 {
35  //
36  // We rely on the Volume Placement utility and the surveyor data to compute the coordinate transfers.
37  // Two distinct ones:
38  //
39  // (i) Going from G4 World to the local coordinate system. This is done in two steps: first a Z shift, fixed.
40  // Key variable: fZShiftUpstrWorldToLocal
41  // second, a linearized rotation due misalignement, in both X and Y.
42  //
43  // (ii) A Z translation to go from G4 World the 8875.112 MD 363xxx drawing coordinate system, such that
44  // we can used the exact parabolic equations (Outer radius one)
45  // fZShiftDrawingCoordinate
46  //
47  // This strategy has the drawback of the danger of making mistakes in the code below, but has
48  // has the advantage of less coordinate transforms. (inverse one done in the G4 Propagation. )
49  // It is assumed here that the misalignment are small, i.e., cos^2(tilt) ~ 0.
50 //
51 // Having the field manager assigned to the top level of the Horn volume instead of just
52 // the conductor polycones volumes, and the volume in between the two conductors,
53 // allows us to add fringe fields if need be, and avoid creating the volumes in between
54 // the conductors..
55 //
56  const LBNEVolumePlacements *aPlacementHandler = LBNEVolumePlacements::Instance();
57 // Radial equation interface. Take the outer equations..
58 
59  fEqnIndicesInner.clear();
60  fEqnIndicesOuter.clear();
61  fZDCBegin.clear();
62  fZDCEnd.clear();
63  fUseHorn1Polycone = false;
64  if(amHorn1) { // Use the Placement data to get the relevant Z coordinate to compute the distance to the inner or outer conductor.
65  const LBNEVolumePlacementData* plDatH1 = aPlacementHandler->Find("Bfield",
66  "Horn1PolyM1", "LBNEMagneticField::LBNEMagneticField");
68  const double zCDNeckStart = aPlacementHandler->GetHorn1NeckZPosition() - aPlacementHandler->GetHorn1NeckLength()/2.;
69  const double zCDNeckEnd = aPlacementHandler->GetHorn1NeckZPosition() + aPlacementHandler->GetHorn1NeckLength()/2.;
70  const double zCDFirstRing = 0.544*zCDNeckStart; // transition from drawing equation 1 to 2 .
71  // Drawing 8875.112-MD 363104
72 // std::cerr << " Horn1 Magnetized region, check, zCDNeckStart " << zCDNeckStart
73 // << " zCDNeckEnd " << zCDNeckEnd << std::endl;
74  //
75  // No Split geometry, August September 2014. Needs Checking..!!!.....
76  //
77  fZDCBegin.push_back(0.); fZDCEnd.push_back(zCDFirstRing);
78  fEqnIndicesInner.push_back(0); fEqnIndicesOuter.push_back(5);
79  fZDCBegin.push_back(zCDFirstRing); fZDCEnd.push_back(zCDNeckStart);
80  fEqnIndicesInner.push_back(1); fEqnIndicesOuter.push_back(5);
81  fZDCBegin.push_back(zCDNeckStart); fZDCEnd.push_back(zCDNeckEnd);
82  fEqnIndicesInner.push_back(99); fEqnIndicesOuter.push_back(99); // No equations, use the radius
83  fHornNeckOuterRadius = aPlacementHandler->GetHorn1NeckOuterRadius();
84  fHornNeckInnerRadius = aPlacementHandler->GetHorn1NeckInnerRadius();
85  const double zEndNR = aPlacementHandler->GetHorn1ZDEndNeckRegion();
86  fZDCBegin.push_back(zCDNeckEnd); fZDCEnd.push_back(zEndNR);
87  fEqnIndicesInner.push_back(3); fEqnIndicesOuter.push_back(7);
88  const double zEnd = aPlacementHandler->GetHorn1ZEndIC();
89  fZDCBegin.push_back(zEndNR); fZDCEnd.push_back(zEnd);
90  fEqnIndicesInner.push_back(4); fEqnIndicesOuter.push_back(7);
91  fEffectiveLength = aPlacementHandler->GetHorn1EffectiveLength();
92  fOuterRadius = aPlacementHandler->GetHorn1OuterTubeOuterRad();
93  fZShiftUpstrWorldToLocal = 0.; // by new definition (beginning of Oct. 2013 ) of the geometry.
94  fZShiftDrawingCoordinate = 30.0*CLHEP::mm*aPlacementHandler->GetHorn1LongRescale(); // Drawing 8875.112-MD-363097
95  if (aPlacementHandler->GetUseHorn1Polycone() || (aPlacementHandler->GetNumberOfHornsPolycone() > 0)) {
96  fUseHorn1Polycone = true;
97  fZShiftDrawingCoordinate = 0.; // Check with Geantino here...
98  fZDCBegin.clear();
99  fRadsInnerC.clear();
100  fRadsOuterC.clear();
101 // std::cerr << " Check coordinates of inner radius of Horn1 Polycone inner conductor... fOuterRadius " << fOuterRadius << std::endl;
102  if (aPlacementHandler->IsHornPnParabolic(1)) {
103  size_t nPts = aPlacementHandler->GetHornParabolicNumInnerPts(0);
104  const double epsil = 0.050*CLHEP::mm; // from LBNEVolumePlacements::UpdateParamsForHornMotherPolyNum
105  for (size_t k=0; k != nPts; k++) {
106  fZDCBegin.push_back(aPlacementHandler->GetHornParabolicRZCoord(0, k) + fZShiftDrawingCoordinate + epsil);
107  const double rIn = aPlacementHandler->GetHornParabolicRIn(0, k) - epsil;
108  fRadsInnerC.push_back(rIn);
109  const double rOut = rIn + aPlacementHandler->GetHornParabolicThick(0, k);
110  fRadsOuterC.push_back(rOut);
111  }
112  } else {
113  for (size_t k=0; k!= static_cast<size_t>(aPlacementHandler->GetUseHorn1PolyNumInnerPts()); k++) {
114  fZDCBegin.push_back(aPlacementHandler->GetHorn1PolyInnerConductorZCoord(k) + fZShiftDrawingCoordinate);
115  const double rIn = aPlacementHandler->GetHorn1PolyInnerConductorRadius(k);
116  fRadsInnerC.push_back(rIn);
117  const double rOut = rIn + aPlacementHandler->GetHorn1PolyInnerConductorThickness(k);
118  fRadsOuterC.push_back(rOut);
119 // std::cerr << " k " << k << " z " << fZDCBegin[fZDCBegin.size()-1] << " InnerC " << rIn << " out " << rOut << std::endl;
120  }
121 // std::cerr << " Horn 1 magentic field decalred.. And quit for now.. I say so.. " << std::endl; exit(2);
122  }
123  } // Polycone, Parabolic style...or straight...
124  } else {
125  const LBNEVolumePlacementData* plDatH2 = aPlacementHandler->Find("Bfield",
126  "Horn2TopLevel", "LBNEMagneticField::LBNEMagneticField");
127 // std::cerr << " Number of equation changes " << aPlacementHandler->GetHorn2ZEqnChangeNumEqn() << std::endl;
128 // for (size_t k=0; k != aPlacementHandler->GetHorn2ZEqnChangeNumEqn(); k++) {
129 // std::cerr << " Horn2 zone " << k << " at z "
130 // << aPlacementHandler->GetHorn2ZEqnChange(k)/25.4 << std::endl;
131 // }
132  fEffectiveLength = plDatH2->fParams[2];
133  const double z1 = aPlacementHandler->GetHorn2ZEqnChange(0);
134  fZDCBegin.push_back(0.); fZDCEnd.push_back(z1);
135  fEqnIndicesInner.push_back(6); fEqnIndicesOuter.push_back(10); //IO trasnsition, Part 1
136 
137  const double z2 = aPlacementHandler->GetHorn2ZEqnChange(1);
138  fZDCBegin.push_back(z1); fZDCEnd.push_back(z2);
139  fEqnIndicesInner.push_back(6); fEqnIndicesOuter.push_back(0); // Getting to the neck region
140 
141  const double z3 = aPlacementHandler->GetHorn2ZEqnChange(2);
142  fZDCBegin.push_back(z2); fZDCEnd.push_back(z3);
143  fEqnIndicesInner.push_back(6); fEqnIndicesOuter.push_back(0); // Getting to the neck, neck region
144 
145  const double z4 = aPlacementHandler->GetHorn2ZEqnChange(3);
146  fZDCBegin.push_back(z3); fZDCEnd.push_back(z4);
147  fEqnIndicesInner.push_back(6); fEqnIndicesOuter.push_back(1); // Just before the neck
148 
149  const double z5 = aPlacementHandler->GetHorn2ZEqnChange(4);
150  fZDCBegin.push_back(z4); fZDCEnd.push_back(z5);
151  fEqnIndicesInner.push_back(99); fEqnIndicesOuter.push_back(99); //The neck, fixe radius
152  fHornNeckOuterRadius = aPlacementHandler->GetHorn2NeckOuterRadius();
153  fHornNeckInnerRadius = aPlacementHandler->GetHorn2NeckInnerRadius();
154 
155  const double z6 = aPlacementHandler->GetHorn2ZEqnChange(5);
156  fZDCBegin.push_back(z5); fZDCEnd.push_back(z6);
157  fEqnIndicesInner.push_back(7); fEqnIndicesOuter.push_back(2); // Just after the neck
158 
159  const double z7 = aPlacementHandler->GetHorn2ZEqnChange(6);
160  fZDCBegin.push_back(z6); fZDCEnd.push_back(z7);
161  fEqnIndicesInner.push_back(7); fEqnIndicesOuter.push_back(3); // moving along positive Z, neck region
162 
163  const double z8 = aPlacementHandler->GetHorn2ZEqnChange(7); // Next physical section
164  fZDCBegin.push_back(z7); fZDCEnd.push_back(z8);
165  fEqnIndicesInner.push_back(7); fEqnIndicesOuter.push_back(3);
166 
167  const double z9 = aPlacementHandler->GetHorn2ZEqnChange(8); //
168  fZDCBegin.push_back(z8); fZDCEnd.push_back(z9);
169  fEqnIndicesInner.push_back(8); fEqnIndicesOuter.push_back(4);
170 
171  const double z10 = aPlacementHandler->GetHorn2ZEqnChange(9);
172  fZDCBegin.push_back(z9); fZDCEnd.push_back(z10);
173  fEqnIndicesInner.push_back(9); fEqnIndicesOuter.push_back(5);
174 
175  fOuterRadius = aPlacementHandler->GetHorn2OuterTubeOuterRad();
176  fZShiftUpstrWorldToLocal = aPlacementHandler->GetHorn2LongPosition() +
177  aPlacementHandler->GetHorn2LongRescale()*
178  aPlacementHandler->GetHorn2DeltaZEntranceToZOrigin(); // by new definition (beginning of Oct. 2013 ) of the geometry.
179  fZShiftDrawingCoordinate = -1.0*aPlacementHandler->GetHorn2LongRescale()*
180  aPlacementHandler->GetHorn2DeltaZEntranceToZOrigin();
181  const LBNEVolumePlacementData* plDatH2b = aPlacementHandler->Find("Bfield",
182  "Horn2Hall", "LBNEMagneticField::LBNEMagneticField");
184  }
185  std::cerr << " Magnetic field coordinate definition done. fZShiftUpstrWorldToLocal " <<
186  fZShiftUpstrWorldToLocal << " fZShiftDrawingCoordinate " << fZShiftDrawingCoordinate << std::endl;
187 // fCoordinateSet = true; obsolete. Except for use of dumping the field...
188  fOuterRadiusEff = fOuterRadius - 2.0*fSkinDepth; // skin depth at 0.43 kHz
189  // Z coordinate change not yet initialize, done at the first track.
190 /*
191  std::cerr << " Table of Z position and equations for ";
192  if (amHorn1) std::cerr << " Horn1 " ;
193  else std::cerr << " Horn2 " ;
194  std::cerr << std::endl << " Z-Start Z-End Innner Eqn Outer Eqn rIC thick" << std::endl;
195  for(size_t k=0; k!= fZDCBegin.size(); k++) {
196  std::cerr << " " << fZDCBegin[k] << " " << fZDCEnd[k]
197  << " " << fEqnIndicesInner[k] << " " << fEqnIndicesOuter[k];
198  const double zMid = 0.5 *( fZDCBegin[k] + fZDCEnd[k]);
199  double rOut = fHornNeckOuterRadius;
200  double rIn = fHornNeckInnerRadius;
201  if (fEqnIndicesInner[k] != 99) {
202  rOut = (amHorn1) ? aPlacementHandler->GetConductorRadiusHorn1(zMid, fEqnIndicesOuter[k]) :
203  aPlacementHandler->GetConductorRadiusHorn2(zMid, fEqnIndicesOuter[k]);
204  rIn = (amHorn1) ? aPlacementHandler->GetConductorRadiusHorn1(zMid, fEqnIndicesInner[k]) :
205  aPlacementHandler->GetConductorRadiusHorn2(zMid, fEqnIndicesInner[k]);
206  }
207  std::cerr << " " << rIn << " " << rOut - rIn << std::endl;
208  }
209 */
210 //
211 // Use now the survey data (simulated for now.. ) to establish the coordinate transform..
212 //
213  LBNESurveyor *theSurvey= LBNESurveyor::Instance();
214  std::string hornIndexStr = (amHorn1) ? std::string("1") : std::string("2");
215  std::string upstrStr("Upstream");std::string downstrStr("Downstream");
216  std::string leftStr("Left"); std::string rightStr("Right");
217  std::string ballStr("BallHorn");
219  theSurvey->GetPoint(G4String(upstrStr + leftStr + ballStr + hornIndexStr));
221  theSurvey->GetPoint(G4String(upstrStr + rightStr + ballStr + hornIndexStr));
223  theSurvey->GetPoint(G4String(downstrStr + leftStr + ballStr + hornIndexStr));
225  theSurvey->GetPoint(G4String(downstrStr + rightStr + ballStr + hornIndexStr));
226  const G4ThreeVector pUpLeft = itUpLeft->GetPosition();
227  const G4ThreeVector pUpRight = itUpRight->GetPosition();
228  const G4ThreeVector pDwLeft = itDwLeft->GetPosition();
229  const G4ThreeVector pDwRight = itDwRight->GetPosition();
230  fHornIsMisaligned = false;
231  for (size_t k=0; k!=2; k++) {
232  fShift[k] = -0.50*(pUpLeft[k] + pUpRight[k]); // minus sign comes from the global to local.
233  // Transverse shoft at the upstream entrance of Horn1
234  fShiftSlope[k] = 0.5*(pUpLeft[k] + pUpRight[k] - pDwLeft[k] - pDwRight[k])/fEffectiveLength;
235  if (std::abs(fShiftSlope[k]) > 1.0e-8) fHornIsMisaligned = true;
236  }
237  if (fHornIsMisaligned) {
238  if (amHorn1) std::cerr << " Horn1 ";
239  else std::cerr << " Horn2 ";
240  std::cerr << " is misaligned "
241  << " xz term " << fRotMatrixHornContainer[0][2] << " yz " << fRotMatrixHornContainer[1][2] << std::endl;
242  }
243 /*
244  if (!amHorn1) {
245  std::cerr << " fShift X " << fShift[0] << " Y " << fShift[1] << std::endl;
246  std::cerr << " fShiftSlope X " << fShiftSlope[0] << " Y " << fShiftSlope[1] << std::endl;
247  std::cerr << " UpLeft X " << pUpLeft[0] << " Y " << pUpLeft[1] << std::endl;
248  std::cerr << " UpRight X " << pUpRight[0] << " Y " << pUpRight[1] << std::endl;
249  std::cerr << " DwLeft X " << pDwLeft[0] << " Y " << pDwLeft[1] << std::endl;
250  std::cerr << " DwRight X " << pDwRight[0] << " Y " << pDwRight[1] << " eff L " << fEffectiveLength << std::endl;
251  exit(2);
252  }
253 */
254 //
255 // Open a file to study the value of the field for displaced trajectory...
256 //
257 // if (!fOutTraj.is_open()) {
258 // G4String fNameStr("./FieldTrajectories_Horn");
259 // if (amHorn1) fNameStr += G4String("1_1.txt");
260 // else fNameStr += G4String("2_1.txt");
261 // fOutTraj.open(fNameStr.c_str()); // we will place a GUI interface at a later stage...
262 // fOutTraj << " id x y z bx by " << std::endl;
263 // }
264 }
double GetHorn1OuterTubeOuterRad() const
double GetHorn2ZEqnChange(size_t k) const
double GetHorn1EffectiveLength() const
const LBNEVolumePlacementData * Find(const G4String &name, const char *motherName, const char *method) const
std::string string
Definition: nybbler.cc:12
std::vector< LBNESurveyedPt >::const_iterator GetPoint(const std::string &aName) const
static LBNEVolumePlacements * Instance()
double GetHorn2DeltaZEntranceToZOrigin() const
intermediate_table::const_iterator const_iterator
std::vector< size_t > fEqnIndicesInner
std::vector< double > fRadsInnerC
std::vector< double > fZDCBegin
double GetHornParabolicRZCoord(size_t iH, size_t k) const
double GetHorn1NeckInnerRadius() const
double GetHorn1LongRescale() const
double GetHorn2OuterTubeOuterRad() const
T abs(T value)
std::vector< double > fParams
static LBNESurveyor * Instance()
double GetHorn2NeckInnerRadius() const
std::vector< double > fShift
double GetHorn1ZEndIC() const
double GetHorn1PolyInnerConductorThickness(size_t numPts) const
bool IsHornPnParabolic(size_t numHorn) const
double GetHorn1NeckOuterRadius() const
std::vector< double > fZDCEnd
double GetHorn1NeckZPosition() const
double GetHorn1PolyInnerConductorRadius(size_t numPts) const
double GetHorn2LongRescale() const
std::vector< double > fShiftSlope
double GetHorn1PolyInnerConductorZCoord(size_t numPts) const
double GetHornParabolicThick(size_t iH, size_t k) const
G4RotationMatrix fRotMatrixHornContainer
double GetHorn1NeckLength() const
std::vector< double > fRadsOuterC
double GetHornParabolicRIn(size_t iH, size_t k) const
std::vector< size_t > fEqnIndicesOuter
int GetNumberOfHornsPolycone() const
double GetHorn1ZDEndNeckRegion() const
size_t GetHornParabolicNumInnerPts(size_t iH) const
double GetHorn2LongPosition() const
int GetUseHorn1PolyNumInnerPts() const
QTextStream & endl(QTextStream &s)
double GetHorn2NeckOuterRadius() const
LBNEMagneticFieldHorn::~LBNEMagneticFieldHorn ( )

Definition at line 472 of file LBNEMagneticField.cc.

472  {
473  std::cerr << " Closing Output Trajectory file in LBNEMagneticFieldHorn " << std::endl;
474  if (fOutTraj.is_open()) fOutTraj.close();
475 }
QTextStream & endl(QTextStream &s)

Member Function Documentation

void LBNEMagneticFieldHorn::dumpField ( ) const

Definition at line 412 of file LBNEMagneticField.cc.

412  {
413 
414  std::string fName = (amHorn1) ? std::string("./FieldMapNuMIHorn1.txt") :
415  std::string("./FieldMapNuMIHorn2.txt");
416  std::ofstream fOut(fName.c_str());
417  fOut << " z zd r bphi " << std::endl;
418  double zStart = -500.;
419  double zEnd = 4000.;
420  double rMax = fOuterRadius + 5.0*CLHEP::mm;
421 // if (amHorn1) std::cerr << " Horn1, Dumpfield, r Max = " << rMax << std::endl;
422 // else std::cerr << " Horn2, Dumpfield, r Max = " << rMax << std::endl;
423  if (!amHorn1) { zStart = 6000.; zEnd = 11000.; }
424  const int numZStep = 100;
425  const int numRStep= 2000;
426  const double zStep = (zEnd-zStart)/numZStep;
427  const double rStep = rMax/numRStep;
428  double point[3];
429  for (int iZ=0; iZ !=numZStep; iZ++) {
430  double z = zStart + iZ*zStep;
431  point[2] = z;
432  const double zLocD = point[2] - fZShiftDrawingCoordinate;
433  double radIC = fHornNeckInnerRadius;
434 // size_t kSelZ = fEqnIndicesInner.size();
435 // for (size_t k=0; k != fEqnIndicesInner.size(); ++k) {
436 // if (zLocD < fZDCBegin[k]) break;
437 // if (zLocD > fZDCEnd[k]) continue; // They are Z ordered..
438 // kSelZ = k;
439 // break;
440 // }
441 // if (kSelZ == fEqnIndicesInner.size()) continue;
442 // if (fEqnIndicesInner[kSelZ] != 99) {
443 // radIC = (amHorn1) ? aPlacementHandler->GetConductorRadiusHorn1(zLocD,fEqnIndicesInner[kSelZ] ) :
444 // aPlacementHandler->GetConductorRadiusHorn2(zLocD, fEqnIndicesInner[kSelZ]);
445 // }
446  double r = std::max(0., (radIC - 5.*CLHEP::mm)); // make sure we cover the Horn1Poly volume
447  // inside the conductor...
448  while (r < rMax) {
449  const double phi = 2.0*M_PI*G4RandFlat::shoot();
450  point[0] = r*std::cos(phi);
451  point[1] = r*std::sin(phi);
452  double bf[3];
453  this->GetFieldValue(point, &bf[0]);
454  fOut << " " << z << " " << zLocD << " " << r << " "
455  << std::sqrt(bf[0]*bf[0] + bf[1]*bf[1])/CLHEP::tesla << std::endl;
456  if (r < (radIC + 5.0*CLHEP::mm)) r += 0.1*CLHEP::mm;
457  else r += rStep;
458  }
459  }
460  fOut.close();
461 }
std::string string
Definition: nybbler.cc:12
virtual void GetFieldValue(const double Point[3], double *Bfield) const
double z
static int max(int a, int b)
QTextStream & endl(QTextStream &s)
void LBNEMagneticFieldHorn::fillHorn1PolygonRadii ( double  z,
double *  rIn,
double *  rOut 
) const
inlineprivate

Definition at line 77 of file LBNEMagneticField.hh.

77  {
78  size_t kLow = 0;
79  size_t kHigh = fZDCBegin.size() - 1;
80  for (size_t k=0; k != fZDCBegin.size() - 1; k++) {
81  if ((z >= fZDCBegin[k]) && (z < fZDCBegin[k+1])) {
82  kLow = k;
83  kHigh = k+1;
84  const double dzFrac = (z - fZDCBegin[kLow])/(fZDCBegin[kHigh] - fZDCBegin[kLow]);
85  *rIn = fRadsInnerC[kLow] + dzFrac*(fRadsInnerC[kHigh] - fRadsInnerC[kLow]);
86  *rOut = fRadsOuterC[kLow] + dzFrac*(fRadsOuterC[kHigh] - fRadsOuterC[kLow]);
87 // std::cerr << " .......... z " << z << " k " << k << " rIn " << (*rIn) << " rOut " << (*rOut) << std::endl;
88  return;
89  }
90  }
91  *rIn = 1.0e10;
92  *rOut = 2.0e10;
93  }
std::vector< double > fRadsInnerC
std::vector< double > fZDCBegin
double z
std::vector< double > fRadsOuterC
void LBNEMagneticFieldHorn::fillTrajectories ( const double  Point[3],
double  bx,
double  by 
) const
private

Definition at line 463 of file LBNEMagneticField.cc.

463  {
464  if (!fOutTraj.is_open()) return;
465  LBNERunManager* pRunManager = dynamic_cast<LBNERunManager*>(G4RunManager::GetRunManager());
466  fOutTraj << " " << pRunManager->GetCurrentEvent()->GetEventID();
467  for (size_t k=0; k!= 3; k++) fOutTraj << " " << Point[k];
468  fOutTraj << " " << bx/CLHEP::tesla << " " << " " << by/CLHEP::tesla << std::endl;
469  // we flush, the destructor never called..
470  fOutTraj.flush();
471 }
QTextStream & endl(QTextStream &s)
double LBNEMagneticFieldHorn::GetEffectiveInnerRad ( ) const
inline

Definition at line 123 of file LBNEMagneticField.hh.

123 { return fEffectiveInnerRad;}
double LBNEMagneticFieldHorn::GetEffectiveOuterRad ( ) const
inline

Definition at line 124 of file LBNEMagneticField.hh.

124 { return fEffectiveOuterRad;}
double LBNEMagneticFieldHorn::GetEffectiveSkinDepthFact ( ) const
inline

Definition at line 125 of file LBNEMagneticField.hh.

void LBNEMagneticFieldHorn::GetFieldValue ( const double  Point[3],
double *  Bfield 
) const
virtual

Definition at line 266 of file LBNEMagneticField.cc.

267 {
268 
269 
270  G4double current = fHornCurrent/CLHEP::ampere/1000.;
271 // std::cerr << " LBNEMagneticFieldHorn::GetFieldValue Z " << Point[2] << " current " << current << std::endl;
272  for (size_t k=0; k!=3; ++k) Bfield[k] = 0.;
273  // Intialization of the coordinate transform.
274  const LBNEVolumePlacements *aPlacementHandler = LBNEVolumePlacements::Instance();
275  /* Obsolete...
276  if (!fCoordinateSet) {
277 
278  G4Navigator* numinavigator=new G4Navigator(); //geometry navigator
279  G4Navigator* theNavigator=G4TransportationManager::GetTransportationManager()->GetNavigatorForTracking();
280  numinavigator->SetWorldVolume(theNavigator->GetWorldVolume());
281  G4ThreeVector Position=G4ThreeVector(Point[0],Point[1],Point[2]);
282  G4VPhysicalVolume* myVolume = numinavigator->LocateGlobalPointAndSetup(Position);
283  G4TouchableHistoryHandle aTouchable = numinavigator->CreateTouchableHistoryHandle();
284  G4ThreeVector localPosition = aTouchable->GetHistory()->GetTopTransform().TransformPoint(Position);
285  delete numinavigator;
286  G4String vName = myVolume->GetLogicalVolume()->GetName();
287  if (amHorn1 ) {
288  if (vName != G4String("Horn1Hall") || (localPosition[2] > 0.)) return; // not there yet.., or getting by the back side.
289  fZShiftUpstrWorldToLocal = Point[2]; // to correct for the misalignment, via the first coordinate transform
290  // Note: because the logival Horn1 container volume is split into to of them,
291  // the offset for the field might a bit different than for the actual volume. This is a small correction.
292  // What matter most the field is the tilt, which is correct.
293  fZShiftDrawingCoordinate = Point[2] - aPlacementHandler->GetHorn1DeltaZEntranceToZOrigin(); // Check the sign !
294  } else {
295  if (vName != G4String("Horn2TopLevel") || (localPosition[2] > 0.)) return;
296  fZShiftUpstrWorldToLocal = Point[2]; // to correct for the misalignment, via the first coordinate transform
297  fZShiftDrawingCoordinate = Point[2] - aPlacementHandler->GetHorn2DeltaZEntranceToZOrigin();
298  }
299  fCoordinateSet = true;
300  this->dumpField();
301  std::cerr << " Coordinate transform, Z shifts at Z World " << Point[2] << " in " << vName << std::endl;
302 // if (!amHorn1) { std::cerr << " And quit !!!! " << std::endl; exit(2); }
303  } // Initialization of Z coordinate transform
304  if (!fCoordinateSet) return;
305  */
306  std::vector<double> ptTrans(2,0.);
307  const double zLocal = Point[2] - fZShiftUpstrWorldToLocal; // from the start of the relevant volume
308  for (size_t k=0; k != 2; k++)
309  ptTrans[k] = Point[k] + fShift[k] + zLocal*fShiftSlope[k];
310  const double r = std::sqrt(ptTrans[0]*ptTrans[0] + ptTrans[1]*ptTrans[1]);
311  if (r > fOuterRadius) return;
312  if ( r < 1.0e-3) return; // The field should go smoothly to zero at the center of the horm
313 
314  double magBField = current / (5.*r/CLHEP::cm)/10*CLHEP::tesla; //B(kG)=i(kA)/[5*r(cm)], 1T=10kG
315  double radIC = fHornNeckInnerRadius;
316  double radOC = fHornNeckOuterRadius;
317  if ( r > fOuterRadiusEff) {
318  const double dr = r - fOuterRadiusEff;
319  const double attLength = std::exp(-dr/fSkinDepth);
320  magBField *= attLength;
321  } else {
322  if (fUseHorn1Polycone) { // Custom Horn1, based on polygons
323  this->fillHorn1PolygonRadii(zLocal, &radIC, &radOC);
324  if (std::abs(radIC) > 1.0e6) return;
325  } else { // Numi style Horn1 (or Horn2)
326  size_t kSelZ = fEqnIndicesInner.size();
327  const double zLocD = zLocal - fZShiftDrawingCoordinate;
328  for (size_t k=0; k != fEqnIndicesInner.size(); ++k) {
329  if (zLocD < fZDCBegin[k]) break;
330  if (zLocD > fZDCEnd[k]) continue; // They are Z ordered..
331  kSelZ = k;
332  break;
333  }
334  if (kSelZ == fEqnIndicesInner.size()) return;
335  if (fEqnIndicesInner[kSelZ] != 99) {
336  radIC = (amHorn1) ? aPlacementHandler->GetConductorRadiusHorn1(zLocD,fEqnIndicesInner[kSelZ] ) :
337  aPlacementHandler->GetConductorRadiusHorn2(zLocD, fEqnIndicesInner[kSelZ]);
338  radOC = (amHorn1) ? aPlacementHandler->GetConductorRadiusHorn1(zLocD,fEqnIndicesOuter[kSelZ] ) :
339  aPlacementHandler->GetConductorRadiusHorn2(zLocD, fEqnIndicesOuter[kSelZ]);
340  }
341  if (amHorn1 && aPlacementHandler->IsHorn1RadiusBigEnough()) { // Obsolete.. (Aug, Sept. 2014)
342  radIC = std::max(radIC, aPlacementHandler->GetHorn1RMinAllBG());
343  radOC = std::max(radOC, aPlacementHandler->GetHorn1RMaxAllBG());
344  }
345  if ((radIC < 1.0e-3) || (radOC < 1.0e-3)) {
346  std::ostringstream mStrStr;
347  mStrStr << " Wrong equation index at Z " << Point[2] << std::endl;
348  G4String mStr(mStrStr.str());
349  G4Exception("LBNEMagneticFieldHorn::GetFieldValue", " ", FatalErrorInArgument, mStr.c_str());
350  return;
351  }
352  }
353  fEffectiveInnerRad = radIC;
354  fEffectiveOuterRad = radOC;
356  // Study of systematic effects. Define an effective radIC wich is large than the physics radIC.
357  // We assume here that the finite skin depth matter, and the current density is not
358  // uniform. Simply increase the radIC
359  if (r < radIC) return; // zero field region (Amps law).
360 // const double deltaRIC = radOC - radIC;
361 // Version from Dec 18-19 2013.
362 // radIC += deltaRIC*std::min(0.99, fSkinDepthCorrInnerRad);
363  //
364 // if ((r > radIC) && (r < radOC)) {
365 // const double surfCyl = radOC*radOC - radIC*radIC;
366 // const double deltaRSq = (r*r - radIC*radIC);
367 // magBField *= deltaRSq/surfCyl; // Assume uniform current density and apply Amps law.
368 // }
369 // Version from Zarko's thesis. ( (MINOS Document 5694-v1) )
370 //
371  if ((r > radIC) && (r < radOC)) {
372  const double surfCyl = radOC*radOC - radIC*radIC;
373  const double deltaRSq = (r*r - radIC*radIC);
374  const double factR = deltaRSq/surfCyl;
375  fEffectiveSkinDepthFact = factR;
376  if (fSkinDepthInnerRad > 10.*CLHEP::mm) { // default assume very large skin depth, assume constant current
377  // current density .
378  magBField *= factR; // Assume uniform current density and apply Amps law.
379  } else { // Realistic skin depth.
380  magBField *= factR*getNormCurrDensityInnerC((r-radIC), (radOC-radIC))
381  /getNormCurrDensityInnerC((radOC-radIC), (radOC-radIC));
382  }
383  }
384 // Sin and cos factor bphi -> bx, by
385  Bfield[0] = -magBField*ptTrans[1]/r;
386  Bfield[1] = magBField*ptTrans[0]/r;
387 //
388 // Important correction.. ( a bug from a long time ago !)
389 // One needs to rotate the field as well. It is expected to be given in global coordinate
390 //
391  if (fHornIsMisaligned) {
392  std::vector<double> bFieldLocal(3);
393  for(size_t k=0; k != 3; k++) { bFieldLocal[k] = Bfield[k]; Bfield[k] = 0.; }
394  for (size_t k1=0; k1 !=3; k1++) {
395  for (size_t k2=0; k2 !=3; k2++) Bfield[k1] += fRotMatrixHornContainer[k1][k2]*bFieldLocal[k2];
396  }
397 // std::cerr << " Misaligned Horn" << hornNumber+1 << ", rotation of the field ... " << std::endl;
398 // for(size_t k=0; k != 3; k++) std::cerr << " Component " << k
399 // << " local " << bFieldLocal[k] << " global " << Bfield[k] << std::endl;
400  }
401  if (!fCoordinateSet) {
402  fCoordinateSet = true; //done once and only once.
403 // this->dumpField();
404  }
405 // this->fillTrajectories(Point, Bfield[0], Bfield[1]);
406 // std::cerr << " Field region at Z " << Point[2] << " r = " << r
407 // << " radIC " << radIC << " radOC "
408 // << radOC << "zLocD " << zLocD << " magBField "
409 // << magBField/tesla << " Bx " << Bfield[0]/tesla << std::endl;
410  }
411 }
double getNormCurrDensityInnerC(double deltaR, double rOut) const
static LBNEVolumePlacements * Instance()
double GetHorn1RMinAllBG() const
std::vector< size_t > fEqnIndicesInner
void G4Exception(const char *originOfException, const char *exceptionCode, G4ExceptionSeverity severity, const char *description)
Definition: G4Exception.cc:45
std::vector< double > fZDCBegin
T abs(T value)
std::vector< double > fShift
static Entry * current
static int max(int a, int b)
std::vector< double > fZDCEnd
double GetConductorRadiusHorn2(double zD, size_t eqn) const
std::vector< double > fShiftSlope
G4RotationMatrix fRotMatrixHornContainer
void fillHorn1PolygonRadii(double z, double *rIn, double *rOut) const
double GetConductorRadiusHorn1(double zD, size_t eqn) const
std::vector< size_t > fEqnIndicesOuter
double GetHorn1RMaxAllBG() const
QTextStream & endl(QTextStream &s)
bool IsHorn1RadiusBigEnough() const
G4double LBNEMagneticFieldHorn::GetHornCurrent ( ) const
inline

Definition at line 121 of file LBNEMagneticField.hh.

121 { return fHornCurrent;}
double LBNEMagneticFieldHorn::getNormCurrDensityInnerC ( double  deltaR,
double  rOut 
) const
inlineprivate

Definition at line 104 of file LBNEMagneticField.hh.

104  {
105  if (deltaR < 0.) return 0.;
106  const double xby2 = fSkinDepthIIRInv*deltaR/2.; // x must be less < 1, otherwise Taylor expansion fails..
107  const double xby2Out = fSkinDepthIIRInv*rOut/2.; // x must be less < 1, otherwise Taylor expansion fails..
108  // keep only 3 terms..
109  const double ber = 1.0 - std::pow(xby2, 4.)/4. + std::pow(xby2, 8.)/576.;
110  const double bei = std::pow(xby2, 2.) - std::pow(xby2, 6.)/36 + std::pow(xby2, 10.)/14400.;
111  const double beNSq = ber*ber + bei*bei;
112  const double berOut = 1.0 - std::pow(xby2Out, 4.)/4. + std::pow(xby2Out, 8.)/576.;
113  const double beiOut = std::pow(xby2Out, 2.) - std::pow(xby2Out, 6.)/36 + std::pow(xby2Out, 10.)/14400.;
114  const double beNSqOut = berOut*berOut + beiOut*beiOut;
115  return std::sqrt(beNSq/beNSqOut);
116  }
constexpr T pow(T x)
Definition: pow.h:72
void LBNEMagneticFieldHorn::SetHornCurrent ( G4double  ihorn)
inline

Definition at line 120 of file LBNEMagneticField.hh.

120 {fHornCurrent = ihorn;}
void LBNEMagneticFieldHorn::SetSkinDepthInnerRad ( G4double  f)
inline

Member Data Documentation

G4bool LBNEMagneticFieldHorn::amHorn1
private

Definition at line 26 of file LBNEMagneticField.hh.

G4bool LBNEMagneticFieldHorn::fCoordinateSet
mutableprivate

Definition at line 30 of file LBNEMagneticField.hh.

double LBNEMagneticFieldHorn::fEffectiveInnerRad
mutableprivate

Definition at line 65 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fEffectiveLength
private

Definition at line 43 of file LBNEMagneticField.hh.

double LBNEMagneticFieldHorn::fEffectiveOuterRad
mutableprivate

Definition at line 66 of file LBNEMagneticField.hh.

double LBNEMagneticFieldHorn::fEffectiveSkinDepthFact
mutableprivate

Definition at line 67 of file LBNEMagneticField.hh.

std::vector<size_t> LBNEMagneticFieldHorn::fEqnIndicesInner
private

Definition at line 52 of file LBNEMagneticField.hh.

std::vector<size_t> LBNEMagneticFieldHorn::fEqnIndicesOuter
private

Definition at line 51 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fHornCurrent
private

Definition at line 27 of file LBNEMagneticField.hh.

bool LBNEMagneticFieldHorn::fHornIsMisaligned
private

Definition at line 31 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fHornNeckInnerRadius
private

Definition at line 45 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fHornNeckOuterRadius
private

Definition at line 44 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fNeckRadius
private

Definition at line 55 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fOuterRadius
private

Definition at line 46 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fOuterRadiusEff
private

Definition at line 47 of file LBNEMagneticField.hh.

std::ofstream LBNEMagneticFieldHorn::fOutTraj
mutableprivate

Definition at line 61 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fRadsInnerC
private

Definition at line 74 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fRadsOuterC
private

Definition at line 75 of file LBNEMagneticField.hh.

G4RotationMatrix LBNEMagneticFieldHorn::fRotMatrixHornContainer
private

Definition at line 32 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fShift
private

Definition at line 33 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fShiftSlope
private

Definition at line 34 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fSkinDepth
private

Definition at line 48 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fSkinDepthIIRInv
private

Definition at line 60 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fSkinDepthInnerRad
private

Definition at line 59 of file LBNEMagneticField.hh.

bool LBNEMagneticFieldHorn::fUseHorn1Polycone
private

Definition at line 73 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fZDCBegin
private

Definition at line 53 of file LBNEMagneticField.hh.

std::vector<double> LBNEMagneticFieldHorn::fZDCEnd
private

Definition at line 54 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fZShiftDrawingCoordinate
mutableprivate

Definition at line 35 of file LBNEMagneticField.hh.

G4double LBNEMagneticFieldHorn::fZShiftUpstrWorldToLocal
mutableprivate

Definition at line 38 of file LBNEMagneticField.hh.


The documentation for this class was generated from the following files: