Progress on bringing the DomainMapper over

This commit is contained in:
2026-09-20 16:33:06 -04:00
parent d7e7a3a015
commit 806268ccb8
9 changed files with 467 additions and 0 deletions

View File

@@ -0,0 +1,127 @@
#pragma once
#include "mfem/fem/fe/fe_base.hpp"
#include "mfem/fem/fespace.hpp"
#include "mfem/linalg/vector.hpp"
#include "mfem/linalg/densemat.hpp"
#include "mfem/mesh/mesh.hpp"
#include <cstdint>
#include <unordered_map>
#include <tuple>
#include "serif/mapping/compactification/kelvin.hpp"
#include "serif/mapping/context.hpp"
#include "serif/mapping/data.hpp"
namespace serif::mapping {
enum class FaceElementSide : uint8_t {
ELEMENT_1,
ELEMENT_2
};
class ElementDisplacementData {
public:
ElementDisplacementData(const mfem::FiniteElement& element, mfem::Vector& displacement_dofs, mfem::Ordering::Type ordering = mfem::Ordering::byNODES);
[[nodiscard]] const mfem::FiniteElement& get_element() const noexcept;
[[nodiscard]] const mfem::DenseMatrix &get_dof_matrix() const noexcept;
[[nodiscard]] int get_dimension() const noexcept;
[[nodiscard]] int get_dof_count() const noexcept;
[[nodiscard]] mfem::Ordering::Type get_ordering() const noexcept;
private:
const mfem::FiniteElement *m_element;
mfem::DenseMatrix m_dof_matrix;
int m_dimension;
mfem::Ordering::Type m_ordering;
};
// Maybe this should be moved into the compactification module
struct CompactificationPointData {
double compactification_coordinate{0.0};
mfem::Vector coordinate_gradient;
};
[[nodiscard]] ElementDisplacementData element_displacement_data_from_element_vdofs(
const mfem::FiniteElement& element,
mfem::Vector &displacement_dofs
);
class ElementCompactificationData {
public:
ElementCompactificationData(const mfem::FiniteElement& element, const mfem::Vector& dofs);
[[nodiscard]] const mfem::FiniteElement& get_element() const noexcept;
[[nodiscard]] const mfem::Vector &get_dofs() const noexcept;
[[nodiscard]] int get_dof_count() const noexcept;
private:
const mfem::FiniteElement *m_element;
mfem::Vector m_dofs;
};
struct ElementMappingData {
const ElementDisplacementData &displacement;
const ElementCompactificationData &compactification;
};
class DMWorkspace {
public:
explicit DMWorkspace (int dimension = 3);
void set_dimension(int dimension);
[[nodiscard]] int get_dimension() const noexcept;
public: // This is a workspace class, these members are kept public so we do not need indirection through getters to access them
mfem::Vector m_shape;
mfem::DenseMatrix m_reference_shape;
mfem::DenseMatrix m_mesh_dshape;
mfem::DenseMatrix m_reference_field_jacobian;
mfem::Vector m_field_value;
mfem::DenseMatrix m_field_jacobian;
mfem::Vector m_compactification_shape;
mfem::DenseMatrix m_compactification_dshape;
CompactificationPointData m_compactification_point;
mfem::Vector m_reference_normal;
mfem::Vector m_mapped_normal;
mfem::DenseMatrix m_full_element_jacobian;
mfem::Vector m_vector_temp;
mfem::DenseMatrix m_matrix_temp_1;
mfem::DenseMatrix m_matrix_temp_2;
compactification::ExteriorMapResult m_exterior_result;
compactification::ExteriorMapVariation m_exterior_variation;
private:
int m_dimension;
};
struct DMFixedMeshGeometry {
mfem::Vector position;
mfem::DenseMatrix jacobian;
mfem::DenseMatrix inverse_jacobian;
double weight{0.0};
};
struct DMGeometryCacheStatistics {
std::uint64_t hits{0};
std::uint64_t misses{0};
std::size_t points{0};
};
struct DMReferenceDisplacementSample {
const mfem::Vector& value;
const mfem::DenseMatrix& gradient;
};
struct DMGeometryCache {
bool enabled{true};
const mfem::Mesh* mesh{nullptr};
int32_t sequence{-1};
int32_t nodesSequence{-1};
std::unordered_map<std::tuple<int, double, double, double>, DMFixedMeshGeometry> points;
uint64_t hits{0};
uint64_t misses{0};
};
}

View File

