16 #include "GaudiKernel/ITHistSvc.h"
17 #include "GaudiKernel/Chrono.h"
20 #include "CLHEP/Vector/ThreeVector.h"
26 #include "G4TransportationManager.hh"
27 #include "G4FieldManager.hh"
45 const double solenoidRadius = 1075.;
46 const double solenoidZhalf = 2820.;
58 ISvcLocator* pSvcLocator) :
60 name), m_thistSvc(
"THistSvc",
name), m_histStream(
61 "MagFieldTestbedAlg"), m_chronoSvc(
"ChronoStatSvc",
name), m_tree(nullptr), m_treeName(
"field"), m_generateBox(false), m_minX(-11999.),
62 m_halfX(11999.), m_halfY(11999.), m_halfZ(22999.), m_stepsX(200), m_stepsY(
63 200), m_stepsZ(200), m_numberOfReadings(0), m_refFile(
""), m_refTreeName(
64 "field"), m_absTolerance(1
e-7), m_relTolerance(0.01), m_xyzt(), m_field(), m_explicitX(
65 0), m_explicitY(0), m_explicitZ(0), m_complete(false), m_useG4Field(
66 false), m_recordReadings(true), m_onlyCheckSolenoid(
67 false), m_coordsAlongBeam(false), m_explicitCoords(false) {
71 "Name of the THistSvc output stream");
75 "Name of the TTree object in the output file.");
86 "Number of steps along x-direction (granularity)");
88 "Number of steps along x-direction (granularity)");
90 "Number of steps along x-direction (granularity)");
94 "Filename of a reference file to compare the output with");
96 "TTree object name in the reference file");
98 "Numerical tolerance when comparing against reference.");
100 "Numerical tolerance when comparing against reference.");
123 if (m_chronoSvc.retrieve().isFailure()) {
125 return StatusCode::FAILURE;
134 if (m_recordReadings || !(m_refFile.empty())) {
136 if (m_thistSvc.retrieve().isSuccess()) {
139 std::string
prefix =
"/" + m_histStream +
"/";
142 m_tree =
new TTree(m_treeName.c_str(),
"Magnetic Field in Atlas");
143 m_tree->Branch(
"pos", &m_xyzt,
"x/D:y/D:z/D");
144 m_tree->Branch(
"field", &m_field,
"fx/D:fy/D:fz/D");
147 if (m_useDerivatives) {
148 m_tree->Branch(
"derivatives", &m_deriv,
149 "d1/D:d2/D:d3/D:d4/D:d5/D:d6/D:d7/D:d8/D:d9/D");
152 if (m_thistSvc->regTree(
prefix + m_treeName, m_tree).isFailure()) {
154 return StatusCode::FAILURE;
159 return StatusCode::FAILURE;
163 m_referenceCount = 0;
167 return StatusCode::SUCCESS;
175 return StatusCode::SUCCESS;
182 if (m_explicitCoords) {
183 if (fetchEnvironment().isFailure()) {
185 return StatusCode::FAILURE;
188 m_xyzt[0] = m_explicitX;
189 m_xyzt[1] = m_explicitY;
190 m_xyzt[2] = m_explicitZ;
194 ATH_MSG_INFO(
"Field Value at: " << m_explicitX <<
", " << m_explicitY <<
", " << m_explicitZ <<
"is: " << m_field[0] <<
", " << m_field[1] <<
", " << m_field[2] );
201 if (fetchEnvironment().isFailure()) {
203 return StatusCode::FAILURE;
206 if (m_refFile.empty()) {
213 std::vector < CLHEP::Hep3Vector > coordinatesToBeChecked;
214 double maxRadius = m_halfX;
215 double maxZ = m_halfZ;
217 if (m_onlyCheckSolenoid) {
218 maxRadius = solenoidRadius;
219 maxZ = solenoidZhalf;
221 if (m_numberOfReadings != 0 && !m_coordsAlongBeam) {
224 if (!m_generateBox) {
226 Chrono chrono(&(*m_chronoSvc),
"MFTBcylGen");
227 for (
long i = 0;
i < m_numberOfReadings;
i++) {
228 CLHEP::Hep3Vector temp;
230 double maxRadius = m_halfX;
231 double maxZ = m_halfZ;
233 if (m_onlyCheckSolenoid) {
234 maxRadius = solenoidRadius;
235 maxZ = solenoidZhalf;
237 temp.setX(ran.Uniform(maxRadius * (-1), maxRadius));
238 temp.setY(ran.Uniform(maxRadius * (-1), maxRadius));
239 temp.setZ(ran.Uniform(maxZ * (-1), maxZ));
243 pow(temp.getX(), 2) +
pow(temp.getY(), 2));
248 coordinatesToBeChecked.push_back(temp);
252 Chrono chrono(&(*m_chronoSvc),
"MFTBboxGen");
253 for (
long i = 0;
i < m_numberOfReadings;
i++) {
254 CLHEP::Hep3Vector temp;
256 double maxRadius = sqrt(
pow(m_halfX, 2) +
pow(m_halfY,2));
257 double maxZ = m_halfZ;
259 if (m_onlyCheckSolenoid) {
260 maxRadius = solenoidRadius;
261 maxZ = solenoidZhalf;
263 temp.setX(ran.Uniform(m_minX, m_halfX));
264 temp.setY(ran.Uniform(m_halfY * (-1), m_halfY));
265 temp.setZ(ran.Uniform(maxZ * (-1), maxZ));
269 pow(temp.getX(), 2) +
pow(temp.getY(), 2));
274 coordinatesToBeChecked.push_back(temp);
279 if (m_coordsAlongBeam) {
282 CLHEP::Hep3Vector temp;
285 for (
long i = 0;
i < m_numberOfReadings;) {
287 phi =
rand.Uniform(3.14 * (-1), 3.14);
289 while (
r < maxRadius) {
295 coordinatesToBeChecked.push_back(temp);
304 if (m_numberOfReadings != 0) {
306 for (
int i = 0;
i < m_numberOfReadings;
i++) {
307 m_xyzt[0] = coordinatesToBeChecked.at(
i).getX();
308 m_xyzt[1] = coordinatesToBeChecked.at(
i).getY();
309 m_xyzt[2] = coordinatesToBeChecked.at(
i).getZ();
313 if (m_recordReadings) {
319 for (
int stepx = 0; stepx < m_stepsX; stepx++) {
320 m_xyzt[0] = -maxRadius + (2 * maxRadius) / m_stepsX * stepx;
323 for (
int stepy = 0; stepy < maxRadius; stepy++) {
324 m_xyzt[1] = -maxRadius
325 + (2 * maxRadius) / maxRadius * stepy;
328 for (
int stepz = 0; stepz < maxZ; stepz++) {
330 m_xyzt[2] = -maxZ + (2 * maxZ) / m_stepsZ * stepz;
336 if (m_recordReadings) {
346 if (m_numberOfReadings != 0) {
348 "the reading of " << m_numberOfReadings
349 <<
" random readings took " <<
seconds
353 "the reading of " << m_stepsX * m_stepsY * m_stepsZ
354 <<
" values in a grid took " <<
seconds
366 "will now run comparison against given reference file: "
368 if (checkWithReference())
369 ATH_MSG_INFO(
"comparison against reference file successful!");
371 ATH_MSG_ERROR(
"comparison against reference file FAILED!!!!");
372 return StatusCode::FAILURE;
380 return StatusCode::SUCCESS;
386 G4TransportationManager *transm =
387 G4TransportationManager::GetTransportationManager();
388 G4FieldManager *fieldm = (transm) ? transm->GetFieldManager() :
nullptr;
389 p_g4field = (fieldm) ? fieldm->GetDetectorField() :
nullptr;
392 return StatusCode::FAILURE;
395 return StatusCode::SUCCESS;
400 p_g4field->GetFieldValue(m_xyzt, m_field);
403 m_magFieldSvc->getField(m_xyzt, m_field,
404 m_useDerivatives ? m_deriv :
nullptr);
406 if (isnan(m_deriv[0]) || isnan(m_deriv[1]) || isnan(m_deriv[2])
407 || isnan(m_deriv[3]) || isnan(m_deriv[4]) || isnan(m_deriv[5])
408 || isnan(m_deriv[6]) || isnan(m_deriv[7]) || isnan(m_deriv[8])) {
410 "at least one Derivative was NaN at: " << m_xyzt[0] <<
", "
411 << m_xyzt[1] <<
", " << m_xyzt[2]);
419 TFile *refF = TFile::Open(m_refFile.c_str());
420 TTree *refT = (refF) ? (TTree*) refF->Get(m_refTreeName.c_str()) :
nullptr;
428 "Unable to read the tree '" << m_refTreeName <<
"'"
429 <<
"from file: " << m_refFile);
433 refT->SetBranchStatus(
"*", 1);
436 for (
int i = 0;
i < 4;
i++)
438 double refField[3] = { 0., 0., 0. };
439 double refDerivatives[9] = { 0., 0., 0., 0., 0., 0., 0., 0., 0. };
441 refT->SetBranchAddress(
"pos", &m_xyzt);
442 refT->SetBranchAddress(
"field", &refField);
443 if (m_useDerivatives) {
444 refT->SetBranchAddress(
"derivatives", &refDerivatives);
448 Long64_t
nentries = refT->GetEntries();
456 m_tree->Branch(
"ReferenceField", &refField,
"x/D:y/D:z/D");
457 m_tree->Branch(
"fieldAbsDiff", &fieldAbsDiff,
"diff/D");
458 m_tree->Branch(
"fieldRelDiff", &fieldRelDiff,
"diff/D");
460 if (m_useDerivatives) {
461 m_tree->Branch(
"ReferenceDerivatives", &refDerivatives,
462 "d1/D:d2/D:d3/D:d4/D:d5/D:d6/D:d7/D:d8/D:d9/D");
473 double biggestAbsDiff = 0.;
474 double biggestRelDiff = 0.;
488 double mFieldTotal = 0;
489 double refFieldTotal = 0;
490 for (
int i = 0;
i < 3;
i++) {
491 mFieldTotal += m_field[
i] * m_field[
i];
492 refFieldTotal += refField[
i] * refField[
i];
494 mFieldTotal = sqrt(mFieldTotal);
495 refFieldTotal = sqrt(refFieldTotal);
497 fieldAbsDiff = fabs(mFieldTotal - refFieldTotal);
498 if (refFieldTotal != 0) {
499 fieldRelDiff = fieldAbsDiff / refFieldTotal;
501 if (m_useDerivatives) {
503 if (fabs((m_deriv[0] - refDerivatives[0]) / refDerivatives[0])
506 (m_deriv[1] - refDerivatives[1])
507 / refDerivatives[1]) > m_relTolerance
509 (m_deriv[2] - refDerivatives[2])
510 / refDerivatives[2]) > m_relTolerance
512 (m_deriv[3] - refDerivatives[3])
513 / refDerivatives[3]) > m_relTolerance
515 (m_deriv[4] - refDerivatives[4])
516 / refDerivatives[4]) > m_relTolerance
518 (m_deriv[5] - refDerivatives[5])
519 / refDerivatives[5]) > m_relTolerance
521 (m_deriv[6] - refDerivatives[6])
522 / refDerivatives[6]) > m_relTolerance
524 (m_deriv[7] - refDerivatives[7])
525 / refDerivatives[7]) > m_relTolerance
527 (m_deriv[8] - refDerivatives[8])
528 / refDerivatives[8]) > m_relTolerance) {
530 "referenceDerivatives 1-9: " << refDerivatives[0]
531 <<
", " << refDerivatives[1] <<
", "
532 << refDerivatives[2] <<
", "
533 << refDerivatives[3] <<
", "
534 << refDerivatives[4] <<
", "
535 << refDerivatives[5] <<
", "
536 << refDerivatives[6] <<
", "
537 << refDerivatives[7] <<
", "
538 << refDerivatives[8]);
540 "derivatives 1-9: " << m_deriv[0] <<
", "
541 << m_deriv[1] <<
", " << m_deriv[2] <<
", "
542 << m_deriv[3] <<
", " << m_deriv[4] <<
", "
543 << m_deriv[5] <<
", " << m_deriv[6] <<
", "
544 << m_deriv[7] <<
", " << m_deriv[8]);
546 "relative differences: "
547 << ((m_deriv[0] - refDerivatives[0])
548 / refDerivatives[0]) <<
", "
549 << ((m_deriv[1] - refDerivatives[1])
550 / refDerivatives[1]) <<
", "
551 << ((m_deriv[2] - refDerivatives[2])
552 / refDerivatives[2]) <<
", "
553 << ((m_deriv[3] - refDerivatives[3])
554 / refDerivatives[3]) <<
", "
555 << ((m_deriv[4] - refDerivatives[4])
556 / refDerivatives[4]) <<
", "
557 << ((m_deriv[5] - refDerivatives[5])
558 / refDerivatives[5]) <<
", "
559 << ((m_deriv[6] - refDerivatives[6])
560 / refDerivatives[6]) <<
", "
561 << ((m_deriv[7] - refDerivatives[7])
562 / refDerivatives[7]) <<
", "
563 << ((m_deriv[8] - refDerivatives[8])
564 / refDerivatives[8]));
566 "coordinates: " << m_xyzt[0] <<
", " << m_xyzt[1]
567 <<
", " << m_xyzt[2]);
575 if (fieldAbsDiff > m_absTolerance && fieldRelDiff > m_relTolerance) {
578 "local reading" << m_field[0] <<
" " << m_field[1] <<
" "
581 "reference reading" << refField[0] <<
" " << refField[1]
582 <<
" " << refField[2]);
584 "coordinates: " << m_xyzt[0] <<
", " << m_xyzt[1] <<
", "
589 if (fieldAbsDiff > biggestAbsDiff) {
590 biggestAbsDiff = fieldAbsDiff;
592 if (fieldRelDiff > biggestRelDiff) {
593 biggestRelDiff = fieldRelDiff;
606 ATH_MSG_INFO(
"number of values unequal: " << m_referenceCount);
610 std::setprecision(20)
611 <<
"1) biggest absolute difference in the mag field comparison: "
612 << biggestAbsDiff <<
" (tolerance: " << m_absTolerance
613 <<
")." <<
endmsg <<
"2) biggest relative difference: "
614 << biggestRelDiff <<
" (tolerance: " << m_relTolerance
615 <<
")" << std::setprecision(-1));