Skip to content

Commit 315f6eb

Browse files
committed
Move code to dof_map and compute on-the-fly
1 parent 51dee79 commit 315f6eb

File tree

3 files changed

+16
-87
lines changed

3 files changed

+16
-87
lines changed

include/mesh/mesh_base.h

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1844,14 +1844,6 @@ class MeshBase : public ParallelObject
18441844
const boundary_id_type b2);
18451845
#endif
18461846

1847-
#ifdef DEBUG
1848-
/**
1849-
* Get the map from subdomain ID to the set of element dimensions contained within
1850-
* that subdomain
1851-
*/
1852-
const std::unordered_map<subdomain_id_type, std::unordered_set<unsigned char>> &
1853-
get_subdomain_to_elem_dims_map() const { return _subdomain_id_to_elem_dims; }
1854-
#endif
18551847

18561848
protected:
18571849

@@ -2162,13 +2154,6 @@ class MeshBase : public ParallelObject
21622154
*/
21632155
Real _point_locator_close_to_point_tol;
21642156

2165-
#ifdef DEBUG
2166-
/**
2167-
* Map from subdomain ID to the set of element dimensions present in that subdomain
2168-
*/
2169-
std::unordered_map<subdomain_id_type, std::unordered_set<unsigned char>> _subdomain_id_to_elem_dims;
2170-
#endif
2171-
21722157
/**
21732158
* The partitioner class is a friend so that it can set
21742159
* the number of partitions.

src/base/dof_map.C

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3142,6 +3142,16 @@ void DofMap::reinit_static_condensation()
31423142
#ifdef DEBUG
31433143
namespace
31443144
{
3145+
unsigned char determine_elem_dims(const MeshBase & mesh,
3146+
const std::set<subdomain_id_type> & subdomains)
3147+
{
3148+
unsigned char elem_dims = 0;
3149+
for (const auto * const elem : mesh.active_subdomain_set_element_ptr_range(subdomains))
3150+
elem_dims |= static_cast<unsigned char>(1u << cast_int<unsigned char>(elem->dim()));
3151+
mesh.comm().bitwise_or(elem_dims);
3152+
return elem_dims;
3153+
}
3154+
31453155
void discontinuity_sanity_check(const System & sys,
31463156
const FEType & fe_type,
31473157
const std::set<subdomain_id_type> * const active_subdomains)
@@ -3155,19 +3165,14 @@ void discontinuity_sanity_check(const System & sys,
31553165
if (!mesh.is_prepared())
31563166
return;
31573167

3158-
const auto & sub_to_elem_dims = mesh.get_subdomain_to_elem_dims_map();
31593168
const auto & var_subdomains = (active_subdomains && !active_subdomains->empty())
31603169
? *active_subdomains
31613170
: mesh.get_mesh_subdomains();
3162-
std::unordered_set<unsigned char> var_elem_dims;
3163-
for (const auto sub_id : var_subdomains)
3164-
{
3165-
const auto & sub_elem_dims = libmesh_map_find(sub_to_elem_dims, sub_id);
3166-
for (const auto dim : sub_elem_dims)
3167-
var_elem_dims.insert(dim);
3168-
}
3171+
const auto var_elem_dims = determine_elem_dims(mesh, var_subdomains);
3172+
// Power of two trick. Note that unsigned char automatically promoted to int for arithmetic and bitwise operations
3173+
const bool more_than_one_bit_set = (var_elem_dims & (var_elem_dims - 1)) != 0;
31693174
libmesh_assert_msg(
3170-
var_elem_dims.size() <= 1,
3175+
!more_than_one_bit_set,
31713176
"Discontinuous finite element families are typically associated with discontinuous Galerkin "
31723177
"methods. If degrees of freedom are associated with different values of element dimension, "
31733178
"then generally this will result in a singular system after application of the DG method.");

src/mesh/mesh_base.C

Lines changed: 2 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@
4141
#include "libmesh/enum_to_string.h"
4242
#include "libmesh/point_locator_nanoflann.h"
4343
#include "libmesh/elem_side_builder.h"
44-
#include "libmesh/utility.h"
4544

4645
// C++ includes
4746
#include <algorithm> // for std::min
@@ -1825,18 +1824,13 @@ void MeshBase::cache_elem_data()
18251824

18261825
for (const auto & elem : this->active_element_ptr_range())
18271826
{
1828-
const auto elem_dim = cast_int<unsigned char>(elem->dim());
1829-
_elem_dims.insert(elem_dim);
1827+
_elem_dims.insert(cast_int<unsigned char>(elem->dim()));
18301828
_elem_default_orders.insert(elem->default_order());
1831-
const auto sub_id = elem->subdomain_id();
1832-
_mesh_subdomains.insert(sub_id);
1829+
_mesh_subdomains.insert(elem->subdomain_id());
18331830
_supported_nodal_order =
18341831
static_cast<Order>
18351832
(std::min(static_cast<int>(_supported_nodal_order),
18361833
static_cast<int>(elem->supported_nodal_order())));
1837-
#ifdef DEBUG
1838-
_subdomain_id_to_elem_dims[sub_id].insert(elem_dim);
1839-
#endif
18401834
}
18411835

18421836
if (!this->is_serial())
@@ -1847,61 +1841,6 @@ void MeshBase::cache_elem_data()
18471841
this->comm().set_union(_elem_default_orders);
18481842
this->comm().min(_supported_nodal_order);
18491843
this->comm().set_union(_mesh_subdomains);
1850-
1851-
#ifdef DEBUG
1852-
#ifdef LIBMESH_HAVE_MPI
1853-
1854-
using Mask = unsigned char;
1855-
1856-
// Prepare sparse subdomain id to dense subdomain "id"
1857-
const auto n_sub = cast_int<int>(_mesh_subdomains.size());
1858-
std::unordered_map<subdomain_id_type, subdomain_id_type> sub_to_dense_idx;
1859-
sub_to_dense_idx.reserve(n_sub);
1860-
std::vector<subdomain_id_type> dense_idx_to_sub;
1861-
dense_idx_to_sub.reserve(n_sub);
1862-
{
1863-
subdomain_id_type dense_idx = 0;
1864-
for (const auto sub_id : _mesh_subdomains)
1865-
{
1866-
sub_to_dense_idx.emplace(sub_id, dense_idx++);
1867-
dense_idx_to_sub.push_back(sub_id);
1868-
}
1869-
}
1870-
1871-
// Pack local dimension sets into Mask
1872-
std::vector<Mask> masks(n_sub, Mask(0));
1873-
for (const auto & [sub_id, elem_dims] : _subdomain_id_to_elem_dims)
1874-
{
1875-
const auto dense_idx = libmesh_map_find(sub_to_dense_idx, sub_id);
1876-
Mask m = 0;
1877-
for (const auto dim : elem_dims)
1878-
m |= Mask(1u << dim);
1879-
1880-
masks[dense_idx] = m;
1881-
}
1882-
_subdomain_id_to_elem_dims.clear();
1883-
1884-
// Communicate the mask data
1885-
MPI_Allreduce(
1886-
MPI_IN_PLACE, masks.data(), n_sub, MPI_UNSIGNED_CHAR, MPI_BOR, _communicator.get());
1887-
1888-
constexpr unsigned char max_elem_dim = LIBMESH_DIM;
1889-
1890-
for (const auto dense_idx : make_range(n_sub))
1891-
{
1892-
const auto mask = masks[dense_idx];
1893-
if (mask == 0)
1894-
// No elements for this subdomain
1895-
continue;
1896-
1897-
const auto sub_id = dense_idx_to_sub[dense_idx];
1898-
auto & dim_set = _subdomain_id_to_elem_dims[sub_id];
1899-
for (const auto dim : make_range(max_elem_dim))
1900-
if (mask & Mask(1u << dim))
1901-
dim_set.insert(dim);
1902-
}
1903-
#endif // LIBMESH_HAVE_MPI
1904-
#endif // DEBUG
19051844
}
19061845

19071846
// If the largest element dimension found is larger than the current

0 commit comments

Comments
 (0)