Project
Loading...
Searching...
No Matches
testMagneticField.cxx
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
12#define BOOST_TEST_MODULE Test MagneticField
13#define BOOST_TEST_MAIN
14#define BOOST_TEST_DYN_LINK
15#include <boost/test/unit_test.hpp>
16#include <iostream>
17#include "Field/MagneticField.h"
18#include "Field/MagFieldFast.h"
19#include <memory>
20#include <fairlogger/Logger.h> // for FairLogger
21#include <TFile.h>
22#include <TStopwatch.h>
23#include <TRandom.h>
24
25using namespace o2::field;
26
27BOOST_AUTO_TEST_CASE(MagneticField_test)
28{
29 // create magnetic field
30 std::unique_ptr<MagneticField> fld = std::make_unique<MagneticField>("Maps", "Maps", 1., 1., o2::field::MagFieldParam::k5kG);
31 double bz0 = fld->solenoidField();
32 LOG(info) << "Created default magnetic field for " << bz0 << "kG";
33 const double nomBz = 5.00685;
34 BOOST_CHECK_CLOSE(bz0, nomBz, 0.1);
35
36 const int ntst = 10000;
37 float rnd[3];
38 double xyz[ntst][3] = {}, bxyz[ntst][3] = {}, dummyAcc = 0.;
39 // fill input
40 for (int it = ntst; it--;) {
41 gRandom->RndmArray(3, rnd);
42 xyz[it][0] = rnd[0] * 400. * TMath::Cos(rnd[1] * TMath::Pi() * 2);
43 xyz[it][1] = rnd[1] * 400. * TMath::Sin(rnd[1] * TMath::Pi() * 2);
44 xyz[it][2] = (rnd[0] - 0.5) * 250;
45 }
46
47 const int repFactor = 50;
48 // timing: slow field
49 TStopwatch swSlow;
50 swSlow.Start();
51 for (int ii = repFactor; ii--;) {
52 for (int it = ntst; it--;) {
53 fld->Field(xyz[it], bxyz[it]);
54 }
55 }
56 swSlow.Stop();
57
58 // init fast field
59 fld->AllowFastField(true);
60
61 // timing: fast field
62 TStopwatch swFast;
63 swFast.Start();
64 double bfast[3];
65 for (int ii = repFactor; ii--;) {
66 for (int it = ntst; it--;) {
67 fld->Field(xyz[it], bfast);
68 }
69 }
70 swFast.Stop();
71 //
72 double sS = swSlow.CpuTime() / (ntst * repFactor);
73 double sF = swFast.CpuTime() / (ntst * repFactor);
74 double rat = sF > 0. ? sS / sF : -1;
75 LOG(info) << "Timing: Exact param: " << sS << " Fast param: " << sF
76 << "s/call -> factor " << rat;
77
78 // compare slow/fast param precision
79 double mean[3] = {0.}, rms[3] = {0.};
80 const char comp[] = "XYZ";
81 LOG(info) << "Relative precision of fast field wrt exact field";
82 for (int it = ntst; it--;) {
83 fld->Field(xyz[it], bfast);
84 for (int i = 0; i < 3; i++) {
85 double df = bxyz[it][i] - bfast[i];
86 mean[i] += df;
87 rms[i] += df * df;
88 }
89 }
90 for (int i = 0; i < 3; i++) {
91 mean[i] /= ntst;
92 rms[i] /= ntst;
93 rms[i] -= mean[i] * mean[i];
94 rms[i] = TMath::Sqrt(rms[i]);
95 LOG(info) << "deltaB" << comp[i] << ": "
96 << " mean=" << mean[i] << "(" << mean[i] / nomBz * 100. << "%)"
97 << " RMS =" << rms[i] << "(" << rms[i] / nomBz * 100. << "%)";
98 BOOST_CHECK(TMath::Abs(mean[i] / nomBz) < 1.e-3);
99 BOOST_CHECK(TMath::Abs(rms[i] / nomBz) < 1.e-3);
100 }
101}
102
103BOOST_AUTO_TEST_CASE(MagneticField_reinitialization_test)
104{
105 // The measured map is transient, so a MagneticField read back from a file has to be
106 // re-created before it can be used. That must reproduce the field vectors, not merely
107 // their magnitude: a sign flip leaves |B| untouched.
108 const double points[][3] = {
109 {0., 0., 0.}, // solenoid, on axis
110 {100., 50., 100.}, // solenoid, off axis
111 {10., 10., -900.}, // muon dipole
112 {0., 0., 1000.}, // compensator 1A, side A
113 {0., 0., -2049.}, // compensator 2C, side C
114 {0., 0., 2049.} // compensator 2A, side A
115 };
116 const int npoints = sizeof(points) / sizeof(points[0]);
117 const double tolerance = 1.e-9; // kGauss
118
119 std::unique_ptr<MagneticField> fld = std::make_unique<MagneticField>("Maps", "Maps", 1., 1., MagFieldParam::k5kG);
120 const double facSol = fld->getFactorSolenoid(), facDip = fld->getFactorDipole();
121 double bref[npoints][3] = {};
122 for (int ip = 0; ip < npoints; ip++) {
123 fld->Field(points[ip], bref[ip]);
124 // a point where the field vanishes would make the comparisons below vacuous
125 BOOST_CHECK(TMath::Abs(bref[ip][0]) + TMath::Abs(bref[ip][1]) + TMath::Abs(bref[ip][2]) > tolerance);
126 }
127
128 const char* fname = "testMagneticFieldReinitialization.root";
129 {
130 TFile fout(fname, "recreate");
131 fout.WriteObject(fld.get(), "field");
132 }
133 TFile fin(fname);
134 auto* fldRead = fin.Get<MagneticField>("field");
135 BOOST_REQUIRE(fldRead != nullptr);
136 fldRead->CreateField();
137 BOOST_CHECK_EQUAL(fldRead->getFactorSolenoid(), facSol);
138 BOOST_CHECK_EQUAL(fldRead->getFactorDipole(), facDip);
139 for (int ip = 0; ip < npoints; ip++) {
140 double b[3] = {};
141 fldRead->Field(points[ip], b);
142 for (int i = 0; i < 3; i++) {
143 BOOST_CHECK_SMALL(b[i] - bref[ip][i], tolerance);
144 }
145 }
146}
int32_t i
Definition of the fast magnetic field parametrization MagFieldFast.
Definition of the MagF class.
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
BOOST_AUTO_TEST_CASE(MagneticField_test)
LOG(info)<< "Compressed in "<< sw.CpuTime()<< " s"
BOOST_CHECK(tree)
BOOST_CHECK_EQUAL(triggersD.size(), triggers.size())