feat(preconditioner): major work on preconditioner system
first preconditioner MVP
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
module;
|
||||
#include "profile.h"
|
||||
#include <cmath>
|
||||
#include <cstdint>
|
||||
#include <memory>
|
||||
@@ -304,6 +305,19 @@ namespace mean_field::operators {
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::Prepare(const mfem::Vector &displacement) {
|
||||
MEAN_FIELD_PROFILE_SCOPE_WARMUP("PreparedMappedGravitySourceOperator::Prepare linearization", 0);
|
||||
PrepareImpl(displacement, PreparationMode::linearization);
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::PreparePrimal(const mfem::Vector &displacement) {
|
||||
MEAN_FIELD_PROFILE_SCOPE_WARMUP("PreparedMappedGravitySourceOperator::Prepare primal", 0);
|
||||
PrepareImpl(displacement, PreparationMode::primal);
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::PrepareImpl(
|
||||
const mfem::Vector &displacement,
|
||||
const PreparationMode mode
|
||||
) {
|
||||
MFEM_VERIFY(
|
||||
displacement.Size() == m_displacement_map.reduced_size(),
|
||||
"PreparedMappedGravitySourceOperator received a displacement "
|
||||
@@ -318,7 +332,8 @@ namespace mean_field::operators {
|
||||
);
|
||||
}
|
||||
|
||||
m_is_prepared = false;
|
||||
m_is_prepared = false;
|
||||
m_has_variation_data = false;
|
||||
m_displacement_true.SetSize(m_displacement_map.full_size());
|
||||
m_displacement_map.scatter(displacement, m_displacement_true);
|
||||
m_elements.clear();
|
||||
@@ -343,8 +358,10 @@ namespace mean_field::operators {
|
||||
data.potential_dof_transformation =
|
||||
m_fem.gravityPotentialFes->GetElementDofs(element_id, data.potential_dofs);
|
||||
|
||||
data.displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, data.displacement_dofs);
|
||||
if (mode == PreparationMode::linearization) {
|
||||
data.displacement_dof_transformation =
|
||||
m_fem.displacementFes->GetElementVDofs(element_id, data.displacement_dofs);
|
||||
}
|
||||
|
||||
const mfem::FiniteElement &density_element = *m_fem.densityFes->GetFE(element_id);
|
||||
|
||||
@@ -367,7 +384,9 @@ namespace mean_field::operators {
|
||||
data.potential_basis.SetSize(quadrature_point_count, potential_dof_count);
|
||||
|
||||
const int dimension = m_fem.mesh->Dimension();
|
||||
data.inverse_element_jacobians.SetSize(quadrature_point_count, dimension * dimension);
|
||||
if (mode == PreparationMode::linearization) {
|
||||
data.inverse_element_jacobians.SetSize(quadrature_point_count, dimension * dimension);
|
||||
}
|
||||
|
||||
data.quadrature_data.SetSize(quadrature_point_count);
|
||||
|
||||
@@ -395,11 +414,13 @@ namespace mean_field::operators {
|
||||
|
||||
const double coefficient_value = source_coefficient.Eval(transformation, integration_point);
|
||||
|
||||
const mfem::DenseMatrix &inverse_element_jacobian = source_coefficient.GetInverseElementJacobian();
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
data.inverse_element_jacobians(quadrature_point, row * dimension + column) =
|
||||
inverse_element_jacobian(row, column);
|
||||
if (mode == PreparationMode::linearization) {
|
||||
const mfem::DenseMatrix &inverse_element_jacobian = source_coefficient.GetInverseElementJacobian();
|
||||
for (int row = 0; row < dimension; ++row) {
|
||||
for (int column = 0; column < dimension; ++column) {
|
||||
data.inverse_element_jacobians(quadrature_point, row * dimension + column) =
|
||||
inverse_element_jacobian(row, column);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,13 +441,16 @@ namespace mean_field::operators {
|
||||
|
||||
MFEM_VERIFY(!m_elements.empty(), "PreparedMappedGravitySourceOperator found no stellar elements.");
|
||||
|
||||
m_is_prepared = true;
|
||||
m_is_prepared = true;
|
||||
m_has_variation_data = mode == PreparationMode::linearization;
|
||||
++m_preparation_count;
|
||||
}
|
||||
void PreparedMappedGravitySourceOperator::Mult(
|
||||
const mfem::Vector &density,
|
||||
mfem::Vector &action
|
||||
) const {
|
||||
MEAN_FIELD_PROFILE_SCOPE("PreparedMappedGravitySourceOperator::Mult");
|
||||
|
||||
MFEM_VERIFY(
|
||||
m_is_prepared, "PreparedMappedGravitySourceOperator must be prepared before "
|
||||
"Mult is called."
|
||||
@@ -440,49 +464,47 @@ namespace mean_field::operators {
|
||||
m_density_true.SetSize(m_density_map.full_size());
|
||||
m_density_map.scatter(density, m_density_true);
|
||||
|
||||
mfem::Vector density_local;
|
||||
true_to_local(*m_fem.densityFes, m_density_true, m_density_local);
|
||||
|
||||
true_to_local(*m_fem.densityFes, m_density_true, density_local);
|
||||
|
||||
mfem::Vector local_action(m_fem.gravityPotentialFes->GetVSize());
|
||||
local_action = 0.0;
|
||||
|
||||
mfem::Vector element_density;
|
||||
mfem::Vector quadrature_density;
|
||||
mfem::Vector element_action;
|
||||
m_local_action.SetSize(m_fem.gravityPotentialFes->GetVSize());
|
||||
m_local_action = 0.0;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
density_local.GetSubVector(data.density_dofs, element_density);
|
||||
m_density_local.GetSubVector(data.density_dofs, m_element_input);
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->InvTransformPrimal(element_density);
|
||||
data.density_dof_transformation->InvTransformPrimal(m_element_input);
|
||||
}
|
||||
|
||||
quadrature_density.SetSize(data.quadrature_data.Size());
|
||||
m_quadrature_action.SetSize(data.quadrature_data.Size());
|
||||
|
||||
// B_density * x_e
|
||||
data.density_basis.Mult(element_density, quadrature_density);
|
||||
data.density_basis.Mult(m_element_input, m_quadrature_action);
|
||||
|
||||
// D * B_density * x_e
|
||||
for (int q = 0; q < quadrature_density.Size(); ++q) {
|
||||
quadrature_density(q) *= data.quadrature_data(q);
|
||||
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
|
||||
m_quadrature_action(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
element_action.SetSize(data.potential_dofs.Size());
|
||||
m_element_action.SetSize(data.potential_dofs.Size());
|
||||
|
||||
// B_potential^T * D * B_density * x_e
|
||||
data.potential_basis.MultTranspose(quadrature_density, element_action);
|
||||
data.potential_basis.MultTranspose(m_quadrature_action, m_element_action);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->TransformDual(element_action);
|
||||
data.potential_dof_transformation->TransformDual(m_element_action);
|
||||
}
|
||||
|
||||
local_action.AddElementVector(data.potential_dofs, element_action);
|
||||
m_local_action.AddElementVector(data.potential_dofs, m_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 (m_potential_map.is_identity()) {
|
||||
local_to_true(*m_fem.gravityPotentialFes, m_local_action, action);
|
||||
} else {
|
||||
local_to_true(*m_fem.gravityPotentialFes, m_local_action, m_action_true);
|
||||
action.SetSize(Height());
|
||||
m_potential_map.gather(m_action_true, action);
|
||||
}
|
||||
}
|
||||
|
||||
void PreparedMappedGravitySourceOperator::MultDisplacementVariationTrue(
|
||||
@@ -494,6 +516,11 @@ namespace mean_field::operators {
|
||||
m_is_prepared,
|
||||
"PreparedMappedGravitySourceOperator must be prepared before applying a displacement variation."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
m_has_variation_data,
|
||||
"PreparedMappedGravitySourceOperator requires linearization preparation before applying a displacement "
|
||||
"variation."
|
||||
);
|
||||
MFEM_VERIFY(
|
||||
densityTrue.Size() == m_fem.densityFes->GetTrueVSize(), "The full density vector has the wrong size."
|
||||
);
|
||||
@@ -591,47 +618,44 @@ namespace mean_field::operators {
|
||||
"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);
|
||||
}
|
||||
|
||||
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);
|
||||
if (m_potential_map.is_identity()) {
|
||||
true_to_local(*m_fem.gravityPotentialFes, potential, m_potential_local);
|
||||
} else {
|
||||
m_potential_true.SetSize(m_potential_map.full_size());
|
||||
m_potential_map.scatter(potential, m_potential_true);
|
||||
true_to_local(*m_fem.gravityPotentialFes, m_potential_true, m_potential_local);
|
||||
}
|
||||
|
||||
local_to_true(*m_fem.densityFes, local_action, m_action_true);
|
||||
m_local_action.SetSize(m_fem.densityFes->GetVSize());
|
||||
m_local_action = 0.0;
|
||||
|
||||
for (const ElementPAData &data : m_elements) {
|
||||
m_potential_local.GetSubVector(data.potential_dofs, m_element_input);
|
||||
|
||||
if (data.potential_dof_transformation != nullptr) {
|
||||
data.potential_dof_transformation->InvTransformPrimal(m_element_input);
|
||||
}
|
||||
|
||||
m_quadrature_action.SetSize(data.quadrature_data.Size());
|
||||
|
||||
data.potential_basis.Mult(m_element_input, m_quadrature_action);
|
||||
|
||||
for (int q = 0; q < m_quadrature_action.Size(); ++q) {
|
||||
m_quadrature_action(q) *= data.quadrature_data(q);
|
||||
}
|
||||
|
||||
m_element_action.SetSize(data.density_dofs.Size());
|
||||
|
||||
data.density_basis.MultTranspose(m_quadrature_action, m_element_action);
|
||||
|
||||
if (data.density_dof_transformation != nullptr) {
|
||||
data.density_dof_transformation->TransformDual(m_element_action);
|
||||
}
|
||||
|
||||
m_local_action.AddElementVector(data.density_dofs, m_element_action);
|
||||
}
|
||||
|
||||
local_to_true(*m_fem.densityFes, m_local_action, m_action_true);
|
||||
action.SetSize(Width());
|
||||
m_density_map.gather(m_action_true, action);
|
||||
}
|
||||
@@ -639,6 +663,10 @@ namespace mean_field::operators {
|
||||
return m_is_prepared;
|
||||
}
|
||||
|
||||
bool PreparedMappedGravitySourceOperator::HasVariationData() const noexcept {
|
||||
return m_has_variation_data;
|
||||
}
|
||||
|
||||
std::uint64_t PreparedMappedGravitySourceOperator::GetPreparationCount() const noexcept {
|
||||
return m_preparation_count;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user