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

Generated by: LCOV version 1.14