LCOV - code coverage report
Current view: top level - src/transfers - NekFieldVariable.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: 920dc5 Lines: 67 77 87.0 %
Date: 2025-08-10 20:41:39 Functions: 5 5 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             : 
      21             : #include "NekFieldVariable.h"
      22             : 
      23             : registerMooseObject("CardinalApp", NekFieldVariable);
      24             : 
      25             : InputParameters
      26        1602 : NekFieldVariable::validParams()
      27             : {
      28        1602 :   auto params = FieldTransferBase::validParams();
      29        3204 :   params.addParam<MooseEnum>(
      30             :       "field",
      31        3204 :       getNekFieldEnum(),
      32             :       "NekRS field variable to read/write; defaults to the name of the object");
      33        1602 :   params.addClassDescription("Reads/writes volumetric field data between NekRS and MOOSE.");
      34        1602 :   return params;
      35           0 : }
      36             : 
      37         801 : NekFieldVariable::NekFieldVariable(const InputParameters & parameters)
      38         801 :   : FieldTransferBase(parameters)
      39             : {
      40         801 :   if (_direction == "from_nek")
      41        1558 :     addExternalVariable(_variable);
      42             :   else
      43             :   {
      44          21 :     if (_usrwrk_slot.size() > 1)
      45           2 :       paramError("usrwrk_slot",
      46             :                  "'usrwrk_slot' must be of length 1 for field transfers to_nek; you have entered "
      47           1 :                  "a vector of length " +
      48           0 :                      Moose::stringify(_usrwrk_slot.size()));
      49             : 
      50          40 :     addExternalVariable(_usrwrk_slot[0], _variable);
      51             : 
      52             :     // we don't impose any requirements on boundary conditions on the NekRS side, because this data
      53             :     // being sent to NekRS doesn't necessarily get used in a boundary condition. It could get used
      54             :     // in a source term, for instance.
      55             :   }
      56             : 
      57        1596 :   if (isParamValid("field"))
      58        1302 :     _field = getParam<MooseEnum>("field").getEnum<field::NekFieldEnum>();
      59             :   else
      60             :   {
      61             :     // try a reasonable default by seeing if the object name matches a valid enumeration
      62         147 :     auto enums = getNekFieldEnum().getNames();
      63         147 :     auto obj_name = name();
      64             :     std::transform(obj_name.begin(), obj_name.end(), obj_name.begin(), ::toupper);
      65         147 :     bool found_name = std::find(enums.begin(), enums.end(), obj_name) != enums.end();
      66         147 :     if (found_name)
      67         146 :       _field = convertToFieldEnum(obj_name);
      68             :     else
      69           1 :       paramError("field",
      70           1 :                  "We tried to choose a default 'field' as '" + name() +
      71             :                      "', but this value is not an option in the 'field' enumeration. Please "
      72             :                      "provide the 'field' parameter.");
      73         146 :   }
      74             : 
      75         797 :   if (_direction == "to_nek")
      76             :   {
      77          20 :     switch (_field)
      78             :     {
      79          20 :       case field::temperature:
      80          20 :         indices.temperature = _usrwrk_slot[0] * nekrs::fieldOffset();
      81             :         break;
      82           0 :       default:
      83           0 :         paramError("field",
      84             :                    "NekFieldVariable currently only supports transfers 'to_nek' for 'temperature'. "
      85             :                    "Please contact the Cardinal developer team if you require writing of other "
      86             :                    "NekRS field variables.");
      87             :     }
      88             :   }
      89             : 
      90         797 :   if (_field == field::velocity_component)
      91           0 :     paramError("field",
      92             :                "'velocity_component' is not yet supported; if you need velocity dotted with a "
      93             :                "specific direction, extract the three components of velocity and perform the "
      94             :                "postprocessing operation using a ParsedAux. If this is hindering your workflow, "
      95             :                "please contact the Cardinal developer team.");
      96         797 : }
      97             : 
      98             : field::NekFieldEnum
      99         146 : NekFieldVariable::convertToFieldEnum(const std::string name) const
     100             : {
     101         146 :   auto lowercase = name;
     102             :   std::transform(lowercase.begin(), lowercase.end(), lowercase.begin(), ::tolower);
     103         146 :   if (lowercase == "velocity_x")
     104             :     return field::velocity_x;
     105         130 :   if (lowercase == "velocity_y")
     106             :     return field::velocity_y;
     107         114 :   if (lowercase == "velocity_z")
     108             :     return field::velocity_z;
     109         106 :   if (lowercase == "velocity")
     110             :     return field::velocity;
     111         102 :   if (lowercase == "velocity_component")
     112             :     return field::velocity_component;
     113         102 :   if (lowercase == "velocity_x_squared")
     114             :     return field::velocity_x_squared;
     115         102 :   if (lowercase == "velocity_y_squared")
     116             :     return field::velocity_y_squared;
     117         102 :   if (lowercase == "velocity_z_squared")
     118             :     return field::velocity_z_squared;
     119          98 :   if (lowercase == "temperature")
     120             :     return field::temperature;
     121          54 :   if (lowercase == "pressure")
     122             :     return field::pressure;
     123          46 :   if (lowercase == "scalar01")
     124             :     return field::scalar01;
     125          34 :   if (lowercase == "scalar02")
     126             :     return field::scalar02;
     127           8 :   if (lowercase == "scalar03")
     128             :     return field::scalar03;
     129           0 :   if (lowercase == "unity")
     130             :     return field::unity;
     131           0 :   if (lowercase == "usrwrk00")
     132             :     return field::usrwrk00;
     133           0 :   if (lowercase == "usrwrk01")
     134             :     return field::usrwrk01;
     135           0 :   if (lowercase == "usrwrk02")
     136             :     return field::usrwrk02;
     137             : 
     138           0 :   mooseError("Unhandled NekFieldEnum in NekFieldVariable!");
     139             : }
     140             : 
     141             : void
     142       88448 : NekFieldVariable::readDataFromNek()
     143             : {
     144       88448 :   if (!_nek_mesh->volume())
     145       20414 :     _nek_problem.boundarySolution(_field, _external_data);
     146             :   else
     147       68034 :     _nek_problem.volumeSolution(_field, _external_data);
     148             : 
     149       88448 :   fillAuxVariable(_variable_number[_variable], _external_data);
     150       88448 : }
     151             : 
     152             : void
     153         256 : NekFieldVariable::sendDataToNek()
     154             : {
     155         256 :   _console << "Sending " << _variable << " to NekRS..." << std::endl;
     156         256 :   auto d = nekrs::nondimensionalDivisor(_field);
     157         256 :   auto a = nekrs::nondimensionalAdditive(_field);
     158             : 
     159         256 :   if (!_nek_mesh->volume())
     160             :   {
     161        6312 :     for (unsigned int e = 0; e < _nek_mesh->numSurfaceElems(); e++)
     162             :     {
     163             :       // We can only write into the nekRS scratch space if that face is "owned" by the current
     164             :       // process
     165        6068 :       if (nekrs::commRank() != _nek_mesh->boundaryCoupling().processor_id(e))
     166        5034 :         continue;
     167             : 
     168        1034 :       _nek_problem.mapFaceDataToNekFace(e, _variable_number[_variable], d, a, &_v_face);
     169        1034 :       _nek_problem.writeBoundarySolution(e, _field, _v_face);
     170             :     }
     171             :   }
     172             :   else
     173             :   {
     174        3888 :     for (unsigned int e = 0; e < _nek_mesh->numVolumeElems(); ++e)
     175             :     {
     176             :       // We can only write into the nekRS scratch space if that face is "owned" by the current
     177             :       // process
     178        3876 :       if (nekrs::commRank() != _nek_mesh->volumeCoupling().processor_id(e))
     179        1938 :         continue;
     180             : 
     181        1938 :       _nek_problem.mapVolumeDataToNekVolume(e, _variable_number[_variable], d, a, &_v_elem);
     182        1938 :       _nek_problem.writeVolumeSolution(e, _field, _v_elem);
     183             :     }
     184             :   }
     185         256 : }
     186             : 
     187             : #endif

Generated by: LCOV version 1.14