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
|