QwGeant4
QweakSimMagneticField.cc
Go to the documentation of this file.
1 //=============================================================================
2 //
3 // ---------------------------
4 // | Doxygen File Information |
5 // ---------------------------
6 //
7 /**
8 
9  \file QweakSimMagneticField.cc
10 
11  $Revision: 1.2 $
12  $Date: 2005/12/27 19:10:21 $
13 
14  \author Klaus Hans Grimm
15 
16 */
17 //=============================================================================
18 
19 //=============================================================================
20 // -----------------------
21 // | CVS File Information |
22 // -----------------------
23 //
24 // Last Update: $Author: grimm $
25 // Update Date: $Date: 2005/12/27 19:10:21 $
26 // CVS/RCS Revision: $Revision: 1.2 $
27 // Status: $State: Exp $
28 //
29 // ===================================
30 // CVS Revision Log at end of file !!
31 // ===================================
32 //
33 //============================================================================
34 
35 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
36 
37 #include "QweakSimMagneticField.hh"
38 
39 // geant4 includes
40 #include "G4SystemOfUnits.hh"
41 
42 // user includes
44 #include "QweakSimFieldMap.hh"
45 
46 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
47 
49 {
50  G4cout << G4endl << "###### Calling QweakSimMagneticField::QweakSimMagneticField() " << G4endl << G4endl;
51 
52  // No field map
53  fField = 0;
54 
55  // Messenger
57 
58  // Default settings
59  SetRotation(0.0);
60  SetTranslation(0.0);
61  SetTranslationVector(G4ThreeVector(0.0,0.0,0.0));
62 
63  // Default field map grid (peiqing_2007.dat)
64  fMin.push_back(-250.0); fMax.push_back(250.0); fStep.push_back(2.0); fWrap.push_back(0);
65  fMin.push_back(2.0); fMax.push_back(300.0); fStep.push_back(2.0); fWrap.push_back(0);
66  fMin.push_back(-0.5 * degree/radian); fMax.push_back(360.5 * degree/radian); fStep.push_back(1.0 * degree/radian); fWrap.push_back(2);
67 
68  // Set current and scale factors
69  G4double current = 8921.0;
70  fActualCurrent = current;
71  fReferenceCurrent = current;
72  fScaleFactor = 1.0;
73 
74  G4cout << G4endl << "###### Leaving QweakSimMagneticField::QweakSimMagneticField " << G4endl << G4endl;
75 }
76 
77 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
79 {
80  G4cout << G4endl << "###### Calling QweakSimMagneticField::~QweakSimMagneticField() " << G4endl << G4endl;
81 
82  // Delete existing magnetic field
83  if (fField) delete fField;
84 
85  // Delete messenger
87 
88  G4cout << G4endl << "###### Leaving QweakSimMagneticField::~QweakSimMagneticField() " << G4endl << G4endl;
89 }
90 
91 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
92 void QweakSimMagneticField::ReadFieldMap(const G4String& filename)
93 {
94  G4cout << G4endl << "###### Calling QweakSimMagneticField::ReadFieldMap() " << G4endl << G4endl;
95 
96  // Depending on form of filename, read regular/binary field map
97  if (filename.find(".dat") != std::string::npos) {
98  ReadFieldMapText(filename);
99  }
100  if (filename.find(".bin") != std::string::npos) {
101  ReadFieldMapBinary(filename);
102  }
103 
104  // Test new field map
105  G4double point1[4] = {100.0 * cm, 0.0 * cm, 100.0 * cm, 0.0};
106  G4double exact1[3] = {-0.0499845 * kilogauss, 3.28516 * kilogauss, -0.0112704 * kilogauss};
107  TestFieldMap(point1,exact1);
108  G4double point2[4] = {0.0 * cm, 100.0 * cm, 100.0 * cm, 0.0};
109  G4double exact2[3] = {-3.28505 * kilogauss, -0.0030823 * kilogauss, 0.0014373 * kilogauss};
110  TestFieldMap(point2,exact2);
111  G4double point3[4] = {100.0 * cm, 100.0 * cm, 100.0 * cm, 0.0};
112  G4double exact3[3] = {-0.838069 * kilogauss, 0.836675 * kilogauss, 0.00004997 * kilogauss};
113  TestFieldMap(point3,exact3);
114 
115  G4cout << G4endl << "###### Leaving QweakSimMagneticField::ReadFieldMap() " << G4endl << G4endl;
116 }
117 
118 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
119 void QweakSimMagneticField::TestFieldMap(const G4double point[4], const G4double exact[3]) const
120 {
121  // Calculate field value
122  G4cout << "Calculating test field value at cartesian position "
123  << "(" << point[0]/cm << "," << point[1]/cm << "," << point[2]/cm << ") cm "
124  << G4endl;
125  G4double value[3] = {0.0, 0.0, 0.0};
126  GetFieldValue(point,value);
127 
128  // Calculate difference
129  G4double diff[3] = {0.0, 0.0, 0.0};
130  G4double norm = 0.0;
131  for (size_t i = 0; i < 3; i++) {
132  diff[i] = value[i] - exact[i];
133  norm += diff[i] * diff[i];
134  }
135  norm = sqrt(norm);
136 
137  // Output
138  G4cout << " Value = "
139  << "(" << value[0]/kilogauss << ", " << value[1]/kilogauss << ", " << value[2]/kilogauss << ") kG."
140  << G4endl;
141  G4cout << " Exact = "
142  << "(" << exact[0]/kilogauss << ", " << exact[1]/kilogauss << ", " << exact[2]/kilogauss << ") kG."
143  << G4endl;
144  G4cout << " Diff = "
145  << "(" << diff[0]/kilogauss << ", " << diff[1]/kilogauss << ", " << diff[2]/kilogauss << ") kG."
146  << G4endl;
147 
148  // Test difference (0.1 kilogauss is of the order of 2%)
149  if (norm > 0.1 * kilogauss) {
150  G4cerr << "Magnetic field is different from expected value by " << norm/kilogauss << " kG."
151  << G4endl;
152  }
153 }
154 
155 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
156 void QweakSimMagneticField::ReadFieldMapBinary(const G4String& filename)
157 {
158  // Delete old field map
159  if (fField) delete fField;
160 
161  // Create new field map
164 
165  // Set debug level to something reasonable
167 }
168 
169 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
170 void QweakSimMagneticField::ReadFieldMapText(const G4String& filename)
171 {
172  // Delete old field map
173  if (fField) delete fField;
174 
175  // Create new field map
178 
179  // Fill vector of grid min, max, and step size
180  fField->SetDimensions(fMin.size());
181  fField->SetMinimumMaximumStep(fMin,fMax,fStep);
182  fField->SetWrapCoordinate(fWrap);
183 
184  // Debug output
185  G4cout << "Reading field grid: ";
186 
187  // Open the field map file
188  std::ifstream inputfile;
189  inputfile.open(filename);
190  while (inputfile.good()) {
191  // Progress bar
192  if (fField->GetCurrentEntries() % (fField->GetMaximumEntries() / 10) == 0) {
193  int pct = fField->GetCurrentEntries() / (fField->GetMaximumEntries() / 100);
194  G4cout << pct << "%" << std::flush;
195  }
196  if (fField->GetCurrentEntries() % (fField->GetMaximumEntries() / 10) != 0
197  && fField->GetCurrentEntries() % (fField->GetMaximumEntries() / 40) == 0) {
198  G4cout << "." << std::flush;
199  }
200 
201  // Read variables
202  G4double r = 0.0, z = 0.0, phi = 0.0;
203  value_t b[3] = {0.0, 0.0, 0.0};
204  inputfile >> r >> z >> phi >> b[0] >> b[1] >> b[2];
205 
206  // Transform units into Geant4 system of units
207  r *= cm;
208  z *= cm;
209  phi *= degree;
210  b[0] *= kilogauss;
211  b[1] *= kilogauss;
212  b[2] *= kilogauss;
213 
214  // Translation
215  z -= fTranslation;
216 
217  // Rotation
218  phi -= fRotation;
219  if (phi < 0.0 * degree) phi += 360.0 * degree;
220  if (phi > 360.0 * degree) phi -= 360.0 * degree;
221  value_t b_rot[2];
222  b_rot[0] = b[0] * fRotationCos + b[1] * fRotationSin;
223  b_rot[1] = -b[0] * fRotationSin + b[1] * fRotationCos;
224  b[0] = b_rot[0]; b[1] = b_rot[1];
225 
226  // Transform units into fieldmap system of units
227  double coord[3] = { z/cm, r/cm, phi/radian };
228  value_t field[3] = { value_t(b[0]/tesla), value_t(b[1]/tesla), value_t(b[2]/tesla) };
229 
230  // Store into fieldmap
231  fField->Set(coord,field);
232  }
233  G4cout << G4endl;
234 
235  // Close file
236  inputfile.close();
237 
238  // Set debug level to something reasonable
240 }
241 
242 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
243 void QweakSimMagneticField::PrintFieldValue(const G4double point[4]) const
244 {
245  G4double field[3];
246  GetFieldValue(point,field);
247 
248  // Calculate field value
249  G4cout << "Calculating test field value at cartesian position "
250  << "(" << point[0]/cm << "," << point[1]/cm << "," << point[2]/cm << ") cm "
251  << G4endl;
252  G4double value[3] = {0.0, 0.0, 0.0};
253  GetFieldValue(point,value);
254 
255  // Output
256  G4cout << " Value = "
257  << "(" << value[0]/kilogauss << ", " << value[1]/kilogauss << ", " << value[2]/kilogauss << ") kG."
258  << G4endl;
259 }
260 
261 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
262 void QweakSimMagneticField::GetFieldValue(const G4double point[4], G4double *field) const
263 {
264  // Shift by translation vector
265  G4double x = point[0] - fTranslationVector[0];
266  G4double y = point[1] - fTranslationVector[1];
267  G4double z = point[2] - fTranslationVector[2];
268 
269  // Convert from cartesian to cylindrical coordinates
270  G4double r = sqrt(x*x + y*y);
271  G4double phi = atan2(y, x);
272  if (phi < 0.0) phi += 360.0 * degree;
273 
274  // Retrieve field value
275  field[0] = 0.0;
276  field[1] = 0.0;
277  field[2] = 0.0;
278  if (fField) {
279  // Get field value
280  G4double coord[3] = {z/cm, r/cm, phi/radian};
281  fField->GetValue(coord,field);
282 
283  // Units and scale factor
284  field[0] *= fScaleFactor * tesla;
285  field[1] *= fScaleFactor * tesla;
286  field[2] *= fScaleFactor * tesla;
287  }
288 }
289 
290 //....oooOO0OOooo........oooOO0OOooo........oooOO0OOooo........oooOO0OOooo......
291 
292 //=======================================================
293 // -----------------------
294 // | CVS File Information |
295 // -----------------------
296 //
297 // $Revisions$
298 // $Log: QweakSimMagneticField.cc,v $
299 // Revision 1.2 2005/12/27 19:10:21 grimm
300 // - Redesign of Doxygen header containing CVS info like revision and date
301 // - Added CVS revision log at the end of file
302 //
303 //
QweakSimFieldMap< value_t, value_n > * fField
void SetTranslationVector(const G4ThreeVector translationvector)
Set the field translation vector.
void SetTranslation(const double translation)
Set the field translation along z.
QweakSimMagneticFieldMessenger * fMagneticFieldMessenger
Messenger.
void ReadFieldMapText(const G4String &filename)
std::vector< size_t > fWrap
A multi-dimensional grid of values with interpolation methods.
std::vector< double > fMax
void ReadFieldMap(const G4String &filename)
Read the field map.
void GetFieldValue(const G4double point[4], G4double *field) const
Get the field value.
void ReadFieldMapBinary(const G4String &filename)
virtual ~QweakSimMagneticField()
Virtual destructor.
double fRotation
Field rotation and translation with respect to the z axis.
std::vector< double > fMin
Field map grid definitions.
QweakSimMagneticField()
Default constructor.
void SetRotation(const double rotation)
Set the field rotation around z.
double fScaleFactor
Field map reference and actual currents.
void TestFieldMap(const G4double point[4], const G4double exact[3]) const
Test the field map.
std::vector< double > fStep
float value_t
Field map storage data type.
Scans input file for /MagnetField/xyz commands.
void PrintFieldValue(const G4double point[4]) const
Print the field value.