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

@@ -11,19 +11,17 @@ import :operators.prepared_gravity_source;
namespace {
int get_operator_height(const mean_field::fem::FEM &f) {
MFEM_VERIFY(
f.gravityPotentialFes != nullptr,
"PreparedMappedGravitySourceOperator requires the "
"gravity-potential "
"finite-element space."
f.gravityPotentialFes != nullptr, "PreparedMappedGravitySourceOperator requires the "
"gravity-potential "
"finite-element space."
);
return f.gravityPotentialFes->GetTrueVSize();
}
int get_operator_width(const mean_field::fem::FEM &f) {
MFEM_VERIFY(
f.densityFes != nullptr,
"PreparedMappedGravitySourceOperator requires the density "
"finite-element space."
f.densityFes != nullptr, "PreparedMappedGravitySourceOperator requires the density "
"finite-element space."
);
return f.densityFes->GetTrueVSize();
}
@@ -35,8 +33,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);
@@ -50,16 +47,12 @@ namespace {
const mfem::Vector &local_vector,
mfem::Vector &true_vector
) {
MFEM_VERIFY(
local_vector.Size() == finite_element_space.GetVSize(),
"Local vector has the wrong size."
);
MFEM_VERIFY(local_vector.Size() == finite_element_space.GetVSize(), "Local vector has the wrong size.");
true_vector.SetSize(finite_element_space.GetTrueVSize());
true_vector = 0.0;
true_vector = 0.0;
const mfem::Operator *prolongation =
finite_element_space.GetProlongationMatrix();
const mfem::Operator *prolongation = finite_element_space.GetProlongationMatrix();
if (prolongation != nullptr) {
prolongation->MultTranspose(local_vector, true_vector);
@@ -74,34 +67,27 @@ namespace {
const mfem::FiniteElement &potential_element,
const mfem::ElementTransformation &transformation
) {
using GravityField =
mean_field::field::Field<mean_field::field::Gravity>;
using GravityField = mean_field::field::Field<mean_field::field::Gravity>;
MFEM_VERIFY(
density_element.GetOrder() ==
mean_field::field::Density::Scalar::familyOrder,
density_element.GetOrder() == mean_field::field::Density::Scalar::familyOrder,
"The prepared source trial element does not match the registered "
"density field."
);
MFEM_VERIFY(
potential_element.GetOrder() ==
mean_field::field::Gravity::Potential::familyOrder,
potential_element.GetOrder() == mean_field::field::Gravity::Potential::familyOrder,
"The prepared source test element does not match the registered "
"gravity potential."
);
const mean_field::quadrature::Query query = GravityField::make_query<
mean_field::field::Gravity::Form::SourceProjection>(
mean_field::quadrature::QuadratureRole::discretization,
transformation.OrderW(), {}, mean_field::utils::DOMAINS::STELLAR,
mean_field::quadrature::MappingKind::general
);
const mean_field::quadrature::Query query =
GravityField::make_query<mean_field::field::Gravity::Form::SourceProjection>(
mean_field::quadrature::QuadratureRole::discretization, transformation.OrderW(), {},
mean_field::utils::DOMAINS::STELLAR, mean_field::quadrature::MappingKind::general
);
return *f.quadratureFactory
->get(query, transformation.GetGeometryType())
.integration_rule;
return *f.quadratureFactory->get(query, transformation.GetGeometryType()).integration_rule;
}
class FrozenMappedGravitySourceCoefficient final
: public mfem::Coefficient {
class FrozenMappedGravitySourceCoefficient final : public mfem::Coefficient {
public:
FrozenMappedGravitySourceCoefficient(
const mean_field::fem::FEM &f,
@@ -111,9 +97,7 @@ namespace {
: m_fem(f),
m_domain_mapper(domain_mapper),
m_workspace(domain_mapper.GetDimension()) {
true_to_local(
*m_fem.displacementFes, displacement_true, m_displacement_local
);
true_to_local(*m_fem.displacementFes, displacement_true, m_displacement_local);
}
double Eval(
@@ -128,79 +112,55 @@ namespace {
"Mapped gravity source coefficient received an invalid element "
"ID."
);
if (transformation.Attribute ==
m_domain_mapper.GetVacuumElementAttribute()) {
if (transformation.Attribute == m_domain_mapper.GetVacuumElementAttribute()) {
return 0.0;
}
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
);
if (status != mean_field::mapping::MappingStatus::valid) {
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::Vector displacement_shape(displacement_element.GetDof());
mfem::Vector compactification_shape(
compactification_element.GetDof()
);
mfem::Vector compactification_shape(compactification_element.GetDof());
mfem::Vector reference_position(m_domain_mapper.GetDimension());
mfem::Vector displacement_value(m_domain_mapper.GetDimension());
displacement_element.CalcShape(
integration_point, displacement_shape
);
compactification_element.CalcShape(
integration_point, compactification_shape
);
displacement_element.CalcShape(integration_point, displacement_shape);
compactification_element.CalcShape(integration_point, compactification_shape);
transformation.Transform(integration_point, reference_position);
m_displacement_data->GetDofMatrix().MultTranspose(
displacement_shape, displacement_value
);
m_displacement_data->GetDofMatrix().MultTranspose(displacement_shape, displacement_value);
const double compactification_coordinate =
m_compactification_data->GetDofs() * compactification_shape;
const double compactification_coordinate = m_compactification_data->GetDofs() * compactification_shape;
MFEM_ABORT(
"Stateless domain mapping failed while preparing the "
"gravity "
"source operator."
<< "\nMapping status = " << static_cast<int>(status)
<< "\nElement ID = " << element_id
<< "\nMapping status = " << static_cast<int>(status) << "\nElement ID = " << element_id
<< "\nElement attribute = " << transformation.Attribute
<< "\nIntegration-point index = " << integration_point.index
<< "\nIntegration point = <" << integration_point.x << ", "
<< integration_point.y << ", " << integration_point.z << ">"
<< "\nReference position = <" << reference_position(0)
<< ", " << reference_position(1) << ", "
<< "\nIntegration-point index = " << integration_point.index << "\nIntegration point = <"
<< integration_point.x << ", " << integration_point.y << ", " << integration_point.z << ">"
<< "\nReference position = <" << reference_position(0) << ", " << reference_position(1) << ", "
<< reference_position(2) << ">"
<< "\nReference radius = " << reference_position.Norml2()
<< "\nDisplacement value = <" << displacement_value(0)
<< ", " << displacement_value(1) << ", "
<< displacement_value(2) << ">"
<< "\nDisplacement magnitude = "
<< displacement_value.Norml2()
<< "\nCompactification coordinate = "
<< compactification_coordinate
<< "\nDisplacement ordering = "
<< static_cast<int>(m_fem.displacementFes->GetOrdering())
<< "\nReference radius = " << reference_position.Norml2() << "\nDisplacement value = <"
<< displacement_value(0) << ", " << displacement_value(1) << ", " << displacement_value(2) << ">"
<< "\nDisplacement magnitude = " << displacement_value.Norml2()
<< "\nCompactification coordinate = " << compactification_coordinate
<< "\nDisplacement ordering = " << static_cast<int>(m_fem.displacementFes->GetOrdering())
);
}
const double mapping_determinant =
mapping_context.mapping.mapping_determinant;
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
MFEM_VERIFY(
std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
"Prepared gravity source operator encountered a non-positive "
@@ -208,8 +168,7 @@ namespace {
"non-finite mapping determinant."
);
return 4.0 * std::numbers::pi * mean_field::utils::G *
mapping_determinant;
return 4.0 * std::numbers::pi * mean_field::utils::G * mapping_determinant;
}
private:
@@ -218,48 +177,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
);
@@ -277,10 +220,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};
@@ -298,30 +239,23 @@ namespace mean_field::operators {
),
m_fem(f),
m_domain_mapper(domain_mapper) {
MFEM_VERIFY(f.mesh != nullptr, "PreparedMappedGravitySourceOperator requires a mesh.");
MFEM_VERIFY(
f.mesh != nullptr,
"PreparedMappedGravitySourceOperator requires a mesh."
f.densityFes != nullptr, "PreparedMappedGravitySourceOperator requires the density "
"finite-element space."
);
MFEM_VERIFY(
f.densityFes != nullptr,
"PreparedMappedGravitySourceOperator requires the density "
"finite-element space."
f.gravityPotentialFes != nullptr, "PreparedMappedGravitySourceOperator requires the "
"gravity-potential "
"finite-element space."
);
MFEM_VERIFY(
f.gravityPotentialFes != nullptr,
"PreparedMappedGravitySourceOperator requires the "
"gravity-potential "
"finite-element space."
f.displacementFes != nullptr, "PreparedMappedGravitySourceOperator requires "
"the displacement finite-element space."
);
MFEM_VERIFY(
f.displacementFes != nullptr,
"PreparedMappedGravitySourceOperator requires "
"the displacement finite-element space."
);
MFEM_VERIFY(
f.compactificationFes != nullptr,
"PreparedMappedGravitySourceOperator requires the compactification "
"finite-element space."
f.compactificationFes != nullptr, "PreparedMappedGravitySourceOperator requires the compactification "
"finite-element space."
);
MFEM_VERIFY(
f.compactificationCoordinate != nullptr,
@@ -329,9 +263,8 @@ namespace mean_field::operators {
"coordinate."
);
MFEM_VERIFY(
f.quadratureFactory != nullptr,
"PreparedMappedGravitySourceOperator "
"requires the quadrature-rule factory."
f.quadratureFactory != nullptr, "PreparedMappedGravitySourceOperator "
"requires the quadrature-rule factory."
);
MFEM_VERIFY(
domain_mapper.GetDimension() == f.mesh->Dimension(),
@@ -339,14 +272,10 @@ 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::STELLAR, m_stellar_marker);
}
void PreparedMappedGravitySourceOperator::Prepare(
const mfem::Vector &displacement_true
) {
void PreparedMappedGravitySourceOperator::Prepare(const mfem::Vector &displacement_true) {
MFEM_VERIFY(
displacement_true.Size() == m_fem.displacementFes->GetTrueVSize(),
"PreparedMappedGravitySourceOperator received a displacement "
@@ -356,9 +285,8 @@ namespace mean_field::operators {
for (int i = 0; i < displacement_true.Size(); ++i) {
MFEM_VERIFY(
std::isfinite(displacement_true(i)),
"PreparedMappedGravitySourceOperator received a non-finite "
"displacement value."
std::isfinite(displacement_true(i)), "PreparedMappedGravitySourceOperator received a non-finite "
"displacement value."
);
}
@@ -366,44 +294,33 @@ namespace mean_field::operators {
m_elements.clear();
m_elements.reserve(m_fem.mesh->GetNE());
FrozenMappedGravitySourceCoefficient source_coefficient(
m_fem, m_domain_mapper, displacement_true
);
FrozenMappedGravitySourceCoefficient source_coefficient(m_fem, m_domain_mapper, displacement_true);
for (int element_id = 0; element_id < m_fem.mesh->GetNE();
++element_id) {
for (int element_id = 0; element_id < m_fem.mesh->GetNE(); ++element_id) {
const int attribute = m_fem.mesh->GetAttribute(element_id);
if (attribute <= 0 || attribute > m_stellar_marker.Size() ||
m_stellar_marker[attribute - 1] == 0) {
if (attribute <= 0 || attribute > m_stellar_marker.Size() || m_stellar_marker[attribute - 1] == 0) {
continue;
}
m_elements.emplace_back();
ElementPAData &data = m_elements.back();
ElementPAData &data = m_elements.back();
data.element_id = element_id;
data.element_id = element_id;
data.density_dof_transformation =
m_fem.densityFes->GetElementDofs(element_id, data.density_dofs);
data.density_dof_transformation = m_fem.densityFes->GetElementDofs(element_id, data.density_dofs);
data.potential_dof_transformation =
m_fem.gravityPotentialFes->GetElementDofs(
element_id, data.potential_dofs
);
m_fem.gravityPotentialFes->GetElementDofs(element_id, data.potential_dofs);
const mfem::FiniteElement &density_element =
*m_fem.densityFes->GetFE(element_id);
const mfem::FiniteElement &density_element = *m_fem.densityFes->GetFE(element_id);
const mfem::FiniteElement &potential_element =
*m_fem.gravityPotentialFes->GetFE(element_id);
const mfem::FiniteElement &potential_element = *m_fem.gravityPotentialFes->GetFE(element_id);
mfem::ElementTransformation &transformation =
*m_fem.mesh->GetElementTransformation(element_id);
mfem::ElementTransformation &transformation = *m_fem.mesh->GetElementTransformation(element_id);
const mfem::IntegrationRule &integration_rule = get_source_rule(
m_fem, density_element, potential_element, transformation
);
const mfem::IntegrationRule &integration_rule =
get_source_rule(m_fem, density_element, potential_element, transformation);
const int quadrature_point_count = integration_rule.GetNPoints();
@@ -411,24 +328,17 @@ namespace mean_field::operators {
const int potential_dof_count = potential_element.GetDof();
data.density_basis.SetSize(
quadrature_point_count, density_dof_count
);
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
data.potential_basis.SetSize(
quadrature_point_count, potential_dof_count
);
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
data.quadrature_data.SetSize(quadrature_point_count);
mfem::Vector density_shape(density_dof_count);
mfem::Vector potential_shape(potential_dof_count);
for (int quadrature_point = 0;
quadrature_point < quadrature_point_count;
++quadrature_point) {
const mfem::IntegrationPoint &integration_point =
integration_rule.IntPoint(quadrature_point);
for (int quadrature_point = 0; quadrature_point < quadrature_point_count; ++quadrature_point) {
const mfem::IntegrationPoint &integration_point = integration_rule.IntPoint(quadrature_point);
transformation.SetIntPoint(&integration_point);
@@ -436,44 +346,34 @@ namespace mean_field::operators {
// including the finite-element map type.
density_element.CalcPhysShape(transformation, density_shape);
potential_element.CalcPhysShape(
transformation, potential_shape
);
potential_element.CalcPhysShape(transformation, potential_shape);
for (int i = 0; i < density_dof_count; ++i) {
data.density_basis(quadrature_point, i) = density_shape(i);
}
for (int i = 0; i < potential_dof_count; ++i) {
data.potential_basis(quadrature_point, i) =
potential_shape(i);
data.potential_basis(quadrature_point, i) = potential_shape(i);
}
const double coefficient_value =
source_coefficient.Eval(transformation, integration_point);
const double coefficient_value = source_coefficient.Eval(transformation, integration_point);
transformation.SetIntPoint(&integration_point);
const double quadrature_value = integration_point.weight *
transformation.Weight() *
coefficient_value;
const double quadrature_value = integration_point.weight * transformation.Weight() * coefficient_value;
MFEM_VERIFY(
std::isfinite(quadrature_value) && quadrature_value > 0.0,
"Prepared gravity source operator encountered invalid "
"quadrature data on element "
<< element_id << ", quadrature point "
<< quadrature_point << "."
<< element_id << ", quadrature point " << quadrature_point << "."
);
data.quadrature_data(quadrature_point) = quadrature_value;
}
}
MFEM_VERIFY(
!m_elements.empty(),
"PreparedMappedGravitySourceOperator found no stellar elements."
);
MFEM_VERIFY(!m_elements.empty(), "PreparedMappedGravitySourceOperator found no stellar elements.");
m_is_prepared = true;
++m_preparation_count;
@@ -483,15 +383,13 @@ namespace mean_field::operators {
mfem::Vector &action
) const {
MFEM_VERIFY(
m_is_prepared,
"PreparedMappedGravitySourceOperator must be prepared before "
"Mult is called."
m_is_prepared, "PreparedMappedGravitySourceOperator must be prepared before "
"Mult is called."
);
MFEM_VERIFY(
density_true.Size() == Width(),
"PreparedMappedGravitySourceOperator received a density vector "
"with the wrong size."
density_true.Size() == Width(), "PreparedMappedGravitySourceOperator received a density vector "
"with the wrong size."
);
mfem::Vector density_local;
@@ -509,9 +407,7 @@ namespace mean_field::operators {
density_local.GetSubVector(data.density_dofs, element_density);
if (data.density_dof_transformation != nullptr) {
data.density_dof_transformation->InvTransformPrimal(
element_density
);
data.density_dof_transformation->InvTransformPrimal(element_density);
}
quadrature_density.SetSize(data.quadrature_data.Size());
@@ -527,14 +423,10 @@ namespace mean_field::operators {
element_action.SetSize(data.potential_dofs.Size());
// B_potential^T * D * B_density * x_e
data.potential_basis.MultTranspose(
quadrature_density, element_action
);
data.potential_basis.MultTranspose(quadrature_density, element_action);
if (data.potential_dof_transformation != nullptr) {
data.potential_dof_transformation->TransformDual(
element_action
);
data.potential_dof_transformation->TransformDual(element_action);
}
local_action.AddElementVector(data.potential_dofs, element_action);
@@ -548,22 +440,18 @@ namespace mean_field::operators {
mfem::Vector &action
) const {
MFEM_VERIFY(
m_is_prepared,
"PreparedMappedGravitySourceOperator must be prepared before "
"MultTranspose is called."
m_is_prepared, "PreparedMappedGravitySourceOperator must be prepared before "
"MultTranspose is called."
);
MFEM_VERIFY(
potential_true.Size() == Height(),
"PreparedMappedGravitySourceOperator received a potential vector "
"with the wrong size."
potential_true.Size() == Height(), "PreparedMappedGravitySourceOperator received a potential vector "
"with the wrong size."
);
mfem::Vector potential_local;
true_to_local(
*m_fem.gravityPotentialFes, potential_true, potential_local
);
true_to_local(*m_fem.gravityPotentialFes, potential_true, potential_local);
mfem::Vector local_action(m_fem.densityFes->GetVSize());
local_action = 0.0;
@@ -573,14 +461,10 @@ namespace mean_field::operators {
mfem::Vector element_action;
for (const ElementPAData &data : m_elements) {
potential_local.GetSubVector(
data.potential_dofs, element_potential
);
potential_local.GetSubVector(data.potential_dofs, element_potential);
if (data.potential_dof_transformation != nullptr) {
data.potential_dof_transformation->InvTransformPrimal(
element_potential
);
data.potential_dof_transformation->InvTransformPrimal(element_potential);
}
quadrature_potential.SetSize(data.quadrature_data.Size());
@@ -593,9 +477,7 @@ namespace mean_field::operators {
element_action.SetSize(data.density_dofs.Size());
data.density_basis.MultTranspose(
quadrature_potential, element_action
);
data.density_basis.MultTranspose(quadrature_potential, element_action);
if (data.density_dof_transformation != nullptr) {
data.density_dof_transformation->TransformDual(element_action);
@@ -610,8 +492,7 @@ namespace mean_field::operators {
return m_is_prepared;
}
std::uint64_t
PreparedMappedGravitySourceOperator::GetPreparationCount() const noexcept {
std::uint64_t PreparedMappedGravitySourceOperator::GetPreparationCount() const noexcept {
return m_preparation_count;
}
} // namespace mean_field::operators