Skip to content

Commit 514d1ed

Browse files
committed
merge
2 parents a4b90c3 + 507a6f0 commit 514d1ed

141 files changed

Lines changed: 5449 additions & 1262 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,3 +90,9 @@ bazel-*
9090
DataFormats/Detectors/CTP/include/DataFormatsCTP/Scalers.h
9191
dpl-config.json
9292
O2.code-workspace
93+
94+
# Python bytecode
95+
*.pyc
96+
97+
# Claude code
98+
.claude/settings.local.json

Common/Field/src/MagFieldFast.cxx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -61,8 +61,11 @@ MagFieldFast::MagFieldFast(float factor, int nomField, const string inpFmt) : mF
6161
bool MagFieldFast::LoadData(const string inpFName)
6262
{
6363
// load field from text file
64-
65-
std::ifstream in(gSystem->ExpandPathName(inpFName.data()), std::ifstream::in);
64+
TString sName(inpFName);
65+
if (gSystem->ExpandPathName(sName)) {
66+
LOG(fatal) << "Failed to expand file name " << inpFName;
67+
}
68+
std::ifstream in(sName.Data(), std::ifstream::in);
6669
if (in.fail()) {
6770
LOG(fatal) << "Failed to open file " << inpFName;
6871
return false;

Common/Field/src/MagneticField.cxx

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,10 @@
1414
/// \author ruben.shahoyan@cern.ch
1515

1616
#include "Field/MagneticField.h"
17-
#include <TFile.h> // for TFile
18-
#include <TPRegexp.h> // for TPRegexp
19-
#include <TSystem.h> // for TSystem, gSystem
17+
#include <TFile.h> // for TFile
18+
#include <TPRegexp.h> // for TPRegexp
19+
#include <TString.h> // for TString
20+
#include <TSystem.h> // for TSystem, gSystem
2021
#include <fairlogger/Logger.h> // for FairLogger
2122
#include "FairParamList.h"
2223
#include "FairRun.h"
@@ -242,7 +243,8 @@ Bool_t MagneticField::loadParameterization()
242243
LOG(fatal) << "MagneticField::loadParameterization: Field data " << getParameterName()
243244
<< " are already loaded from " << getDataFileName() << "\n";
244245
}
245-
const char* fname = gSystem->ExpandPathName(getDataFileName());
246+
TString fname = getDataFileName();
247+
gSystem->ExpandPathName(fname);
246248
TFile* file = TFile::Open(fname);
247249
if (!file) {
248250
LOG(fatal) << "MagneticField::loadParameterization: Failed to open magnetic field data file " << fname << "\n";

Common/MathUtils/CMakeLists.txt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,13 @@ o2_add_test(
5757
PUBLIC_LINK_LIBRARIES O2::MathUtils
5858
LABELS utils)
5959

60+
o2_add_test(
61+
Chebyshev3D
62+
SOURCES test/testChebyshev3D.cxx
63+
COMPONENT_NAME MathUtils
64+
PUBLIC_LINK_LIBRARIES O2::MathUtils
65+
LABELS utils)
66+
6067
o2_add_test(
6168
Utils
6269
SOURCES test/testUtils.cxx

Common/MathUtils/include/MathUtils/Chebyshev3DCalc.h

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818

1919
#include <TNamed.h> // for TNamed
2020
#include <cstdio> // for FILE, stdout
21+
#include <cmath> // for std::fma
2122
#include "Rtypes.h" // for Float_t, UShort_t, Int_t, Double_t, etc
2223

2324
class TString;
@@ -208,9 +209,14 @@ inline Float_t Chebyshev3DCalc::chebyshevEvaluation1D(Float_t x, const Float_t*
208209
for (int i = ncf; i--;) {
209210
b2 = b1;
210211
b1 = b0;
211-
b0 = array[i] + x2 * b1 - b2;
212+
// Clenshaw recurrence, grouped as fma(x2, b1, array[i] - b2). Mathematically
213+
// identical to `array[i] + x2 * b1 - b2`, but `array[i] - b2` does not depend
214+
// on the just-updated b1, so the loop-carried chain collapses to a single FMA
215+
// latency instead of a dependent multiply+add+subtract. This kernel dominates
216+
// magnetic-field evaluation in (e.g.) muon track extrapolation.
217+
b0 = std::fma(x2, b1, array[i] - b2);
212218
}
213-
return b0 - x * b1;
219+
return std::fma(-x, b1, b0);
214220
}
215221

216222
/// Evaluates Chebyshev parameterization for 3D function.

Common/MathUtils/include/MathUtils/Utils.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -210,12 +210,12 @@ inline double angle2Alphad(double phi)
210210
return detail::angle2Alpha<double>(phi);
211211
}
212212

213-
GPUhdi() float fastATan2(float y, float x)
213+
GPUhdi() constexpr float fastATan2(float y, float x)
214214
{
215215
return detail::fastATan2<float>(y, x);
216216
}
217217

218-
GPUhdi() double fastATan2d(double y, double x)
218+
GPUhdi() constexpr double fastATan2d(double y, double x)
219219
{
220220
return detail::fastATan2<double>(y, x);
221221
}

Common/MathUtils/include/MathUtils/detail/basicMath.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ namespace detail
3434
{
3535

3636
template <typename T>
37-
GPUhdi() T copysign(T x, T y)
37+
GPUhdi() constexpr T copysign(T x, T y)
3838
{
3939
return o2::gpu::GPUCommonMath::Copysign(x, y);
4040
}

Common/MathUtils/include/MathUtils/detail/trigonometric.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,7 @@ GPUhdi() constexpr T deltaPhiSmall(T phi0, T phi1)
269269
}
270270

271271
template <typename T>
272-
GPUhdi() T fastATan2(T y, T x)
272+
GPUhdi() constexpr T fastATan2(T y, T x)
273273
{
274274
// Fast atan2(y,x) for any angle [-Pi,Pi]
275275
// Average inaccuracy: 0.00048
@@ -283,7 +283,7 @@ GPUhdi() T fastATan2(T y, T x)
283283
// https://stackoverflow.com/questions/42537957/fast-accurate-atan-arctan-approximation-algorithm
284284
constexpr T A = 0.0776509570923569;
285285
constexpr T B = -0.287434475393028;
286-
constexpr T C = (Pi / 4 - A - B);
286+
constexpr T C = ((Pi / 4) - A - B);
287287
const T a2 = a * a;
288288
return ((A * a2 + B) * a2 + C) * a;
289289
};
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
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+
/// \file testChebyshev3D.cxx
13+
/// \brief Accuracy of the Chebyshev3D evaluation kernel.
14+
///
15+
/// Guards `Chebyshev3DCalc::Eval` / `chebyshevEvaluation1D` (the Clenshaw
16+
/// recurrence that dominates magnetic-field evaluation in track extrapolation).
17+
/// We build an in-memory parameterization of a known smooth function and check
18+
/// that `Eval` reproduces it to the requested precision over many random points,
19+
/// and that the per-dimension and double-precision overloads agree with the
20+
/// float vector overload. Any breakage of the recurrence (e.g. a wrong FMA
21+
/// regrouping) makes the reproduction error explode and fails the test.
22+
23+
#define BOOST_TEST_MODULE Test Chebyshev3D
24+
#define BOOST_TEST_MAIN
25+
#define BOOST_TEST_DYN_LINK
26+
#include <boost/test/unit_test.hpp>
27+
#include <cmath>
28+
#include <random>
29+
#include "MathUtils/Chebyshev3D.h"
30+
31+
using o2::math_utils::Chebyshev3D;
32+
33+
namespace
34+
{
35+
// A smooth, low-degree (≤3 per variable) vector function over the fit box, of
36+
// the kind a Chebyshev parameterization reproduces to ~float precision. Stands
37+
// in for a slowly-varying magnetic field B(x,y,z).
38+
void referenceField(float* in, float* out)
39+
{
40+
const float x = in[0], y = in[1], z = in[2];
41+
out[0] = 0.50f + 0.020f * x - 1.0e-4f * x * y + 3.0e-3f * z - 2.0e-6f * x * x * z;
42+
out[1] = -0.30f + 0.015f * y + 5.0e-5f * y * z - 1.0e-3f * x;
43+
out[2] = 5.00f - 4.0e-4f * x * x + 6.0e-4f * y * y + 1.0e-3f * x * y - 2.0e-6f * x * y * z;
44+
}
45+
} // namespace
46+
47+
BOOST_AUTO_TEST_CASE(Chebyshev3D_eval_accuracy)
48+
{
49+
const Float_t bmin[3] = {-40.f, -40.f, -200.f};
50+
const Float_t bmax[3] = {40.f, 40.f, 200.f};
51+
const Int_t np[3] = {7, 7, 7}; // > polynomial degree in every dimension
52+
const Float_t fitPrec = 1.0e-5f;
53+
54+
Chebyshev3D cheb(referenceField, 3, bmin, bmax, np, fitPrec);
55+
56+
// Deterministic interior sampling (fixed seed -> no flakiness). Stay a hair
57+
// inside the box so we never hit the boundary-clamping branch.
58+
std::mt19937 rng(20260604u);
59+
std::uniform_real_distribution<float> ux(bmin[0] + 1.f, bmax[0] - 1.f);
60+
std::uniform_real_distribution<float> uy(bmin[1] + 1.f, bmax[1] - 1.f);
61+
std::uniform_real_distribution<float> uz(bmin[2] + 1.f, bmax[2] - 1.f);
62+
63+
float maxAbsErr = 0.f; // |cheb - reference| (kernel reproduces the function)
64+
float maxDimMismatch = 0.f; // |vector overload - per-dim overload|
65+
float maxDoubleMismatch = 0.f; // |float overload - double overload|
66+
67+
for (int i = 0; i < 20000; ++i) {
68+
float par[3] = {ux(rng), uy(rng), uz(rng)};
69+
float ref[3];
70+
referenceField(par, ref);
71+
72+
float res[3];
73+
cheb.Eval(par, res);
74+
75+
double pard[3] = {par[0], par[1], par[2]};
76+
double resd[3];
77+
cheb.Eval(pard, resd);
78+
79+
for (int d = 0; d < 3; ++d) {
80+
BOOST_REQUIRE(std::isfinite(res[d]));
81+
maxAbsErr = std::max(maxAbsErr, std::abs(res[d] - ref[d]));
82+
// Single-component overload must match the vector overload (same kernel).
83+
maxDimMismatch = std::max(maxDimMismatch, std::abs(res[d] - cheb.Eval(par, d)));
84+
// Double overload differs only by intermediate precision.
85+
maxDoubleMismatch = std::max(maxDoubleMismatch, std::abs(static_cast<float>(resd[d]) - res[d]));
86+
}
87+
}
88+
89+
BOOST_TEST_MESSAGE("Chebyshev3D max |eval - reference| = " << maxAbsErr);
90+
BOOST_TEST_MESSAGE("Chebyshev3D max vector-vs-perdim = " << maxDimMismatch);
91+
BOOST_TEST_MESSAGE("Chebyshev3D max float-vs-double = " << maxDoubleMismatch);
92+
93+
// Reproduction of the known function: fit precision (1e-5) plus a little float
94+
// slack from the three nested Clenshaw sums (observed ~1.4e-6). A broken
95+
// recurrence misses this by orders of magnitude (coefficient-scale error / NaN).
96+
BOOST_CHECK_SMALL(maxAbsErr, 1.0e-4f);
97+
// The two float entry points share the kernel: expect bit-for-bit agreement.
98+
BOOST_CHECK_SMALL(maxDimMismatch, 1.0e-6f);
99+
// float vs double evaluation of the same coefficients: within float epsilon.
100+
BOOST_CHECK_SMALL(maxDoubleMismatch, 1.0e-3f);
101+
}

Common/SimConfig/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ o2_add_library(SimConfig
2020
src/MatMapParams.cxx
2121
src/InteractionDiamondParam.cxx
2222
src/GlobalProcessCutSimParam.cxx
23+
src/FluenceWeightCalculator.cxx
2324
PUBLIC_LINK_LIBRARIES O2::CommonUtils
2425
O2::DetectorsCommonDataFormats O2::SimulationDataFormat
2526
FairRoot::Base Boost::program_options)
@@ -35,7 +36,8 @@ o2_target_root_dictionary(SimConfig
3536
include/SimConfig/G4Params.h
3637
include/SimConfig/DetectorLists.h
3738
include/SimConfig/GlobalProcessCutSimParam.h
38-
include/SimConfig/MatMapParams.h)
39+
include/SimConfig/MatMapParams.h
40+
include/SimConfig/FluenceWeightCalculator.h)
3941

4042
o2_add_test(Config
4143
SOURCES test/TestConfig.cxx

0 commit comments

Comments
 (0)