Back to home page

sPhenix code displayed by LXR

 
 

    


File indexing completed on 2025-08-06 08:17:58

0001 #include "PHField3DCartesian.h"
0002 
0003 #include <phool/phool.h>
0004 
0005 #include <TDirectory.h>  // for TDirectory, gDirectory
0006 #include <TFile.h>
0007 #include <TNtuple.h>
0008 #include <TSystem.h>
0009 
0010 #include <Geant4/G4SystemOfUnits.hh>
0011 
0012 // stacktrace gives a shadow warning
0013 #pragma GCC diagnostic push
0014 #pragma GCC diagnostic ignored "-Wshadow"
0015 #include <boost/stacktrace.hpp>
0016 #pragma GCC diagnostic pop
0017 
0018 #include <cassert>
0019 #include <cmath>
0020 #include <cstdlib>
0021 #include <iostream>
0022 #include <iterator>
0023 #include <set>
0024 #include <utility>
0025 
0026 PHField3DCartesian::PHField3DCartesian(const std::string &fname, const float magfield_rescale, const float innerradius, const float outerradius, const float size_z)
0027   : filename(fname)
0028 {
0029   std::cout << "PHField3DCartesian::PHField3DCartesian" << std::endl;
0030 
0031   for (int i = 0; i < 2; i++)
0032   {
0033     for (int j = 0; j < 2; j++)
0034     {
0035       for (int k = 0; k < 2; k++)
0036       {
0037         for (int l = 0; l < 3; l++)
0038         {
0039           bf[i][j][k][l] = NAN;
0040         }
0041       }
0042     }
0043   }
0044   std::cout << "\n================ Begin Construct Mag Field =====================" << std::endl;
0045   std::cout << "\n-----------------------------------------------------------"
0046             << "\n      Magnetic field Module - Verbosity:"
0047             << "\n-----------------------------------------------------------";
0048 
0049   // open file
0050   TFile *rootinput = TFile::Open(filename.c_str());
0051   if (!rootinput)
0052   {
0053     std::cout << "\n could not open " << filename << " exiting now" << std::endl;
0054     gSystem->Exit(1);
0055     exit(1);
0056   }
0057   std::cout << "\n ---> "
0058                "Reading the field grid from "
0059             << filename << " ... " << std::endl;
0060 
0061   //  get root NTuple objects
0062   TNtuple *field_map = nullptr;
0063   rootinput->GetObject("fieldmap", field_map);
0064   if (field_map == nullptr)
0065   {
0066     std::cout << PHWHERE << " Could not load fieldmap ntuple from "
0067               << filename << " exiting now" << std::endl;
0068     gSystem->Exit(1);
0069     exit(1);
0070   }
0071   Float_t ROOT_X, ROOT_Y, ROOT_Z;
0072   Float_t ROOT_BX, ROOT_BY, ROOT_BZ;
0073   field_map->SetBranchAddress("x", &ROOT_X);
0074   field_map->SetBranchAddress("y", &ROOT_Y);
0075   field_map->SetBranchAddress("z", &ROOT_Z);
0076   field_map->SetBranchAddress("bx", &ROOT_BX);
0077   field_map->SetBranchAddress("by", &ROOT_BY);
0078   field_map->SetBranchAddress("bz", &ROOT_BZ);
0079   for (int i = 0; i < field_map->GetEntries(); i++)
0080   {
0081     field_map->GetEntry(i);
0082     trio coord_key(ROOT_X * cm, ROOT_Y * cm, ROOT_Z * cm);
0083     trio field_val(ROOT_BX * tesla * magfield_rescale, ROOT_BY * tesla * magfield_rescale, ROOT_BZ * tesla * magfield_rescale);
0084     xvals.insert(ROOT_X * cm);
0085     yvals.insert(ROOT_Y * cm);
0086     zvals.insert(ROOT_Z * cm);
0087     if ((std::sqrt(ROOT_X * cm * ROOT_X * cm + ROOT_Y * cm * ROOT_Y * cm) >= innerradius &&
0088          std::sqrt(ROOT_X * cm * ROOT_X * cm + ROOT_Y * cm * ROOT_Y * cm) <= outerradius) ||
0089         std::abs(ROOT_Z * cm) > size_z)
0090     {
0091       fieldmap[coord_key] = field_val;
0092     }
0093   }
0094   xmin = *(xvals.begin());
0095   xmax = *(xvals.rbegin());
0096 
0097   ymin = *(yvals.begin());
0098   ymax = *(yvals.rbegin());
0099   if (ymin != xmin || ymax != xmax)
0100   {
0101     std::cout << "PHField3DCartesian: Compiler bug!!!!!!!! Do not use inlining!!!!!!" << std::endl;
0102     std::cout << "exiting now - recompile with -fno-inline" << std::endl;
0103     exit(1);
0104   }
0105 
0106   zmin = *(zvals.begin());
0107   zmax = *(zvals.rbegin());
0108 
0109   xstepsize = (xmax - xmin) / (xvals.size() - 1);
0110   ystepsize = (ymax - ymin) / (yvals.size() - 1);
0111   zstepsize = (zmax - zmin) / (zvals.size() - 1);
0112 
0113   delete field_map;
0114   delete rootinput;
0115   std::cout << "\n================= End Construct Mag Field ======================\n"
0116             << std::endl;
0117 }
0118 
0119 PHField3DCartesian::~PHField3DCartesian()
0120 {
0121   std::cout << "PHField3DCartesian::~PHField3DCartesian" << std::endl;
0122   if (Verbosity() > 0)
0123   {
0124     std::cout << "PHField3DCartesian: cache hits: " << cache_hits
0125               << " cache misses: " << cache_misses
0126               << std::endl;
0127   }
0128 }
0129 
0130 void PHField3DCartesian::GetFieldValue(const double point[4], double *Bfield) const
0131 {
0132 
0133   static double xsav = -1000000.;
0134   static double ysav = -1000000.;
0135   static double zsav = -1000000.;
0136 
0137   const double& x = point[0];
0138   const double& y = point[1];
0139   const double& z = point[2];
0140 
0141   Bfield[0] = 0.0;
0142   Bfield[1] = 0.0;
0143   Bfield[2] = 0.0;
0144   if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z))
0145   {
0146     static int ifirst = 0;
0147     if (ifirst < 10)
0148     {
0149       std::cout << "PHField3DCartesian::GetFieldValue: "
0150         << "Invalid coordinates: "
0151         << "x: " << x / cm
0152         << ", y: " << y / cm
0153         << ", z: " << z / cm
0154         << " bailing out returning zero bfield"
0155         << std::endl;
0156       std::cout << "previous point: "
0157         << "x: " << xsav / cm
0158         << ", y: " << ysav / cm
0159         << ", z: " << zsav / cm
0160         << std::endl;
0161       std::cout << "Here is the stacktrace: " << std::endl;
0162       std::cout << boost::stacktrace::stacktrace();
0163       std::cout << "This is not a segfault. Check the stacktrace for the guilty party (typically #2)" << std::endl;
0164       ifirst++;
0165     }
0166     return;
0167   }
0168 
0169   xsav = x;
0170   ysav = y;
0171   zsav = z;
0172 
0173   if (point[0] < xmin || point[0] > xmax ||
0174       point[1] < ymin || point[1] > ymax ||
0175       point[2] < zmin || point[2] > zmax)
0176   {
0177     return;
0178   }
0179 
0180   double xkey[2];
0181   std::set<float>::const_iterator it = xvals.lower_bound(x);
0182   xkey[0] = *it;
0183   if (it == xvals.begin())
0184   {
0185     xkey[1] = *it;
0186     if (x < xkey[0])
0187     {
0188       std::cout << PHWHERE << ": This should not happen! x too small - outside range: " << x / cm << std::endl;
0189       return;
0190     }
0191   }
0192   else
0193   {
0194     --it;
0195     xkey[1] = *it;
0196   }
0197 
0198   double ykey[2];
0199   it = yvals.lower_bound(y);
0200   ykey[0] = *it;
0201   if (it == yvals.begin())
0202   {
0203     ykey[1] = *it;
0204     if (y < ykey[0])
0205     {
0206       std::cout << PHWHERE << ": This should not happen! y too small - outside range: " << y / cm << std::endl;
0207       return;
0208     }
0209   }
0210   else
0211   {
0212     --it;
0213     ykey[1] = *it;
0214   }
0215   double zkey[2];
0216   it = zvals.lower_bound(z);
0217   zkey[0] = *it;
0218   if (it == zvals.begin())
0219   {
0220     zkey[1] = *it;
0221     if (z < zkey[0])
0222     {
0223       std::cout << PHWHERE << ": This should not happen! z too small - outside range: " << z / cm << std::endl;
0224       return;
0225     }
0226   }
0227   else
0228   {
0229     --it;
0230     zkey[1] = *it;
0231   }
0232 
0233   if (xkey_save != xkey[0] ||
0234       ykey_save != ykey[0] ||
0235       zkey_save != zkey[0])
0236   {
0237     cache_misses++;
0238     xkey_save = xkey[0];
0239     ykey_save = ykey[0];
0240     zkey_save = zkey[0];
0241 
0242     std::map<std::tuple<float, float, float>, std::tuple<float, float, float> >::const_iterator magval;
0243     trio key;
0244     for (int i = 0; i < 2; i++)
0245     {
0246       for (int j = 0; j < 2; j++)
0247       {
0248         for (int k = 0; k < 2; k++)
0249         {
0250           key = std::make_tuple(xkey[i], ykey[j], zkey[k]);
0251           magval = fieldmap.find(key);
0252           if (magval == fieldmap.end())
0253           {
0254             std::cout << PHWHERE << " could not locate key in " << filename
0255                       << " value: x: " << xkey[i] / cm
0256                       << ", y: " << ykey[j] / cm
0257                       << ", z: " << zkey[k] / cm << std::endl;
0258             return;
0259           }
0260           bf[i][j][k][0] = std::get<0>(magval->second);
0261           bf[i][j][k][1] = std::get<1>(magval->second);
0262           bf[i][j][k][2] = std::get<2>(magval->second);
0263           if (Verbosity() > 0)
0264           {
0265             const double x_loc = std::get<0>(magval->first);
0266             const double y_loc = std::get<1>(magval->first);
0267             const double z_loc = std::get<2>(magval->first);
0268 
0269             std::cout << "read x/y/z: " << x_loc / cm << "/"
0270               << y_loc / cm << "/"
0271               << z_loc / cm << " bx/by/bz: "
0272               << bf[i][j][k][0] / tesla << "/"
0273               << bf[i][j][k][1] / tesla << "/"
0274               << bf[i][j][k][2] / tesla << std::endl;
0275           }
0276         }
0277       }
0278     }
0279   }
0280   else
0281   {
0282     cache_hits++;
0283   }
0284 
0285   // how far are we away from the reference point
0286   double xinblock = point[0] - xkey[1];
0287   double yinblock = point[1] - ykey[1];
0288   double zinblock = point[2] - zkey[1];
0289   // normalize distance to step size
0290   double fractionx = xinblock / xstepsize;
0291   double fractiony = yinblock / ystepsize;
0292   double fractionz = zinblock / zstepsize;
0293   if (Verbosity() > 0)
0294   {
0295     std::cout << "x/y/z stepsize: " << xstepsize / cm << "/" << ystepsize / cm << "/" << zstepsize / cm << std::endl;
0296     std::cout << "x/y/z inblock: " << xinblock / cm << "/" << yinblock / cm << "/" << zinblock / cm << std::endl;
0297     std::cout << "x/y/z fraction: " << fractionx << "/" << fractiony << "/" << fractionz << std::endl;
0298   }
0299 
0300   // linear extrapolation in cube:
0301 
0302   // Vxyz =
0303   // V000 * x * y * z +
0304   // V100 * (1 - x) * y * z +
0305   // V010 * x * (1 - y) * z +
0306   // V001 * x y * (1 - z) +
0307   // V101 * (1 - x) * y * (1 - z) +
0308   // V011 * x * (1 - y) * (1 - z) +
0309   // V110 * (1 - x) * (1 - y) * z +
0310   // V111 * (1 - x) * (1 - y) * (1 - z)
0311 
0312   for (int i = 0; i < 3; i++)
0313   {
0314     Bfield[i] = bf[0][0][0][i] * fractionx * fractiony * fractionz +
0315                 bf[1][0][0][i] * (1. - fractionx) * fractiony * fractionz +
0316                 bf[0][1][0][i] * fractionx * (1. - fractiony) * fractionz +
0317                 bf[0][0][1][i] * fractionx * fractiony * (1. - fractionz) +
0318                 bf[1][0][1][i] * (1. - fractionx) * fractiony * (1. - fractionz) +
0319                 bf[0][1][1][i] * fractionx * (1. - fractiony) * (1. - fractionz) +
0320                 bf[1][1][0][i] * (1. - fractionx) * (1. - fractiony) * fractionz +
0321                 bf[1][1][1][i] * (1. - fractionx) * (1. - fractiony) * (1. - fractionz);
0322   }
0323 
0324   return;
0325 }
0326 
0327 //_____________________________________________________________
0328 void PHField3DCartesian::GetFieldValue_nocache(const double point[4], double *Bfield) const
0329 {
0330 
0331   const double& x = point[0];
0332   const double& y = point[1];
0333   const double& z = point[2];
0334 
0335   Bfield[0] = 0.0;
0336   Bfield[1] = 0.0;
0337   Bfield[2] = 0.0;
0338   if (!std::isfinite(x) || !std::isfinite(y) || !std::isfinite(z))
0339   { return; }
0340 
0341   if (point[0] < xmin || point[0] > xmax ||
0342       point[1] < ymin || point[1] > ymax ||
0343       point[2] < zmin || point[2] > zmax)
0344   { return; }
0345 
0346   double xkey[2];
0347   std::set<float>::const_iterator it = xvals.lower_bound(x);
0348   xkey[0] = *it;
0349   if (it == xvals.begin())
0350   {
0351     xkey[1] = *it;
0352     if (x < xkey[0])
0353     {
0354       std::cout << PHWHERE << ": This should not happen! x too small - outside range: " << x / cm << std::endl;
0355       return;
0356     }
0357   }
0358   else
0359   {
0360     --it;
0361     xkey[1] = *it;
0362   }
0363 
0364   double ykey[2];
0365   it = yvals.lower_bound(y);
0366   ykey[0] = *it;
0367   if (it == yvals.begin())
0368   {
0369     ykey[1] = *it;
0370     if (y < ykey[0])
0371     {
0372       std::cout << PHWHERE << ": This should not happen! y too small - outside range: " << y / cm << std::endl;
0373       return;
0374     }
0375   }
0376   else
0377   {
0378     --it;
0379     ykey[1] = *it;
0380   }
0381   double zkey[2];
0382   it = zvals.lower_bound(z);
0383   zkey[0] = *it;
0384   if (it == zvals.begin())
0385   {
0386     zkey[1] = *it;
0387     if (z < zkey[0])
0388     {
0389       std::cout << PHWHERE << ": This should not happen! z too small - outside range: " << z / cm << std::endl;
0390       return;
0391     }
0392   }
0393   else
0394   {
0395     --it;
0396     zkey[1] = *it;
0397   }
0398 
0399   // local xyz and field
0400   double bf_loc[2][2][2][3]{};
0401 
0402   std::map<std::tuple<float, float, float>, std::tuple<float, float, float> >::const_iterator magval;
0403   trio key;
0404   for (int i = 0; i < 2; i++)
0405   {
0406     for (int j = 0; j < 2; j++)
0407     {
0408       for (int k = 0; k < 2; k++)
0409       {
0410         key = std::make_tuple(xkey[i], ykey[j], zkey[k]);
0411         magval = fieldmap.find(key);
0412         if (magval == fieldmap.end())
0413         {
0414           std::cout << PHWHERE << " could not locate key in " << filename
0415             << " value: x: " << xkey[i] / cm
0416             << ", y: " << ykey[j] / cm
0417             << ", z: " << zkey[k] / cm << std::endl;
0418           return;
0419         }
0420 
0421         bf_loc[i][j][k][0] = std::get<0>(magval->second);
0422         bf_loc[i][j][k][1] = std::get<1>(magval->second);
0423         bf_loc[i][j][k][2] = std::get<2>(magval->second);
0424         if (Verbosity() > 0)
0425         {
0426 
0427           const double x_loc = std::get<0>(magval->first);
0428           const double y_loc = std::get<1>(magval->first);
0429           const double z_loc = std::get<2>(magval->first);
0430 
0431           std::cout << "read x/y/z: " << x_loc / cm << "/"
0432             << y_loc / cm << "/"
0433             << z_loc / cm << " bx/by/bz: "
0434             << bf_loc[i][j][k][0] / tesla << "/"
0435             << bf_loc[i][j][k][1] / tesla << "/"
0436             << bf_loc[i][j][k][2] / tesla << std::endl;
0437         }
0438       }
0439     }
0440   }
0441 
0442   // how far are we away from the reference point
0443   double xinblock = point[0] - xkey[1];
0444   double yinblock = point[1] - ykey[1];
0445   double zinblock = point[2] - zkey[1];
0446   // normalize distance to step size
0447   double fractionx = xinblock / xstepsize;
0448   double fractiony = yinblock / ystepsize;
0449   double fractionz = zinblock / zstepsize;
0450   if (Verbosity() > 0)
0451   {
0452     std::cout << "x/y/z stepsize: " << xstepsize / cm << "/" << ystepsize / cm << "/" << zstepsize / cm << std::endl;
0453     std::cout << "x/y/z inblock: " << xinblock / cm << "/" << yinblock / cm << "/" << zinblock / cm << std::endl;
0454     std::cout << "x/y/z fraction: " << fractionx << "/" << fractiony << "/" << fractionz << std::endl;
0455   }
0456 
0457   // linear extrapolation in cube:
0458 
0459   // Vxyz =
0460   // V000 * x * y * z +
0461   // V100 * (1 - x) * y * z +
0462   // V010 * x * (1 - y) * z +
0463   // V001 * x y * (1 - z) +
0464   // V101 * (1 - x) * y * (1 - z) +
0465   // V011 * x * (1 - y) * (1 - z) +
0466   // V110 * (1 - x) * (1 - y) * z +
0467   // V111 * (1 - x) * (1 - y) * (1 - z)
0468 
0469   for (int i = 0; i < 3; i++)
0470   {
0471     Bfield[i] = bf_loc[0][0][0][i] * fractionx * fractiony * fractionz +
0472                 bf_loc[1][0][0][i] * (1. - fractionx) * fractiony * fractionz +
0473                 bf_loc[0][1][0][i] * fractionx * (1. - fractiony) * fractionz +
0474                 bf_loc[0][0][1][i] * fractionx * fractiony * (1. - fractionz) +
0475                 bf_loc[1][0][1][i] * (1. - fractionx) * fractiony * (1. - fractionz) +
0476                 bf_loc[0][1][1][i] * fractionx * (1. - fractiony) * (1. - fractionz) +
0477                 bf_loc[1][1][0][i] * (1. - fractionx) * (1. - fractiony) * fractionz +
0478                 bf_loc[1][1][1][i] * (1. - fractionx) * (1. - fractiony) * (1. - fractionz);
0479   }
0480 
0481   return;
0482 }