feat(support): continued migration to new field dof support system

mass normaliztion, gravity, displacement, and hydrostatic equilibrium are now migrated
This commit is contained in:
2026-08-24 15:44:24 -04:00
parent 0f3ca8050b
commit 177ae8b38a
48 changed files with 1738 additions and 935 deletions

View File

@@ -7,72 +7,55 @@ module mean_field;
import :operators.context.gravity_field;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
void validate_displacement(
const mean_field::fem::FEM &f,
const mfem::Vector &displacement_true
const mean_field::field::FieldDofMap &displacement_map,
const mfem::Vector &displacement
) {
MFEM_VERIFY(
f.displacementFes != nullptr, "GravityFieldGeometryContext requires the "
"displacement finite-element space."
);
MFEM_VERIFY(
displacement_true.Size() == f.displacementFes->GetTrueVSize(),
displacement.Size() == displacement_map.reduced_size(),
"GravityFieldGeometryContext received a displacement vector with "
"the "
"wrong size."
);
for (int i = 0; i < displacement_true.Size(); ++i) {
for (int i = 0; i < displacement.Size(); ++i) {
MFEM_VERIFY(
std::isfinite(displacement_true(i)), "GravityFieldGeometryContext received a non-finite "
"displacement "
"value."
std::isfinite(displacement(i)), "GravityFieldGeometryContext received a non-finite "
"displacement "
"value."
);
}
}
void validate_linearization_state(
const mean_field::fem::FEM &f,
const mean_field::field::FieldDofMap &density_map,
const mean_field::field::FieldDofMap &displacement_map,
const mean_field::field::FieldDofMap &gravity_gradient_map,
const mean_field::field::FieldDofMap &gravity_potential_map,
const mean_field::operators::context::gravity_field::GravityFieldStateView &state
) {
MFEM_VERIFY(
f.densityFes != nullptr, "GravityFieldLinearizationContext "
"requires the density finite-element "
"space."
);
MFEM_VERIFY(
f.gravityPotentialFes != nullptr, "GravityFieldLinearizationContext requires the gravity-potential "
"finite-element space."
);
MFEM_VERIFY(
f.gravityFluxFes != nullptr, "GravityFieldLinearizationContext requires the "
"gravity-gradient finite-element space."
);
MFEM_VERIFY(
f.displacementFes != nullptr, "GravityFieldLinearizationContext requires "
"the displacement finite-element space."
);
MFEM_VERIFY(
state.density.Size() == f.densityFes->GetTrueVSize(),
state.density.Size() == density_map.reduced_size(),
"GravityFieldLinearizationContext received a density vector with "
"the "
"wrong size."
);
MFEM_VERIFY(
state.displacement.Size() == f.displacementFes->GetTrueVSize(),
state.displacement.Size() == displacement_map.reduced_size(),
"GravityFieldLinearizationContext received a displacement vector "
"with "
"the wrong size."
);
MFEM_VERIFY(
state.gravity_gradient.Size() == f.gravityFluxFes->GetTrueVSize(),
state.gravity_gradient.Size() == gravity_gradient_map.reduced_size(),
"GravityFieldLinearizationContext received a gravity-gradient "
"vector "
"with the wrong size."
);
MFEM_VERIFY(
state.gravity_potential.Size() == f.gravityPotentialFes->GetTrueVSize(),
state.gravity_potential.Size() == gravity_potential_map.reduced_size(),
"GravityFieldLinearizationContext received a gravity-potential "
"vector "
"with the wrong size."
@@ -116,7 +99,12 @@ namespace mean_field::operators::context::gravity_field {
const mapping::DomainMapperStateless &domain_mapper
)
: m_fem(f),
m_domain_mapper(domain_mapper) {
m_domain_mapper(domain_mapper),
m_displacement_map(
field::make_field_dof_map<
field::Displacement,
DomainSchema>(*f.displacementFes)
) {
MFEM_VERIFY(f.mesh != nullptr, "GravityFieldGeometryContext requires a mesh.");
MFEM_VERIFY(
f.gravityFluxFes != nullptr, "GravityFieldGeometryContext requires the "
@@ -153,11 +141,11 @@ namespace mean_field::operators::context::gravity_field {
}
GravityFieldGeometryPreparation GravityFieldGeometryContext::Prepare(
const mfem::Vector &displacement_true,
const mfem::Vector &displacement,
const DiscretizationRevision discretization_revision,
const DisplacementRevision displacement_revision
) {
validate_displacement(m_fem, displacement_true);
validate_displacement(m_displacement_map, displacement);
if (m_is_prepared) {
MFEM_VERIFY(
@@ -185,8 +173,8 @@ namespace mean_field::operators::context::gravity_field {
auto mass_operator = std::make_unique<PreparedMappedHDivMassOperator>(m_fem, m_domain_mapper);
auto source_operator = std::make_unique<PreparedMappedGravitySourceOperator>(m_fem, m_domain_mapper);
mass_operator->Prepare(displacement_true);
source_operator->Prepare(displacement_true);
mass_operator->Prepare(displacement);
source_operator->Prepare(displacement);
m_mass_operator = std::move(mass_operator);
m_source_operator = std::move(source_operator);
@@ -204,14 +192,15 @@ namespace mean_field::operators::context::gravity_field {
"operator."
);
m_mass_operator->Prepare(displacement_true);
m_source_operator->Prepare(displacement_true);
m_mass_operator->Prepare(displacement);
m_source_operator->Prepare(displacement);
preparation.rebuilt_mass_operator = true;
preparation.rebuilt_source_operator = true;
}
m_displacement_true = displacement_true;
m_displacement_true.SetSize(m_displacement_map.full_size());
m_displacement_map.scatter(displacement, m_displacement_true);
m_discretization_revision = discretization_revision;
m_displacement_revision = displacement_revision;
m_is_prepared = true;
@@ -242,7 +231,7 @@ namespace mean_field::operators::context::gravity_field {
return *m_source_operator;
}
const mfem::Vector &GravityFieldGeometryContext::GetDisplacement() const {
const mfem::Vector &GravityFieldGeometryContext::GetDisplacementTrue() const {
MFEM_VERIFY(
m_is_prepared, "GravityFieldGeometryContext must be prepared before "
"accessing its displacement."
@@ -250,6 +239,10 @@ namespace mean_field::operators::context::gravity_field {
return m_displacement_true;
}
const field::FieldDofMap &GravityFieldGeometryContext::GetDisplacementMap() const noexcept {
return m_displacement_map;
}
DiscretizationRevision GravityFieldGeometryContext::GetDiscretizationRevision() const noexcept {
return m_discretization_revision;
}
@@ -270,6 +263,21 @@ namespace mean_field::operators::context::gravity_field {
m_geometry_context(
f,
domain_mapper
),
m_density_map(
field::make_field_dof_map<
field::Density,
DomainSchema>(*f.densityFes)
),
m_gravity_gradient_map(
field::make_field_dof_map<
field::Gravity,
DomainSchema>(*f.gravityFluxFes)
),
m_gravity_potential_map(
field::make_field_dof_map<
field::Gravity,
DomainSchema>(*f.gravityPotentialFes)
) {
MFEM_VERIFY(
f.densityFes != nullptr, "GravityFieldLinearizationContext "
@@ -294,7 +302,10 @@ namespace mean_field::operators::context::gravity_field {
const GravityFieldStateView &state,
const GravityFieldRevisions &revisions
) {
validate_linearization_state(m_fem, state);
validate_linearization_state(
m_density_map, m_geometry_context.GetDisplacementMap(), m_gravity_gradient_map, m_gravity_potential_map,
state
);
if (m_is_prepared) {
MFEM_VERIFY(
@@ -338,12 +349,14 @@ namespace mean_field::operators::context::gravity_field {
m_geometry_context.Prepare(state.displacement, revisions.discretization, revisions.displacement);
if (density_changed) {
m_density_true = state.density;
m_density_true.SetSize(m_density_map.full_size());
m_density_map.scatter(state.density, m_density_true);
report.updated_density = true;
}
if (gravity_gradient_changed) {
m_gravity_gradient_true = state.gravity_gradient;
m_gravity_gradient_true.SetSize(m_gravity_gradient_map.full_size());
m_gravity_gradient_map.scatter(state.gravity_gradient, m_gravity_gradient_true);
report.updated_gravity_gradient = true;
}
@@ -361,7 +374,7 @@ namespace mean_field::operators::context::gravity_field {
return m_geometry_context;
}
const mfem::Vector &GravityFieldLinearizationContext::GetDensity() const {
const mfem::Vector &GravityFieldLinearizationContext::GetDensityTrue() const {
MFEM_VERIFY(
m_is_prepared, "GravityFieldLinearizationContext must be prepared "
"before accessing its density."
@@ -369,7 +382,7 @@ namespace mean_field::operators::context::gravity_field {
return m_density_true;
}
const mfem::Vector &GravityFieldLinearizationContext::GetGravityGradient() const {
const mfem::Vector &GravityFieldLinearizationContext::GetGravityGradientTrue() const {
MFEM_VERIFY(
m_is_prepared, "GravityFieldLinearizationContext must be prepared "
"before accessing its gravity gradient."
@@ -377,6 +390,22 @@ namespace mean_field::operators::context::gravity_field {
return m_gravity_gradient_true;
}
const field::FieldDofMap &GravityFieldLinearizationContext::GetDensityMap() const noexcept {
return m_density_map;
}
const field::FieldDofMap &GravityFieldLinearizationContext::GetDisplacementMap() const noexcept {
return m_geometry_context.GetDisplacementMap();
}
const field::FieldDofMap &GravityFieldLinearizationContext::GetGravityGradientMap() const noexcept {
return m_gravity_gradient_map;
}
const field::FieldDofMap &GravityFieldLinearizationContext::GetGravityPotentialMap() const noexcept {
return m_gravity_potential_map;
}
const GravityFieldRevisions &GravityFieldLinearizationContext::GetRevisions() const {
MFEM_VERIFY(
m_is_prepared, "GravityFieldLinearizationContext must be prepared "

View File

@@ -9,6 +9,8 @@ module mean_field;
import :operators.context.hydrostatic_equilibrium;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
void validate_finite_vector(
const mfem::Vector &vector,
const char *message
@@ -19,38 +21,24 @@ namespace {
}
void validate_state(
const mean_field::fem::FEM &f,
const mean_field::field::FieldDofMap &enthalpyMap,
const mean_field::field::FieldDofMap &gravityPotentialMap,
const mean_field::field::FieldDofMap &displacementMap,
const mean_field::operators::context::hydrostatic::HydrostaticEquilibriumStateView &state
) {
MFEM_VERIFY(
f.enthalpyFes != nullptr, "HydrostaticEquilibriumContext requires the "
"enthalpy finite-element space."
state.enthalpy.Size() == enthalpyMap.reduced_size(), "HydrostaticEquilibriumContext received a supported "
"enthalpy vector with the wrong size."
);
MFEM_VERIFY(
f.gravityPotentialFes != nullptr, "HydrostaticEquilibriumContext requires the "
"gravity-potential finite-element space."
state.gravityPotential.Size() == gravityPotentialMap.reduced_size(),
"HydrostaticEquilibriumContext received a supported gravity-potential vector with the wrong size."
);
MFEM_VERIFY(
f.displacementFes != nullptr, "HydrostaticEquilibriumContext requires the "
"displacement finite-element space."
);
MFEM_VERIFY(
state.enthalpy.Size() == f.enthalpyFes->GetTrueVSize(), "HydrostaticEquilibriumContext received an "
"enthalpy vector with the wrong size."
);
MFEM_VERIFY(
state.gravityPotential.Size() == f.gravityPotentialFes->GetTrueVSize(),
"HydrostaticEquilibriumContext received a "
"gravity-potential vector with the wrong size."
);
MFEM_VERIFY(
state.displacement.Size() == f.displacementFes->GetTrueVSize(), "HydrostaticEquilibriumContext received a "
"displacement vector with the wrong size."
state.displacement.Size() == displacementMap.reduced_size(),
"HydrostaticEquilibriumContext received a supported displacement vector with the wrong size."
);
validate_finite_vector(
@@ -90,7 +78,16 @@ namespace mean_field::operators::context::hydrostatic {
const mapping::DomainMapperStateless &domainMapper
)
: m_f(f),
m_domainMapper(domainMapper) {
m_domainMapper(domainMapper),
m_enthalpyMap(
field::make_field_dof_map<field::Enthalpy, DomainSchema>(*f.enthalpyFes)
),
m_gravityPotentialMap(
field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes)
),
m_displacementMap(
field::make_field_dof_map<field::Displacement, DomainSchema>(*f.displacementFes)
) {
MFEM_VERIFY(m_f.mesh != nullptr, "HydrostaticEquilibriumContext requires a mesh.");
MFEM_VERIFY(
@@ -113,13 +110,17 @@ namespace mean_field::operators::context::hydrostatic {
"domain-mapper dimension does not match the mesh "
"dimension."
);
m_baseEnthalpyTrue.SetSize(m_enthalpyMap.full_size());
m_baseGravityPotentialTrue.SetSize(m_gravityPotentialMap.full_size());
m_displacementTrue.SetSize(m_displacementMap.full_size());
}
HydrostaticPreparationReport HydrostaticEquilibriumContext::Prepare(
const HydrostaticEquilibriumStateView &state,
const HydrostaticEquilibriumDependencies &dependencies
) {
validate_state(m_f, state);
validate_state(m_enthalpyMap, m_gravityPotentialMap, m_displacementMap, state);
if (m_isPrepared) {
validate_dependency_transition(
@@ -188,18 +189,18 @@ namespace mean_field::operators::context::hydrostatic {
report.preparedBaseState = baseStatePreparationRequired;
if (staticChanged || enthalpyChanged) {
m_baseEnthalpyTrue = state.enthalpy;
m_enthalpyMap.scatter(state.enthalpy, m_baseEnthalpyTrue);
report.updatedEnthalpy = true;
}
if (staticChanged || gravityPotentialChanged) {
m_baseGravityPotentialTrue = state.gravityPotential;
m_gravityPotentialMap.scatter(state.gravityPotential, m_baseGravityPotentialTrue);
report.updatedGravityPotential = true;
}
if (geometryPreparationRequired) {
m_displacementTrue = state.displacement;
m_displacementMap.scatter(state.displacement, m_displacementTrue);
report.updatedDisplacement = true;
}
@@ -249,6 +250,18 @@ namespace mean_field::operators::context::hydrostatic {
return m_statistics;
}
const field::FieldDofMap &HydrostaticEquilibriumContext::GetEnthalpyMap() const noexcept {
return m_enthalpyMap;
}
const field::FieldDofMap &HydrostaticEquilibriumContext::GetGravityPotentialMap() const noexcept {
return m_gravityPotentialMap;
}
const field::FieldDofMap &HydrostaticEquilibriumContext::GetDisplacementMap() const noexcept {
return m_displacementMap;
}
const mfem::Vector &HydrostaticEquilibriumContext::GetBaseEnthalpyTrue() const {
VerifyPrepared();
return m_baseEnthalpyTrue;

View File

@@ -9,6 +9,8 @@ module mean_field;
import :operators.context.rotational_displacement_force;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
void validate_finite_vector(
const mfem::Vector &vector,
const char *message
@@ -33,7 +35,17 @@ namespace mean_field::operators::context::rotational_displacement_force {
const fem::FEM &f,
const mapping::DomainMapperStateless &domainMapper
)
: m_f(f) {
: m_f(f),
m_densityMap(
field::make_field_dof_map<
field::Density,
DomainSchema>(*f.densityFes)
),
m_displacementMap(
field::make_field_dof_map<
field::Displacement,
DomainSchema>(*f.displacementFes)
) {
MFEM_VERIFY(
m_f.mesh != nullptr, "RotationalDisplacementForceLinearizationContext requires a "
"mesh."
@@ -61,13 +73,13 @@ namespace mean_field::operators::context::rotational_displacement_force {
const RotationalDisplacementForceDependencies &dependencies
) {
MFEM_VERIFY(
state.density.Size() == m_f.densityFes->GetTrueVSize(),
state.density.Size() == m_densityMap.reduced_size(),
"RotationalDisplacementForceLinearizationContext received a "
"density vector with the wrong size."
);
MFEM_VERIFY(
state.displacement.Size() == m_f.displacementFes->GetTrueVSize(),
state.displacement.Size() == m_displacementMap.reduced_size(),
"RotationalDisplacementForceLinearizationContext received a "
"displacement vector with the wrong size."
);
@@ -132,12 +144,14 @@ namespace mean_field::operators::context::rotational_displacement_force {
report.preparedBaseState = baseStatePreparationRequired;
if (discretizationChanged || densityChanged) {
m_baseDensityTrue = state.density;
m_baseDensityTrue.SetSize(m_densityMap.full_size());
m_densityMap.scatter(state.density, m_baseDensityTrue);
report.updatedDensity = true;
}
if (geometryPreparationRequired) {
m_displacementTrue = state.displacement;
m_displacementTrue.SetSize(m_displacementMap.full_size());
m_displacementMap.scatter(state.displacement, m_displacementTrue);
report.updatedDisplacement = true;
}
@@ -194,6 +208,14 @@ namespace mean_field::operators::context::rotational_displacement_force {
return m_displacementTrue;
}
const field::FieldDofMap &RotationalDisplacementForceLinearizationContext::GetDensityMap() const noexcept {
return m_densityMap;
}
const field::FieldDofMap &RotationalDisplacementForceLinearizationContext::GetDisplacementMap() const noexcept {
return m_displacementMap;
}
void RotationalDisplacementForceLinearizationContext::VerifyPrepared() const {
MFEM_VERIFY(
m_isPrepared, "RotationalDisplacementForceLinearizationContext has not been "