@@ -0,0 +1,161 @@
#pragma once
#include <cstdint>
#include <memory>
#include "mfem/linalg/vector.hpp"
#include "mfem/linalg/densemat.hpp"
#include "mfem/fem/eltrans.hpp"
#include "mfem/fem/intrules.hpp"
#include "serif/mapping/compactification/kelvin.hpp"
#include "serif/mapping/context.hpp"
#include "serif/mapping/data.hpp"
#include "serif/utils/user_options/mapping/domain_mapper.hpp"
namespace serif::mapping {
class DomainMapper {
public:
DomainMapper(
utils::user_options::DomainMapperOptions options,
std::unique_ptr<compactification::ExteriorDomainMap> exterior_map
);
DomainMapper(const DomainMapper&) = delete;
DomainMapper& operator=(const DomainMapper&) = delete;
~DomainMapper();
DomainMapper(DomainMapper&&) = delete;
DomainMapper& operator=(DomainMapper&&) = delete;
void set_geometry_cache_enabled(bool enabled) const;
[[nodiscard]] bool is_geometry_cache_enabled() const noexcept;
void clear_geometry_cache() const;
[[nodiscard]] DMGeometryCacheStatistics get_geometry_cache_statistics() const;
[[nodiscard]] const DMFixedMeshGeometry* get_fixed_mesh_geometry(mfem::ElementTransformation& transformation, const mfem::IntegrationPoint& ip) const;
[[nodiscard]] MappingStatus evaluate_point(
const ElementMappingData& element_data,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
MappingPointContext& context
) const;
[[nodiscard]] MappingStatus evaluate_volume(
const ElementMappingData& element_data,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
VolumeMappingContext& context,
const DMReferenceDisplacementSample *displacement_sample = nullptr
) const;
[[nodiscard]] MappingStatus evaluate_face(
const ElementMappingData& element_data,
mfem::ElementTransformation& transformation,
FaceElementSide side,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
FaceMappingContext& context
) const;
[[nodiscard]] MappingStatus evaluate_point_variation(
const ElementMappingData& element_data,
const ElementDisplacementData& direction,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
const MappingPointContext& context,
DMWorkspace& workspace,
MappingPointVariation& variation
);
[[nodiscard]] MappingStatus evaluate_volume_variation(
const ElementMappingData& element_data,
const ElementDisplacementData& direction,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
const VolumeMappingContext& context,
DMWorkspace& workspace,
VolumeMappingVariation& variation
);
[[nodiscard]] MappingStatus evaluate_face_variation(
const ElementMappingData& element_data,
const ElementDisplacementData& direction,
mfem::ElementTransformation& transformation,
FaceElementSide side,
const mfem::IntegrationPoint& ip,
const FaceMappingContext& context,
DMWorkspace& workspace,
FaceMappingVariation& variation
);
[[nodiscard]] bool is_compactified_element(const mfem::ElementTransformation& transformation) const noexcept;
[[nodiscard]] int get_dimension() const noexcept;
[[nodiscard]] const compactification::ExteriorDomainMap& get_exterior_map() const noexcept;
private:
[[nodiscard]] MappingStatus evaluate_point_impl(
const ElementMappingData& element_data,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
MappingPointContext& context,
const DMFixedMeshGeometry* geometry,
const DMReferenceDisplacementSample* displacement_sample = nullptr
) const;
void validate_element_data(
const ElementMappingData& element_data
) const;
void evaluate_field(
const ElementDisplacementData& field,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
mfem::Vector& value,
mfem::DenseMatrix& jacobian,
const mfem::DenseMatrix *inverse_mesh_jacobian
) const;
[[nodiscard]] MappingStatus evaluate_compactification_coordinate(
const ElementCompactificationData& compactification,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
DMWorkspace& workspace,
CompactificationPointData& point_data,
const mfem::DenseMatrix *inverse_mesh_jacobian
) const;
[[nodiscard]] MappingStatus evaluate_point_variation_impl(
const ElementMappingData& element_data,
const ElementDisplacementData& direction,
mfem::ElementTransformation& transformation,
const mfem::IntegrationPoint& ip,
const MappingPointContext& context,
DMWorkspace& workspace,
MappingPointVariation& variation,
const mfem::DenseMatrix *inverse_mesh_jacobian
) const;
// These are static since they do not use any class members or workspace. Really these could and
// maybe should be free functions...
[[nodiscard]] static mfem::ElementTransformation& select_face_element_transformation(
mfem::FaceElementTransformations& transformations,
FaceElementSide side
);
[[nodiscard]] static const mfem::IntegrationPoint& select_face_element_integration_point(
mfem::FaceElementTransformations& transformations,
FaceElementSide side
);
private:
mutable std::unique_ptr<DMGeometryCache> m_geometryCache;
utils::user_options::DomainMapperOptions m_options;
std::unique_ptr<const compactification::ExteriorDomainMap> m_exterior_map;
};
}

View File

@@ -51,6 +51,12 @@ namespace serif::utils::errors {
NON_FINITE_MAPPING_RESULT,
NON_POSITIVE_DETERMINATE,
INVALID_DOF_COUNT,
INVALID_DOF_ORDERING,
INVALID_COMPACTIFICATION_RANK,
INVALID_COMPACTIFICATION_TYPE,
INVALID_COMPACTIFICATION_DERIVATIVE_VALUE,
IMPROPERLY_ORDERED_REFERENCE_RADII = 450,
INVALID_COORDINATE_TOLERANCE,

View File

@@ -0,0 +1,8 @@
#pragma once
namespace serif::utils::user_options {
struct DomainMapperOptions {
int dimension{3};
int vacuum_element_attribute_ID{3};
};
}