12 #include "serac/numerics/functional/integral.hpp"
13 #include "serac/numerics/functional/element_restriction.hpp"
69 operator uint32_t() {
return index_; }
80 return SignedIndex{
static_cast<uint32_t
>((i >= 0) ? i : -1 - i), (i >= 0) ? 1 : -1};
88 inline bool isHcurl(
const mfem::ParFiniteElementSpace& fes)
90 return (fes.FEColl()->GetContType() == mfem::FiniteElementCollection::TANGENTIAL);
98 inline bool isL2(
const mfem::ParFiniteElementSpace& fes)
100 return (fes.FEColl()->GetContType() == mfem::FiniteElementCollection::DISCONTINUOUS);
111 return !(
isHcurl(fes) && fes.GetMesh()->Dimension() == 2) && !(
isHcurl(fes) && fes.GetMesh()->Dimension() == 3) &&
112 !(
isL2(fes)) && fes.GetMesh()->GetNBE() > 0;
128 template <
typename T, ExecutionSpace exec>
130 const mfem::ParFiniteElementSpace& test_fes)
132 auto* test_BE = test_fes.GetBE(0);
133 auto* trial_BE = trial_fes.GetBE(0);
134 return {
static_cast<size_t>(trial_fes.GetNFbyType(mfem::FaceType::Boundary)),
135 static_cast<size_t>(test_BE->GetDof() * test_fes.GetVDim()),
136 static_cast<size_t>(trial_BE->GetDof() * trial_fes.GetVDim())};
140 template <
typename T, ExecutionSpace exec>
144 auto* BE = fes.GetBE(0);
145 return {
static_cast<size_t>(fes.GetNFbyType(mfem::FaceType::Boundary)),
146 static_cast<size_t>(BE->GetDof() * fes.GetVDim())};
170 static_cast<size_t>(fespace.GetFE(0)->GetDof() * fespace.GetVDim())),
173 int dim = fespace.GetMesh()->Dimension();
174 mfem::Geometry::Type elem_geom[4] = {mfem::Geometry::INVALID, mfem::Geometry::SEGMENT, mfem::Geometry::SQUARE,
175 mfem::Geometry::CUBE};
180 auto elem_restriction = fespace.GetElementRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC);
182 mfem::Vector iota(elem_restriction->Width());
183 mfem::Vector dof_ids(elem_restriction->Height());
185 for (
int i = 0; i < iota.Size(); i++) {
195 elem_restriction->Mult(iota, dof_ids);
196 const double* dof_ids_h = dof_ids.HostRead();
199 for (axom::IndexType e = 0; e <
element_dofs_.shape()[0]; e++) {
200 for (axom::IndexType i = 0; i <
element_dofs_.shape()[1]; i++) {
201 uint32_t dof_id =
static_cast<uint32_t
>(fabs(dof_ids_h[index]));
202 int dof_sign = dof_ids[index] > 0 ? +1 : -1;
210 auto face_restriction = fespace.GetFaceRestriction(mfem::ElementDofOrdering::LEXICOGRAPHIC,
211 mfem::FaceType::Boundary, mfem::L2FaceValues::SingleValued);
213 mfem::Vector iota(face_restriction->Width());
214 mfem::Vector dof_ids(face_restriction->Height());
215 for (
int i = 0; i < iota.Size(); i++) {
219 face_restriction->Mult(iota, dof_ids);
220 const double* dof_ids_h = dof_ids.HostRead();
225 uint32_t dof_id =
static_cast<uint32_t
>(fabs(dof_ids_h[index]));
226 int dof_sign = dof_ids[index] > 0 ? +1 : -1;
273 std::size_t seed = std::hash<uint32_t>()(k.
row);
274 seed ^= std::hash<uint32_t>()(k.
column) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
293 for (
const auto& [geometry, trial_dofs] : block_trial_dofs.
restrictions) {
294 const auto& test_dofs = block_test_dofs.
restrictions.at(geometry);
296 std::vector<DoF> test_vdofs(test_dofs.nodes_per_elem * test_dofs.components);
297 std::vector<DoF> trial_vdofs(trial_dofs.nodes_per_elem * trial_dofs.components);
299 auto num_elements =
static_cast<uint32_t
>(trial_dofs.num_elements);
300 for (uint32_t e = 0; e < num_elements; e++) {
301 for (uint64_t i = 0; i < uint64_t(test_dofs.dof_info.shape()[1]); i++) {
302 auto test_dof = test_dofs.dof_info(e, i);
304 for (uint64_t j = 0; j < uint64_t(trial_dofs.dof_info.shape()[1]); j++) {
305 auto trial_dof = trial_dofs.dof_info(e, j);
307 for (uint64_t k = 0; k < test_dofs.components; k++) {
308 uint32_t test_global_id = uint32_t(test_dofs.GetVDof(test_dof, k).index());
309 for (uint64_t l = 0; l < trial_dofs.components; l++) {
310 uint32_t trial_global_id = uint32_t(trial_dofs.GetVDof(trial_dof, l).index());
311 nz_LUT[{test_global_id, trial_global_id}] = 0;
318 std::vector<Entry> entries(
nz_LUT.size());
321 for (
auto [key, value] :
nz_LUT) {
322 entries[count++] = key;
325 std::sort(entries.begin(), entries.end());
327 nnz =
static_cast<uint32_t
>(
nz_LUT.size());
328 row_ptr.resize(
static_cast<size_t>(block_test_dofs.
LSize() + 1));
332 col_ind[0] = int(entries[0].column);
334 for (uint32_t i = 1; i <
nnz; i++) {
336 col_ind[i] = int(entries[i].column);
339 for (uint32_t j = entries[i - 1].row; j < entries[i].row; j++) {
370 std::unordered_map<Entry, uint32_t, Entry::Hasher>
nz_LUT;
This file contains the interface used for initializing/terminating any hardware accelerator-related f...
Accelerator functionality.
bool isL2(const mfem::ParFiniteElementSpace &fes)
return whether or not the underlying function space is L2 or not
ExecArray< T, 3, exec > allocateMemoryForBdrElementGradients(const mfem::ParFiniteElementSpace &trial_fes, const mfem::ParFiniteElementSpace &test_fes)
this is a (hopefully) temporary measure to work around the fact that mfem's support for querying info...
axom::Array< T, dim, detail::execution_to_memory_v< space > > ExecArray
Alias for an Array corresponding to a particular ExecutionSpace.
bool compatibleWithFaceRestriction(const mfem::ParFiniteElementSpace &fes)
attempt to characterize which FiniteElementSpaces mfem::FaceRestriction actually works with
bool isHcurl(const mfem::ParFiniteElementSpace &fes)
return whether or not the underlying function space is Hcurl or not
bool operator<(const ElemInfo &x, const ElemInfo &y)
operator for sorting lexicographically by {global_row, global_col}
SignedIndex decodeSignedIndex(int i)
mfem will frequently encode {sign, index} into a single int32_t. This function decodes those values.
ExecutionSpace
enum used for signalling whether or not to perform certain calculations on the CPU or GPU
ExecArray< T, dim, ExecutionSpace::CPU > CPUArray
Alias for an array on the CPU.
bool operator!=(const ElemInfo &x, const ElemInfo &y)
operator determining inequality by {global_row, global_col}
a generalization of mfem::ElementRestriction that works with multiple kinds of element geometries....
std::map< mfem::Geometry::Type, ElementRestriction > restrictions
the individual ElementRestriction operators for each element geometry
uint64_t LSize() const
the size of the "L-vector" associated with this restriction operator
this object extracts the dofs for each element in a FiniteElementSpace as a 2D array such that elemen...
CPUArray< SignedIndex, 2 > element_dofs_
element_dofs_(e, i) stores the ith dof of element e.
DofNumbering(const mfem::ParFiniteElementSpace &fespace)
create lookup tables of which degrees of freedom correspond to each element and boundary element
CPUArray< SignedIndex, 2 > bdr_element_dofs_
bdr_element_dofs_(b, i) stores the ith dof of boundary element b.
Type
enum describing what kind of elements are included in a Domain
a (poorly named) tuple of quantities used to discover the sparsity pattern associated with element an...
uint32_t global_col_
The global column number.
uint32_t element_id_
The element ID.
Domain::Type type
Which kind of Integral this entry comes from.
int sign_
The orientation of the element.
uint32_t local_col_
The global column number.
uint32_t global_row_
The global row number.
uint32_t local_row_
The local row number.
hash functor required for use in std::unordered_map
std::size_t operator()(const Entry &k) const
a hash function implementation for Entry
a type for representing a nonzero entry in a sparse matrix
bool operator<(const Entry &other) const
operator< is used when sorting Entry. Lexicographical ordering
uint32_t row
row value for this nonzero Entry
bool operator==(const Entry &other) const
operator== is required for use in std::unordered_map
uint32_t column
column value for this nonzero Entry
this object figures out the sparsity pattern associated with a finite element discretization of the g...
GradientAssemblyLookupTables(const serac::BlockElementRestriction &block_test_dofs, const serac::BlockElementRestriction &block_trial_dofs)
create lookup tables describing which degrees of freedom correspond to each domain/boundary element
std::vector< int > row_ptr
array holding the offsets for a given row of the sparse matrix i.e. row r corresponds to the indices ...
std::vector< int > col_ind
array holding the column associated with each nonzero entry
uint32_t nnz
how many nonzero entries appear in the sparse matrix
std::unordered_map< Entry, uint32_t, Entry::Hasher > nz_LUT
nz_LUT returns the index of the col_ind / value CSR arrays corresponding to the (i,...
uint32_t operator()(int i, int j) const
return the index (into the nonzero entries) corresponding to entry (i,j)
this type explicitly stores sign (typically used conveying edge/face orientation) and index values
uint32_t index_
the actual index of some quantity
int sign_
whether or not the value associated with this index is positive or negative