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 "

View File

@@ -12,18 +12,16 @@ import :operators.kernels.gravity_field;
namespace {
using namespace mean_field;
int get_state_width(const mfem::Array<int> &state_true_offsets) {
MFEM_VERIFY(state_true_offsets.Size() >= 2, "The coupled state requires at least one block.");
MFEM_VERIFY(state_true_offsets[0] == 0, "The coupled state offsets must begin at zero.");
int get_state_width(const mfem::Array<int> &state_offsets) {
MFEM_VERIFY(state_offsets.Size() >= 2, "The coupled state requires at least one block.");
MFEM_VERIFY(state_offsets[0] == 0, "The coupled state offsets must begin at zero.");
for (int i = 0; i < state_true_offsets.Size() - 1; ++i) {
MFEM_VERIFY(
state_true_offsets[i + 1] >= state_true_offsets[i], "The coupled state offsets must be nondecreasing."
);
for (int i = 0; i < state_offsets.Size() - 1; ++i) {
MFEM_VERIFY(state_offsets[i + 1] >= state_offsets[i], "The coupled state offsets must be nondecreasing.");
}
MFEM_VERIFY(state_true_offsets.Last() > 0, "The coupled state cannot be empty.");
return state_true_offsets.Last();
MFEM_VERIFY(state_offsets.Last() > 0, "The coupled state cannot be empty.");
return state_offsets.Last();
}
int get_gravity_residual_height(const fem::FEM &f) {
@@ -37,29 +35,33 @@ namespace {
"space (L2: Lebesgue "
"space of square-integrable functions)."
);
return f.gravityFluxFes->GetTrueVSize() + f.gravityPotentialFes->GetTrueVSize();
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
return field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityFluxFes).reduced_size() +
field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes).reduced_size();
}
mfem::Array<int> make_gravity_residual_offsets(const fem::FEM &f) {
mfem::Array<int> offsets(operators::gravity_residual_block_count + 1);
offsets[0] = 0;
offsets[1] = f.gravityFluxFes->GetTrueVSize();
offsets[2] = offsets[1] + f.gravityPotentialFes->GetTrueVSize();
mfem::Array<int> offsets(utils::blocks::gravity_field_form::residual_block_count + 1);
offsets[0] = 0;
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
offsets[1] = field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityFluxFes).reduced_size();
offsets[2] =
offsets[1] + field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes).reduced_size();
return offsets;
}
template <int index>
int get_state_block_size(
const mfem::Array<int> &state_true_offsets,
const mfem::Array<int> &state_offsets,
const utils::blocks::value_block<index>
) {
MFEM_VERIFY(index + 1 < state_true_offsets.Size(), "Value block is not present in the state offsets.");
return state_true_offsets[index + 1] - state_true_offsets[index];
MFEM_VERIFY(index + 1 < state_offsets.Size(), "Value block is not present in the state offsets.");
return state_offsets[index + 1] - state_offsets[index];
}
void validate_state_offsets(
const fem::FEM &f,
const mfem::Array<int> &state_true_offsets
const mfem::Array<int> &state_offsets
) {
MFEM_VERIFY(f.densityFes != nullptr, "GravityFieldOperator requires the density finite-element space.");
MFEM_VERIFY(
@@ -78,26 +80,32 @@ namespace {
utils::blocks::get_value_block<form>(utils::blocks::gravity_field.poisson_term);
MFEM_VERIFY(
state_true_offsets.Size() == form::value_block_count + 1,
state_offsets.Size() == form::value_block_count + 1,
"The gravity state offsets do not match gravity_field_form."
);
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
const auto density_map = field::make_field_dof_map<field::Density, DomainSchema>(*f.densityFes);
const auto displacement_map = field::make_field_dof_map<field::Displacement, DomainSchema>(*f.displacementFes);
const auto flux_map = field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityFluxFes);
const auto potential_map = field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes);
MFEM_VERIFY(
get_state_block_size(state_true_offsets, density_block) == f.densityFes->GetTrueVSize(),
get_state_block_size(state_offsets, density_block) == density_map.reduced_size(),
"The density block does not match the density finite-element space."
);
MFEM_VERIFY(
get_state_block_size(state_true_offsets, displacement_block) == f.displacementFes->GetTrueVSize(),
get_state_block_size(state_offsets, displacement_block) == displacement_map.reduced_size(),
"The displacement block does not match the displacement "
"finite-element "
"space."
);
MFEM_VERIFY(
get_state_block_size(state_true_offsets, gravity_gradient_block) == f.gravityFluxFes->GetTrueVSize(),
get_state_block_size(state_offsets, gravity_gradient_block) == flux_map.reduced_size(),
"The gravity-gradient block does not match the RT finite-element "
"space."
);
MFEM_VERIFY(
get_state_block_size(state_true_offsets, gravity_potential_block) == f.gravityPotentialFes->GetTrueVSize(),
get_state_block_size(state_offsets, gravity_potential_block) == potential_map.reduced_size(),
"The gravity-potential block does not match the potential "
"finite-element space."
);
@@ -162,18 +170,18 @@ namespace mean_field::operators {
fem::FEM &f,
const mapping::DomainMapperStateless &domain_mapper,
context::gravity_field::GravityFieldLinearizationContext &linearization_context,
const mfem::Array<int> &state_true_offsets,
const mfem::Array<int> &state_offsets,
GravityFieldJacobianOperator &jacobian
)
: Operator(
get_gravity_residual_height(f),
get_state_width(state_true_offsets)
get_state_width(state_offsets)
),
m_fem(f),
m_domain_mapper(domain_mapper),
m_linearization_context(linearization_context),
m_state_true_offsets(state_true_offsets),
m_residual_true_offsets(make_gravity_residual_offsets(f)),
m_state_offsets(state_offsets),
m_residual_offsets(make_gravity_residual_offsets(f)),
m_jacobian(jacobian) {
MFEM_VERIFY(f.mesh != nullptr, "GravityFieldOperator requires a mesh.");
MFEM_VERIFY(
@@ -198,7 +206,7 @@ namespace mean_field::operators {
"dimension."
);
validate_state_offsets(f, m_state_true_offsets);
validate_state_offsets(f, m_state_offsets);
validate_gravity_context(f);
bool has_vacuum_domain = false;
@@ -212,11 +220,9 @@ namespace mean_field::operators {
MFEM_VERIFY(has_vacuum_domain, "GravityFieldOperator requires a compactified vacuum domain.");
MFEM_VERIFY(
m_residual_true_offsets.Last() == Height(), "The gravity residual offsets do not match the operator height."
);
MFEM_VERIFY(
m_state_true_offsets.Last() == Width(), "The coupled state offsets do not match the operator width."
m_residual_offsets.Last() == Height(), "The gravity residual offsets do not match the operator height."
);
MFEM_VERIFY(m_state_offsets.Last() == Width(), "The coupled state offsets do not match the operator width.");
}
context::gravity_field::GravityFieldPreparationReport GravityFieldOperator::Prepare(
@@ -238,12 +244,11 @@ namespace mean_field::operators {
"preparation state with the wrong size."
);
const mfem::Vector density = make_read_only_value_view(state, m_state_true_offsets, density_block);
const mfem::Vector displacement = make_read_only_value_view(state, m_state_true_offsets, displacement_block);
const mfem::Vector gravity_gradient =
make_read_only_value_view(state, m_state_true_offsets, gravity_gradient_block);
const mfem::Vector density = make_read_only_value_view(state, m_state_offsets, density_block);
const mfem::Vector displacement = make_read_only_value_view(state, m_state_offsets, displacement_block);
const mfem::Vector gravity_gradient = make_read_only_value_view(state, m_state_offsets, gravity_gradient_block);
const mfem::Vector gravity_potential =
make_read_only_value_view(state, m_state_true_offsets, gravity_potential_block);
make_read_only_value_view(state, m_state_offsets, gravity_potential_block);
return m_linearization_context.Prepare(
{.density = density,
@@ -254,12 +259,12 @@ namespace mean_field::operators {
);
}
const mfem::Array<int> &GravityFieldOperator::GetStateTrueOffsets() const noexcept {
return m_state_true_offsets;
const mfem::Array<int> &GravityFieldOperator::GetStateOffsets() const noexcept {
return m_state_offsets;
}
const mfem::Array<int> &GravityFieldOperator::GetResidualTrueOffsets() const noexcept {
return m_residual_true_offsets;
const mfem::Array<int> &GravityFieldOperator::GetResidualOffsets() const noexcept {
return m_residual_offsets;
}
void GravityFieldOperator::ApplyGravityUnknowns(
@@ -277,12 +282,12 @@ namespace mean_field::operators {
MFEM_VERIFY(geometry_context.IsPrepared(), "GravityFieldOperator received an unprepared geometry context.");
MFEM_VERIFY(
gravity_gradient.Size() == m_fem.gravityFluxFes->GetTrueVSize(),
gravity_gradient.Size() == geometry_context.GetMassOperator().GetFluxMap().reduced_size(),
"GravityFieldOperator received a gravity-gradient vector with the "
"wrong size."
);
MFEM_VERIFY(
gravity_potential.Size() == m_fem.gravityPotentialFes->GetTrueVSize(),
gravity_potential.Size() == geometry_context.GetSourceOperator().GetPotentialMap().reduced_size(),
"GravityFieldOperator received a gravity-potential vector with the "
"wrong size."
);
@@ -291,15 +296,25 @@ namespace mean_field::operators {
action = 0.0;
mfem::Vector gravity_gradient_action =
make_residual_view(action, m_residual_true_offsets, gravity_gradient_residual_block);
make_residual_view(action, m_residual_offsets, gravity_gradient_residual_block);
mfem::Vector gravity_poisson_action =
make_residual_view(action, m_residual_true_offsets, gravity_poisson_residual_block);
mfem::Vector transpose_divergence_action(gravity_gradient_action.Size());
make_residual_view(action, m_residual_offsets, gravity_poisson_residual_block);
const field::FieldDofMap &flux_map = geometry_context.GetMassOperator().GetFluxMap();
const field::FieldDofMap &potential_map = geometry_context.GetSourceOperator().GetPotentialMap();
mfem::Vector potential_true(potential_map.full_size());
mfem::Vector transpose_divergence_action_true(flux_map.full_size());
mfem::Vector transpose_divergence_action(flux_map.reduced_size());
mfem::Vector gradient_true(flux_map.full_size());
mfem::Vector divergence_action_true(potential_map.full_size());
geometry_context.GetMassOperator().Mult(gravity_gradient, gravity_gradient_action);
m_fem.gravityContext.BT->Mult(gravity_potential, transpose_divergence_action);
potential_map.scatter(gravity_potential, potential_true);
m_fem.gravityContext.BT->Mult(potential_true, transpose_divergence_action_true);
flux_map.gather(transpose_divergence_action_true, transpose_divergence_action);
gravity_gradient_action += transpose_divergence_action;
m_fem.gravityContext.b_form->Mult(gravity_gradient, gravity_poisson_action);
flux_map.scatter(gravity_gradient, gradient_true);
m_fem.gravityContext.b_form->Mult(gradient_true, divergence_action_true);
potential_map.gather(divergence_action_true, gravity_poisson_action);
}
void GravityFieldOperator::ApplyDensitySource(
@@ -314,7 +329,7 @@ namespace mean_field::operators {
MFEM_VERIFY(geometry_context.IsPrepared(), "GravityFieldOperator received an unprepared geometry context.");
MFEM_VERIFY(
density.Size() == m_fem.densityFes->GetTrueVSize(),
density.Size() == geometry_context.GetSourceOperator().GetDensityMap().reduced_size(),
"GravityFieldOperator received a density vector with the wrong "
"size."
);
@@ -323,7 +338,7 @@ namespace mean_field::operators {
action = 0.0;
mfem::Vector gravity_poisson_action =
make_residual_view(action, m_residual_true_offsets, gravity_poisson_residual_block);
make_residual_view(action, m_residual_offsets, gravity_poisson_residual_block);
geometry_context.GetSourceOperator().Mult(density, gravity_poisson_action);
}
@@ -346,11 +361,10 @@ namespace mean_field::operators {
m_linearization_context.IsPrepared(), "GravityFieldOperator must be prepared before Mult is called."
);
const mfem::Vector density = make_read_only_value_view(state, m_state_true_offsets, density_block);
const mfem::Vector gravity_gradient =
make_read_only_value_view(state, m_state_true_offsets, gravity_gradient_block);
const mfem::Vector density = make_read_only_value_view(state, m_state_offsets, density_block);
const mfem::Vector gravity_gradient = make_read_only_value_view(state, m_state_offsets, gravity_gradient_block);
const mfem::Vector gravity_potential =
make_read_only_value_view(state, m_state_true_offsets, gravity_potential_block);
make_read_only_value_view(state, m_state_offsets, gravity_potential_block);
const context::gravity_field::GravityFieldGeometryContext &geometry_context =
m_linearization_context.GetGeometryContext();
@@ -393,7 +407,7 @@ namespace mean_field::operators {
gravity_field_operator.Height()
),
m_gravity_field_operator(gravity_field_operator),
m_gravity_true_offsets(gravity_field_operator.GetResidualTrueOffsets()),
m_gravity_offsets(gravity_field_operator.GetResidualOffsets()),
m_gravity_field_geometry_context(gravity_field_geometry_context) {
using form = utils::blocks::gravity_field_form;
@@ -406,52 +420,48 @@ namespace mean_field::operators {
constexpr auto gravity_poisson_residual_block =
utils::blocks::get_residual_block<form>(utils::blocks::gravity_field.poisson_term);
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateTrueOffsets();
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateOffsets();
MFEM_VERIFY(
state_offsets.Size() == form::value_block_count + 1,
"ReducedGravityFieldOperator received an invalid full-state layout."
"ReducedGravityFieldOperator received an invalid coupled-state layout."
);
MFEM_VERIFY(
m_gravity_true_offsets.Size() == form::residual_block_count + 1,
m_gravity_offsets.Size() == form::residual_block_count + 1,
"ReducedGravityFieldOperator received an invalid gravity-residual "
"layout."
);
MFEM_VERIFY(state_offsets[0] == 0, "The full-state offsets must begin at zero.");
MFEM_VERIFY(m_gravity_true_offsets[0] == 0, "The reduced gravity offsets must begin at zero.");
MFEM_VERIFY(state_offsets[0] == 0, "The coupled-state offsets must begin at zero.");
MFEM_VERIFY(m_gravity_offsets[0] == 0, "The reduced gravity offsets must begin at zero.");
MFEM_VERIFY(
state_offsets.Last() == m_gravity_field_operator.Width(),
"The full-state offsets do not match the gravity-field operator "
"The coupled-state offsets do not match the gravity-field operator "
"width."
);
MFEM_VERIFY(
m_gravity_true_offsets.Last() == m_gravity_field_operator.Height(),
m_gravity_offsets.Last() == m_gravity_field_operator.Height(),
"The reduced gravity offsets do not match the gravity-field "
"operator "
"height."
);
MFEM_VERIFY(Width() == Height(), "ReducedGravityFieldOperator must be square.");
const int full_gradient_size =
const int state_gradient_size =
state_offsets[static_cast<int>(gravity_gradient_block) + 1] - state_offsets[gravity_gradient_block];
const int full_potential_size =
const int state_potential_size =
state_offsets[static_cast<int>(gravity_potential_block) + 1] - state_offsets[gravity_potential_block];
const int reduced_gradient_size =
m_gravity_true_offsets[static_cast<int>(gravity_gradient_residual_block) + 1] -
m_gravity_true_offsets[gravity_gradient_residual_block];
const int reduced_potential_size =
m_gravity_true_offsets[static_cast<int>(gravity_poisson_residual_block) + 1] -
m_gravity_true_offsets[gravity_poisson_residual_block];
const int gravity_gradient_size = m_gravity_offsets[static_cast<int>(gravity_gradient_residual_block) + 1] -
m_gravity_offsets[gravity_gradient_residual_block];
const int gravity_potential_size = m_gravity_offsets[static_cast<int>(gravity_poisson_residual_block) + 1] -
m_gravity_offsets[gravity_poisson_residual_block];
MFEM_VERIFY(
full_gradient_size == reduced_gradient_size,
"The reduced gravity-gradient block does not match the full-state "
"gravity-gradient block."
state_gradient_size == gravity_gradient_size, "The gravity-gradient block does not match the coupled-state "
"gravity-gradient block."
);
MFEM_VERIFY(
full_potential_size == reduced_potential_size,
"The reduced gravity-potential block does not match the Poisson "
"residual block."
state_potential_size == gravity_potential_size, "The gravity-potential block does not match the Poisson "
"residual block."
);
SetDisplacement(displacement);
@@ -475,10 +485,11 @@ namespace mean_field::operators {
}
m_gravity_field_geometry_context.Prepare(displacement, discretization_revision, displacement_revision);
m_displacement = displacement;
}
const mfem::Vector &ReducedGravityFieldOperator::GetDisplacement() const {
return m_gravity_field_geometry_context.GetDisplacement();
return m_displacement;
}
void ReducedGravityFieldOperator::BuildRightHandSide(
@@ -511,13 +522,13 @@ namespace mean_field::operators {
ValidateGravityState(gravity_state);
const mfem::Vector gravity_gradient_true =
make_read_only_residual_view(gravity_state, m_gravity_true_offsets, gravity_gradient_residual_block);
const mfem::Vector gravity_potential_true =
make_read_only_residual_view(gravity_state, m_gravity_true_offsets, gravity_poisson_residual_block);
const mfem::Vector gravity_gradient =
make_read_only_residual_view(gravity_state, m_gravity_offsets, gravity_gradient_residual_block);
const mfem::Vector gravity_potential =
make_read_only_residual_view(gravity_state, m_gravity_offsets, gravity_poisson_residual_block);
m_gravity_field_operator.ApplyGravityUnknowns(
gravity_gradient_true, gravity_potential_true, m_gravity_field_geometry_context, action
gravity_gradient, gravity_potential, m_gravity_field_geometry_context, action
);
MFEM_VERIFY(
@@ -543,8 +554,8 @@ namespace mean_field::operators {
return m_gravity_field_geometry_context;
}
const mfem::Array<int> &ReducedGravityFieldOperator::GetGravityTrueOffsets() const noexcept {
return m_gravity_true_offsets;
const mfem::Array<int> &ReducedGravityFieldOperator::GetGravityOffsets() const noexcept {
return m_gravity_offsets;
}
void ReducedGravityFieldOperator::ValidateDisplacement(const mfem::Vector &displacement) const {
@@ -553,7 +564,7 @@ namespace mean_field::operators {
constexpr auto displacement_block =
utils::blocks::get_value_block<form>(utils::blocks::displacement_field.geometry_term);
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateTrueOffsets();
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateOffsets();
const int expected_size =
state_offsets[static_cast<int>(displacement_block) + 1] - state_offsets[displacement_block];
@@ -577,7 +588,7 @@ namespace mean_field::operators {
constexpr auto density_block = utils::blocks::get_value_block<form>(utils::blocks::density_field.mass_term);
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateTrueOffsets();
const mfem::Array<int> &state_offsets = m_gravity_field_operator.GetStateOffsets();
const int expected_size = state_offsets[static_cast<int>(density_block) + 1] - state_offsets[density_block];
MFEM_VERIFY(

View File

@@ -89,28 +89,38 @@ namespace {
"form."
);
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
const auto density_map =
mean_field::field::make_field_dof_map<mean_field::field::Density, DomainSchema>(*f.densityFes);
const auto displacement_map =
mean_field::field::make_field_dof_map<mean_field::field::Displacement, DomainSchema>(*f.displacementFes);
const auto flux_map =
mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityFluxFes);
const auto potential_map =
mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityPotentialFes);
MFEM_VERIFY(
get_block_size(state_offsets, density_block) == f.densityFes->GetTrueVSize(),
get_block_size(state_offsets, density_block) == density_map.reduced_size(),
"The Jacobian density block has the wrong size."
);
MFEM_VERIFY(
get_block_size(state_offsets, displacement_block) == f.displacementFes->GetTrueVSize(),
get_block_size(state_offsets, displacement_block) == displacement_map.reduced_size(),
"The Jacobian displacement block has the wrong size."
);
MFEM_VERIFY(
get_block_size(state_offsets, gravity_gradient_block) == f.gravityFluxFes->GetTrueVSize(),
get_block_size(state_offsets, gravity_gradient_block) == flux_map.reduced_size(),
"The Jacobian gravity-gradient block has the wrong size."
);
MFEM_VERIFY(
get_block_size(state_offsets, gravity_potential_block) == f.gravityPotentialFes->GetTrueVSize(),
get_block_size(state_offsets, gravity_potential_block) == potential_map.reduced_size(),
"The Jacobian gravity-potential block has the wrong size."
);
MFEM_VERIFY(
get_block_size(residual_offsets, gravity_gradient_residual_block) == f.gravityFluxFes->GetTrueVSize(),
get_block_size(residual_offsets, gravity_gradient_residual_block) == flux_map.reduced_size(),
"The Jacobian gradient-residual block has the wrong size."
);
MFEM_VERIFY(
get_block_size(residual_offsets, gravity_poisson_residual_block) == f.gravityPotentialFes->GetTrueVSize(),
get_block_size(residual_offsets, gravity_poisson_residual_block) == potential_map.reduced_size(),
"The Jacobian Poisson-residual block has the wrong size."
);
}
@@ -121,18 +131,18 @@ namespace mean_field::operators {
fem::FEM &f,
const mapping::DomainMapperStateless &domain_mapper,
const context::gravity_field::GravityFieldLinearizationContext &linearization_context,
const mfem::Array<int> &state_true_offsets,
const mfem::Array<int> &residual_true_offsets
const mfem::Array<int> &state_offsets,
const mfem::Array<int> &residual_offsets
)
: Operator(
residual_true_offsets.Last(),
state_true_offsets.Last()
residual_offsets.Last(),
state_offsets.Last()
),
m_fem(f),
m_domain_mapper(domain_mapper),
m_linearization_context(linearization_context),
m_state_true_offsets(state_true_offsets),
m_residual_true_offsets(residual_true_offsets) {
m_state_offsets(state_offsets),
m_residual_offsets(residual_offsets) {
MFEM_VERIFY(
f.densityFes != nullptr, "GravityFieldJacobianOperator requires the density finite-element "
"space."
@@ -166,7 +176,7 @@ namespace mean_field::operators {
"dimension."
);
validate_layout(f, m_state_true_offsets, m_residual_true_offsets);
validate_layout(f, m_state_offsets, m_residual_offsets);
}
void GravityFieldJacobianOperator::Mult(
@@ -198,50 +208,70 @@ namespace mean_field::operators {
const context::gravity_field::GravityFieldGeometryContext &geometry_context =
m_linearization_context.GetGeometryContext();
const mfem::Vector &density = m_linearization_context.GetDensity();
const mfem::Vector &displacement = geometry_context.GetDisplacement();
const mfem::Vector &gravity_gradient = m_linearization_context.GetGravityGradient();
const mfem::Vector &density = m_linearization_context.GetDensityTrue();
const mfem::Vector &displacement = geometry_context.GetDisplacementTrue();
const mfem::Vector &gravity_gradient = m_linearization_context.GetGravityGradientTrue();
const mfem::Vector density_direction =
make_read_only_value_view(direction, m_state_true_offsets, density_block);
const mfem::Vector density_direction = make_read_only_value_view(direction, m_state_offsets, density_block);
const mfem::Vector displacement_direction =
make_read_only_value_view(direction, m_state_true_offsets, displacement_block);
make_read_only_value_view(direction, m_state_offsets, displacement_block);
const mfem::Vector gravity_gradient_direction =
make_read_only_value_view(direction, m_state_true_offsets, gravity_gradient_block);
make_read_only_value_view(direction, m_state_offsets, gravity_gradient_block);
const mfem::Vector gravity_potential_direction =
make_read_only_value_view(direction, m_state_true_offsets, gravity_potential_block);
make_read_only_value_view(direction, m_state_offsets, gravity_potential_block);
const field::FieldDofMap &displacement_map = m_linearization_context.GetDisplacementMap();
const field::FieldDofMap &flux_map = m_linearization_context.GetGravityGradientMap();
const field::FieldDofMap &potential_map = m_linearization_context.GetGravityPotentialMap();
mfem::Vector displacement_direction_true(displacement_map.full_size());
mfem::Vector gravity_gradient_direction_true(flux_map.full_size());
mfem::Vector gravity_potential_direction_true(potential_map.full_size());
displacement_map.scatter(displacement_direction, displacement_direction_true);
flux_map.scatter(gravity_gradient_direction, gravity_gradient_direction_true);
potential_map.scatter(gravity_potential_direction, gravity_potential_direction_true);
action.SetSize(Height());
action = 0.0;
mfem::Vector gravity_gradient_action =
make_residual_view(action, m_residual_true_offsets, gravity_gradient_residual_block);
make_residual_view(action, m_residual_offsets, gravity_gradient_residual_block);
mfem::Vector gravity_poisson_action =
make_residual_view(action, m_residual_true_offsets, gravity_poisson_residual_block);
make_residual_view(action, m_residual_offsets, gravity_poisson_residual_block);
mfem::Vector transpose_divergence_action;
mfem::Vector transpose_divergence_action_true;
mfem::Vector transpose_divergence_action(flux_map.reduced_size());
mfem::Vector divergence_action_true;
mfem::Vector source_action;
mfem::Vector mass_variation_action;
mfem::Vector source_variation_action;
mfem::Vector mass_variation_action_true;
mfem::Vector mass_variation_action(flux_map.reduced_size());
mfem::Vector source_variation_action_true;
mfem::Vector source_variation_action(potential_map.reduced_size());
geometry_context.GetMassOperator().Mult(gravity_gradient_direction, gravity_gradient_action);
geometry_context.GetSourceOperator().Mult(density_direction, source_action);
kernels::apply_mapped_hdiv_mass_variation(
m_fem, m_domain_mapper, gravity_gradient, displacement, displacement_direction, mass_variation_action
m_fem, m_domain_mapper, gravity_gradient, displacement, displacement_direction_true,
mass_variation_action_true
);
flux_map.gather(mass_variation_action_true, mass_variation_action);
kernels::apply_mapped_source_variation(
m_fem, m_domain_mapper, density, displacement, displacement_direction, source_variation_action
m_fem, m_domain_mapper, density, displacement, displacement_direction_true, source_variation_action_true
);
potential_map.gather(source_variation_action_true, source_variation_action);
transpose_divergence_action.SetSize(gravity_gradient_action.Size());
m_fem.gravityContext.BT->Mult(gravity_potential_direction, transpose_divergence_action);
transpose_divergence_action_true.SetSize(flux_map.full_size());
m_fem.gravityContext.BT->Mult(gravity_potential_direction_true, transpose_divergence_action_true);
flux_map.gather(transpose_divergence_action_true, transpose_divergence_action);
gravity_gradient_action += transpose_divergence_action;
gravity_gradient_action += mass_variation_action;
m_fem.gravityContext.b_form->Mult(gravity_gradient_direction, gravity_poisson_action);
divergence_action_true.SetSize(potential_map.full_size());
m_fem.gravityContext.b_form->Mult(gravity_gradient_direction_true, divergence_action_true);
potential_map.gather(divergence_action_true, gravity_poisson_action);
gravity_poisson_action -= source_action;
gravity_poisson_action -= source_variation_action;

View File

@@ -153,10 +153,11 @@ namespace mean_field::operators {
);
}
const mfem::Vector &density = m_gravityContext.GetDensity();
const mfem::Vector &displacement = m_gravityContext.GetGeometryContext().GetDisplacement();
const mfem::Vector density = m_gravityContext.GetDensityMap().gather(m_gravityContext.GetDensityTrue());
const mfem::Vector displacement =
m_gravityContext.GetDisplacementMap().gather(m_gravityContext.GetGeometryContext().GetDisplacementTrue());
m_isPrepared = false;
m_isPrepared = false;
PreparedDisplacementResidualReport report;
@@ -170,13 +171,14 @@ namespace mean_field::operators {
{.density = density, .displacement = displacement}, make_rotational_dependencies(dependencies), rotation
);
if (report.DidAnyChildWork() || m_cachedResidual.Size() != m_fem.displacementFes->GetTrueVSize()) {
if (report.DidAnyChildWork() ||
m_cachedResidual.Size() != m_gravityContext.GetDisplacementMap().reduced_size()) {
AssembleResidual();
report.assembledResidual = true;
}
MFEM_VERIFY(
m_cachedResidual.Size() == m_fem.displacementFes->GetTrueVSize(),
m_cachedResidual.Size() == m_gravityContext.GetDisplacementMap().reduced_size(),
"PreparedDisplacementResidualOperator produced a cached "
"residual with the wrong size."
);
@@ -445,10 +447,13 @@ namespace mean_field::operators {
utils::blocks::get_residual_block<Form>(utils::blocks::barotropic_constant_field.mass_normalization_term);
MFEM_VERIFY(
m_layout.size(densityValue) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementValue) == f.displacementFes->GetTrueVSize() &&
m_layout.size(gravityGradientValue) == f.gravityFluxFes->GetTrueVSize() &&
m_layout.size(gravityPotentialValue) == f.gravityPotentialFes->GetTrueVSize() &&
m_layout.size(densityValue) == m_preparedOperator.GetGravityContext().GetDensityMap().reduced_size() &&
m_layout.size(displacementValue) ==
m_preparedOperator.GetGravityContext().GetDisplacementMap().reduced_size() &&
m_layout.size(gravityGradientValue) ==
m_preparedOperator.GetGravityContext().GetGravityGradientMap().reduced_size() &&
m_layout.size(gravityPotentialValue) ==
m_preparedOperator.GetGravityContext().GetGravityPotentialMap().reduced_size() &&
m_layout.size(barotropicConstantValue) == 1,
"Prepared displacement-residual MFEM adapter received "
"incompatible barotropic value-block sizes."
@@ -461,11 +466,16 @@ namespace mean_field::operators {
);
MFEM_VERIFY(
m_layout.size(gravityGradientResidual) == f.gravityFluxFes->GetTrueVSize() &&
m_layout.size(gravityPotentialResidual) == f.gravityPotentialFes->GetTrueVSize() &&
m_layout.size(densityResidual) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementResidual) == f.displacementFes->GetTrueVSize() &&
m_layout.size(enthalpyResidual) == f.enthalpyFes->GetTrueVSize() && m_layout.size(massResidual) == 1,
m_layout.size(gravityGradientResidual) ==
m_preparedOperator.GetGravityContext().GetGravityGradientMap().reduced_size() &&
m_layout.size(gravityPotentialResidual) ==
m_preparedOperator.GetGravityContext().GetGravityPotentialMap().reduced_size() &&
m_layout.size(densityResidual) ==
m_preparedOperator.GetGravityContext().GetDensityMap().reduced_size() &&
m_layout.size(displacementResidual) ==
m_preparedOperator.GetGravityContext().GetDisplacementMap().reduced_size() &&
m_layout.size(enthalpyResidual) == m_preparedOperator.GetPressureOperator().GetEnthalpySize() &&
m_layout.size(massResidual) == 1,
"Prepared displacement-residual MFEM adapter received "
"incompatible barotropic residual-block sizes."
);

View File

@@ -54,9 +54,11 @@ namespace mean_field::operators {
}
kernels::apply_gravity_displacement_force_residual(
m_fem, m_domainMapper, m_gravityContext.GetDensity(), m_gravityContext.GetGravityGradient(),
m_gravityContext.GetGeometryContext().GetDisplacement(), m_cachedResidual
m_fem, m_domainMapper, m_gravityContext.GetDensityTrue(), m_gravityContext.GetGravityGradientTrue(),
m_gravityContext.GetGeometryContext().GetDisplacementTrue(), m_actionTrue
);
m_cachedResidual.SetSize(m_gravityContext.GetDisplacementMap().reduced_size());
m_gravityContext.GetDisplacementMap().gather(m_actionTrue, m_cachedResidual);
m_preparedRevisions = requestedRevisions;
++m_residualPreparationCount;
@@ -77,10 +79,15 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_densityVariationTrue.SetSize(m_gravityContext.GetDensityMap().full_size());
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
kernels::apply_gravity_displacement_force_density_action(
m_fem, m_domainMapper, densityVariation, m_gravityContext.GetGravityGradient(),
m_gravityContext.GetGeometryContext().GetDisplacement(), action
m_fem, m_domainMapper, m_densityVariationTrue, m_gravityContext.GetGravityGradientTrue(),
m_gravityContext.GetGeometryContext().GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_gravityContext.GetDisplacementMap().reduced_size());
m_gravityContext.GetDisplacementMap().gather(m_actionTrue, action);
++m_densityJacobianStatistics.applications;
}
@@ -91,10 +98,15 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_gravityGradientVariationTrue.SetSize(m_gravityContext.GetGravityGradientMap().full_size());
m_gravityContext.GetGravityGradientMap().scatter(gravityGradientVariation, m_gravityGradientVariationTrue);
kernels::apply_gravity_displacement_force_gradient_action(
m_fem, m_domainMapper, m_gravityContext.GetDensity(), gravityGradientVariation,
m_gravityContext.GetGeometryContext().GetDisplacement(), action
m_fem, m_domainMapper, m_gravityContext.GetDensityTrue(), m_gravityGradientVariationTrue,
m_gravityContext.GetGeometryContext().GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_gravityContext.GetDisplacementMap().reduced_size());
m_gravityContext.GetDisplacementMap().gather(m_actionTrue, action);
++m_gravityGradientJacobianStatistics.applications;
}
@@ -105,10 +117,15 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_displacementVariationTrue.SetSize(m_gravityContext.GetDisplacementMap().full_size());
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
kernels::apply_gravity_displacement_force_displacement_action(
m_fem, m_domainMapper, m_gravityContext.GetDensity(), m_gravityContext.GetGravityGradient(),
displacementVariation, m_gravityContext.GetGeometryContext().GetDisplacement(), action
m_fem, m_domainMapper, m_gravityContext.GetDensityTrue(), m_gravityContext.GetGravityGradientTrue(),
m_displacementVariationTrue, m_gravityContext.GetGeometryContext().GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_gravityContext.GetDisplacementMap().reduced_size());
m_gravityContext.GetDisplacementMap().gather(m_actionTrue, action);
++m_displacementJacobianStatistics.applications;
}
@@ -121,11 +138,20 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_densityVariationTrue.SetSize(m_gravityContext.GetDensityMap().full_size());
m_gravityGradientVariationTrue.SetSize(m_gravityContext.GetGravityGradientMap().full_size());
m_displacementVariationTrue.SetSize(m_gravityContext.GetDisplacementMap().full_size());
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
m_gravityContext.GetGravityGradientMap().scatter(gravityGradientVariation, m_gravityGradientVariationTrue);
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
kernels::apply_gravity_displacement_force_complete_action(
m_fem, m_domainMapper, m_gravityContext.GetDensity(), densityVariation,
m_gravityContext.GetGravityGradient(), gravityGradientVariation, displacementVariation,
m_gravityContext.GetGeometryContext().GetDisplacement(), action
m_fem, m_domainMapper, m_gravityContext.GetDensityTrue(), m_densityVariationTrue,
m_gravityContext.GetGravityGradientTrue(), m_gravityGradientVariationTrue, m_displacementVariationTrue,
m_gravityContext.GetGeometryContext().GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_gravityContext.GetDisplacementMap().reduced_size());
m_gravityContext.GetDisplacementMap().gather(m_actionTrue, action);
++m_densityJacobianStatistics.applications;
++m_gravityGradientJacobianStatistics.applications;
@@ -196,8 +222,6 @@ namespace mean_field::operators {
),
m_layout(layout),
m_preparedOperator(preparedOperator) {
const fem::FEM &f = m_preparedOperator.GetFEM();
using Form = utils::blocks::barotropic_equilibrium_form;
constexpr auto densityValue = utils::blocks::get_value_block<Form>(utils::blocks::density_field.mass_term);
@@ -212,10 +236,13 @@ namespace mean_field::operators {
utils::blocks::get_residual_block<Form>(utils::blocks::displacement_field.geometry_term);
MFEM_VERIFY(
m_layout.size(densityValue) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementValue) == f.displacementFes->GetTrueVSize() &&
m_layout.size(gravityGradientValue) == f.gravityFluxFes->GetTrueVSize() &&
m_layout.size(displacementResidual) == f.displacementFes->GetTrueVSize(),
m_layout.size(densityValue) == m_preparedOperator.GetGravityContext().GetDensityMap().reduced_size() &&
m_layout.size(displacementValue) ==
m_preparedOperator.GetGravityContext().GetDisplacementMap().reduced_size() &&
m_layout.size(gravityGradientValue) ==
m_preparedOperator.GetGravityContext().GetGravityGradientMap().reduced_size() &&
m_layout.size(displacementResidual) ==
m_preparedOperator.GetGravityContext().GetDisplacementMap().reduced_size(),
"Prepared gravity-displacement-force MFEM adapter received "
"incompatible coupled block sizes."
);
@@ -287,4 +314,4 @@ namespace mean_field::operators {
const GravityDisplacementForceLayout &PreparedGravityDisplacementForceJacobianOperator::GetLayout() const noexcept {
return m_layout;
}
} // namespace mean_field::operators
} // namespace mean_field::operators

View File

@@ -9,13 +9,16 @@ module mean_field;
import :operators.prepared_gravity_source;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
int get_operator_height(const mean_field::fem::FEM &f) {
MFEM_VERIFY(
f.gravityPotentialFes != nullptr, "PreparedMappedGravitySourceOperator requires the "
"gravity-potential "
"finite-element space."
);
return f.gravityPotentialFes->GetTrueVSize();
return mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityPotentialFes)
.reduced_size();
}
int get_operator_width(const mean_field::fem::FEM &f) {
@@ -23,7 +26,8 @@ namespace {
f.densityFes != nullptr, "PreparedMappedGravitySourceOperator requires the density "
"finite-element space."
);
return f.densityFes->GetTrueVSize();
return mean_field::field::make_field_dof_map<mean_field::field::Density, DomainSchema>(*f.densityFes)
.reduced_size();
}
void true_to_local(
@@ -238,7 +242,22 @@ namespace mean_field::operators {
get_operator_width(f)
),
m_fem(f),
m_domain_mapper(domain_mapper) {
m_domain_mapper(domain_mapper),
m_density_map(
field::make_field_dof_map<
field::Density,
DomainSchema>(*f.densityFes)
),
m_potential_map(
field::make_field_dof_map<
field::Gravity,
DomainSchema>(*f.gravityPotentialFes)
),
m_displacement_map(
field::make_field_dof_map<
field::Displacement,
DomainSchema>(*f.displacementFes)
) {
MFEM_VERIFY(f.mesh != nullptr, "PreparedMappedGravitySourceOperator requires a mesh.");
MFEM_VERIFY(
f.densityFes != nullptr, "PreparedMappedGravitySourceOperator requires the density "
@@ -275,26 +294,28 @@ namespace mean_field::operators {
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) {
MFEM_VERIFY(
displacement_true.Size() == m_fem.displacementFes->GetTrueVSize(),
displacement.Size() == m_displacement_map.reduced_size(),
"PreparedMappedGravitySourceOperator 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)), "PreparedMappedGravitySourceOperator received a non-finite "
"displacement value."
std::isfinite(displacement(i)), "PreparedMappedGravitySourceOperator received a non-finite "
"displacement value."
);
}
m_is_prepared = false;
m_displacement_true.SetSize(m_displacement_map.full_size());
m_displacement_map.scatter(displacement, m_displacement_true);
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, m_displacement_true);
for (int element_id = 0; element_id < m_fem.mesh->GetNE(); ++element_id) {
const int attribute = m_fem.mesh->GetAttribute(element_id);
@@ -379,7 +400,7 @@ namespace mean_field::operators {
++m_preparation_count;
}
void PreparedMappedGravitySourceOperator::Mult(
const mfem::Vector &density_true,
const mfem::Vector &density,
mfem::Vector &action
) const {
MFEM_VERIFY(
@@ -388,13 +409,16 @@ namespace mean_field::operators {
);
MFEM_VERIFY(
density_true.Size() == Width(), "PreparedMappedGravitySourceOperator received a density vector "
"with the wrong size."
density.Size() == Width(), "PreparedMappedGravitySourceOperator received a density vector "
"with the wrong size."
);
m_density_true.SetSize(m_density_map.full_size());
m_density_map.scatter(density, m_density_true);
mfem::Vector density_local;
true_to_local(*m_fem.densityFes, density_true, density_local);
true_to_local(*m_fem.densityFes, m_density_true, density_local);
mfem::Vector local_action(m_fem.gravityPotentialFes->GetVSize());
local_action = 0.0;
@@ -432,11 +456,13 @@ namespace mean_field::operators {
local_action.AddElementVector(data.potential_dofs, element_action);
}
local_to_true(*m_fem.gravityPotentialFes, local_action, action);
local_to_true(*m_fem.gravityPotentialFes, local_action, m_action_true);
action.SetSize(Height());
m_potential_map.gather(m_action_true, action);
}
void PreparedMappedGravitySourceOperator::MultTranspose(
const mfem::Vector &potential_true,
const mfem::Vector &potential,
mfem::Vector &action
) const {
MFEM_VERIFY(
@@ -445,13 +471,16 @@ namespace mean_field::operators {
);
MFEM_VERIFY(
potential_true.Size() == Height(), "PreparedMappedGravitySourceOperator received a potential vector "
"with the wrong size."
potential.Size() == Height(), "PreparedMappedGravitySourceOperator received a potential vector "
"with the wrong size."
);
m_potential_true.SetSize(m_potential_map.full_size());
m_potential_map.scatter(potential, m_potential_true);
mfem::Vector potential_local;
true_to_local(*m_fem.gravityPotentialFes, potential_true, potential_local);
true_to_local(*m_fem.gravityPotentialFes, m_potential_true, potential_local);
mfem::Vector local_action(m_fem.densityFes->GetVSize());
local_action = 0.0;
@@ -486,7 +515,9 @@ namespace mean_field::operators {
local_action.AddElementVector(data.density_dofs, element_action);
}
local_to_true(*m_fem.densityFes, local_action, action);
local_to_true(*m_fem.densityFes, local_action, m_action_true);
action.SetSize(Width());
m_density_map.gather(m_action_true, action);
}
bool PreparedMappedGravitySourceOperator::IsPrepared() const noexcept {
return m_is_prepared;
@@ -495,4 +526,16 @@ namespace mean_field::operators {
std::uint64_t PreparedMappedGravitySourceOperator::GetPreparationCount() const noexcept {
return m_preparation_count;
}
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetDensityMap() const noexcept {
return m_density_map;
}
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetPotentialMap() const noexcept {
return m_potential_map;
}
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetDisplacementMap() const noexcept {
return m_displacement_map;
}
} // namespace mean_field::operators

View File

@@ -8,12 +8,15 @@ module mean_field;
import :operators.prepared_hdiv_mass;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
int get_operator_size(const mean_field::fem::FEM &f) {
MFEM_VERIFY(
f.gravityFluxFes != nullptr, "PreparedMappedHDivMassOperator requires the "
"gravity-gradient finite-element space."
);
return f.gravityFluxFes->GetTrueVSize();
return mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityFluxFes)
.reduced_size();
}
void true_to_local(
@@ -222,7 +225,17 @@ namespace mean_field::operators {
)
: Operator(get_operator_size(f)),
m_fem(f),
m_domain_mapper(domain_mapper) {
m_domain_mapper(domain_mapper),
m_flux_map(
field::make_field_dof_map<
field::Gravity,
DomainSchema>(*f.gravityFluxFes)
),
m_displacement_map(
field::make_field_dof_map<
field::Displacement,
DomainSchema>(*f.displacementFes)
) {
MFEM_VERIFY(f.mesh != nullptr, "PreparedMappedHDivMassOperator requires a mesh.");
MFEM_VERIFY(
f.gravityFluxFes != nullptr, "PreparedMappedHDivMassOperator requires the "
@@ -269,22 +282,25 @@ namespace mean_field::operators {
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) {
MFEM_VERIFY(
displacement_true.Size() == m_fem.displacementFes->GetTrueVSize(),
displacement.Size() == m_displacement_map.reduced_size(),
"PreparedMappedHDivMassOperator 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)), "PreparedMappedHDivMassOperator received a non-finite "
"displacement "
"value."
std::isfinite(displacement(i)), "PreparedMappedHDivMassOperator received a non-finite "
"displacement "
"value."
);
}
m_displacement_true.SetSize(m_displacement_map.full_size());
m_displacement_map.scatter(displacement, m_displacement_true);
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);
@@ -299,9 +315,9 @@ namespace mean_field::operators {
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, m_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, m_displacement_true, true);
m_mass_form = std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
m_mass_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
@@ -328,7 +344,7 @@ namespace mean_field::operators {
}
void PreparedMappedHDivMassOperator::Mult(
const mfem::Vector &gravity_gradient_true,
const mfem::Vector &gravity_gradient,
mfem::Vector &action
) const {
MFEM_VERIFY(
@@ -340,13 +356,16 @@ namespace mean_field::operators {
"assembled partial-assembly form."
);
MFEM_VERIFY(
gravity_gradient_true.Size() == Width(),
"PreparedMappedHDivMassOperator received a gravity-gradient vector "
"with the wrong size."
gravity_gradient.Size() == Width(), "PreparedMappedHDivMassOperator received a gravity-gradient vector "
"with the wrong size."
);
m_flux_true.SetSize(m_flux_map.full_size());
m_action_true.SetSize(m_flux_map.full_size());
m_flux_map.scatter(gravity_gradient, m_flux_true);
m_mass_form->Mult(m_flux_true, m_action_true);
action.SetSize(Height());
m_mass_form->Mult(gravity_gradient_true, action);
m_flux_map.gather(m_action_true, action);
}
bool PreparedMappedHDivMassOperator::IsPrepared() const noexcept {
@@ -356,4 +375,12 @@ namespace mean_field::operators {
std::uint64_t PreparedMappedHDivMassOperator::GetPreparationCount() const noexcept {
return m_preparation_count;
}
} // namespace mean_field::operators
const field::FieldDofMap &PreparedMappedHDivMassOperator::GetFluxMap() const noexcept {
return m_flux_map;
}
const field::FieldDofMap &PreparedMappedHDivMassOperator::GetDisplacementMap() const noexcept {
return m_displacement_map;
}
} // namespace mean_field::operators

View File

@@ -12,6 +12,8 @@ module mean_field;
import :operators.prepared_hydrostatic_equilibrium;
namespace {
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
void true_to_local(
const mfem::ParFiniteElementSpace &finiteElementSpace,
const mfem::Vector &trueVector,
@@ -151,9 +153,18 @@ namespace mean_field::operators {
"displacement finite-element space."
);
m_enthalpySize = f.enthalpyFes->GetTrueVSize();
m_gravityPotentialSize = f.gravityPotentialFes->GetTrueVSize();
m_displacementSize = f.displacementFes->GetTrueVSize();
const field::FieldDofMap enthalpyMap =
field::make_field_dof_map<field::Enthalpy, DomainSchema>(*f.enthalpyFes);
const field::FieldDofMap gravityPotentialMap =
field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes);
const field::FieldDofMap displacementMap =
field::make_field_dof_map<field::Displacement, DomainSchema>(*f.displacementFes);
m_enthalpySize = enthalpyMap.reduced_size();
m_gravityPotentialSize = gravityPotentialMap.reduced_size();
m_displacementSize = displacementMap.reduced_size();
m_residualSize = m_enthalpySize;
m_totalSize = m_enthalpySize + m_gravityPotentialSize + 1 + m_displacementSize;
@@ -265,6 +276,11 @@ namespace mean_field::operators {
m_domainMapper.GetDimension() == m_fem.mesh->Dimension(), "The hydrostatic operator's stateless mapper "
"dimension does not match the mesh dimension."
);
m_enthalpyVariationTrue.SetSize(m_context.GetEnthalpyMap().full_size());
m_gravityPotentialVariationTrue.SetSize(m_context.GetGravityPotentialMap().full_size());
m_displacementVariationTrue.SetSize(m_context.GetDisplacementMap().full_size());
m_fullEnthalpyAction.SetSize(m_context.GetEnthalpyMap().full_size());
}
PreparedHydrostaticEquilibriumReport PreparedHydrostaticEquilibriumOperator::Prepare(
@@ -320,8 +336,8 @@ namespace mean_field::operators {
);
MFEM_VERIFY(
m_cachedResidual.Size() == m_fem.enthalpyFes->GetTrueVSize(),
"The prepared hydrostatic residual has the wrong size."
m_cachedResidual.Size() == m_context.GetEnthalpyMap().reduced_size(),
"The prepared hydrostatic residual has the wrong supported size."
);
m_isPrepared = true;
@@ -708,7 +724,10 @@ namespace mean_field::operators {
localResidual.AddElementVector(data.enthalpyDofs, elementResidual);
}
local_to_true(*m_fem.enthalpyFes, localResidual, m_cachedResidual);
local_to_true(*m_fem.enthalpyFes, localResidual, m_fullEnthalpyAction);
m_cachedResidual.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, m_cachedResidual);
}
void PreparedHydrostaticEquilibriumOperator::BuildResidual(mfem::Vector &residual) const {
@@ -723,9 +742,16 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
MFEM_VERIFY(
enthalpyVariation.Size() == m_context.GetEnthalpyMap().reduced_size(),
"Prepared hydrostatic enthalpy variation has the wrong supported size."
);
m_context.GetEnthalpyMap().scatter(enthalpyVariation, m_enthalpyVariationTrue);
mfem::Vector enthalpyVariationLocal;
true_to_local(*m_fem.enthalpyFes, enthalpyVariation, enthalpyVariationLocal);
true_to_local(*m_fem.enthalpyFes, m_enthalpyVariationTrue, enthalpyVariationLocal);
mfem::Vector localAction(m_fem.enthalpyFes->GetVSize());
@@ -752,7 +778,10 @@ namespace mean_field::operators {
localAction.AddElementVector(data.enthalpyDofs, elementAction);
}
local_to_true(*m_fem.enthalpyFes, localAction, action);
local_to_true(*m_fem.enthalpyFes, localAction, m_fullEnthalpyAction);
action.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, action);
++m_algebraicJacobianStatistics.enthalpyApplications;
}
@@ -763,9 +792,18 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
MFEM_VERIFY(
gravityPotentialVariation.Size() == m_context.GetGravityPotentialMap().reduced_size(),
"Prepared hydrostatic gravity-potential variation has the wrong supported size."
);
m_context.GetGravityPotentialMap().scatter(gravityPotentialVariation, m_gravityPotentialVariationTrue);
mfem::Vector gravityPotentialVariationLocal;
true_to_local(*m_fem.gravityPotentialFes, gravityPotentialVariation, gravityPotentialVariationLocal);
true_to_local(
*m_fem.gravityPotentialFes, m_gravityPotentialVariationTrue, gravityPotentialVariationLocal
);
mfem::Vector localAction(m_fem.enthalpyFes->GetVSize());
@@ -792,7 +830,10 @@ namespace mean_field::operators {
localAction.AddElementVector(data.enthalpyDofs, elementAction);
}
local_to_true(*m_fem.enthalpyFes, localAction, action);
local_to_true(*m_fem.enthalpyFes, localAction, m_fullEnthalpyAction);
action.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, action);
++m_algebraicJacobianStatistics.gravityPotentialApplications;
}
@@ -824,7 +865,10 @@ namespace mean_field::operators {
localAction.AddElementVector(data.enthalpyDofs, elementAction);
}
local_to_true(*m_fem.enthalpyFes, localAction, action);
local_to_true(*m_fem.enthalpyFes, localAction, m_fullEnthalpyAction);
action.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, action);
++m_algebraicJacobianStatistics.bernoulliConstantApplications;
}
@@ -842,12 +886,27 @@ namespace mean_field::operators {
"a non-finite Bernoulli-constant variation."
);
MFEM_VERIFY(
enthalpyVariation.Size() == m_context.GetEnthalpyMap().reduced_size(),
"Prepared hydrostatic algebraic enthalpy variation has the wrong supported size."
);
MFEM_VERIFY(
gravityPotentialVariation.Size() == m_context.GetGravityPotentialMap().reduced_size(),
"Prepared hydrostatic algebraic gravity-potential variation has the wrong supported size."
);
m_context.GetEnthalpyMap().scatter(enthalpyVariation, m_enthalpyVariationTrue);
m_context.GetGravityPotentialMap().scatter(gravityPotentialVariation, m_gravityPotentialVariationTrue);
mfem::Vector enthalpyVariationLocal;
mfem::Vector gravityPotentialVariationLocal;
true_to_local(*m_fem.enthalpyFes, enthalpyVariation, enthalpyVariationLocal);
true_to_local(*m_fem.enthalpyFes, m_enthalpyVariationTrue, enthalpyVariationLocal);
true_to_local(*m_fem.gravityPotentialFes, gravityPotentialVariation, gravityPotentialVariationLocal);
true_to_local(
*m_fem.gravityPotentialFes, m_gravityPotentialVariationTrue, gravityPotentialVariationLocal
);
mfem::Vector localAction(m_fem.enthalpyFes->GetVSize());
@@ -898,7 +957,10 @@ namespace mean_field::operators {
localAction.AddElementVector(data.enthalpyDofs, elementAction);
}
local_to_true(*m_fem.enthalpyFes, localAction, action);
local_to_true(*m_fem.enthalpyFes, localAction, m_fullEnthalpyAction);
action.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, action);
++m_algebraicJacobianStatistics.combinedApplications;
}
@@ -909,9 +971,16 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
MFEM_VERIFY(
displacementVariation.Size() == m_context.GetDisplacementMap().reduced_size(),
"Prepared hydrostatic displacement variation has the wrong supported size."
);
m_context.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
mfem::Vector displacementVariationLocal;
true_to_local(*m_fem.displacementFes, displacementVariation, displacementVariationLocal);
true_to_local(*m_fem.displacementFes, m_displacementVariationTrue, displacementVariationLocal);
mfem::Vector localAction(m_fem.enthalpyFes->GetVSize());
@@ -1018,7 +1087,10 @@ namespace mean_field::operators {
localAction.AddElementVector(data.enthalpyDofs, elementAction);
}
local_to_true(*m_fem.enthalpyFes, localAction, action);
local_to_true(*m_fem.enthalpyFes, localAction, m_fullEnthalpyAction);
action.SetSize(m_context.GetEnthalpyMap().reduced_size());
m_context.GetEnthalpyMap().gather(m_fullEnthalpyAction, action);
++m_displacementJacobianStatistics.applications;
}
@@ -1087,6 +1159,18 @@ namespace mean_field::operators {
return m_fem;
}
const field::FieldDofMap &PreparedHydrostaticEquilibriumOperator::GetEnthalpyMap() const noexcept {
return m_context.GetEnthalpyMap();
}
const field::FieldDofMap &PreparedHydrostaticEquilibriumOperator::GetGravityPotentialMap() const noexcept {
return m_context.GetGravityPotentialMap();
}
const field::FieldDofMap &PreparedHydrostaticEquilibriumOperator::GetDisplacementMap() const noexcept {
return m_context.GetDisplacementMap();
}
void PreparedHydrostaticEquilibriumOperator::VerifyPrepared() const {
MFEM_VERIFY(
m_isPrepared, "PreparedHydrostaticEquilibriumOperator must be "
@@ -1099,7 +1183,7 @@ namespace mean_field::operators {
const PreparedHydrostaticEquilibriumOperator &preparedOperator
)
: mfem::Operator(
f.enthalpyFes != nullptr ? f.enthalpyFes->GetTrueVSize() : 0,
HydrostaticJacobianBlockLayout(f).GetResidualSize(),
HydrostaticJacobianBlockLayout(f).GetTotalSize()
),
m_layout(f),

View File

@@ -114,6 +114,15 @@ namespace mean_field::operators {
"PreparedMassNormalizationOperator received a mapper with the "
"wrong dimension."
);
MFEM_VERIFY(
m_gravityContext.GetDensityMap().full_size() == m_fem.densityFes->GetTrueVSize() &&
m_gravityContext.GetDisplacementMap().full_size() == m_fem.displacementFes->GetTrueVSize(),
"PreparedMassNormalizationOperator received incompatible shared FieldDof maps."
);
m_densityVariationTrue.SetSize(m_gravityContext.GetDensityMap().full_size());
m_displacementVariationTrue.SetSize(m_gravityContext.GetDisplacementMap().full_size());
}
PreparedMassNormalizationReport PreparedMassNormalizationOperator::Prepare(
@@ -167,12 +176,12 @@ namespace mean_field::operators {
}
if (refreshGeometry) {
RefreshGeometry(m_gravityContext.GetGeometryContext().GetDisplacement());
RefreshGeometry(m_gravityContext.GetGeometryContext().GetDisplacementTrue());
report.refreshedGeometry = true;
}
if (refreshDensity) {
RefreshDensity(m_gravityContext.GetDensity());
RefreshDensity(m_gravityContext.GetDensityTrue());
report.refreshedDensity = true;
}
@@ -476,8 +485,16 @@ namespace mean_field::operators {
mfem::Vector &action
) const {
VerifyPrepared();
MFEM_VERIFY(
densityVariation.Size() == m_gravityContext.GetDensityMap().reduced_size(),
"Mass-normalization density action received a supported vector with the wrong size."
);
validate_finite_vector(densityVariation, "Mass-normalization density action received a non-finite value.");
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
action.SetSize(1);
action(0) = GlobalSum(EvaluateDensityActionLocal(densityVariation));
action(0) = GlobalSum(EvaluateDensityActionLocal(m_densityVariationTrue));
++m_actionStatistics.densityApplications;
}
@@ -486,8 +503,18 @@ namespace mean_field::operators {
mfem::Vector &action
) const {
VerifyPrepared();
MFEM_VERIFY(
displacementVariation.Size() == m_gravityContext.GetDisplacementMap().reduced_size(),
"Mass-normalization displacement action received a supported vector with the wrong size."
);
validate_finite_vector(
displacementVariation, "Mass-normalization displacement action received a non-finite value."
);
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
action.SetSize(1);
action(0) = GlobalSum(EvaluateDisplacementActionLocal(displacementVariation));
action(0) = GlobalSum(EvaluateDisplacementActionLocal(m_displacementVariationTrue));
++m_actionStatistics.displacementApplications;
}
@@ -498,8 +525,25 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
MFEM_VERIFY(
densityVariation.Size() == m_gravityContext.GetDensityMap().reduced_size(),
"Mass-normalization complete action received a supported density vector with the wrong size."
);
MFEM_VERIFY(
displacementVariation.Size() == m_gravityContext.GetDisplacementMap().reduced_size(),
"Mass-normalization complete action received a supported displacement vector with the wrong size."
);
validate_finite_vector(densityVariation, "Mass-normalization complete action received a non-finite density.");
validate_finite_vector(
displacementVariation, "Mass-normalization complete action received a non-finite displacement."
);
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
const double localAction =
EvaluateDensityActionLocal(densityVariation) + EvaluateDisplacementActionLocal(displacementVariation);
EvaluateDensityActionLocal(m_densityVariationTrue) +
EvaluateDisplacementActionLocal(m_displacementVariationTrue);
action.SetSize(1);
action(0) = GlobalSum(localAction);
@@ -607,18 +651,25 @@ namespace mean_field::operators {
constexpr auto massResidual =
utils::blocks::get_residual_block<Form>(utils::blocks::barotropic_constant_field.mass_normalization_term);
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
const auto &gravityContext = m_preparedOperator.GetGravityContext();
const field::FieldDofMap enthalpyMap =
field::make_field_dof_map<field::Enthalpy, DomainSchema>(*f.enthalpyFes);
MFEM_VERIFY(
m_layout.size(densityValue) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementValue) == f.displacementFes->GetTrueVSize() &&
m_layout.size(gravityGradientValue) == f.gravityFluxFes->GetTrueVSize() &&
m_layout.size(gravityPotentialValue) == f.gravityPotentialFes->GetTrueVSize() &&
m_layout.size(enthalpyValue) == f.enthalpyFes->GetTrueVSize() &&
m_layout.size(densityValue) == gravityContext.GetDensityMap().reduced_size() &&
m_layout.size(displacementValue) == gravityContext.GetDisplacementMap().reduced_size() &&
m_layout.size(gravityGradientValue) == gravityContext.GetGravityGradientMap().reduced_size() &&
m_layout.size(gravityPotentialValue) == gravityContext.GetGravityPotentialMap().reduced_size() &&
m_layout.size(enthalpyValue) == enthalpyMap.reduced_size() &&
m_layout.size(barotropicConstantValue) == 1 &&
m_layout.size(gravityGradientResidual) == f.gravityFluxFes->GetTrueVSize() &&
m_layout.size(gravityPotentialResidual) == f.gravityPotentialFes->GetTrueVSize() &&
m_layout.size(densityResidual) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementResidual) == f.displacementFes->GetTrueVSize() &&
m_layout.size(enthalpyResidual) == f.enthalpyFes->GetTrueVSize() && m_layout.size(massResidual) == 1,
m_layout.size(gravityGradientResidual) == gravityContext.GetGravityGradientMap().reduced_size() &&
m_layout.size(gravityPotentialResidual) == gravityContext.GetGravityPotentialMap().reduced_size() &&
m_layout.size(densityResidual) == gravityContext.GetDensityMap().reduced_size() &&
m_layout.size(displacementResidual) == gravityContext.GetDisplacementMap().reduced_size() &&
m_layout.size(enthalpyResidual) == enthalpyMap.reduced_size() && m_layout.size(massResidual) == 1,
"Prepared mass-normalization MFEM adapter received incompatible "
"barotropic block sizes."
);
@@ -665,4 +716,4 @@ namespace mean_field::operators {
const MassNormalizationLayout &PreparedMassNormalizationJacobianOperator::GetLayout() const noexcept {
return m_layout;
}
} // namespace mean_field::operators
} // namespace mean_field::operators

View File

@@ -79,15 +79,17 @@ namespace mean_field::operators {
if (report.contextReport.preparedBaseState) {
kernels::apply_rotational_displacement_force_residual(
m_fem, m_domainMapper, *m_rotation, m_context.GetBaseDensityTrue(), m_context.GetDisplacementTrue(),
m_cachedResidual
m_actionTrue
);
m_cachedResidual.SetSize(m_context.GetDisplacementMap().reduced_size());
m_context.GetDisplacementMap().gather(m_actionTrue, m_cachedResidual);
++m_residualPreparationCount;
report.preparedResidual = true;
}
MFEM_VERIFY(
m_cachedResidual.Size() == m_fem.displacementFes->GetTrueVSize(),
m_cachedResidual.Size() == m_context.GetDisplacementMap().reduced_size(),
"The prepared rotational-displacement-force residual has the "
"wrong size."
);
@@ -110,9 +112,14 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_densityVariationTrue.SetSize(m_context.GetDensityMap().full_size());
m_context.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
kernels::apply_rotational_displacement_force_density_action(
m_fem, m_domainMapper, *m_rotation, densityVariation, m_context.GetDisplacementTrue(), action
m_fem, m_domainMapper, *m_rotation, m_densityVariationTrue, m_context.GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_context.GetDisplacementMap().reduced_size());
m_context.GetDisplacementMap().gather(m_actionTrue, action);
++m_densityJacobianStatistics.applications;
}
@@ -123,10 +130,15 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_displacementVariationTrue.SetSize(m_context.GetDisplacementMap().full_size());
m_context.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
kernels::apply_rotational_displacement_force_displacement_action(
m_fem, m_domainMapper, *m_rotation, m_context.GetBaseDensityTrue(), displacementVariation,
m_context.GetDisplacementTrue(), action
m_fem, m_domainMapper, *m_rotation, m_context.GetBaseDensityTrue(), m_displacementVariationTrue,
m_context.GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_context.GetDisplacementMap().reduced_size());
m_context.GetDisplacementMap().gather(m_actionTrue, action);
++m_displacementJacobianStatistics.applications;
}
@@ -138,10 +150,17 @@ namespace mean_field::operators {
) const {
VerifyPrepared();
m_densityVariationTrue.SetSize(m_context.GetDensityMap().full_size());
m_displacementVariationTrue.SetSize(m_context.GetDisplacementMap().full_size());
m_context.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
m_context.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
kernels::apply_rotational_displacement_force_complete_action(
m_fem, m_domainMapper, *m_rotation, m_context.GetBaseDensityTrue(), densityVariation, displacementVariation,
m_context.GetDisplacementTrue(), action
m_fem, m_domainMapper, *m_rotation, m_context.GetBaseDensityTrue(), m_densityVariationTrue,
m_displacementVariationTrue, m_context.GetDisplacementTrue(), m_actionTrue
);
action.SetSize(m_context.GetDisplacementMap().reduced_size());
m_context.GetDisplacementMap().gather(m_actionTrue, action);
++m_densityJacobianStatistics.applications;
++m_displacementJacobianStatistics.applications;
@@ -207,8 +226,6 @@ namespace mean_field::operators {
),
m_layout(layout),
m_preparedOperator(preparedOperator) {
const fem::FEM &f = m_preparedOperator.GetFEM();
using Form = utils::blocks::barotropic_equilibrium_form;
constexpr auto densityValue = utils::blocks::get_value_block<Form>(utils::blocks::density_field.mass_term);
@@ -220,9 +237,11 @@ namespace mean_field::operators {
utils::blocks::get_residual_block<Form>(utils::blocks::displacement_field.geometry_term);
MFEM_VERIFY(
m_layout.size(densityValue) == f.densityFes->GetTrueVSize() &&
m_layout.size(displacementValue) == f.displacementFes->GetTrueVSize() &&
m_layout.size(displacementResidual) == f.displacementFes->GetTrueVSize(),
m_layout.size(densityValue) == m_preparedOperator.GetContext().GetDensityMap().reduced_size() &&
m_layout.size(displacementValue) ==
m_preparedOperator.GetContext().GetDisplacementMap().reduced_size() &&
m_layout.size(displacementResidual) ==
m_preparedOperator.GetContext().GetDisplacementMap().reduced_size(),
"Prepared rotational-displacement-force MFEM adapter received "
"incompatible coupled block sizes."
);

View File

@@ -55,21 +55,29 @@ namespace {
return {valueSizes, residualSizes};
}
[[nodiscard]] mfem::Array<int> make_gravity_state_offsets(const mean_field::fem::FEM &f) {
[[nodiscard]] mfem::Array<int> make_gravity_state_offsets(
const mean_field::field::FieldDofMap &densityMap,
const mean_field::field::FieldDofMap &displacementMap,
const mean_field::field::FieldDofMap &gravityFluxMap,
const mean_field::field::FieldDofMap &gravityPotentialMap
) {
mfem::Array<int> offsets(5);
offsets[0] = 0;
offsets[1] = offsets[0] + f.densityFes->GetTrueVSize();
offsets[2] = offsets[1] + f.displacementFes->GetTrueVSize();
offsets[3] = offsets[2] + f.gravityFluxFes->GetTrueVSize();
offsets[4] = offsets[3] + f.gravityPotentialFes->GetTrueVSize();
offsets[1] = offsets[0] + densityMap.reduced_size();
offsets[2] = offsets[1] + displacementMap.reduced_size();
offsets[3] = offsets[2] + gravityFluxMap.reduced_size();
offsets[4] = offsets[3] + gravityPotentialMap.reduced_size();
return offsets;
}
[[nodiscard]] mfem::Array<int> make_gravity_residual_offsets(const mean_field::fem::FEM &f) {
[[nodiscard]] mfem::Array<int> make_gravity_residual_offsets(
const mean_field::field::FieldDofMap &gravityFluxMap,
const mean_field::field::FieldDofMap &gravityPotentialMap
) {
mfem::Array<int> offsets(3);
offsets[0] = 0;
offsets[1] = f.gravityFluxFes->GetTrueVSize();
offsets[2] = offsets[1] + f.gravityPotentialFes->GetTrueVSize();
offsets[1] = gravityFluxMap.reduced_size();
offsets[2] = offsets[1] + gravityPotentialMap.reduced_size();
return offsets;
}
@@ -295,8 +303,16 @@ namespace mean_field::operators {
gravityPotentialMap,
enthalpyMap
)),
gravityStateOffsets(make_gravity_state_offsets(f)),
gravityResidualOffsets(make_gravity_residual_offsets(f)) {
gravityStateOffsets(make_gravity_state_offsets(
densityMap,
displacementMap,
gravityFluxMap,
gravityPotentialMap
)),
gravityResidualOffsets(make_gravity_residual_offsets(
gravityFluxMap,
gravityPotentialMap
)) {
}
};
@@ -386,12 +402,7 @@ namespace mean_field::operators {
domainMapper,
m_gravityContext
),
m_targetMass(targetMass),
m_densityMap(std::move(constructionData.densityMap)),
m_displacementMap(std::move(constructionData.displacementMap)),
m_gravityFluxMap(std::move(constructionData.gravityFluxMap)),
m_gravityPotentialMap(std::move(constructionData.gravityPotentialMap)),
m_enthalpyMap(std::move(constructionData.enthalpyMap)) {
m_targetMass(targetMass) {
MFEM_VERIFY(
std::isfinite(m_targetMass) && m_targetMass > 0.0,
"PreparedStellarEquilibriumOperator requires a finite, positive target mass."
@@ -402,35 +413,12 @@ namespace mean_field::operators {
"PreparedStellarEquilibriumOperator has inconsistent block dimensions."
);
MFEM_VERIFY(
m_displacementMap.is_identity(), "PreparedStellarEquilibriumOperator currently requires Displacement "
"support to span the full MFEM true-DOF space."
);
MFEM_VERIFY(
m_gravityFluxMap.is_identity(), "PreparedStellarEquilibriumOperator currently requires gravity-flux "
"support to span the full MFEM true-DOF space."
);
MFEM_VERIFY(
m_gravityPotentialMap.is_identity(), "PreparedStellarEquilibriumOperator currently requires "
"gravity-potential support to span the full MFEM true-DOF space."
);
m_gravityState.SetSize(m_gravityStateOffsets.Last());
m_fullDensity.SetSize(m_densityMap.full_size());
m_fullEnthalpy.SetSize(m_enthalpyMap.full_size());
m_fullGravityState.SetSize(m_gravityStateOffsets.Last());
m_gravityDirection.SetSize(m_gravityStateOffsets.Last());
m_fullDensityVariation.SetSize(m_densityMap.full_size());
m_fullEnthalpyVariation.SetSize(m_enthalpyMap.full_size());
m_fullGravityDirection.SetSize(m_gravityStateOffsets.Last());
m_fullEnthalpyAction.SetSize(m_enthalpyMap.full_size());
m_fullDensity = 0.0;
m_fullEnthalpy = 0.0;
m_fullGravityState = 0.0;
m_fullDensityVariation = 0.0;
m_fullEnthalpyVariation = 0.0;
m_fullGravityDirection = 0.0;
m_fullEnthalpyAction = 0.0;
m_gravityState = 0.0;
m_gravityDirection = 0.0;
}
PreparedStellarEquilibriumReport PreparedStellarEquilibriumOperator::Prepare(
@@ -502,16 +490,13 @@ namespace mean_field::operators {
const mfem::Vector reducedEnthalpy = make_value_view(state, m_layout, enthalpyValue);
const mfem::Vector bernoulli = make_value_view(state, m_layout, bernoulliValue);
m_densityMap.scatter(reducedDensity, m_fullDensity);
m_enthalpyMap.scatter(reducedEnthalpy, m_fullEnthalpy);
pack_gravity_vector(
m_fullGravityState, m_gravityStateOffsets, m_fullDensity, displacement, gravityGradient, gravityPotential
m_gravityState, m_gravityStateOffsets, reducedDensity, displacement, gravityGradient, gravityPotential
);
PreparedStellarEquilibriumReport report;
report.gravity = m_gravityOperator.Prepare(m_fullGravityState, make_gravity_revisions(dependencies));
report.gravity = m_gravityOperator.Prepare(m_gravityState, make_gravity_revisions(dependencies));
report.barotropicClosure = m_barotropicClosureOperator.Prepare(
{.density = reducedDensity, .enthalpy = reducedEnthalpy, .displacement = displacement},
@@ -519,7 +504,7 @@ namespace mean_field::operators {
);
report.hydrostatic = m_hydrostaticOperator.Prepare(
{.enthalpy = m_fullEnthalpy,
{.enthalpy = reducedEnthalpy,
.gravityPotential = gravityPotential,
.displacement = displacement,
.bernoulliConstant = bernoulli(0)},
@@ -563,12 +548,13 @@ namespace mean_field::operators {
mfem::Vector gravity;
mfem::Vector closure;
mfem::Vector displacement;
mfem::Vector hydrostatic;
mfem::Vector mass;
m_gravityOperator.Mult(m_fullGravityState, gravity);
m_gravityOperator.Mult(m_gravityState, gravity);
m_barotropicClosureOperator.BuildResidual(closure);
m_displacementOperator.BuildResidual(displacement);
m_hydrostaticOperator.BuildResidual(m_fullEnthalpyAction);
m_hydrostaticOperator.BuildResidual(hydrostatic);
m_massNormalizationOperator.BuildResidual(mass);
m_cachedResidual.SetSize(Height());
@@ -600,10 +586,10 @@ namespace mean_field::operators {
"The displacement residual has the wrong size."
);
{
mfem::Vector reducedEnthalpyResidual = make_residual_view(m_cachedResidual, m_layout, enthalpyResidual);
m_enthalpyMap.gather(m_fullEnthalpyAction, reducedEnthalpyResidual);
}
assign_residual_block(
m_cachedResidual, m_layout, enthalpyResidual, hydrostatic,
"The hydrostatic residual has the wrong size."
);
assign_residual_block(
m_cachedResidual, m_layout, massResidual, mass, "The mass-normalization residual has the wrong size."
@@ -665,37 +651,35 @@ namespace mean_field::operators {
const mfem::Vector reducedEnthalpyDirection = make_value_view(direction, m_layout, enthalpyValue);
const mfem::Vector bernoulliDirection = make_value_view(direction, m_layout, bernoulliValue);
m_densityMap.scatter(reducedDensityDirection, m_fullDensityVariation);
m_enthalpyMap.scatter(reducedEnthalpyDirection, m_fullEnthalpyVariation);
pack_gravity_vector(
m_fullGravityDirection, m_gravityStateOffsets, m_fullDensityVariation, displacementDirection,
m_gravityDirection, m_gravityStateOffsets, reducedDensityDirection, displacementDirection,
gravityGradientDirection, gravityPotentialDirection
);
mfem::Vector gravityAction;
mfem::Vector closureAction;
mfem::Vector displacementAction;
mfem::Vector hydrostaticAction;
mfem::Vector massAction;
m_gravityJacobianOperator.Mult(m_fullGravityDirection, gravityAction);
m_gravityJacobianOperator.Mult(m_gravityDirection, gravityAction);
m_barotropicClosureOperator.Mult(
reducedDensityDirection, reducedEnthalpyDirection, displacementDirection, closureAction
);
m_displacementOperator.ApplyCompleteJacobianAction(
m_fullDensityVariation, displacementDirection, gravityGradientDirection, reducedEnthalpyDirection,
reducedDensityDirection, displacementDirection, gravityGradientDirection, reducedEnthalpyDirection,
displacementAction
);
m_hydrostaticOperator.ApplyCompleteJacobianAction(
m_fullEnthalpyVariation, gravityPotentialDirection, bernoulliDirection(0), displacementDirection,
m_fullEnthalpyAction
reducedEnthalpyDirection, gravityPotentialDirection, bernoulliDirection(0), displacementDirection,
hydrostaticAction
);
m_massNormalizationOperator.ApplyCompleteJacobianAction(
m_fullDensityVariation, displacementDirection, massAction
reducedDensityDirection, displacementDirection, massAction
);
action.SetSize(Height());
@@ -727,10 +711,10 @@ namespace mean_field::operators {
"The displacement Jacobian action has the wrong size."
);
{
mfem::Vector reducedEnthalpyAction = make_residual_view(action, m_layout, enthalpyResidual);
m_enthalpyMap.gather(m_fullEnthalpyAction, reducedEnthalpyAction);
}
assign_residual_block(
action, m_layout, enthalpyResidual, hydrostaticAction,
"The hydrostatic Jacobian action has the wrong size."
);
assign_residual_block(
action, m_layout, massResidual, massAction, "The mass-normalization Jacobian action has the wrong size."

View File

@@ -331,7 +331,10 @@ namespace mean_field::physics {
auto source_form =
std::make_unique<operators::PreparedMappedGravitySourceOperator>(f, *f.domainMapperStateless);
source_form->Prepare(displacement_true);
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
const field::FieldDofMap displacement_map =
field::make_field_dof_map<field::Displacement, DomainSchema>(*f.displacementFes);
source_form->Prepare(displacement_map.gather(displacement_true));
f.gravityContext.source_form = std::move(source_form);
// ==========================================
@@ -440,13 +443,22 @@ namespace mean_field::physics {
constexpr auto gravity_poisson_residual_block =
utils::blocks::get_residual_block<form>(utils::blocks::gravity_field.poisson_term);
using DomainSchema = utils::domain::CoreEnvelopeVacuumDomainSchema;
const field::FieldDofMap density_map = field::make_field_dof_map<field::Density, DomainSchema>(*f.densityFes);
const field::FieldDofMap displacement_map =
field::make_field_dof_map<field::Displacement, DomainSchema>(*f.displacementFes);
const field::FieldDofMap gravity_flux_map =
field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityFluxFes);
const field::FieldDofMap gravity_potential_map =
field::make_field_dof_map<field::Gravity, DomainSchema>(*f.gravityPotentialFes);
const std::array<int, form::value_block_count> value_sizes{
f.densityFes->GetTrueVSize(), f.displacementFes->GetTrueVSize(), f.gravityFluxFes->GetTrueVSize(),
f.gravityPotentialFes->GetTrueVSize()
density_map.reduced_size(), displacement_map.reduced_size(), gravity_flux_map.reduced_size(),
gravity_potential_map.reduced_size()
};
const std::array<int, form::residual_block_count> residual_sizes{
f.gravityFluxFes->GetTrueVSize(), f.gravityPotentialFes->GetTrueVSize()
gravity_flux_map.reduced_size(), gravity_potential_map.reduced_size()
};
const utils::blocks::form_layout<form> layout(value_sizes, residual_sizes);
@@ -457,6 +469,9 @@ namespace mean_field::physics {
grid_function_to_true_dofs(*f.densityFes, rho, density_true);
grid_function_to_true_dofs(*f.displacementFes, displacement, displacement_true);
const mfem::Vector density = density_map.gather(density_true);
const mfem::Vector reduced_displacement = displacement_map.gather(displacement_true);
operators::context::gravity_field::GravityFieldLinearizationContext linearization_context(
f, *f.domainMapperStateless
);
@@ -474,18 +489,18 @@ namespace mean_field::physics {
);
operators::ReducedGravityFieldOperator reduced_operator(
gravity_operator, reduced_geometry_context, displacement_true
gravity_operator, reduced_geometry_context, reduced_displacement
);
mfem::Vector right_hand_side;
reduced_operator.BuildRightHandSide(density_true, right_hand_side);
reduced_operator.BuildRightHandSide(density, right_hand_side);
MFEM_VERIFY(
right_hand_side.Size() == reduced_operator.Height(),
"The reduced gravity right-hand side has the wrong size."
);
mfem::BlockVector gravity_state(reduced_operator.GetGravityTrueOffsets());
mfem::BlockVector gravity_state(reduced_operator.GetGravityOffsets());
gravity_state = 0.0;
mfem::MINRESSolver minres(f.mesh->GetComm());
@@ -501,9 +516,14 @@ namespace mean_field::physics {
GravitySolution solution(f);
solution.gradPhi.SetFromTrueDofs(gravity_state.GetBlock(gravity_gradient_residual_block));
const mfem::Vector gravity_flux_true =
gravity_flux_map.scatter(gravity_state.GetBlock(gravity_gradient_residual_block));
const mfem::Vector gravity_potential_true =
gravity_potential_map.scatter(gravity_state.GetBlock(gravity_poisson_residual_block));
solution.phi.SetFromTrueDofs(gravity_state.GetBlock(gravity_poisson_residual_block));
solution.gradPhi.SetFromTrueDofs(gravity_flux_true);
solution.phi.SetFromTrueDofs(gravity_potential_true);
return solution;
}