LCOV - code coverage report
Current view: top level - src/transfers - FieldTransferBase.C (source / functions) Hit Total Coverage
Test: neams-th-coe/cardinal: 920dc5 Lines: 73 76 96.1 %
Date: 2025-08-10 20:41:39 Functions: 6 7 85.7 %
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        2411 : FieldTransferBase::validParams()
      29             : {
      30        2411 :   auto params = NekTransferBase::validParams();
      31        4822 :   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        2411 :   params.addClassDescription("Base class for transferring field data between NekRS and MOOSE.");
      36        2411 :   params.registerBase("FieldTransfer");
      37        2411 :   params.registerSystemAttributeName("FieldTransfer");
      38        2411 :   return params;
      39           0 : }
      40             : 
      41        1213 : FieldTransferBase::FieldTransferBase(const InputParameters & parameters)
      42        1213 :   : NekTransferBase(parameters), _variable(name())
      43             : {
      44        1213 :   if (_direction == "to_nek")
      45             :   {
      46         832 :     checkRequiredParam(parameters, "usrwrk_slot", "writing data 'to_nek'");
      47        1248 :     _usrwrk_slot = getParam<std::vector<unsigned int>>("usrwrk_slot");
      48             : 
      49             :     // there should be no duplicates within a single transfer
      50         416 :     std::set<unsigned int> slots(_usrwrk_slot.begin(), _usrwrk_slot.end());
      51         416 :     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         922 :     for (const auto & u : _usrwrk_slot)
      67         508 :       checkAllocatedUsrwrkSlot(u);
      68             :   }
      69             : 
      70        1211 :   _n_per_surf = _nek_mesh->exactMirror() ? std::pow(_nek_mesh->nekNumQuadraturePoints1D(), 2.0)
      71        1111 :                                          : _nek_mesh->numVerticesPerSurface();
      72        1211 :   _n_per_vol = _nek_mesh->exactMirror() ? std::pow(_nek_mesh->nekNumQuadraturePoints1D(), 3.0)
      73        1111 :                                         : _nek_mesh->numVerticesPerVolume();
      74        1211 :   _v_face = (double *)calloc(_n_per_surf, sizeof(double));
      75        1211 :   _v_elem = (double *)calloc(_n_per_vol, sizeof(double));
      76        1211 :   _external_data = (double *)calloc(_nek_problem.nPoints(), sizeof(double));
      77        1211 : }
      78             : 
      79        1176 : FieldTransferBase::~FieldTransferBase()
      80             : {
      81        1176 :   freePointer(_v_face);
      82        1176 :   freePointer(_v_elem);
      83        1176 :   freePointer(_external_data);
      84        1176 : }
      85             : 
      86             : void
      87        1297 : FieldTransferBase::addExternalVariable(const std::string name)
      88             : {
      89        1297 :   InputParameters var_params = _factory.getValidParams("MooseVariable");
      90        2594 :   var_params.set<MooseEnum>("family") = "LAGRANGE";
      91             : 
      92        1297 :   switch (_nek_mesh->order())
      93             :   {
      94             :     case order::first:
      95        1764 :       var_params.set<MooseEnum>("order") = "FIRST";
      96         882 :       break;
      97             :     case order::second:
      98         830 :       var_params.set<MooseEnum>("order") = "SECOND";
      99         415 :       break;
     100           0 :     default:
     101           0 :       mooseError("Unhandled 'NekOrderEnum' in 'FieldTransferBase'!");
     102             :   }
     103             : 
     104        1297 :   _nek_problem.checkDuplicateVariableName(name);
     105        1294 :   _nek_problem.addAuxVariable("MooseVariable", name, var_params);
     106        1294 :   _variable_number.insert(std::pair<std::string, unsigned int>(
     107        1294 :       name, _nek_problem.getAuxiliarySystem().getFieldVariable<Real>(0, name).number()));
     108        1294 : }
     109             : 
     110             : void
     111         500 : FieldTransferBase::addExternalVariable(const unsigned int slot, const std::string name)
     112             : {
     113         999 :   addExternalVariable(name);
     114             : 
     115             :   // check that no other field transfer is trying to write into the same slot;
     116             :   // we don't need to check the scalar transfers, because they will always execute
     117             :   // after the field transfers
     118             :   bool duplicate_field = _field_usrwrk_map.find(slot) != _field_usrwrk_map.end();
     119         499 :   if (duplicate_field)
     120           1 :     paramError("usrwrk_slot",
     121           1 :                "A duplicate slot, " + Moose::stringify(slot) +
     122             :                    ", is being used by another FieldTransfer. Duplicate slots are not allowed for "
     123             :                    "field transfers because these transfers will overwrite all data in that slot. "
     124             :                    "If you need more slots, increase 'n_usrwrk_slots' in the [Problem] block.");
     125             : 
     126         498 :   _field_usrwrk_map.insert({slot, name});
     127         498 : }
     128             : 
     129             : void
     130       88692 : FieldTransferBase::fillAuxVariable(const unsigned int var_number, const double * value)
     131             : {
     132       88692 :   auto & solution = _nek_problem.getAuxiliarySystem().solution();
     133       88692 :   auto sys_number = _nek_problem.getAuxiliarySystem().number();
     134       88692 :   auto pid = _communicator.rank();
     135             : 
     136    16705512 :   for (unsigned int e = 0; e < _nek_mesh->numElems(); e++)
     137             :   {
     138    40342408 :     for (int build = 0; build < _nek_mesh->nMoosePerNek(); ++build)
     139             :     {
     140    23725588 :       auto elem_ptr = _nek_mesh->queryElemPtr(e * _nek_mesh->nMoosePerNek() + build);
     141             : 
     142             :       // Only work on elements we can find on our local chunk of a
     143             :       // distributed mesh
     144    23725588 :       if (!elem_ptr)
     145             :       {
     146             :         libmesh_assert(!_nek_mesh->getMesh().is_serial());
     147     2955858 :         continue;
     148             :       }
     149             : 
     150   303067318 :       for (unsigned int n = 0; n < _nek_mesh->numVerticesPerElem(); n++)
     151             :       {
     152             :         auto node_ptr = elem_ptr->node_ptr(n);
     153             : 
     154             :         // For each face vertex, we can only write into the MOOSE auxiliary fields if that
     155             :         // vertex is "owned" by the present MOOSE process.
     156   282297588 :         if (node_ptr->processor_id() == pid)
     157             :         {
     158    66631160 :           int node_index = _nek_mesh->nodeIndex(n);
     159             :           auto node_offset =
     160    66631160 :               (e * _nek_mesh->nMoosePerNek() + build) * _nek_mesh->numVerticesPerElem() +
     161    66631160 :               node_index;
     162             : 
     163             :           // get the DOF for the auxiliary variable, then use it to set the value in the auxiliary
     164             :           // system
     165    66631160 :           auto dof_idx = node_ptr->dof_number(sys_number, var_number, 0);
     166    66631160 :           solution.set(dof_idx, value[node_offset]);
     167             :         }
     168             :       }
     169             :     }
     170             :   }
     171             : 
     172       88692 :   solution.close();
     173       88692 : }
     174             : #endif

Generated by: LCOV version 1.14