LCOV - code coverage report
Current view: top level - src/transfers - MultiAppPostprocessorInterpolationTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 419b9d Lines: 99 103 96.1 %
Date: 2025-08-08 20:01:16 Functions: 3 3 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : //* This file is part of the MOOSE framework
       2             : //* https://mooseframework.inl.gov
       3             : //*
       4             : //* All rights reserved, see COPYRIGHT for full restrictions
       5             : //* https://github.com/idaholab/moose/blob/master/COPYRIGHT
       6             : //*
       7             : //* Licensed under LGPL 2.1, please see LICENSE for details
       8             : //* https://www.gnu.org/licenses/lgpl-2.1.html
       9             : 
      10             : #include "MultiAppPostprocessorInterpolationTransfer.h"
      11             : 
      12             : // MOOSE includes
      13             : #include "FEProblem.h"
      14             : #include "MooseMesh.h"
      15             : #include "MooseTypes.h"
      16             : #include "MultiApp.h"
      17             : #include "MooseAppCoordTransform.h"
      18             : 
      19             : #include "libmesh/meshfree_interpolation.h"
      20             : #include "libmesh/numeric_vector.h"
      21             : #include "libmesh/system.h"
      22             : #include "libmesh/radial_basis_interpolation.h"
      23             : 
      24             : using namespace libMesh;
      25             : 
      26             : registerMooseObject("MooseApp", MultiAppPostprocessorInterpolationTransfer);
      27             : 
      28             : InputParameters
      29       14541 : MultiAppPostprocessorInterpolationTransfer::validParams()
      30             : {
      31       14541 :   InputParameters params = MultiAppTransfer::validParams();
      32       14541 :   params.addClassDescription("Transfer postprocessor data from sub-application into field data on "
      33             :                              "the parent application.");
      34       14541 :   params.addRequiredParam<AuxVariableName>(
      35             :       "variable", "The auxiliary variable to store the transferred values in.");
      36       14541 :   params.addRequiredParam<PostprocessorName>("postprocessor", "The Postprocessor to interpolate.");
      37       43623 :   params.addParam<unsigned int>(
      38       29082 :       "num_points", 3, "The number of nearest points to use for interpolation.");
      39       43623 :   params.addParam<Real>(
      40       29082 :       "power", 2, "The polynomial power to use for calculation of the decay in the interpolation.");
      41             : 
      42       14541 :   MooseEnum interp_type("inverse_distance radial_basis", "inverse_distance");
      43             : 
      44       14541 :   params.addParam<MooseEnum>("interp_type", interp_type, "The algorithm to use for interpolation.");
      45             : 
      46       43623 :   params.addParam<Real>("radius",
      47       29082 :                         -1,
      48             :                         "Radius to use for radial_basis interpolation.  If negative "
      49             :                         "then the radius is taken as the max distance between "
      50             :                         "points.");
      51       29082 :   return params;
      52       14541 : }
      53             : 
      54         144 : MultiAppPostprocessorInterpolationTransfer::MultiAppPostprocessorInterpolationTransfer(
      55         144 :     const InputParameters & parameters)
      56             :   : MultiAppTransfer(parameters),
      57         144 :     _postprocessor(getParam<PostprocessorName>("postprocessor")),
      58         144 :     _to_var_name(getParam<AuxVariableName>("variable")),
      59         144 :     _num_points(getParam<unsigned int>("num_points")),
      60         144 :     _power(getParam<Real>("power")),
      61         144 :     _interp_type(getParam<MooseEnum>("interp_type")),
      62         144 :     _radius(getParam<Real>("radius")),
      63         144 :     _nodal(false)
      64             : {
      65         144 :   if (isParamValid("to_multi_app"))
      66           4 :     paramError("to_multi_app", "Unused parameter; only from-MultiApp transfers are implemented");
      67             : 
      68             :   auto & to_fe_type =
      69         140 :       getFromMultiApp()->problemBase().getStandardVariable(0, _to_var_name).feType();
      70         348 :   if ((to_fe_type.order != CONSTANT || to_fe_type.family != MONOMIAL) &&
      71         212 :       (to_fe_type.order != FIRST || to_fe_type.family != LAGRANGE))
      72           4 :     paramError("variable", "Must be either CONSTANT MONOMIAL or FIRST LAGRANGE");
      73             : 
      74         132 :   _nodal = to_fe_type.family == LAGRANGE;
      75         132 : }
      76             : 
      77             : void
      78         578 : MultiAppPostprocessorInterpolationTransfer::execute()
      79             : {
      80         578 :   TIME_SECTION("MultiAppPostprocessorInterpolationTransfer::execute()",
      81             :                5,
      82             :                "Transferring/interpolating postprocessors");
      83             : 
      84         578 :   switch (_current_direction)
      85             :   {
      86           0 :     case TO_MULTIAPP:
      87             :     {
      88           0 :       mooseError("Interpolation from a variable to a MultiApp postprocessors has not been "
      89             :                  "implemented. Use MultiAppVariableValueSamplePostprocessorTransfer!");
      90             :       break;
      91             :     }
      92         578 :     case FROM_MULTIAPP:
      93             :     {
      94         578 :       errorIfObjectExecutesOnTransferInSourceApp(_postprocessor);
      95         578 :       std::unique_ptr<InverseDistanceInterpolation<LIBMESH_DIM>> idi;
      96             : 
      97         578 :       switch (_interp_type)
      98             :       {
      99         565 :         case 0:
     100         565 :           idi = std::make_unique<InverseDistanceInterpolation<LIBMESH_DIM>>(
     101         565 :               _communicator, _num_points, _power);
     102         565 :           break;
     103          13 :         case 1:
     104          13 :           idi = std::make_unique<RadialBasisInterpolation<LIBMESH_DIM>>(_communicator, _radius);
     105          13 :           break;
     106           0 :         default:
     107           0 :           mooseError("Unknown interpolation type!");
     108             :       }
     109             : 
     110         578 :       std::vector<Point> & src_pts(idi->get_source_points());
     111         578 :       std::vector<Number> & src_vals(idi->get_source_vals());
     112             : 
     113        1156 :       std::vector<std::string> field_vars;
     114         578 :       field_vars.push_back(_to_var_name);
     115         578 :       idi->set_field_variables(field_vars);
     116             : 
     117             :       {
     118             :         mooseAssert(_to_transforms.size() == 1, "There should only be one transform here");
     119         578 :         const auto & to_coord_transform = *_to_transforms[0];
     120        3226 :         for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
     121             :         {
     122        2648 :           if (getFromMultiApp()->hasLocalApp(i) && getFromMultiApp()->isRootProcessor())
     123             :           {
     124             :             // Evaluation of the _from_transform at the origin yields the transformed position of
     125             :             // the from multi-app
     126        2000 :             if (!getFromMultiApp()->runningInPosition())
     127        1568 :               src_pts.push_back(to_coord_transform.mapBack((*_from_transforms[i])(Point(0))));
     128             :             else
     129             :               // if running in position, the subapp mesh has been transformed so the translation
     130             :               // is no longer applied by the transform
     131         432 :               src_pts.push_back(to_coord_transform.mapBack(
     132         864 :                   (*_from_transforms[i])(getFromMultiApp()->position(i))));
     133        2000 :             src_vals.push_back(getFromMultiApp()->appPostprocessorValue(i, _postprocessor));
     134             :           }
     135             :         }
     136             :       }
     137             : 
     138             :       // We have only set local values - prepare for use by gathering remote data
     139         578 :       idi->prepare_for_use();
     140             : 
     141             :       // Loop over the parent app nodes and set the value of the variable
     142             :       {
     143         578 :         System * to_sys = find_sys(getFromMultiApp()->problemBase().es(), _to_var_name);
     144             : 
     145         578 :         unsigned int sys_num = to_sys->number();
     146         578 :         unsigned int var_num = to_sys->variable_number(_to_var_name);
     147             : 
     148         578 :         NumericVector<Real> & solution = *to_sys->solution;
     149             : 
     150         578 :         MooseMesh & mesh = getFromMultiApp()->problemBase().mesh();
     151             : 
     152         578 :         std::vector<std::string> vars;
     153             : 
     154         578 :         vars.push_back(_to_var_name);
     155             : 
     156         578 :         if (_nodal)
     157             :         {
     158             :           // handle linear lagrange shape functions
     159      100473 :           for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
     160             :           {
     161       49960 :             if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
     162             :             {
     163       49960 :               std::vector<Point> pts;
     164       49960 :               std::vector<Number> vals;
     165             : 
     166       49960 :               pts.push_back(*node);
     167       49960 :               vals.resize(1);
     168             : 
     169       49960 :               idi->interpolate_field_data(vars, pts, vals);
     170             : 
     171       49960 :               Real value = vals.front();
     172             : 
     173             :               // The zero only works for LAGRANGE!
     174       49960 :               dof_id_type dof = node->dof_number(sys_num, var_num, 0);
     175             : 
     176       49960 :               solution.set(dof, value);
     177       49960 :             }
     178         553 :           }
     179             :         }
     180             :         else
     181             :         {
     182             :           // handle constant monomial shape functions
     183          25 :           for (const auto & elem :
     184        2158 :                as_range(mesh.getMesh().local_elements_begin(), mesh.getMesh().local_elements_end()))
     185             :           {
     186             :             // Exclude the elements without dofs
     187        1054 :             if (elem->n_dofs(sys_num, var_num) > 0)
     188             :             {
     189        1054 :               std::vector<Point> pts;
     190        1054 :               std::vector<Number> vals;
     191             : 
     192        1054 :               pts.push_back(elem->vertex_average());
     193        1054 :               vals.resize(1);
     194             : 
     195        1054 :               idi->interpolate_field_data(vars, pts, vals);
     196             : 
     197        1054 :               Real value = vals.front();
     198             : 
     199        1054 :               dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
     200        1054 :               solution.set(dof, value);
     201        1054 :             }
     202          25 :           }
     203             :         }
     204             : 
     205         578 :         solution.close();
     206         578 :       }
     207             : 
     208         578 :       getFromMultiApp()->problemBase().es().update();
     209             : 
     210         578 :       break;
     211         578 :     }
     212             :   }
     213         578 : }

Generated by: LCOV version 1.14