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:
@@ -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 "
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 "
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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."
|
||||
);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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."
|
||||
);
|
||||
|
||||
@@ -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."
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ module;
|
||||
|
||||
export module mean_field:operators.context.gravity_field;
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
export import :operators.prepared_gravity_source;
|
||||
export import :operators.prepared_hdiv_mass;
|
||||
@@ -69,14 +70,15 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
GravityFieldGeometryContext &operator=(GravityFieldGeometryContext &&) = delete;
|
||||
|
||||
GravityFieldGeometryPreparation Prepare(
|
||||
const mfem::Vector &displacement_true,
|
||||
const mfem::Vector &displacement,
|
||||
DiscretizationRevision discretization_revision,
|
||||
DisplacementRevision displacement_revision
|
||||
);
|
||||
|
||||
[[nodiscard]] const PreparedMappedHDivMassOperator &GetMassOperator() const;
|
||||
[[nodiscard]] const PreparedMappedGravitySourceOperator &GetSourceOperator() const;
|
||||
[[nodiscard]] const mfem::Vector &GetDisplacement() const;
|
||||
[[nodiscard]] const mfem::Vector &GetDisplacementTrue() const;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
[[nodiscard]] DiscretizationRevision GetDiscretizationRevision() const noexcept;
|
||||
[[nodiscard]] DisplacementRevision GetDisplacementRevision() const noexcept;
|
||||
[[nodiscard]] bool IsPrepared() const noexcept;
|
||||
@@ -88,6 +90,7 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
std::unique_ptr<PreparedMappedHDivMassOperator> m_mass_operator;
|
||||
std::unique_ptr<PreparedMappedGravitySourceOperator> m_source_operator;
|
||||
|
||||
field::FieldDofMap m_displacement_map;
|
||||
mfem::Vector m_displacement_true;
|
||||
|
||||
DiscretizationRevision m_discretization_revision;
|
||||
@@ -124,8 +127,12 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
);
|
||||
|
||||
[[nodiscard]] const GravityFieldGeometryContext &GetGeometryContext() const;
|
||||
[[nodiscard]] const mfem::Vector &GetDensity() const;
|
||||
[[nodiscard]] const mfem::Vector &GetGravityGradient() const;
|
||||
[[nodiscard]] const mfem::Vector &GetDensityTrue() const;
|
||||
[[nodiscard]] const mfem::Vector &GetGravityGradientTrue() const;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDensityMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetGravityGradientMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetGravityPotentialMap() const noexcept;
|
||||
[[nodiscard]] const GravityFieldRevisions &GetRevisions() const;
|
||||
[[nodiscard]] bool IsPrepared() const noexcept;
|
||||
|
||||
@@ -134,10 +141,13 @@ export namespace mean_field::operators::context::gravity_field {
|
||||
|
||||
GravityFieldGeometryContext m_geometry_context;
|
||||
|
||||
field::FieldDofMap m_density_map;
|
||||
field::FieldDofMap m_gravity_gradient_map;
|
||||
field::FieldDofMap m_gravity_potential_map;
|
||||
mfem::Vector m_density_true;
|
||||
mfem::Vector m_gravity_gradient_true;
|
||||
|
||||
GravityFieldRevisions m_revisions;
|
||||
bool m_is_prepared{false};
|
||||
};
|
||||
} // namespace mean_field::operators::context::gravity_field
|
||||
} // namespace mean_field::operators::context::gravity_field
|
||||
|
||||
@@ -8,6 +8,7 @@ module;
|
||||
export module mean_field:operators.context.hydrostatic_equilibrium;
|
||||
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators::context::hydrostatic {
|
||||
@@ -52,6 +53,12 @@ export namespace mean_field::operators::context::hydrostatic {
|
||||
constexpr auto operator<=>(const HydrostaticEquilibriumDependencies &) const = default;
|
||||
};
|
||||
|
||||
/*
|
||||
* Frozen solver-facing state in registered FieldDof coordinates.
|
||||
*
|
||||
* The context owns the only expansion into MFEM true-DOF vectors used
|
||||
* by the stateless hydrostatic kernels and prepared quadrature data.
|
||||
*/
|
||||
struct HydrostaticEquilibriumStateView {
|
||||
const mfem::Vector &enthalpy;
|
||||
const mfem::Vector &gravityPotential;
|
||||
@@ -113,6 +120,12 @@ export namespace mean_field::operators::context::hydrostatic {
|
||||
|
||||
[[nodiscard]] const HydrostaticPreparationStatistics &GetPreparationStatistics() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetEnthalpyMap() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetGravityPotentialMap() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
[[nodiscard]] const mfem::Vector &GetBaseEnthalpyTrue() const;
|
||||
|
||||
[[nodiscard]] const mfem::Vector &GetBaseGravityPotentialTrue() const;
|
||||
@@ -127,6 +140,10 @@ export namespace mean_field::operators::context::hydrostatic {
|
||||
const fem::FEM &m_f;
|
||||
const mapping::DomainMapperStateless &m_domainMapper;
|
||||
|
||||
field::FieldDofMap m_enthalpyMap;
|
||||
field::FieldDofMap m_gravityPotentialMap;
|
||||
field::FieldDofMap m_displacementMap;
|
||||
|
||||
mfem::Vector m_baseEnthalpyTrue;
|
||||
mfem::Vector m_baseGravityPotentialTrue;
|
||||
mfem::Vector m_displacementTrue;
|
||||
|
||||
@@ -8,6 +8,7 @@ module;
|
||||
export module mean_field:operators.context.rotational_displacement_force;
|
||||
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators::context::rotational_displacement_force {
|
||||
@@ -108,12 +109,16 @@ export namespace mean_field::operators::context::rotational_displacement_force {
|
||||
[[nodiscard]] const mfem::Vector &GetBaseDensityTrue() const;
|
||||
|
||||
[[nodiscard]] const mfem::Vector &GetDisplacementTrue() const;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDensityMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
private:
|
||||
void VerifyPrepared() const;
|
||||
|
||||
const fem::FEM &m_f;
|
||||
|
||||
field::FieldDofMap m_densityMap;
|
||||
field::FieldDofMap m_displacementMap;
|
||||
mfem::Vector m_baseDensityTrue;
|
||||
mfem::Vector m_displacementTrue;
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
module;
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
#include <mfem.hpp>
|
||||
|
||||
@@ -10,21 +9,13 @@ export import :operators.gravity_field_jacobian;
|
||||
export import :operators.context.gravity_field;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
enum class GravityResidualBlock : std::uint8_t { gradient_equation = 0, poisson_equation = 1, count = 2 };
|
||||
|
||||
constexpr int gravity_residual_block_index(const GravityResidualBlock block) noexcept {
|
||||
return static_cast<int>(block);
|
||||
}
|
||||
|
||||
inline constexpr int gravity_residual_block_count = gravity_residual_block_index(GravityResidualBlock::count);
|
||||
|
||||
class GravityFieldOperator final : public mfem::Operator {
|
||||
public:
|
||||
GravityFieldOperator(
|
||||
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
|
||||
);
|
||||
|
||||
@@ -40,9 +31,9 @@ export namespace mean_field::operators {
|
||||
|
||||
Operator &GetGradient(const mfem::Vector &state) const override;
|
||||
|
||||
[[nodiscard]] const mfem::Array<int> &GetStateTrueOffsets() const noexcept;
|
||||
[[nodiscard]] const mfem::Array<int> &GetStateOffsets() const noexcept;
|
||||
|
||||
[[nodiscard]] const mfem::Array<int> &GetResidualTrueOffsets() const noexcept;
|
||||
[[nodiscard]] const mfem::Array<int> &GetResidualOffsets() const noexcept;
|
||||
|
||||
[[nodiscard]] context::gravity_field::GravityFieldLinearizationContext &GetLinearizationContext() noexcept;
|
||||
|
||||
@@ -66,8 +57,8 @@ export namespace mean_field::operators {
|
||||
fem::FEM &m_fem;
|
||||
const mapping::DomainMapperStateless &m_domain_mapper;
|
||||
context::gravity_field::GravityFieldLinearizationContext &m_linearization_context;
|
||||
mfem::Array<int> m_state_true_offsets;
|
||||
mfem::Array<int> m_residual_true_offsets;
|
||||
mfem::Array<int> m_state_offsets;
|
||||
mfem::Array<int> m_residual_offsets;
|
||||
GravityFieldJacobianOperator &m_jacobian;
|
||||
};
|
||||
|
||||
@@ -106,7 +97,7 @@ export namespace mean_field::operators {
|
||||
|
||||
[[nodiscard]] const context::gravity_field::GravityFieldGeometryContext &GetGeometryContext() const noexcept;
|
||||
|
||||
[[nodiscard]] const mfem::Array<int> &GetGravityTrueOffsets() const noexcept;
|
||||
[[nodiscard]] const mfem::Array<int> &GetGravityOffsets() const noexcept;
|
||||
|
||||
private:
|
||||
void ValidateDisplacement(const mfem::Vector &displacement) const;
|
||||
@@ -117,7 +108,8 @@ export namespace mean_field::operators {
|
||||
|
||||
private:
|
||||
GravityFieldOperator &m_gravity_field_operator;
|
||||
mfem::Array<int> m_gravity_true_offsets;
|
||||
mfem::Array<int> m_gravity_offsets;
|
||||
context::gravity_field::GravityFieldGeometryContext &m_gravity_field_geometry_context;
|
||||
mfem::Vector m_displacement;
|
||||
};
|
||||
} // namespace mean_field::operators
|
||||
} // namespace mean_field::operators
|
||||
|
||||
@@ -13,8 +13,8 @@ export 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
|
||||
);
|
||||
|
||||
void Mult(
|
||||
@@ -29,7 +29,7 @@ export namespace mean_field::operators {
|
||||
fem::FEM &m_fem;
|
||||
const mapping::DomainMapperStateless &m_domain_mapper;
|
||||
const context::gravity_field::GravityFieldLinearizationContext &m_linearization_context;
|
||||
mfem::Array<int> m_state_true_offsets;
|
||||
mfem::Array<int> m_residual_true_offsets;
|
||||
mfem::Array<int> m_state_offsets;
|
||||
mfem::Array<int> m_residual_offsets;
|
||||
};
|
||||
} // namespace mean_field::operators
|
||||
} // namespace mean_field::operators
|
||||
|
||||
@@ -5,6 +5,13 @@ export import :mapping.domain_mapper;
|
||||
export import :fem;
|
||||
|
||||
export namespace mean_field::operators::kernels {
|
||||
/*
|
||||
* Kernel boundary contract
|
||||
* ------------------------
|
||||
* These low-level element kernels operate on MFEM true-DOF vectors. The
|
||||
* prepared operators and gravity contexts own FieldDof maps and are the
|
||||
* only layer that gathers/scatters reduced public coordinates.
|
||||
*/
|
||||
|
||||
void apply_mapped_hdiv_mass(
|
||||
const fem::FEM &f,
|
||||
|
||||
@@ -113,6 +113,11 @@ export namespace mean_field::operators {
|
||||
context::gravity_field::GravityFieldRevisions m_preparedRevisions;
|
||||
mfem::Vector m_cachedResidual;
|
||||
|
||||
mutable mfem::Vector m_densityVariationTrue;
|
||||
mutable mfem::Vector m_gravityGradientVariationTrue;
|
||||
mutable mfem::Vector m_displacementVariationTrue;
|
||||
mutable mfem::Vector m_actionTrue;
|
||||
|
||||
std::uint64_t m_residualPreparationCount{0};
|
||||
mutable std::uint64_t m_residualApplicationCount{0};
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ module;
|
||||
|
||||
export module mean_field:operators.prepared_gravity_source;
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
@@ -16,17 +17,21 @@ export namespace mean_field::operators {
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
);
|
||||
|
||||
void Prepare(const mfem::Vector &displacement_true);
|
||||
void Prepare(const mfem::Vector &displacement);
|
||||
void Mult(
|
||||
const mfem::Vector &density_true,
|
||||
const mfem::Vector &density,
|
||||
mfem::Vector &action
|
||||
) const override;
|
||||
|
||||
[[nodiscard]] bool IsPrepared() const noexcept;
|
||||
[[nodiscard]] std::uint64_t GetPreparationCount() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetDensityMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetPotentialMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
void MultTranspose(
|
||||
const mfem::Vector &potential_true,
|
||||
const mfem::Vector &potential,
|
||||
mfem::Vector &action
|
||||
) const override;
|
||||
|
||||
@@ -52,9 +57,18 @@ export namespace mean_field::operators {
|
||||
const fem::FEM &m_fem;
|
||||
const mapping::DomainMapperStateless &m_domain_mapper;
|
||||
|
||||
field::FieldDofMap m_density_map;
|
||||
field::FieldDofMap m_potential_map;
|
||||
field::FieldDofMap m_displacement_map;
|
||||
|
||||
mfem::Array<int> m_stellar_marker;
|
||||
std::vector<ElementPAData> m_elements;
|
||||
|
||||
mutable mfem::Vector m_density_true;
|
||||
mutable mfem::Vector m_potential_true;
|
||||
mutable mfem::Vector m_action_true;
|
||||
mfem::Vector m_displacement_true;
|
||||
|
||||
std::uint64_t m_preparation_count{0};
|
||||
bool m_is_prepared{false};
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@ module;
|
||||
|
||||
export module mean_field:operators.prepared_hdiv_mass;
|
||||
export import :fem;
|
||||
export import :field.mfem;
|
||||
export import :mapping.domain_mapper;
|
||||
|
||||
export namespace mean_field::operators {
|
||||
@@ -15,26 +16,35 @@ export namespace mean_field::operators {
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
);
|
||||
|
||||
void Prepare(const mfem::Vector &displacement_true);
|
||||
void Prepare(const mfem::Vector &displacement);
|
||||
void Mult(
|
||||
const mfem::Vector &gravity_gradient_true,
|
||||
const mfem::Vector &gravity_gradient,
|
||||
mfem::Vector &action
|
||||
) const override;
|
||||
|
||||
[[nodiscard]] bool IsPrepared() const noexcept;
|
||||
[[nodiscard]] std::uint64_t GetPreparationCount() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetFluxMap() const noexcept;
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
private:
|
||||
const fem::FEM &m_fem;
|
||||
const mapping::DomainMapperStateless &m_domain_mapper;
|
||||
|
||||
field::FieldDofMap m_flux_map;
|
||||
field::FieldDofMap m_displacement_map;
|
||||
|
||||
mfem::Array<int> m_stellar_marker;
|
||||
mfem::Array<int> m_vacuum_marker;
|
||||
|
||||
std::unique_ptr<mfem::MatrixCoefficient> m_stellar_mass_coefficient;
|
||||
std::unique_ptr<mfem::MatrixCoefficient> m_vacuum_mass_coefficient;
|
||||
std::unique_ptr<mfem::ParBilinearForm> m_mass_form;
|
||||
mutable mfem::Vector m_flux_true;
|
||||
mutable mfem::Vector m_action_true;
|
||||
mfem::Vector m_displacement_true;
|
||||
std::uint64_t m_preparation_count{0};
|
||||
bool m_is_prepared{false};
|
||||
};
|
||||
} // namespace mean_field::operators
|
||||
} // namespace mean_field::operators
|
||||
|
||||
@@ -160,6 +160,12 @@ export namespace mean_field::operators {
|
||||
|
||||
[[nodiscard]] const fem::FEM &GetFEM() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetEnthalpyMap() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetGravityPotentialMap() const noexcept;
|
||||
|
||||
[[nodiscard]] const field::FieldDofMap &GetDisplacementMap() const noexcept;
|
||||
|
||||
private:
|
||||
struct ElementPAData {
|
||||
int elementId{-1};
|
||||
@@ -219,6 +225,11 @@ export namespace mean_field::operators {
|
||||
std::vector<ElementPAData> m_elements;
|
||||
mfem::Vector m_cachedResidual;
|
||||
|
||||
mutable mfem::Vector m_enthalpyVariationTrue;
|
||||
mutable mfem::Vector m_gravityPotentialVariationTrue;
|
||||
mutable mfem::Vector m_displacementVariationTrue;
|
||||
mutable mfem::Vector m_fullEnthalpyAction;
|
||||
|
||||
std::uint64_t m_residualPreparationCount{0};
|
||||
|
||||
mutable std::uint64_t m_residualApplicationCount{0};
|
||||
|
||||
@@ -61,6 +61,8 @@ export namespace mean_field::operators {
|
||||
* Density and displacement are borrowed from the shared gravity-field
|
||||
* linearization context. This keeps the mass row on exactly the same
|
||||
* frozen state and geometry as the gravity and mechanical rows.
|
||||
* Jacobian directions use the corresponding registered FieldDof
|
||||
* coordinates; expansion to MFEM true-DOF vectors is private.
|
||||
*/
|
||||
class PreparedMassNormalizationOperator final {
|
||||
public:
|
||||
@@ -153,6 +155,9 @@ export namespace mean_field::operators {
|
||||
MassNormalizationDependencies m_preparedDependencies;
|
||||
mfem::Vector m_cachedResidual;
|
||||
|
||||
mutable mfem::Vector m_densityVariationTrue;
|
||||
mutable mfem::Vector m_displacementVariationTrue;
|
||||
|
||||
double m_currentMass{0.0};
|
||||
double m_targetMass{0.0};
|
||||
|
||||
|
||||
@@ -111,6 +111,9 @@ export namespace mean_field::operators {
|
||||
|
||||
std::optional<physics::RigidRotation> m_rotation;
|
||||
mfem::Vector m_cachedResidual;
|
||||
mutable mfem::Vector m_densityVariationTrue;
|
||||
mutable mfem::Vector m_displacementVariationTrue;
|
||||
mutable mfem::Vector m_actionTrue;
|
||||
|
||||
context::rotational_displacement_force::RotationalDisplacementForceDependencies m_preparedDependencies;
|
||||
|
||||
|
||||
@@ -158,20 +158,8 @@ export namespace mean_field::operators {
|
||||
mutable PreparedStellarEquilibriumStatistics m_statistics;
|
||||
bool m_isPrepared{false};
|
||||
|
||||
field::FieldDofMap m_densityMap;
|
||||
field::FieldDofMap m_displacementMap;
|
||||
field::FieldDofMap m_gravityFluxMap;
|
||||
field::FieldDofMap m_gravityPotentialMap;
|
||||
field::FieldDofMap m_enthalpyMap;
|
||||
mfem::Vector m_gravityState;
|
||||
|
||||
mfem::Vector m_fullDensity;
|
||||
mfem::Vector m_fullEnthalpy;
|
||||
mfem::Vector m_fullGravityState;
|
||||
|
||||
mutable mfem::Vector m_fullDensityVariation;
|
||||
mutable mfem::Vector m_fullEnthalpyVariation;
|
||||
mutable mfem::Vector m_fullGravityDirection;
|
||||
|
||||
mutable mfem::Vector m_fullEnthalpyAction;
|
||||
mutable mfem::Vector m_gravityDirection;
|
||||
};
|
||||
} // namespace mean_field::operators
|
||||
|
||||
Reference in New Issue
Block a user