LCOV - code coverage report
Current view: top level - src/userobjects - NeutronicsSpectrumSamplerBase.C (source / functions) Hit Total Coverage
Test: idaholab/magpie: 5710af Lines: 0 114 0.0 %
Date: 2025-07-21 23:34:39 Functions: 0 14 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /**********************************************************************/
       2             : /*                     DO NOT MODIFY THIS HEADER                      */
       3             : /* MAGPIE - Mesoscale Atomistic Glue Program for Integrated Execution */
       4             : /*                                                                    */
       5             : /*            Copyright 2017 Battelle Energy Alliance, LLC            */
       6             : /*                        ALL RIGHTS RESERVED                         */
       7             : /**********************************************************************/
       8             : 
       9             : #include "NeutronicsSpectrumSamplerBase.h"
      10             : #include "MooseMesh.h"
      11             : 
      12             : #ifdef RATTLESNAKE_ENABLED
      13             : #include "IsotopeUtilities.h"
      14             : #endif
      15             : 
      16             : // C++ includes
      17             : #include <sstream>
      18             : #include <algorithm>
      19             : #include <limits>
      20             : 
      21             : InputParameters
      22           0 : NeutronicsSpectrumSamplerBase::validParams()
      23             : {
      24           0 :   InputParameters params = ElementUserObject::validParams();
      25           0 :   params.addRequiredParam<std::vector<std::string>>("target_isotope_names",
      26             :                                                     "The list of target isotope names e.g. U235.");
      27           0 :   params.addRequiredCoupledVar("number_densities", "Number densities for each isotope.");
      28           0 :   params.addRequiredParam<std::vector<Real>>("energy_group_boundaries",
      29             :                                              "The energy group boundaries in units of eV orderd "
      30             :                                              "from high to low [natural neutronics ordering].");
      31           0 :   params.addRequiredParam<unsigned int>(
      32             :       "L", "The maximum order of Legendre terms for expanding the recoil XS in mu_lab.");
      33           0 :   params.addRequiredParam<std::vector<Point>>(
      34             :       "points", "The points where you want to evaluate the variables");
      35           0 :   params.addClassDescription("Radiation Damage user object base class.\n Computes PDFs from "
      36             :                              "neutronics calculations that are used to sample PKAs in BCMC "
      37             :                              "simulations.");
      38           0 :   return params;
      39           0 : }
      40             : 
      41           0 : NeutronicsSpectrumSamplerBase::NeutronicsSpectrumSamplerBase(const InputParameters & parameters)
      42             :   : ElementUserObject(parameters),
      43           0 :     _target_isotope_names(getParam<std::vector<std::string>>("target_isotope_names")),
      44           0 :     _energy_group_boundaries(getParam<std::vector<Real>>("energy_group_boundaries")),
      45           0 :     _I(_target_isotope_names.size()),
      46           0 :     _G(_energy_group_boundaries.size() - 1),
      47           0 :     _L(getParam<unsigned int>("L")),
      48           0 :     _points(getParam<std::vector<Point>>("points")),
      49           0 :     _npoints(_points.size()),
      50           0 :     _qp_is_cached(false)
      51             : {
      52             :   // check input dimensions
      53           0 :   if (coupledComponents("number_densities") != _I)
      54           0 :     mooseError("ZAID and number_densities must have the same length.");
      55             : 
      56             :   // get the number density variables
      57           0 :   _number_densities.resize(_I);
      58           0 :   for (unsigned int i = 0; i < _I; ++i)
      59           0 :     _number_densities[i] = &coupledValue("number_densities", i);
      60             : 
      61           0 :   _zaids.resize(_I);
      62           0 :   for (unsigned int i = 0; i < _I; ++i)
      63             :   {
      64             : #ifdef RATTLESNAKE_ENABLED
      65             :     unsigned int Z, A;
      66             :     // check if isotope names are valid, NOTE: error handling is delegated to Yakxs::Utilities
      67             :     YAKXS::Utility::getAZ(_target_isotope_names[i], A, Z);
      68             :     // convert from name to ZAID
      69             :     _zaids[i] = YAKXS::Utility::getZaid(_target_isotope_names[i]);
      70             : #else
      71           0 :     _zaids[i] = localStringToZaid(_target_isotope_names[i]);
      72             : #endif
      73             :   }
      74             : 
      75           0 :   _owner.resize(_npoints);
      76           0 :   _qp_cache.resize(_npoints);
      77             : 
      78             :   // check energy group ordering
      79           0 :   if (_energy_group_boundaries.size() < 2)
      80           0 :     mooseError("At least 2 boundaries must be provided for energy_group_boundaries");
      81           0 :   for (unsigned int j = 1; j < _energy_group_boundaries.size(); ++j)
      82           0 :     if (_energy_group_boundaries[j] >= _energy_group_boundaries[j - 1])
      83           0 :       mooseError("energy_group_boundaries must be ordered from high to low");
      84           0 : }
      85             : 
      86             : void
      87           0 : NeutronicsSpectrumSamplerBase::execute()
      88             : {
      89           0 :   if (_local_elem_to_contained_points.find(_current_elem) != _local_elem_to_contained_points.end())
      90             :   {
      91           0 :     for (auto & j : _local_elem_to_contained_points[_current_elem])
      92             :     {
      93           0 :       _current_point = j;
      94             :       // NOTE: PKA is evaluated at a point that is not necessarily a qp but material
      95             :       // props only live on qps. This is a cheap and dirty solution evaluating the
      96             :       // PKA at the closest quadrature point.
      97           0 :       if (!_qp_is_cached)
      98             :       {
      99           0 :         Real min_dsq = (_q_point[0] - _points[_current_point]).norm_sq();
     100             :         unsigned int min_qp = 0;
     101           0 :         for (unsigned int qp = 1; qp < _q_point.size(); qp++)
     102             :         {
     103             :           Real dsq = (_q_point[qp] - _points[_current_point]).norm_sq();
     104           0 :           if (dsq < min_dsq)
     105             :           {
     106             :             min_dsq = dsq;
     107             :             min_qp = qp;
     108             :           }
     109             :         }
     110           0 :         _qp_cache[_current_point] = min_qp;
     111             :       }
     112             : 
     113             :       // Set current qp to cached min_qp
     114           0 :       _qp = _qp_cache[_current_point];
     115             : 
     116             :       // call back before computing radiation damage PDF for caching things that
     117             :       // don't change
     118           0 :       preComputeRadiationDamagePDF();
     119             : 
     120             :       // Evalute the radiation damage PDF at min_qp
     121           0 :       for (unsigned int i = 0; i < _I; ++i)
     122           0 :         for (unsigned int g = 0; g < _G; ++g)
     123           0 :           for (unsigned int p = 0; p < _nphi; ++p)
     124           0 :             for (unsigned int q = 0; q < _nmu; ++q)
     125           0 :               _sample_point_data[_current_point]({i, g, p, q}) =
     126           0 :                   computeRadiationDamagePDF(i, g, p, q);
     127             :     }
     128             :   }
     129           0 : }
     130             : 
     131             : void
     132           0 : NeutronicsSpectrumSamplerBase::preComputeRadiationDamagePDF()
     133             : {
     134           0 : }
     135             : 
     136             : void
     137           0 : NeutronicsSpectrumSamplerBase::meshChanged()
     138             : {
     139             :   // make sure that _local_elem_to_contained_points is empty
     140             :   _local_elem_to_contained_points.clear();
     141             : 
     142             :   // Rebuild point_locator & find the right element for each point
     143           0 :   std::unique_ptr<PointLocatorBase> point_locator = _mesh.getPointLocator();
     144           0 :   for (unsigned int j = 0; j < _npoints; j++)
     145             :   {
     146             :     // make sure element is local
     147           0 :     _owner[j] = 0;
     148           0 :     const Elem * candidate_elem = (*point_locator)(_points[j]);
     149           0 :     if (candidate_elem && candidate_elem->processor_id() == processor_id())
     150             :     {
     151           0 :       _owner[j] = processor_id();
     152           0 :       if (_local_elem_to_contained_points.find(candidate_elem) !=
     153             :           _local_elem_to_contained_points.end())
     154           0 :         _local_elem_to_contained_points[candidate_elem].push_back(j);
     155             :       else
     156           0 :         _local_elem_to_contained_points[candidate_elem] = {j};
     157             :     }
     158             :   }
     159             : 
     160             :   // make sure everyone knows who owns which point
     161           0 :   for (unsigned int j = 0; j < _npoints; j++)
     162           0 :     gatherMax(_owner[j]);
     163             : 
     164           0 :   _qp_is_cached = false;
     165           0 : }
     166             : 
     167             : void
     168           0 : NeutronicsSpectrumSamplerBase::initialSetup()
     169             : {
     170             :   // allocate PDF
     171             :   // NOTE: Needs to be delayed to initialize because _nSH is set in derived class
     172           0 :   for (unsigned int j = 0; j < _npoints; ++j)
     173           0 :     _sample_point_data.push_back(MultiIndex<Real>({_I, _G, _nphi, _nmu}));
     174           0 : }
     175             : 
     176             : void
     177           0 : NeutronicsSpectrumSamplerBase::initialize()
     178             : {
     179           0 :   meshChanged();
     180             : 
     181           0 :   for (unsigned j = 0; j < _npoints; ++j)
     182           0 :     for (auto entry : _sample_point_data[j])
     183           0 :       entry.second = 0;
     184           0 : }
     185             : 
     186             : void
     187           0 : NeutronicsSpectrumSamplerBase::finalize()
     188             : {
     189           0 :   if (_mesh.n_processors() > 1)
     190             :   {
     191           0 :     for (unsigned j = 0; j < _npoints; ++j)
     192             :     {
     193           0 :       std::vector<Real> flat_data(_I * _G * _nmu * _nphi);
     194           0 :       if (_owner[j] == processor_id())
     195           0 :         flat_data = _sample_point_data[j].getRawData();
     196             : 
     197           0 :       _communicator.broadcast(flat_data, _owner[j]);
     198             : 
     199           0 :       if (_owner[j] != processor_id())
     200           0 :         _sample_point_data[j] = MultiIndex<Real>({_I, _G, _nphi, _nmu}, flat_data);
     201             :     }
     202             :   }
     203             : 
     204             :   // set _qp_is_cached flag to true. Actually we only need to do this if
     205             :   // it was false but this way we can save an if statement
     206           0 :   _qp_is_cached = true;
     207           0 : }
     208             : 
     209             : void
     210           0 : NeutronicsSpectrumSamplerBase::threadJoin(const UserObject & y)
     211             : {
     212             :   const NeutronicsSpectrumSamplerBase & uo = static_cast<const NeutronicsSpectrumSamplerBase &>(y);
     213           0 :   for (unsigned j = 0; j < _npoints; ++j)
     214           0 :     for (unsigned int i = 0; i < _I; ++i)
     215           0 :       for (unsigned int g = 0; g < _G; ++g)
     216           0 :         for (unsigned int p = 0; p < _nphi; ++p)
     217           0 :           for (unsigned int q = 0; q < _nmu; ++q)
     218           0 :             _sample_point_data[j]({i, g, p, q}) += uo._sample_point_data[j]({i, g, p, q});
     219           0 : }
     220             : 
     221             : MultiIndex<Real>
     222           0 : NeutronicsSpectrumSamplerBase::getPDF(unsigned int point_id) const
     223             : {
     224           0 :   return _sample_point_data[point_id];
     225             : }
     226             : 
     227             : std::vector<unsigned int>
     228           0 : NeutronicsSpectrumSamplerBase::getZAIDs() const
     229             : {
     230           0 :   return _zaids;
     231             : }
     232             : 
     233             : std::vector<Real>
     234           0 : NeutronicsSpectrumSamplerBase::getEnergies() const
     235             : {
     236           0 :   return _energy_group_boundaries;
     237             : }
     238             : 
     239             : bool
     240           0 : NeutronicsSpectrumSamplerBase::hasIsotope(std::string target_isotope) const
     241             : {
     242           0 :   auto it = std::find(_target_isotope_names.begin(), _target_isotope_names.end(), target_isotope);
     243           0 :   return it != _target_isotope_names.end();
     244             : }
     245             : 
     246             : unsigned int
     247           0 : NeutronicsSpectrumSamplerBase::localStringToZaid(std::string s) const
     248             : {
     249           0 :   if (s == "U235")
     250             :     return 922350;
     251           0 :   else if (s == "U238")
     252             :     return 922380;
     253           0 :   else if (s == "Pu238")
     254             :     return 942380;
     255           0 :   else if (s == "Pu239")
     256             :     return 942390;
     257           0 :   else if (s == "Pu240")
     258             :     return 942400;
     259           0 :   mooseError(
     260             :       "Isotope name ", s, " cannot be converted with the localStringToZaid conversion method.");
     261             :   return 0;
     262             : }

Generated by: LCOV version 1.14