LCOV - code coverage report
Current view: top level - src/actions - DimensionalizeAction.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: be601f Lines: 73 76 96.1 %
Date: 2025-07-15 20:50:38 Functions: 4 4 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /********************************************************************/
       2             : /*                  SOFTWARE COPYRIGHT NOTIFICATION                 */
       3             : /*                             Cardinal                             */
       4             : /*                                                                  */
       5             : /*                  (c) 2021 UChicago Argonne, LLC                  */
       6             : /*                        ALL RIGHTS RESERVED                       */
       7             : /*                                                                  */
       8             : /*                 Prepared by UChicago Argonne, LLC                */
       9             : /*               Under Contract No. DE-AC02-06CH11357               */
      10             : /*                With the U. S. Department of Energy               */
      11             : /*                                                                  */
      12             : /*             Prepared by Battelle Energy Alliance, LLC            */
      13             : /*               Under Contract No. DE-AC07-05ID14517               */
      14             : /*                With the U. S. Department of Energy               */
      15             : /*                                                                  */
      16             : /*                 See LICENSE for full restrictions                */
      17             : /********************************************************************/
      18             : 
      19             : #ifdef ENABLE_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

Generated by: LCOV version 1.14