From 0e0872decf34f1a939e77c4faac245d726d9263e Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 13:26:00 -0500 Subject: [PATCH 01/25] Shift lumi system closer to IP due to proximity with electron CRAB magnet. --- compact/far_backward/definitions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compact/far_backward/definitions.xml b/compact/far_backward/definitions.xml index 85bb3686f..2b3823ed1 100644 --- a/compact/far_backward/definitions.xml +++ b/compact/far_backward/definitions.xml @@ -251,7 +251,7 @@ - + From 31e1e3df64699fdfe042a9e7b58e427231d93525 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 13:30:27 -0500 Subject: [PATCH 02/25] new B mapping code, which can handle R-Z and X-Y-Z coordinate systems. Implement lumi dipole B maps. --- compact/far_backward/lumi/lumi_magnets.xml | 36 +- compact/fields/marco.xml | 6 +- src/FieldMapB.cpp | 365 +++++++++++++++++++++ src/FieldMapBrBz.cpp | 246 -------------- 4 files changed, 403 insertions(+), 250 deletions(-) create mode 100644 src/FieldMapB.cpp delete mode 100644 src/FieldMapBrBz.cpp diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 7a277e79b..20dee0f4e 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -77,7 +77,10 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. Detailed field map to be inserted later. + + + + + Calculated fields + + + + + + + + + + + + + + + + + + + + diff --git a/compact/fields/marco.xml b/compact/fields/marco.xml index f5df7e8ee..704513058 100644 --- a/compact/fields/marco.xml +++ b/compact/fields/marco.xml @@ -3,14 +3,14 @@ - - - + + diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp new file mode 100644 index 000000000..5fa40b880 --- /dev/null +++ b/src/FieldMapB.cpp @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2023 Wouter Deconinck, Dhevan Gangadharan, Aranya Giri + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +namespace fs = std::filesystem; + +#include "FileLoaderHelper.h" + +using namespace dd4hep; + +// Two coordinate options: +// coord_type="BrBz" +// expected fields contained within : +// +// +// coord_type="BxByBz" +// expected fields contained within : +// +// +// + +// In DD4hep 1.26, the name for the `field_type` enum changed (from `type`). +#if DD4HEP_VERSION_GE(1, 26) +#define DD4HEP_FIELD_TYPE field_type +#else +#define DD4HEP_FIELD_TYPE type +#endif + +// This allows us to specify the name of the variable by hand, when patching +// the previous versions, by setting `DD4HEP_FIELD_TYPE_OVERRIDE`. +// TODO remove after DD4hep 1.26 release +#define XSTR(x) STR(x) +#define STR(x) #x +#ifdef DD4HEP_FIELD_TYPE_OVERRIDE +#undef DD4HEP_FIELD_TYPE +#define DD4HEP_FIELD_TYPE DD4HEP_FIELD_TYPE_OVERRIDE +#pragma message("DD4HEP_FIELD_TYPE overridden as " XSTR(DD4HEP_FIELD_TYPE)) +#endif +#pragma message("DD4HEP_FIELD_TYPE is " XSTR(DD4HEP_FIELD_TYPE)) + +// implementation of the field map +class FieldMapB : public dd4hep::CartesianField::Object { +public: + FieldMapB(const std::string& field_type_str = "magnetic", const std::string& coord_type_str = "BrBz"); + void Configure(std::vector dimensions); + void LoadMap(const std::string& map_file, double scale); + void GetIndices(std::vector coord, std::vector *indices, std::vector *deltas); + void SetTransform(const Transform3D& tr) + { + trans = tr; + trans_inv = tr.Inverse(); + } + + virtual void fieldComponents(const double* pos, double* field); + +private: + std::string coord_type; + Transform3D trans, trans_inv; + std::vector steps, mins, maxs; + std::vector>> Bvals_RZ; // {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // {X}, {Y}, {Z}, {Bx,By,Bz} +}; + +// constructor +FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord_type_str) +{ + std::string ftype = field_type_str; + for (auto& c : ftype) { + c = tolower(c); + } + + // set type + if (ftype == "magnetic") { + DD4HEP_FIELD_TYPE = CartesianField::MAGNETIC; + } else if (ftype == "electric") { + DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; + } else { + DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; + std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; + } + + coord_type = coord_type_str; +} + +// fill field vector +void FieldMapB::Configure(std::vector dimensions) +{ + // Fill vectors with step size, min, max for each dimension + for( auto el : dimensions ) { + steps.push_back( el.step() ); + mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); + maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); + } + + if( coord_type.compare("BrBz") == 0 ) { + int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; + int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; + + Bvals_RZ.resize(nr); + for (auto& B2 : Bvals_RZ) { + B2.resize(nz); + for (auto& B : B2) { + B.resize(2, 0.); // Br, Bz + } + } + } + + if( coord_type.compare("BxByBz") == 0 ) { + int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; + int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; + int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; + + Bvals_XYZ.resize(nx); + for (auto& B3 : Bvals_XYZ) { + B3.resize(ny); + for (auto& B2 : B3) { + B2.resize(nz); + for (auto& B : B2) { + B.resize(3, 0.); // Bx, By, Bz + } + } + } + } +} + +// get cell indices corresponding to point of interest +void FieldMapB::GetIndices(std::vector coord, std::vector *indices, std::vector *deltas) +{ + for( uint i = 0; i < coord.size(); i++ ) { + // Range check + if( coord[i] < mins[i] || coord[i] > maxs[i] ) { + indices->clear(); + indices->resize( coord.size(), -1 ); + return; + } + + double temp_idx; + deltas->push_back( std::modf( (coord[i] - mins[i]) / steps[i], &temp_idx ) ); + indices->push_back( static_cast(temp_idx) ); + } +} + +// load data +void FieldMapB::LoadMap(const std::string& map_file, double scale) +{ + std::string line; + std::ifstream input(map_file); + if (!input) { + std::cout << "FieldMapB Error: file \"" << map_file << "\" cannot be read." << std::endl; + } + + std::vector coord = {}; + std::vector Bcomp = {}; + std::vector indices = {}; + std::vector deltas = {}; + + while (std::getline(input, line).good()) { + std::istringstream iss(line); + + coord.clear(); + Bcomp.clear(); + indices.clear(); + deltas.clear(); + + if( coord_type.compare("BrBz") == 0 ) { + coord.resize(2); + Bcomp.resize(2); + iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; + } + if( coord_type.compare("BxByBz") == 0 ) { + coord.resize(3); + Bcomp.resize(3); + iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; + } + + GetIndices(coord, &indices, &deltas); + + if (std::count( indices.begin(), indices.end(), -1)) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it." + << std::endl; + } else { + if( coord_type.compare("BrBz") == 0 ) { + Bvals_RZ[ indices[0] ][ indices[1] ] = {Bcomp[0] * scale, Bcomp[1] * scale}; + //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); + //std::cout << p << " -> " << trans*p << std::endl; + //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + } + if( coord_type.compare("BxByBz") == 0 ) { + Bvals_XYZ[ indices[0] ][ indices[1] ][ indices[2] ] = {Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale}; + } + } + } +} + +// get field components +void FieldMapB::fieldComponents(const double* pos, double* field) +{ + // coordinate conversion + auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); + + std::vector indices = {}; + std::vector deltas = {}; + ROOT::Math::XYZPoint B = ROOT::Math::XYZPoint(0,0,0); + + if( coord_type.compare("BrBz") == 0 ) { + // coordinates conversion + const double r = sqrt(p.x() * p.x() + p.y() * p.y()); + const double z = p.z(); + const double phi = atan2(p.y(), p.x()); + + GetIndices({r, z}, &indices, &deltas); + + // out of the range + if (std::count( indices.begin(), indices.end(), -1)) { + return; + } + + // p1 p3 + // p + // p0 p2 + auto& p0 = Bvals_RZ[indices[0]][indices[1]]; + auto& p1 = Bvals_RZ[indices[0]][indices[1] + 1]; + auto& p2 = Bvals_RZ[indices[0] + 1][indices[1]]; + auto& p3 = Bvals_RZ[indices[0] + 1][indices[1] + 1]; + + // Bilinear interpolation + double Br = p0[0] * (1 - deltas[0]) * (1 - deltas[1]) + + p1[0] * (1 - deltas[0]) * deltas[1] + + p2[0] * deltas[0] * (1 - deltas[1]) + + p3[0] * deltas[0] * deltas[1]; + + double Bz = p0[1] * (1 - deltas[0]) * (1 - deltas[1]) + + p1[1] * (1 - deltas[0]) * deltas[1] + + p2[1] * deltas[0] * (1 - deltas[1]) + + p3[1] * deltas[0] * deltas[1]; + + // convert Br Bz to Bx By Bz + B = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + B = trans * B; + } + + if( coord_type.compare("BxByBz") == 0 ) { + + GetIndices({p.x(), p.y(), p.z()}, &indices, &deltas); + + // out of the range + if (std::count( indices.begin(), indices.end(), -1)) { + return; + } + + for(int comp = 0; comp < 3; comp++) { // field component loop + // Trilinear interpolation + // First along X, along 4 lines + double b00 = Bvals_XYZ[indices[0]][indices[1]][indices[2]][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2]][comp] * deltas[0]; + double b01 = Bvals_XYZ[indices[0]][indices[1]][indices[2] + 1][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2] + 1][comp] * deltas[0]; + double b10 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2]][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2]][comp] * deltas[0]; + double b11 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2] + 1][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2] + 1][comp] * deltas[0]; + //// Next along Y, along 2 lines + double b0 = b00 * (1 - deltas[1]) + b10 * deltas[1]; + double b1 = b01 * (1 - deltas[1]) + b11 * deltas[1]; + //// Finally along Z + double b = b0 * (1 - deltas[2]) + b1 * deltas[2]; + if(comp == 0) { B.SetX( b ); } + if(comp == 1) { B.SetY( b ); } + if(comp == 2) { B.SetZ( b ); } + } + } + + field[0] += B.x() * tesla; + field[1] += B.y() * tesla; + field[2] += B.z() * tesla; + + return; +} + +// assign the field map to CartesianField +static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) +{ + xml_comp_t x_par(handle); + + if (!x_par.hasAttr(_Unicode(field_map))) { + throw std::runtime_error("FieldMapB Error: must have an xml attribute \"field_map\" for the field map."); + } + + CartesianField field; + std::string field_type = x_par.attr(_Unicode(field_type)); + + // coordinate type: "BrBz" or "BxByBz" + std::string coord_type = x_par.attr(_Unicode(coord_type)); + + // dimensions + xml_comp_t x_dim = x_par.dimensions(); + + // vector of dimension parameters: step, min, max + std::vector dimensions; + + if( coord_type.compare("BrBz") == 0 ) { + dimensions.push_back( x_dim.child(_Unicode(R)) ); + dimensions.push_back( x_dim.child(_Unicode(Z)) ); + } + else if( coord_type.compare("BxByBz") == 0 ) { + dimensions.push_back( x_dim.child(_Unicode(X)) ); + dimensions.push_back( x_dim.child(_Unicode(Y)) ); + dimensions.push_back( x_dim.child(_Unicode(Z)) ); + } + else { + printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); + std::_Exit(EXIT_FAILURE); + } + + std::string field_map_file = x_par.attr(_Unicode(field_map)); + std::string field_map_url = x_par.attr(_Unicode(url)); + std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); + + EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); + + double field_map_scale = x_par.attr(_Unicode(scale)); + + if (!fs::exists(fs::path(field_map_file))) { + printout(ERROR, "FieldMapB", "file " + field_map_file + " does not exist"); + printout(ERROR, "FieldMapB", "use a FileLoader plugin before the field element"); + std::_Exit(EXIT_FAILURE); + } + + auto map = new FieldMapB(field_type, coord_type); + map->Configure( dimensions ); + + // translation, rotation + static double deg2r = ROOT::Math::Pi() / 180.; + RotationZYX rot(0., 0., 0.); + if (x_dim.hasChild(_Unicode(rotation))) { + xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); + rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); + } + + Translation3D trans(0., 0., 0.); + if (x_dim.hasChild(_Unicode(translation))) { + xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); + trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); + } + map->SetTransform(trans * rot); + + map->LoadMap(field_map_file, field_map_scale); + field.assign(map, x_par.nameStr(), "FieldMapB"); + + return field; +} + +DECLARE_XMLELEMENT(epic_FieldMapB, create_field_map_b) diff --git a/src/FieldMapBrBz.cpp b/src/FieldMapBrBz.cpp deleted file mode 100644 index 7b53a554d..000000000 --- a/src/FieldMapBrBz.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -namespace fs = std::filesystem; - -#include "FileLoaderHelper.h" - -using namespace dd4hep; - -// In DD4hep 1.26, the name for the `field_type` enum changed (from `type`). -#if DD4HEP_VERSION_GE(1, 26) -#define DD4HEP_FIELD_TYPE field_type -#else -#define DD4HEP_FIELD_TYPE type -#endif - -// This allows us to specify the name of the variable by hand, when patching -// the previous versions, by setting `DD4HEP_FIELD_TYPE_OVERRIDE`. -// TODO remove after DD4hep 1.26 release -#define XSTR(x) STR(x) -#define STR(x) #x -#ifdef DD4HEP_FIELD_TYPE_OVERRIDE -#undef DD4HEP_FIELD_TYPE -#define DD4HEP_FIELD_TYPE DD4HEP_FIELD_TYPE_OVERRIDE -#pragma message("DD4HEP_FIELD_TYPE overridden as " XSTR(DD4HEP_FIELD_TYPE)) -#endif -#pragma message("DD4HEP_FIELD_TYPE is " XSTR(DD4HEP_FIELD_TYPE)) - -// implementation of the field map -class FieldMapBrBz : public dd4hep::CartesianField::Object { -public: - FieldMapBrBz(const std::string& field_type_str = "magnetic"); - void Configure(double rmin, double rmax, double rstep, double zmin, double zmax, double zstep); - void LoadMap(const std::string& map_file, double scale); - void GetIndices(double r, double z, int& ir, int& iz, double& dr, double& dz); - void SetTransform(const Transform3D& tr) - { - trans = tr; - trans_inv = tr.Inverse(); - } - - virtual void fieldComponents(const double* pos, double* field); - -private: - Transform3D trans, trans_inv; - double rmin, rmax, rstep, zmin, zmax, zstep; - std::vector>> Bvals; -}; - -// constructor -FieldMapBrBz::FieldMapBrBz(const std::string& field_type_str) -{ - std::string ftype = field_type_str; - for (auto& c : ftype) { - c = tolower(c); - } - - // set type - if (ftype == "magnetic") { - DD4HEP_FIELD_TYPE = CartesianField::MAGNETIC; - } else if (ftype == "electric") { - DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; - } else { - DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; - std::cout << "FieldMapBrBz Warning: Unknown field type " << field_type_str << "!" << std::endl; - } -} - -void FieldMapBrBz::Configure(double r1, double r2, double rs, double z1, double z2, double zs) -{ - rmin = r1; - rmax = r2; - rstep = rs; - zmin = z1; - zmax = z2; - zstep = zs; - - int nr = int((r2 - r1) / rs) + 2; - int nz = int((z2 - z1) / zs) + 2; - - Bvals.resize(nr); - for (auto& B2 : Bvals) { - B2.resize(nz); - for (auto& B : B2) { - B.resize(2, 0.); - } - } -} - -void FieldMapBrBz::GetIndices(double r, double z, int& ir, int& iz, double& dr, double& dz) -{ - // boundary check - if (r > rmax || r < rmin || z > zmax || z < zmin) { - ir = -1; - iz = -1; - return; - } - // get indices - double idr, idz; - dr = std::modf((r - rmin) / rstep, &idr); - dz = std::modf((z - zmin) / zstep, &idz); - - ir = static_cast(idr); - iz = static_cast(idz); -} - -// load data -void FieldMapBrBz::LoadMap(const std::string& map_file, double scale) -{ - std::string line; - std::ifstream input(map_file); - if (!input) { - std::cout << "FieldMapBrBz Error: file \"" << map_file << "\" cannot be read." << std::endl; - } - - double r, z, br, bz; - int ir, iz; - double dr, dz; - while (std::getline(input, line).good()) { - std::istringstream iss(line); - iss >> r >> z >> br >> bz; - GetIndices(r, z, ir, iz, dr, dz); - if (ir < 0 || iz < 0) { - std::cout << "FieldMapBrBz Warning: coordinates out of range (" << r << ", " << z << "), skipped it." - << std::endl; - } else { - Bvals[ir][iz] = {br * scale, bz * scale}; - // ROOT::Math::XYZPoint p(r, 0, z); - // std::cout << p << " -> " << trans*p << std::endl; - // std::cout << ir << ", " << iz << ", " << br << ", " << bz << std::endl; - } - } -} - -// get field components -void FieldMapBrBz::fieldComponents(const double* pos, double* field) -{ - // coordinate conversion - auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - - // coordinates conversion - const double r = sqrt(p.x() * p.x() + p.y() * p.y()); - const double z = p.z(); - const double phi = atan2(p.y(), p.x()); - - int ir, iz; - double dr, dz; - GetIndices(r, z, ir, iz, dr, dz); - - // out of the range - if (ir < 0 || iz < 0) { - return; - } - - // p1 p3 - // p - // p0 p2 - auto& p0 = Bvals[ir][iz]; - auto& p1 = Bvals[ir][iz + 1]; - auto& p2 = Bvals[ir + 1][iz]; - auto& p3 = Bvals[ir + 1][iz + 1]; - - // linear interpolation - double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - - double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; - - // convert Br Bz to Bx By Bz - auto B = trans * ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); - field[0] += B.x() * tesla; - field[1] += B.y() * tesla; - field[2] += B.z() * tesla; - return; -} - -// assign the field map to CartesianField -static Ref_t create_field_map_brbz(Detector& /*lcdd*/, xml::Handle_t handle) -{ - xml_comp_t x_par(handle); - - if (!x_par.hasAttr(_Unicode(field_map))) { - throw std::runtime_error("FieldMapBrBz Error: must have an xml attribute \"field_map\" for the field map."); - } - - CartesianField field; - std::string field_type = x_par.attr(_Unicode(field_type)); - - // dimensions - xml_comp_t x_dim = x_par.dimensions(); - - // min, max, step - xml_comp_t r_dim = x_dim.child(_Unicode(transverse)); - xml_comp_t z_dim = x_dim.child(_Unicode(longitudinal)); - - std::string field_map_file = x_par.attr(_Unicode(field_map)); - std::string field_map_url = x_par.attr(_Unicode(url)); - std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); - - EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); - - double field_map_scale = x_par.attr(_Unicode(scale)); - - if (!fs::exists(fs::path(field_map_file))) { - printout(ERROR, "FieldMapBrBz", "file " + field_map_file + " does not exist"); - printout(ERROR, "FieldMapBrBz", "use a FileLoader plugin before the field element"); - std::_Exit(EXIT_FAILURE); - } - - auto map = new FieldMapBrBz(field_type); - map->Configure(r_dim.rmin(), r_dim.rmax(), r_dim.step(), z_dim.zmin(), z_dim.zmax(), z_dim.step()); - - // translation, rotation - static double deg2r = ROOT::Math::Pi() / 180.; - RotationZYX rot(0., 0., 0.); - if (x_dim.hasChild(_Unicode(rotation))) { - xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); - rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); - } - - Translation3D trans(0., 0., 0.); - if (x_dim.hasChild(_Unicode(translation))) { - xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); - trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); - } - map->SetTransform(trans * rot); - - map->LoadMap(field_map_file, field_map_scale); - field.assign(map, x_par.nameStr(), "FieldMapBrBz"); - - return field; -} - -DECLARE_XMLELEMENT(epic_FieldMapBrBz, create_field_map_brbz) From ca0b7a04202e009b34ec341fd72d86f65899d012 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 14:39:00 -0500 Subject: [PATCH 03/25] Change name of ideal lumi B field values. --- compact/far_backward/lumi/lumi_magnets.xml | 8 ++++---- compact/fields/beamline_10x100.xml | 4 ++-- compact/fields/beamline_10x110_H2.xml | 4 ++-- compact/fields/beamline_10x275.xml | 4 ++-- compact/fields/beamline_18x110_Au.xml | 4 ++-- compact/fields/beamline_18x110_H2.xml | 4 ++-- compact/fields/beamline_18x110_He3.xml | 4 ++-- compact/fields/beamline_18x110_Pb.xml | 4 ++-- compact/fields/beamline_18x275.xml | 4 ++-- compact/fields/beamline_5x100.xml | 4 ++-- compact/fields/beamline_5x110_H2.xml | 4 ++-- compact/fields/beamline_5x41.xml | 4 ++-- compact/fields/beamline_5x41_H2.xml | 4 ++-- compact/fields/beamline_5x41_He3.xml | 4 ++-- compact/fields/beamline_5x41_He4.xml | 4 ++-- 15 files changed, 32 insertions(+), 32 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 20dee0f4e..7d7d6d484 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -80,19 +80,19 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - diff --git a/compact/fields/beamline_10x100.xml b/compact/fields/beamline_10x100.xml index 548ca2ae2..2b34c4ac0 100644 --- a/compact/fields/beamline_10x100.xml +++ b/compact/fields/beamline_10x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_10x110_H2.xml b/compact/fields/beamline_10x110_H2.xml index e1fbea347..8c2be92e9 100644 --- a/compact/fields/beamline_10x110_H2.xml +++ b/compact/fields/beamline_10x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_10x275.xml b/compact/fields/beamline_10x275.xml index a2d0e47f0..cc3e0e73a 100644 --- a/compact/fields/beamline_10x275.xml +++ b/compact/fields/beamline_10x275.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_18x110_Au.xml b/compact/fields/beamline_18x110_Au.xml index 44725ebc8..3da33869c 100644 --- a/compact/fields/beamline_18x110_Au.xml +++ b/compact/fields/beamline_18x110_Au.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_H2.xml b/compact/fields/beamline_18x110_H2.xml index 7ab918a99..6994eef7a 100644 --- a/compact/fields/beamline_18x110_H2.xml +++ b/compact/fields/beamline_18x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_He3.xml b/compact/fields/beamline_18x110_He3.xml index d1bf496f1..aae21dd69 100644 --- a/compact/fields/beamline_18x110_He3.xml +++ b/compact/fields/beamline_18x110_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_Pb.xml b/compact/fields/beamline_18x110_Pb.xml index 9801622be..9d9423c0c 100644 --- a/compact/fields/beamline_18x110_Pb.xml +++ b/compact/fields/beamline_18x110_Pb.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x275.xml b/compact/fields/beamline_18x275.xml index 713ae0b2b..29f0e47d1 100644 --- a/compact/fields/beamline_18x275.xml +++ b/compact/fields/beamline_18x275.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x100.xml b/compact/fields/beamline_5x100.xml index 5e9a18f80..9e6d104fa 100644 --- a/compact/fields/beamline_5x100.xml +++ b/compact/fields/beamline_5x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x110_H2.xml b/compact/fields/beamline_5x110_H2.xml index 7a65b2ee3..7fb84a1ab 100644 --- a/compact/fields/beamline_5x110_H2.xml +++ b/compact/fields/beamline_5x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41.xml b/compact/fields/beamline_5x41.xml index ca787e71b..83e616bf5 100644 --- a/compact/fields/beamline_5x41.xml +++ b/compact/fields/beamline_5x41.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x41_H2.xml b/compact/fields/beamline_5x41_H2.xml index f38e05f7e..bb9a6dadb 100644 --- a/compact/fields/beamline_5x41_H2.xml +++ b/compact/fields/beamline_5x41_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He3.xml b/compact/fields/beamline_5x41_He3.xml index d474b021f..08894fff4 100644 --- a/compact/fields/beamline_5x41_He3.xml +++ b/compact/fields/beamline_5x41_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He4.xml b/compact/fields/beamline_5x41_He4.xml index 1a2561621..c1a3143f8 100644 --- a/compact/fields/beamline_5x41_He4.xml +++ b/compact/fields/beamline_5x41_He4.xml @@ -24,8 +24,8 @@ - - + + From dc3a8930b77a3f9eaca2e09763c2da447b960696 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:48:15 +0000 Subject: [PATCH 04/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- compact/far_backward/lumi/lumi_magnets.xml | 2 +- src/FieldMapB.cpp | 36 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 7d7d6d484..2928734f7 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -79,7 +79,7 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - + Ideal fields - - + + Forward Fields diff --git a/compact/fields/beamline_10x110_H2.xml b/compact/fields/beamline_10x110_H2.xml index 8c2be92e9..e1fbea347 100644 --- a/compact/fields/beamline_10x110_H2.xml +++ b/compact/fields/beamline_10x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_10x275.xml b/compact/fields/beamline_10x275.xml index cc3e0e73a..a2d0e47f0 100644 --- a/compact/fields/beamline_10x275.xml +++ b/compact/fields/beamline_10x275.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_18x110_Au.xml b/compact/fields/beamline_18x110_Au.xml index 3da33869c..44725ebc8 100644 --- a/compact/fields/beamline_18x110_Au.xml +++ b/compact/fields/beamline_18x110_Au.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_H2.xml b/compact/fields/beamline_18x110_H2.xml index 6994eef7a..7ab918a99 100644 --- a/compact/fields/beamline_18x110_H2.xml +++ b/compact/fields/beamline_18x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_He3.xml b/compact/fields/beamline_18x110_He3.xml index aae21dd69..d1bf496f1 100644 --- a/compact/fields/beamline_18x110_He3.xml +++ b/compact/fields/beamline_18x110_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_Pb.xml b/compact/fields/beamline_18x110_Pb.xml index 9d9423c0c..9801622be 100644 --- a/compact/fields/beamline_18x110_Pb.xml +++ b/compact/fields/beamline_18x110_Pb.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x275.xml b/compact/fields/beamline_18x275.xml index 29f0e47d1..713ae0b2b 100644 --- a/compact/fields/beamline_18x275.xml +++ b/compact/fields/beamline_18x275.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x100.xml b/compact/fields/beamline_5x100.xml index 9e6d104fa..5e9a18f80 100644 --- a/compact/fields/beamline_5x100.xml +++ b/compact/fields/beamline_5x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x110_H2.xml b/compact/fields/beamline_5x110_H2.xml index 7fb84a1ab..7a65b2ee3 100644 --- a/compact/fields/beamline_5x110_H2.xml +++ b/compact/fields/beamline_5x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41.xml b/compact/fields/beamline_5x41.xml index 83e616bf5..ca787e71b 100644 --- a/compact/fields/beamline_5x41.xml +++ b/compact/fields/beamline_5x41.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x41_H2.xml b/compact/fields/beamline_5x41_H2.xml index bb9a6dadb..f38e05f7e 100644 --- a/compact/fields/beamline_5x41_H2.xml +++ b/compact/fields/beamline_5x41_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He3.xml b/compact/fields/beamline_5x41_He3.xml index 08894fff4..d474b021f 100644 --- a/compact/fields/beamline_5x41_He3.xml +++ b/compact/fields/beamline_5x41_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He4.xml b/compact/fields/beamline_5x41_He4.xml index c1a3143f8..1a2561621 100644 --- a/compact/fields/beamline_5x41_He4.xml +++ b/compact/fields/beamline_5x41_He4.xml @@ -24,8 +24,8 @@ - - + + From 14a2ef43d9105dcd95343c518dc60c9f80e068b7 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 22 Sep 2023 15:20:28 -0500 Subject: [PATCH 06/25] Change comment syntax in xml file. Attempt to streamline calls to fieldComponents. --- compact/far_backward/lumi/lumi_magnets.xml | 5 +- src/FieldMapB.cpp | 198 +++++++++++---------- 2 files changed, 108 insertions(+), 95 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 2928734f7..dc554c3aa 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -81,7 +81,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. Ideal fields - + Calculated fields dimensions); void LoadMap(const std::string& map_file, double scale); - void GetIndices(std::vector coord, std::vector *indices, std::vector *deltas); + bool GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ); + bool GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ); void SetTransform(const Transform3D& tr) { trans = tr; @@ -66,11 +67,15 @@ class FieldMapB : public dd4hep::CartesianField::Object { virtual void fieldComponents(const double* pos, double* field); private: - std::string coord_type; - Transform3D trans, trans_inv; - std::vector steps, mins, maxs; - std::vector>> Bvals_RZ; // {R}, {Z}, {Br,Bz} - std::vector>>> Bvals_XYZ; // {X}, {Y}, {Z}, {Bx,By,Bz} + bool case_BrBz; // is it BrBz or not (BxByBz) + Transform3D trans, trans_inv; // transformation matrices + std::vector steps, mins, maxs; // B map cell info + int ir, ix, iy, iz; // lookup indices + double ir_d, ix_d, iy_d, iz_d; // transient indices for std::modf + double dr, dx, dy, dz; // deltas for interpolation + std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} + ROOT::Math::XYZPoint B_interpolated; // interpolated B }; // constructor @@ -91,7 +96,12 @@ FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; } - coord_type = coord_type_str; + if( coord_type_str.compare("BrBz") == 0 ) { // BrBz + case_BrBz = true; + } + else { // BxByBz + case_BrBz = false; + } } // fill field vector @@ -104,7 +114,7 @@ void FieldMapB::Configure(std::vector dimensions) maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); } - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; @@ -116,8 +126,7 @@ void FieldMapB::Configure(std::vector dimensions) } } } - - if( coord_type.compare("BxByBz") == 0 ) { + else { int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; @@ -135,21 +144,42 @@ void FieldMapB::Configure(std::vector dimensions) } } -// get cell indices corresponding to point of interest -void FieldMapB::GetIndices(std::vector coord, std::vector *indices, std::vector *deltas) +// get RZ cell indices corresponding to point of interest +bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ) +{ + // boundary check + if( R > maxs[0] || R < mins[0] || Z > maxs[1] || Z < mins[1] ) { + return false; + } + + // get indices + *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); + *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); + + *idxR = static_cast( ir_d ); + *idxZ = static_cast( iz_d ); + + return true; +} + +// get XYZ cell indices corresponding to point of interest +bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ) { - for( uint i = 0; i < coord.size(); i++ ) { - // Range check - if( coord[i] < mins[i] || coord[i] > maxs[i] ) { - indices->clear(); - indices->resize( coord.size(), -1 ); - return; - } - - double temp_idx; - deltas->push_back( std::modf( (coord[i] - mins[i]) / steps[i], &temp_idx ) ); - indices->push_back( static_cast(temp_idx) ); + // boundary check + if( X > maxs[0] || X < mins[0] || Y > maxs[1] || Y < mins[1] || Z > maxs[2] || Z < mins[2] ) { + return false; } + + // get indices + *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); + *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); + *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); + + *idxX = static_cast( ix_d ); + *idxY = static_cast( iy_d ); + *idxZ = static_cast( iz_d ); + + return true; } // load data @@ -163,42 +193,38 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) std::vector coord = {}; std::vector Bcomp = {}; - std::vector indices = {}; - std::vector deltas = {}; while (std::getline(input, line).good()) { std::istringstream iss(line); coord.clear(); Bcomp.clear(); - indices.clear(); - deltas.clear(); - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { coord.resize(2); Bcomp.resize(2); iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; + + if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + } + else { + Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; + //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); + //std::cout << p << " -> " << trans*p << std::endl; + //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + } } - if( coord_type.compare("BxByBz") == 0 ) { + else { coord.resize(3); Bcomp.resize(3); iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; - } - GetIndices(coord, &indices, &deltas); - - if (std::count( indices.begin(), indices.end(), -1)) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it." - << std::endl; - } else { - if( coord_type.compare("BrBz") == 0 ) { - Bvals_RZ[ indices[0] ][ indices[1] ] = {Bcomp[0] * scale, Bcomp[1] * scale}; - //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); - //std::cout << p << " -> " << trans*p << std::endl; - //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; } - if( coord_type.compare("BxByBz") == 0 ) { - Bvals_XYZ[ indices[0] ][ indices[1] ][ indices[2] ] = {Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale}; + else { + Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; } } } @@ -210,81 +236,67 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // coordinate conversion auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - std::vector indices = {}; - std::vector deltas = {}; - ROOT::Math::XYZPoint B = ROOT::Math::XYZPoint(0,0,0); - - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { // coordinates conversion const double r = sqrt(p.x() * p.x() + p.y() * p.y()); const double z = p.z(); const double phi = atan2(p.y(), p.x()); - GetIndices({r, z}, &indices, &deltas); - - // out of the range - if (std::count( indices.begin(), indices.end(), -1)) { + if( ! GetIndices(r, z, &ir, &iz, &dr, &dz) ) { + // out of range return; } // p1 p3 // p // p0 p2 - auto& p0 = Bvals_RZ[indices[0]][indices[1]]; - auto& p1 = Bvals_RZ[indices[0]][indices[1] + 1]; - auto& p2 = Bvals_RZ[indices[0] + 1][indices[1]]; - auto& p3 = Bvals_RZ[indices[0] + 1][indices[1] + 1]; + auto& p0 = Bvals_RZ[ ir ][ iz ]; + auto& p1 = Bvals_RZ[ ir ][ iz + 1]; + auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; + auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; // Bilinear interpolation - double Br = p0[0] * (1 - deltas[0]) * (1 - deltas[1]) - + p1[0] * (1 - deltas[0]) * deltas[1] - + p2[0] * deltas[0] * (1 - deltas[1]) - + p3[0] * deltas[0] * deltas[1]; + double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - double Bz = p0[1] * (1 - deltas[0]) * (1 - deltas[1]) - + p1[1] * (1 - deltas[0]) * deltas[1] - + p2[1] * deltas[0] * (1 - deltas[1]) - + p3[1] * deltas[0] * deltas[1]; + double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz - B = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); - B = trans * B; + B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + B_interpolated = trans * B_interpolated; } + else { - if( coord_type.compare("BxByBz") == 0 ) { - - GetIndices({p.x(), p.y(), p.z()}, &indices, &deltas); - - // out of the range - if (std::count( indices.begin(), indices.end(), -1)) { - return; + if( ! GetIndices(p.x(), p.y(), p.z(), &ix, &iy, &iz, &dx, &dy, &dz) ) { + return; // out of range } + double b[3] = {0}; for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - double b00 = Bvals_XYZ[indices[0]][indices[1]][indices[2]][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2]][comp] * deltas[0]; - double b01 = Bvals_XYZ[indices[0]][indices[1]][indices[2] + 1][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2] + 1][comp] * deltas[0]; - double b10 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2]][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2]][comp] * deltas[0]; - double b11 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2] + 1][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2] + 1][comp] * deltas[0]; - //// Next along Y, along 2 lines - double b0 = b00 * (1 - deltas[1]) + b10 * deltas[1]; - double b1 = b01 * (1 - deltas[1]) + b11 * deltas[1]; - //// Finally along Z - double b = b0 * (1 - deltas[2]) + b1 * deltas[2]; - if(comp == 0) { B.SetX( b ); } - if(comp == 1) { B.SetY( b ); } - if(comp == 2) { B.SetZ( b ); } + double b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; + double b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; + double b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; + double b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + // Next along Y, along 2 lines + double b0 = b00 * (1 - dy) + b10 * dy; + double b1 = b01 * (1 - dy) + b11 * dy; + // Finally along Z + b[comp] = b0 * (1 - dz) + b1 * dz; } + + B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); } - field[0] += B.x() * tesla; - field[1] += B.y() * tesla; - field[2] += B.z() * tesla; + field[0] += B_interpolated.x() * tesla; + field[1] += B_interpolated.y() * tesla; + field[2] += B_interpolated.z() * tesla; return; } @@ -323,7 +335,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); std::_Exit(EXIT_FAILURE); } - + std::string field_map_file = x_par.attr(_Unicode(field_map)); std::string field_map_url = x_par.attr(_Unicode(url)); std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); From c16103002ee38090a6ab033234b2bd544ed75349 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:20:42 +0000 Subject: [PATCH 07/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/FieldMapB.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 6b4ef9d82..420af62b9 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -155,7 +155,7 @@ bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *del // get indices *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); - + *idxR = static_cast( ir_d ); *idxZ = static_cast( iz_d ); @@ -174,7 +174,7 @@ bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, i *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); - + *idxX = static_cast( ix_d ); *idxY = static_cast( iy_d ); *idxZ = static_cast( iz_d ); @@ -290,7 +290,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // Finally along Z b[comp] = b0 * (1 - dz) + b1 * dz; } - + B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); } @@ -335,7 +335,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); std::_Exit(EXIT_FAILURE); } - + std::string field_map_file = x_par.attr(_Unicode(field_map)); std::string field_map_url = x_par.attr(_Unicode(url)); std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); From b785e19e323b8bb85573f0c69f06fe8d09815604 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 25 Sep 2023 14:21:25 -0500 Subject: [PATCH 08/25] Changes as requested in the PR. --- src/FieldMapB.cpp | 135 +++++++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 73 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 6b4ef9d82..302c87244 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -52,12 +52,19 @@ using namespace dd4hep; // implementation of the field map class FieldMapB : public dd4hep::CartesianField::Object { + + enum FieldCoord { + BrBz, + BxByBz + }; + + public: FieldMapB(const std::string& field_type_str = "magnetic", const std::string& coord_type_str = "BrBz"); void Configure(std::vector dimensions); - void LoadMap(const std::string& map_file, double scale); - bool GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ); - bool GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ); + void LoadMap(const std::string& map_file, float scale); + bool GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ); + bool GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ); void SetTransform(const Transform3D& tr) { trans = tr; @@ -67,14 +74,13 @@ class FieldMapB : public dd4hep::CartesianField::Object { virtual void fieldComponents(const double* pos, double* field); private: - bool case_BrBz; // is it BrBz or not (BxByBz) + FieldCoord fieldCoord; // field coordinate type Transform3D trans, trans_inv; // transformation matrices - std::vector steps, mins, maxs; // B map cell info + std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices - double ir_d, ix_d, iy_d, iz_d; // transient indices for std::modf - double dr, dx, dy, dz; // deltas for interpolation - std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} - std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} + float dr, dx, dy, dz; // deltas for interpolation + std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} ROOT::Math::XYZPoint B_interpolated; // interpolated B }; @@ -93,14 +99,14 @@ FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; } else { DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; - std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; + printout(ERROR, "FieldMap","Unknown field type " + ftype); } if( coord_type_str.compare("BrBz") == 0 ) { // BrBz - case_BrBz = true; + fieldCoord = FieldCoord::BrBz; } else { // BxByBz - case_BrBz = false; + fieldCoord = FieldCoord::BxByBz; } } @@ -110,42 +116,36 @@ void FieldMapB::Configure(std::vector dimensions) // Fill vectors with step size, min, max for each dimension for( auto el : dimensions ) { steps.push_back( el.step() ); - mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); - maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); + mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); + maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); } - if( case_BrBz ) { - int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; - int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; + if( fieldCoord == FieldCoord::BrBz ) { + int nr = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; + int nz = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; Bvals_RZ.resize(nr); for (auto& B2 : Bvals_RZ) { B2.resize(nz); - for (auto& B : B2) { - B.resize(2, 0.); // Br, Bz - } } } else { - int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; - int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; - int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; + int nx = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; + int ny = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; + int nz = std::roundf( (maxs[2] - mins[2]) / steps[2] ) + 1; Bvals_XYZ.resize(nx); for (auto& B3 : Bvals_XYZ) { B3.resize(ny); for (auto& B2 : B3) { B2.resize(nz); - for (auto& B : B2) { - B.resize(3, 0.); // Bx, By, Bz - } } } } } // get RZ cell indices corresponding to point of interest -bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ) +bool FieldMapB::GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ) { // boundary check if( R > maxs[0] || R < mins[0] || Z > maxs[1] || Z < mins[1] ) { @@ -153,17 +153,14 @@ bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *del } // get indices - *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); - *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); - - *idxR = static_cast( ir_d ); - *idxZ = static_cast( iz_d ); + *deltaR = std::remquof( (R - mins[0]), steps[0], idxR ); + *deltaZ = std::remquof( (Z - mins[1]), steps[1], idxZ ); return true; } // get XYZ cell indices corresponding to point of interest -bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ) +bool FieldMapB::GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ) { // boundary check if( X > maxs[0] || X < mins[0] || Y > maxs[1] || Y < mins[1] || Z > maxs[2] || Z < mins[2] ) { @@ -171,28 +168,24 @@ bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, i } // get indices - *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); - *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); - *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); - - *idxX = static_cast( ix_d ); - *idxY = static_cast( iy_d ); - *idxZ = static_cast( iz_d ); + *deltaX = std::remquof( (X - mins[0]), steps[0], idxX ); + *deltaY = std::remquof( (Y - mins[1]), steps[1], idxY ); + *deltaZ = std::remquof( (Z - mins[2]), steps[2], idxZ ); return true; } // load data -void FieldMapB::LoadMap(const std::string& map_file, double scale) +void FieldMapB::LoadMap(const std::string& map_file, float scale) { std::string line; std::ifstream input(map_file); - if (!input) { - std::cout << "FieldMapB Error: file \"" << map_file << "\" cannot be read." << std::endl; + if( ! input ) { + printout(ERROR,"FieldMapB", "FieldMapB Error: file " + map_file + " cannot be read."); } - std::vector coord = {}; - std::vector Bcomp = {}; + std::vector coord = {}; + std::vector Bcomp = {}; while (std::getline(input, line).good()) { std::istringstream iss(line); @@ -200,19 +193,16 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) coord.clear(); Bcomp.clear(); - if( case_BrBz ) { + if( fieldCoord == FieldCoord::BrBz) { coord.resize(2); Bcomp.resize(2); iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } else { Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; - //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); - //std::cout << p << " -> " << trans*p << std::endl; - //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; } } else { @@ -221,7 +211,7 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } else { Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; @@ -236,11 +226,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // coordinate conversion auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - if( case_BrBz ) { + if( fieldCoord == FieldCoord::BrBz ) { // coordinates conversion - const double r = sqrt(p.x() * p.x() + p.y() * p.y()); - const double z = p.z(); - const double phi = atan2(p.y(), p.x()); + const float r = sqrt(p.x() * p.x() + p.y() * p.y()); + const float z = p.z(); + const float phi = atan2(p.y(), p.x()); if( ! GetIndices(r, z, &ir, &iz, &dr, &dz) ) { // out of range @@ -256,11 +246,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; // Bilinear interpolation - double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz - + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; + float Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz - + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; + float Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); @@ -272,21 +262,21 @@ void FieldMapB::fieldComponents(const double* pos, double* field) return; // out of range } - double b[3] = {0}; + float b[3] = {0}; for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - double b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; - double b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; - double b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; - double b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; + float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; + float b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; + float b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; // Next along Y, along 2 lines - double b0 = b00 * (1 - dy) + b10 * dy; - double b1 = b01 * (1 - dy) + b11 * dy; + float b0 = b00 * (1 - dy) + b10 * dy; + float b1 = b01 * (1 - dy) + b11 * dy; // Finally along Z b[comp] = b0 * (1 - dz) + b1 * dz; } @@ -313,7 +303,6 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) CartesianField field; std::string field_type = x_par.attr(_Unicode(field_type)); - // coordinate type: "BrBz" or "BxByBz" std::string coord_type = x_par.attr(_Unicode(coord_type)); // dimensions @@ -342,7 +331,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); - double field_map_scale = x_par.attr(_Unicode(scale)); + float field_map_scale = x_par.attr(_Unicode(scale)); if (!fs::exists(fs::path(field_map_file))) { printout(ERROR, "FieldMapB", "file " + field_map_file + " does not exist"); @@ -354,7 +343,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) map->Configure( dimensions ); // translation, rotation - static double deg2r = ROOT::Math::Pi() / 180.; + static float deg2r = ROOT::Math::Pi() / 180.; RotationZYX rot(0., 0., 0.); if (x_dim.hasChild(_Unicode(rotation))) { xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); From 9f53900013851663002bd88f096107e58508748a Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 29 Sep 2023 12:05:43 -0500 Subject: [PATCH 09/25] Remove transformation of the B field for the BrBz case. Multiply by tesla units once when the field is loaded. Remove unnecessary intermediate variable, B_interpolated. --- src/FieldMapB.cpp | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index ed07ba58b..5c3cbbbc9 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -81,7 +81,6 @@ class FieldMapB : public dd4hep::CartesianField::Object { float dr, dx, dy, dz; // deltas for interpolation std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} - ROOT::Math::XYZPoint B_interpolated; // interpolated B }; // constructor @@ -202,7 +201,9 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } else { - Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; + Bvals_RZ[ ir ][ iz ] = + { Bcomp[0] * scale * float(tesla), + Bcomp[1] * scale * float(tesla) }; } } else { @@ -214,7 +215,10 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } else { - Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; + Bvals_XYZ[ ix ][ iy ][ iz ] = + { Bcomp[0] * scale * float(tesla), + Bcomp[1] * scale * float(tesla), + Bcomp[2] * scale * float(tesla) }; } } } @@ -240,10 +244,10 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // p1 p3 // p // p0 p2 - auto& p0 = Bvals_RZ[ ir ][ iz ]; - auto& p1 = Bvals_RZ[ ir ][ iz + 1]; - auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; - auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; + auto& p0 = Bvals_RZ[ ir ][ iz ]; + auto& p1 = Bvals_RZ[ ir ][ iz + 1 ]; + auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; + auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1 ]; // Bilinear interpolation float Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz @@ -253,8 +257,9 @@ void FieldMapB::fieldComponents(const double* pos, double* field) + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz - B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); - B_interpolated = trans * B_interpolated; + field[0] += Br * sin(phi); + field[1] += Br * cos(phi); + field[2] += Bz; } else { @@ -266,14 +271,14 @@ void FieldMapB::fieldComponents(const double* pos, double* field) for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; - float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; - float b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; - float b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy ][ iz ][comp] * dx; + float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1 ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy ][ iz + 1 ][comp] * dx; + float b10 = Bvals_XYZ[ ix ][ iy + 1 ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy + 1 ][ iz ][comp] * dx; + float b11 = Bvals_XYZ[ ix ][ iy + 1 ][ iz + 1 ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy + 1 ][ iz + 1 ][comp] * dx; // Next along Y, along 2 lines float b0 = b00 * (1 - dy) + b10 * dy; float b1 = b01 * (1 - dy) + b11 * dy; @@ -281,13 +286,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) b[comp] = b0 * (1 - dz) + b1 * dz; } - B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); + field[0] += b[0]; + field[1] += b[1]; + field[2] += b[2]; } - field[0] += B_interpolated.x() * tesla; - field[1] += B_interpolated.y() * tesla; - field[2] += B_interpolated.z() * tesla; - return; } From 4fbbb8f1baf0ea694d2d1712c7895b21ed741576 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 6 Oct 2023 15:22:20 -0500 Subject: [PATCH 10/25] WIP. Add field vector rotation separate from field coord translation vector. --- compact/far_backward/lumi/lumi_magnets.xml | 8 ++-- compact/fields/marco.xml | 4 +- src/FieldMapB.cpp | 51 +++++++++++++--------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index dc554c3aa..42e8aad0d 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -107,8 +107,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - - + + @@ -121,8 +121,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - - + + diff --git a/compact/fields/marco.xml b/compact/fields/marco.xml index 704513058..931c8d7f1 100644 --- a/compact/fields/marco.xml +++ b/compact/fields/marco.xml @@ -11,8 +11,8 @@ - - + + diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 5c3cbbbc9..88d6707cc 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -65,17 +65,23 @@ class FieldMapB : public dd4hep::CartesianField::Object { void LoadMap(const std::string& map_file, float scale); bool GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ); bool GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ); - void SetTransform(const Transform3D& tr) + void SetCoordTranslation(const Transform3D& tr) { - trans = tr; - trans_inv = tr.Inverse(); + coordTranslate = tr; + coordTranslate_inv = tr.Inverse(); + } + void SetFieldRotation(const Transform3D& tr) + { + fieldRot = tr; + fieldRot_inv = tr.Inverse(); } virtual void fieldComponents(const double* pos, double* field); private: FieldCoord fieldCoord; // field coordinate type - Transform3D trans, trans_inv; // transformation matrices + Transform3D coordTranslate, coordTranslate_inv; // coord translation + Transform3D fieldRot, fieldRot_inv; // field rotation std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices float dr, dx, dy, dz; // deltas for interpolation @@ -200,7 +206,7 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } - else { + else { // scale field Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale * float(tesla), Bcomp[1] * scale * float(tesla) }; @@ -214,11 +220,11 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } - else { - Bvals_XYZ[ ix ][ iy ][ iz ] = - { Bcomp[0] * scale * float(tesla), - Bcomp[1] * scale * float(tesla), - Bcomp[2] * scale * float(tesla) }; + else { // scale and rotate B field vector + auto B = ROOT::Math::XYZPoint( Bcomp[0], Bcomp[1], Bcomp[2] ); + B *= scale * float(tesla); + B = fieldRot * B; + Bvals_XYZ[ ix ][ iy ][ iz ] = { float(B.x()), float(B.y()), float(B.z()) }; } } } @@ -228,7 +234,7 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) void FieldMapB::fieldComponents(const double* pos, double* field) { // coordinate conversion - auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); + auto p = coordTranslate_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); if( fieldCoord == FieldCoord::BrBz ) { // coordinates conversion @@ -256,12 +262,13 @@ void FieldMapB::fieldComponents(const double* pos, double* field) float Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; - // convert Br Bz to Bx By Bz - field[0] += Br * sin(phi); - field[1] += Br * cos(phi); - field[2] += Bz; + // convert Br Bz to Bx By Bz and rotate field + auto B = fieldRot * ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + field[0] += B.x(); + field[1] += B.y(); + field[2] += B.z(); } - else { + else { // BxByBz if( ! GetIndices(p.x(), p.y(), p.z(), &ix, &iy, &iz, &dx, &dy, &dz) ) { return; // out of range @@ -286,6 +293,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) b[comp] = b0 * (1 - dz) + b1 * dz; } + // field rotation done in LoadMap() field[0] += b[0]; field[1] += b[1]; field[2] += b[2]; @@ -348,17 +356,18 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) // translation, rotation static float deg2r = ROOT::Math::Pi() / 180.; RotationZYX rot(0., 0., 0.); - if (x_dim.hasChild(_Unicode(rotation))) { - xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); + if (x_dim.hasChild(_Unicode(rotationField))) { + xml_comp_t rot_dim = x_dim.child(_Unicode(rotationField)); rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); } Translation3D trans(0., 0., 0.); - if (x_dim.hasChild(_Unicode(translation))) { - xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); + if (x_dim.hasChild(_Unicode(translationCoord))) { + xml_comp_t trans_dim = x_dim.child(_Unicode(translationCoord)); trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); } - map->SetTransform(trans * rot); + map->SetCoordTranslation( Transform3D(trans) ); + map->SetFieldRotation( Transform3D(rot) ); map->LoadMap(field_map_file, field_map_scale); field.assign(map, x_par.nameStr(), "FieldMapB"); From c0cafbb9b2a409fef1f6621c5a85596a0190bd7e Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 6 Oct 2023 16:42:53 -0500 Subject: [PATCH 11/25] Bug fix: wrong usage of std::remquof. Go back to using std::modf, with transient floats. --- src/FieldMapB.cpp | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 88d6707cc..06c9f8855 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -84,6 +84,7 @@ class FieldMapB : public dd4hep::CartesianField::Object { Transform3D fieldRot, fieldRot_inv; // field rotation std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices + float idx_1_f, idx_2_f, idx_3_f; // transient float indicies float dr, dx, dy, dz; // deltas for interpolation std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} @@ -158,8 +159,10 @@ bool FieldMapB::GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR } // get indices - *deltaR = std::remquof( (R - mins[0]), steps[0], idxR ); - *deltaZ = std::remquof( (Z - mins[1]), steps[1], idxZ ); + *deltaR = std::modf( (R - mins[0]) / steps[0], &idx_1_f ); + *deltaZ = std::modf( (Z - mins[1]) / steps[1], &idx_2_f ); + *idxR = static_cast(idx_1_f); + *idxZ = static_cast(idx_2_f); return true; } @@ -173,9 +176,12 @@ bool FieldMapB::GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int } // get indices - *deltaX = std::remquof( (X - mins[0]), steps[0], idxX ); - *deltaY = std::remquof( (Y - mins[1]), steps[1], idxY ); - *deltaZ = std::remquof( (Z - mins[2]), steps[2], idxZ ); + *deltaX = std::modf( (X - mins[0]) / steps[0], &idx_1_f ); + *deltaY = std::modf( (Y - mins[1]) / steps[1], &idx_2_f ); + *deltaZ = std::modf( (Z - mins[2]) / steps[2], &idx_3_f ); + *idxX = static_cast(idx_1_f); + *idxY = static_cast(idx_2_f); + *idxZ = static_cast(idx_3_f); return true; } From dba96216aae658e10d5b2dd0f48ad2685ad2573c Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan <43478603+dhevang@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:53:38 -0500 Subject: [PATCH 12/25] Swap Bx and By components in new file as per the recent bug fix. Co-authored-by: Dmitry Kalinkin --- src/FieldMapB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 06c9f8855..39992fe0d 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -269,7 +269,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz and rotate field - auto B = fieldRot * ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + auto B = fieldRot * ROOT::Math::XYZPoint(Br * cos(phi), Br * sin(phi), Bz); field[0] += B.x(); field[1] += B.y(); field[2] += B.z(); From 835566ee1ee5ea0fdfabe202bc49e1887f7d3ae6 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 13:26:00 -0500 Subject: [PATCH 13/25] Shift lumi system closer to IP due to proximity with electron CRAB magnet. --- compact/far_backward/definitions.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compact/far_backward/definitions.xml b/compact/far_backward/definitions.xml index 85bb3686f..2b3823ed1 100644 --- a/compact/far_backward/definitions.xml +++ b/compact/far_backward/definitions.xml @@ -251,7 +251,7 @@ - + From 739f10326fc8d464a526d03d74af9126ff79c127 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 13:30:27 -0500 Subject: [PATCH 14/25] new B mapping code, which can handle R-Z and X-Y-Z coordinate systems. Implement lumi dipole B maps. --- compact/far_backward/lumi/lumi_magnets.xml | 36 +- compact/fields/marco.xml | 6 +- src/FieldMapB.cpp | 365 +++++++++++++++++++++ src/FieldMapBrBz.cpp | 246 -------------- 4 files changed, 403 insertions(+), 250 deletions(-) create mode 100644 src/FieldMapB.cpp delete mode 100644 src/FieldMapBrBz.cpp diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 7a277e79b..20dee0f4e 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -77,7 +77,10 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. Detailed field map to be inserted later. + + + + + Calculated fields + + + + + + + + + + + + + + + + + + + + diff --git a/compact/fields/marco.xml b/compact/fields/marco.xml index f5df7e8ee..704513058 100644 --- a/compact/fields/marco.xml +++ b/compact/fields/marco.xml @@ -3,14 +3,14 @@ - - - + + diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp new file mode 100644 index 000000000..5fa40b880 --- /dev/null +++ b/src/FieldMapB.cpp @@ -0,0 +1,365 @@ +// SPDX-License-Identifier: LGPL-3.0-or-later +// Copyright (C) 2023 Wouter Deconinck, Dhevan Gangadharan, Aranya Giri + +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +namespace fs = std::filesystem; + +#include "FileLoaderHelper.h" + +using namespace dd4hep; + +// Two coordinate options: +// coord_type="BrBz" +// expected fields contained within : +// +// +// coord_type="BxByBz" +// expected fields contained within : +// +// +// + +// In DD4hep 1.26, the name for the `field_type` enum changed (from `type`). +#if DD4HEP_VERSION_GE(1, 26) +#define DD4HEP_FIELD_TYPE field_type +#else +#define DD4HEP_FIELD_TYPE type +#endif + +// This allows us to specify the name of the variable by hand, when patching +// the previous versions, by setting `DD4HEP_FIELD_TYPE_OVERRIDE`. +// TODO remove after DD4hep 1.26 release +#define XSTR(x) STR(x) +#define STR(x) #x +#ifdef DD4HEP_FIELD_TYPE_OVERRIDE +#undef DD4HEP_FIELD_TYPE +#define DD4HEP_FIELD_TYPE DD4HEP_FIELD_TYPE_OVERRIDE +#pragma message("DD4HEP_FIELD_TYPE overridden as " XSTR(DD4HEP_FIELD_TYPE)) +#endif +#pragma message("DD4HEP_FIELD_TYPE is " XSTR(DD4HEP_FIELD_TYPE)) + +// implementation of the field map +class FieldMapB : public dd4hep::CartesianField::Object { +public: + FieldMapB(const std::string& field_type_str = "magnetic", const std::string& coord_type_str = "BrBz"); + void Configure(std::vector dimensions); + void LoadMap(const std::string& map_file, double scale); + void GetIndices(std::vector coord, std::vector *indices, std::vector *deltas); + void SetTransform(const Transform3D& tr) + { + trans = tr; + trans_inv = tr.Inverse(); + } + + virtual void fieldComponents(const double* pos, double* field); + +private: + std::string coord_type; + Transform3D trans, trans_inv; + std::vector steps, mins, maxs; + std::vector>> Bvals_RZ; // {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // {X}, {Y}, {Z}, {Bx,By,Bz} +}; + +// constructor +FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord_type_str) +{ + std::string ftype = field_type_str; + for (auto& c : ftype) { + c = tolower(c); + } + + // set type + if (ftype == "magnetic") { + DD4HEP_FIELD_TYPE = CartesianField::MAGNETIC; + } else if (ftype == "electric") { + DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; + } else { + DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; + std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; + } + + coord_type = coord_type_str; +} + +// fill field vector +void FieldMapB::Configure(std::vector dimensions) +{ + // Fill vectors with step size, min, max for each dimension + for( auto el : dimensions ) { + steps.push_back( el.step() ); + mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); + maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); + } + + if( coord_type.compare("BrBz") == 0 ) { + int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; + int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; + + Bvals_RZ.resize(nr); + for (auto& B2 : Bvals_RZ) { + B2.resize(nz); + for (auto& B : B2) { + B.resize(2, 0.); // Br, Bz + } + } + } + + if( coord_type.compare("BxByBz") == 0 ) { + int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; + int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; + int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; + + Bvals_XYZ.resize(nx); + for (auto& B3 : Bvals_XYZ) { + B3.resize(ny); + for (auto& B2 : B3) { + B2.resize(nz); + for (auto& B : B2) { + B.resize(3, 0.); // Bx, By, Bz + } + } + } + } +} + +// get cell indices corresponding to point of interest +void FieldMapB::GetIndices(std::vector coord, std::vector *indices, std::vector *deltas) +{ + for( uint i = 0; i < coord.size(); i++ ) { + // Range check + if( coord[i] < mins[i] || coord[i] > maxs[i] ) { + indices->clear(); + indices->resize( coord.size(), -1 ); + return; + } + + double temp_idx; + deltas->push_back( std::modf( (coord[i] - mins[i]) / steps[i], &temp_idx ) ); + indices->push_back( static_cast(temp_idx) ); + } +} + +// load data +void FieldMapB::LoadMap(const std::string& map_file, double scale) +{ + std::string line; + std::ifstream input(map_file); + if (!input) { + std::cout << "FieldMapB Error: file \"" << map_file << "\" cannot be read." << std::endl; + } + + std::vector coord = {}; + std::vector Bcomp = {}; + std::vector indices = {}; + std::vector deltas = {}; + + while (std::getline(input, line).good()) { + std::istringstream iss(line); + + coord.clear(); + Bcomp.clear(); + indices.clear(); + deltas.clear(); + + if( coord_type.compare("BrBz") == 0 ) { + coord.resize(2); + Bcomp.resize(2); + iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; + } + if( coord_type.compare("BxByBz") == 0 ) { + coord.resize(3); + Bcomp.resize(3); + iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; + } + + GetIndices(coord, &indices, &deltas); + + if (std::count( indices.begin(), indices.end(), -1)) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it." + << std::endl; + } else { + if( coord_type.compare("BrBz") == 0 ) { + Bvals_RZ[ indices[0] ][ indices[1] ] = {Bcomp[0] * scale, Bcomp[1] * scale}; + //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); + //std::cout << p << " -> " << trans*p << std::endl; + //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + } + if( coord_type.compare("BxByBz") == 0 ) { + Bvals_XYZ[ indices[0] ][ indices[1] ][ indices[2] ] = {Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale}; + } + } + } +} + +// get field components +void FieldMapB::fieldComponents(const double* pos, double* field) +{ + // coordinate conversion + auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); + + std::vector indices = {}; + std::vector deltas = {}; + ROOT::Math::XYZPoint B = ROOT::Math::XYZPoint(0,0,0); + + if( coord_type.compare("BrBz") == 0 ) { + // coordinates conversion + const double r = sqrt(p.x() * p.x() + p.y() * p.y()); + const double z = p.z(); + const double phi = atan2(p.y(), p.x()); + + GetIndices({r, z}, &indices, &deltas); + + // out of the range + if (std::count( indices.begin(), indices.end(), -1)) { + return; + } + + // p1 p3 + // p + // p0 p2 + auto& p0 = Bvals_RZ[indices[0]][indices[1]]; + auto& p1 = Bvals_RZ[indices[0]][indices[1] + 1]; + auto& p2 = Bvals_RZ[indices[0] + 1][indices[1]]; + auto& p3 = Bvals_RZ[indices[0] + 1][indices[1] + 1]; + + // Bilinear interpolation + double Br = p0[0] * (1 - deltas[0]) * (1 - deltas[1]) + + p1[0] * (1 - deltas[0]) * deltas[1] + + p2[0] * deltas[0] * (1 - deltas[1]) + + p3[0] * deltas[0] * deltas[1]; + + double Bz = p0[1] * (1 - deltas[0]) * (1 - deltas[1]) + + p1[1] * (1 - deltas[0]) * deltas[1] + + p2[1] * deltas[0] * (1 - deltas[1]) + + p3[1] * deltas[0] * deltas[1]; + + // convert Br Bz to Bx By Bz + B = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + B = trans * B; + } + + if( coord_type.compare("BxByBz") == 0 ) { + + GetIndices({p.x(), p.y(), p.z()}, &indices, &deltas); + + // out of the range + if (std::count( indices.begin(), indices.end(), -1)) { + return; + } + + for(int comp = 0; comp < 3; comp++) { // field component loop + // Trilinear interpolation + // First along X, along 4 lines + double b00 = Bvals_XYZ[indices[0]][indices[1]][indices[2]][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2]][comp] * deltas[0]; + double b01 = Bvals_XYZ[indices[0]][indices[1]][indices[2] + 1][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2] + 1][comp] * deltas[0]; + double b10 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2]][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2]][comp] * deltas[0]; + double b11 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2] + 1][comp] * (1 - deltas[0]) + + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2] + 1][comp] * deltas[0]; + //// Next along Y, along 2 lines + double b0 = b00 * (1 - deltas[1]) + b10 * deltas[1]; + double b1 = b01 * (1 - deltas[1]) + b11 * deltas[1]; + //// Finally along Z + double b = b0 * (1 - deltas[2]) + b1 * deltas[2]; + if(comp == 0) { B.SetX( b ); } + if(comp == 1) { B.SetY( b ); } + if(comp == 2) { B.SetZ( b ); } + } + } + + field[0] += B.x() * tesla; + field[1] += B.y() * tesla; + field[2] += B.z() * tesla; + + return; +} + +// assign the field map to CartesianField +static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) +{ + xml_comp_t x_par(handle); + + if (!x_par.hasAttr(_Unicode(field_map))) { + throw std::runtime_error("FieldMapB Error: must have an xml attribute \"field_map\" for the field map."); + } + + CartesianField field; + std::string field_type = x_par.attr(_Unicode(field_type)); + + // coordinate type: "BrBz" or "BxByBz" + std::string coord_type = x_par.attr(_Unicode(coord_type)); + + // dimensions + xml_comp_t x_dim = x_par.dimensions(); + + // vector of dimension parameters: step, min, max + std::vector dimensions; + + if( coord_type.compare("BrBz") == 0 ) { + dimensions.push_back( x_dim.child(_Unicode(R)) ); + dimensions.push_back( x_dim.child(_Unicode(Z)) ); + } + else if( coord_type.compare("BxByBz") == 0 ) { + dimensions.push_back( x_dim.child(_Unicode(X)) ); + dimensions.push_back( x_dim.child(_Unicode(Y)) ); + dimensions.push_back( x_dim.child(_Unicode(Z)) ); + } + else { + printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); + std::_Exit(EXIT_FAILURE); + } + + std::string field_map_file = x_par.attr(_Unicode(field_map)); + std::string field_map_url = x_par.attr(_Unicode(url)); + std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); + + EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); + + double field_map_scale = x_par.attr(_Unicode(scale)); + + if (!fs::exists(fs::path(field_map_file))) { + printout(ERROR, "FieldMapB", "file " + field_map_file + " does not exist"); + printout(ERROR, "FieldMapB", "use a FileLoader plugin before the field element"); + std::_Exit(EXIT_FAILURE); + } + + auto map = new FieldMapB(field_type, coord_type); + map->Configure( dimensions ); + + // translation, rotation + static double deg2r = ROOT::Math::Pi() / 180.; + RotationZYX rot(0., 0., 0.); + if (x_dim.hasChild(_Unicode(rotation))) { + xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); + rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); + } + + Translation3D trans(0., 0., 0.); + if (x_dim.hasChild(_Unicode(translation))) { + xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); + trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); + } + map->SetTransform(trans * rot); + + map->LoadMap(field_map_file, field_map_scale); + field.assign(map, x_par.nameStr(), "FieldMapB"); + + return field; +} + +DECLARE_XMLELEMENT(epic_FieldMapB, create_field_map_b) diff --git a/src/FieldMapBrBz.cpp b/src/FieldMapBrBz.cpp deleted file mode 100644 index 9791b3f54..000000000 --- a/src/FieldMapBrBz.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// SPDX-License-Identifier: LGPL-3.0-or-later -// Copyright (C) 2022 Wouter Deconinck - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include -namespace fs = std::filesystem; - -#include "FileLoaderHelper.h" - -using namespace dd4hep; - -// In DD4hep 1.26, the name for the `field_type` enum changed (from `type`). -#if DD4HEP_VERSION_GE(1, 26) -#define DD4HEP_FIELD_TYPE field_type -#else -#define DD4HEP_FIELD_TYPE type -#endif - -// This allows us to specify the name of the variable by hand, when patching -// the previous versions, by setting `DD4HEP_FIELD_TYPE_OVERRIDE`. -// TODO remove after DD4hep 1.26 release -#define XSTR(x) STR(x) -#define STR(x) #x -#ifdef DD4HEP_FIELD_TYPE_OVERRIDE -#undef DD4HEP_FIELD_TYPE -#define DD4HEP_FIELD_TYPE DD4HEP_FIELD_TYPE_OVERRIDE -#pragma message("DD4HEP_FIELD_TYPE overridden as " XSTR(DD4HEP_FIELD_TYPE)) -#endif -#pragma message("DD4HEP_FIELD_TYPE is " XSTR(DD4HEP_FIELD_TYPE)) - -// implementation of the field map -class FieldMapBrBz : public dd4hep::CartesianField::Object { -public: - FieldMapBrBz(const std::string& field_type_str = "magnetic"); - void Configure(double rmin, double rmax, double rstep, double zmin, double zmax, double zstep); - void LoadMap(const std::string& map_file, double scale); - void GetIndices(double r, double z, int& ir, int& iz, double& dr, double& dz); - void SetTransform(const Transform3D& tr) - { - trans = tr; - trans_inv = tr.Inverse(); - } - - virtual void fieldComponents(const double* pos, double* field); - -private: - Transform3D trans, trans_inv; - double rmin, rmax, rstep, zmin, zmax, zstep; - std::vector>> Bvals; -}; - -// constructor -FieldMapBrBz::FieldMapBrBz(const std::string& field_type_str) -{ - std::string ftype = field_type_str; - for (auto& c : ftype) { - c = tolower(c); - } - - // set type - if (ftype == "magnetic") { - DD4HEP_FIELD_TYPE = CartesianField::MAGNETIC; - } else if (ftype == "electric") { - DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; - } else { - DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; - std::cout << "FieldMapBrBz Warning: Unknown field type " << field_type_str << "!" << std::endl; - } -} - -void FieldMapBrBz::Configure(double r1, double r2, double rs, double z1, double z2, double zs) -{ - rmin = r1; - rmax = r2; - rstep = rs; - zmin = z1; - zmax = z2; - zstep = zs; - - int nr = int((r2 - r1) / rs) + 2; - int nz = int((z2 - z1) / zs) + 2; - - Bvals.resize(nr); - for (auto& B2 : Bvals) { - B2.resize(nz); - for (auto& B : B2) { - B.resize(2, 0.); - } - } -} - -void FieldMapBrBz::GetIndices(double r, double z, int& ir, int& iz, double& dr, double& dz) -{ - // boundary check - if (r > rmax || r < rmin || z > zmax || z < zmin) { - ir = -1; - iz = -1; - return; - } - // get indices - double idr, idz; - dr = std::modf((r - rmin) / rstep, &idr); - dz = std::modf((z - zmin) / zstep, &idz); - - ir = static_cast(idr); - iz = static_cast(idz); -} - -// load data -void FieldMapBrBz::LoadMap(const std::string& map_file, double scale) -{ - std::string line; - std::ifstream input(map_file); - if (!input) { - std::cout << "FieldMapBrBz Error: file \"" << map_file << "\" cannot be read." << std::endl; - } - - double r, z, br, bz; - int ir, iz; - double dr, dz; - while (std::getline(input, line).good()) { - std::istringstream iss(line); - iss >> r >> z >> br >> bz; - GetIndices(r, z, ir, iz, dr, dz); - if (ir < 0 || iz < 0) { - std::cout << "FieldMapBrBz Warning: coordinates out of range (" << r << ", " << z << "), skipped it." - << std::endl; - } else { - Bvals[ir][iz] = {br * scale, bz * scale}; - // ROOT::Math::XYZPoint p(r, 0, z); - // std::cout << p << " -> " << trans*p << std::endl; - // std::cout << ir << ", " << iz << ", " << br << ", " << bz << std::endl; - } - } -} - -// get field components -void FieldMapBrBz::fieldComponents(const double* pos, double* field) -{ - // coordinate conversion - auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - - // coordinates conversion - const double r = sqrt(p.x() * p.x() + p.y() * p.y()); - const double z = p.z(); - const double phi = atan2(p.y(), p.x()); - - int ir, iz; - double dr, dz; - GetIndices(r, z, ir, iz, dr, dz); - - // out of the range - if (ir < 0 || iz < 0) { - return; - } - - // p1 p3 - // p - // p0 p2 - auto& p0 = Bvals[ir][iz]; - auto& p1 = Bvals[ir][iz + 1]; - auto& p2 = Bvals[ir + 1][iz]; - auto& p3 = Bvals[ir + 1][iz + 1]; - - // linear interpolation - double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - - double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; - - // convert Br Bz to Bx By Bz - auto B = trans * ROOT::Math::XYZPoint(Br * cos(phi), Br * sin(phi), Bz); - field[0] += B.x() * tesla; - field[1] += B.y() * tesla; - field[2] += B.z() * tesla; - return; -} - -// assign the field map to CartesianField -static Ref_t create_field_map_brbz(Detector& /*lcdd*/, xml::Handle_t handle) -{ - xml_comp_t x_par(handle); - - if (!x_par.hasAttr(_Unicode(field_map))) { - throw std::runtime_error("FieldMapBrBz Error: must have an xml attribute \"field_map\" for the field map."); - } - - CartesianField field; - std::string field_type = x_par.attr(_Unicode(field_type)); - - // dimensions - xml_comp_t x_dim = x_par.dimensions(); - - // min, max, step - xml_comp_t r_dim = x_dim.child(_Unicode(transverse)); - xml_comp_t z_dim = x_dim.child(_Unicode(longitudinal)); - - std::string field_map_file = x_par.attr(_Unicode(field_map)); - std::string field_map_url = x_par.attr(_Unicode(url)); - std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); - - EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); - - double field_map_scale = x_par.attr(_Unicode(scale)); - - if (!fs::exists(fs::path(field_map_file))) { - printout(ERROR, "FieldMapBrBz", "file " + field_map_file + " does not exist"); - printout(ERROR, "FieldMapBrBz", "use a FileLoader plugin before the field element"); - std::_Exit(EXIT_FAILURE); - } - - auto map = new FieldMapBrBz(field_type); - map->Configure(r_dim.rmin(), r_dim.rmax(), r_dim.step(), z_dim.zmin(), z_dim.zmax(), z_dim.step()); - - // translation, rotation - static double deg2r = ROOT::Math::Pi() / 180.; - RotationZYX rot(0., 0., 0.); - if (x_dim.hasChild(_Unicode(rotation))) { - xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); - rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); - } - - Translation3D trans(0., 0., 0.); - if (x_dim.hasChild(_Unicode(translation))) { - xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); - trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); - } - map->SetTransform(trans * rot); - - map->LoadMap(field_map_file, field_map_scale); - field.assign(map, x_par.nameStr(), "FieldMapBrBz"); - - return field; -} - -DECLARE_XMLELEMENT(epic_FieldMapBrBz, create_field_map_brbz) From 297827ac62e7b28e4dc1ce81e2441d736a42d590 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 18 Sep 2023 14:39:00 -0500 Subject: [PATCH 15/25] Change name of ideal lumi B field values. --- compact/far_backward/lumi/lumi_magnets.xml | 8 ++++---- compact/fields/beamline_10x100.xml | 4 ++-- compact/fields/beamline_10x110_H2.xml | 4 ++-- compact/fields/beamline_10x275.xml | 4 ++-- compact/fields/beamline_18x110_Au.xml | 4 ++-- compact/fields/beamline_18x110_H2.xml | 4 ++-- compact/fields/beamline_18x110_He3.xml | 4 ++-- compact/fields/beamline_18x110_Pb.xml | 4 ++-- compact/fields/beamline_18x275.xml | 4 ++-- compact/fields/beamline_5x100.xml | 4 ++-- compact/fields/beamline_5x110_H2.xml | 4 ++-- compact/fields/beamline_5x41.xml | 4 ++-- compact/fields/beamline_5x41_H2.xml | 4 ++-- compact/fields/beamline_5x41_He3.xml | 4 ++-- compact/fields/beamline_5x41_He4.xml | 4 ++-- 15 files changed, 32 insertions(+), 32 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 20dee0f4e..7d7d6d484 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -80,19 +80,19 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - diff --git a/compact/fields/beamline_10x100.xml b/compact/fields/beamline_10x100.xml index 548ca2ae2..2b34c4ac0 100644 --- a/compact/fields/beamline_10x100.xml +++ b/compact/fields/beamline_10x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_10x110_H2.xml b/compact/fields/beamline_10x110_H2.xml index e1fbea347..8c2be92e9 100644 --- a/compact/fields/beamline_10x110_H2.xml +++ b/compact/fields/beamline_10x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_10x275.xml b/compact/fields/beamline_10x275.xml index a2d0e47f0..cc3e0e73a 100644 --- a/compact/fields/beamline_10x275.xml +++ b/compact/fields/beamline_10x275.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_18x110_Au.xml b/compact/fields/beamline_18x110_Au.xml index 44725ebc8..3da33869c 100644 --- a/compact/fields/beamline_18x110_Au.xml +++ b/compact/fields/beamline_18x110_Au.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_H2.xml b/compact/fields/beamline_18x110_H2.xml index 7ab918a99..6994eef7a 100644 --- a/compact/fields/beamline_18x110_H2.xml +++ b/compact/fields/beamline_18x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_He3.xml b/compact/fields/beamline_18x110_He3.xml index d1bf496f1..aae21dd69 100644 --- a/compact/fields/beamline_18x110_He3.xml +++ b/compact/fields/beamline_18x110_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_Pb.xml b/compact/fields/beamline_18x110_Pb.xml index 9801622be..9d9423c0c 100644 --- a/compact/fields/beamline_18x110_Pb.xml +++ b/compact/fields/beamline_18x110_Pb.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x275.xml b/compact/fields/beamline_18x275.xml index 713ae0b2b..29f0e47d1 100644 --- a/compact/fields/beamline_18x275.xml +++ b/compact/fields/beamline_18x275.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x100.xml b/compact/fields/beamline_5x100.xml index 5e9a18f80..9e6d104fa 100644 --- a/compact/fields/beamline_5x100.xml +++ b/compact/fields/beamline_5x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x110_H2.xml b/compact/fields/beamline_5x110_H2.xml index 7a65b2ee3..7fb84a1ab 100644 --- a/compact/fields/beamline_5x110_H2.xml +++ b/compact/fields/beamline_5x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41.xml b/compact/fields/beamline_5x41.xml index ca787e71b..83e616bf5 100644 --- a/compact/fields/beamline_5x41.xml +++ b/compact/fields/beamline_5x41.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x41_H2.xml b/compact/fields/beamline_5x41_H2.xml index f38e05f7e..bb9a6dadb 100644 --- a/compact/fields/beamline_5x41_H2.xml +++ b/compact/fields/beamline_5x41_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He3.xml b/compact/fields/beamline_5x41_He3.xml index d474b021f..08894fff4 100644 --- a/compact/fields/beamline_5x41_He3.xml +++ b/compact/fields/beamline_5x41_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He4.xml b/compact/fields/beamline_5x41_He4.xml index 1a2561621..c1a3143f8 100644 --- a/compact/fields/beamline_5x41_He4.xml +++ b/compact/fields/beamline_5x41_He4.xml @@ -24,8 +24,8 @@ - - + + From 46360c7b7e35a03587f8f793507074e04c54dd51 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:48:15 +0000 Subject: [PATCH 16/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- compact/far_backward/lumi/lumi_magnets.xml | 2 +- src/FieldMapB.cpp | 36 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 7d7d6d484..2928734f7 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -79,7 +79,7 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - + Ideal fields - - + + Forward Fields diff --git a/compact/fields/beamline_10x110_H2.xml b/compact/fields/beamline_10x110_H2.xml index 8c2be92e9..e1fbea347 100644 --- a/compact/fields/beamline_10x110_H2.xml +++ b/compact/fields/beamline_10x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_10x275.xml b/compact/fields/beamline_10x275.xml index cc3e0e73a..a2d0e47f0 100644 --- a/compact/fields/beamline_10x275.xml +++ b/compact/fields/beamline_10x275.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_18x110_Au.xml b/compact/fields/beamline_18x110_Au.xml index 3da33869c..44725ebc8 100644 --- a/compact/fields/beamline_18x110_Au.xml +++ b/compact/fields/beamline_18x110_Au.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_H2.xml b/compact/fields/beamline_18x110_H2.xml index 6994eef7a..7ab918a99 100644 --- a/compact/fields/beamline_18x110_H2.xml +++ b/compact/fields/beamline_18x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_He3.xml b/compact/fields/beamline_18x110_He3.xml index aae21dd69..d1bf496f1 100644 --- a/compact/fields/beamline_18x110_He3.xml +++ b/compact/fields/beamline_18x110_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x110_Pb.xml b/compact/fields/beamline_18x110_Pb.xml index 9d9423c0c..9801622be 100644 --- a/compact/fields/beamline_18x110_Pb.xml +++ b/compact/fields/beamline_18x110_Pb.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_18x275.xml b/compact/fields/beamline_18x275.xml index 29f0e47d1..713ae0b2b 100644 --- a/compact/fields/beamline_18x275.xml +++ b/compact/fields/beamline_18x275.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x100.xml b/compact/fields/beamline_5x100.xml index 9e6d104fa..5e9a18f80 100644 --- a/compact/fields/beamline_5x100.xml +++ b/compact/fields/beamline_5x100.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x110_H2.xml b/compact/fields/beamline_5x110_H2.xml index 7fb84a1ab..7a65b2ee3 100644 --- a/compact/fields/beamline_5x110_H2.xml +++ b/compact/fields/beamline_5x110_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41.xml b/compact/fields/beamline_5x41.xml index 83e616bf5..ca787e71b 100644 --- a/compact/fields/beamline_5x41.xml +++ b/compact/fields/beamline_5x41.xml @@ -24,8 +24,8 @@ - - + + Forward Fields diff --git a/compact/fields/beamline_5x41_H2.xml b/compact/fields/beamline_5x41_H2.xml index bb9a6dadb..f38e05f7e 100644 --- a/compact/fields/beamline_5x41_H2.xml +++ b/compact/fields/beamline_5x41_H2.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He3.xml b/compact/fields/beamline_5x41_He3.xml index 08894fff4..d474b021f 100644 --- a/compact/fields/beamline_5x41_He3.xml +++ b/compact/fields/beamline_5x41_He3.xml @@ -24,8 +24,8 @@ - - + + diff --git a/compact/fields/beamline_5x41_He4.xml b/compact/fields/beamline_5x41_He4.xml index c1a3143f8..1a2561621 100644 --- a/compact/fields/beamline_5x41_He4.xml +++ b/compact/fields/beamline_5x41_He4.xml @@ -24,8 +24,8 @@ - - + + From 019992c8a233e6f69f2de26d5e1aed0f8a63c4fb Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 22 Sep 2023 15:20:28 -0500 Subject: [PATCH 18/25] Change comment syntax in xml file. Attempt to streamline calls to fieldComponents. --- compact/far_backward/lumi/lumi_magnets.xml | 5 +- src/FieldMapB.cpp | 198 +++++++++++---------- 2 files changed, 108 insertions(+), 95 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index 2928734f7..dc554c3aa 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -81,7 +81,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. Ideal fields - + Calculated fields dimensions); void LoadMap(const std::string& map_file, double scale); - void GetIndices(std::vector coord, std::vector *indices, std::vector *deltas); + bool GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ); + bool GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ); void SetTransform(const Transform3D& tr) { trans = tr; @@ -66,11 +67,15 @@ class FieldMapB : public dd4hep::CartesianField::Object { virtual void fieldComponents(const double* pos, double* field); private: - std::string coord_type; - Transform3D trans, trans_inv; - std::vector steps, mins, maxs; - std::vector>> Bvals_RZ; // {R}, {Z}, {Br,Bz} - std::vector>>> Bvals_XYZ; // {X}, {Y}, {Z}, {Bx,By,Bz} + bool case_BrBz; // is it BrBz or not (BxByBz) + Transform3D trans, trans_inv; // transformation matrices + std::vector steps, mins, maxs; // B map cell info + int ir, ix, iy, iz; // lookup indices + double ir_d, ix_d, iy_d, iz_d; // transient indices for std::modf + double dr, dx, dy, dz; // deltas for interpolation + std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} + ROOT::Math::XYZPoint B_interpolated; // interpolated B }; // constructor @@ -91,7 +96,12 @@ FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; } - coord_type = coord_type_str; + if( coord_type_str.compare("BrBz") == 0 ) { // BrBz + case_BrBz = true; + } + else { // BxByBz + case_BrBz = false; + } } // fill field vector @@ -104,7 +114,7 @@ void FieldMapB::Configure(std::vector dimensions) maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); } - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; @@ -116,8 +126,7 @@ void FieldMapB::Configure(std::vector dimensions) } } } - - if( coord_type.compare("BxByBz") == 0 ) { + else { int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; @@ -135,21 +144,42 @@ void FieldMapB::Configure(std::vector dimensions) } } -// get cell indices corresponding to point of interest -void FieldMapB::GetIndices(std::vector coord, std::vector *indices, std::vector *deltas) +// get RZ cell indices corresponding to point of interest +bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ) +{ + // boundary check + if( R > maxs[0] || R < mins[0] || Z > maxs[1] || Z < mins[1] ) { + return false; + } + + // get indices + *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); + *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); + + *idxR = static_cast( ir_d ); + *idxZ = static_cast( iz_d ); + + return true; +} + +// get XYZ cell indices corresponding to point of interest +bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ) { - for( uint i = 0; i < coord.size(); i++ ) { - // Range check - if( coord[i] < mins[i] || coord[i] > maxs[i] ) { - indices->clear(); - indices->resize( coord.size(), -1 ); - return; - } - - double temp_idx; - deltas->push_back( std::modf( (coord[i] - mins[i]) / steps[i], &temp_idx ) ); - indices->push_back( static_cast(temp_idx) ); + // boundary check + if( X > maxs[0] || X < mins[0] || Y > maxs[1] || Y < mins[1] || Z > maxs[2] || Z < mins[2] ) { + return false; } + + // get indices + *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); + *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); + *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); + + *idxX = static_cast( ix_d ); + *idxY = static_cast( iy_d ); + *idxZ = static_cast( iz_d ); + + return true; } // load data @@ -163,42 +193,38 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) std::vector coord = {}; std::vector Bcomp = {}; - std::vector indices = {}; - std::vector deltas = {}; while (std::getline(input, line).good()) { std::istringstream iss(line); coord.clear(); Bcomp.clear(); - indices.clear(); - deltas.clear(); - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { coord.resize(2); Bcomp.resize(2); iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; + + if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + } + else { + Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; + //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); + //std::cout << p << " -> " << trans*p << std::endl; + //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + } } - if( coord_type.compare("BxByBz") == 0 ) { + else { coord.resize(3); Bcomp.resize(3); iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; - } - GetIndices(coord, &indices, &deltas); - - if (std::count( indices.begin(), indices.end(), -1)) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it." - << std::endl; - } else { - if( coord_type.compare("BrBz") == 0 ) { - Bvals_RZ[ indices[0] ][ indices[1] ] = {Bcomp[0] * scale, Bcomp[1] * scale}; - //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); - //std::cout << p << " -> " << trans*p << std::endl; - //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; + if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { + std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; } - if( coord_type.compare("BxByBz") == 0 ) { - Bvals_XYZ[ indices[0] ][ indices[1] ][ indices[2] ] = {Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale}; + else { + Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; } } } @@ -210,81 +236,67 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // coordinate conversion auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - std::vector indices = {}; - std::vector deltas = {}; - ROOT::Math::XYZPoint B = ROOT::Math::XYZPoint(0,0,0); - - if( coord_type.compare("BrBz") == 0 ) { + if( case_BrBz ) { // coordinates conversion const double r = sqrt(p.x() * p.x() + p.y() * p.y()); const double z = p.z(); const double phi = atan2(p.y(), p.x()); - GetIndices({r, z}, &indices, &deltas); - - // out of the range - if (std::count( indices.begin(), indices.end(), -1)) { + if( ! GetIndices(r, z, &ir, &iz, &dr, &dz) ) { + // out of range return; } // p1 p3 // p // p0 p2 - auto& p0 = Bvals_RZ[indices[0]][indices[1]]; - auto& p1 = Bvals_RZ[indices[0]][indices[1] + 1]; - auto& p2 = Bvals_RZ[indices[0] + 1][indices[1]]; - auto& p3 = Bvals_RZ[indices[0] + 1][indices[1] + 1]; + auto& p0 = Bvals_RZ[ ir ][ iz ]; + auto& p1 = Bvals_RZ[ ir ][ iz + 1]; + auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; + auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; // Bilinear interpolation - double Br = p0[0] * (1 - deltas[0]) * (1 - deltas[1]) - + p1[0] * (1 - deltas[0]) * deltas[1] - + p2[0] * deltas[0] * (1 - deltas[1]) - + p3[0] * deltas[0] * deltas[1]; + double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - double Bz = p0[1] * (1 - deltas[0]) * (1 - deltas[1]) - + p1[1] * (1 - deltas[0]) * deltas[1] - + p2[1] * deltas[0] * (1 - deltas[1]) - + p3[1] * deltas[0] * deltas[1]; + double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz - B = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); - B = trans * B; + B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + B_interpolated = trans * B_interpolated; } + else { - if( coord_type.compare("BxByBz") == 0 ) { - - GetIndices({p.x(), p.y(), p.z()}, &indices, &deltas); - - // out of the range - if (std::count( indices.begin(), indices.end(), -1)) { - return; + if( ! GetIndices(p.x(), p.y(), p.z(), &ix, &iy, &iz, &dx, &dy, &dz) ) { + return; // out of range } + double b[3] = {0}; for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - double b00 = Bvals_XYZ[indices[0]][indices[1]][indices[2]][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2]][comp] * deltas[0]; - double b01 = Bvals_XYZ[indices[0]][indices[1]][indices[2] + 1][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1]][indices[2] + 1][comp] * deltas[0]; - double b10 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2]][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2]][comp] * deltas[0]; - double b11 = Bvals_XYZ[indices[0]][indices[1] + 1][indices[2] + 1][comp] * (1 - deltas[0]) - + Bvals_XYZ[indices[0] + 1][indices[1] + 1][indices[2] + 1][comp] * deltas[0]; - //// Next along Y, along 2 lines - double b0 = b00 * (1 - deltas[1]) + b10 * deltas[1]; - double b1 = b01 * (1 - deltas[1]) + b11 * deltas[1]; - //// Finally along Z - double b = b0 * (1 - deltas[2]) + b1 * deltas[2]; - if(comp == 0) { B.SetX( b ); } - if(comp == 1) { B.SetY( b ); } - if(comp == 2) { B.SetZ( b ); } + double b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; + double b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; + double b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; + double b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + // Next along Y, along 2 lines + double b0 = b00 * (1 - dy) + b10 * dy; + double b1 = b01 * (1 - dy) + b11 * dy; + // Finally along Z + b[comp] = b0 * (1 - dz) + b1 * dz; } + + B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); } - field[0] += B.x() * tesla; - field[1] += B.y() * tesla; - field[2] += B.z() * tesla; + field[0] += B_interpolated.x() * tesla; + field[1] += B_interpolated.y() * tesla; + field[2] += B_interpolated.z() * tesla; return; } @@ -323,7 +335,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); std::_Exit(EXIT_FAILURE); } - + std::string field_map_file = x_par.attr(_Unicode(field_map)); std::string field_map_url = x_par.attr(_Unicode(url)); std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); From ae0783f694858494178332cde70fb86b6300f8fb Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Mon, 25 Sep 2023 14:21:25 -0500 Subject: [PATCH 19/25] Changes as requested in the PR. --- src/FieldMapB.cpp | 135 +++++++++++++++++++++------------------------- 1 file changed, 62 insertions(+), 73 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 6b4ef9d82..302c87244 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -52,12 +52,19 @@ using namespace dd4hep; // implementation of the field map class FieldMapB : public dd4hep::CartesianField::Object { + + enum FieldCoord { + BrBz, + BxByBz + }; + + public: FieldMapB(const std::string& field_type_str = "magnetic", const std::string& coord_type_str = "BrBz"); void Configure(std::vector dimensions); - void LoadMap(const std::string& map_file, double scale); - bool GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ); - bool GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ); + void LoadMap(const std::string& map_file, float scale); + bool GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ); + bool GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ); void SetTransform(const Transform3D& tr) { trans = tr; @@ -67,14 +74,13 @@ class FieldMapB : public dd4hep::CartesianField::Object { virtual void fieldComponents(const double* pos, double* field); private: - bool case_BrBz; // is it BrBz or not (BxByBz) + FieldCoord fieldCoord; // field coordinate type Transform3D trans, trans_inv; // transformation matrices - std::vector steps, mins, maxs; // B map cell info + std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices - double ir_d, ix_d, iy_d, iz_d; // transient indices for std::modf - double dr, dx, dy, dz; // deltas for interpolation - std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} - std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} + float dr, dx, dy, dz; // deltas for interpolation + std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} + std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} ROOT::Math::XYZPoint B_interpolated; // interpolated B }; @@ -93,14 +99,14 @@ FieldMapB::FieldMapB(const std::string& field_type_str, const std::string& coord DD4HEP_FIELD_TYPE = CartesianField::ELECTRIC; } else { DD4HEP_FIELD_TYPE = CartesianField::UNKNOWN; - std::cout << "FieldMapB Warning: Unknown field type " << field_type_str << "!" << std::endl; + printout(ERROR, "FieldMap","Unknown field type " + ftype); } if( coord_type_str.compare("BrBz") == 0 ) { // BrBz - case_BrBz = true; + fieldCoord = FieldCoord::BrBz; } else { // BxByBz - case_BrBz = false; + fieldCoord = FieldCoord::BxByBz; } } @@ -110,42 +116,36 @@ void FieldMapB::Configure(std::vector dimensions) // Fill vectors with step size, min, max for each dimension for( auto el : dimensions ) { steps.push_back( el.step() ); - mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); - maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); + mins.push_back( getAttrOrDefault(el, _Unicode(min), 0) ); + maxs.push_back( getAttrOrDefault(el, _Unicode(max), 0) ); } - if( case_BrBz ) { - int nr = int((maxs[0] - mins[0]) / steps[0]) + 2; - int nz = int((maxs[1] - mins[1]) / steps[1]) + 2; + if( fieldCoord == FieldCoord::BrBz ) { + int nr = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; + int nz = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; Bvals_RZ.resize(nr); for (auto& B2 : Bvals_RZ) { B2.resize(nz); - for (auto& B : B2) { - B.resize(2, 0.); // Br, Bz - } } } else { - int nx = int((maxs[0] - mins[0]) / steps[0]) + 2; - int ny = int((maxs[1] - mins[1]) / steps[1]) + 2; - int nz = int((maxs[2] - mins[2]) / steps[2]) + 2; + int nx = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; + int ny = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; + int nz = std::roundf( (maxs[2] - mins[2]) / steps[2] ) + 1; Bvals_XYZ.resize(nx); for (auto& B3 : Bvals_XYZ) { B3.resize(ny); for (auto& B2 : B3) { B2.resize(nz); - for (auto& B : B2) { - B.resize(3, 0.); // Bx, By, Bz - } } } } } // get RZ cell indices corresponding to point of interest -bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *deltaR, double *deltaZ) +bool FieldMapB::GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ) { // boundary check if( R > maxs[0] || R < mins[0] || Z > maxs[1] || Z < mins[1] ) { @@ -153,17 +153,14 @@ bool FieldMapB::GetIndices(double R, double Z, int *idxR, int *idxZ, double *del } // get indices - *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); - *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); - - *idxR = static_cast( ir_d ); - *idxZ = static_cast( iz_d ); + *deltaR = std::remquof( (R - mins[0]), steps[0], idxR ); + *deltaZ = std::remquof( (Z - mins[1]), steps[1], idxZ ); return true; } // get XYZ cell indices corresponding to point of interest -bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, int *idxZ, double *deltaX, double *deltaY, double *deltaZ) +bool FieldMapB::GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ) { // boundary check if( X > maxs[0] || X < mins[0] || Y > maxs[1] || Y < mins[1] || Z > maxs[2] || Z < mins[2] ) { @@ -171,28 +168,24 @@ bool FieldMapB::GetIndices(double X, double Y, double Z, int *idxX, int *idxY, i } // get indices - *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); - *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); - *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); - - *idxX = static_cast( ix_d ); - *idxY = static_cast( iy_d ); - *idxZ = static_cast( iz_d ); + *deltaX = std::remquof( (X - mins[0]), steps[0], idxX ); + *deltaY = std::remquof( (Y - mins[1]), steps[1], idxY ); + *deltaZ = std::remquof( (Z - mins[2]), steps[2], idxZ ); return true; } // load data -void FieldMapB::LoadMap(const std::string& map_file, double scale) +void FieldMapB::LoadMap(const std::string& map_file, float scale) { std::string line; std::ifstream input(map_file); - if (!input) { - std::cout << "FieldMapB Error: file \"" << map_file << "\" cannot be read." << std::endl; + if( ! input ) { + printout(ERROR,"FieldMapB", "FieldMapB Error: file " + map_file + " cannot be read."); } - std::vector coord = {}; - std::vector Bcomp = {}; + std::vector coord = {}; + std::vector Bcomp = {}; while (std::getline(input, line).good()) { std::istringstream iss(line); @@ -200,19 +193,16 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) coord.clear(); Bcomp.clear(); - if( case_BrBz ) { + if( fieldCoord == FieldCoord::BrBz) { coord.resize(2); Bcomp.resize(2); iss >> coord[0] >> coord[1] >> Bcomp[0] >> Bcomp[1]; if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } else { Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; - //ROOT::Math::XYZPoint p(coord[0], 0, coord[1]); - //std::cout << p << " -> " << trans*p << std::endl; - //std::cout << indices[0] << ", " << indices[1] << ", " << Bcomp[0] << ", " << Bcomp[1] << std::endl; } } else { @@ -221,7 +211,7 @@ void FieldMapB::LoadMap(const std::string& map_file, double scale) iss >> coord[0] >> coord[1] >> coord[2] >> Bcomp[0] >> Bcomp[1] >> Bcomp[2]; if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { - std::cout << "FieldMapB Warning: coordinates out of range, skipped it."<< std::endl; + printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } else { Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; @@ -236,11 +226,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // coordinate conversion auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); - if( case_BrBz ) { + if( fieldCoord == FieldCoord::BrBz ) { // coordinates conversion - const double r = sqrt(p.x() * p.x() + p.y() * p.y()); - const double z = p.z(); - const double phi = atan2(p.y(), p.x()); + const float r = sqrt(p.x() * p.x() + p.y() * p.y()); + const float z = p.z(); + const float phi = atan2(p.y(), p.x()); if( ! GetIndices(r, z, &ir, &iz, &dr, &dz) ) { // out of range @@ -256,11 +246,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; // Bilinear interpolation - double Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz - + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; + float Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz + + p2[0] * dr * (1 - dz) + p3[0] * dr * dz; - double Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz - + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; + float Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); @@ -272,21 +262,21 @@ void FieldMapB::fieldComponents(const double* pos, double* field) return; // out of range } - double b[3] = {0}; + float b[3] = {0}; for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - double b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; - double b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; - double b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; - double b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; + float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; + float b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; + float b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; // Next along Y, along 2 lines - double b0 = b00 * (1 - dy) + b10 * dy; - double b1 = b01 * (1 - dy) + b11 * dy; + float b0 = b00 * (1 - dy) + b10 * dy; + float b1 = b01 * (1 - dy) + b11 * dy; // Finally along Z b[comp] = b0 * (1 - dz) + b1 * dz; } @@ -313,7 +303,6 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) CartesianField field; std::string field_type = x_par.attr(_Unicode(field_type)); - // coordinate type: "BrBz" or "BxByBz" std::string coord_type = x_par.attr(_Unicode(coord_type)); // dimensions @@ -342,7 +331,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) EnsureFileFromURLExists(field_map_url, field_map_file, field_map_cache); - double field_map_scale = x_par.attr(_Unicode(scale)); + float field_map_scale = x_par.attr(_Unicode(scale)); if (!fs::exists(fs::path(field_map_file))) { printout(ERROR, "FieldMapB", "file " + field_map_file + " does not exist"); @@ -354,7 +343,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) map->Configure( dimensions ); // translation, rotation - static double deg2r = ROOT::Math::Pi() / 180.; + static float deg2r = ROOT::Math::Pi() / 180.; RotationZYX rot(0., 0., 0.); if (x_dim.hasChild(_Unicode(rotation))) { xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); From 517100827f018b47c14f258ef61f81edfe2eb463 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Fri, 22 Sep 2023 20:20:42 +0000 Subject: [PATCH 20/25] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/FieldMapB.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 302c87244..d82cd94e9 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -153,8 +153,10 @@ bool FieldMapB::GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR } // get indices - *deltaR = std::remquof( (R - mins[0]), steps[0], idxR ); - *deltaZ = std::remquof( (Z - mins[1]), steps[1], idxZ ); + *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); + *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); + *idxR = static_cast( ir_d ); + *idxZ = static_cast( iz_d ); return true; } @@ -168,9 +170,12 @@ bool FieldMapB::GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int } // get indices - *deltaX = std::remquof( (X - mins[0]), steps[0], idxX ); - *deltaY = std::remquof( (Y - mins[1]), steps[1], idxY ); - *deltaZ = std::remquof( (Z - mins[2]), steps[2], idxZ ); + *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); + *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); + *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); + *idxX = static_cast( ix_d ); + *idxY = static_cast( iy_d ); + *idxZ = static_cast( iz_d ); return true; } @@ -280,7 +285,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // Finally along Z b[comp] = b0 * (1 - dz) + b1 * dz; } - + B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); } @@ -324,7 +329,7 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) printout(ERROR, "FieldMapB", "Coordinate type: " + coord_type + ", is not BrBz nor BxByBz"); std::_Exit(EXIT_FAILURE); } - + std::string field_map_file = x_par.attr(_Unicode(field_map)); std::string field_map_url = x_par.attr(_Unicode(url)); std::string field_map_cache = getAttrOrDefault(x_par, _Unicode(cache), ""); From 069a65c9ee4fdeff84499c36f4be421758944e96 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 29 Sep 2023 12:05:43 -0500 Subject: [PATCH 21/25] Remove transformation of the B field for the BrBz case. Multiply by tesla units once when the field is loaded. Remove unnecessary intermediate variable, B_interpolated. --- src/FieldMapB.cpp | 47 +++++++++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 22 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index d82cd94e9..78505bc9f 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -81,7 +81,6 @@ class FieldMapB : public dd4hep::CartesianField::Object { float dr, dx, dy, dz; // deltas for interpolation std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} - ROOT::Math::XYZPoint B_interpolated; // interpolated B }; // constructor @@ -207,7 +206,9 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } else { - Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale }; + Bvals_RZ[ ir ][ iz ] = + { Bcomp[0] * scale * float(tesla), + Bcomp[1] * scale * float(tesla) }; } } else { @@ -219,7 +220,10 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } else { - Bvals_XYZ[ ix ][ iy ][ iz ] = { Bcomp[0] * scale, Bcomp[1] * scale, Bcomp[2] * scale }; + Bvals_XYZ[ ix ][ iy ][ iz ] = + { Bcomp[0] * scale * float(tesla), + Bcomp[1] * scale * float(tesla), + Bcomp[2] * scale * float(tesla) }; } } } @@ -245,10 +249,10 @@ void FieldMapB::fieldComponents(const double* pos, double* field) // p1 p3 // p // p0 p2 - auto& p0 = Bvals_RZ[ ir ][ iz ]; - auto& p1 = Bvals_RZ[ ir ][ iz + 1]; - auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; - auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1]; + auto& p0 = Bvals_RZ[ ir ][ iz ]; + auto& p1 = Bvals_RZ[ ir ][ iz + 1 ]; + auto& p2 = Bvals_RZ[ ir + 1 ][ iz ]; + auto& p3 = Bvals_RZ[ ir + 1 ][ iz + 1 ]; // Bilinear interpolation float Br = p0[0] * (1 - dr) * (1 - dz) + p1[0] * (1 - dr) * dz @@ -258,8 +262,9 @@ void FieldMapB::fieldComponents(const double* pos, double* field) + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz - B_interpolated = ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); - B_interpolated = trans * B_interpolated; + field[0] += Br * sin(phi); + field[1] += Br * cos(phi); + field[2] += Bz; } else { @@ -271,14 +276,14 @@ void FieldMapB::fieldComponents(const double* pos, double* field) for(int comp = 0; comp < 3; comp++) { // field component loop // Trilinear interpolation // First along X, along 4 lines - float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz ][comp] * dx; - float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy ][ iz + 1][comp] * dx; - float b10 = Bvals_XYZ[ ix ][ iy + 1][ iz ][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz ][comp] * dx; - float b11 = Bvals_XYZ[ ix ][ iy + 1][ iz + 1][comp] * (1 - dx) - + Bvals_XYZ[ ix + 1][ iy + 1][ iz + 1][comp] * dx; + float b00 = Bvals_XYZ[ ix ][ iy ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy ][ iz ][comp] * dx; + float b01 = Bvals_XYZ[ ix ][ iy ][ iz + 1 ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy ][ iz + 1 ][comp] * dx; + float b10 = Bvals_XYZ[ ix ][ iy + 1 ][ iz ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy + 1 ][ iz ][comp] * dx; + float b11 = Bvals_XYZ[ ix ][ iy + 1 ][ iz + 1 ][comp] * (1 - dx) + + Bvals_XYZ[ ix + 1 ][ iy + 1 ][ iz + 1 ][comp] * dx; // Next along Y, along 2 lines float b0 = b00 * (1 - dy) + b10 * dy; float b1 = b01 * (1 - dy) + b11 * dy; @@ -286,13 +291,11 @@ void FieldMapB::fieldComponents(const double* pos, double* field) b[comp] = b0 * (1 - dz) + b1 * dz; } - B_interpolated = ROOT::Math::XYZPoint( b[0], b[1], b[2] ); + field[0] += b[0]; + field[1] += b[1]; + field[2] += b[2]; } - field[0] += B_interpolated.x() * tesla; - field[1] += B_interpolated.y() * tesla; - field[2] += B_interpolated.z() * tesla; - return; } From bb53bbb581fee08368d56a5e8f0f72a4b8db5b0d Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 6 Oct 2023 15:22:20 -0500 Subject: [PATCH 22/25] WIP. Add field vector rotation separate from field coord translation vector. --- compact/far_backward/lumi/lumi_magnets.xml | 8 ++-- compact/fields/marco.xml | 4 +- src/FieldMapB.cpp | 51 +++++++++++++--------- 3 files changed, 36 insertions(+), 27 deletions(-) diff --git a/compact/far_backward/lumi/lumi_magnets.xml b/compact/far_backward/lumi/lumi_magnets.xml index dc554c3aa..42e8aad0d 100644 --- a/compact/far_backward/lumi/lumi_magnets.xml +++ b/compact/far_backward/lumi/lumi_magnets.xml @@ -107,8 +107,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - - + + @@ -121,8 +121,8 @@ Construct the sweeper and analyzer dipole magnets for the luminosity subsystem. - - + + diff --git a/compact/fields/marco.xml b/compact/fields/marco.xml index 704513058..931c8d7f1 100644 --- a/compact/fields/marco.xml +++ b/compact/fields/marco.xml @@ -11,8 +11,8 @@ - - + + diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 78505bc9f..6ee8bc57a 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -65,17 +65,23 @@ class FieldMapB : public dd4hep::CartesianField::Object { void LoadMap(const std::string& map_file, float scale); bool GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR, float *deltaZ); bool GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int *idxZ, float *deltaX, float *deltaY, float *deltaZ); - void SetTransform(const Transform3D& tr) + void SetCoordTranslation(const Transform3D& tr) { - trans = tr; - trans_inv = tr.Inverse(); + coordTranslate = tr; + coordTranslate_inv = tr.Inverse(); + } + void SetFieldRotation(const Transform3D& tr) + { + fieldRot = tr; + fieldRot_inv = tr.Inverse(); } virtual void fieldComponents(const double* pos, double* field); private: FieldCoord fieldCoord; // field coordinate type - Transform3D trans, trans_inv; // transformation matrices + Transform3D coordTranslate, coordTranslate_inv; // coord translation + Transform3D fieldRot, fieldRot_inv; // field rotation std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices float dr, dx, dy, dz; // deltas for interpolation @@ -205,7 +211,7 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) if( ! GetIndices( coord[0], coord[1], &ir, &iz, &dr, &dz) ) { printout(WARNING, "FieldMapB", "coordinates out of range, skipped it."); } - else { + else { // scale field Bvals_RZ[ ir ][ iz ] = { Bcomp[0] * scale * float(tesla), Bcomp[1] * scale * float(tesla) }; @@ -219,11 +225,11 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) if( ! GetIndices(coord[0], coord[1], coord[2], &ix, &iy, &iz, &dx, &dy, &dz) ) { printout(WARNING, "FieldMap","coordinates out of range, skipped it."); } - else { - Bvals_XYZ[ ix ][ iy ][ iz ] = - { Bcomp[0] * scale * float(tesla), - Bcomp[1] * scale * float(tesla), - Bcomp[2] * scale * float(tesla) }; + else { // scale and rotate B field vector + auto B = ROOT::Math::XYZPoint( Bcomp[0], Bcomp[1], Bcomp[2] ); + B *= scale * float(tesla); + B = fieldRot * B; + Bvals_XYZ[ ix ][ iy ][ iz ] = { float(B.x()), float(B.y()), float(B.z()) }; } } } @@ -233,7 +239,7 @@ void FieldMapB::LoadMap(const std::string& map_file, float scale) void FieldMapB::fieldComponents(const double* pos, double* field) { // coordinate conversion - auto p = trans_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); + auto p = coordTranslate_inv * ROOT::Math::XYZPoint(pos[0], pos[1], pos[2]); if( fieldCoord == FieldCoord::BrBz ) { // coordinates conversion @@ -261,12 +267,13 @@ void FieldMapB::fieldComponents(const double* pos, double* field) float Bz = p0[1] * (1 - dr) * (1 - dz) + p1[1] * (1 - dr) * dz + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; - // convert Br Bz to Bx By Bz - field[0] += Br * sin(phi); - field[1] += Br * cos(phi); - field[2] += Bz; + // convert Br Bz to Bx By Bz and rotate field + auto B = fieldRot * ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + field[0] += B.x(); + field[1] += B.y(); + field[2] += B.z(); } - else { + else { // BxByBz if( ! GetIndices(p.x(), p.y(), p.z(), &ix, &iy, &iz, &dx, &dy, &dz) ) { return; // out of range @@ -291,6 +298,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) b[comp] = b0 * (1 - dz) + b1 * dz; } + // field rotation done in LoadMap() field[0] += b[0]; field[1] += b[1]; field[2] += b[2]; @@ -353,17 +361,18 @@ static Ref_t create_field_map_b(Detector& /*lcdd*/, xml::Handle_t handle) // translation, rotation static float deg2r = ROOT::Math::Pi() / 180.; RotationZYX rot(0., 0., 0.); - if (x_dim.hasChild(_Unicode(rotation))) { - xml_comp_t rot_dim = x_dim.child(_Unicode(rotation)); + if (x_dim.hasChild(_Unicode(rotationField))) { + xml_comp_t rot_dim = x_dim.child(_Unicode(rotationField)); rot = RotationZYX(rot_dim.z() * deg2r, rot_dim.y() * deg2r, rot_dim.x() * deg2r); } Translation3D trans(0., 0., 0.); - if (x_dim.hasChild(_Unicode(translation))) { - xml_comp_t trans_dim = x_dim.child(_Unicode(translation)); + if (x_dim.hasChild(_Unicode(translationCoord))) { + xml_comp_t trans_dim = x_dim.child(_Unicode(translationCoord)); trans = Translation3D(trans_dim.x(), trans_dim.y(), trans_dim.z()); } - map->SetTransform(trans * rot); + map->SetCoordTranslation( Transform3D(trans) ); + map->SetFieldRotation( Transform3D(rot) ); map->LoadMap(field_map_file, field_map_scale); field.assign(map, x_par.nameStr(), "FieldMapB"); From eebc4a6ff334403fd8a94ce565ceebb206f5f4d3 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Fri, 6 Oct 2023 16:42:53 -0500 Subject: [PATCH 23/25] Bug fix: wrong usage of std::remquof. Go back to using std::modf, with transient floats. --- src/FieldMapB.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 6ee8bc57a..06c9f8855 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -84,6 +84,7 @@ class FieldMapB : public dd4hep::CartesianField::Object { Transform3D fieldRot, fieldRot_inv; // field rotation std::vector steps, mins, maxs; // B map cell info int ir, ix, iy, iz; // lookup indices + float idx_1_f, idx_2_f, idx_3_f; // transient float indicies float dr, dx, dy, dz; // deltas for interpolation std::vector>> Bvals_RZ; // B map values: {R}, {Z}, {Br,Bz} std::vector>>> Bvals_XYZ; // B map values: {X}, {Y}, {Z}, {Bx,By,Bz} @@ -158,10 +159,10 @@ bool FieldMapB::GetIndices(float R, float Z, int *idxR, int *idxZ, float *deltaR } // get indices - *deltaR = std::modf( (R - mins[0]) / steps[0], &ir_d ); - *deltaZ = std::modf( (Z - mins[1]) / steps[1], &iz_d ); - *idxR = static_cast( ir_d ); - *idxZ = static_cast( iz_d ); + *deltaR = std::modf( (R - mins[0]) / steps[0], &idx_1_f ); + *deltaZ = std::modf( (Z - mins[1]) / steps[1], &idx_2_f ); + *idxR = static_cast(idx_1_f); + *idxZ = static_cast(idx_2_f); return true; } @@ -175,12 +176,12 @@ bool FieldMapB::GetIndices(float X, float Y, float Z, int *idxX, int *idxY, int } // get indices - *deltaX = std::modf( (X - mins[0]) / steps[0], &ix_d ); - *deltaY = std::modf( (Y - mins[1]) / steps[1], &iy_d ); - *deltaZ = std::modf( (Z - mins[2]) / steps[2], &iz_d ); - *idxX = static_cast( ix_d ); - *idxY = static_cast( iy_d ); - *idxZ = static_cast( iz_d ); + *deltaX = std::modf( (X - mins[0]) / steps[0], &idx_1_f ); + *deltaY = std::modf( (Y - mins[1]) / steps[1], &idx_2_f ); + *deltaZ = std::modf( (Z - mins[2]) / steps[2], &idx_3_f ); + *idxX = static_cast(idx_1_f); + *idxY = static_cast(idx_2_f); + *idxZ = static_cast(idx_3_f); return true; } From 6903dfd406cbde642cd352e910cfea171739f915 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan <43478603+dhevang@users.noreply.github.com> Date: Mon, 9 Oct 2023 15:53:38 -0500 Subject: [PATCH 24/25] Swap Bx and By components in new file as per the recent bug fix. Co-authored-by: Dmitry Kalinkin --- src/FieldMapB.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 06c9f8855..39992fe0d 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -269,7 +269,7 @@ void FieldMapB::fieldComponents(const double* pos, double* field) + p2[1] * dr * (1 - dz) + p3[1] * dr * dz; // convert Br Bz to Bx By Bz and rotate field - auto B = fieldRot * ROOT::Math::XYZPoint(Br * sin(phi), Br * cos(phi), Bz); + auto B = fieldRot * ROOT::Math::XYZPoint(Br * cos(phi), Br * sin(phi), Bz); field[0] += B.x(); field[1] += B.y(); field[2] += B.z(); From 6a2e18c5e23bd44c8b21df34d97d2b57a25892a8 Mon Sep 17 00:00:00 2001 From: Dhevan Gangadharan Date: Wed, 11 Oct 2023 12:41:30 -0500 Subject: [PATCH 25/25] Increase grid sizes by 1 in order to prevent seg faults for cases at upper limits. --- src/FieldMapB.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/FieldMapB.cpp b/src/FieldMapB.cpp index 39992fe0d..625cd6fa4 100644 --- a/src/FieldMapB.cpp +++ b/src/FieldMapB.cpp @@ -127,8 +127,9 @@ void FieldMapB::Configure(std::vector dimensions) } if( fieldCoord == FieldCoord::BrBz ) { - int nr = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; - int nz = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; + // N bins increased by 1 beyond grid size to account for edge cases at upper limits + int nr = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 2; + int nz = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 2; Bvals_RZ.resize(nr); for (auto& B2 : Bvals_RZ) { @@ -136,9 +137,10 @@ void FieldMapB::Configure(std::vector dimensions) } } else { - int nx = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 1; - int ny = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 1; - int nz = std::roundf( (maxs[2] - mins[2]) / steps[2] ) + 1; + // N bins increased by 1 beyond grid size to account for edge cases at upper limits + int nx = std::roundf( (maxs[0] - mins[0]) / steps[0] ) + 2; + int ny = std::roundf( (maxs[1] - mins[1]) / steps[1] ) + 2; + int nz = std::roundf( (maxs[2] - mins[2]) / steps[2] ) + 2; Bvals_XYZ.resize(nx); for (auto& B3 : Bvals_XYZ) {