https://mooseframework.inl.gov
MFEMNodalProjector.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 
12 #include "MFEMNodalProjector.h"
13 #include "MFEMVectorUtils.h"
14 #include "MooseError.h"
15 
16 void
17 MFEMNodalProjector::extractNodePositions(const mfem::ParFiniteElementSpace & fespace,
18  mfem::Vector & node_positions,
19  mfem::Ordering::Type & node_ordering)
20 {
21  const int nelem = fespace.GetParMesh()->GetNE();
22  const int dim = fespace.GetParMesh()->Dimension();
23 
24  // Find total number of local nodes/interpolation points
25  int nnodes = 0;
26  for (const auto i : make_range(nelem))
27  nnodes += fespace.GetFE(i)->GetNodes().GetNPoints();
28 
29  node_positions.SetSize(nnodes * dim);
30 
31  int nodal_offset = 0;
32  for (const auto i : make_range(nelem))
33  {
34  const mfem::IntegrationRule ir = fespace.GetFE(i)->GetNodes();
35  const int nqpt = ir.GetNPoints();
36 
37  mfem::DenseMatrix pos;
38  fespace.GetElementTransformation(i)->Transform(ir, pos);
39  mfem::Vector row;
40 
41  for (const auto d : make_range(dim))
42  {
43  row.SetDataAndSize(node_positions.GetData() + nodal_offset + d * nnodes, nqpt);
44  pos.GetRow(d, row);
45  }
46 
47  nodal_offset += nqpt;
48  }
49  node_ordering = mfem::Ordering::Type::byNODES;
50 }
51 
52 void
53 MFEMNodalProjector::projectNodalValues(const mfem::Vector & nodal_vals,
54  const mfem::Ordering::Type & nodal_val_ordering,
55  mfem::ParGridFunction & gridfunction)
56 {
57  mfem::ParFiniteElementSpace & fespace = *gridfunction.ParFESpace();
58  const int nelem = fespace.GetParMesh()->GetNE();
59  const int gf_ncomp = gridfunction.VectorDim();
60 
61  fespace.GetParMesh()->EnsureNodes();
62 
63  // Check FESpaces can be transferred
64  const auto map = fespace.FEColl()->GetMapType(fespace.GetParMesh()->Dimension());
65  const bool H1L2 = map == mfem::FiniteElement::VALUE || map == mfem::FiniteElement::INTEGRAL;
66  const bool RTND = map == mfem::FiniteElement::H_DIV || map == mfem::FiniteElement::H_CURL;
67  if (!H1L2 && !RTND)
68  mooseError("FESpace type not supported yet in transfers.");
69 
70  // Project the interpolated values to the target FiniteElementSpace.
71  mfem::Ordering::Type dof_ordering = H1L2 ? mfem::Ordering::byNODES : mfem::Ordering::byVDIM;
72  mfem::Array<int> vdofs;
73  mfem::Vector vals;
74  int nodal_offset = 0;
75  for (const auto el : make_range(nelem))
76  {
77  const int nqpt = fespace.GetFE(el)->GetNodes().GetNPoints();
78  mfem::Vector dof_vals(nqpt * gf_ncomp);
79  fespace.GetElementVDofs(el, vdofs); // Returned vdofs always indexed with ordering byNODES
80  for (const auto qp : make_range(nqpt))
81  for (const auto d : make_range(gf_ncomp))
82  dof_vals(Moose::MFEM::MFEMIndex(d, qp, gf_ncomp, nqpt, dof_ordering)) = nodal_vals(
83  Moose::MFEM::MFEMIndex(d, qp, gf_ncomp, nqpt, nodal_val_ordering) + nodal_offset);
84 
85  if (H1L2)
86  gridfunction.SetSubVector(vdofs, dof_vals);
87  else if (RTND)
88  {
89  vals.SetSize(vdofs.Size());
90  fespace.GetFE(el)->ProjectFromNodes(dof_vals, *fespace.GetElementTransformation(el), vals);
91  gridfunction.SetSubVector(vdofs, vals);
92  }
93 
94  nodal_offset += nqpt * gf_ncomp;
95  }
96  gridfunction.SetTrueVector();
97 }
98 
99 #endif
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...
void mooseError(Args &&... args)
Emit an error message with the given stringified, concatenated args and terminate the application...
Definition: MooseError.h:311
static constexpr std::size_t dim
This is the dimension of all vector and tensor datastructures used in MOOSE.
Definition: Moose.h:163
std::size_t MFEMIndex(const std::size_t i_dim, const std::size_t i_point, const std::size_t num_dims, const std::size_t num_points, const mfem::Ordering::Type ordering)
Convert an index of a vector of libMesh::Points to an MFEM vector index, given an MFEM ordering...
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.
IntRange< T > make_range(T beg, T end)