File indexing completed on 2025-08-06 08:10:46
0001
0002
0003
0004
0005
0006
0007
0008
0009 #include "ActsExamples/Io/Csv/CsvBFieldWriter.hpp"
0010
0011 #include "Acts/Definitions/Algebra.hpp"
0012 #include "Acts/Definitions/Units.hpp"
0013 #include "Acts/MagneticField/InterpolatedBFieldMap.hpp"
0014 #include "Acts/MagneticField/MagneticFieldContext.hpp"
0015 #include "Acts/Utilities/Logger.hpp"
0016 #include "Acts/Utilities/Result.hpp"
0017 #include "Acts/Utilities/VectorHelpers.hpp"
0018
0019 #include <iomanip>
0020 #include <ostream>
0021 #include <stdexcept>
0022 #include <vector>
0023
0024 #include <dfe/dfe_io_dsv.hpp>
0025
0026 namespace ActsExamples {
0027 template <CsvBFieldWriter::CoordinateType Coord, bool Grid>
0028 void CsvBFieldWriter::run(const Config<Coord, Grid>& config,
0029 Acts::Logging::Level level) {
0030 ACTS_LOCAL_LOGGER(Acts::getDefaultLogger("CsvBFieldWriter", level));
0031
0032
0033 using ConfigType = std::decay_t<decltype(config)>;
0034 using FieldType = typename decltype(ConfigType::bField)::element_type;
0035 using Vector = Acts::ActsVector<ConfigType::NDims>;
0036
0037 FieldType& field = *config.bField;
0038
0039
0040
0041
0042 std::vector<std::string> fields;
0043
0044 if constexpr (Coord == CoordinateType::XYZ) {
0045 fields = {"x", "y", "z", "Bx", "By", "Bz"};
0046 } else {
0047 fields = {"r", "z", "Br", "Bz"};
0048 }
0049
0050
0051
0052 dfe::io_dsv_impl::DsvWriter<','> writer(fields, config.fileName);
0053
0054
0055
0056
0057 std::array<std::size_t, ConfigType::NDims> bins{};
0058 Vector min, max;
0059
0060 if constexpr (Grid) {
0061
0062
0063 if (bins.size() != ConfigType::NDims ||
0064 field.getMin().size() != ConfigType::NDims ||
0065 field.getMax().size() != ConfigType::NDims) {
0066 throw std::invalid_argument("Incorrect input B-field dimensionality.");
0067 }
0068
0069
0070
0071
0072 for (std::size_t i = 0; i < ConfigType::NDims; ++i) {
0073
0074
0075 bins[i] = field.getNBins()[i];
0076 min[i] = field.getMin()[i];
0077 max[i] = field.getMax()[i];
0078
0079
0080 if (config.bins[i]) {
0081 bins[i] = *config.bins[i];
0082 }
0083
0084 if (config.range[i][0]) {
0085 min[i] = *config.range[i][0];
0086 }
0087
0088 if (config.range[i][1]) {
0089 max[i] = *config.range[i][1];
0090 }
0091 }
0092 } else {
0093
0094
0095
0096 for (std::size_t i = 0; i < ConfigType::NDims; ++i) {
0097 bins[i] = config.bins[i];
0098 min[i] = config.range[i][0];
0099 max[i] = config.range[i][1];
0100 }
0101 }
0102
0103
0104 Vector delta;
0105
0106 for (std::size_t i = 0; i < ConfigType::NDims; ++i) {
0107 delta[i] = (max[i] - min[i]) / (bins[i] - 1);
0108 }
0109
0110
0111
0112 Acts::MagneticFieldContext mctx{};
0113 typename FieldType::Cache cache = field.makeCache(mctx);
0114
0115
0116
0117
0118 if constexpr (Coord == CoordinateType::XYZ) {
0119 ACTS_INFO("Writing XYZ field of size " << bins[0] << " x " << bins[1]
0120 << " x " << bins[2] << " to file "
0121 << config.fileName << "...");
0122
0123 std::size_t total_items = bins[0] * bins[1] * bins[2];
0124
0125
0126
0127
0128 for (std::size_t x = 0; x < bins[0]; ++x) {
0129 for (std::size_t y = 0; y < bins[1]; ++y) {
0130 for (std::size_t z = 0; z < bins[2]; ++z) {
0131
0132
0133 Acts::Vector3 pos = {x * delta[0] + min[0], y * delta[1] + min[1],
0134 z * delta[2] + min[2]};
0135
0136 Acts::Vector3 bField;
0137 if (auto fieldMap =
0138 dynamic_cast<const Acts::InterpolatedMagneticField*>(
0139 &field)) {
0140
0141
0142
0143 bField = fieldMap->getFieldUnchecked(pos);
0144 } else {
0145 Acts::Result<Acts::Vector3> flx = field.getField(pos, cache);
0146
0147
0148
0149
0150 if (flx.ok()) {
0151 bField = *flx;
0152 } else {
0153 throw std::runtime_error("B-field returned a non-extant value!");
0154 }
0155 }
0156
0157 writer.append(pos[0] / Acts::UnitConstants::mm,
0158 pos[1] / Acts::UnitConstants::mm,
0159 pos[2] / Acts::UnitConstants::mm,
0160 bField[0] / Acts::UnitConstants::T,
0161 bField[1] / Acts::UnitConstants::T,
0162 bField[2] / Acts::UnitConstants::T);
0163
0164
0165
0166
0167 std::size_t idx = (x * bins[1] * bins[2]) + (y * bins[2]) + z + 1;
0168
0169 if (idx % 10000 == 0 || idx == total_items) {
0170 ACTS_VERBOSE("Wrote " << idx << " out of " << total_items
0171 << " items (" << std::setprecision(3)
0172 << ((100.f * idx) / total_items) << "%).");
0173 }
0174 }
0175 }
0176 }
0177 } else {
0178 ACTS_INFO("Writing RZ field of size " << bins[0] << " x " << bins[1]
0179 << " to file " << config.fileName
0180 << "...");
0181
0182 std::size_t total_items = bins[0] * bins[1];
0183
0184
0185
0186
0187 for (std::size_t r = 0; r < bins[0]; ++r) {
0188 for (std::size_t z = 0; z < bins[1]; ++z) {
0189
0190
0191 Acts::Vector3 pos(min[0] + r * delta[0], 0.f, min[1] + z * delta[1]);
0192
0193 Acts::Vector3 bField;
0194 if (auto fieldMap =
0195 dynamic_cast<const Acts::InterpolatedMagneticField*>(&field)) {
0196
0197
0198
0199 bField = fieldMap->getFieldUnchecked(pos);
0200 } else {
0201 Acts::Result<Acts::Vector3> flx = field.getField(pos, cache);
0202
0203
0204
0205
0206
0207 if (flx.ok()) {
0208 bField = *flx;
0209 } else {
0210 throw std::runtime_error("B-field returned a non-extant value!");
0211 }
0212 }
0213
0214 writer.append(
0215 pos[0] / Acts::UnitConstants::mm, pos[2] / Acts::UnitConstants::mm,
0216 Acts::VectorHelpers::perp(bField) / Acts::UnitConstants::T,
0217 bField[2] / Acts::UnitConstants::T);
0218
0219
0220
0221 std::size_t idx = (r * bins[1]) + z + 1;
0222
0223 if (idx % 10000 == 0 || idx == total_items) {
0224 ACTS_VERBOSE("Wrote " << idx << " out of " << total_items
0225 << " items (" << std::setprecision(3)
0226 << ((100.f * idx) / total_items) << "%).");
0227 }
0228 }
0229 }
0230 }
0231 }
0232
0233
0234
0235
0236
0237
0238 template void CsvBFieldWriter::run<CsvBFieldWriter::CoordinateType::XYZ, true>(
0239 const Config<CoordinateType::XYZ, true>&, Acts::Logging::Level);
0240 template void CsvBFieldWriter::run<CsvBFieldWriter::CoordinateType::RZ, true>(
0241 const Config<CoordinateType::RZ, true>&, Acts::Logging::Level);
0242 template void CsvBFieldWriter::run<CsvBFieldWriter::CoordinateType::XYZ, false>(
0243 const Config<CoordinateType::XYZ, false>&, Acts::Logging::Level);
0244 template void CsvBFieldWriter::run<CsvBFieldWriter::CoordinateType::RZ, false>(
0245 const Config<CoordinateType::RZ, false>&, Acts::Logging::Level);
0246 }