feat(FieldDofMap): Completed FieldDofMap migration
also removed legacy BarotropicPolytrope implementation
This commit is contained in:
@@ -35,7 +35,7 @@ namespace {
|
||||
namespace mean_field::operators::context::barotropic {
|
||||
BarotropicClosureLinearizationContext::BarotropicClosureLinearizationContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const field::FieldDofMap &densityMap,
|
||||
const field::FieldDofMap &enthalpyMap,
|
||||
const field::FieldDofMap &displacementMap
|
||||
|
||||
@@ -9,6 +9,29 @@ import :operators.context.gravity_field;
|
||||
namespace {
|
||||
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
|
||||
[[nodiscard]] std::unique_ptr<mfem::ParMixedBilinearForm> make_divergence_operator(const mean_field::fem::FEM &f) {
|
||||
auto divergence =
|
||||
std::make_unique<mfem::ParMixedBilinearForm>(f.gravityFluxFes.get(), f.gravityPotentialFes.get());
|
||||
|
||||
divergence->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
|
||||
auto integrator = std::make_unique<mfem::VectorFEDivergenceIntegrator>();
|
||||
|
||||
const mfem::FiniteElement &trialElement = *f.gravityFluxFes->GetTypicalFE();
|
||||
const mfem::FiniteElement &testElement = *f.gravityPotentialFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &transformation = *f.mesh->GetElementTransformation(0);
|
||||
|
||||
f.quadratureFactory->configure_gravity_divergence(
|
||||
*integrator, mean_field::quadrature::QuadratureRole::discretization, trialElement, testElement,
|
||||
transformation, mean_field::utils::DOMAINS::ALL, mean_field::quadrature::MappingKind::none
|
||||
);
|
||||
|
||||
divergence->AddDomainIntegrator(integrator.release());
|
||||
divergence->Assemble();
|
||||
|
||||
return divergence;
|
||||
}
|
||||
|
||||
void validate_displacement(
|
||||
const mean_field::field::FieldDofMap &displacement_map,
|
||||
const mfem::Vector &displacement
|
||||
@@ -96,7 +119,7 @@ namespace {
|
||||
namespace mean_field::operators::context::gravity_field {
|
||||
GravityFieldGeometryContext::GravityFieldGeometryContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
const mapping::DomainMapper &domain_mapper
|
||||
)
|
||||
: m_fem(f),
|
||||
m_domain_mapper(domain_mapper),
|
||||
@@ -170,18 +193,23 @@ namespace mean_field::operators::context::gravity_field {
|
||||
}
|
||||
|
||||
if (discretization_changed) {
|
||||
auto mass_operator = std::make_unique<PreparedMappedHDivMassOperator>(m_fem, m_domain_mapper);
|
||||
auto source_operator = std::make_unique<PreparedMappedGravitySourceOperator>(m_fem, m_domain_mapper);
|
||||
auto mass_operator = std::make_unique<PreparedMappedHDivMassOperator>(m_fem, m_domain_mapper);
|
||||
auto source_operator = std::make_unique<PreparedMappedGravitySourceOperator>(m_fem, m_domain_mapper);
|
||||
auto divergence_operator = make_divergence_operator(m_fem);
|
||||
auto transpose_divergence_operator = std::make_unique<mfem::TransposeOperator>(divergence_operator.get());
|
||||
|
||||
mass_operator->Prepare(displacement);
|
||||
source_operator->Prepare(displacement);
|
||||
|
||||
m_mass_operator = std::move(mass_operator);
|
||||
m_source_operator = std::move(source_operator);
|
||||
m_mass_operator = std::move(mass_operator);
|
||||
m_source_operator = std::move(source_operator);
|
||||
m_divergence_operator = std::move(divergence_operator);
|
||||
m_transpose_divergence_operator = std::move(transpose_divergence_operator);
|
||||
|
||||
preparation.reconstructed_operators = true;
|
||||
preparation.rebuilt_mass_operator = true;
|
||||
preparation.rebuilt_source_operator = true;
|
||||
preparation.reconstructed_operators = true;
|
||||
preparation.rebuilt_mass_operator = true;
|
||||
preparation.rebuilt_source_operator = true;
|
||||
preparation.rebuilt_divergence_operator = true;
|
||||
} else {
|
||||
MFEM_VERIFY(
|
||||
m_mass_operator != nullptr, "GravityFieldGeometryContext has "
|
||||
@@ -231,6 +259,23 @@ namespace mean_field::operators::context::gravity_field {
|
||||
return *m_source_operator;
|
||||
}
|
||||
|
||||
const mfem::Operator &GravityFieldGeometryContext::GetDivergenceOperator() const {
|
||||
MFEM_VERIFY(m_is_prepared, "GravityFieldGeometryContext must be prepared before accessing divergence.");
|
||||
MFEM_VERIFY(m_divergence_operator != nullptr, "GravityFieldGeometryContext has no divergence operator.");
|
||||
return *m_divergence_operator;
|
||||
}
|
||||
|
||||
const mfem::Operator &GravityFieldGeometryContext::GetTransposeDivergenceOperator() const {
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "GravityFieldGeometryContext must be prepared before accessing transpose divergence."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
m_transpose_divergence_operator != nullptr,
|
||||
"GravityFieldGeometryContext has no transpose-divergence operator."
|
||||
);
|
||||
return *m_transpose_divergence_operator;
|
||||
}
|
||||
|
||||
const mfem::Vector &GravityFieldGeometryContext::GetDisplacementTrue() const {
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "GravityFieldGeometryContext must be prepared before "
|
||||
@@ -257,7 +302,7 @@ namespace mean_field::operators::context::gravity_field {
|
||||
|
||||
GravityFieldLinearizationContext::GravityFieldLinearizationContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
const mapping::DomainMapper &domain_mapper
|
||||
)
|
||||
: m_fem(f),
|
||||
m_geometry_context(
|
||||
|
||||
@@ -75,7 +75,7 @@ namespace {
|
||||
namespace mean_field::operators::context::hydrostatic {
|
||||
HydrostaticEquilibriumContext::HydrostaticEquilibriumContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper
|
||||
const mapping::DomainMapper &domainMapper
|
||||
)
|
||||
: m_f(f),
|
||||
m_domainMapper(domainMapper),
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace {
|
||||
namespace mean_field::operators::context::pressure_force {
|
||||
PressureForceLinearizationContext::PressureForceLinearizationContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const field::FieldDofMap &enthalpyMap,
|
||||
const field::FieldDofMap &displacementMap
|
||||
)
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace {
|
||||
namespace mean_field::operators::context::rotational_displacement_force {
|
||||
RotationalDisplacementForceLinearizationContext::RotationalDisplacementForceLinearizationContext(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper
|
||||
const mapping::DomainMapper &domainMapper
|
||||
)
|
||||
: m_f(f),
|
||||
m_densityMap(
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -129,7 +129,7 @@ namespace {
|
||||
namespace mean_field::operators {
|
||||
GravityFieldJacobianOperator::GravityFieldJacobianOperator(
|
||||
fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domain_mapper,
|
||||
const mapping::DomainMapper &domain_mapper,
|
||||
const context::gravity_field::GravityFieldLinearizationContext &linearization_context,
|
||||
const mfem::Array<int> &state_offsets,
|
||||
const mfem::Array<int> &residual_offsets
|
||||
@@ -159,13 +159,6 @@ namespace mean_field::operators {
|
||||
f.displacementFes != nullptr, "GravityFieldJacobianOperator requires the "
|
||||
"displacement finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.b_form != nullptr, "GravityFieldJacobianOperator requires the divergence operator."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.BT != nullptr, "GravityFieldJacobianOperator requires the transpose divergence "
|
||||
"operator."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.quadratureFactory != nullptr, "GravityFieldJacobianOperator requires the quadrature-rule factory."
|
||||
);
|
||||
@@ -263,14 +256,16 @@ namespace mean_field::operators {
|
||||
potential_map.gather(source_variation_action_true, source_variation_action);
|
||||
|
||||
transpose_divergence_action_true.SetSize(flux_map.full_size());
|
||||
m_fem.gravityContext.BT->Mult(gravity_potential_direction_true, transpose_divergence_action_true);
|
||||
geometry_context.GetTransposeDivergenceOperator().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;
|
||||
|
||||
divergence_action_true.SetSize(potential_map.full_size());
|
||||
m_fem.gravityContext.b_form->Mult(gravity_gradient_direction_true, divergence_action_true);
|
||||
geometry_context.GetDivergenceOperator().Mult(gravity_gradient_direction_true, divergence_action_true);
|
||||
potential_map.gather(divergence_action_true, gravity_poisson_action);
|
||||
|
||||
gravity_poisson_action -= source_action;
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace {
|
||||
|
||||
void validate_common_inputs(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapperStateless &domainMapper,
|
||||
const mean_field::mapping::DomainMapper &domainMapper,
|
||||
const mfem::Vector &displacementTrue
|
||||
) {
|
||||
MFEM_VERIFY(f.mesh != nullptr, "The EOS closure kernel requires a mesh.");
|
||||
@@ -150,7 +150,7 @@ namespace {
|
||||
|
||||
void apply_closure_action(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapperStateless &domainMapper,
|
||||
const mean_field::mapping::DomainMapper &domainMapper,
|
||||
const mean_field::eos::Polytrope &barotrope,
|
||||
const ClosureAction closureAction,
|
||||
const mfem::Vector *densityInputTrue,
|
||||
@@ -204,7 +204,7 @@ namespace {
|
||||
mfem::Vector localAction(f.densityFes->GetVSize());
|
||||
localAction = 0.0;
|
||||
|
||||
mean_field::mapping::DomainMapperStateless::Workspace workspace(f.mesh->Dimension());
|
||||
mean_field::mapping::DomainMapper::Workspace workspace(f.mesh->Dimension());
|
||||
|
||||
mfem::Array<int> densityDofs;
|
||||
mfem::Array<int> enthalpyDofs;
|
||||
@@ -365,7 +365,7 @@ namespace {
|
||||
namespace mean_field::operators::kernels {
|
||||
void apply_barotropic_closure(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &barotrope,
|
||||
const mfem::Vector &densityTrue,
|
||||
const mfem::Vector &enthalpyTrue,
|
||||
@@ -380,7 +380,7 @@ namespace mean_field::operators::kernels {
|
||||
|
||||
void apply_barotropic_closure_density_action(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &barotrope,
|
||||
const mfem::Vector &densityVariationTrue,
|
||||
const mfem::Vector &displacementTrue,
|
||||
@@ -394,7 +394,7 @@ namespace mean_field::operators::kernels {
|
||||
|
||||
void apply_barotropic_closure_enthalpy_action(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &barotrope,
|
||||
const mfem::Vector &baseEnthalpyTrue,
|
||||
const mfem::Vector &enthalpyVariationTrue,
|
||||
@@ -409,7 +409,7 @@ namespace mean_field::operators::kernels {
|
||||
|
||||
void apply_barotropic_closure_displacement_action(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &barotrope,
|
||||
const mfem::Vector &baseDensityTrue,
|
||||
const mfem::Vector &baseEnthalpyTrue,
|
||||
@@ -490,7 +490,7 @@ namespace mean_field::operators::kernels {
|
||||
mfem::Vector localAction(f.densityFes->GetVSize());
|
||||
localAction = 0.0;
|
||||
|
||||
mapping::DomainMapperStateless::Workspace workspace(f.mesh->Dimension());
|
||||
mapping::DomainMapper::Workspace workspace(f.mesh->Dimension());
|
||||
|
||||
mfem::Array<int> densityDofs;
|
||||
mfem::Array<int> enthalpyDofs;
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -183,7 +183,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedBarotropicClosureOperator::PreparedBarotropicClosureOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState
|
||||
)
|
||||
: PreparedBarotropicClosureOperator(
|
||||
@@ -196,7 +196,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedBarotropicClosureOperator::PreparedBarotropicClosureOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
ConstructionData constructionData
|
||||
)
|
||||
@@ -285,7 +285,7 @@ namespace mean_field::operators {
|
||||
true_to_local(*m_fem.enthalpyFes, m_baseEnthalpyTrue, baseEnthalpyLocal);
|
||||
true_to_local(*m_fem.displacementFes, m_baseDisplacementTrue, displacementLocal);
|
||||
|
||||
mapping::DomainMapperStateless::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
|
||||
mfem::Array<int> displacementDofs;
|
||||
mfem::Array<int> compactificationDofs;
|
||||
|
||||
@@ -76,7 +76,7 @@ namespace {
|
||||
namespace mean_field::operators {
|
||||
PreparedDisplacementResidualOperator::PreparedDisplacementResidualOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &barotrope,
|
||||
const context::gravity_field::GravityFieldLinearizationContext &gravityContext
|
||||
)
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace {
|
||||
namespace mean_field::operators {
|
||||
PreparedGravityDisplacementForceOperator::PreparedGravityDisplacementForceOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const context::gravity_field::GravityFieldLinearizationContext &gravityContext
|
||||
)
|
||||
: m_fem(f),
|
||||
|
||||
@@ -9,533 +9,531 @@ module mean_field;
|
||||
import :operators.prepared_gravity_source;
|
||||
|
||||
namespace {
|
||||
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
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 mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityPotentialFes)
|
||||
.reduced_size();
|
||||
}
|
||||
int get_operator_height(const mean_field::fem::FEM &f) {
|
||||
MFEM_VERIFY(f.gravityPotentialFes != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the "
|
||||
"gravity-potential "
|
||||
"finite-element space.");
|
||||
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) {
|
||||
MFEM_VERIFY(
|
||||
f.densityFes != nullptr, "PreparedMappedGravitySourceOperator requires the density "
|
||||
"finite-element space."
|
||||
);
|
||||
return mean_field::field::make_field_dof_map<mean_field::field::Density, DomainSchema>(*f.densityFes)
|
||||
.reduced_size();
|
||||
}
|
||||
int get_operator_width(const mean_field::fem::FEM &f) {
|
||||
MFEM_VERIFY(f.densityFes != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the density "
|
||||
"finite-element space.");
|
||||
return mean_field::field::make_field_dof_map<mean_field::field::Density,
|
||||
DomainSchema>(*f.densityFes)
|
||||
.reduced_size();
|
||||
}
|
||||
|
||||
void true_to_local(
|
||||
const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &true_vector,
|
||||
mfem::Vector &local_vector
|
||||
) {
|
||||
local_vector.SetSize(finite_element_space.GetVSize());
|
||||
void true_to_local(const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &true_vector,
|
||||
mfem::Vector &local_vector) {
|
||||
local_vector.SetSize(finite_element_space.GetVSize());
|
||||
|
||||
const mfem::Operator *prolongation = finite_element_space.GetProlongationMatrix();
|
||||
const mfem::Operator *prolongation =
|
||||
finite_element_space.GetProlongationMatrix();
|
||||
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->Mult(true_vector, local_vector);
|
||||
} else {
|
||||
local_vector = true_vector;
|
||||
}
|
||||
}
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->Mult(true_vector, local_vector);
|
||||
} else {
|
||||
local_vector = true_vector;
|
||||
}
|
||||
}
|
||||
|
||||
void local_to_true(
|
||||
const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &local_vector,
|
||||
mfem::Vector &true_vector
|
||||
) {
|
||||
MFEM_VERIFY(local_vector.Size() == finite_element_space.GetVSize(), "Local vector has the wrong size.");
|
||||
void local_to_true(const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &local_vector,
|
||||
mfem::Vector &true_vector) {
|
||||
MFEM_VERIFY(local_vector.Size() == finite_element_space.GetVSize(),
|
||||
"Local vector has the wrong size.");
|
||||
|
||||
true_vector.SetSize(finite_element_space.GetTrueVSize());
|
||||
true_vector = 0.0;
|
||||
true_vector.SetSize(finite_element_space.GetTrueVSize());
|
||||
true_vector = 0.0;
|
||||
|
||||
const mfem::Operator *prolongation = finite_element_space.GetProlongationMatrix();
|
||||
const mfem::Operator *prolongation =
|
||||
finite_element_space.GetProlongationMatrix();
|
||||
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->MultTranspose(local_vector, true_vector);
|
||||
} else {
|
||||
true_vector = local_vector;
|
||||
}
|
||||
}
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->MultTranspose(local_vector, true_vector);
|
||||
} else {
|
||||
true_vector = local_vector;
|
||||
}
|
||||
}
|
||||
|
||||
const mfem::IntegrationRule &get_source_rule(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mfem::FiniteElement &density_element,
|
||||
const mfem::FiniteElement &potential_element,
|
||||
const mfem::ElementTransformation &transformation
|
||||
) {
|
||||
using GravityField = mean_field::field::Field<mean_field::field::Gravity>;
|
||||
MFEM_VERIFY(
|
||||
density_element.GetOrder() == mean_field::field::Density::Scalar::familyOrder,
|
||||
"The prepared source trial element does not match the registered "
|
||||
"density field."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
potential_element.GetOrder() == mean_field::field::Gravity::Potential::familyOrder,
|
||||
"The prepared source test element does not match the registered "
|
||||
"gravity potential."
|
||||
);
|
||||
const mean_field::quadrature::Query query =
|
||||
GravityField::make_query<mean_field::field::Gravity::Form::SourceProjection>(
|
||||
mean_field::quadrature::QuadratureRole::discretization, transformation.OrderW(), {},
|
||||
mean_field::utils::DOMAINS::STELLAR, mean_field::quadrature::MappingKind::general
|
||||
);
|
||||
const mfem::IntegrationRule &
|
||||
get_source_rule(const mean_field::fem::FEM &f,
|
||||
const mfem::FiniteElement &density_element,
|
||||
const mfem::FiniteElement &potential_element,
|
||||
const mfem::ElementTransformation &transformation) {
|
||||
using GravityField = mean_field::field::Field<mean_field::field::Gravity>;
|
||||
MFEM_VERIFY(density_element.GetOrder() ==
|
||||
mean_field::field::Density::Scalar::familyOrder,
|
||||
"The prepared source trial element does not match the registered "
|
||||
"density field.");
|
||||
MFEM_VERIFY(potential_element.GetOrder() ==
|
||||
mean_field::field::Gravity::Potential::familyOrder,
|
||||
"The prepared source test element does not match the registered "
|
||||
"gravity potential.");
|
||||
const mean_field::quadrature::Query query = GravityField::make_query<
|
||||
mean_field::field::Gravity::Form::SourceProjection>(
|
||||
mean_field::quadrature::QuadratureRole::discretization,
|
||||
transformation.OrderW(), {}, mean_field::utils::DOMAINS::STELLAR,
|
||||
mean_field::quadrature::MappingKind::general);
|
||||
|
||||
return *f.quadratureFactory->get(query, transformation.GetGeometryType()).integration_rule;
|
||||
}
|
||||
return *f.quadratureFactory->get(query, transformation.GetGeometryType())
|
||||
.integration_rule;
|
||||
}
|
||||
|
||||
class FrozenMappedGravitySourceCoefficient final : public mfem::Coefficient {
|
||||
public:
|
||||
FrozenMappedGravitySourceCoefficient(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapperStateless &domain_mapper,
|
||||
const mfem::Vector &displacement_true
|
||||
)
|
||||
: m_fem(f),
|
||||
m_domain_mapper(domain_mapper),
|
||||
m_workspace(domain_mapper.GetDimension()) {
|
||||
true_to_local(*m_fem.displacementFes, displacement_true, m_displacement_local);
|
||||
}
|
||||
class FrozenMappedGravitySourceCoefficient final : public mfem::Coefficient {
|
||||
public:
|
||||
FrozenMappedGravitySourceCoefficient(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapper &domain_mapper,
|
||||
const mfem::Vector &displacement_true)
|
||||
: m_fem(f), m_domain_mapper(domain_mapper),
|
||||
m_workspace(domain_mapper.GetDimension()) {
|
||||
true_to_local(*m_fem.displacementFes, displacement_true,
|
||||
m_displacement_local);
|
||||
}
|
||||
|
||||
double Eval(
|
||||
mfem::ElementTransformation &transformation,
|
||||
const mfem::IntegrationPoint &integration_point
|
||||
) override {
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
double Eval(mfem::ElementTransformation &transformation,
|
||||
const mfem::IntegrationPoint &integration_point) override {
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
const int element_id = transformation.ElementNo;
|
||||
MFEM_VERIFY(
|
||||
element_id >= 0 && element_id < m_fem.mesh->GetNE(),
|
||||
const int element_id = transformation.ElementNo;
|
||||
MFEM_VERIFY(element_id >= 0 && element_id < m_fem.mesh->GetNE(),
|
||||
"Mapped gravity source coefficient received an invalid element "
|
||||
"ID."
|
||||
);
|
||||
if (transformation.Attribute == m_domain_mapper.GetVacuumElementAttribute()) {
|
||||
return 0.0;
|
||||
}
|
||||
"ID.");
|
||||
if (DomainSchema::template attribute_belongs_to<
|
||||
mean_field::utils::domain::Vacuum>(transformation.Attribute)) {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
LoadElement(element_id);
|
||||
const mean_field::mapping::ElementMappingData mapping_data{
|
||||
.displacement = *m_displacement_data, .compactification = *m_compactification_data
|
||||
};
|
||||
LoadElement(element_id);
|
||||
const mean_field::mapping::ElementMappingData mapping_data{
|
||||
.displacement = *m_displacement_data,
|
||||
.compactification = *m_compactification_data};
|
||||
|
||||
mean_field::mapping::VolumeMappingContext mapping_context;
|
||||
mean_field::mapping::VolumeMappingContext mapping_context;
|
||||
|
||||
const mean_field::mapping::MappingStatus status = m_domain_mapper.EvaluateVolume(
|
||||
mapping_data, transformation, integration_point, m_workspace, mapping_context
|
||||
);
|
||||
const mean_field::mapping::MappingStatus status =
|
||||
m_domain_mapper.EvaluateVolume(mapping_data, transformation,
|
||||
integration_point, m_workspace,
|
||||
mapping_context);
|
||||
|
||||
if (status != mean_field::mapping::MappingStatus::valid) {
|
||||
const mfem::FiniteElement &displacement_element = *m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element = *m_fem.compactificationFes->GetFE(element_id);
|
||||
if (status != mean_field::mapping::MappingStatus::valid) {
|
||||
const mfem::FiniteElement &displacement_element =
|
||||
*m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element =
|
||||
*m_fem.compactificationFes->GetFE(element_id);
|
||||
|
||||
mfem::Vector displacement_shape(displacement_element.GetDof());
|
||||
mfem::Vector compactification_shape(compactification_element.GetDof());
|
||||
mfem::Vector reference_position(m_domain_mapper.GetDimension());
|
||||
mfem::Vector displacement_value(m_domain_mapper.GetDimension());
|
||||
mfem::Vector displacement_shape(displacement_element.GetDof());
|
||||
mfem::Vector compactification_shape(compactification_element.GetDof());
|
||||
mfem::Vector reference_position(m_domain_mapper.GetDimension());
|
||||
mfem::Vector displacement_value(m_domain_mapper.GetDimension());
|
||||
|
||||
displacement_element.CalcShape(integration_point, displacement_shape);
|
||||
compactification_element.CalcShape(integration_point, compactification_shape);
|
||||
transformation.Transform(integration_point, reference_position);
|
||||
m_displacement_data->GetDofMatrix().MultTranspose(displacement_shape, displacement_value);
|
||||
displacement_element.CalcShape(integration_point, displacement_shape);
|
||||
compactification_element.CalcShape(integration_point,
|
||||
compactification_shape);
|
||||
transformation.Transform(integration_point, reference_position);
|
||||
m_displacement_data->GetDofMatrix().MultTranspose(displacement_shape,
|
||||
displacement_value);
|
||||
|
||||
const double compactification_coordinate = m_compactification_data->GetDofs() * compactification_shape;
|
||||
const double compactification_coordinate =
|
||||
m_compactification_data->GetDofs() * compactification_shape;
|
||||
|
||||
MFEM_ABORT(
|
||||
"Stateless domain mapping failed while preparing the "
|
||||
"gravity "
|
||||
"source operator."
|
||||
<< "\nMapping status = " << static_cast<int>(status) << "\nElement ID = " << element_id
|
||||
<< "\nElement attribute = " << transformation.Attribute
|
||||
<< "\nIntegration-point index = " << integration_point.index << "\nIntegration point = <"
|
||||
<< integration_point.x << ", " << integration_point.y << ", " << integration_point.z << ">"
|
||||
<< "\nReference position = <" << reference_position(0) << ", " << reference_position(1) << ", "
|
||||
<< reference_position(2) << ">"
|
||||
<< "\nReference radius = " << reference_position.Norml2() << "\nDisplacement value = <"
|
||||
<< displacement_value(0) << ", " << displacement_value(1) << ", " << displacement_value(2) << ">"
|
||||
<< "\nDisplacement magnitude = " << displacement_value.Norml2()
|
||||
<< "\nCompactification coordinate = " << compactification_coordinate
|
||||
<< "\nDisplacement ordering = " << static_cast<int>(m_fem.displacementFes->GetOrdering())
|
||||
);
|
||||
}
|
||||
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
|
||||
MFEM_ABORT(
|
||||
"Stateless domain mapping failed while preparing the "
|
||||
"gravity "
|
||||
"source operator."
|
||||
<< "\nMapping status = " << static_cast<int>(status)
|
||||
<< "\nElement ID = " << element_id
|
||||
<< "\nElement attribute = " << transformation.Attribute
|
||||
<< "\nIntegration-point index = " << integration_point.index
|
||||
<< "\nIntegration point = <" << integration_point.x << ", "
|
||||
<< integration_point.y << ", " << integration_point.z << ">"
|
||||
<< "\nReference position = <" << reference_position(0) << ", "
|
||||
<< reference_position(1) << ", " << reference_position(2) << ">"
|
||||
<< "\nReference radius = " << reference_position.Norml2()
|
||||
<< "\nDisplacement value = <" << displacement_value(0) << ", "
|
||||
<< displacement_value(1) << ", " << displacement_value(2) << ">"
|
||||
<< "\nDisplacement magnitude = " << displacement_value.Norml2()
|
||||
<< "\nCompactification coordinate = " << compactification_coordinate
|
||||
<< "\nDisplacement ordering = "
|
||||
<< static_cast<int>(m_fem.displacementFes->GetOrdering()));
|
||||
}
|
||||
const double mapping_determinant =
|
||||
mapping_context.mapping.mapping_determinant;
|
||||
MFEM_VERIFY(std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
|
||||
"Prepared gravity source operator encountered a non-positive "
|
||||
"or "
|
||||
"non-finite mapping determinant."
|
||||
);
|
||||
"non-finite mapping determinant.");
|
||||
|
||||
return 4.0 * std::numbers::pi * mean_field::utils::G * mapping_determinant;
|
||||
}
|
||||
return 4.0 * std::numbers::pi * mean_field::utils::G * mapping_determinant;
|
||||
}
|
||||
|
||||
private:
|
||||
void LoadElement(const int element_id) {
|
||||
if (element_id == m_cached_element_id) {
|
||||
return;
|
||||
}
|
||||
private:
|
||||
void LoadElement(const int element_id) {
|
||||
if (element_id == m_cached_element_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &displacement_element = *m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element = *m_fem.compactificationFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &displacement_element =
|
||||
*m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element =
|
||||
*m_fem.compactificationFes->GetFE(element_id);
|
||||
|
||||
mfem::DofTransformation *displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, m_displacement_dofs);
|
||||
mfem::DofTransformation *compactification_dof_transformation =
|
||||
m_fem.compactificationFes->GetElementDofs(element_id, m_compactification_dofs);
|
||||
mfem::DofTransformation *displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, m_displacement_dofs);
|
||||
mfem::DofTransformation *compactification_dof_transformation =
|
||||
m_fem.compactificationFes->GetElementDofs(element_id,
|
||||
m_compactification_dofs);
|
||||
|
||||
m_displacement_local.GetSubVector(m_displacement_dofs, m_element_displacement);
|
||||
m_fem.compactificationCoordinate->GetSubVector(m_compactification_dofs, m_element_compactification);
|
||||
m_displacement_local.GetSubVector(m_displacement_dofs,
|
||||
m_element_displacement);
|
||||
m_fem.compactificationCoordinate->GetSubVector(m_compactification_dofs,
|
||||
m_element_compactification);
|
||||
|
||||
if (displacement_dof_transformation != nullptr) {
|
||||
displacement_dof_transformation->InvTransformPrimal(m_element_displacement);
|
||||
}
|
||||
if (displacement_dof_transformation != nullptr) {
|
||||
displacement_dof_transformation->InvTransformPrimal(
|
||||
m_element_displacement);
|
||||
}
|
||||
|
||||
if (compactification_dof_transformation != nullptr) {
|
||||
compactification_dof_transformation->InvTransformPrimal(m_element_compactification);
|
||||
}
|
||||
if (compactification_dof_transformation != nullptr) {
|
||||
compactification_dof_transformation->InvTransformPrimal(
|
||||
m_element_compactification);
|
||||
}
|
||||
|
||||
m_displacement_data = std::make_unique<mean_field::mapping::ElementDisplacementData>(
|
||||
mean_field::mapping::ElementDisplacementDataFromElementVDofs(
|
||||
displacement_element, m_element_displacement
|
||||
)
|
||||
);
|
||||
m_displacement_data =
|
||||
std::make_unique<mean_field::mapping::ElementDisplacementData>(
|
||||
mean_field::mapping::ElementDisplacementDataFromElementVDofs(
|
||||
displacement_element, m_element_displacement));
|
||||
|
||||
m_compactification_data = std::make_unique<mean_field::mapping::ElementCompactificationData>(
|
||||
compactification_element, m_element_compactification
|
||||
);
|
||||
m_compactification_data =
|
||||
std::make_unique<mean_field::mapping::ElementCompactificationData>(
|
||||
compactification_element, m_element_compactification);
|
||||
|
||||
m_cached_element_id = element_id;
|
||||
}
|
||||
m_cached_element_id = element_id;
|
||||
}
|
||||
|
||||
const mean_field::fem::FEM &m_fem;
|
||||
const mean_field::mapping::DomainMapperStateless &m_domain_mapper;
|
||||
const mean_field::fem::FEM &m_fem;
|
||||
const mean_field::mapping::DomainMapper &m_domain_mapper;
|
||||
|
||||
mfem::Vector m_displacement_local;
|
||||
mfem::Vector m_displacement_local;
|
||||
|
||||
mfem::Array<int> m_displacement_dofs;
|
||||
mfem::Array<int> m_compactification_dofs;
|
||||
mfem::Array<int> m_displacement_dofs;
|
||||
mfem::Array<int> m_compactification_dofs;
|
||||
|
||||
mfem::Vector m_element_displacement;
|
||||
mfem::Vector m_element_compactification;
|
||||
mfem::Vector m_element_displacement;
|
||||
mfem::Vector m_element_compactification;
|
||||
|
||||
std::unique_ptr<mean_field::mapping::ElementDisplacementData> m_displacement_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementCompactificationData> m_compactification_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementDisplacementData>
|
||||
m_displacement_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementCompactificationData>
|
||||
m_compactification_data;
|
||||
|
||||
mean_field::mapping::DomainMapperStateless::Workspace m_workspace;
|
||||
int m_cached_element_id{-1};
|
||||
};
|
||||
mean_field::mapping::DomainMapper::Workspace m_workspace;
|
||||
int m_cached_element_id{-1};
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace mean_field::operators {
|
||||
PreparedMappedGravitySourceOperator::PreparedMappedGravitySourceOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
)
|
||||
: Operator(
|
||||
get_operator_height(f),
|
||||
get_operator_width(f)
|
||||
),
|
||||
m_fem(f),
|
||||
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 "
|
||||
"finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityPotentialFes != nullptr, "PreparedMappedGravitySourceOperator requires the "
|
||||
"gravity-potential "
|
||||
"finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.displacementFes != nullptr, "PreparedMappedGravitySourceOperator requires "
|
||||
"the displacement finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.compactificationFes != nullptr, "PreparedMappedGravitySourceOperator requires the compactification "
|
||||
"finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.compactificationCoordinate != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the compactification "
|
||||
"coordinate."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.quadratureFactory != nullptr, "PreparedMappedGravitySourceOperator "
|
||||
"requires the quadrature-rule factory."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
domain_mapper.GetDimension() == f.mesh->Dimension(),
|
||||
"The stateless domain-mapper dimension does not match the mesh "
|
||||
"dimension."
|
||||
);
|
||||
PreparedMappedGravitySourceOperator::PreparedMappedGravitySourceOperator(
|
||||
const fem::FEM &f, const mapping::DomainMapper &domain_mapper)
|
||||
: Operator(get_operator_height(f), get_operator_width(f)), m_fem(f),
|
||||
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 "
|
||||
"finite-element space.");
|
||||
MFEM_VERIFY(f.gravityPotentialFes != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the "
|
||||
"gravity-potential "
|
||||
"finite-element space.");
|
||||
MFEM_VERIFY(f.displacementFes != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires "
|
||||
"the displacement finite-element space.");
|
||||
MFEM_VERIFY(
|
||||
f.compactificationFes != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the compactification "
|
||||
"finite-element space.");
|
||||
MFEM_VERIFY(
|
||||
f.compactificationCoordinate != nullptr,
|
||||
"PreparedMappedGravitySourceOperator requires the compactification "
|
||||
"coordinate.");
|
||||
MFEM_VERIFY(f.quadratureFactory != nullptr,
|
||||
"PreparedMappedGravitySourceOperator "
|
||||
"requires the quadrature-rule factory.");
|
||||
MFEM_VERIFY(domain_mapper.GetDimension() == f.mesh->Dimension(),
|
||||
"The stateless domain-mapper dimension does not match the mesh "
|
||||
"dimension.");
|
||||
|
||||
utils::populate_element_mask(f.mesh.get(), utils::DOMAINS::STELLAR, m_stellar_marker);
|
||||
m_stellar_marker =
|
||||
utils::domain::make_attribute_marker<utils::domain::Stellar,
|
||||
DomainSchema>(*f.mesh);
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::Prepare(
|
||||
const mfem::Vector &displacement) {
|
||||
MFEM_VERIFY(displacement.Size() == m_displacement_map.reduced_size(),
|
||||
"PreparedMappedGravitySourceOperator received a displacement "
|
||||
"vector "
|
||||
"with the wrong size.");
|
||||
|
||||
for (int i = 0; i < displacement.Size(); ++i) {
|
||||
MFEM_VERIFY(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, 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);
|
||||
|
||||
if (attribute <= 0 || attribute > m_stellar_marker.Size() ||
|
||||
m_stellar_marker[attribute - 1] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::Prepare(const mfem::Vector &displacement) {
|
||||
MFEM_VERIFY(
|
||||
displacement.Size() == m_displacement_map.reduced_size(),
|
||||
"PreparedMappedGravitySourceOperator received a displacement "
|
||||
"vector "
|
||||
"with the wrong size."
|
||||
);
|
||||
m_elements.emplace_back();
|
||||
ElementPAData &data = m_elements.back();
|
||||
|
||||
for (int i = 0; i < displacement.Size(); ++i) {
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(displacement(i)), "PreparedMappedGravitySourceOperator received a non-finite "
|
||||
"displacement value."
|
||||
);
|
||||
}
|
||||
data.element_id = element_id;
|
||||
|
||||
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());
|
||||
data.density_dof_transformation =
|
||||
m_fem.densityFes->GetElementDofs(element_id, data.density_dofs);
|
||||
|
||||
FrozenMappedGravitySourceCoefficient source_coefficient(m_fem, m_domain_mapper, m_displacement_true);
|
||||
data.potential_dof_transformation =
|
||||
m_fem.gravityPotentialFes->GetElementDofs(element_id,
|
||||
data.potential_dofs);
|
||||
|
||||
for (int element_id = 0; element_id < m_fem.mesh->GetNE(); ++element_id) {
|
||||
const int attribute = m_fem.mesh->GetAttribute(element_id);
|
||||
const mfem::FiniteElement &density_element =
|
||||
*m_fem.densityFes->GetFE(element_id);
|
||||
|
||||
if (attribute <= 0 || attribute > m_stellar_marker.Size() || m_stellar_marker[attribute - 1] == 0) {
|
||||
continue;
|
||||
}
|
||||
const mfem::FiniteElement &potential_element =
|
||||
*m_fem.gravityPotentialFes->GetFE(element_id);
|
||||
|
||||
m_elements.emplace_back();
|
||||
ElementPAData &data = m_elements.back();
|
||||
mfem::ElementTransformation &transformation =
|
||||
*m_fem.mesh->GetElementTransformation(element_id);
|
||||
|
||||
data.element_id = element_id;
|
||||
const mfem::IntegrationRule &integration_rule = get_source_rule(
|
||||
m_fem, density_element, potential_element, transformation);
|
||||
|
||||
data.density_dof_transformation = m_fem.densityFes->GetElementDofs(element_id, data.density_dofs);
|
||||
const int quadrature_point_count = integration_rule.GetNPoints();
|
||||
|
||||
data.potential_dof_transformation =
|
||||
m_fem.gravityPotentialFes->GetElementDofs(element_id, data.potential_dofs);
|
||||
const int density_dof_count = density_element.GetDof();
|
||||
|
||||
const mfem::FiniteElement &density_element = *m_fem.densityFes->GetFE(element_id);
|
||||
const int potential_dof_count = potential_element.GetDof();
|
||||
|
||||
const mfem::FiniteElement &potential_element = *m_fem.gravityPotentialFes->GetFE(element_id);
|
||||
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
|
||||
|
||||
mfem::ElementTransformation &transformation = *m_fem.mesh->GetElementTransformation(element_id);
|
||||
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
|
||||
|
||||
const mfem::IntegrationRule &integration_rule =
|
||||
get_source_rule(m_fem, density_element, potential_element, transformation);
|
||||
data.quadrature_data.SetSize(quadrature_point_count);
|
||||
|
||||
const int quadrature_point_count = integration_rule.GetNPoints();
|
||||
mfem::Vector density_shape(density_dof_count);
|
||||
mfem::Vector potential_shape(potential_dof_count);
|
||||
|
||||
const int density_dof_count = density_element.GetDof();
|
||||
for (int quadrature_point = 0; quadrature_point < quadrature_point_count;
|
||||
++quadrature_point) {
|
||||
const mfem::IntegrationPoint &integration_point =
|
||||
integration_rule.IntPoint(quadrature_point);
|
||||
|
||||
const int potential_dof_count = potential_element.GetDof();
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
data.density_basis.SetSize(quadrature_point_count, density_dof_count);
|
||||
// CalcPhysShape matches the scalar mixed-mass discretization,
|
||||
// including the finite-element map type.
|
||||
density_element.CalcPhysShape(transformation, density_shape);
|
||||
|
||||
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
|
||||
potential_element.CalcPhysShape(transformation, potential_shape);
|
||||
|
||||
data.quadrature_data.SetSize(quadrature_point_count);
|
||||
for (int i = 0; i < density_dof_count; ++i) {
|
||||
data.density_basis(quadrature_point, i) = density_shape(i);
|
||||
}
|
||||
|
||||
mfem::Vector density_shape(density_dof_count);
|
||||
mfem::Vector potential_shape(potential_dof_count);
|
||||
for (int i = 0; i < potential_dof_count; ++i) {
|
||||
data.potential_basis(quadrature_point, i) = potential_shape(i);
|
||||
}
|
||||
|
||||
for (int quadrature_point = 0; quadrature_point < quadrature_point_count; ++quadrature_point) {
|
||||
const mfem::IntegrationPoint &integration_point = integration_rule.IntPoint(quadrature_point);
|
||||
const double coefficient_value =
|
||||
source_coefficient.Eval(transformation, integration_point);
|
||||
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
// CalcPhysShape matches the scalar mixed-mass discretization,
|
||||
// including the finite-element map type.
|
||||
density_element.CalcPhysShape(transformation, density_shape);
|
||||
const double quadrature_value = integration_point.weight *
|
||||
transformation.Weight() *
|
||||
coefficient_value;
|
||||
|
||||
potential_element.CalcPhysShape(transformation, potential_shape);
|
||||
MFEM_VERIFY(std::isfinite(quadrature_value) && quadrature_value > 0.0,
|
||||
"Prepared gravity source operator encountered invalid "
|
||||
"quadrature data on element "
|
||||
<< element_id << ", quadrature point " << quadrature_point
|
||||
<< ".");
|
||||
|
||||
for (int i = 0; i < density_dof_count; ++i) {
|
||||
data.density_basis(quadrature_point, i) = density_shape(i);
|
||||
}
|
||||
|
||||
for (int i = 0; i < potential_dof_count; ++i) {
|
||||
data.potential_basis(quadrature_point, i) = potential_shape(i);
|
||||
}
|
||||
|
||||
const double coefficient_value = source_coefficient.Eval(transformation, integration_point);
|
||||
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
const double quadrature_value = integration_point.weight * transformation.Weight() * coefficient_value;
|
||||
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(quadrature_value) && quadrature_value > 0.0,
|
||||
"Prepared gravity source operator encountered invalid "
|
||||
"quadrature data on element "
|
||||
<< element_id << ", quadrature point " << quadrature_point << "."
|
||||
);
|
||||
|
||||
data.quadrature_data(quadrature_point) = quadrature_value;
|
||||
}
|
||||
}
|
||||
|
||||
MFEM_VERIFY(!m_elements.empty(), "PreparedMappedGravitySourceOperator found no stellar elements.");
|
||||
|
||||
m_is_prepared = true;
|
||||
++m_preparation_count;
|
||||
data.quadrature_data(quadrature_point) = quadrature_value;
|
||||
}
|
||||
void PreparedMappedGravitySourceOperator::Mult(
|
||||
const mfem::Vector &density,
|
||||
mfem::Vector &action
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "PreparedMappedGravitySourceOperator must be prepared before "
|
||||
"Mult is called."
|
||||
);
|
||||
}
|
||||
|
||||
MFEM_VERIFY(
|
||||
density.Size() == Width(), "PreparedMappedGravitySourceOperator received a density vector "
|
||||
"with the wrong size."
|
||||
);
|
||||
MFEM_VERIFY(!m_elements.empty(),
|
||||
"PreparedMappedGravitySourceOperator found no stellar elements.");
|
||||
|
||||
m_density_true.SetSize(m_density_map.full_size());
|
||||
m_density_map.scatter(density, m_density_true);
|
||||
m_is_prepared = true;
|
||||
++m_preparation_count;
|
||||
}
|
||||
void PreparedMappedGravitySourceOperator::Mult(const mfem::Vector &density,
|
||||
mfem::Vector &action) const {
|
||||
MFEM_VERIFY(m_is_prepared,
|
||||
"PreparedMappedGravitySourceOperator must be prepared before "
|
||||
"Mult is called.");
|
||||
|
||||
mfem::Vector density_local;
|
||||
MFEM_VERIFY(density.Size() == Width(),
|
||||
"PreparedMappedGravitySourceOperator received a density vector "
|
||||
"with the wrong size.");
|
||||
|
||||
true_to_local(*m_fem.densityFes, m_density_true, density_local);
|
||||
m_density_true.SetSize(m_density_map.full_size());
|
||||
m_density_map.scatter(density, m_density_true);
|
||||
|
||||
mfem::Vector local_action(m_fem.gravityPotentialFes->GetVSize());
|
||||
local_action = 0.0;
|
||||
mfem::Vector density_local;
|
||||
|
||||
mfem::Vector element_density;
|
||||
mfem::Vector quadrature_density;
|
||||
mfem::Vector element_action;
|
||||
true_to_local(*m_fem.densityFes, m_density_true, density_local);
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
density_local.GetSubVector(data.density_dofs, element_density);
|
||||
mfem::Vector local_action(m_fem.gravityPotentialFes->GetVSize());
|
||||
local_action = 0.0;
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->InvTransformPrimal(element_density);
|
||||
}
|
||||
mfem::Vector element_density;
|
||||
mfem::Vector quadrature_density;
|
||||
mfem::Vector element_action;
|
||||
|
||||
quadrature_density.SetSize(data.quadrature_data.Size());
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
density_local.GetSubVector(data.density_dofs, element_density);
|
||||
|
||||
// B_density * x_e
|
||||
data.density_basis.Mult(element_density, quadrature_density);
|
||||
|
||||
// D * B_density * x_e
|
||||
for (int q = 0; q < quadrature_density.Size(); ++q) {
|
||||
quadrature_density(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
element_action.SetSize(data.potential_dofs.Size());
|
||||
|
||||
// B_potential^T * D * B_density * x_e
|
||||
data.potential_basis.MultTranspose(quadrature_density, element_action);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->TransformDual(element_action);
|
||||
}
|
||||
|
||||
local_action.AddElementVector(data.potential_dofs, element_action);
|
||||
}
|
||||
|
||||
local_to_true(*m_fem.gravityPotentialFes, local_action, m_action_true);
|
||||
action.SetSize(Height());
|
||||
m_potential_map.gather(m_action_true, action);
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->InvTransformPrimal(element_density);
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::MultTranspose(
|
||||
const mfem::Vector &potential,
|
||||
mfem::Vector &action
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "PreparedMappedGravitySourceOperator must be prepared before "
|
||||
"MultTranspose is called."
|
||||
);
|
||||
quadrature_density.SetSize(data.quadrature_data.Size());
|
||||
|
||||
MFEM_VERIFY(
|
||||
potential.Size() == Height(), "PreparedMappedGravitySourceOperator received a potential vector "
|
||||
"with the wrong size."
|
||||
);
|
||||
// B_density * x_e
|
||||
data.density_basis.Mult(element_density, quadrature_density);
|
||||
|
||||
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, m_potential_true, potential_local);
|
||||
|
||||
mfem::Vector local_action(m_fem.densityFes->GetVSize());
|
||||
local_action = 0.0;
|
||||
|
||||
mfem::Vector element_potential;
|
||||
mfem::Vector quadrature_potential;
|
||||
mfem::Vector element_action;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
potential_local.GetSubVector(data.potential_dofs, element_potential);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->InvTransformPrimal(element_potential);
|
||||
}
|
||||
|
||||
quadrature_potential.SetSize(data.quadrature_data.Size());
|
||||
|
||||
data.potential_basis.Mult(element_potential, quadrature_potential);
|
||||
|
||||
for (int q = 0; q < quadrature_potential.Size(); ++q) {
|
||||
quadrature_potential(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
element_action.SetSize(data.density_dofs.Size());
|
||||
|
||||
data.density_basis.MultTranspose(quadrature_potential, element_action);
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->TransformDual(element_action);
|
||||
}
|
||||
|
||||
local_action.AddElementVector(data.density_dofs, element_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;
|
||||
// D * B_density * x_e
|
||||
for (int q = 0; q < quadrature_density.Size(); ++q) {
|
||||
quadrature_density(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
std::uint64_t PreparedMappedGravitySourceOperator::GetPreparationCount() const noexcept {
|
||||
return m_preparation_count;
|
||||
element_action.SetSize(data.potential_dofs.Size());
|
||||
|
||||
// B_potential^T * D * B_density * x_e
|
||||
data.potential_basis.MultTranspose(quadrature_density, element_action);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->TransformDual(element_action);
|
||||
}
|
||||
|
||||
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetDensityMap() const noexcept {
|
||||
return m_density_map;
|
||||
local_action.AddElementVector(data.potential_dofs, element_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, mfem::Vector &action) const {
|
||||
MFEM_VERIFY(m_is_prepared,
|
||||
"PreparedMappedGravitySourceOperator must be prepared before "
|
||||
"MultTranspose is called.");
|
||||
|
||||
MFEM_VERIFY(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, m_potential_true, potential_local);
|
||||
|
||||
mfem::Vector local_action(m_fem.densityFes->GetVSize());
|
||||
local_action = 0.0;
|
||||
|
||||
mfem::Vector element_potential;
|
||||
mfem::Vector quadrature_potential;
|
||||
mfem::Vector element_action;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
potential_local.GetSubVector(data.potential_dofs, element_potential);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->InvTransformPrimal(element_potential);
|
||||
}
|
||||
|
||||
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetPotentialMap() const noexcept {
|
||||
return m_potential_map;
|
||||
quadrature_potential.SetSize(data.quadrature_data.Size());
|
||||
|
||||
data.potential_basis.Mult(element_potential, quadrature_potential);
|
||||
|
||||
for (int q = 0; q < quadrature_potential.Size(); ++q) {
|
||||
quadrature_potential(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
const field::FieldDofMap &PreparedMappedGravitySourceOperator::GetDisplacementMap() const noexcept {
|
||||
return m_displacement_map;
|
||||
element_action.SetSize(data.density_dofs.Size());
|
||||
|
||||
data.density_basis.MultTranspose(quadrature_potential, element_action);
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->TransformDual(element_action);
|
||||
}
|
||||
|
||||
local_action.AddElementVector(data.density_dofs, element_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;
|
||||
}
|
||||
|
||||
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,379 +8,405 @@ module mean_field;
|
||||
import :operators.prepared_hdiv_mass;
|
||||
|
||||
namespace {
|
||||
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
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 mean_field::field::make_field_dof_map<mean_field::field::Gravity, DomainSchema>(*f.gravityFluxFes)
|
||||
.reduced_size();
|
||||
int get_operator_size(const mean_field::fem::FEM &f) {
|
||||
MFEM_VERIFY(f.gravityFluxFes != nullptr,
|
||||
"PreparedMappedHDivMassOperator requires the "
|
||||
"gravity-gradient finite-element space.");
|
||||
return mean_field::field::make_field_dof_map<mean_field::field::Gravity,
|
||||
DomainSchema>(*f.gravityFluxFes)
|
||||
.reduced_size();
|
||||
}
|
||||
|
||||
void true_to_local(const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &true_vector,
|
||||
mfem::Vector &local_vector) {
|
||||
local_vector.SetSize(finite_element_space.GetVSize());
|
||||
|
||||
const mfem::Operator *prolongation =
|
||||
finite_element_space.GetProlongationMatrix();
|
||||
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->Mult(true_vector, local_vector);
|
||||
} else {
|
||||
local_vector = true_vector;
|
||||
}
|
||||
}
|
||||
|
||||
int find_representative_element(const mean_field::fem::FEM &f,
|
||||
const mfem::Array<int> &marker) {
|
||||
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
|
||||
const int attribute = f.mesh->GetAttribute(element_id);
|
||||
|
||||
if (attribute > 0 && attribute <= marker.Size() &&
|
||||
marker[attribute - 1] != 0) {
|
||||
return element_id;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void validate_uniform_domain_discretization(
|
||||
const mean_field::fem::FEM &f, const mfem::Array<int> &marker,
|
||||
const int representative_element_id) {
|
||||
const mfem::FiniteElement &representative_element =
|
||||
*f.gravityFluxFes->GetFE(representative_element_id);
|
||||
const mfem::ElementTransformation &representative_transformation =
|
||||
*f.mesh->GetElementTransformation(representative_element_id);
|
||||
|
||||
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
|
||||
const int attribute = f.mesh->GetAttribute(element_id);
|
||||
|
||||
if (attribute <= 0 || attribute > marker.Size() ||
|
||||
marker[attribute - 1] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
void true_to_local(
|
||||
const mfem::ParFiniteElementSpace &finite_element_space,
|
||||
const mfem::Vector &true_vector,
|
||||
mfem::Vector &local_vector
|
||||
) {
|
||||
local_vector.SetSize(finite_element_space.GetVSize());
|
||||
const mfem::FiniteElement &element = *f.gravityFluxFes->GetFE(element_id);
|
||||
const mfem::ElementTransformation &transformation =
|
||||
*f.mesh->GetElementTransformation(element_id);
|
||||
|
||||
const mfem::Operator *prolongation = finite_element_space.GetProlongationMatrix();
|
||||
|
||||
if (prolongation != nullptr) {
|
||||
prolongation->Mult(true_vector, local_vector);
|
||||
} else {
|
||||
local_vector = true_vector;
|
||||
}
|
||||
}
|
||||
|
||||
int find_representative_element(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mfem::Array<int> &marker
|
||||
) {
|
||||
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
|
||||
const int attribute = f.mesh->GetAttribute(element_id);
|
||||
|
||||
if (attribute > 0 && attribute <= marker.Size() && marker[attribute - 1] != 0) {
|
||||
return element_id;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
void validate_uniform_domain_discretization(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mfem::Array<int> &marker,
|
||||
const int representative_element_id
|
||||
) {
|
||||
const mfem::FiniteElement &representative_element = *f.gravityFluxFes->GetFE(representative_element_id);
|
||||
const mfem::ElementTransformation &representative_transformation =
|
||||
*f.mesh->GetElementTransformation(representative_element_id);
|
||||
|
||||
for (int element_id = 0; element_id < f.mesh->GetNE(); ++element_id) {
|
||||
const int attribute = f.mesh->GetAttribute(element_id);
|
||||
|
||||
if (attribute <= 0 || attribute > marker.Size() || marker[attribute - 1] == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &element = *f.gravityFluxFes->GetFE(element_id);
|
||||
const mfem::ElementTransformation &transformation = *f.mesh->GetElementTransformation(element_id);
|
||||
|
||||
MFEM_VERIFY(
|
||||
element.GetGeomType() == representative_element.GetGeomType(),
|
||||
MFEM_VERIFY(element.GetGeomType() == representative_element.GetGeomType(),
|
||||
"Prepared H(div) mass domains currently require a uniform "
|
||||
"element "
|
||||
"geometry."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
element.GetOrder() == representative_element.GetOrder(),
|
||||
"geometry.");
|
||||
MFEM_VERIFY(element.GetOrder() == representative_element.GetOrder(),
|
||||
"Prepared H(div) mass domains currently require a uniform "
|
||||
"finite-element order."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
transformation.OrderW() == representative_transformation.OrderW(),
|
||||
"finite-element order.");
|
||||
MFEM_VERIFY(transformation.OrderW() ==
|
||||
representative_transformation.OrderW(),
|
||||
"Prepared H(div) mass domains currently require a uniform "
|
||||
"geometry-weight order."
|
||||
);
|
||||
}
|
||||
"geometry-weight order.");
|
||||
}
|
||||
}
|
||||
|
||||
class FrozenMappedHDivMassCoefficient final : public mfem::MatrixCoefficient {
|
||||
public:
|
||||
FrozenMappedHDivMassCoefficient(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapper &domain_mapper,
|
||||
const mfem::Vector &displacement_true, bool elevates_vacuum)
|
||||
: MatrixCoefficient(domain_mapper.GetDimension()), m_fem(f),
|
||||
m_domain_mapper(domain_mapper),
|
||||
m_workspace(domain_mapper.GetDimension()),
|
||||
m_elevates_vacuum(elevates_vacuum) {
|
||||
true_to_local(*m_fem.displacementFes, displacement_true,
|
||||
m_displacement_local);
|
||||
}
|
||||
|
||||
void Eval(mfem::DenseMatrix &mass_tensor,
|
||||
mfem::ElementTransformation &transformation,
|
||||
const mfem::IntegrationPoint &integration_point) override {
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
|
||||
const int element_id = transformation.ElementNo;
|
||||
MFEM_VERIFY(
|
||||
element_id >= 0 && element_id < m_fem.mesh->GetNE(),
|
||||
"Mapped H(div) mass coefficient received an invalid element ID.");
|
||||
|
||||
const bool element_is_vacuum = DomainSchema::template attribute_belongs_to<
|
||||
mean_field::utils::domain::Vacuum>(transformation.Attribute);
|
||||
|
||||
if (element_is_vacuum != m_elevates_vacuum) {
|
||||
mass_tensor.SetSize(m_domain_mapper.GetDimension());
|
||||
mass_tensor = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
class FrozenMappedHDivMassCoefficient final : public mfem::MatrixCoefficient {
|
||||
public:
|
||||
FrozenMappedHDivMassCoefficient(
|
||||
const mean_field::fem::FEM &f,
|
||||
const mean_field::mapping::DomainMapperStateless &domain_mapper,
|
||||
const mfem::Vector &displacement_true,
|
||||
bool elevates_vacuum
|
||||
)
|
||||
: MatrixCoefficient(domain_mapper.GetDimension()),
|
||||
m_fem(f),
|
||||
m_domain_mapper(domain_mapper),
|
||||
m_workspace(domain_mapper.GetDimension()),
|
||||
m_elevates_vacuum(elevates_vacuum) {
|
||||
true_to_local(*m_fem.displacementFes, displacement_true, m_displacement_local);
|
||||
}
|
||||
LoadElement(element_id);
|
||||
|
||||
void Eval(
|
||||
mfem::DenseMatrix &mass_tensor,
|
||||
mfem::ElementTransformation &transformation,
|
||||
const mfem::IntegrationPoint &integration_point
|
||||
) override {
|
||||
transformation.SetIntPoint(&integration_point);
|
||||
const mean_field::mapping::ElementMappingData mapping_data{
|
||||
.displacement = *m_displacement_data,
|
||||
.compactification = *m_compactification_data};
|
||||
|
||||
const int element_id = transformation.ElementNo;
|
||||
MFEM_VERIFY(
|
||||
element_id >= 0 && element_id < m_fem.mesh->GetNE(),
|
||||
"Mapped H(div) mass coefficient received an invalid element ID."
|
||||
);
|
||||
mean_field::mapping::VolumeMappingContext mapping_context;
|
||||
|
||||
const bool element_is_vacuum = transformation.Attribute == m_domain_mapper.GetVacuumElementAttribute();
|
||||
const mean_field::mapping::MappingStatus status =
|
||||
m_domain_mapper.EvaluateVolume(mapping_data, transformation,
|
||||
integration_point, m_workspace,
|
||||
mapping_context);
|
||||
|
||||
if (element_is_vacuum != m_elevates_vacuum) {
|
||||
mass_tensor.SetSize(m_domain_mapper.GetDimension());
|
||||
mass_tensor = 0.0;
|
||||
return;
|
||||
}
|
||||
|
||||
LoadElement(element_id);
|
||||
|
||||
const mean_field::mapping::ElementMappingData mapping_data{
|
||||
.displacement = *m_displacement_data, .compactification = *m_compactification_data
|
||||
};
|
||||
|
||||
mean_field::mapping::VolumeMappingContext mapping_context;
|
||||
|
||||
const mean_field::mapping::MappingStatus status = m_domain_mapper.EvaluateVolume(
|
||||
mapping_data, transformation, integration_point, m_workspace, mapping_context
|
||||
);
|
||||
|
||||
MFEM_VERIFY(
|
||||
status == mean_field::mapping::MappingStatus::valid,
|
||||
MFEM_VERIFY(status == mean_field::mapping::MappingStatus::valid,
|
||||
"Stateless domain mapping failed while preparing the H(div) "
|
||||
"mass "
|
||||
"operator. Mapping status = "
|
||||
<< static_cast<int>(status) << ", element ID = " << element_id
|
||||
<< static_cast<int>(status)
|
||||
<< ", element ID = " << element_id
|
||||
<< ", element attribute = " << transformation.Attribute
|
||||
<< ", coefficient domain = " << (m_elevates_vacuum ? "vacuum" : "stellar")
|
||||
);
|
||||
<< ", coefficient domain = "
|
||||
<< (m_elevates_vacuum ? "vacuum" : "stellar"));
|
||||
|
||||
const mfem::DenseMatrix &mapping_jacobian = mapping_context.mapping.mapping_jacobian;
|
||||
const double mapping_determinant = mapping_context.mapping.mapping_determinant;
|
||||
const mfem::DenseMatrix &mapping_jacobian =
|
||||
mapping_context.mapping.mapping_jacobian;
|
||||
const double mapping_determinant =
|
||||
mapping_context.mapping.mapping_determinant;
|
||||
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
|
||||
MFEM_VERIFY(std::isfinite(mapping_determinant) && mapping_determinant > 0.0,
|
||||
"Prepared H(div) mass operator encountered a non-positive or "
|
||||
"non-finite mapping determinant."
|
||||
);
|
||||
"non-finite mapping determinant.");
|
||||
|
||||
mfem::MultAtB(mapping_jacobian, mapping_jacobian, mass_tensor);
|
||||
mass_tensor *= 1.0 / mapping_determinant;
|
||||
}
|
||||
mfem::MultAtB(mapping_jacobian, mapping_jacobian, mass_tensor);
|
||||
mass_tensor *= 1.0 / mapping_determinant;
|
||||
}
|
||||
|
||||
private:
|
||||
void LoadElement(const int element_id) {
|
||||
if (element_id == m_cached_element_id) {
|
||||
return;
|
||||
}
|
||||
private:
|
||||
void LoadElement(const int element_id) {
|
||||
if (element_id == m_cached_element_id) {
|
||||
return;
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &displacement_element = *m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element = *m_fem.compactificationFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &displacement_element =
|
||||
*m_fem.displacementFes->GetFE(element_id);
|
||||
const mfem::FiniteElement &compactification_element =
|
||||
*m_fem.compactificationFes->GetFE(element_id);
|
||||
|
||||
mfem::DofTransformation *displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, m_displacement_dofs);
|
||||
mfem::DofTransformation *compactification_dof_transformation =
|
||||
m_fem.compactificationFes->GetElementDofs(element_id, m_compactification_dofs);
|
||||
mfem::DofTransformation *displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, m_displacement_dofs);
|
||||
mfem::DofTransformation *compactification_dof_transformation =
|
||||
m_fem.compactificationFes->GetElementDofs(element_id,
|
||||
m_compactification_dofs);
|
||||
|
||||
m_displacement_local.GetSubVector(m_displacement_dofs, m_element_displacement);
|
||||
m_fem.compactificationCoordinate->GetSubVector(m_compactification_dofs, m_element_compactification);
|
||||
m_displacement_local.GetSubVector(m_displacement_dofs,
|
||||
m_element_displacement);
|
||||
m_fem.compactificationCoordinate->GetSubVector(m_compactification_dofs,
|
||||
m_element_compactification);
|
||||
|
||||
if (displacement_dof_transformation != nullptr) {
|
||||
displacement_dof_transformation->InvTransformPrimal(m_element_displacement);
|
||||
}
|
||||
if (displacement_dof_transformation != nullptr) {
|
||||
displacement_dof_transformation->InvTransformPrimal(
|
||||
m_element_displacement);
|
||||
}
|
||||
|
||||
if (compactification_dof_transformation != nullptr) {
|
||||
compactification_dof_transformation->InvTransformPrimal(m_element_compactification);
|
||||
}
|
||||
if (compactification_dof_transformation != nullptr) {
|
||||
compactification_dof_transformation->InvTransformPrimal(
|
||||
m_element_compactification);
|
||||
}
|
||||
|
||||
m_displacement_data = std::make_unique<mean_field::mapping::ElementDisplacementData>(
|
||||
mean_field::mapping::ElementDisplacementDataFromElementVDofs(
|
||||
displacement_element, m_element_displacement
|
||||
)
|
||||
);
|
||||
m_displacement_data =
|
||||
std::make_unique<mean_field::mapping::ElementDisplacementData>(
|
||||
mean_field::mapping::ElementDisplacementDataFromElementVDofs(
|
||||
displacement_element, m_element_displacement));
|
||||
|
||||
m_compactification_data = std::make_unique<mean_field::mapping::ElementCompactificationData>(
|
||||
compactification_element, m_element_compactification
|
||||
);
|
||||
m_compactification_data =
|
||||
std::make_unique<mean_field::mapping::ElementCompactificationData>(
|
||||
compactification_element, m_element_compactification);
|
||||
|
||||
m_cached_element_id = element_id;
|
||||
}
|
||||
m_cached_element_id = element_id;
|
||||
}
|
||||
|
||||
const mean_field::fem::FEM &m_fem;
|
||||
const mean_field::mapping::DomainMapperStateless &m_domain_mapper;
|
||||
const mean_field::fem::FEM &m_fem;
|
||||
const mean_field::mapping::DomainMapper &m_domain_mapper;
|
||||
|
||||
mfem::Vector m_displacement_local;
|
||||
mfem::Vector m_displacement_local;
|
||||
|
||||
mfem::Array<int> m_displacement_dofs;
|
||||
mfem::Array<int> m_compactification_dofs;
|
||||
mfem::Array<int> m_displacement_dofs;
|
||||
mfem::Array<int> m_compactification_dofs;
|
||||
|
||||
mfem::Vector m_element_displacement;
|
||||
mfem::Vector m_element_compactification;
|
||||
mfem::Vector m_element_displacement;
|
||||
mfem::Vector m_element_compactification;
|
||||
|
||||
std::unique_ptr<mean_field::mapping::ElementDisplacementData> m_displacement_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementCompactificationData> m_compactification_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementDisplacementData>
|
||||
m_displacement_data;
|
||||
std::unique_ptr<mean_field::mapping::ElementCompactificationData>
|
||||
m_compactification_data;
|
||||
|
||||
mean_field::mapping::DomainMapperStateless::Workspace m_workspace;
|
||||
int m_cached_element_id{-1};
|
||||
bool m_elevates_vacuum;
|
||||
};
|
||||
mean_field::mapping::DomainMapper::Workspace m_workspace;
|
||||
int m_cached_element_id{-1};
|
||||
bool m_elevates_vacuum;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace mean_field::operators {
|
||||
PreparedMappedHDivMassOperator::PreparedMappedHDivMassOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domain_mapper
|
||||
)
|
||||
: Operator(get_operator_size(f)),
|
||||
m_fem(f),
|
||||
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 "
|
||||
"gravity-gradient finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.displacementFes != nullptr, "PreparedMappedHDivMassOperator requires the "
|
||||
"displacement finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.compactificationFes != nullptr, "PreparedMappedHDivMassOperator requires the compactification "
|
||||
"finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.compactificationCoordinate != nullptr, "PreparedMappedHDivMassOperator requires the compactification "
|
||||
"coordinate."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.quadratureFactory != nullptr, "PreparedMappedHDivMassOperator requires the quadrature-rule "
|
||||
"factory."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
domain_mapper.GetDimension() == f.mesh->Dimension(),
|
||||
"The stateless domain-mapper dimension does not match the mesh "
|
||||
"dimension."
|
||||
);
|
||||
PreparedMappedHDivMassOperator::PreparedMappedHDivMassOperator(
|
||||
const fem::FEM &f, const mapping::DomainMapper &domain_mapper)
|
||||
: Operator(get_operator_size(f)), m_fem(f), 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 "
|
||||
"gravity-gradient finite-element space.");
|
||||
MFEM_VERIFY(f.displacementFes != nullptr,
|
||||
"PreparedMappedHDivMassOperator requires the "
|
||||
"displacement finite-element space.");
|
||||
MFEM_VERIFY(f.compactificationFes != nullptr,
|
||||
"PreparedMappedHDivMassOperator requires the compactification "
|
||||
"finite-element space.");
|
||||
MFEM_VERIFY(f.compactificationCoordinate != nullptr,
|
||||
"PreparedMappedHDivMassOperator requires the compactification "
|
||||
"coordinate.");
|
||||
MFEM_VERIFY(f.quadratureFactory != nullptr,
|
||||
"PreparedMappedHDivMassOperator requires the quadrature-rule "
|
||||
"factory.");
|
||||
MFEM_VERIFY(domain_mapper.GetDimension() == f.mesh->Dimension(),
|
||||
"The stateless domain-mapper dimension does not match the mesh "
|
||||
"dimension.");
|
||||
|
||||
utils::populate_element_mask(f.mesh.get(), utils::DOMAINS::STELLAR, m_stellar_marker);
|
||||
utils::populate_element_mask(f.mesh.get(), utils::DOMAINS::VACUUM, m_vacuum_marker);
|
||||
m_stellar_marker =
|
||||
utils::domain::make_attribute_marker<utils::domain::Stellar,
|
||||
DomainSchema>(*f.mesh);
|
||||
m_vacuum_marker =
|
||||
utils::domain::make_attribute_marker<utils::domain::Vacuum, DomainSchema>(
|
||||
*f.mesh);
|
||||
|
||||
const int stellar_element_id = find_representative_element(f, m_stellar_marker);
|
||||
const int vacuum_element_id = find_representative_element(f, m_vacuum_marker);
|
||||
const int stellar_element_id =
|
||||
find_representative_element(f, m_stellar_marker);
|
||||
const int vacuum_element_id = find_representative_element(f, m_vacuum_marker);
|
||||
|
||||
MFEM_VERIFY(
|
||||
stellar_element_id >= 0, "PreparedMappedHDivMassOperator requires "
|
||||
"at least one stellar element."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
vacuum_element_id >= 0, "PreparedMappedHDivMassOperator requires at "
|
||||
"least one compactified vacuum element."
|
||||
);
|
||||
MFEM_VERIFY(stellar_element_id >= 0,
|
||||
"PreparedMappedHDivMassOperator requires "
|
||||
"at least one stellar element.");
|
||||
MFEM_VERIFY(vacuum_element_id >= 0,
|
||||
"PreparedMappedHDivMassOperator requires at "
|
||||
"least one compactified vacuum element.");
|
||||
|
||||
validate_uniform_domain_discretization(f, m_stellar_marker, stellar_element_id);
|
||||
validate_uniform_domain_discretization(f, m_vacuum_marker, vacuum_element_id);
|
||||
}
|
||||
validate_uniform_domain_discretization(f, m_stellar_marker,
|
||||
stellar_element_id);
|
||||
validate_uniform_domain_discretization(f, m_vacuum_marker, vacuum_element_id);
|
||||
}
|
||||
|
||||
void PreparedMappedHDivMassOperator::Prepare(const mfem::Vector &displacement) {
|
||||
MFEM_VERIFY(
|
||||
displacement.Size() == m_displacement_map.reduced_size(),
|
||||
"PreparedMappedHDivMassOperator received a displacement vector "
|
||||
"with "
|
||||
"the wrong size."
|
||||
);
|
||||
void PreparedMappedHDivMassOperator::Prepare(const mfem::Vector &displacement) {
|
||||
MFEM_VERIFY(displacement.Size() == m_displacement_map.reduced_size(),
|
||||
"PreparedMappedHDivMassOperator received a displacement vector "
|
||||
"with "
|
||||
"the wrong size.");
|
||||
|
||||
for (int i = 0; i < displacement.Size(); ++i) {
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(displacement(i)), "PreparedMappedHDivMassOperator received a non-finite "
|
||||
"displacement "
|
||||
"value."
|
||||
);
|
||||
}
|
||||
for (int i = 0; i < displacement.Size(); ++i) {
|
||||
MFEM_VERIFY(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);
|
||||
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);
|
||||
const int stellar_element_id =
|
||||
find_representative_element(m_fem, m_stellar_marker);
|
||||
const int vacuum_element_id =
|
||||
find_representative_element(m_fem, m_vacuum_marker);
|
||||
|
||||
const mfem::FiniteElement &stellar_element = *m_fem.gravityFluxFes->GetFE(stellar_element_id);
|
||||
const mfem::FiniteElement &vacuum_element = *m_fem.gravityFluxFes->GetFE(vacuum_element_id);
|
||||
const mfem::FiniteElement &stellar_element =
|
||||
*m_fem.gravityFluxFes->GetFE(stellar_element_id);
|
||||
const mfem::FiniteElement &vacuum_element =
|
||||
*m_fem.gravityFluxFes->GetFE(vacuum_element_id);
|
||||
|
||||
mfem::ElementTransformation &stellar_transformation = *m_fem.mesh->GetElementTransformation(stellar_element_id);
|
||||
mfem::ElementTransformation &vacuum_transformation = *m_fem.mesh->GetElementTransformation(vacuum_element_id);
|
||||
mfem::ElementTransformation &stellar_transformation =
|
||||
*m_fem.mesh->GetElementTransformation(stellar_element_id);
|
||||
mfem::ElementTransformation &vacuum_transformation =
|
||||
*m_fem.mesh->GetElementTransformation(vacuum_element_id);
|
||||
|
||||
m_mass_form.reset();
|
||||
m_stellar_mass_coefficient.reset();
|
||||
m_vacuum_mass_coefficient.reset();
|
||||
m_stellar_mass_form.reset();
|
||||
m_vacuum_mass_form.reset();
|
||||
m_stellar_mass_coefficient.reset();
|
||||
m_vacuum_mass_coefficient.reset();
|
||||
|
||||
m_stellar_mass_coefficient =
|
||||
std::make_unique<FrozenMappedHDivMassCoefficient>(m_fem, m_domain_mapper, m_displacement_true, false);
|
||||
m_vacuum_mass_coefficient =
|
||||
std::make_unique<FrozenMappedHDivMassCoefficient>(m_fem, m_domain_mapper, m_displacement_true, true);
|
||||
m_stellar_mass_coefficient =
|
||||
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, m_displacement_true, true);
|
||||
|
||||
m_mass_form = std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
|
||||
m_mass_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
m_stellar_mass_form =
|
||||
std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
|
||||
m_vacuum_mass_form =
|
||||
std::make_unique<mfem::ParBilinearForm>(m_fem.gravityFluxFes.get());
|
||||
m_stellar_mass_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
m_vacuum_mass_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
|
||||
auto stellar_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(*m_stellar_mass_coefficient);
|
||||
auto vacuum_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(*m_vacuum_mass_coefficient);
|
||||
auto stellar_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(
|
||||
*m_stellar_mass_coefficient);
|
||||
auto vacuum_integrator = std::make_unique<mfem::VectorFEMassIntegrator>(
|
||||
*m_vacuum_mass_coefficient);
|
||||
|
||||
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
|
||||
*stellar_integrator, quadrature::QuadratureRole::discretization, stellar_element, stellar_transformation,
|
||||
utils::DOMAINS::STELLAR, quadrature::MappingKind::general
|
||||
);
|
||||
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
|
||||
*stellar_integrator, quadrature::QuadratureRole::discretization,
|
||||
stellar_element, stellar_transformation, utils::DOMAINS::STELLAR,
|
||||
quadrature::MappingKind::general);
|
||||
|
||||
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
|
||||
*vacuum_integrator, quadrature::QuadratureRole::discretization, vacuum_element, vacuum_transformation,
|
||||
utils::DOMAINS::VACUUM, quadrature::MappingKind::kelvin
|
||||
);
|
||||
m_fem.quadratureFactory->configure_gravity_hdiv_mass(
|
||||
*vacuum_integrator, quadrature::QuadratureRole::discretization,
|
||||
vacuum_element, vacuum_transformation, utils::DOMAINS::VACUUM,
|
||||
quadrature::MappingKind::kelvin);
|
||||
|
||||
m_mass_form->AddDomainIntegrator(stellar_integrator.release(), m_stellar_marker);
|
||||
m_mass_form->AddDomainIntegrator(vacuum_integrator.release(), m_vacuum_marker);
|
||||
m_mass_form->Assemble();
|
||||
m_stellar_mass_form->AddDomainIntegrator(stellar_integrator.release(),
|
||||
m_stellar_marker);
|
||||
m_vacuum_mass_form->AddDomainIntegrator(vacuum_integrator.release(),
|
||||
m_vacuum_marker);
|
||||
m_stellar_mass_form->Assemble();
|
||||
m_vacuum_mass_form->Assemble();
|
||||
|
||||
m_is_prepared = true;
|
||||
++m_preparation_count;
|
||||
}
|
||||
m_is_prepared = true;
|
||||
++m_preparation_count;
|
||||
}
|
||||
|
||||
void PreparedMappedHDivMassOperator::Mult(
|
||||
const mfem::Vector &gravity_gradient,
|
||||
mfem::Vector &action
|
||||
) const {
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "PreparedMappedHDivMassOperator must be prepared "
|
||||
"before Mult is called."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
m_mass_form != nullptr, "PreparedMappedHDivMassOperator has no "
|
||||
"assembled partial-assembly form."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
gravity_gradient.Size() == Width(), "PreparedMappedHDivMassOperator received a gravity-gradient vector "
|
||||
"with the wrong size."
|
||||
);
|
||||
void PreparedMappedHDivMassOperator::Mult(const mfem::Vector &gravity_gradient,
|
||||
mfem::Vector &action) const {
|
||||
MFEM_VERIFY(m_is_prepared, "PreparedMappedHDivMassOperator must be prepared "
|
||||
"before Mult is called.");
|
||||
MFEM_VERIFY(
|
||||
m_stellar_mass_form != nullptr && m_vacuum_mass_form != nullptr,
|
||||
"PreparedMappedHDivMassOperator has incomplete domain mass forms.");
|
||||
MFEM_VERIFY(
|
||||
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_flux_map.gather(m_action_true, action);
|
||||
}
|
||||
m_flux_true.SetSize(m_flux_map.full_size());
|
||||
m_action_true.SetSize(m_flux_map.full_size());
|
||||
m_domain_action_true.SetSize(m_flux_map.full_size());
|
||||
m_flux_map.scatter(gravity_gradient, m_flux_true);
|
||||
m_stellar_mass_form->Mult(m_flux_true, m_action_true);
|
||||
m_vacuum_mass_form->Mult(m_flux_true, m_domain_action_true);
|
||||
m_action_true += m_domain_action_true;
|
||||
action.SetSize(Height());
|
||||
m_flux_map.gather(m_action_true, action);
|
||||
}
|
||||
|
||||
bool PreparedMappedHDivMassOperator::IsPrepared() const noexcept {
|
||||
return m_is_prepared;
|
||||
}
|
||||
void PreparedMappedHDivMassOperator::AssembleDiagonal(
|
||||
mfem::Vector &diagonal) const {
|
||||
mfem::Vector true_diagonal;
|
||||
AssembleTrueDiagonal(true_diagonal);
|
||||
diagonal.SetSize(Height());
|
||||
m_flux_map.gather(true_diagonal, diagonal);
|
||||
}
|
||||
|
||||
std::uint64_t PreparedMappedHDivMassOperator::GetPreparationCount() const noexcept {
|
||||
return m_preparation_count;
|
||||
}
|
||||
void PreparedMappedHDivMassOperator::AssembleTrueDiagonal(
|
||||
mfem::Vector &diagonal) const {
|
||||
MFEM_VERIFY(m_is_prepared, "PreparedMappedHDivMassOperator must be prepared "
|
||||
"before assembling its diagonal.");
|
||||
MFEM_VERIFY(
|
||||
m_stellar_mass_form != nullptr && m_vacuum_mass_form != nullptr,
|
||||
"PreparedMappedHDivMassOperator has incomplete domain mass forms.");
|
||||
|
||||
const field::FieldDofMap &PreparedMappedHDivMassOperator::GetFluxMap() const noexcept {
|
||||
return m_flux_map;
|
||||
}
|
||||
diagonal.SetSize(m_flux_map.full_size());
|
||||
mfem::Vector domain_diagonal(m_flux_map.full_size());
|
||||
m_stellar_mass_form->AssembleDiagonal(diagonal);
|
||||
m_vacuum_mass_form->AssembleDiagonal(domain_diagonal);
|
||||
diagonal += domain_diagonal;
|
||||
}
|
||||
|
||||
const field::FieldDofMap &PreparedMappedHDivMassOperator::GetDisplacementMap() const noexcept {
|
||||
return m_displacement_map;
|
||||
}
|
||||
bool PreparedMappedHDivMassOperator::IsPrepared() const noexcept {
|
||||
return m_is_prepared;
|
||||
}
|
||||
|
||||
std::uint64_t
|
||||
PreparedMappedHDivMassOperator::GetPreparationCount() const noexcept {
|
||||
return m_preparation_count;
|
||||
}
|
||||
|
||||
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
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -213,7 +213,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedPressureForceOperator::PreparedPressureForceOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState
|
||||
)
|
||||
: PreparedPressureForceOperator(
|
||||
@@ -226,7 +226,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedPressureForceOperator::PreparedPressureForceOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
ConstructionData constructionData
|
||||
)
|
||||
@@ -460,7 +460,7 @@ namespace mean_field::operators {
|
||||
|
||||
true_to_local(*m_fem.displacementFes, m_baseDisplacementTrue, displacementLocal);
|
||||
|
||||
mapping::DomainMapperStateless::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
|
||||
mfem::Vector elementDisplacement;
|
||||
mfem::Vector elementCompactification;
|
||||
@@ -807,7 +807,7 @@ namespace mean_field::operators {
|
||||
|
||||
localAction = 0.0;
|
||||
|
||||
mapping::DomainMapperStateless::Workspace workspace(m_fem.mesh->Dimension());
|
||||
mapping::DomainMapper::Workspace workspace(m_fem.mesh->Dimension());
|
||||
|
||||
mfem::Vector elementDisplacementVariation;
|
||||
mfem::Vector elementAction;
|
||||
|
||||
@@ -10,7 +10,7 @@ import :operators.prepared_rotational_displacement_force;
|
||||
namespace mean_field::operators {
|
||||
PreparedRotationalDisplacementForceOperator::PreparedRotationalDisplacementForceOperator(
|
||||
const fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper
|
||||
const mapping::DomainMapper &domainMapper
|
||||
)
|
||||
: m_fem(f),
|
||||
m_domainMapper(domainMapper),
|
||||
|
||||
@@ -9,28 +9,16 @@ module;
|
||||
module mean_field;
|
||||
|
||||
import :operators.prepared_stellar_equilibrium;
|
||||
import :physics.gravity;
|
||||
|
||||
namespace {
|
||||
using DomainSchema = mean_field::utils::domain::CoreEnvelopeVacuumDomainSchema;
|
||||
|
||||
[[nodiscard]] mean_field::fem::FEM &ensure_gravity_static_operators(mean_field::fem::FEM &f) {
|
||||
void verify_coupled_discretization(const mean_field::fem::FEM &f) {
|
||||
MFEM_VERIFY(
|
||||
f.mesh != nullptr && f.densityFes != nullptr && f.displacementFes != nullptr &&
|
||||
f.gravityFluxFes != nullptr && f.gravityPotentialFes != nullptr && f.enthalpyFes != nullptr,
|
||||
"PreparedStellarEquilibriumOperator requires the complete coupled finite-element discretization."
|
||||
);
|
||||
|
||||
if (f.gravityContext.b_form == nullptr || f.gravityContext.BT == nullptr) {
|
||||
mean_field::physics::update_stiffness_matrix(f);
|
||||
}
|
||||
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.b_form != nullptr && f.gravityContext.BT != nullptr,
|
||||
"PreparedStellarEquilibriumOperator could not initialize the static gravity divergence operators."
|
||||
);
|
||||
|
||||
return f;
|
||||
}
|
||||
|
||||
[[nodiscard]] mean_field::operators::StellarEquilibriumLayout make_layout(
|
||||
@@ -318,13 +306,13 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedStellarEquilibriumOperator::ConstructionData
|
||||
PreparedStellarEquilibriumOperator::MakeConstructionData(fem::FEM &f) {
|
||||
ensure_gravity_static_operators(f);
|
||||
verify_coupled_discretization(f);
|
||||
return ConstructionData(f);
|
||||
}
|
||||
|
||||
PreparedStellarEquilibriumOperator::PreparedStellarEquilibriumOperator(
|
||||
fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
const models::StellarModel &stellarModel
|
||||
)
|
||||
@@ -338,7 +326,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedStellarEquilibriumOperator::PreparedStellarEquilibriumOperator(
|
||||
fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
const double targetMass
|
||||
)
|
||||
@@ -353,7 +341,7 @@ namespace mean_field::operators {
|
||||
|
||||
PreparedStellarEquilibriumOperator::PreparedStellarEquilibriumOperator(
|
||||
fem::FEM &f,
|
||||
const mapping::DomainMapperStateless &domainMapper,
|
||||
const mapping::DomainMapper &domainMapper,
|
||||
const eos::Polytrope &equationOfState,
|
||||
const double targetMass,
|
||||
ConstructionData constructionData
|
||||
@@ -587,8 +575,7 @@ namespace mean_field::operators {
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
m_cachedResidual, m_layout, enthalpyResidual, hydrostatic,
|
||||
"The hydrostatic residual has the wrong size."
|
||||
m_cachedResidual, m_layout, enthalpyResidual, hydrostatic, "The hydrostatic residual has the wrong size."
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
@@ -712,8 +699,7 @@ namespace mean_field::operators {
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
action, m_layout, enthalpyResidual, hydrostaticAction,
|
||||
"The hydrostatic Jacobian action has the wrong size."
|
||||
action, m_layout, enthalpyResidual, hydrostaticAction, "The hydrostatic Jacobian action has the wrong size."
|
||||
);
|
||||
|
||||
assign_residual_block(
|
||||
|
||||
Reference in New Issue
Block a user