LCOV - code coverage report
Current view: top level - src/transfers - MultiAppPostprocessorInterpolationTransfer.C (source / functions) Hit Total Coverage
Test: idaholab/moose framework: 2bf808 Lines: 99 103 96.1 %
Date: 2025-07-17 01:28:37 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       14521 : MultiAppPostprocessorInterpolationTransfer::validParams()
      30             : {
      31       14521 :   InputParameters params = MultiAppTransfer::validParams();
      32       14521 :   params.addClassDescription("Transfer postprocessor data from sub-application into field data on "
      33             :                              "the parent application.");
      34       14521 :   params.addRequiredParam<AuxVariableName>(
      35             :       "variable", "The auxiliary variable to store the transferred values in.");
      36       14521 :   params.addRequiredParam<PostprocessorName>("postprocessor", "The Postprocessor to interpolate.");
      37       43563 :   params.addParam<unsigned int>(
      38       29042 :       "num_points", 3, "The number of nearest points to use for interpolation.");
      39       43563 :   params.addParam<Real>(
      40       29042 :       "power", 2, "The polynomial power to use for calculation of the decay in the interpolation.");
      41             : 
      42       14521 :   MooseEnum interp_type("inverse_distance radial_basis", "inverse_distance");
      43             : 
      44       14521 :   params.addParam<MooseEnum>("interp_type", interp_type, "The algorithm to use for interpolation.");
      45             : 
      46       43563 :   params.addParam<Real>("radius",
      47       29042 :                         -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       29042 :   return params;
      52       14521 : }
      53             : 
      54         134 : MultiAppPostprocessorInterpolationTransfer::MultiAppPostprocessorInterpolationTransfer(
      55         134 :     const InputParameters & parameters)
      56             :   : MultiAppTransfer(parameters),
      57         134 :     _postprocessor(getParam<PostprocessorName>("postprocessor")),
      58         134 :     _to_var_name(getParam<AuxVariableName>("variable")),
      59         134 :     _num_points(getParam<unsigned int>("num_points")),
      60         134 :     _power(getParam<Real>("power")),
      61         134 :     _interp_type(getParam<MooseEnum>("interp_type")),
      62         134 :     _radius(getParam<Real>("radius")),
      63         134 :     _nodal(false)
      64             : {
      65         134 :   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         130 :       getFromMultiApp()->problemBase().getStandardVariable(0, _to_var_name).feType();
      70         322 :   if ((to_fe_type.order != CONSTANT || to_fe_type.family != MONOMIAL) &&
      71         196 :       (to_fe_type.order != FIRST || to_fe_type.family != LAGRANGE))
      72           4 :     paramError("variable", "Must be either CONSTANT MONOMIAL or FIRST LAGRANGE");
      73             : 
      74         122 :   _nodal = to_fe_type.family == LAGRANGE;
      75         122 : }
      76             : 
      77             : void
      78         522 : MultiAppPostprocessorInterpolationTransfer::execute()
      79             : {
      80         522 :   TIME_SECTION("MultiAppPostprocessorInterpolationTransfer::execute()",
      81             :                5,
      82             :                "Transferring/interpolating postprocessors");
      83             : 
      84         522 :   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         522 :     case FROM_MULTIAPP:
      93             :     {
      94         522 :       errorIfObjectExecutesOnTransferInSourceApp(_postprocessor);
      95         522 :       std::unique_ptr<InverseDistanceInterpolation<LIBMESH_DIM>> idi;
      96             : 
      97         522 :       switch (_interp_type)
      98             :       {
      99         511 :         case 0:
     100         511 :           idi = std::make_unique<InverseDistanceInterpolation<LIBMESH_DIM>>(
     101         511 :               _communicator, _num_points, _power);
     102         511 :           break;
     103          11 :         case 1:
     104          11 :           idi = std::make_unique<RadialBasisInterpolation<LIBMESH_DIM>>(_communicator, _radius);
     105          11 :           break;
     106           0 :         default:
     107           0 :           mooseError("Unknown interpolation type!");
     108             :       }
     109             : 
     110         522 :       std::vector<Point> & src_pts(idi->get_source_points());
     111         522 :       std::vector<Number> & src_vals(idi->get_source_vals());
     112             : 
     113        1044 :       std::vector<std::string> field_vars;
     114         522 :       field_vars.push_back(_to_var_name);
     115         522 :       idi->set_field_variables(field_vars);
     116             : 
     117             :       {
     118             :         mooseAssert(_to_transforms.size() == 1, "There should only be one transform here");
     119         522 :         const auto & to_coord_transform = *_to_transforms[0];
     120        2930 :         for (unsigned int i = 0; i < getFromMultiApp()->numGlobalApps(); i++)
     121             :         {
     122        2408 :           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        1760 :             if (!getFromMultiApp()->runningInPosition())
     127        1376 :               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         384 :               src_pts.push_back(to_coord_transform.mapBack(
     132         768 :                   (*_from_transforms[i])(getFromMultiApp()->position(i))));
     133        1760 :             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         522 :       idi->prepare_for_use();
     140             : 
     141             :       // Loop over the parent app nodes and set the value of the variable
     142             :       {
     143         522 :         System * to_sys = find_sys(getFromMultiApp()->problemBase().es(), _to_var_name);
     144             : 
     145         522 :         unsigned int sys_num = to_sys->number();
     146         522 :         unsigned int var_num = to_sys->variable_number(_to_var_name);
     147             : 
     148         522 :         NumericVector<Real> & solution = *to_sys->solution;
     149             : 
     150         522 :         MooseMesh & mesh = getFromMultiApp()->problemBase().mesh();
     151             : 
     152         522 :         std::vector<std::string> vars;
     153             : 
     154         522 :         vars.push_back(_to_var_name);
     155             : 
     156         522 :         if (_nodal)
     157             :         {
     158             :           // handle linear lagrange shape functions
     159       87812 :           for (const auto & node : as_range(mesh.localNodesBegin(), mesh.localNodesEnd()))
     160             :           {
     161       43656 :             if (node->n_dofs(sys_num, var_num) > 0) // If this variable has dofs at this node
     162             :             {
     163       43656 :               std::vector<Point> pts;
     164       43656 :               std::vector<Number> vals;
     165             : 
     166       43656 :               pts.push_back(*node);
     167       43656 :               vals.resize(1);
     168             : 
     169       43656 :               idi->interpolate_field_data(vars, pts, vals);
     170             : 
     171       43656 :               Real value = vals.front();
     172             : 
     173             :               // The zero only works for LAGRANGE!
     174       43656 :               dof_id_type dof = node->dof_number(sys_num, var_num, 0);
     175             : 
     176       43656 :               solution.set(dof, value);
     177       43656 :             }
     178         500 :           }
     179             :         }
     180             :         else
     181             :         {
     182             :           // handle constant monomial shape functions
     183          22 :           for (const auto & elem :
     184        1740 :                as_range(mesh.getMesh().local_elements_begin(), mesh.getMesh().local_elements_end()))
     185             :           {
     186             :             // Exclude the elements without dofs
     187         848 :             if (elem->n_dofs(sys_num, var_num) > 0)
     188             :             {
     189         848 :               std::vector<Point> pts;
     190         848 :               std::vector<Number> vals;
     191             : 
     192         848 :               pts.push_back(elem->vertex_average());
     193         848 :               vals.resize(1);
     194             : 
     195         848 :               idi->interpolate_field_data(vars, pts, vals);
     196             : 
     197         848 :               Real value = vals.front();
     198             : 
     199         848 :               dof_id_type dof = elem->dof_number(sys_num, var_num, 0);
     200         848 :               solution.set(dof, value);
     201         848 :             }
     202          22 :           }
     203             :         }
     204             : 
     205         522 :         solution.close();
     206         522 :       }
     207             : 
     208         522 :       getFromMultiApp()->problemBase().es().update();
     209             : 
     210         522 :       break;
     211         522 :     }
     212             :   }
     213         522 : }

Generated by: LCOV version 1.14