feat(field-support): added field support system, mid migration

currently the barotope and the pressure force operator are migrated to the new support system
This commit is contained in:
2026-08-23 10:13:53 -04:00
parent dc912fd15e
commit 0f3ca8050b
137 changed files with 29975 additions and 16389 deletions

View File

@@ -10,9 +10,8 @@ import :operators.prepared_hdiv_mass;
namespace {
int get_operator_size(const mean_field::fem::FEM &f) {
MFEM_VERIFY(
f.gravityFluxFes != nullptr,
"PreparedMappedHDivMassOperator requires the "
"gravity-gradient finite-element space."
f.gravityFluxFes != nullptr, "PreparedMappedHDivMassOperator requires the "
"gravity-gradient finite-element space."
);
return f.gravityFluxFes->GetTrueVSize();
}
@@ -24,8 +23,7 @@ namespace {
) {
local_vector.SetSize(finite_element_space.GetVSize());
const mfem::Operator *prolongation =
finite_element_space.GetProlongationMatrix();
const mfem::Operator *prolongation = finite_element_space.GetProlongationMatrix();
if (prolongation != nullptr) {
prolongation->Mult(true_vector, local_vector);
@@ -41,8 +39,7 @@ namespace {
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
const int attribute = f.mesh->GetAttribute(element_id);
if (attribute > 0 && attribute <= marker.Size() &&
marker[attribute - 1] != 0) {
if (attribute > 0 && attribute <= marker.Size() && marker[attribute - 1] != 0) {
return element_id;
}
}
@@ -55,23 +52,19 @@ namespace {
const mfem::Array<int> &marker,
const int representative_element_id
) {
const mfem::FiniteElement &representative_element =
*f.gravityFluxFes->GetFE(representative_element_id);
const mfem::FiniteElement &representative_element = *f.gravityFluxFes->GetFE(representative_element_id);
const mfem::ElementTransformation &representative_transformation =
*f.mesh->GetElementTransformation(representative_element_id);
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
const int attribute = f.mesh->GetAttribute(element_id);
if (attribute <= 0 || attribute > marker.Size() ||
marker[attribute - 1] == 0) {
if (attribute <= 0 || attribute > marker.Size() || marker[attribute - 1] == 0) {
continue;
}
const mfem::FiniteElement &element =
*f.gravityFluxFes->GetFE(element_id);
const mfem::ElementTransformation &transformation =
*f.mesh->GetElementTransformation(element_id);
const mfem::FiniteElement &element = *f.gravityFluxFes->GetFE(element_id);
const mfem::ElementTransformation &transformation = *f.mesh->GetElementTransformation(element_id);
MFEM_VERIFY(
element.GetGeomType() == representative_element.GetGeomType(),
@@ -85,16 +78,14 @@ namespace {
"finite-element order."
);
MFEM_VERIFY(
transformation.OrderW() ==
representative_transformation.OrderW(),
transformation.OrderW() == representative_transformation.OrderW(),
"Prepared H(div) mass domains currently require a uniform "
"geometry-weight order."
);
}
}
class FrozenMappedHDivMassCoefficient final
: public mfem::MatrixCoefficient {
class FrozenMappedHDivMassCoefficient final : public mfem::MatrixCoefficient {
public:
FrozenMappedHDivMassCoefficient(
const mean_field::fem::FEM &f,
@@ -107,9 +98,7 @@ namespace {
m_domain_mapper(domain_mapper),
m_workspace(domain_mapper.GetDimension()),
m_elevates_vacuum(elevates_vacuum) {
true_to_local(
*m_fem.displacementFes, displacement_true, m_displacement_local
);
true_to_local(*m_fem.displacementFes, displacement_true, m_displacement_local);
}
void Eval(
@@ -125,9 +114,7 @@ namespace {
"Mapped H(div) mass coefficient received an invalid element ID."
);
const bool element_is_vacuum =
transformation.Attribute ==
m_domain_mapper.GetVacuumElementAttribute();
const bool element_is_vacuum = transformation.Attribute == m_domain_mapper.GetVacuumElementAttribute();
if (element_is_vacuum != m_elevates_vacuum) {
mass_tensor.SetSize(m_domain_mapper.GetDimension());
@@ -138,34 +125,27 @@ namespace {
LoadElement(element_id);
const mean_field::mapping::ElementMappingData mapping_data{
.displacement = *m_displacement_data,
.compactification = *m_compactification_data
.displacement = *m_displacement_data, .compactification = *m_compactification_data
};
mean_field::mapping::VolumeMappingContext mapping_context;
const mean_field::mapping::MappingStatus status =
m_domain_mapper.EvaluateVolume(
mapping_data, transformation, integration_point,
m_workspace, mapping_context
);
const mean_field::mapping::MappingStatus status = m_domain_mapper.EvaluateVolume(
mapping_data, transformation, integration_point, m_workspace, mapping_context
);
MFEM_VERIFY(
status == mean_field::mapping::MappingStatus::valid,
"Stateless domain mapping failed while preparing the H(div) "
"mass "
"operator. Mapping status = "
<< static_cast<int>(status)
<< ", element ID = " << element_id
<< static_cast<int>(status) << ", element ID = " << element_id
<< ", element attribute = " << transformation.Attribute
<< ", coefficient domain = "
<< (m_elevates_vacuum ? "vacuum" : "stellar")
<< ", coefficient domain = " << (m_elevates_vacuum ? "vacuum" : "stellar")
);
const mfem::DenseMatrix &mapping_jacobian =
mapping_context.mapping.mapping_jacobian;
const double mapping_determinant =
mapping_context.mapping.mapping_determinant;
const mfem::DenseMatrix &mapping_jacobian = mapping_context.mapping.mapping_jacobian;
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
MFEM_VERIFY(
std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
@@ -183,48 +163,32 @@ namespace {
return;
}
const mfem::FiniteElement &displacement_element =
*m_fem.displacementFes->GetFE(element_id);
const mfem::FiniteElement &compactification_element =
*m_fem.compactificationFes->GetFE(element_id);
const mfem::FiniteElement &displacement_element = *m_fem.displacementFes->GetFE(element_id);
const mfem::FiniteElement &compactification_element = *m_fem.compactificationFes->GetFE(element_id);
mfem::DofTransformation *displacement_dof_transformation =
m_fem.displacementFes->GetElementVDofs(
element_id, m_displacement_dofs
);
m_fem.displacementFes->GetElementVDofs(element_id, m_displacement_dofs);
mfem::DofTransformation *compactification_dof_transformation =
m_fem.compactificationFes->GetElementDofs(
element_id, m_compactification_dofs
);
m_fem.compactificationFes->GetElementDofs(element_id, m_compactification_dofs);
m_displacement_local.GetSubVector(
m_displacement_dofs, m_element_displacement
);
m_fem.compactificationCoordinate->GetSubVector(
m_compactification_dofs, m_element_compactification
);
m_displacement_local.GetSubVector(m_displacement_dofs, m_element_displacement);
m_fem.compactificationCoordinate->GetSubVector(m_compactification_dofs, m_element_compactification);
if (displacement_dof_transformation != nullptr) {
displacement_dof_transformation->InvTransformPrimal(
m_element_displacement
);
displacement_dof_transformation->InvTransformPrimal(m_element_displacement);
}
if (compactification_dof_transformation != nullptr) {
compactification_dof_transformation->InvTransformPrimal(
m_element_compactification
);
compactification_dof_transformation->InvTransformPrimal(m_element_compactification);
}
m_displacement_data = std::make_unique<
mean_field::mapping::ElementDisplacementData>(
m_displacement_data = std::make_unique<mean_field::mapping::ElementDisplacementData>(
mean_field::mapping::ElementDisplacementDataFromElementVDofs(
displacement_element, m_element_displacement
)
);
m_compactification_data = std::make_unique<
mean_field::mapping::ElementCompactificationData>(
m_compactification_data = std::make_unique<mean_field::mapping::ElementCompactificationData>(
compactification_element, m_element_compactification
);
@@ -242,10 +206,8 @@ namespace {
mfem::Vector m_element_displacement;
mfem::Vector m_element_compactification;
std::unique_ptr<mean_field::mapping::ElementDisplacementData>
m_displacement_data;
std::unique_ptr<mean_field::mapping::ElementCompactificationData>
m_compactification_data;
std::unique_ptr<mean_field::mapping::ElementDisplacementData> m_displacement_data;
std::unique_ptr<mean_field::mapping::ElementCompactificationData> m_compactification_data;
mean_field::mapping::DomainMapperStateless::Workspace m_workspace;
int m_cached_element_id{-1};
@@ -261,33 +223,26 @@ namespace mean_field::operators {
: Operator(get_operator_size(f)),
m_fem(f),
m_domain_mapper(domain_mapper) {
MFEM_VERIFY(f.mesh != nullptr, "PreparedMappedHDivMassOperator requires a mesh.");
MFEM_VERIFY(
f.mesh != nullptr, "PreparedMappedHDivMassOperator requires a mesh."
f.gravityFluxFes != nullptr, "PreparedMappedHDivMassOperator requires the "
"gravity-gradient finite-element space."
);
MFEM_VERIFY(
f.gravityFluxFes != nullptr,
"PreparedMappedHDivMassOperator requires the "
"gravity-gradient finite-element space."
f.displacementFes != nullptr, "PreparedMappedHDivMassOperator requires the "
"displacement finite-element space."
);
MFEM_VERIFY(
f.displacementFes != nullptr,
"PreparedMappedHDivMassOperator requires the "
"displacement finite-element space."
f.compactificationFes != nullptr, "PreparedMappedHDivMassOperator requires the compactification "
"finite-element space."
);
MFEM_VERIFY(
f.compactificationFes != nullptr,
"PreparedMappedHDivMassOperator requires the compactification "
"finite-element space."
f.compactificationCoordinate != nullptr, "PreparedMappedHDivMassOperator requires the compactification "
"coordinate."
);
MFEM_VERIFY(
f.compactificationCoordinate != nullptr,
"PreparedMappedHDivMassOperator requires the compactification "
"coordinate."
);
MFEM_VERIFY(
f.quadratureFactory != nullptr,
"PreparedMappedHDivMassOperator requires the quadrature-rule "
"factory."
f.quadratureFactory != nullptr, "PreparedMappedHDivMassOperator requires the quadrature-rule "
"factory."
);
MFEM_VERIFY(
domain_mapper.GetDimension() == f.mesh->Dimension(),
@@ -295,39 +250,26 @@ namespace mean_field::operators {
"dimension."
);
utils::populate_element_mask(
f.mesh.get(), utils::DOMAINS::STELLAR, m_stellar_marker
);
utils::populate_element_mask(
f.mesh.get(), utils::DOMAINS::VACUUM, m_vacuum_marker
);
utils::populate_element_mask(f.mesh.get(), utils::DOMAINS::STELLAR, m_stellar_marker);
utils::populate_element_mask(f.mesh.get(), utils::DOMAINS::VACUUM, m_vacuum_marker);
const int stellar_element_id =
find_representative_element(f, m_stellar_marker);
const int vacuum_element_id =
find_representative_element(f, m_vacuum_marker);
const int stellar_element_id = find_representative_element(f, m_stellar_marker);
const int vacuum_element_id = find_representative_element(f, m_vacuum_marker);
MFEM_VERIFY(
stellar_element_id >= 0, "PreparedMappedHDivMassOperator requires "
"at least one stellar element."
);
MFEM_VERIFY(
vacuum_element_id >= 0,
"PreparedMappedHDivMassOperator requires at "
"least one compactified vacuum element."
vacuum_element_id >= 0, "PreparedMappedHDivMassOperator requires at "
"least one compactified vacuum element."
);
validate_uniform_domain_discretization(
f, m_stellar_marker, stellar_element_id
);
validate_uniform_domain_discretization(
f, m_vacuum_marker, vacuum_element_id
);
validate_uniform_domain_discretization(f, m_stellar_marker, stellar_element_id);
validate_uniform_domain_discretization(f, m_vacuum_marker, vacuum_element_id);
}
void PreparedMappedHDivMassOperator::Prepare(
const mfem::Vector &displacement_true
) {
void PreparedMappedHDivMassOperator::Prepare(const mfem::Vector &displacement_true) {
MFEM_VERIFY(
displacement_true.Size() == m_fem.displacementFes->GetTrueVSize(),
"PreparedMappedHDivMassOperator received a displacement vector "
@@ -337,71 +279,48 @@ namespace mean_field::operators {
for (int i = 0; i < displacement_true.Size(); ++i) {
MFEM_VERIFY(
std::isfinite(displacement_true(i)),
"PreparedMappedHDivMassOperator received a non-finite "
"displacement "
"value."
std::isfinite(displacement_true(i)), "PreparedMappedHDivMassOperator received a non-finite "
"displacement "
"value."
);
}
const int stellar_element_id =
find_representative_element(m_fem, m_stellar_marker);
const int vacuum_element_id =
find_representative_element(m_fem, m_vacuum_marker);
const int stellar_element_id = find_representative_element(m_fem, m_stellar_marker);
const int vacuum_element_id = find_representative_element(m_fem, m_vacuum_marker);
const mfem::FiniteElement &stellar_element =
*m_fem.gravityFluxFes->GetFE(stellar_element_id);
const mfem::FiniteElement &vacuum_element =
*m_fem.gravityFluxFes->GetFE(vacuum_element_id);
const mfem::FiniteElement &stellar_element = *m_fem.gravityFluxFes->GetFE(stellar_element_id);
const mfem::FiniteElement &vacuum_element = *m_fem.gravityFluxFes->GetFE(vacuum_element_id);
mfem::ElementTransformation &stellar_transformation =
*m_fem.mesh->GetElementTransformation(stellar_element_id);
mfem::ElementTransformation &vacuum_transformation =
*m_fem.mesh->GetElementTransformation(vacuum_element_id);
mfem::ElementTransformation &stellar_transformation = *m_fem.mesh->GetElementTransformation(stellar_element_id);
mfem::ElementTransformation &vacuum_transformation = *m_fem.mesh->GetElementTransformation(vacuum_element_id);
m_mass_form.reset();
m_stellar_mass_coefficient.reset();
m_vacuum_mass_coefficient.reset();
m_stellar_mass_coefficient =
std::make_unique<FrozenMappedHDivMassCoefficient>(
m_fem, m_domain_mapper, displacement_true, false
);
std::make_unique<FrozenMappedHDivMassCoefficient>(m_fem, m_domain_mapper, displacement_true, false);
m_vacuum_mass_coefficient =
std::make_unique<FrozenMappedHDivMassCoefficient>(
m_fem, m_domain_mapper, displacement_true, true
);
std::make_unique<FrozenMappedHDivMassCoefficient>(m_fem, m_domain_mapper, displacement_true, true);
m_mass_form =
std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
m_mass_form = std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
m_mass_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
auto stellar_integrator =
std::make_unique<mfem::VectorFEMassIntegrator>(
*m_stellar_mass_coefficient
);
auto vacuum_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(
*m_vacuum_mass_coefficient
auto stellar_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(*m_stellar_mass_coefficient);
auto vacuum_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(*m_vacuum_mass_coefficient);
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
*stellar_integrator, quadrature::QuadratureRole::discretization, stellar_element, stellar_transformation,
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
);
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
*stellar_integrator, quadrature::QuadratureRole::discretization,
stellar_element, stellar_transformation, utils::DOMAINS::STELLAR,
quadrature::MappingKind::general
*vacuum_integrator, quadrature::QuadratureRole::discretization, vacuum_element, vacuum_transformation,
utils::DOMAINS::VACUUM, quadrature::MappingKind::kelvin
);
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
*vacuum_integrator, quadrature::QuadratureRole::discretization,
vacuum_element, vacuum_transformation, utils::DOMAINS::VACUUM,
quadrature::MappingKind::kelvin
);
m_mass_form->AddDomainIntegrator(
stellar_integrator.release(), m_stellar_marker
);
m_mass_form->AddDomainIntegrator(
vacuum_integrator.release(), m_vacuum_marker
);
m_mass_form->AddDomainIntegrator(stellar_integrator.release(), m_stellar_marker);
m_mass_form->AddDomainIntegrator(vacuum_integrator.release(), m_vacuum_marker);
m_mass_form->Assemble();
m_is_prepared = true;
@@ -434,8 +353,7 @@ namespace mean_field::operators {
return m_is_prepared;
}
std::uint64_t
PreparedMappedHDivMassOperator::GetPreparationCount() const noexcept {
std::uint64_t PreparedMappedHDivMassOperator::GetPreparationCount() const noexcept {
return m_preparation_count;
}
} // namespace mean_field::operators