LCOV - code coverage report
Current view: top level - src/criticality - CriticalitySearchBase.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: 93e9c4 Lines: 75 79 94.9 %
Date: 2026-07-16 12:06:10 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         174 : CriticalitySearchBase::validParams()
      31             : {
      32         174 :   auto params = MooseObject::validParams();
      33         174 :   params += OpenMCBase::validParams();
      34         348 :   params.addRequiredParam<Real>(
      35             :       "minimum",
      36             :       "Minimum for values to search over; the root must occur at a value greater than the minimum");
      37         348 :   params.addRequiredParam<Real>(
      38             :       "maximum",
      39             :       "Maximum for values to search over; the root must occur at a value smaller than the maximum");
      40         522 :   params.addRangeCheckedParam<Real>(
      41         348 :       "target", 1.0, "target > 0.0", "Target value of k effective to search for");
      42         348 :   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         522 :   params.addRangeCheckedParam<Real>(
      47             :       "k_tol",
      48         348 :       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         348 :   params.addParam<MooseEnum>(
      53         348 :       "estimator", getEigenvalueEnum(), "Type of eigenvalue estimator to use");
      54         348 :   params.addParam<bool>(
      55             :       "run_critical_state",
      56         348 :       true,
      57             :       "Whether a final k-eigenvalue calculation should be performed on the critical model state.");
      58         348 :   params.addParam<bool>(
      59             :       "tally_during_search",
      60         348 :       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         174 :   params.addClassDescription(
      66             :       "Base class for defining parameters used in a criticality search in OpenMC.");
      67         174 :   params.registerBase("CriticalitySearch");
      68         174 :   params.registerSystemAttributeName("CriticalitySearch");
      69         174 :   params.addPrivateParam<OpenMCCellAverageProblem *>("_openmc_problem");
      70         174 :   return params;
      71           0 : }
      72             : 
      73          96 : CriticalitySearchBase::CriticalitySearchBase(const InputParameters & parameters)
      74             :   : MooseObject(parameters),
      75             :     OpenMCBase(this, parameters),
      76          96 :     _maximum(getParam<Real>("maximum")),
      77         192 :     _minimum(getParam<Real>("minimum")),
      78         192 :     _k_tol(getParam<Real>("k_tol")),
      79         192 :     _root_tol(getParam<Real>("root_tol")),
      80         192 :     _estimator(getParam<MooseEnum>("estimator").getEnum<eigenvalue::EigenvalueEnum>()),
      81         192 :     _run_critical_state(getParam<bool>("run_critical_state")),
      82         192 :     _tally_during_search(getParam<bool>("tally_during_search")),
      83         288 :     _target(getParam<Real>("target"))
      84             : {
      85          96 :   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          94 :   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          92 :   auto pp_params = _factory.getValidParams("Receiver");
      98          92 :   _openmc_problem->addPostprocessor("Receiver", _pp_name, pp_params);
      99          92 : }
     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             :     int err = 0;
     137         812 :     if (_openmc_problem->runRandomRay())
     138           0 :       openmc_run_random_ray();
     139             :     else
     140         812 :       err = openmc_run();
     141             : 
     142         812 :     if (err)
     143           0 :       mooseError(openmc_err_msg);
     144             : 
     145             :     // fetch k and print values to console
     146         812 :     Real k = kMean(_estimator);
     147         812 :     Real k_std_dev = kStandardDeviation(_estimator);
     148         812 :     _k_values.push_back(k);
     149         812 :     _k_std_dev_values.push_back(k_std_dev);
     150             : 
     151         812 :     vt.addRow(_k_values.size() - 1, x, k, k_std_dev);
     152         812 :     vt.print(_console);
     153             : 
     154         812 :     if (_k_tol < 3 * k_std_dev)
     155         102 :       mooseDoOnce(mooseWarning(
     156             :           "The 'k_tol' for the criticality search (" + std::to_string(_k_tol) +
     157             :           ") is smaller than 3-sigma standard deviation in k (" + std::to_string(3 * k_std_dev) +
     158             :           "), which may require many search iterations to converge to this tolerance "
     159             :           "Consider a looser 'k_tol' or increase the number of particles."));
     160             : 
     161         810 :     return k - _target;
     162          76 :   };
     163             : 
     164          76 :   BrentsMethod::root(func, _minimum, _maximum, _root_tol);
     165             : 
     166             :   // check if the method converged
     167          74 :   if (abs(kMean(_estimator) - _target) >= _k_tol)
     168           2 :     mooseWarning("The eigenvalue produced by the criticality search was not within "
     169             :                  "specified 'k_tol' of the target! This could occur if 'k_tol' is too "
     170             :                  "tight for simulation's statistical error. It can also occur if "
     171             :                  "'root_tol' is too loose and the worth curve is steep near the target");
     172             : 
     173             :   // Run the critical state calculation, if requested.
     174          72 :   if (_run_critical_state)
     175             :   {
     176          72 :     _console << "Running the critical state calculation" << std::endl;
     177             : 
     178             :     // Re-enable tallies.
     179          72 :     if (!_tally_during_search)
     180          96 :       for (auto & t : openmc::model::tallies)
     181             :         t->set_active(true);
     182             : 
     183          72 :     int err = openmc_run();
     184          72 :     if (err)
     185           0 :       mooseError(openmc_err_msg);
     186             :   }
     187             : 
     188             :   // fill the converged value into a postprocessor
     189         144 :   _openmc_problem->setPostprocessorValueByName(_pp_name, _inputs.back());
     190         300 : }
     191             : 
     192             : #endif

Generated by: LCOV version 1.14