feat(discretization/domain): updated domain system to use unified mfem backend
This means that the domain system never directly uses mfem code any more
This commit is contained in:
@@ -1,45 +1,38 @@
|
||||
#include "serif/discretization/domain/mesh/topology.hpp"
|
||||
|
||||
#include <mfem.hpp>
|
||||
#include <utility>
|
||||
#include "serif/utils/error/errors.hpp"
|
||||
|
||||
namespace serif::discretization::domain::mesh {
|
||||
const std::vector<int> MeshTopology::s_noElements{};
|
||||
|
||||
namespace {
|
||||
/** @brief Convert a nonnegative topology coordinate to a container index. */
|
||||
[[nodiscard]] std::size_t as_index(const int id) noexcept {
|
||||
return static_cast<std::size_t>(id);
|
||||
}
|
||||
|
||||
/** @brief Test a signed topology coordinate before indexing storage. */
|
||||
[[nodiscard]] bool in_range(const int id, const std::size_t size) noexcept {
|
||||
return id >= 0 && as_index(id) < size;
|
||||
}
|
||||
}
|
||||
|
||||
MeshTopology::MeshTopology(const mfem::Mesh &mesh)
|
||||
: m_elementDomainIDs(as_index(mesh.GetNE()), 0),
|
||||
m_faceElements(as_index(mesh.GetNumFaces())),
|
||||
m_elementNeighbors(as_index(mesh.GetNE())),
|
||||
m_boundaryElementBoundaryIDs(as_index(mesh.GetNBE()), 0),
|
||||
m_boundaryElementFaceIDs(as_index(mesh.GetNBE()), -1),
|
||||
m_boundaryElementsByFace(as_index(mesh.GetNumFaces())) {
|
||||
|
||||
// Which domain each volume element claims to belong to.
|
||||
for (int elementID = 0; elementID < mesh.GetNE(); ++elementID) {
|
||||
m_elementDomainIDs[as_index(elementID)] = mesh.GetAttribute(elementID);
|
||||
}
|
||||
|
||||
// Face connectivity.
|
||||
for (int faceID = 0; faceID < mesh.GetNumFaces(); ++faceID) {
|
||||
int firstElementID = -1;
|
||||
int secondElementID = -1;
|
||||
|
||||
mesh.GetFaceElements(faceID, &firstElementID, &secondElementID);
|
||||
|
||||
m_faceElements[as_index(faceID)] = FaceElements{
|
||||
.firstElementID = firstElementID,
|
||||
.secondElementID = secondElementID
|
||||
};
|
||||
MeshTopology::MeshTopology(MeshTopologyData data)
|
||||
: m_elementDomainIDs(std::move(data.elementDomainIDs)),
|
||||
m_faceElements(std::move(data.faceElements)),
|
||||
m_elementNeighbors(m_elementDomainIDs.size()),
|
||||
m_boundaryElementBoundaryIDs(std::move(data.boundaryElementBoundaryIDs)),
|
||||
m_boundaryElementFaceIDs(std::move(data.boundaryElementFaceIDs)),
|
||||
m_boundaryElementsByFace(m_faceElements.size()) {
|
||||
using namespace utils::errors;
|
||||
|
||||
serif_ensure<SERiFErrorCode::INVALID_ARGUMENT>(m_boundaryElementBoundaryIDs.size() == m_boundaryElementFaceIDs.size(), "Each topology boundary element requires both a boundary ID and a face ID.");
|
||||
// Face connectivity determines adjacency independently of backend numbering conventions.
|
||||
for (const FaceElements& face : m_faceElements) {
|
||||
const int firstElementID = face.firstElementID;
|
||||
const int secondElementID = face.secondElementID;
|
||||
serif_ensure<SERiFErrorCode::OUT_OF_RANGE_ERROR>((firstElementID == -1 || in_range(firstElementID, m_elementDomainIDs.size())) && (secondElementID == -1 || in_range(secondElementID, m_elementDomainIDs.size())), "Topology face elements must be valid element indices or -1 for the exterior; received {} and {} for {} elements.", firstElementID, secondElementID, m_elementDomainIDs.size());
|
||||
if (firstElementID < 0 || secondElementID < 0) {
|
||||
continue;
|
||||
}
|
||||
@@ -48,16 +41,12 @@ namespace serif::discretization::domain::mesh {
|
||||
m_elementNeighbors[as_index(secondElementID)].push_back(firstElementID);
|
||||
}
|
||||
|
||||
// Boundary elements
|
||||
for (int boundaryElementID = 0; boundaryElementID < mesh.GetNBE(); ++boundaryElementID) {
|
||||
m_boundaryElementBoundaryIDs[as_index(boundaryElementID)] = mesh.GetBdrAttribute(boundaryElementID);
|
||||
|
||||
const int faceID = mesh.GetBdrElementFaceIndex(boundaryElementID);
|
||||
|
||||
m_boundaryElementFaceIDs[as_index(boundaryElementID)] = faceID;
|
||||
|
||||
// A face can carry several boundary labels; retain all of them for schema validation.
|
||||
for (std::size_t boundaryElementID = 0; boundaryElementID < m_boundaryElementFaceIDs.size(); ++boundaryElementID) {
|
||||
const int faceID = m_boundaryElementFaceIDs[boundaryElementID];
|
||||
serif_ensure<SERiFErrorCode::OUT_OF_RANGE_ERROR>(faceID == -1 || in_range(faceID, m_faceElements.size()), "Topology boundary face {} must be a valid face index or -1 for an unresolved face.", faceID);
|
||||
if (in_range(faceID, m_boundaryElementsByFace.size())) {
|
||||
m_boundaryElementsByFace[as_index(faceID)].push_back(boundaryElementID);
|
||||
m_boundaryElementsByFace[as_index(faceID)].push_back(static_cast<int>(boundaryElementID));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user