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_NEK_COUPLING
20 : #include "DimensionalizeAction.h"
21 : #include "NekRSProblem.h"
22 : #include "NekInterface.h"
23 : #include "VariadicTable.h"
24 : #include "NekRSMesh.h"
25 : #include "UserErrorChecking.h"
26 :
27 : registerMooseAction("CardinalApp", DimensionalizeAction, "add_dimensionalization");
28 :
29 : InputParameters
30 115 : DimensionalizeAction::validParams()
31 : {
32 115 : auto params = Action::validParams();
33 115 : params.addClassDescription("Defines how to dimensionalize the NekRS fields when accessing from "
34 : "MOOSE as AuxVariables, in Postprocessors, in UserObjects, etc.");
35 :
36 230 : params.addRangeCheckedParam<Real>("U", 1.0, "U > 0.0", "Reference velocity");
37 230 : params.addRangeCheckedParam<Real>("L", 1.0, "L > 0.0", "Reference length");
38 230 : params.addRangeCheckedParam<Real>("rho", 1.0, "rho > 0.0", "Reference density");
39 230 : params.addRangeCheckedParam<Real>("Cp", 1.0, "Cp > 0.0", "Reference isobaric specific heat");
40 :
41 : // for passive scalars, these are typically dimensionalized as (T - T0) / dT
42 230 : params.addRangeCheckedParam<Real>("T", 0.0, "T >= 0.0", "Reference temperature");
43 230 : params.addRangeCheckedParam<Real>("dT", 1.0, "dT > 0.0", "Reference temperature difference");
44 230 : params.addRangeCheckedParam<Real>("s01", 0.0, "s01 >= 0.0", "Reference scalar 1");
45 230 : params.addRangeCheckedParam<Real>("ds01", 1.0, "ds01 > 0.0", "Reference scalar 1 difference");
46 230 : params.addRangeCheckedParam<Real>("s02", 0.0, "s02 >= 0.0", "Reference scalar 2");
47 230 : params.addRangeCheckedParam<Real>("ds02", 2.0, "ds02 > 0.0", "Reference scalar 2 difference");
48 230 : params.addRangeCheckedParam<Real>("s03", 0.0, "s03 >= 0.0", "Reference scalar 3");
49 230 : params.addRangeCheckedParam<Real>("ds03", 3.0, "ds03 > 0.0", "Reference scalar 3 difference");
50 115 : return params;
51 0 : }
52 :
53 115 : DimensionalizeAction::DimensionalizeAction(const InputParameters & parameters)
54 : : Action(parameters),
55 115 : _U(getParam<Real>("U")),
56 230 : _T(getParam<Real>("T")),
57 230 : _dT(getParam<Real>("dT")),
58 230 : _s01(getParam<Real>("s01")),
59 230 : _ds01(getParam<Real>("ds01")),
60 230 : _s02(getParam<Real>("s02")),
61 230 : _ds02(getParam<Real>("ds02")),
62 230 : _s03(getParam<Real>("s03")),
63 230 : _ds03(getParam<Real>("ds03")),
64 230 : _L(getParam<Real>("L")),
65 230 : _rho(getParam<Real>("rho")),
66 345 : _Cp(getParam<Real>("Cp"))
67 : {
68 : // inform NekRS of the scaling that we are using; the NekInterface holds all
69 : // the reference scales and provides accessor methods
70 115 : nekrs::initializeDimensionalScales(
71 115 : _U, _T, _dT, _L, _rho, _Cp, _s01, _ds01, _s02, _ds02, _s03, _ds03);
72 115 : }
73 :
74 : void
75 113 : DimensionalizeAction::act()
76 : {
77 113 : if (_current_task == "add_dimensionalization")
78 : {
79 113 : auto nek_problem = dynamic_cast<NekRSProblem *>(_problem.get());
80 :
81 113 : if (!nek_problem)
82 1 : mooseError("The [Dimensionalize] block can only be used with wrapped Nek cases! "
83 : "You need to change the [Problem] block to type NekRSProblem.");
84 :
85 : // check if the temperature actually exists
86 112 : if (!nekrs::hasTemperatureVariable())
87 : {
88 0 : checkUnusedParam(parameters(), "T", "NekRS case files do not have a temperature variable");
89 0 : checkUnusedParam(parameters(), "dT", "NekRS case files do not have a temperature variable");
90 : }
91 :
92 : // check if the scalars actually exist; we currently support 3 scalars
93 448 : for (int i = 0; i < 3; ++i)
94 : {
95 336 : if (!nekrs::hasScalarVariable(i))
96 : {
97 178 : auto is = std::to_string(i);
98 356 : checkUnusedParam(parameters(), "s0" + is, "NekRS case files do not have a SCALAR" + is);
99 356 : checkUnusedParam(parameters(), "ds0" + is, "NekRS case files do not have a SCALAR" + is);
100 : }
101 : }
102 :
103 : // It's too complicated to make sure that the dimensional form _also_ works when our
104 : // reference coordinates are different from what MOOSE is expecting, so just throw an error
105 112 : auto nek_mesh = dynamic_cast<NekRSMesh *>(&(_problem->mesh()));
106 112 : if (!MooseUtils::absoluteFuzzyEqual(nek_mesh->scaling(), _L))
107 1 : paramError("L",
108 : "If solving NekRS in nondimensional form, you must choose "
109 : "reference dimensional scales in the same units as expected by MOOSE, i.e. 'L' "
110 : "must match 'scaling' in 'NekRSMesh'.");
111 :
112 333 : VariadicTable<std::string, std::string> vt({"Quantity (Non-Dimensional)", "Expression"});
113 :
114 1248 : auto compress = [](Real a)
115 : {
116 1248 : std::ostringstream v;
117 : v << std::setprecision(3) << std::scientific << a;
118 1248 : return v.str();
119 1248 : };
120 :
121 222 : vt.addRow("Position", "x / " + compress(_L));
122 222 : vt.addRow("Time", "t / " + compress(nekrs::referenceTime()));
123 222 : vt.addRow("Velocity", "u / " + compress(_U));
124 222 : vt.addRow("Pressure", "P / " + compress(nekrs::nondimensionalDivisor(field::pressure)));
125 :
126 111 : if (nekrs::hasScalarVariable(0))
127 : {
128 444 : vt.addRow("Temperature", "(T - " + compress(_T) + ") / " + compress(_dT));
129 222 : vt.addRow("Heat flux", "q'' / " + compress(nekrs::nondimensionalDivisor(field::flux)));
130 222 : vt.addRow("Power density",
131 222 : "q / " + compress(nekrs::nondimensionalDivisor(field::heat_source)));
132 : }
133 :
134 : // TODO: when we add coupling for scalars, we will need to add internal variables
135 : // to hold reference scales for flux and source terms, in addition to the
136 : // collecting the material property info for properly obtaining those values
137 111 : if (nekrs::hasScalarVariable(1))
138 92 : vt.addRow("Scalar 01", "(s - " + compress(_s01) + ") /" + compress(_ds01));
139 111 : if (nekrs::hasScalarVariable(2))
140 92 : vt.addRow("Scalar 02", "(s - " + compress(_s02) + ") /" + compress(_ds02));
141 111 : if (nekrs::hasScalarVariable(3))
142 92 : vt.addRow("Scalar 03", "(s - " + compress(_s03) + ") /" + compress(_ds03));
143 :
144 222 : vt.addRow("Density", "rho / " + compress(_rho));
145 222 : vt.addRow("Specific heat", "Cp / " + compress(_Cp));
146 :
147 111 : _console << "Scales used for dimensionalizing the NekRS fields:" << std::endl;
148 111 : vt.print(_console);
149 111 : _console << std::endl;
150 111 : }
151 333 : }
152 :
153 : #endif
|