feat(field-support): added field support system, mid migration
currently the barotope and the pressure force operator are migrated to the new support system
This commit is contained in:
@@ -33,17 +33,15 @@ namespace {
|
||||
|
||||
true_dofs.SetSize(finite_element_space.GetTrueVSize());
|
||||
|
||||
const mfem::Operator *restriction =
|
||||
finite_element_space.GetRestrictionMatrix();
|
||||
const mfem::Operator *restriction = finite_element_space.GetRestrictionMatrix();
|
||||
|
||||
if (restriction != nullptr) {
|
||||
restriction->Mult(grid_function, true_dofs);
|
||||
} else {
|
||||
MFEM_VERIFY(
|
||||
grid_function.Size() == true_dofs.Size(),
|
||||
"A finite-element space without a restriction operator must "
|
||||
"have "
|
||||
"matching local and true sizes."
|
||||
grid_function.Size() == true_dofs.Size(), "A finite-element space without a restriction operator must "
|
||||
"have "
|
||||
"matching local and true sizes."
|
||||
);
|
||||
|
||||
true_dofs = grid_function;
|
||||
@@ -62,10 +60,7 @@ namespace mean_field::physics {
|
||||
f.densityFes != nullptr && rho.FESpace() == f.densityFes.get(),
|
||||
"Gravity solve requires rho to use the registered density space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityPotentialFes != nullptr,
|
||||
"Gravity solve requires the registered gravity-potential space."
|
||||
);
|
||||
MFEM_VERIFY(f.gravityPotentialFes != nullptr, "Gravity solve requires the registered gravity-potential space.");
|
||||
|
||||
mfem::Array<int> outer_bdr_marker(f.mesh->bdr_attributes.Max());
|
||||
outer_bdr_marker = 0;
|
||||
@@ -86,23 +81,16 @@ namespace mean_field::physics {
|
||||
return l2_multipole_potential(f, utils::MASS, x_physical);
|
||||
};
|
||||
|
||||
boundary_potential_coeff =
|
||||
std::make_unique<mfem::FunctionCoefficient>(boundary_potential);
|
||||
boundary_potential_coeff = std::make_unique<mfem::FunctionCoefficient>(boundary_potential);
|
||||
auto boundary_integrator =
|
||||
std::make_unique<mfem::VectorFEBoundaryFluxLFIntegrator>(
|
||||
*boundary_potential_coeff
|
||||
);
|
||||
const mfem::FiniteElement &boundary_element =
|
||||
*f.gravityFluxFes->GetTypicalTraceElement();
|
||||
std::make_unique<mfem::VectorFEBoundaryFluxLFIntegrator>(*boundary_potential_coeff);
|
||||
const mfem::FiniteElement &boundary_element = *f.gravityFluxFes->GetTypicalTraceElement();
|
||||
|
||||
f.quadratureFactory->configure_gravity_boundary(
|
||||
*boundary_integrator,
|
||||
quadrature::QuadratureRole::discretization, boundary_element,
|
||||
*boundary_integrator, quadrature::QuadratureRole::discretization, boundary_element,
|
||||
utils::DOMAINS::VACUUM, quadrature::MappingKind::none
|
||||
);
|
||||
g_rhs.AddBoundaryIntegrator(
|
||||
boundary_integrator.release(), outer_bdr_marker
|
||||
);
|
||||
g_rhs.AddBoundaryIntegrator(boundary_integrator.release(), outer_bdr_marker);
|
||||
}
|
||||
|
||||
g_rhs.Assemble();
|
||||
@@ -112,36 +100,25 @@ namespace mean_field::physics {
|
||||
mfem::ParLinearForm f_rhs(f.gravityPotentialFes.get());
|
||||
|
||||
std::unique_ptr<mfem::Coefficient> mapped_source_coeff;
|
||||
mfem::Coefficient *active_source_coeff = &source_coeff;
|
||||
quadrature::MappingKind source_mapping_kind =
|
||||
quadrature::MappingKind::none;
|
||||
mfem::Coefficient *active_source_coeff = &source_coeff;
|
||||
quadrature::MappingKind source_mapping_kind = quadrature::MappingKind::none;
|
||||
|
||||
if (f.has_mapping()) {
|
||||
mapped_source_coeff =
|
||||
std::make_unique<mapping::MappedScalarCoefficient>(
|
||||
*f.mapping, source_coeff
|
||||
);
|
||||
mapped_source_coeff = std::make_unique<mapping::MappedScalarCoefficient>(*f.mapping, source_coeff);
|
||||
active_source_coeff = mapped_source_coeff.get();
|
||||
source_mapping_kind = quadrature::MappingKind::general;
|
||||
}
|
||||
|
||||
auto source_integrator =
|
||||
std::make_unique<mfem::DomainLFIntegrator>(*active_source_coeff);
|
||||
const mfem::FiniteElement &source_test_element =
|
||||
*f.gravityPotentialFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &source_transformation =
|
||||
*f.mesh->GetElementTransformation(0);
|
||||
const int source_coefficient_order = f.densityFes->GetMaxElementOrder();
|
||||
auto source_integrator = std::make_unique<mfem::DomainLFIntegrator>(*active_source_coeff);
|
||||
const mfem::FiniteElement &source_test_element = *f.gravityPotentialFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &source_transformation = *f.mesh->GetElementTransformation(0);
|
||||
const int source_coefficient_order = f.densityFes->GetMaxElementOrder();
|
||||
|
||||
f.quadratureFactory->configure_gravity_source(
|
||||
*source_integrator, quadrature::QuadratureRole::discretization,
|
||||
source_test_element, source_transformation,
|
||||
source_coefficient_order, utils::DOMAINS::STELLAR,
|
||||
source_mapping_kind
|
||||
);
|
||||
f_rhs.AddDomainIntegrator(
|
||||
source_integrator.release(), f.gravityContext.stellar_mask
|
||||
*source_integrator, quadrature::QuadratureRole::discretization, source_test_element, source_transformation,
|
||||
source_coefficient_order, utils::DOMAINS::STELLAR, source_mapping_kind
|
||||
);
|
||||
f_rhs.AddDomainIntegrator(source_integrator.release(), f.gravityContext.stellar_mask);
|
||||
f_rhs.Assemble();
|
||||
|
||||
mfem::BlockVector RHS(f.gravityBlockTrueOffsets);
|
||||
@@ -177,13 +154,9 @@ namespace mean_field::physics {
|
||||
|
||||
std::unique_ptr<mfem::Coefficient> centrifugal_coeff;
|
||||
if (fem.has_mapping()) {
|
||||
centrifugal_coeff = std::make_unique<
|
||||
mapping::PhysicalPositionFunctionCoefficient>(
|
||||
*fem.mapping, rot
|
||||
);
|
||||
centrifugal_coeff = std::make_unique<mapping::PhysicalPositionFunctionCoefficient>(*fem.mapping, rot);
|
||||
} else {
|
||||
centrifugal_coeff =
|
||||
std::make_unique<mfem::FunctionCoefficient>(rot);
|
||||
centrifugal_coeff = std::make_unique<mfem::FunctionCoefficient>(rot);
|
||||
}
|
||||
|
||||
mfem::GridFunction centrifugal_gf(fem.gravityPotentialFes.get());
|
||||
@@ -207,19 +180,14 @@ namespace mean_field::physics {
|
||||
if (fem.mesh->GetAttribute(i) == 3)
|
||||
continue;
|
||||
|
||||
mfem::ElementTransformation *trans =
|
||||
fem.mesh->GetElementTransformation(i);
|
||||
using DensityField = field::Field<field::Density>;
|
||||
const quadrature::Query query =
|
||||
DensityField::make_query<field::Density::Form::Quadrupole>(
|
||||
quadrature::QuadratureRole::diagnostic, trans->OrderW(),
|
||||
std::array<int, 1>{2}, utils::DOMAINS::STELLAR,
|
||||
fem.has_mapping() ? quadrature::MappingKind::general
|
||||
: quadrature::MappingKind::none
|
||||
);
|
||||
mfem::ElementTransformation *trans = fem.mesh->GetElementTransformation(i);
|
||||
using DensityField = field::Field<field::Density>;
|
||||
const quadrature::Query query = DensityField::make_query<field::Density::Form::Quadrupole>(
|
||||
quadrature::QuadratureRole::diagnostic, trans->OrderW(), std::array<int, 1>{2}, utils::DOMAINS::STELLAR,
|
||||
fem.has_mapping() ? quadrature::MappingKind::general : quadrature::MappingKind::none
|
||||
);
|
||||
const mfem::IntegrationRule &ir =
|
||||
*fem.quadratureFactory->get(query, trans->GetGeometryType())
|
||||
.integration_rule;
|
||||
*fem.quadratureFactory->get(query, trans->GetGeometryType()).integration_rule;
|
||||
|
||||
for (int j = 0; j < ir.GetNPoints(); ++j) {
|
||||
const mfem::IntegrationPoint &ip = ir.IntPoint(j);
|
||||
@@ -250,9 +218,8 @@ namespace mean_field::physics {
|
||||
|
||||
for (int m = 0; m < dim; ++m) {
|
||||
for (int n = 0; n < dim; ++n) {
|
||||
const double delta = (m == n) ? 1.0 : 0.0;
|
||||
const double contrib =
|
||||
3.0 * x_prime(m) * x_prime(n) - delta * r_sq;
|
||||
const double delta = (m == n) ? 1.0 : 0.0;
|
||||
const double contrib = 3.0 * x_prime(m) * x_prime(n) - delta * r_sq;
|
||||
local_Q(m, n) += rho_val * contrib * weight;
|
||||
}
|
||||
}
|
||||
@@ -260,10 +227,7 @@ namespace mean_field::physics {
|
||||
}
|
||||
|
||||
mfem::DenseMatrix global_Q(dim, dim);
|
||||
MPI_Allreduce(
|
||||
local_Q.GetData(), global_Q.GetData(), dim * dim, MPI_DOUBLE,
|
||||
MPI_SUM, fem.mesh->GetComm()
|
||||
);
|
||||
MPI_Allreduce(local_Q.GetData(), global_Q.GetData(), dim * dim, MPI_DOUBLE, MPI_SUM, fem.mesh->GetComm());
|
||||
|
||||
return global_Q;
|
||||
}
|
||||
@@ -289,8 +253,7 @@ namespace mean_field::physics {
|
||||
}
|
||||
}
|
||||
|
||||
const double l2_contrib =
|
||||
-(utils::G / (2.0 * std::pow(r, 3))) * l2_mult_factor;
|
||||
const double l2_contrib = -(utils::G / (2.0 * std::pow(r, 3))) * l2_mult_factor;
|
||||
|
||||
const double l0_contrib = -utils::G * total_mass / r;
|
||||
|
||||
@@ -304,92 +267,69 @@ namespace mean_field::physics {
|
||||
// ==========================================
|
||||
// 1. Partially Assemble the High-Order Mass Block
|
||||
// ==========================================
|
||||
f.gravityContext.m_form =
|
||||
std::make_unique<mfem::ParBilinearForm>(f.gravityFluxFes.get());
|
||||
f.gravityContext.m_form = std::make_unique<mfem::ParBilinearForm>(f.gravityFluxFes.get());
|
||||
f.gravityContext.m_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
|
||||
std::unique_ptr<mfem::VectorFEMassIntegrator> hdiv_mass_integrator;
|
||||
|
||||
if (f.has_mapping()) {
|
||||
f.gravityContext.mapped_hdiv_mass_coeff =
|
||||
std::make_unique<mapping::MappedHDivMassCoefficient>(
|
||||
*f.mapping, f.mesh->Dimension()
|
||||
);
|
||||
std::make_unique<mapping::MappedHDivMassCoefficient>(*f.mapping, f.mesh->Dimension());
|
||||
hdiv_mass_integrator =
|
||||
std::make_unique<mfem::VectorFEMassIntegrator>(
|
||||
*f.gravityContext.mapped_hdiv_mass_coeff
|
||||
);
|
||||
std::make_unique<mfem::VectorFEMassIntegrator>(*f.gravityContext.mapped_hdiv_mass_coeff);
|
||||
} else {
|
||||
f.gravityContext.mapped_hdiv_mass_coeff.reset();
|
||||
hdiv_mass_integrator =
|
||||
std::make_unique<mfem::VectorFEMassIntegrator>();
|
||||
hdiv_mass_integrator = std::make_unique<mfem::VectorFEMassIntegrator>();
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &hdiv_element =
|
||||
*f.gravityFluxFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &hdiv_transformation =
|
||||
*f.mesh->GetElementTransformation(0);
|
||||
const mfem::FiniteElement &hdiv_element = *f.gravityFluxFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &hdiv_transformation = *f.mesh->GetElementTransformation(0);
|
||||
const quadrature::MappingKind mapping_kind =
|
||||
f.has_mapping() ? quadrature::MappingKind::general
|
||||
: quadrature::MappingKind::none;
|
||||
f.has_mapping() ? quadrature::MappingKind::general : quadrature::MappingKind::none;
|
||||
|
||||
f.quadratureFactory->configure_gravity_hdiv_mass(
|
||||
*hdiv_mass_integrator, quadrature::QuadratureRole::discretization,
|
||||
hdiv_element, hdiv_transformation, utils::DOMAINS::ALL, mapping_kind
|
||||
);
|
||||
f.gravityContext.m_form->AddDomainIntegrator(
|
||||
hdiv_mass_integrator.release()
|
||||
*hdiv_mass_integrator, quadrature::QuadratureRole::discretization, hdiv_element, hdiv_transformation,
|
||||
utils::DOMAINS::ALL, mapping_kind
|
||||
);
|
||||
f.gravityContext.m_form->AddDomainIntegrator(hdiv_mass_integrator.release());
|
||||
|
||||
f.gravityContext.m_form->Assemble();
|
||||
|
||||
// ==========================================
|
||||
// 2. Partially Assemble the High-Order Divergence Block
|
||||
// ==========================================
|
||||
f.gravityContext.b_form = std::make_unique<mfem::ParMixedBilinearForm>(
|
||||
f.gravityFluxFes.get(), f.gravityPotentialFes.get()
|
||||
);
|
||||
f.gravityContext.b_form =
|
||||
std::make_unique<mfem::ParMixedBilinearForm>(f.gravityFluxFes.get(), f.gravityPotentialFes.get());
|
||||
f.gravityContext.b_form->SetAssemblyLevel(mfem::AssemblyLevel::PARTIAL);
|
||||
|
||||
auto divergence_discretization_integrator =
|
||||
std::make_unique<mfem::VectorFEDivergenceIntegrator>();
|
||||
const mfem::FiniteElement &divergence_discretization_test_element =
|
||||
*f.gravityPotentialFes->GetTypicalFE();
|
||||
auto divergence_discretization_integrator = std::make_unique<mfem::VectorFEDivergenceIntegrator>();
|
||||
const mfem::FiniteElement &divergence_discretization_test_element = *f.gravityPotentialFes->GetTypicalFE();
|
||||
|
||||
f.quadratureFactory->configure_gravity_divergence(
|
||||
*divergence_discretization_integrator,
|
||||
quadrature::QuadratureRole::discretization, hdiv_element,
|
||||
divergence_discretization_test_element, hdiv_transformation,
|
||||
utils::DOMAINS::ALL, quadrature::MappingKind::none
|
||||
);
|
||||
f.gravityContext.b_form->AddDomainIntegrator(
|
||||
divergence_discretization_integrator.release()
|
||||
*divergence_discretization_integrator, quadrature::QuadratureRole::discretization, hdiv_element,
|
||||
divergence_discretization_test_element, hdiv_transformation, utils::DOMAINS::ALL,
|
||||
quadrature::MappingKind::none
|
||||
);
|
||||
f.gravityContext.b_form->AddDomainIntegrator(divergence_discretization_integrator.release());
|
||||
|
||||
f.gravityContext.b_form->Assemble();
|
||||
|
||||
MFEM_VERIFY(
|
||||
f.domainMapperStateless != nullptr,
|
||||
"Gravity source partial assembly requires the stateless domain "
|
||||
"mapper."
|
||||
f.domainMapperStateless != nullptr, "Gravity source partial assembly requires the stateless domain "
|
||||
"mapper."
|
||||
);
|
||||
|
||||
mfem::Vector displacement_true(f.displacementFes->GetTrueVSize());
|
||||
displacement_true = 0.0;
|
||||
displacement_true = 0.0;
|
||||
|
||||
const mfem::GridFunction *active_displacement =
|
||||
f.mapping->GetDisplacement();
|
||||
const mfem::GridFunction *active_displacement = f.mapping->GetDisplacement();
|
||||
|
||||
if (active_displacement != nullptr) {
|
||||
grid_function_to_true_dofs(
|
||||
*f.displacementFes, *active_displacement, displacement_true
|
||||
);
|
||||
grid_function_to_true_dofs(*f.displacementFes, *active_displacement, displacement_true);
|
||||
}
|
||||
|
||||
auto source_form =
|
||||
std::make_unique<operators::PreparedMappedGravitySourceOperator>(
|
||||
f, *f.domainMapperStateless
|
||||
);
|
||||
std::make_unique<operators::PreparedMappedGravitySourceOperator>(f, *f.domainMapperStateless);
|
||||
|
||||
source_form->Prepare(displacement_true);
|
||||
|
||||
@@ -397,12 +337,9 @@ namespace mean_field::physics {
|
||||
// ==========================================
|
||||
// 3. Assemble Global Block Operator
|
||||
// ==========================================
|
||||
f.gravityContext.BT = std::make_unique<mfem::TransposeOperator>(
|
||||
f.gravityContext.b_form.get()
|
||||
);
|
||||
f.gravityContext.BT = std::make_unique<mfem::TransposeOperator>(f.gravityContext.b_form.get());
|
||||
|
||||
f.gravityContext.block_A =
|
||||
std::make_unique<mfem::BlockOperator>(f.gravityBlockTrueOffsets);
|
||||
f.gravityContext.block_A = std::make_unique<mfem::BlockOperator>(f.gravityBlockTrueOffsets);
|
||||
f.gravityContext.block_A->SetBlock(0, 0, f.gravityContext.m_form.get());
|
||||
f.gravityContext.block_A->SetBlock(0, 1, f.gravityContext.BT.get());
|
||||
f.gravityContext.block_A->SetBlock(1, 0, f.gravityContext.b_form.get());
|
||||
@@ -417,8 +354,7 @@ namespace mean_field::physics {
|
||||
|
||||
for (int i = 0; i < inverse_mass_diagonal.Size(); ++i) {
|
||||
MFEM_VERIFY(
|
||||
std::isfinite(inverse_mass_diagonal(i)) &&
|
||||
inverse_mass_diagonal(i) > 0.0,
|
||||
std::isfinite(inverse_mass_diagonal(i)) && inverse_mass_diagonal(i) > 0.0,
|
||||
"Mapped RT mass matrix has a non-positive or non-finite "
|
||||
"diagonal "
|
||||
"entry."
|
||||
@@ -426,58 +362,34 @@ namespace mean_field::physics {
|
||||
inverse_mass_diagonal(i) = 1.0 / inverse_mass_diagonal(i);
|
||||
}
|
||||
|
||||
mfem::ParMixedBilinearForm b_preconditioner(
|
||||
f.gravityFluxFes.get(), f.gravityPotentialFes.get()
|
||||
);
|
||||
auto divergence_preconditioner_integrator =
|
||||
std::make_unique<mfem::VectorFEDivergenceIntegrator>();
|
||||
mfem::ParMixedBilinearForm b_preconditioner(f.gravityFluxFes.get(), f.gravityPotentialFes.get());
|
||||
auto divergence_preconditioner_integrator = std::make_unique<mfem::VectorFEDivergenceIntegrator>();
|
||||
|
||||
const mfem::FiniteElement &divergence_trial_element =
|
||||
*f.gravityFluxFes->GetTypicalFE();
|
||||
const mfem::FiniteElement &divergence_test_element =
|
||||
*f.gravityPotentialFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &divergence_transformation =
|
||||
*f.mesh->GetElementTransformation(0);
|
||||
const mfem::FiniteElement &divergence_trial_element = *f.gravityFluxFes->GetTypicalFE();
|
||||
const mfem::FiniteElement &divergence_test_element = *f.gravityPotentialFes->GetTypicalFE();
|
||||
const mfem::ElementTransformation &divergence_transformation = *f.mesh->GetElementTransformation(0);
|
||||
|
||||
f.quadratureFactory->configure_gravity_divergence(
|
||||
*divergence_preconditioner_integrator,
|
||||
quadrature::QuadratureRole::preconditioner,
|
||||
divergence_trial_element, divergence_test_element,
|
||||
divergence_transformation, utils::DOMAINS::ALL,
|
||||
quadrature::MappingKind::none
|
||||
);
|
||||
b_preconditioner.AddDomainIntegrator(
|
||||
divergence_preconditioner_integrator.release()
|
||||
*divergence_preconditioner_integrator, quadrature::QuadratureRole::preconditioner, divergence_trial_element,
|
||||
divergence_test_element, divergence_transformation, utils::DOMAINS::ALL, quadrature::MappingKind::none
|
||||
);
|
||||
b_preconditioner.AddDomainIntegrator(divergence_preconditioner_integrator.release());
|
||||
b_preconditioner.Assemble();
|
||||
b_preconditioner.Finalize();
|
||||
std::unique_ptr<mfem::HypreParMatrix> b_matrix(
|
||||
b_preconditioner.ParallelAssemble()
|
||||
);
|
||||
std::unique_ptr<mfem::HypreParMatrix> inverse_mass_b_transpose(
|
||||
b_matrix->Transpose()
|
||||
);
|
||||
std::unique_ptr<mfem::HypreParMatrix> b_matrix(b_preconditioner.ParallelAssemble());
|
||||
std::unique_ptr<mfem::HypreParMatrix> inverse_mass_b_transpose(b_matrix->Transpose());
|
||||
|
||||
inverse_mass_b_transpose->ScaleRows(inverse_mass_diagonal);
|
||||
|
||||
f.gravityContext.Schur.reset(
|
||||
mfem::ParMult(b_matrix.get(), inverse_mass_b_transpose.get())
|
||||
);
|
||||
f.gravityContext.Schur.reset(mfem::ParMult(b_matrix.get(), inverse_mass_b_transpose.get()));
|
||||
|
||||
// ==========================================
|
||||
// 5. Wire Up the preconditioners
|
||||
// ==========================================
|
||||
f.gravityContext.prec_M =
|
||||
std::make_unique<mfem::OperatorJacobiSmoother>(
|
||||
mass_diagonal, empty_tdofs
|
||||
);
|
||||
f.gravityContext.prec_M = std::make_unique<mfem::OperatorJacobiSmoother>(mass_diagonal, empty_tdofs);
|
||||
f.gravityContext.prec_Phi->SetOperator(*f.gravityContext.Schur);
|
||||
f.gravityContext.block_prec->SetDiagonalBlock(
|
||||
0, f.gravityContext.prec_M.get()
|
||||
);
|
||||
f.gravityContext.block_prec->SetDiagonalBlock(
|
||||
1, f.gravityContext.prec_Phi.get()
|
||||
);
|
||||
f.gravityContext.block_prec->SetDiagonalBlock(0, f.gravityContext.prec_M.get());
|
||||
f.gravityContext.block_prec->SetDiagonalBlock(1, f.gravityContext.prec_Phi.get());
|
||||
}
|
||||
|
||||
GravitySolution grav_potential_new(
|
||||
@@ -486,49 +398,32 @@ namespace mean_field::physics {
|
||||
const mfem::GridFunction &rho,
|
||||
const mfem::GridFunction &displacement
|
||||
) {
|
||||
MFEM_VERIFY(f.mesh != nullptr, "Gravity initialization requires a parallel mesh.");
|
||||
MFEM_VERIFY(f.densityFes != nullptr, "Gravity initialization requires the density finite-element space.");
|
||||
MFEM_VERIFY(
|
||||
f.mesh != nullptr,
|
||||
"Gravity initialization requires a parallel mesh."
|
||||
f.gravityPotentialFes != nullptr, "Gravity initialization requires the gravity-potential "
|
||||
"finite-element "
|
||||
"space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.densityFes != nullptr,
|
||||
"Gravity initialization requires the density finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityPotentialFes != nullptr,
|
||||
"Gravity initialization requires the gravity-potential "
|
||||
"finite-element "
|
||||
"space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityFluxFes != nullptr,
|
||||
"Gravity initialization requires the "
|
||||
"gravity-gradient finite-element space."
|
||||
f.gravityFluxFes != nullptr, "Gravity initialization requires the "
|
||||
"gravity-gradient finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.displacementFes != nullptr, "Gravity initialization requires the "
|
||||
"displacement finite-element space."
|
||||
);
|
||||
MFEM_VERIFY(f.domainMapperStateless != nullptr, "Gravity initialization requires the stateless domain mapper.");
|
||||
MFEM_VERIFY(f.gravityContext.b_form != nullptr, "Gravity initialization requires the divergence operator.");
|
||||
MFEM_VERIFY(
|
||||
f.domainMapperStateless != nullptr,
|
||||
"Gravity initialization requires the stateless domain mapper."
|
||||
f.gravityContext.BT != nullptr, "Gravity initialization requires the transpose divergence operator."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.b_form != nullptr,
|
||||
"Gravity initialization requires the divergence operator."
|
||||
f.gravityContext.block_prec != nullptr, "Gravity initialization requires the gravity block preconditioner."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.BT != nullptr,
|
||||
"Gravity initialization requires the transpose divergence operator."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
f.gravityContext.block_prec != nullptr,
|
||||
"Gravity initialization requires the gravity block preconditioner."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
rho.FESpace() == f.densityFes.get(),
|
||||
"Gravity initialization requires density to use the FEM density "
|
||||
"space."
|
||||
rho.FESpace() == f.densityFes.get(), "Gravity initialization requires density to use the FEM density "
|
||||
"space."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
displacement.FESpace() == f.displacementFes.get(),
|
||||
@@ -540,53 +435,43 @@ namespace mean_field::physics {
|
||||
using form = utils::blocks::gravity_field_form;
|
||||
|
||||
constexpr auto gravity_gradient_residual_block =
|
||||
utils::blocks::get_residual_block<form>(
|
||||
utils::blocks::gravity_field.gradient_term
|
||||
);
|
||||
utils::blocks::get_residual_block<form>(utils::blocks::gravity_field.gradient_term);
|
||||
|
||||
constexpr auto gravity_poisson_residual_block =
|
||||
utils::blocks::get_residual_block<form>(
|
||||
utils::blocks::gravity_field.poisson_term
|
||||
);
|
||||
utils::blocks::get_residual_block<form>(utils::blocks::gravity_field.poisson_term);
|
||||
|
||||
const std::array<int, form::value_block_count> value_sizes{
|
||||
f.densityFes->GetTrueVSize(), f.displacementFes->GetTrueVSize(),
|
||||
f.gravityFluxFes->GetTrueVSize(),
|
||||
f.densityFes->GetTrueVSize(), f.displacementFes->GetTrueVSize(), f.gravityFluxFes->GetTrueVSize(),
|
||||
f.gravityPotentialFes->GetTrueVSize()
|
||||
};
|
||||
|
||||
const std::array<int, form::residual_block_count> residual_sizes{
|
||||
f.gravityFluxFes->GetTrueVSize(),
|
||||
f.gravityPotentialFes->GetTrueVSize()
|
||||
f.gravityFluxFes->GetTrueVSize(), f.gravityPotentialFes->GetTrueVSize()
|
||||
};
|
||||
|
||||
const utils::blocks::form_layout<form> layout(
|
||||
value_sizes, residual_sizes
|
||||
);
|
||||
const utils::blocks::form_layout<form> layout(value_sizes, residual_sizes);
|
||||
|
||||
mfem::Vector density_true;
|
||||
mfem::Vector displacement_true;
|
||||
|
||||
grid_function_to_true_dofs(*f.densityFes, rho, density_true);
|
||||
grid_function_to_true_dofs(
|
||||
*f.displacementFes, displacement, displacement_true
|
||||
grid_function_to_true_dofs(*f.displacementFes, displacement, displacement_true);
|
||||
|
||||
operators::context::gravity_field::GravityFieldLinearizationContext linearization_context(
|
||||
f, *f.domainMapperStateless
|
||||
);
|
||||
|
||||
operators::context::gravity_field::GravityFieldLinearizationContext
|
||||
linearization_context(f, *f.domainMapperStateless);
|
||||
|
||||
operators::GravityFieldJacobianOperator gravity_jacobian(
|
||||
f, *f.domainMapperStateless, linearization_context,
|
||||
layout.value_offsets(), layout.residual_offsets()
|
||||
f, *f.domainMapperStateless, linearization_context, layout.value_offsets(), layout.residual_offsets()
|
||||
);
|
||||
|
||||
operators::GravityFieldOperator gravity_operator(
|
||||
f, *f.domainMapperStateless, linearization_context,
|
||||
layout.value_offsets(), gravity_jacobian
|
||||
f, *f.domainMapperStateless, linearization_context, layout.value_offsets(), gravity_jacobian
|
||||
);
|
||||
|
||||
operators::context::gravity_field::GravityFieldGeometryContext
|
||||
reduced_geometry_context(f, *f.domainMapperStateless);
|
||||
operators::context::gravity_field::GravityFieldGeometryContext reduced_geometry_context(
|
||||
f, *f.domainMapperStateless
|
||||
);
|
||||
|
||||
operators::ReducedGravityFieldOperator reduced_operator(
|
||||
gravity_operator, reduced_geometry_context, displacement_true
|
||||
@@ -600,9 +485,7 @@ namespace mean_field::physics {
|
||||
"The reduced gravity right-hand side has the wrong size."
|
||||
);
|
||||
|
||||
mfem::BlockVector gravity_state(
|
||||
reduced_operator.GetGravityTrueOffsets()
|
||||
);
|
||||
mfem::BlockVector gravity_state(reduced_operator.GetGravityTrueOffsets());
|
||||
gravity_state = 0.0;
|
||||
|
||||
mfem::MINRESSolver minres(f.mesh->GetComm());
|
||||
@@ -614,20 +497,13 @@ namespace mean_field::physics {
|
||||
minres.SetPrintLevel(1);
|
||||
minres.Mult(right_hand_side, gravity_state);
|
||||
|
||||
MFEM_VERIFY(
|
||||
minres.GetConverged(),
|
||||
"The reduced gravity solve failed to converge."
|
||||
);
|
||||
MFEM_VERIFY(minres.GetConverged(), "The reduced gravity solve failed to converge.");
|
||||
|
||||
GravitySolution solution(f);
|
||||
|
||||
solution.gradPhi.SetFromTrueDofs(
|
||||
gravity_state.GetBlock(gravity_gradient_residual_block)
|
||||
);
|
||||
solution.gradPhi.SetFromTrueDofs(gravity_state.GetBlock(gravity_gradient_residual_block));
|
||||
|
||||
solution.phi.SetFromTrueDofs(
|
||||
gravity_state.GetBlock(gravity_poisson_residual_block)
|
||||
);
|
||||
solution.phi.SetFromTrueDofs(gravity_state.GetBlock(gravity_poisson_residual_block));
|
||||
|
||||
return solution;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user