LCOV - code coverage report
Current view: top level - src/criticality - CriticalitySearchBase.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: ddd5f2 Lines: 74 77 96.1 %
Date: 2026-06-07 19:35:24 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /********************************************************************/
       2             : /*                  SOFTWARE COPYRIGHT NOTIFICATION                 */
       3             : /*                             Cardinal                             */
       4             : /*                                                                  */
       5             : /*                  (c) 2021 UChicago Argonne, LLC                  */
       6             : /*                        ALL RIGHTS RESERVED                       */
       7             : /*                                                                  */
       8             : /*                 Prepared by UChicago Argonne, LLC                */
       9             : /*               Under Contract No. DE-AC02-06CH11357               */
      10             : /*                With the U. S. Department of Energy               */
      11             : /*                                                                  */
      12             : /*             Prepared by Battelle Energy Alliance, LLC            */
      13             : /*               Under Contract No. DE-AC07-05ID14517               */
      14             : /*                With the U. S. Department of Energy               */
      15             : /*                                                                  */
      16             : /*                 See LICENSE for full restrictions                */
      17             : /********************************************************************/
      18             : 
      19             : #ifdef ENABLE_OPENMC_COUPLING
      20             : 
      21             : #include "CriticalitySearchBase.h"
      22             : #include "UserErrorChecking.h"
      23             : #include "VariadicTable.h"
      24             : #include "BrentsMethod.h"
      25             : 
      26             : // To disable tallies
      27             : #include "openmc/tallies/tally.h"
      28             : 
      29             : InputParameters
      30         172 : CriticalitySearchBase::validParams()
      31             : {
      32         172 :   auto params = MooseObject::validParams();
      33         172 :   params += OpenMCBase::validParams();
      34         344 :   params.addRequiredParam<Real>(
      35             :       "minimum",
      36             :       "Minimum for values to search over; the root must occur at a value greater than the minimum");
      37         344 :   params.addRequiredParam<Real>(
      38             :       "maximum",
      39             :       "Maximum for values to search over; the root must occur at a value smaller than the maximum");
      40         516 :   params.addRangeCheckedParam<Real>(
      41         344 :       "target", 1.0, "target > 0.0", "Target value of k effective to search for");
      42         344 :   params.addRequiredRangeCheckedParam<Real>(
      43             :       "root_tol",
      44             :       "root_tol > 0",
      45             :       "Absolute tolerance to converge root that yields target value of the multiplication factor.");
      46         516 :   params.addRangeCheckedParam<Real>(
      47             :       "k_tol",
      48         344 :       1e-3,
      49             :       "k_tol > 0",
      50             :       "Absolute tolerance to converge multiplication factor; be aware that if too few particles "
      51             :       "are used, statistical noise may require many criticality calculations to converge.");
      52         344 :   params.addParam<MooseEnum>(
      53         344 :       "estimator", getEigenvalueEnum(), "Type of eigenvalue estimator to use");
      54         344 :   params.addParam<bool>(
      55             :       "run_critical_state",
      56         344 :       true,
      57             :       "Whether a final k-eigenvalue calculation should be performed on the critical model state.");
      58         344 :   params.addParam<bool>(
      59             :       "tally_during_search",
      60         344 :       false,
      61             :       "Whether non-eigenvalue tallies should be disabled during the search process as a "
      62             :       "performance optimization. If set to 'false', `run_critical_state` must be set to 'true' "
      63             :       "to ensure tallies are computed on the last iteration.");
      64             : 
      65         172 :   params.addClassDescription(
      66             :       "Base class for defining parameters used in a criticality search in OpenMC.");
      67         172 :   params.registerBase("CriticalitySearch");
      68         172 :   params.registerSystemAttributeName("CriticalitySearch");
      69         172 :   params.addPrivateParam<OpenMCCellAverageProblem *>("_openmc_problem");
      70         172 :   return params;
      71           0 : }
      72             : 
      73          94 : CriticalitySearchBase::CriticalitySearchBase(const InputParameters & parameters)
      74             :   : MooseObject(parameters),
      75             :     OpenMCBase(this, parameters),
      76          94 :     _maximum(getParam<Real>("maximum")),
      77         188 :     _minimum(getParam<Real>("minimum")),
      78         188 :     _k_tol(getParam<Real>("k_tol")),
      79         188 :     _root_tol(getParam<Real>("root_tol")),
      80         188 :     _estimator(getParam<MooseEnum>("estimator").getEnum<eigenvalue::EigenvalueEnum>()),
      81         188 :     _run_critical_state(getParam<bool>("run_critical_state")),
      82         188 :     _tally_during_search(getParam<bool>("tally_during_search")),
      83         282 :     _target(getParam<Real>("target"))
      84             : {
      85          94 :   if (_minimum >= _maximum)
      86           4 :     paramError("minimum",
      87           2 :                "The 'minimum' value (" + std::to_string(_minimum) +
      88           2 :                    ") must be less than the 'maximum' value (" + std::to_string(_maximum) + ").");
      89             : 
      90          92 :   if (!_tally_during_search && !_run_critical_state)
      91           2 :     paramError(
      92             :         "tally_during_search",
      93             :         "When disabling tallies during intermediate calculations in the criticality search, "
      94             :         "you must set 'run_critical_state' to 'true'! This ensures you get tallies on the final "
      95             :         "iteration.");
      96             : 
      97          90 :   auto pp_params = _factory.getValidParams("Receiver");
      98          90 :   _openmc_problem->addPostprocessor("Receiver", _pp_name, pp_params);
      99          90 : }
     100             : 
     101             : void
     102          76 : CriticalitySearchBase::searchForCriticality(std::function<void()> step_callback)
     103             : {
     104          76 :   _console << "Running criticality search in OpenMC for " << quantity() << " in range "
     105         152 :            << std::to_string(_minimum) << " - " << std::to_string(_maximum) << " " << units() << " "
     106          76 :            << std::endl;
     107             : 
     108             :   VariadicTable<int, Real, Real, Real> vt(
     109         532 :       {"Iteration", quantity() + " " + units(), "  k (mean)  ", " k (std dev) "});
     110          76 :   vt.setColumnFormat({VariadicTableColumnFormat::AUTO,
     111             :                       VariadicTableColumnFormat::SCIENTIFIC,
     112             :                       VariadicTableColumnFormat::SCIENTIFIC,
     113             :                       VariadicTableColumnFormat::SCIENTIFIC});
     114             : 
     115             :   std::function<Real(Real)> func;
     116         964 :   func = [&](Real x)
     117             :   {
     118             :     // update the OpenMC model with a new parameter
     119         812 :     updateOpenMCModel(x);
     120         812 :     _inputs.push_back(x);
     121             : 
     122             :     // Execute the callback after updating the model prior to running the OpenMC problem.
     123             :     // This is used by OpenMCCellAverageProblem to update the MOOSE->OpenMC coupling, where
     124             :     // we need to ensure the correct temperatures and densities are applied to OpenMC cells
     125             :     // to maintain a critical state on the final solve. This also ensures that cell tallies
     126             :     // are extracted using the correct cell->element maps.
     127         812 :     step_callback();
     128             : 
     129             :     // Disable tallies during the search. We need to run this on each step as Cardinal wrapped
     130             :     // tallies have been reset.
     131         812 :     if (!_tally_during_search)
     132        1124 :       for (auto & t : openmc::model::tallies)
     133             :         t->set_active(false);
     134             : 
     135             :     // re-run the model
     136         812 :     int err = openmc_run();
     137         812 :     if (err)
     138           0 :       mooseError(openmc_err_msg);
     139             : 
     140             :     // fetch k and print values to console
     141         812 :     Real k = kMean(_estimator);
     142         812 :     Real k_std_dev = kStandardDeviation(_estimator);
     143         812 :     _k_values.push_back(k);
     144         812 :     _k_std_dev_values.push_back(k_std_dev);
     145             : 
     146         812 :     vt.addRow(_k_values.size() - 1, x, k, k_std_dev);
     147         812 :     vt.print(_console);
     148             : 
     149         812 :     if (_k_tol < 3 * k_std_dev)
     150         102 :       mooseDoOnce(mooseWarning(
     151             :           "The 'k_tol' for the criticality search (" + std::to_string(_k_tol) +
     152             :           ") is smaller than 3-sigma standard deviation in k (" + std::to_string(3 * k_std_dev) +
     153             :           "), which may require many search iterations to converge to this tolerance "
     154             :           "Consider a looser 'k_tol' or increase the number of particles."));
     155             : 
     156         810 :     return k - _target;
     157          76 :   };
     158             : 
     159          76 :   BrentsMethod::root(func, _minimum, _maximum, _root_tol);
     160             : 
     161             :   // check if the method converged
     162          74 :   if (abs(kMean(_estimator) - _target) >= _k_tol)
     163           2 :     mooseWarning("The eigenvalue produced by the criticality search was not within "
     164             :                  "specified 'k_tol' of the target! This could occur if 'k_tol' is too "
     165             :                  "tight for simulation's statistical error. It can also occur if "
     166             :                  "'root_tol' is too loose and the worth curve is steep near the target");
     167             : 
     168             :   // Run the critical state calculation, if requested.
     169          72 :   if (_run_critical_state)
     170             :   {
     171          72 :     _console << "Running the critical state calculation" << std::endl;
     172             : 
     173             :     // Re-enable tallies.
     174          72 :     if (!_tally_during_search)
     175          96 :       for (auto & t : openmc::model::tallies)
     176             :         t->set_active(true);
     177             : 
     178          72 :     int err = openmc_run();
     179          72 :     if (err)
     180           0 :       mooseError(openmc_err_msg);
     181             :   }
     182             : 
     183             :   // fill the converged value into a postprocessor
     184         144 :   _openmc_problem->setPostprocessorValueByName(_pp_name, _inputs.back());
     185         300 : }
     186             : 
     187             : #endif

Generated by: LCOV version 1.14