Skip to content

Commit 3802d10

Browse files
authored
Merge pull request #92 from rest-for-physics/jgalan_updates
Fixing argument not being passed by reference. Strongly enhances field computation time!
2 parents 05273f6 + e6b815b commit 3802d10

File tree

4 files changed

+135
-13
lines changed

4 files changed

+135
-13
lines changed

inc/TRestAxionMagneticField.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ class TRestAxionMagneticField : public TRestMetadata {
9595

9696
void LoadMagneticFieldData(MagneticFieldVolume& mVol, std::vector<std::vector<Float_t>> data);
9797

98-
TVector3 GetMagneticVolumeNode(MagneticFieldVolume mVol, TVector3 pos);
98+
TVector3 GetMagneticVolumeNode(size_t id, TVector3 pos);
9999

100100
/// \brief This private method returns true if the magnetic field volumes loaded are the same as
101101
/// the volumes defined.
@@ -161,6 +161,9 @@ class TRestAxionMagneticField : public TRestMetadata {
161161
std::vector<Double_t> GetTransversalComponentAlongPath(TVector3 from, TVector3 to, Double_t dl = 1.,
162162
Int_t Nmax = 0);
163163

164+
std::vector<Double_t> GetComponentAlongPath(Int_t axis, TVector3 from, TVector3 to, Double_t dl = 1.,
165+
Int_t Nmax = 0);
166+
164167
Double_t GetTransversalFieldAverage(TVector3 from, TVector3 to, Double_t dl = 1., Int_t Nmax = 0);
165168

166169
TVector3 GetFieldAverageTransverseVector(TVector3 from, TVector3 to, Double_t dl = 10., Int_t Nmax = 0);
@@ -170,6 +173,8 @@ class TRestAxionMagneticField : public TRestMetadata {
170173

171174
TCanvas* DrawTracks(TVector3 vanishingPoint, Int_t divisions, Int_t volId = 0);
172175

176+
TCanvas* DrawComponents(Int_t volId = 0);
177+
173178
void PrintMetadata();
174179

175180
TRestAxionMagneticField();

macros/REST_Axion_FieldIntegrationTests.C

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@
2121
int REST_Axion_FieldIntegrationTests(Double_t sX = 10, Double_t sY = 10, Double_t sZ = 50, Double_t dm = 0.01,
2222
Double_t tolerance = 0.1, Double_t Ea = 4.2) {
2323
/// Setting up magnetic field and track to evaluate
24-
TRestAxionMagneticField magneticField("fields.rml", "babyIAXO_HD");
24+
TRestAxionMagneticField magneticField("fields.rml", "babyIAXO_2024");
2525

2626
for (size_t n = 0; n < magneticField.GetNumberOfVolumes(); n++)
2727
magneticField.ReMap(n, TVector3(sX, sY, sZ));

src/TRestAxionField.cxx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,7 @@
210210

211211
#include <TComplex.h>
212212
#include <TVectorD.h>
213+
#include <gsl/gsl_errno.h>
213214
#include <gsl/gsl_integration.h>
214215

215216
#include <numeric>
@@ -482,13 +483,17 @@ std::pair<Double_t, Double_t> TRestAxionField::GammaTransmissionFieldMapProbabil
482483
Double_t accuracy,
483484
Int_t num_intervals,
484485
Int_t qawo_levels) {
486+
gsl_set_error_handler_off();
487+
485488
if (!fMagneticField) {
486489
RESTError << "TRestAxionField::GammaTransmissionFieldMapProbability requires a magnetic field map!"
487490
<< RESTendl;
488491
RESTError << "Use TRestAxionField::AssignMagneticField method to assign one" << RESTendl;
489492
return {0.0, 0.0};
490493
}
491494

495+
if (fMagneticField->GetTrackLength() <= 0) return {0.0, 0.0};
496+
492497
double photonMass = 0; // Vacuum
493498
if (fBufferGas) photonMass = fBufferGas->GetPhotonMass(Ea);
494499

@@ -555,8 +560,10 @@ std::pair<Double_t, Double_t> TRestAxionField::ComputeResonanceIntegral(Double_t
555560

556561
auto start = std::chrono::system_clock::now();
557562

558-
gsl_integration_qag(&F, 0, fMagneticField->GetTrackLength(), accuracy, accuracy, num_intervals,
559-
GSL_INTEG_GAUSS61, workspace, &reprob, &rerr);
563+
int status = gsl_integration_qag(&F, 0, fMagneticField->GetTrackLength(), accuracy, accuracy,
564+
num_intervals, GSL_INTEG_GAUSS61, workspace, &reprob, &rerr);
565+
566+
if (status > 0) return {0, status};
560567

561568
auto end = std::chrono::system_clock::now();
562569
auto seconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);
@@ -618,12 +625,19 @@ std::pair<Double_t, Double_t> TRestAxionField::ComputeOffResonanceIntegral(Doubl
618625

619626
gsl_integration_qawo_table* wf =
620627
gsl_integration_qawo_table_alloc(q, fMagneticField->GetTrackLength(), GSL_INTEG_COSINE, qawo_levels);
621-
gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &reprob, &rerr);
628+
int status =
629+
gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &reprob, &rerr);
630+
if (status > 0) {
631+
gsl_integration_qawo_table_free(wf);
632+
return {0, status};
633+
}
622634

623635
gsl_integration_qawo_table_set(wf, q, fMagneticField->GetTrackLength(), GSL_INTEG_SINE);
624-
gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &improb, &imerr);
625-
626-
gsl_integration_qawo_table_free(wf);
636+
status = gsl_integration_qawo(&F, 0, accuracy, accuracy, num_intervals, workspace, wf, &improb, &imerr);
637+
if (status > 0) {
638+
gsl_integration_qawo_table_free(wf);
639+
return {0, status};
640+
}
627641

628642
auto end = std::chrono::system_clock::now();
629643
auto seconds = std::chrono::duration_cast<std::chrono::milliseconds>(end - start);

src/TRestAxionMagneticField.cxx

Lines changed: 108 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -584,6 +584,65 @@ TCanvas* TRestAxionMagneticField::DrawHistogram(TString projection, TString Bcom
584584
return fCanvas;
585585
}
586586

587+
///////////////////////////////////////////////
588+
/// \brief A method that creates a canvas where tracks traversing the magnetic volume
589+
/// are drawm together with their corresponding field intensity profile along the Z-axis.
590+
///
591+
TCanvas* TRestAxionMagneticField::DrawComponents(Int_t volId) {
592+
Int_t divisions = 100;
593+
if (fCanvas != NULL) {
594+
delete fCanvas;
595+
fCanvas = NULL;
596+
}
597+
fCanvas = new TCanvas("fCanvas", "", 1600, 600);
598+
599+
TPad* pad1 = new TPad("pad1", "This is pad1", 0.01, 0.02, 0.99, 0.97);
600+
// pad1->Divide(2, 1);
601+
pad1->Draw();
602+
pad1->cd();
603+
604+
Int_t n = 0;
605+
Double_t genPositionZ = fPositions[volId][2] - fBoundMax[volId].Z() - 2000;
606+
Double_t finalPositionZ = fPositions[volId][2] + fBoundMax[volId].Z() + 2000;
607+
TVector3 position(0, 0, genPositionZ);
608+
TVector3 direction(0, 0, 1);
609+
610+
RESTDebug << RESTendl;
611+
RESTDebug << "Start moving along" << RESTendl;
612+
RESTDebug << "++++++++++++++++++" << RESTendl;
613+
614+
TGraph* fieldGr = new TGraph();
615+
Double_t posZ = fPositions[volId][2] - fBoundMax[volId].Z() - 10;
616+
Double_t delta = fBoundMax[volId][2] * 2. / divisions;
617+
618+
while (posZ <= fPositions[volId][2] + fBoundMax[volId].Z()) {
619+
TVector3 posAlongAxis = TVector3(fPositions[volId][0], fPositions[volId][1], posZ);
620+
621+
position = MoveToPlane(position, direction, TVector3(0, 0, 1), posAlongAxis);
622+
Double_t fieldY = this->GetMagneticField(position).Y();
623+
624+
fieldGr->SetPoint(fieldGr->GetN(), posZ, fieldY);
625+
626+
posZ += delta;
627+
}
628+
629+
fieldGr->SetLineWidth(3);
630+
fieldGr->SetLineColor(38 + n);
631+
fieldGr->GetXaxis()->SetLimits(genPositionZ - 500, finalPositionZ + 500);
632+
fieldGr->GetHistogram()->SetMaximum(2.5);
633+
fieldGr->GetHistogram()->SetMinimum(0);
634+
fieldGr->GetXaxis()->SetTitle("Z [mm]");
635+
fieldGr->GetXaxis()->SetTitleSize(0.05);
636+
fieldGr->GetXaxis()->SetLabelSize(0.05);
637+
fieldGr->GetYaxis()->SetTitle("B [T]");
638+
fieldGr->GetYaxis()->SetTitleOffset(1.3);
639+
fieldGr->GetYaxis()->SetTitleSize(0.05);
640+
fieldGr->GetYaxis()->SetLabelSize(0.05);
641+
fieldGr->Draw("AL");
642+
643+
return fCanvas;
644+
}
645+
587646
///////////////////////////////////////////////
588647
/// \brief A method that creates a canvas where tracks traversing the magnetic volume
589648
/// are drawm together with their corresponding field intensity profile along the Z-axis.
@@ -966,7 +1025,7 @@ TVector3 TRestAxionMagneticField::GetMagneticField(TVector3 pos, Bool_t showWarn
9661025
return TVector3(0, 0, 0);
9671026
} else {
9681027
if (IsFieldConstant(id)) return fConstantField[id];
969-
TVector3 node = GetMagneticVolumeNode(fMagneticFieldVolumes[id], pos);
1028+
TVector3 node = GetMagneticVolumeNode((size_t)id, pos);
9701029
Int_t nX = node.X();
9711030
Int_t nY = node.Y();
9721031
Int_t nZ = node.Z();
@@ -1214,6 +1273,49 @@ std::vector<Double_t> TRestAxionMagneticField::GetTransversalComponentAlongPath(
12141273
return Bt;
12151274
}
12161275

1276+
///////////////////////////////////////////////
1277+
/// \brief It returns a vector describing the magnetic field profile component requested using the `axis`
1278+
/// argument which may take values 0,1,2 for X,Y,Z components. The field profile will be constructed in the
1279+
/// track defined between `from` and `to` positions given by argument.
1280+
///
1281+
/// The differential element `dl` is by default 1mm, but it can be modified through the third argument of
1282+
/// this function.
1283+
///
1284+
/// The maximum number of divisions (unlimited by default) of the output vector can be fixed by the forth
1285+
/// argument. In that case, the differential element `dl` length might be increased to fullfil such
1286+
/// condition.
1287+
///
1288+
std::vector<Double_t> TRestAxionMagneticField::GetComponentAlongPath(Int_t axis, TVector3 from, TVector3 to,
1289+
Double_t dl, Int_t Nmax) {
1290+
std::vector<Double_t> Bt;
1291+
if (axis != 0 && axis != 1 && axis != 2) {
1292+
RESTError << "TRestAxionMagneticField::GetComponentAlongPath. Axis must take values 0,1 or 2"
1293+
<< RESTendl;
1294+
return Bt;
1295+
}
1296+
Double_t length = (to - from).Mag();
1297+
1298+
Double_t diff = dl;
1299+
if (Nmax > 0) {
1300+
if (length / dl > Nmax) {
1301+
diff = length / Nmax;
1302+
RESTWarning << "TRestAxionMagneticField::GetComponentAlongPath. Nmax reached!" << RESTendl;
1303+
RESTWarning << "Nmax = " << Nmax << RESTendl;
1304+
RESTWarning << "Adjusting differential step to : " << diff << " mm" << RESTendl;
1305+
}
1306+
}
1307+
1308+
TVector3 direction = (to - from).Unit();
1309+
1310+
for (Double_t d = 0; d < length; d += diff) {
1311+
if (axis == 0) Bt.push_back(GetMagneticField(from + d * direction).X());
1312+
if (axis == 1) Bt.push_back(GetMagneticField(from + d * direction).Y());
1313+
if (axis == 2) Bt.push_back(GetMagneticField(from + d * direction).Z());
1314+
}
1315+
1316+
return Bt;
1317+
}
1318+
12171319
///////////////////////////////////////////////
12181320
/// \brief It initializes the field track boundaries data members of this class using a
12191321
/// track position and direction so that these values can be used later on in parameterization.
@@ -1225,6 +1327,7 @@ void TRestAxionMagneticField::SetTrack(const TVector3& position, const TVector3&
12251327
fTrackStart = TVector3(0, 0, 0);
12261328
fTrackDirection = TVector3(0, 0, 0);
12271329
fTrackLength = 0;
1330+
return;
12281331
}
12291332

12301333
fTrackStart = trackBounds[0];
@@ -1327,10 +1430,10 @@ TVector3 TRestAxionMagneticField::GetFieldAverageTransverseVector(TVector3 from,
13271430
///
13281431
/// This method will be made private, no reason to use it outside this class.
13291432
///
1330-
TVector3 TRestAxionMagneticField::GetMagneticVolumeNode(MagneticFieldVolume mVol, TVector3 pos) {
1331-
Int_t nx = mVol.mesh.GetNodeX(pos.X());
1332-
Int_t ny = mVol.mesh.GetNodeY(pos.Y());
1333-
Int_t nz = mVol.mesh.GetNodeZ(pos.Z());
1433+
TVector3 TRestAxionMagneticField::GetMagneticVolumeNode(size_t id, TVector3 pos) {
1434+
Int_t nx = fMagneticFieldVolumes[id].mesh.GetNodeX(pos.X());
1435+
Int_t ny = fMagneticFieldVolumes[id].mesh.GetNodeY(pos.Y());
1436+
Int_t nz = fMagneticFieldVolumes[id].mesh.GetNodeZ(pos.Z());
13341437
return TVector3(nx, ny, nz);
13351438
}
13361439

0 commit comments

Comments
 (0)