feat(libmeanfield): centrifugal + pressure

This commit is contained in:
2026-08-04 14:24:55 -04:00
parent 9bc4f2758a
commit dc912fd15e
115 changed files with 260058 additions and 163261 deletions

View File

@@ -10,7 +10,7 @@ export namespace mean_field::mapping {
public:
MappedScalarCoefficient(
const DomainMapper &map,
mfem::Coefficient &coeff,
Coefficient &coeff,
COORDINATE_SPACE coord_space = COORDINATE_SPACE::PHYSICAL
);
@@ -21,14 +21,14 @@ export namespace mean_field::mapping {
private:
static double eval_at_point(
mfem::Coefficient &c,
Coefficient &c,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
);
private:
const DomainMapper &m_map;
mfem::Coefficient &m_coeff;
Coefficient &m_coeff;
COORDINATE_SPACE m_coord_space;
};
@@ -42,29 +42,37 @@ export namespace mean_field::mapping {
MappedDiffusionCoefficient(
const DomainMapper &map,
mfem::MatrixCoefficient &sigma
MatrixCoefficient &sigma
);
void Eval(mfem::DenseMatrix &K, mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip) override;
void Eval(
mfem::DenseMatrix &K,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) override;
private:
const DomainMapper &m_map;
mfem::Coefficient *m_scalar;
mfem::MatrixCoefficient *m_tensor;
MatrixCoefficient *m_tensor;
};
class MappedVectorCoefficient : public mfem::VectorCoefficient {
public:
MappedVectorCoefficient(
const DomainMapper &map,
mfem::VectorCoefficient &coeff
VectorCoefficient &coeff
);
void Eval(mfem::Vector &V, mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip) override;
void Eval(
mfem::Vector &V,
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) override;
private:
const DomainMapper &m_map;
mfem::VectorCoefficient &m_coeff;
VectorCoefficient &m_coeff;
};
class PhysicalPositionFunctionCoefficient : public mfem::Coefficient {
@@ -76,7 +84,10 @@ export namespace mean_field::mapping {
Func f
);
double Eval(mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip) override;
double Eval(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) override;
private:
Func m_f;
@@ -85,11 +96,18 @@ export namespace mean_field::mapping {
class MappedHDivMassCoefficient final : public mfem::MatrixCoefficient {
public:
MappedHDivMassCoefficient(const DomainMapper& map, const int dim);
MappedHDivMassCoefficient(
const DomainMapper &map,
const int dim
);
void Eval(
mfem::DenseMatrix &matrix,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point
) override;
void Eval(mfem::DenseMatrix& matrix, mfem::ElementTransformation& transformation, const mfem::IntegrationPoint& integration_point) override;
private:
const DomainMapper& m_map;
const DomainMapper &m_map;
};
}
} // namespace mean_field::mapping

View File

@@ -0,0 +1,46 @@
module;
#include <mfem.hpp>
export module mean_field:mapping.compactification;
export import :mapping.types;
export namespace mean_field::mapping::compactification {
struct ExteriorMapInput {
const mfem::Vector &reference_position;
const mfem::Vector &displaced_position;
const mfem::DenseMatrix &displacement_jacobian;
double compactification_coordinate;
const mfem::Vector &compactification_coordinate_gradient;
};
struct ExteriorMapResult {
mfem::Vector physical_position;
mfem::DenseMatrix mapping_jacobian;
};
struct ExteriorMapDirection {
const mfem::Vector &displaced_position_variation;
const mfem::DenseMatrix &displacement_jacobian_variation;
};
struct ExteriorMapVariation {
mfem::Vector physical_position_variation;
mfem::DenseMatrix mapping_jacobian_variation;
};
class ExteriorDomainMap {
public:
virtual ~ExteriorDomainMap() = default;
[[nodiscard]] virtual MappingStatus Evaluate(
const ExteriorMapInput &input,
ExteriorMapResult &result
) const = 0;
[[nodiscard]] virtual MappingStatus EvaluateVariation(
const ExteriorMapInput &input,
const ExteriorMapResult &result,
const ExteriorMapDirection &direction,
ExteriorMapVariation &variation
) const = 0;
[[nodiscard]] virtual std::string_view GetName() const noexcept = 0;
};
} // namespace mean_field::mapping::compactification

View File

@@ -0,0 +1,50 @@
module;
#include <mfem.hpp>
export module mean_field:mapping.kelvin;
export import :mapping.compactification;
export import :mapping.types;
export import :mapping.compactification.options;
export namespace mean_field::mapping::compactification {
class KelvinCompactification final : public ExteriorDomainMap {
public:
explicit KelvinCompactification(
options::KelvinCompactificationOptions options
);
[[nodiscard]] MappingStatus Evaluate(
const ExteriorMapInput &input,
ExteriorMapResult &result
) const override;
[[nodiscard]] MappingStatus EvaluateVariation(
const ExteriorMapInput &input,
const ExteriorMapResult &result,
const ExteriorMapDirection &direction,
ExteriorMapVariation &variation
) const override;
[[nodiscard]] std::string_view GetName() const noexcept override;
[[nodiscard]] double GetReferenceStellarRadius() const noexcept;
[[nodiscard]] double GetReferenceInfinityRadius() const noexcept;
[[nodiscard]] double GetCoordinateTolerance() const noexcept;
private:
struct RadialFactors {
double coordinate;
double computational_radius;
double scale;
double scale_derivative;
};
[[nodiscard]] MappingStatus ComputeRadialFactors(
double compactification_coordinate,
RadialFactors &factors
) const;
options::KelvinCompactificationOptions m_options;
};
} // namespace mean_field::mapping::compactification

View File

@@ -0,0 +1,9 @@
export module mean_field:mapping.compactification.options;
export namespace mean_field::mapping::compactification::options {
struct KelvinCompactificationOptions {
double r_star_ref{1.0};
double r_inf_ref{2.0};
double coordinate_tolerance{1.0e-12};
};
} // namespace mean_field::mapping::compactification::options

View File

@@ -3,51 +3,302 @@ module;
#include "mean_field.h"
export module mean_field:mapping.domain_mapper;
export import :mapping.types;
import :mapping.compactification;
import :utils.user;
export namespace mean_field::mapping {
enum class FaceElementSide : uint8_t { element_1, element_2 };
class ElementDisplacementData {
public:
ElementDisplacementData(
const mfem::FiniteElement &element,
const mfem::Vector &displacement_dofs,
mfem::Ordering::Type ordering = mfem::Ordering::byNODES
);
[[nodiscard]] const mfem::FiniteElement &GetElement() const noexcept;
[[nodiscard]] const mfem::DenseMatrix &GetDofMatrix() const noexcept;
[[nodiscard]] int GetDimension() const noexcept;
[[nodiscard]] int GetDofCount() const noexcept;
[[nodiscard]] mfem::Ordering::Type GetOrdering() const noexcept;
private:
const mfem::FiniteElement *m_element;
mfem::DenseMatrix m_dof_matrix;
int m_dimension;
mfem::Ordering::Type m_ordering;
};
struct CompactificationPointData {
double coordinate{0.0};
mfem::Vector coordinate_gradient;
};
[[nodiscard]] ElementDisplacementData
ElementDisplacementDataFromElementVDofs(
const mfem::FiniteElement &element,
const mfem::Vector &displacement_dofs
);
class ElementCompactificationData {
public:
ElementCompactificationData(
const mfem::FiniteElement &element,
const mfem::Vector &dofs
);
[[nodiscard]] const mfem::FiniteElement &GetElement() const noexcept;
[[nodiscard]] const mfem::Vector &GetDofs() const noexcept;
[[nodiscard]] int GetDofCount() const noexcept;
private:
const mfem::FiniteElement *m_element;
mfem::Vector m_dofs;
};
struct ElementMappingData {
const ElementDisplacementData &displacement;
const ElementCompactificationData &compactification;
};
class DomainMapperStateless {
public:
class Workspace {
public:
explicit Workspace(int dimension = 3);
void SetDimension(int dimension);
[[nodiscard]] int GetDimension() const noexcept;
private:
friend class DomainMapperStateless;
int m_dimension;
mfem::Vector m_shape;
mfem::DenseMatrix m_mesh_dshape;
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;
};
public:
DomainMapperStateless(
utils::DomainMapperStatelessOptions options,
std::unique_ptr<const compactification::ExteriorDomainMap>
exterior_map
);
DomainMapperStateless(const DomainMapperStateless &) = delete;
DomainMapperStateless &
operator=(const DomainMapperStateless &) = delete;
DomainMapperStateless(DomainMapperStateless &&) = default;
DomainMapperStateless &operator=(DomainMapperStateless &&) = default;
[[nodiscard]] MappingStatus EvaluatePoint(
const ElementMappingData &element_data,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
Workspace &workspace,
MappingPointContext &context
) const;
[[nodiscard]] MappingStatus EvaluateVolume(
const ElementMappingData &element_data,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
Workspace &workspace,
VolumeMappingContext &context
) const;
[[nodiscard]] MappingStatus EvaluateFace(
const ElementMappingData &element_data,
mfem::FaceElementTransformations &transformation,
FaceElementSide side,
const mfem::IntegrationPoint &integration_point,
Workspace &workspace,
FaceMappingContext &context
) const;
[[nodiscard]] MappingStatus EvaluatePointVariation(
const ElementMappingData &element_data,
const ElementDisplacementData &direction,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
const MappingPointContext &base_context,
Workspace &workspace,
MappingPointVariation &variation
) const;
[[nodiscard]] MappingStatus EvaluateVolumeVariation(
const ElementMappingData &element_data,
const ElementDisplacementData &direction,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
const VolumeMappingContext &base_context,
Workspace &workspace,
VolumeMappingVariation &variation
) const;
[[nodiscard]] MappingStatus EvaluateFaceVariation(
const ElementMappingData &element_data,
const ElementDisplacementData &direction,
mfem::FaceElementTransformations &transformation,
FaceElementSide side,
const mfem::IntegrationPoint &integration_point,
const FaceMappingContext &base_context,
Workspace &workspace,
FaceMappingVariation &variation
) const;
[[nodiscard]] bool IsCompactifiedElement(
const mfem::ElementTransformation &transformation
) const noexcept;
[[nodiscard]] int GetDimension() const noexcept;
[[nodiscard]] int GetVacuumElementAttribute() const noexcept;
[[nodiscard]] const compactification::ExteriorDomainMap &
GetExteriorMap() const noexcept;
private:
void ValidateElementData(const ElementMappingData &element_data) const;
void EvaluateField(
const ElementDisplacementData &field,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
Workspace &workspace,
mfem::Vector &value,
mfem::DenseMatrix &jacobian
) const;
[[nodiscard]] MappingStatus EvaluateCompactificationCoordinate(
const ElementCompactificationData &compactification,
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
Workspace &workspace,
CompactificationPointData &point_data
) const;
[[nodiscard]] static mfem::ElementTransformation &
SelectFaceElementTransformation(
mfem::FaceElementTransformations &transformation,
FaceElementSide side
);
[[nodiscard]] static const mfem::IntegrationPoint &
SelectFaceElementIntegrationPoint(
mfem::FaceElementTransformations &transformation,
FaceElementSide side
);
utils::DomainMapperStatelessOptions m_options;
std::unique_ptr<const compactification::ExteriorDomainMap>
m_exterior_map;
};
class DomainMapper {
public:
struct VolumeQuadratureContext {
mfem::DenseMatrix J_inv;
double detJ;
double weight;
};
struct FaceQuadratureContext {
mfem::Vector normal;
double ds;
double v_dot_n_scale;
};
public:
explicit DomainMapper(const double r_star_ref, const double r_inf_ref);
explicit DomainMapper(
const double r_star_ref,
const double r_inf_ref
);
explicit DomainMapper(const mfem::GridFunction &d, const double r_star_ref, const double r_inf_ref);
explicit DomainMapper(
const mfem::GridFunction &d,
const double r_star_ref,
const double r_inf_ref
);
[[nodiscard]] bool is_vacuum(const mfem::ElementTransformation &T) const;
[[nodiscard]] bool
is_vacuum(const mfem::ElementTransformation &T) const;
void SetDisplacement(const mfem::GridFunction &d);
[[nodiscard]] bool IsIdentity() const;
[[nodiscard]] bool HasCompactification() const noexcept;
[[nodiscard]] bool HasDisplacementField() const noexcept;
[[nodiscard]] bool CalcIsIdentity() const;
void ResetDisplacement();
void ComputeJacobian(mfem::ElementTransformation &T, mfem::DenseMatrix &J) const;
void ComputeJacobian(
mfem::ElementTransformation &T,
mfem::DenseMatrix &J
) const;
double ComputeDetJ(mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip) const;
double ComputeDetJ(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) const;
void ComputeMappedDiffusionTensor(mfem::ElementTransformation &T, mfem::DenseMatrix &D) const;
void ComputeMappedDiffusionTensor(
mfem::ElementTransformation &T,
mfem::DenseMatrix &D
) const;
void ComputeInverseJacobian(mfem::ElementTransformation &T, mfem::DenseMatrix &JInv) const;
void ComputeInverseJacobian(
mfem::ElementTransformation &T,
mfem::DenseMatrix &JInv
) const;
VolumeQuadratureContext GetQuadratureContext(mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip) const;
VolumeQuadratureContext GetQuadratureContext(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip
) const;
FaceQuadratureContext GetFaceQuadratureContext(mfem::FaceElementTransformations &T, const mfem::IntegrationPoint &ip) const;
FaceQuadratureContext GetFaceQuadratureContext(
mfem::FaceElementTransformations &T,
const mfem::IntegrationPoint &ip
) const;
void GetPhysicalPoint(mfem::ElementTransformation &T, const mfem::IntegrationPoint &ip, mfem::Vector &x_phys) const;
void GetPhysicalPoint(
mfem::ElementTransformation &T,
const mfem::IntegrationPoint &ip,
mfem::Vector &x_phys
) const;
void GetVectorValue(const int i, const mfem::IntegrationPoint &ip, mfem::Vector &val) const;
void GetVectorValue(
const int i,
const mfem::IntegrationPoint &ip,
mfem::Vector &val
) const;
void MapHDivFluxToPhysical(
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
const mfem::Vector &reference_flux,
mfem::Vector &physical_flux
) const;
void MapPhysicalFluxToHDivReference(
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
const mfem::Vector &physical_flux,
mfem::Vector &reference_flux
) const;
void MapReferenceGradientToPhysical(
mfem::ElementTransformation &transformation,
const mfem::IntegrationPoint &integration_point,
const mfem::Vector &reference_gradient,
mfem::Vector &physical_gradient
) const;
[[nodiscard]] const mfem::GridFunction *GetDisplacement() const;
[[nodiscard]] double GetPhysInfRadius() const;
@@ -63,9 +314,17 @@ export namespace mean_field::mapping {
private:
void InitAllScratchSpaces() const;
void ApplyKelvinMapping(const mfem::Vector &x_ref, mfem::Vector &x_phys) const;
void ApplyKelvinMapping(
const mfem::Vector &x_ref,
mfem::Vector &x_phys
) const;
void ComputeKelvinJacobian(const mfem::Vector &x_ref, const mfem::Vector &x_disp, const mfem::DenseMatrix &J_D, mfem::DenseMatrix &J) const;
void ComputeKelvinJacobian(
const mfem::Vector &x_ref,
const mfem::Vector &x_disp,
const mfem::DenseMatrix &J_D,
mfem::DenseMatrix &J
) const;
void InvalidateCache() const;
@@ -98,6 +357,8 @@ export namespace mean_field::mapping {
mutable mfem::Vector m_x_ref;
mutable mfem::Vector m_x_disp;
mutable mfem::Vector m_d_val;
bool m_displacement_is_identity{true};
};
}
} // namespace mean_field::mapping

View File

@@ -0,0 +1,87 @@
module;
#include <mfem.hpp>
export module mean_field:mapping.transformations;
export import :mapping.types;
export namespace mean_field::mapping {
void MapHDivFluxToPhysical(
const MappingPointContext &context,
const mfem::Vector &reference_flux,
mfem::Vector &physical_flux
);
void MapPhysicalFluxToHDivReference(
const MappingPointContext &context,
const mfem::Vector &physical_flux,
mfem::Vector &reference_flux
);
void MapReferenceGradientToPhysical(
const MappingPointContext &context,
const mfem::Vector &reference_gradient,
mfem::Vector &physical_gradient
);
void MapPhysicalGradientToReference(
const MappingPointContext &context,
const mfem::Vector &physical_gradient,
mfem::Vector &reference_gradient
);
void MapReferenceVectorGradientToPhysical(
const MappingPointContext &context,
const mfem::DenseMatrix &reference_gradient,
mfem::DenseMatrix &physical_gradient
);
void MapPhysicalVectorGradientToReference(
const MappingPointContext &context,
const mfem::DenseMatrix &physical_gradient,
mfem::DenseMatrix &reference_gradient
);
[[nodiscard]] double MapHDivDivergenceToPhysical(
const MappingPointContext &context,
double reference_divergence
);
void ComputeHDivMassTensor(
const MappingPointContext &context,
mfem::DenseMatrix &mass_tensor
);
void ComputeScalarDiffusionTensor(
const MappingPointContext &context,
mfem::DenseMatrix &diffusion_tensor
);
void MapHCurlFieldToPhysical(
const MappingPointContext &context,
const mfem::Vector &reference_field,
mfem::Vector &physical_field
);
void MapPhysicalFieldToHCurlReference(
const MappingPointContext &context,
const mfem::Vector &physical_field,
mfem::Vector &reference_field
);
void MapHCurlCurlToPhysical(
const MappingPointContext &context,
const mfem::Vector &reference_curl,
mfem::Vector &physical_curl
);
void MapPhysicalCurlToHCurlReference(
const MappingPointContext &context,
const mfem::Vector &physical_curl,
mfem::Vector &reference_curl
);
void ComputeHCurlMassTensor(
const MappingPointContext &context,
mfem::DenseMatrix &mass_tensor
);
void ComputeHCurlCurlTensor(
const MappingPointContext &context,
mfem::DenseMatrix &curl_tensor
);
void ComputeHDivMassTensorVariation(
const MappingPointContext &context,
const MappingPointVariation &variation,
mfem::DenseMatrix &mass_tensor_variation
);
} // namespace mean_field::mapping

View File

@@ -1,10 +1,77 @@
module;
#include <cstdint>
#include <mfem.hpp>
export module mean_field:mapping.types;
namespace mean_field::mapping {
enum class COORDINATE_SPACE : uint8_t {
PHYSICAL,
REFERENCE
export namespace mean_field::mapping {
enum class COORDINATE_SPACE : uint8_t { PHYSICAL, REFERENCE };
enum class MappingStatus : uint8_t {
valid,
invalid_dimension,
non_finite_input,
invalid_reference_radius,
at_compactified_infinity,
outside_reference_domain,
non_finite_result,
non_positive_determinant
};
}
struct VolumeQuadratureContext {
mfem::DenseMatrix J_inv;
double detJ;
double weight;
};
struct FaceQuadratureContext {
mfem::Vector normal;
double ds;
double v_dot_n_scale;
};
struct MappingPointContext {
mfem::Vector reference_position;
mfem::Vector displaced_position;
mfem::Vector physical_position;
mfem::DenseMatrix displacement_jacobian;
mfem::DenseMatrix mapping_jacobian;
mfem::DenseMatrix inverse_mapping_jacobian;
double mapping_determinant{0.0};
bool compactified{false};
};
struct VolumeMappingContext {
MappingPointContext mapping;
VolumeQuadratureContext quadrature;
};
struct FaceMappingContext {
MappingPointContext mapping;
FaceQuadratureContext quadrature;
mfem::Vector reference_normal;
double reference_surface_weight{0.0};
double physical_surface_weight{0.0};
};
struct MappingPointVariation {
mfem::Vector displacement_variation;
mfem::Vector physical_position_variation;
mfem::DenseMatrix displacement_jacobian_variation;
mfem::DenseMatrix mapping_jacobian_variation;
mfem::DenseMatrix inverse_mapping_jacobian_variation;
double mapping_determinant_variation{0.0};
};
struct VolumeMappingVariation {
MappingPointVariation mapping;
mfem::DenseMatrix inverse_element_jacobian_variation;
double weight_variation{0.0};
};
struct FaceMappingVariation {
MappingPointVariation mapping;
mfem::Vector physical_normal_variation;
double physical_surface_weight_variation{0.0};
double normal_flux_scale_variation{0.0};
};
} // namespace mean_field::mapping