Serac  0.1
Serac is an implicit thermal strucural mechanics simulation code.
finite_element_vector.cpp
1 // Copyright (c) 2019-2024, Lawrence Livermore National Security, LLC and
2 // other Serac Project Developers. See the top-level LICENSE file for
3 // details.
4 //
5 // SPDX-License-Identifier: (BSD-3-Clause)
6 
9 
10 namespace serac {
11 
12 FiniteElementVector::FiniteElementVector(const mfem::ParFiniteElementSpace& space, const std::string& name)
13  : mesh_(*space.GetParMesh()),
14  coll_(std::unique_ptr<mfem::FiniteElementCollection>(mfem::FiniteElementCollection::New(space.FEColl()->Name()))),
15  space_(std::make_unique<mfem::ParFiniteElementSpace>(space, &mesh_.get(), coll_.get())),
16  name_(name)
17 {
18  SLIC_ERROR_ROOT_IF(space.GetOrdering() == mfem::Ordering::byVDIM,
19  "Serac only operates on finite element spaces ordered by nodes");
20 
21  // Construct a hypre par vector based on the new finite element space
22  HypreParVector new_vector(space_.get());
23 
24  // Move the data from this new hypre vector into this object without doubly allocating the data
25  auto* parallel_vec = new_vector.StealParVector();
26  WrapHypreParVector(parallel_vec);
27 
28  // Initialize the vector to zero
29  HypreParVector::operator=(0.0);
30 }
31 
33  : mesh_(input_vector.mesh()),
34  coll_(std::move(input_vector.coll_)),
35  space_(std::move(input_vector.space_)),
36  name_(std::move(input_vector.name_))
37 {
38  // Grab the allocated data from the input argument for the underlying Hypre vector
39  auto* parallel_vec = input_vector.StealParVector();
40  WrapHypreParVector(parallel_vec);
41 }
42 
43 FiniteElementVector& FiniteElementVector::operator=(const mfem::HypreParVector& rhs)
44 {
45  SLIC_ERROR_IF(Size() != rhs.Size(),
46  axom::fmt::format("Finite element vector of size '{}' assigned to a HypreParVector of size '{}'",
47  Size(), rhs.Size()));
48 
49  HypreParVector::operator=(rhs);
50  return *this;
51 }
52 
54 {
55  Vector::operator=(rhs);
56  return *this;
57 }
58 
60 {
61  SLIC_ERROR_IF(Size() != rhs.Size(),
62  axom::fmt::format("Finite element vector of size '{}' assigned to a HypreParVector of size '{}'",
63  Size(), rhs.Size()));
64 
65  HypreParVector::operator=(rhs);
66 
67  return *this;
68 }
69 
71 {
72  mesh_ = rhs.mesh_;
73  coll_ = std::move(rhs.coll_);
74  space_ = std::move(rhs.space_);
75  name_ = rhs.name_;
76 
77  auto* parallel_vec = rhs.StealParVector();
78  WrapHypreParVector(parallel_vec);
79 
80  return *this;
81 }
82 
84 {
85  HypreParVector::operator=(value);
86  return *this;
87 }
88 
89 double avg(const FiniteElementVector& fe_vector)
90 {
91  double global_sum;
92  double local_sum = fe_vector.Sum();
93  int global_size;
94  int local_size = fe_vector.Size();
95  MPI_Allreduce(&local_sum, &global_sum, 1, MPI_DOUBLE, MPI_SUM, fe_vector.comm());
96  MPI_Allreduce(&local_size, &global_size, 1, MPI_INT, MPI_SUM, fe_vector.comm());
97  return global_sum / global_size;
98 }
99 
100 double max(const FiniteElementVector& fe_vector)
101 {
102  double global_max;
103  double local_max = fe_vector.Max();
104  MPI_Allreduce(&local_max, &global_max, 1, MPI_DOUBLE, MPI_MAX, fe_vector.comm());
105  return global_max;
106 }
107 
108 double min(const FiniteElementVector& fe_vector)
109 {
110  double global_min;
111  double local_min = fe_vector.Min();
112  MPI_Allreduce(&local_min, &global_min, 1, MPI_DOUBLE, MPI_MIN, fe_vector.comm());
113  return global_min;
114 }
115 
123 bool sameFiniteElementSpace(const mfem::FiniteElementSpace& left, const mfem::FiniteElementSpace& right)
124 {
125  bool sameMesh = (left.GetMesh() == right.GetMesh());
126  bool equivalentFEColl = strcmp(left.FEColl()->Name(), right.FEColl()->Name()) == 0;
127  bool sameVectorDimension = (left.GetVDim() == right.GetVDim());
128  bool sameOrdering = (left.GetOrdering() == right.GetOrdering());
129  return sameMesh && equivalentFEColl && sameVectorDimension && sameOrdering;
130 }
131 
133 {
134  SLIC_ERROR_IF(
135  v1.Size() != v2.Size(),
136  axom::fmt::format("Finite element vector of size '{}' can not inner product with another vector of size '{}'",
137  v1.Size(), v2.Size()));
138  SLIC_ERROR_IF(v1.comm() != v2.comm(),
139  "Cannot compute inner products between finite element vectors with different mpi communicators");
140  SLIC_ERROR_IF(!sameFiniteElementSpace(v1.space(), v2.space()),
141  "Currently cannot compute inner products between finite element vectors with different mfem spaces");
142 
143  double global_ip;
144  double local_ip = mfem::InnerProduct(v1, v2);
145  MPI_Allreduce(&local_ip, &global_ip, 1, MPI_DOUBLE, MPI_SUM, v1.comm());
146  return global_ip;
147 }
148 
149 } // namespace serac
Class for encapsulating the data associated with a vector derived from a MFEM finite element space....
std::string name_
The name of the finite element vector.
std::unique_ptr< mfem::FiniteElementCollection > coll_
Handle to the FiniteElementCollection, which is owned by MFEMSidreDataCollection.
MPI_Comm comm() const
Returns the MPI communicator for the state.
mfem::ParFiniteElementSpace & space()
Returns a non-owning reference to the internal FESpace.
FiniteElementVector & operator=(const FiniteElementVector &rhs)
Copy assignment.
std::reference_wrapper< mfem::ParMesh > mesh_
A reference to the mesh object on which the field is defined.
std::unique_ptr< mfem::ParFiniteElementSpace > space_
Handle to the mfem::ParFiniteElementSpace, which is owned by MFEMSidreDataCollection.
FiniteElementVector(const mfem::ParFiniteElementSpace &space, const std::string &name="")
Minimal constructor for a FiniteElementVector given a finite element space.
This file contains the declaration of structure that manages vectors derived from an MFEM finite elem...
This file contains the all the necessary functions and macros required for logging as well as a helpe...
Accelerator functionality.
Definition: serac.cpp:38
double innerProduct(const FiniteElementVector &v1, const FiniteElementVector &v2)
Find the inner prodcut between two finite element vectors across all dofs.
constexpr T & get(variant< T0, T1 > &v)
Returns the variant member of specified type.
Definition: variant.hpp:338
SERAC_HOST_DEVICE auto max(dual< gradient_type > a, double b)
Implementation of max for dual numbers.
Definition: dual.hpp:230
SERAC_HOST_DEVICE auto min(dual< gradient_type > a, double b)
Implementation of min for dual numbers.
Definition: dual.hpp:256
double avg(const FiniteElementVector &fe_vector)
Find the average value of a finite element vector across all dofs.
bool sameFiniteElementSpace(const mfem::FiniteElementSpace &left, const mfem::FiniteElementSpace &right)
Check if two finite element spaces are the same.