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

Generated by: LCOV version 1.14