https://mooseframework.inl.gov
MultiApplibMeshToMFEMShapeEvaluationTransfer.C
Go to the documentation of this file.
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 #ifdef MOOSE_MFEM_ENABLED
11 
13 #include "MFEMVectorUtils.h"
14 #include "libmesh/mesh_function.h"
15 #include "libmesh/parallel_algebra.h" // for communicator send and receive stuff
16 
18 
21 {
23  params.addClassDescription("Transfers variable values from a libMesh based application to an "
24  "MFEM application, using shape function evaluations.");
25  return params;
26 }
27 
29  InputParameters const & params)
30  : MFEMMultiAppTransfer(params)
31 {
32  checkValidTransferProblemTypes<Moose::FEBackend::MFEM, Moose::FEBackend::LibMesh>();
33 }
34 
37 {
39 }
40 
41 void
43 {
44  for (const auto var_index : make_range(numToVar()))
45  {
46  // Declare map of processor ID to corresponding vector of libMesh points
47  // on that processor to interpolate source libMesh variable at
48  std::map<processor_id_type, std::vector<Point>> outgoing_points;
49  mfem::Vector interp_vals;
50  if (is_target_local)
51  {
52  // Generate list of points where the grid function will be evaluated
53  mfem::ParGridFunction & to_gf =
55  mfem::ParFiniteElementSpace & to_pfespace = *to_gf.ParFESpace();
56  if (to_gf.VectorDim() > 1)
57  mooseError("MultiApplibMeshToMFEMShapeEvaluationTransfer does not support transfers of "
58  "vector variables from libMesh to MFEM-based subapps");
59  mfem::Vector vxyz;
60  mfem::Ordering::Type point_ordering;
61  _mfem_projector.extractNodePositions(to_pfespace, vxyz, point_ordering);
62 
63  // Populate outgoing point locations map between processor and points vector for libMesh to
64  // use in interpolation
65  const int dim = to_pfespace.GetParMesh()->Dimension();
66  const int nnodes = vxyz.Size() / dim;
67  for (const auto i : make_range(nnodes))
68  {
69  libMesh::Point point_in_target_frame;
70  for (const auto d : make_range(dim))
71  point_in_target_frame(d) = vxyz[i + d * nnodes];
72 
73  const auto point_in_source_frame = mapPointToActiveSourceFrame(point_in_target_frame);
74  for (const auto i_proc : make_range(n_processors()))
75  outgoing_points[i_proc].push_back(point_in_source_frame);
76  }
77  interp_vals.SetSize(nnodes);
78  }
79 
80  // Perform interpolation of libMesh variable at specified points
81  interpolatelibMeshVariable(outgoing_points, var_index, interp_vals);
82 
83  // Project DoFs to MFEM GridFunction
84  if (is_target_local)
85  {
86  mfem::ParGridFunction & to_gf =
88  mfem::Ordering::Type libmesh_interp_ordering(mfem::Ordering::Type::byNODES);
89  _mfem_projector.projectNodalValues(interp_vals, libmesh_interp_ordering, to_gf);
90  }
91  }
92 }
93 
94 void
96  std::map<processor_id_type, std::vector<Point>> & outgoing_points,
97  const unsigned int var_index,
98  mfem::Vector & interp_vals)
99 {
100  FEProblemBase & from_problem = getActiveFromProblem();
101  MooseVariableFieldBase & from_var = from_problem.getVariable(0,
102  getFromVarName(var_index),
105  System & from_sys = from_var.sys().system();
106  unsigned int from_var_num = from_sys.variable_number(getFromVarName(var_index));
107  // Construct a local mesh function for each origin problem
108  libMesh::MeshFunction local_meshfuns(
110  *from_sys.current_local_solution,
111  from_sys.get_dof_map(),
112  from_var_num);
113  local_meshfuns.init();
114  local_meshfuns.enable_out_of_mesh_mode(getMFEMOutOfMeshValue());
115 
116  // Evaluate interpolated values at incoming points.
117  auto gather_functor =
118  [&](processor_id_type /*pid*/,
119  const std::vector<Point> & incoming_points,
120  std::vector<std::pair<mfem::real_t, unsigned>> & vals_for_incoming_points)
121  {
122  vals_for_incoming_points.assign(incoming_points.size(), {0., 0});
123  // Compute interpolation values of the libMesh variable at all requested points
124  for (const auto i_pt : index_range(incoming_points))
125  {
126  const auto map = local_meshfuns.discontinuous_value(incoming_points[i_pt]);
127  for (const auto & [elem, val] : map)
128  if (elem && elem->processor_id() == this->processor_id())
129  {
130  vals_for_incoming_points[i_pt].first += val;
131  vals_for_incoming_points[i_pt].second++;
132  }
133  }
134  };
135 
136  // Counters for the no. of elements sharing/neighboring a given point to perform arithmetic avg
137  std::vector<unsigned> neighbor_elems(interp_vals.Size(), 0);
138  // Copy data out to interp_vals
139  auto action_functor =
140  [&](processor_id_type /*pid*/,
141  const std::vector<Point> & /*my_outgoing_points*/,
142  const std::vector<std::pair<mfem::real_t, unsigned>> & vals_for_outgoing_points)
143  {
144  for (const auto i : make_range(interp_vals.Size()))
145  {
146  const auto val = vals_for_outgoing_points[i].first;
147  const auto elems = vals_for_outgoing_points[i].second;
148  if (!elems)
149  continue;
150  else if (interp_vals(i) == getMFEMOutOfMeshValue())
151  interp_vals(i) = val / (neighbor_elems[i] += elems);
152  else
153  interp_vals(i) = (interp_vals(i) * neighbor_elems[i] + val) / (neighbor_elems[i] += elems);
154  }
155  };
156 
157  // Set interpolated field values at points on local processor
158  interp_vals = getMFEMOutOfMeshValue(); // default to the out-of-mesh value
159  // We assume incoming_vals is ordered in the same way as outgoing_points
160  std::pair<mfem::real_t, unsigned> * dummy = nullptr;
161  libMesh::Parallel::pull_parallel_vector_data(
162  comm(), outgoing_points, gather_functor, action_functor, dummy);
163 }
164 
165 #endif
std::shared_ptr< mfem::ParGridFunction > getGridFunction(const std::string &name)
Definition: MFEMProblem.h:323
Virtual base class for MultiApp transfers to and/or from MFEMProblems.
void projectNodalValues(const mfem::Vector &nodal_vals, const mfem::Ordering::Type &nodal_val_ordering, mfem::ParGridFunction &gridfunction)
Project a vector of values provided at projection points (nodes) to set GridFunction DoFs...
libMesh::EquationSystems & getlibMeshEquationSystem(FEProblemBase &problem, bool use_displaced) const
Get libMesh EquationSystem, which may or may not be displaced.
registerMooseObject("MooseApp", MultiApplibMeshToMFEMShapeEvaluationTransfer)
virtual libMesh::System & system()=0
Get the reference to the libMesh system.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
const Parallel::Communicator & comm() const
This class provides an interface for common operations on field variables of both FE and FV types wit...
virtual FEProblemBase & getActiveFromProblem()
Getter for current problem containing source variables.
Specialization of SubProblem for solving nonlinear equations plus auxiliary equations.
virtual const MooseVariableFieldBase & getVariable(const THREAD_ID tid, const std::string &var_name, Moose::VarKindType expected_var_type=Moose::VarKindType::VAR_ANY, Moose::VarFieldType expected_var_field_type=Moose::VarFieldType::VAR_FIELD_ANY) const override
Returns the variable reference for requested variable which must be of the expected_var_type (Nonline...
unsigned int variable_number(std::string_view var) const
uint8_t processor_id_type
virtual FEProblemBase & getActiveToProblem()
Getter for current problem containing destination variables.
processor_id_type n_processors() const
unsigned int numToVar() const
Return for the number of destination variables.
virtual void init() override
MFEMNodalProjector _mfem_projector
Object to extract node positions and perform projections on MFEM GridFunctions.
void extractNodePositions(const mfem::ParFiniteElementSpace &fespace, mfem::Vector &node_positions, mfem::Ordering::Type &node_ordering)
Extract node positions from MFEM FESpace at which projection will take place.
mfem::real_t getMFEMOutOfMeshValue() const
Getter for default value for transfers evaluated at points outside source mesh.
const VariableName & getFromVarName(int i) const
Getter for source variable name.
static InputParameters validParams()
libMesh::Point mapPointToActiveSourceFrame(const Point &point_in_target_frame) const
Map a point in the active destination app frame to the active source app frame.
virtual MFEMProblem & getActiveToProblem() override
Set current MFEM problem to fetch destination variables from.
void interpolatelibMeshVariable(std::map< processor_id_type, std::vector< Point >> &outgoing_points, const unsigned int var_index, mfem::Vector &interp_vals)
Interpolate libMesh variable corresponding to var_index at target points for DoF evaluation.
const VariableName & getToVarName(int i) const
Getter for destination variable name.
IntRange< T > make_range(T beg, T end)
bool _displaced_source_mesh
True if displaced mesh is used for the source mesh, otherwise false.
void mooseError(Args &&... args) const
Emits an error prefixed with object name and type and optionally a file path to the top-level block p...
Definition: MooseBase.h:281
virtual void transferVariables(bool is_target_local) override
Transfer all variables from active source problem to active destination problem.
void addClassDescription(const std::string &doc_string)
This method adds a description of the class that will be displayed in the input file syntax dump...
processor_id_type processor_id() const
SystemBase & sys()
Get the system this variable is part of.
auto index_range(const T &sizable)
MultiApp transfer from libMesh to MFEM variables, performed via evaluation of shape functions...