LCOV - code coverage report
Current view: top level - src/actions - SetupMGXSAction.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: ddd5f2 Lines: 432 445 97.1 %
Date: 2026-06-07 19:35:24 Functions: 9 9 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 "SetupMGXSAction.h"
      22             : 
      23             : #include "AddOutputAction.h"
      24             : 
      25             : #include "CardinalEnums.h"
      26             : #include "OpenMCCellAverageProblem.h"
      27             : 
      28             : registerMooseAction("CardinalApp", SetupMGXSAction, "add_tallies");
      29             : registerMooseAction("CardinalApp", SetupMGXSAction, "add_filters");
      30             : registerMooseAction("CardinalApp", SetupMGXSAction, "add_aux_variable");
      31             : registerMooseAction("CardinalApp", SetupMGXSAction, "add_aux_kernel");
      32             : registerMooseAction("CardinalApp", SetupMGXSAction, "modify_outputs");
      33             : 
      34             : InputParameters
      35        2929 : SetupMGXSAction::validParams()
      36             : {
      37        2929 :   auto params = CardinalAction::validParams();
      38        2929 :   params.addClassDescription("A class which sets up multi-group cross section generation using "
      39             :                              "Cardinal's mapped tallies.");
      40        2929 :   params += EnergyBinBase::validParams();
      41             :   // MGXS' are always reversed.
      42        2929 :   params.suppressParameter<bool>("reverse_bins");
      43        2929 :   params.set<bool>("reverse_bins") = true;
      44             : 
      45        5858 :   params.addRequiredParam<MooseEnum>(
      46        5858 :       "tally_type", getTallyTypeEnum(), "The type of spatial tally to use");
      47        5858 :   params.addRequiredParam<MooseEnum>("particle",
      48        5858 :                                      getSingleParticleFilterEnum(),
      49             :                                      "The particle to filter for. At present cross sections can "
      50             :                                      "only be generated for neutrons or photons, if 'electron' or "
      51             :                                      "'positron' are selected an error will be thrown.");
      52        2929 :   auto estimator_enum = getTallyEstimatorEnum();
      53        5858 :   estimator_enum.assign("tracklength");
      54        5858 :   params.addParam<MooseEnum>(
      55             :       "estimator",
      56             :       estimator_enum,
      57             :       "The type of estimator to use with the tallies added for MGXS generation. This is not "
      58             :       "applied to scattering / fission"
      59             :       " scores as the filters applied to those scores only support analog estimators.");
      60        5858 :   params.addParam<bool>("check_tally_sum",
      61             :                         "Whether to check consistency between the local tallies "
      62             :                         "with a global tally sum. This will require that the "
      63             :                         "integral of the local tally matches a tally with no filters "
      64             :                         "(defined over the entire phase space).");
      65        5858 :   params.addParam<bool>(
      66             :       "normalize_by_global_tally",
      67        5858 :       true,
      68             :       "Whether to normalize local tallies by a global tally (true) or else by the sum "
      69             :       "of the local tally (false)");
      70             : 
      71             :   // Options for MGXS generation. At a minimum, we generate multi-group total cross sections.
      72        5858 :   params.addParam<bool>(
      73             :       "add_scattering",
      74        5858 :       true,
      75             :       "Whether or not the scattering multi-group cross section matrix should be generated.");
      76        5858 :   params.addParam<unsigned int>("legendre_order",
      77        5858 :                                 0,
      78             :                                 "The order of the Legendre expansion in scattering angle to use "
      79             :                                 "for generating scattering cross sections. Defaults to 0.");
      80        5858 :   params.addParam<bool>("transport_correction",
      81        5858 :                         true,
      82             :                         "Whether the in-group scattering cross section should include a P0 "
      83             :                         "transport correction or not.");
      84             : 
      85        5858 :   params.addParam<bool>("add_fission",
      86        5858 :                         false,
      87             :                         "Whether or not fission multi-group cross sections (neutron production and "
      88             :                         "the discrete chi spectrum) should be generated.");
      89             : 
      90        5858 :   params.addParam<bool>(
      91             :       "add_fission_heating",
      92        5858 :       false,
      93             :       "Whether or not per-group fission heating (kappa-fission) values should be generated.");
      94             : 
      95        5858 :   params.addParam<bool>("add_inverse_velocity",
      96        5858 :                         false,
      97             :                         "Whether or not per-group inverse velocities should be generated.");
      98             : 
      99        5858 :   params.addParam<bool>(
     100             :       "add_diffusion_coefficient",
     101        5858 :       false,
     102             :       "Whether or not per-group particle diffusion coefficients should be generated.");
     103        5858 :   params.addParam<Real>("void_diffusion_coefficient",
     104        5858 :                         1e3,
     105             :                         "The value the diffusion coefficient should take in a void region.");
     106             : 
     107        5858 :   params.addParam<bool>(
     108             :       "add_absorption",
     109        5858 :       false,
     110             :       "Whether or not absorption multi-group cross sections should be generated.");
     111             : 
     112        5858 :   params.addParam<bool>("hide_tally_vars",
     113        5858 :                         true,
     114             :                         "Whether or not tally variables used to compute multi-group cross sections "
     115             :                         "are hidden in exodus output.");
     116             : 
     117        2929 :   return params;
     118        2929 : }
     119             : 
     120          72 : SetupMGXSAction::SetupMGXSAction(const InputParameters & parameters)
     121             :   : CardinalAction(parameters),
     122             :     EnergyBinBase(this, parameters),
     123          72 :     _t_type(getParam<MooseEnum>("tally_type").getEnum<tally::TallyTypeEnum>()),
     124         144 :     _particle(getParam<MooseEnum>("particle")),
     125         144 :     _estimator(getParam<MooseEnum>("estimator")),
     126         144 :     _add_scattering(getParam<bool>("add_scattering")),
     127         144 :     _l_order(getParam<unsigned int>("legendre_order")),
     128         144 :     _transport_correction(getParam<bool>("transport_correction")),
     129         144 :     _add_fission(getParam<bool>("add_fission")),
     130         144 :     _add_kappa_fission(getParam<bool>("add_fission_heating")),
     131         144 :     _add_inv_vel(getParam<bool>("add_inverse_velocity")),
     132         144 :     _add_diffusion(getParam<bool>("add_diffusion_coefficient")),
     133         144 :     _void_diff(getParam<Real>("void_diffusion_coefficient")),
     134         144 :     _add_absorption(getParam<bool>("add_absorption")),
     135         144 :     _hide_tally_vars(getParam<bool>("hide_tally_vars")),
     136          72 :     _need_p1_scatter(false)
     137             : {
     138          72 :   if (_particle == "electron" || _particle == "positron")
     139           4 :     paramError("particle",
     140             :                "Multi-group cross sections can only be generated for neutrons or photons.");
     141             : 
     142          68 :   if (_add_fission && _particle == "photon")
     143           2 :     paramError("add_fission",
     144             :                "Multi-group fission cross sections / chi spectra cannot be "
     145             :                "generated when selecting particle = 'photon'! Please set 'add_fission = false' to "
     146             :                "continue.");
     147             : 
     148          66 :   if (_add_kappa_fission && _particle == "photon")
     149           2 :     paramError("add_fission_heating",
     150             :                "Multi-group fission heating values cannot be "
     151             :                "generated when selecting particle = 'photon'! Please set add_fission_heating = "
     152             :                "false to continue.");
     153             : 
     154          64 :   if (_t_type == tally::TallyTypeEnum::mesh && _estimator == "tracklength")
     155             :   {
     156           4 :     if (isParamSetByUser("estimator"))
     157           2 :       mooseWarning(
     158             :           "You've selected an unstructured mesh tally discretization for your multi-group cross "
     159             :           "sections and requested a tracklength estimator. Unstructured mesh tallies don't "
     160             :           "support, tracklength estimators, the estimator will be set to 'collision' instead.");
     161             : 
     162           0 :     _estimator.assign("collision");
     163             :   }
     164             : 
     165          62 :   if (_estimator != "analog" && (_add_fission || _add_scattering || _add_diffusion))
     166             :   {
     167           2 :     mooseWarning("You've requested the generation of scattering / fission / diffusion group "
     168             :                  "constants with a "
     169             :                  "non-analog estimator. At present these MGXS don't support 'collision' / "
     170             :                  "'tracklength' estimators, the estimator will be set to 'analog' instead.");
     171             : 
     172           0 :     _estimator.assign("analog");
     173             :   }
     174             : 
     175          60 :   if (_l_order > 0 && _transport_correction)
     176             :   {
     177           4 :     mooseWarning(
     178             :         "Transport-corrected scattering cross sections can only be used with isotropic scattering "
     179           2 :         "(l = 0). You've set l = " +
     180           0 :         Moose::stringify(_l_order) + ", the transport correction will not be applied.");
     181           0 :     _transport_correction = false;
     182             :   }
     183             : 
     184          58 :   if ((_transport_correction || _add_diffusion) && _l_order == 0)
     185          42 :     _need_p1_scatter = true;
     186          58 : }
     187             : 
     188             : void
     189         290 : SetupMGXSAction::act()
     190             : {
     191         290 :   if (_current_task == "add_filters")
     192          58 :     addFilters();
     193             : 
     194         290 :   if (_current_task == "add_tallies")
     195          58 :     addTallies();
     196             : 
     197         290 :   if (_current_task == "add_aux_variable")
     198          58 :     addAuxVars();
     199             : 
     200         290 :   if (_current_task == "add_aux_kernel")
     201          58 :     addAuxKernels();
     202             : 
     203         290 :   if (_current_task == "modify_outputs" && _hide_tally_vars)
     204          58 :     modifyOutputs();
     205         290 : }
     206             : 
     207             : OpenMCCellAverageProblem *
     208        1308 : SetupMGXSAction::openmcProblem()
     209             : {
     210        1308 :   auto p = dynamic_cast<OpenMCCellAverageProblem *>(_problem.get());
     211        1308 :   if (!p)
     212           0 :     mooseError("MGXS can only be used with problems of the type 'OpenMCCellAverageProblem'! Please "
     213             :                "ensure you've added one in the [Problem] block.");
     214        1308 :   return p;
     215             : }
     216             : 
     217             : void
     218          58 : SetupMGXSAction::addFilters()
     219             : {
     220             :   // Need an EnergyFilter for all cross sections.
     221             :   {
     222          58 :     auto params = _factory.getValidParams("EnergyFilter");
     223          58 :     params.set<std::vector<Real>>("energy_boundaries") = _energy_bnds;
     224          58 :     params.set<bool>("reverse_bins") = true;
     225             : 
     226          58 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     227         116 :     openmcProblem()->addFilter("EnergyFilter", "MGXS_EnergyFilter", params);
     228          58 :   }
     229             : 
     230             :   // Need a ParticleFilter for all cross sections.
     231             :   {
     232         116 :     auto params = _factory.getValidParams("ParticleFilter");
     233          58 :     params.set<MultiMooseEnum>("particles") =
     234         232 :         MultiMooseEnum(getParticleFilterEnums().getRawNames(), _particle, false);
     235             : 
     236          58 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     237         116 :     openmcProblem()->addFilter("ParticleFilter", "MGXS_ParticleFilter", params);
     238          58 :   }
     239             : 
     240             :   // Need an EnergyOutFilter for scattering / neutron production cross sections.
     241          58 :   if (_add_scattering || _add_fission || _add_diffusion)
     242             :   {
     243          34 :     auto params = _factory.getValidParams("EnergyOutFilter");
     244          34 :     params.set<std::vector<Real>>("energy_boundaries") = _energy_bnds;
     245          34 :     params.set<bool>("reverse_bins") = true;
     246             : 
     247          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     248          68 :     openmcProblem()->addFilter("EnergyOutFilter", "MGXS_EnergyOutFilter", params);
     249          34 :   }
     250             : 
     251             :   // Need an AngularLegendreFilter for scattering cross sections.
     252          58 :   if (_add_scattering || _add_diffusion)
     253             :   {
     254          34 :     auto params = _factory.getValidParams("AngularLegendreFilter");
     255          34 :     params.set<unsigned int>("order") = _need_p1_scatter ? 1 : _l_order;
     256             : 
     257          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     258          68 :     openmcProblem()->addFilter("AngularLegendreFilter", "MGXS_AngularLegendreFilter", params);
     259          34 :   }
     260          58 : }
     261             : 
     262             : void
     263          58 : SetupMGXSAction::addTallies()
     264             : {
     265             :   // Determine the string form of the tally type.
     266             :   std::string tally_type;
     267          58 :   switch (_t_type)
     268             :   {
     269             :     case tally::TallyTypeEnum::cell:
     270             :       tally_type = "CellTally";
     271             :       break;
     272             : 
     273             :     case tally::TallyTypeEnum::mesh:
     274             :       tally_type = "MeshTally";
     275             :       break;
     276             : 
     277           0 :     default:
     278           0 :       mooseError("Internal error: Unhandled enum in 'tally::TallyTypeEnum'.");
     279             :       break;
     280             :   }
     281             : 
     282             :   // Total and flux tally.
     283             :   {
     284          58 :     auto params = _factory.getValidParams(tally_type);
     285         116 :     if (isParamValid("check_tally_sum"))
     286           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     287         116 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     288          58 :     params.set<MultiMooseEnum>("score") =
     289         232 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "total flux", false);
     290          58 :     params.set<MooseEnum>("estimator") = _estimator;
     291         116 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_total"),
     292         290 :                                                     std::string("mgxs_flux")};
     293         116 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     294         290 :                                                        std::string("MGXS_ParticleFilter")};
     295          58 :     setObjectBlocks(params, _blocks);
     296             : 
     297          58 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     298          58 :     _mgxs_tallies.push_back(
     299         116 :         openmcProblem()->addTally(tally_type, "MGXS_" + tally_type + "_Total_Flux", params).get());
     300          58 :   }
     301             : 
     302             :   // Scattering tally.
     303          58 :   if (_add_scattering || _add_diffusion)
     304             :   {
     305          34 :     auto params = _factory.getValidParams(tally_type);
     306          68 :     if (isParamValid("check_tally_sum"))
     307           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     308          68 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     309          34 :     params.set<MultiMooseEnum>("score") =
     310         136 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "nu_scatter", false);
     311          68 :     params.set<MooseEnum>("estimator") = "analog";
     312         102 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_scatter")};
     313          68 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     314             :                                                        std::string("MGXS_EnergyOutFilter"),
     315             :                                                        std::string("MGXS_AngularLegendreFilter"),
     316         238 :                                                        std::string("MGXS_ParticleFilter")};
     317          34 :     setObjectBlocks(params, _blocks);
     318             : 
     319          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     320             :     _mgxs_tallies.push_back(
     321          68 :         openmcProblem()->addTally(tally_type, "MGXS_" + tally_type + "_Scatter", params).get());
     322          34 :   }
     323             : 
     324             :   // Fission tally.
     325          58 :   if (_add_fission)
     326             :   {
     327          18 :     auto params = _factory.getValidParams(tally_type);
     328          36 :     if (isParamValid("check_tally_sum"))
     329           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     330          36 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     331          18 :     params.set<MultiMooseEnum>("score") =
     332          72 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "nu_fission", false);
     333          36 :     params.set<MooseEnum>("estimator") = "analog";
     334          54 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_fission")};
     335          36 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     336             :                                                        std::string("MGXS_EnergyOutFilter"),
     337         108 :                                                        std::string("MGXS_ParticleFilter")};
     338          18 :     setObjectBlocks(params, _blocks);
     339             : 
     340          18 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     341             :     _mgxs_tallies.push_back(
     342          36 :         openmcProblem()->addTally(tally_type, "MGXS_" + tally_type + "_Fission", params).get());
     343          18 :   }
     344             : 
     345             :   // Kappa-fission tally.
     346          58 :   if (_add_kappa_fission)
     347             :   {
     348          34 :     auto params = _factory.getValidParams(tally_type);
     349          68 :     if (isParamValid("check_tally_sum"))
     350           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     351          68 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     352          34 :     params.set<MultiMooseEnum>("score") =
     353         136 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "kappa_fission", false);
     354          34 :     params.set<MooseEnum>("estimator") = _estimator;
     355         102 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_kappa_fission")};
     356          68 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     357         170 :                                                        std::string("MGXS_ParticleFilter")};
     358          34 :     setObjectBlocks(params, _blocks);
     359             : 
     360          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     361             :     _mgxs_tallies.push_back(
     362             :         openmcProblem()
     363          68 :             ->addTally(tally_type, "MGXS_" + tally_type + "_Kappa_Fission", params)
     364          34 :             .get());
     365          34 :   }
     366             : 
     367             :   // Inverse velocity tally.
     368          58 :   if (_add_inv_vel)
     369             :   {
     370          34 :     auto params = _factory.getValidParams(tally_type);
     371          68 :     if (isParamValid("check_tally_sum"))
     372           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     373          68 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     374          34 :     params.set<MultiMooseEnum>("score") =
     375         136 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "inverse_velocity", false);
     376          34 :     params.set<MooseEnum>("estimator") = _estimator;
     377         102 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_inverse_velocity")};
     378          68 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     379         170 :                                                        std::string("MGXS_ParticleFilter")};
     380          34 :     setObjectBlocks(params, _blocks);
     381             : 
     382          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     383             :     _mgxs_tallies.push_back(
     384             :         openmcProblem()
     385          68 :             ->addTally(tally_type, "MGXS_" + tally_type + "_Inverse_velocity", params)
     386          34 :             .get());
     387          34 :   }
     388             : 
     389             :   // Absorption tally.
     390          58 :   if (_add_absorption)
     391             :   {
     392          34 :     auto params = _factory.getValidParams(tally_type);
     393          68 :     if (isParamValid("check_tally_sum"))
     394           0 :       params.set<bool>("check_tally_sum") = getParam<bool>("check_tally_sum");
     395          68 :     params.set<bool>("normalize_by_global_tally") = getParam<bool>("normalize_by_global_tally");
     396          34 :     params.set<MultiMooseEnum>("score") =
     397         136 :         MultiMooseEnum(getTallyScoreEnum().getRawNames(), "absorption", false);
     398          34 :     params.set<MooseEnum>("estimator") = _estimator;
     399         102 :     params.set<std::vector<std::string>>("name") = {std::string("mgxs_absorption")};
     400          68 :     params.set<std::vector<std::string>>("filters") = {std::string("MGXS_EnergyFilter"),
     401         170 :                                                        std::string("MGXS_ParticleFilter")};
     402          34 :     setObjectBlocks(params, _blocks);
     403             : 
     404          34 :     params.set<OpenMCCellAverageProblem *>("_openmc_problem") = openmcProblem();
     405             :     _mgxs_tallies.push_back(
     406          68 :         openmcProblem()->addTally(tally_type, "MGXS_" + tally_type + "_Absorption", params).get());
     407          34 :   }
     408         694 : }
     409             : 
     410             : void
     411          58 : SetupMGXSAction::addAuxVars()
     412             : {
     413             :   // Total MGXE variables.
     414         166 :   for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     415             :   {
     416         108 :     const std::string name = "total_xs_g" + Moose::stringify(g + 1);
     417         108 :     auto params = _factory.getValidParams("MooseVariable");
     418         216 :     params.set<MooseEnum>("family") = "MONOMIAL";
     419         216 :     params.set<MooseEnum>("order") = "CONSTANT";
     420         108 :     setObjectBlocks(params, _blocks);
     421             : 
     422         108 :     openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     423         108 :     _problem->addAuxVariable("MooseVariable", name, params);
     424         108 :   }
     425             : 
     426             :   // Scattering matrix MGXS variables.
     427          58 :   if (_add_scattering)
     428             :   {
     429          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     430             :     {
     431         172 :       for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     432             :       {
     433         256 :         for (unsigned int l = 0; l <= _l_order; ++l)
     434             :         {
     435         432 :           const std::string name = "scatter_xs_g" + Moose::stringify(g + 1) + "_gp" +
     436         432 :                                    Moose::stringify(g_prime + 1) + "_l" + Moose::stringify(l);
     437         144 :           auto params = _factory.getValidParams("MooseVariable");
     438         288 :           params.set<MooseEnum>("family") = "MONOMIAL";
     439         288 :           params.set<MooseEnum>("order") = "CONSTANT";
     440         144 :           setObjectBlocks(params, _blocks);
     441             : 
     442         144 :           openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     443         144 :           _problem->addAuxVariable("MooseVariable", name, params);
     444         144 :         }
     445             :       }
     446             :     }
     447             :   }
     448             : 
     449             :   // Neutron production MGXS and discrete chi spectrum variables.
     450          58 :   if (_add_fission)
     451             :   {
     452          46 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     453             :     {
     454             :       {
     455          28 :         const std::string name = "nu_fission_xs_g" + Moose::stringify(g + 1);
     456          28 :         auto params = _factory.getValidParams("MooseVariable");
     457          56 :         params.set<MooseEnum>("family") = "MONOMIAL";
     458          56 :         params.set<MooseEnum>("order") = "CONSTANT";
     459          28 :         setObjectBlocks(params, _blocks);
     460             : 
     461          28 :         openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     462          28 :         _problem->addAuxVariable("MooseVariable", name, params);
     463          28 :       }
     464             :       {
     465          28 :         const std::string name = "chi_g" + Moose::stringify(g + 1);
     466          28 :         auto params = _factory.getValidParams("MooseVariable");
     467          56 :         params.set<MooseEnum>("family") = "MONOMIAL";
     468          56 :         params.set<MooseEnum>("order") = "CONSTANT";
     469          28 :         setObjectBlocks(params, _blocks);
     470             : 
     471          28 :         openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     472          28 :         _problem->addAuxVariable("MooseVariable", name, params);
     473          28 :       }
     474             :     }
     475             :   }
     476             : 
     477             :   // Discrete kappa-fission variables.
     478          58 :   if (_add_kappa_fission)
     479             :   {
     480          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     481             :     {
     482          60 :       const std::string name = "kappa_fission_g" + Moose::stringify(g + 1);
     483          60 :       auto params = _factory.getValidParams("MooseVariable");
     484         120 :       params.set<MooseEnum>("family") = "MONOMIAL";
     485         120 :       params.set<MooseEnum>("order") = "CONSTANT";
     486          60 :       setObjectBlocks(params, _blocks);
     487             : 
     488          60 :       openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     489          60 :       _problem->addAuxVariable("MooseVariable", name, params);
     490          60 :     }
     491             :   }
     492             : 
     493             :   // Inverse velocity MGXS variables.
     494          58 :   if (_add_inv_vel)
     495             :   {
     496          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     497             :     {
     498          60 :       const std::string name = "inv_v_g" + Moose::stringify(g + 1);
     499          60 :       auto params = _factory.getValidParams("MooseVariable");
     500         120 :       params.set<MooseEnum>("family") = "MONOMIAL";
     501         120 :       params.set<MooseEnum>("order") = "CONSTANT";
     502          60 :       setObjectBlocks(params, _blocks);
     503             : 
     504          60 :       openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     505          60 :       _problem->addAuxVariable("MooseVariable", name, params);
     506          60 :     }
     507             :   }
     508             : 
     509             :   // MG diffusion coefficients.
     510          58 :   if (_add_diffusion)
     511             :   {
     512          46 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     513             :     {
     514          28 :       const std::string name = "diff_g" + Moose::stringify(g + 1);
     515          28 :       auto params = _factory.getValidParams("MooseVariable");
     516          56 :       params.set<MooseEnum>("family") = "MONOMIAL";
     517          56 :       params.set<MooseEnum>("order") = "CONSTANT";
     518          28 :       setObjectBlocks(params, _blocks);
     519             : 
     520          28 :       openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     521          28 :       _problem->addAuxVariable("MooseVariable", name, params);
     522          28 :     }
     523             :   }
     524             : 
     525             :   // Absorption MGXE variables.
     526          58 :   if (_add_absorption)
     527             :   {
     528          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     529             :     {
     530          60 :       const std::string name = "abs_xs_g" + Moose::stringify(g + 1);
     531          60 :       auto params = _factory.getValidParams("MooseVariable");
     532         120 :       params.set<MooseEnum>("family") = "MONOMIAL";
     533         120 :       params.set<MooseEnum>("order") = "CONSTANT";
     534          60 :       setObjectBlocks(params, _blocks);
     535             : 
     536          60 :       openmcProblem()->checkDuplicateVariableName(name, "MGXS");
     537          60 :       _problem->addAuxVariable("MooseVariable", name, params);
     538          60 :     }
     539             :   }
     540          58 : }
     541             : 
     542             : void
     543          58 : SetupMGXSAction::addAuxKernels()
     544             : {
     545             :   // Add auxkernels to compute the total MGXS'.
     546         166 :   for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     547             :   {
     548         108 :     const auto n = "total_xs_g" + Moose::stringify(g + 1);
     549         216 :     auto params = _factory.getValidParams("ComputeMGXSAux");
     550         216 :     params.set<AuxVariableName>("variable") = n;
     551         108 :     params.set<std::vector<VariableName>>("rxn_rates")
     552         324 :         .emplace_back("mgxs_total_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     553         108 :     params.set<std::vector<VariableName>>("normalize_by")
     554         324 :         .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     555         108 :     setObjectBlocks(params, _blocks);
     556             : 
     557         216 :     _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     558         108 :   }
     559             : 
     560             :   // Add auxkernels to compute the elements of the MGXS scattering matrix.
     561          58 :   if (_add_scattering)
     562             :   {
     563          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     564             :     {
     565         172 :       for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     566             :       {
     567             :         // Handle within-group scattering cross sections separately for
     568             :         // transport-corrected P0 cross sections.
     569         112 :         if (g == g_prime && _transport_correction)
     570          20 :           continue;
     571             : 
     572         216 :         for (unsigned int l = 0; l <= _l_order; ++l)
     573             :         {
     574         372 :           const auto n = "scatter_xs_g" + Moose::stringify(g + 1) + "_gp" +
     575         372 :                          Moose::stringify(g_prime + 1) + "_l" + Moose::stringify(l);
     576         248 :           auto params = _factory.getValidParams("ComputeMGXSAux");
     577         248 :           params.set<AuxVariableName>("variable") = n;
     578         124 :           params.set<std::vector<VariableName>>("rxn_rates")
     579         496 :               .emplace_back("mgxs_scatter_g" + Moose::stringify(g + 1) + "_gp" +
     580         372 :                             Moose::stringify(g_prime + 1) + "_l" + Moose::stringify(l) + "_" +
     581         124 :                             std::string(_particle));
     582         124 :           params.set<std::vector<VariableName>>("normalize_by")
     583         372 :               .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     584         124 :           setObjectBlocks(params, _blocks);
     585             : 
     586         248 :           _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     587         124 :         }
     588             :       }
     589             :     }
     590             : 
     591          34 :     if (_transport_correction)
     592             :     {
     593          30 :       for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     594             :       {
     595             :         const auto n =
     596          80 :             "scatter_xs_g" + Moose::stringify(g + 1) + "_gp" + Moose::stringify(g + 1) + "_l0";
     597          40 :         auto params = _factory.getValidParams("ComputeTCScatterMGXSAux");
     598          40 :         params.set<AuxVariableName>("variable") = n;
     599          20 :         params.set<std::vector<VariableName>>("p0_scatter_rxn_rate")
     600          80 :             .emplace_back("mgxs_scatter_g" + Moose::stringify(g + 1) + "_gp" +
     601          40 :                           Moose::stringify(g + 1) + "_l0_" + std::string(_particle));
     602          60 :         for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     603          80 :           params.set<std::vector<VariableName>>("p1_scatter_rxn_rates")
     604         160 :               .emplace_back("mgxs_scatter_g" + Moose::stringify(g_prime + 1) + "_gp" +
     605          80 :                             Moose::stringify(g + 1) + "_l1_" + std::string(_particle));
     606          20 :         params.set<std::vector<VariableName>>("scalar_flux")
     607          60 :             .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     608          20 :         setObjectBlocks(params, _blocks);
     609             : 
     610          40 :         _problem->addAuxKernel("ComputeTCScatterMGXSAux", "comp_" + n, params);
     611          20 :       }
     612             :     }
     613             :   }
     614             : 
     615             :   // Add auxkernels to compute the fission neutron production MGXS and the discrete chi spectrum.
     616          58 :   if (_add_fission)
     617             :   {
     618          46 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     619             :     {
     620          28 :       const auto n = "nu_fission_xs_g" + Moose::stringify(g + 1);
     621          56 :       auto params = _factory.getValidParams("ComputeMGXSAux");
     622          56 :       params.set<AuxVariableName>("variable") = n;
     623          76 :       for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     624             :       {
     625          96 :         params.set<std::vector<VariableName>>("rxn_rates")
     626         192 :             .emplace_back("mgxs_fission_g" + Moose::stringify(g + 1) + "_gp" +
     627         144 :                           Moose::stringify(g_prime + 1) + "_" + std::string(_particle));
     628             :       }
     629          28 :       params.set<std::vector<VariableName>>("normalize_by")
     630          84 :           .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     631          28 :       setObjectBlocks(params, _blocks);
     632             : 
     633          56 :       _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     634          28 :     }
     635             : 
     636             :     std::vector<VariableName> all_fission;
     637          46 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     638          76 :       for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     639         192 :         all_fission.emplace_back("mgxs_fission_g" + Moose::stringify(g + 1) + "_gp" +
     640         144 :                                  Moose::stringify(g_prime + 1) + "_" + std::string(_particle));
     641             : 
     642          46 :     for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     643             :     {
     644          28 :       const auto n = "chi_g" + Moose::stringify(g_prime + 1);
     645          56 :       auto params = _factory.getValidParams("ComputeMGXSAux");
     646          56 :       params.set<AuxVariableName>("variable") = n;
     647          76 :       for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     648             :       {
     649          96 :         params.set<std::vector<VariableName>>("rxn_rates")
     650         192 :             .emplace_back("mgxs_fission_g" + Moose::stringify(g + 1) + "_gp" +
     651          96 :                           Moose::stringify(g_prime + 1) + "_" + std::string(_particle));
     652             :       }
     653          28 :       params.set<std::vector<VariableName>>("normalize_by") = all_fission;
     654          28 :       setObjectBlocks(params, _blocks);
     655             : 
     656          56 :       _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     657          28 :     }
     658          18 :   }
     659             : 
     660             :   // Add auxkernels to compute a group-wise kappa fission.
     661          58 :   if (_add_kappa_fission)
     662             :   {
     663          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     664             :     {
     665          60 :       const auto n = "kappa_fission_g" + Moose::stringify(g + 1);
     666         120 :       auto params = _factory.getValidParams("ComputeMGXSAux");
     667         120 :       params.set<AuxVariableName>("variable") = n;
     668          60 :       params.set<std::vector<VariableName>>("rxn_rates")
     669         180 :           .emplace_back("mgxs_kappa_fission_g" + Moose::stringify(g + 1) + "_" +
     670          60 :                         std::string(_particle));
     671          60 :       params.set<std::vector<VariableName>>("normalize_by")
     672         180 :           .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     673          60 :       setObjectBlocks(params, _blocks);
     674             : 
     675         120 :       _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     676          60 :     }
     677             :   }
     678             : 
     679             :   // Add auxkernels to compute a group-wise inverse velocity.
     680          58 :   if (_add_inv_vel)
     681             :   {
     682          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     683             :     {
     684          60 :       const auto n = "inv_v_g" + Moose::stringify(g + 1);
     685         120 :       auto params = _factory.getValidParams("ComputeMGXSAux");
     686         120 :       params.set<AuxVariableName>("variable") = n;
     687          60 :       params.set<std::vector<VariableName>>("rxn_rates")
     688         180 :           .emplace_back("mgxs_inverse_velocity_g" + Moose::stringify(g + 1) + "_" +
     689          60 :                         std::string(_particle));
     690          60 :       params.set<std::vector<VariableName>>("normalize_by")
     691         180 :           .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     692          60 :       setObjectBlocks(params, _blocks);
     693             : 
     694         120 :       _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     695          60 :     }
     696             :   }
     697             : 
     698             :   // Add auxkernels to compute MG diffusion coefficients.
     699          58 :   if (_add_diffusion)
     700             :   {
     701          46 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     702             :     {
     703          28 :       const std::string n = "diff_g" + Moose::stringify(g + 1);
     704          56 :       auto params = _factory.getValidParams("ComputeDiffusionCoeffMGAux");
     705          56 :       params.set<AuxVariableName>("variable") = n;
     706          28 :       params.set<std::vector<VariableName>>("total_rxn_rate")
     707          84 :           .emplace_back("mgxs_total_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     708          28 :       params.set<std::vector<VariableName>>("scalar_flux")
     709          84 :           .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     710          28 :       params.set<Real>("void_diffusion_coefficient") = _void_diff;
     711          76 :       for (unsigned int g_prime = 0; g_prime < _energy_bnds.size() - 1; ++g_prime)
     712          96 :         params.set<std::vector<VariableName>>("p1_scatter_rxn_rates")
     713         192 :             .emplace_back("mgxs_scatter_g" + Moose::stringify(g_prime + 1) + "_gp" +
     714          96 :                           Moose::stringify(g + 1) + "_l1_" + std::string(_particle));
     715          28 :       setObjectBlocks(params, _blocks);
     716             : 
     717          56 :       _problem->addAuxKernel("ComputeDiffusionCoeffMGAux", "comp_" + n, params);
     718          28 :     }
     719             :   }
     720             : 
     721             :   // Add auxkernels to compute the absorption MGXS'.
     722          58 :   if (_add_absorption)
     723             :   {
     724          94 :     for (unsigned int g = 0; g < _energy_bnds.size() - 1; ++g)
     725             :     {
     726          60 :       const auto n = "abs_xs_g" + Moose::stringify(g + 1);
     727         120 :       auto params = _factory.getValidParams("ComputeMGXSAux");
     728         120 :       params.set<AuxVariableName>("variable") = n;
     729          60 :       params.set<std::vector<VariableName>>("rxn_rates")
     730         180 :           .emplace_back("mgxs_absorption_g" + Moose::stringify(g + 1) + "_" +
     731          60 :                         std::string(_particle));
     732          60 :       params.set<std::vector<VariableName>>("normalize_by")
     733         180 :           .emplace_back("mgxs_flux_g" + Moose::stringify(g + 1) + "_" + std::string(_particle));
     734          60 :       setObjectBlocks(params, _blocks);
     735             : 
     736         120 :       _problem->addAuxKernel("ComputeMGXSAux", "comp_" + n, params);
     737          60 :     }
     738             :   }
     739          58 : }
     740             : 
     741             : void
     742          58 : SetupMGXSAction::modifyOutputs()
     743             : {
     744         116 :   const auto & output_actions = _app.actionWarehouse().getActionListByName("add_output");
     745         348 :   for (const auto & act : output_actions)
     746             :   {
     747             :     // Extract the Output action.
     748         290 :     AddOutputAction * action = dynamic_cast<AddOutputAction *>(act);
     749         290 :     if (!action)
     750          58 :       continue;
     751             : 
     752             :     // Hide the tally variables.
     753             :     InputParameters & output_params = action->getObjectParams();
     754         232 :     if (output_params.have_parameter<std::vector<VariableName>>("hide"))
     755         810 :       for (const auto & t : _mgxs_tallies)
     756        2544 :         for (const auto & v : t->getAuxVarNames())
     757        3816 :           output_params.set<std::vector<VariableName>>("hide").emplace_back(v);
     758             :   }
     759          58 : }
     760             : 
     761             : #endif

Generated by: LCOV version 1.14