https://mooseframework.inl.gov
MultiAppMFEMTolibMeshShapeEvaluationTransfer.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 
17 
20 {
22  params.addClassDescription("Transfers variable values from an MFEM based application to a "
23  "libMesh application, using shape function evaluations.");
24  return params;
25 }
26 
28  InputParameters const & params)
29  : MFEMMultiAppTransfer(params), _mfem_interpolator(this->comm().get())
30 {
31  checkValidTransferProblemTypes<Moose::FEBackend::LibMesh, Moose::FEBackend::MFEM>();
32 }
33 
36 {
38 }
39 
41 void
43  libMesh::System & to_sys,
44  const MooseVariableFieldBase & to_var,
45  std::vector<Point> & outgoing_libmesh_points)
46 {
47  // libMesh mesh
48  const MeshBase & to_mesh = getActiveToProblem().mesh(_displaced_target_mesh).getMesh();
49  auto var_num = to_var.number();
50  auto sys_num = to_sys.number();
51  auto & fe_type = to_var.feType();
52  bool is_nodal = to_var.isNodal();
53 
54  // Populate set of points
55  if (fe_type.order > CONSTANT && !is_nodal)
56  mooseError("Transfers of non-nodal FEs from MFEM to libMesh with order higher than "
57  "CONSTANT are not supported.");
58  else if (is_nodal)
59  {
60  // Consider nodes the variable has dofs at.
61  for (const auto & node : to_mesh.local_node_ptr_range())
62  if (node->n_dofs(sys_num, var_num))
63  outgoing_libmesh_points.push_back(*node);
64  }
65  else // Elemental, constant monomial
66  {
67  // Consider elements the variable has dofs at.
68  for (const auto & elem : as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
69  if (elem->n_dofs(sys_num, var_num))
70  outgoing_libmesh_points.push_back(elem->vertex_average());
71  }
72 }
73 
75 void
77  libMesh::System & to_sys, const MooseVariableFieldBase & to_var, mfem::Vector & interp_vals)
78 {
79  // libMesh mesh
80  const MeshBase & to_mesh = getActiveToProblem().mesh(_displaced_target_mesh).getMesh();
81  auto var_num = to_var.number();
82  auto sys_num = to_sys.number();
83  auto & fe_type = to_var.feType();
84  bool is_nodal = to_var.isNodal();
85 
86  unsigned int mfem_point_index = 0;
87  if (fe_type.order > CONSTANT && !is_nodal)
88  mooseError("Transfers of non-nodal FEs from MFEM to libMesh with order higher than "
89  "CONSTANT are not supported.");
90  else if (is_nodal)
91  {
92  // Consider nodes the variable has dofs at.
93  for (const auto & node : to_mesh.local_node_ptr_range())
94  if (node->n_dofs(sys_num, var_num))
95  {
96  const auto dof_object_id = node->id();
97  const DofObject * dof_object = to_mesh.node_ptr(dof_object_id);
98  const auto dof = dof_object->dof_number(sys_num, var_num, 0);
99  const auto val = interp_vals[mfem_point_index];
100  to_sys.solution->set(dof, val);
101  mfem_point_index++;
102  }
103  }
104  else // Elemental, constant monomial
105  {
106  // Consider elements the variable has dofs at.
107  for (const auto & elem : as_range(to_mesh.local_elements_begin(), to_mesh.local_elements_end()))
108  if (elem->n_dofs(sys_num, var_num))
109  {
110  const auto dof_object_id = elem->id();
111  const DofObject * dof_object = to_mesh.elem_ptr(dof_object_id);
112  const auto dof = dof_object->dof_number(sys_num, var_num, 0);
113  const auto val = interp_vals[mfem_point_index];
114  to_sys.solution->set(dof, val);
115  mfem_point_index++;
116  }
117  }
118  to_sys.solution->close();
119  // Sync local solutions
120  to_sys.update();
121 }
122 
123 void
125 {
126  // Send from MFEM problem to libMesh problem
127  for (const auto var_index : make_range(numToVar()))
128  {
129  // Declare source variable alias and construct vectors to store interpolation points and vals
130  auto & from_var = *getActiveFromProblem().getGridFunction(getFromVarName(var_index));
131  if (from_var.VectorDim() > 1)
132  mooseError("MultiAppMFEMTolibMeshShapeEvaluationTransfer does not support transfers of "
133  "vector variables from MFEM to libMesh-based subapps");
134  from_var.ParFESpace()->GetParMesh()->EnsureNodes();
135  // Ordering of interpolated MFEM output, chosen to match libMesh ordering
136  const mfem::Ordering::Type ordering = mfem::Ordering::byVDIM;
137  mfem::Vector interp_vals;
138  mfem::Vector outgoing_mfem_points;
139 
140  // If target libMesh app is on the current rank, update the set of interpolation
141  // points with the libMesh variable's set
142  if (is_target_local)
143  {
144  // Declare aliases for convenience
145  FEProblemBase & to_problem = getActiveToProblem();
146  const MooseVariableFieldBase & to_var(
147  to_problem.getVariable(0,
148  getToVarName(var_index),
151  const auto & to_var_name = getToVarName(var_index);
152  auto & es = getlibMeshEquationSystem(to_problem, _displaced_target_mesh);
153  System & to_sys = *find_sys(es, to_var_name);
154  // Extract set of target points in libMesh mesh to perform interpolation of MFEM variable at
155  std::vector<Point> outgoing_libmesh_points;
156  extractlibMeshNodePositions(to_sys, to_var, outgoing_libmesh_points);
157  const MeshBase & to_mesh = to_problem.mesh(_displaced_target_mesh).getMesh();
158  // Perform interpolation of MFEM variable
159  for (auto & point : outgoing_libmesh_points)
161  outgoing_mfem_points = Moose::MFEM::libMeshPointsToMFEMVector(
162  outgoing_libmesh_points, to_mesh.mesh_dimension(), ordering);
163  }
164 
165  // MFEM interpolation using FindPointsGSLib::Interpolate must be over all ranks
166  // of the MFEM variable's MPI communicator
167  _mfem_interpolator.SetDefaultInterpolationValue(getMFEMOutOfMeshValue());
168  _mfem_interpolator.Interpolate(*from_var.ParFESpace()->GetParMesh(),
169  outgoing_mfem_points,
170  from_var,
171  interp_vals,
172  ordering);
173 
174  // If target libMesh variable exists on the current rank, update the set of local
175  // DoFs of the target libMesh variable using the interpolated MFEM values
176  if (is_target_local)
177  {
178  // Declare aliases for convenience
179  FEProblemBase & to_problem = getActiveToProblem();
180  const MooseVariableFieldBase & to_var(
181  to_problem.getVariable(0,
182  getToVarName(var_index),
185  const auto & to_var_name = getToVarName(var_index);
186  // Get undisplaced system for writing transferred variable to
187  auto & out_es = getlibMeshEquationSystem(to_problem, false);
188  auto & out_sys = *find_sys(out_es, to_var_name);
189 
190  // Project interpolated values at destination nodes onto destination variables to set DoFs
191  projectlibMeshNodalValues(out_sys, to_var, interp_vals);
192  }
193  }
194 }
195 
196 #endif
std::shared_ptr< mfem::ParGridFunction > getGridFunction(const std::string &name)
Definition: MFEMProblem.h:323
virtual bool isNodal() const
Is this variable nodal.
Virtual base class for MultiApp transfers to and/or from MFEMProblems.
const libMesh::FEType & feType() const
Get the type of finite element object.
libMesh::EquationSystems & getlibMeshEquationSystem(FEProblemBase &problem, bool use_displaced) const
Get libMesh EquationSystem, which may or may not be displaced.
unsigned int number() const
Get variable number coming from libMesh.
virtual void transferVariables(bool is_target_local) override
Transfer all variables from active MFEM source problem to active libMesh destination problem...
mfem::Vector libMeshPointsToMFEMVector(const std::vector< libMesh::Point > &points, const unsigned int num_dims, const mfem::Ordering::Type ordering)
Convert a vector of libMesh::Point objects to an mfem::Vector containing all points, given an ordering.
The main MOOSE class responsible for handling user-defined parameters in almost every MOOSE system...
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.
mfem::FindPointsGSLIB _mfem_interpolator
Object to perform pointwise interpolation of source MFEM GridFunctions.
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...
bool _displaced_target_mesh
True if displaced mesh is used for the target mesh, otherwise false.
MultiApp transfer from MFEM to libMesh variables, performed via evaluation of shape functions...
virtual FEProblemBase & getActiveToProblem()
Getter for current problem containing destination variables.
CONSTANT
unsigned int number() const
unsigned int numToVar() const
Return for the number of destination variables.
void extractlibMeshNodePositions(libMesh::System &to_sys, const MooseVariableFieldBase &to_var, std::vector< Point > &outgoing_libmesh_points)
Extract all target points of the destination libMesh variable, needed to set DoFs in transfer...
MeshBase & getMesh()
Accessor for the underlying libMesh Mesh object.
Definition: MooseMesh.C:3575
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
static libMesh::System * find_sys(libMesh::EquationSystems &es, const std::string &var_name)
Small helper function for finding the system containing the variable.
Definition: Transfer.C:91
std::unique_ptr< NumericVector< Number > > solution
void projectlibMeshNodalValues(libMesh::System &to_sys, const MooseVariableFieldBase &to_var, mfem::Vector &interp_vals)
Set DoFs of destination libMesh variable via projection, using a vector of interpolated values...
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.
virtual void update()
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.
const VariableName & getToVarName(int i) const
Getter for destination variable name.
IntRange< T > make_range(T beg, T end)
virtual MooseMesh & mesh() override
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
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...
registerMooseObject("MooseApp", MultiAppMFEMTolibMeshShapeEvaluationTransfer)
const Elem & get(const ElemType type_in)
virtual MFEMProblem & getActiveFromProblem() override
Set current MFEM problem to fetch source variables from.