LCOV - code coverage report
Current view: top level - src/transfers - FieldTransferBase.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: be601f Lines: 65 68 95.6 %
Date: 2025-07-15 20:50:38 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 "NekRSProblem.h"
      22             : #include "FieldTransferBase.h"
      23             : #include "UserErrorChecking.h"
      24             : 
      25             : std::map<unsigned int, std::string> FieldTransferBase::_field_usrwrk_map;
      26             : 
      27             : InputParameters
      28        2320 : FieldTransferBase::validParams()
      29             : {
      30        2320 :   auto params = NekTransferBase::validParams();
      31        4640 :   params.addParam<std::vector<unsigned int>>(
      32             :       "usrwrk_slot",
      33             :       "When 'direction = to_nek', the slot(s) in the usrwrk array to write the incoming data; "
      34             :       "provide one entry for each quantity being passed");
      35        2320 :   params.addClassDescription("Base class for transferring field data between NekRS and MOOSE.");
      36        2320 :   params.registerBase("FieldTransfer");
      37        2320 :   params.registerSystemAttributeName("FieldTransfer");
      38        2320 :   return params;
      39           0 : }
      40             : 
      41        1167 : FieldTransferBase::FieldTransferBase(const InputParameters & parameters)
      42        1167 :   : NekTransferBase(parameters), _variable(name())
      43             : {
      44        1167 :   if (_direction == "to_nek")
      45             :   {
      46         790 :     checkRequiredParam(parameters, "usrwrk_slot", "writing data 'to_nek'");
      47        1185 :     _usrwrk_slot = getParam<std::vector<unsigned int>>("usrwrk_slot");
      48             : 
      49             :     // there should be no duplicates within a single transfer
      50         395 :     std::set<unsigned int> slots(_usrwrk_slot.begin(), _usrwrk_slot.end());
      51         395 :     if (slots.size() != _usrwrk_slot.size())
      52             :     {
      53             :       std::string slots;
      54           3 :       for (const auto & u : _usrwrk_slot)
      55           4 :         slots += Moose::stringify(u) + " ";
      56           1 :       paramError(
      57             :           "usrwrk_slot",
      58           1 :           "There are duplicate entries in 'usrwrk_slot': " + slots +
      59             :               "; duplicate entries are not allowed because the field transfer will overwrite "
      60           1 :               "itself. Cardinal has allocated " +
      61           1 :               Moose::stringify(_nek_problem.nUsrWrkSlots()) +
      62             :               " usrwrk slots; if you need more, set 'n_usrwrk_slots' in the [Problem] block.");
      63             :     }
      64             : 
      65             :     // each slot should not be greater than the amount allocated
      66         879 :     for (const auto & u : _usrwrk_slot)
      67         486 :       checkAllocatedUsrwrkSlot(u);
      68             :   }
      69             : 
      70        1165 :   _n_per_surf = _nek_mesh->exactMirror() ? std::pow(_nek_mesh->nekNumQuadraturePoints1D(), 2.0)
      71        1065 :                                          : _nek_mesh->numVerticesPerSurface();
      72        1165 :   _n_per_vol = _nek_mesh->exactMirror() ? std::pow(_nek_mesh->nekNumQuadraturePoints1D(), 3.0)
      73        1065 :                                         : _nek_mesh->numVerticesPerVolume();
      74        1165 : }
      75             : 
      76             : void
      77        1254 : FieldTransferBase::addExternalVariable(const std::string name)
      78             : {
      79        1254 :   InputParameters var_params = _factory.getValidParams("MooseVariable");
      80        2508 :   var_params.set<MooseEnum>("family") = "LAGRANGE";
      81             : 
      82        1254 :   switch (_nek_mesh->order())
      83             :   {
      84             :     case order::first:
      85        1678 :       var_params.set<MooseEnum>("order") = "FIRST";
      86         839 :       break;
      87             :     case order::second:
      88         830 :       var_params.set<MooseEnum>("order") = "SECOND";
      89         415 :       break;
      90           0 :     default:
      91           0 :       mooseError("Unhandled 'NekOrderEnum' in 'FieldTransferBase'!");
      92             :   }
      93             : 
      94        1254 :   _nek_problem.checkDuplicateVariableName(name);
      95        1251 :   _nek_problem.addAuxVariable("MooseVariable", name, var_params);
      96        1251 :   _variable_number.insert(std::pair<std::string, unsigned int>(
      97        1251 :       name, _nek_problem.getAuxiliarySystem().getFieldVariable<Real>(0, name).number()));
      98        1251 : }
      99             : 
     100             : void
     101         482 : FieldTransferBase::addExternalVariable(const unsigned int slot, const std::string name)
     102             : {
     103         963 :   addExternalVariable(name);
     104             : 
     105             :   // check that no other field transfer is trying to write into the same slot;
     106             :   // we don't need to check the scalar transfers, because they will always execute
     107             :   // after the field transfers
     108             :   bool duplicate_field = _field_usrwrk_map.find(slot) != _field_usrwrk_map.end();
     109         481 :   if (duplicate_field)
     110           1 :     paramError("usrwrk_slot",
     111           1 :                "A duplicate slot, " + Moose::stringify(slot) +
     112             :                    ", is being used by another FieldTransfer. Duplicate slots are not allowed for "
     113             :                    "field transfers because these transfers will overwrite all data in that slot. "
     114             :                    "If you need more slots, increase 'n_usrwrk_slots' in the [Problem] block.");
     115             : 
     116         480 :   _field_usrwrk_map.insert({slot, name});
     117         480 : }
     118             : 
     119             : void
     120       88432 : FieldTransferBase::fillAuxVariable(const unsigned int var_number, const double * value)
     121             : {
     122       88432 :   auto & solution = _nek_problem.getAuxiliarySystem().solution();
     123       88432 :   auto sys_number = _nek_problem.getAuxiliarySystem().number();
     124       88432 :   auto pid = _communicator.rank();
     125             : 
     126    16695292 :   for (unsigned int e = 0; e < _nek_mesh->numElems(); e++)
     127             :   {
     128    40322488 :     for (int build = 0; build < _nek_mesh->nMoosePerNek(); ++build)
     129             :     {
     130    23715628 :       auto elem_ptr = _nek_mesh->queryElemPtr(e * _nek_mesh->nMoosePerNek() + build);
     131             : 
     132             :       // Only work on elements we can find on our local chunk of a
     133             :       // distributed mesh
     134    23715628 :       if (!elem_ptr)
     135             :       {
     136             :         libmesh_assert(!_nek_mesh->getMesh().is_serial());
     137     2951895 :         continue;
     138             :       }
     139             : 
     140   303029581 :       for (unsigned int n = 0; n < _nek_mesh->numVerticesPerElem(); n++)
     141             :       {
     142             :         auto node_ptr = elem_ptr->node_ptr(n);
     143             : 
     144             :         // For each face vertex, we can only write into the MOOSE auxiliary fields if that
     145             :         // vertex is "owned" by the present MOOSE process.
     146   282265848 :         if (node_ptr->processor_id() == pid)
     147             :         {
     148    66611488 :           int node_index = _nek_mesh->nodeIndex(n);
     149             :           auto node_offset =
     150    66611488 :               (e * _nek_mesh->nMoosePerNek() + build) * _nek_mesh->numVerticesPerElem() +
     151    66611488 :               node_index;
     152             : 
     153             :           // get the DOF for the auxiliary variable, then use it to set the value in the auxiliary
     154             :           // system
     155    66611488 :           auto dof_idx = node_ptr->dof_number(sys_number, var_number, 0);
     156    66611488 :           solution.set(dof_idx, value[node_offset]);
     157             :         }
     158             :       }
     159             :     }
     160             :   }
     161             : 
     162       88432 :   solution.close();
     163       88432 : }
     164             : #endif

Generated by: LCOV version 1.14