Snapshot optimized solver and audit diagnostics before numerical experiments

This commit is contained in:
2026-09-16 14:34:06 -04:00
parent 75cc638739
commit 80cc3d83d7
64 changed files with 11969 additions and 267 deletions

View File

@@ -9,6 +9,7 @@ module;
#include <utility>
#include <mpi.h>
#include "interior_displacement_contractions.hpp"
module mean_field;
@@ -321,6 +322,7 @@ namespace mean_field::operators {
const bool updateTargetMass = !m_isPrepared || dependencies.targetMass != m_preparedDependencies.targetMass ||
state.targetMass != m_targetMass;
if (refreshGeometry || refreshDensity) m_jacobianRowsReady = false;
m_isPrepared = false;
PreparedMassNormalizationReport report;
@@ -603,7 +605,83 @@ namespace mean_field::operators {
++m_residualApplicationCount;
}
double PreparedMassNormalizationOperator::EvaluateDensityActionLocal(const mfem::Vector &densityVariation) const {
bool PreparedMassNormalizationOperator::PrepareJacobianRows() const {
VerifyPrepared();
if (m_jacobianRowsReady) return m_jacobianRowsSupported;
m_jacobianRowsSupported = false;
const int dimension = m_fem.mesh->Dimension();
for (const ElementPAData &data : m_elements) {
const auto &element = *m_fem.displacementFes->GetFE(data.elementId);
if (dimension < 1 || dimension > 3 || element.GetMapType() != mfem::FiniteElement::VALUE ||
element.GetDerivType() != mfem::FiniteElement::GRAD ||
m_domainMapper.IsCompactifiedElement(*m_fem.mesh->GetElementTransformation(data.elementId))) {
m_jacobianRowsReady = true;
return false;
}
}
m_densityJacobianLocal.SetSize(m_fem.densityFes->GetVSize());
m_displacementJacobianLocal.SetSize(m_fem.displacementFes->GetVSize());
m_densityJacobianLocal = 0.0;
m_displacementJacobianLocal = 0.0;
mfem::Vector densityRow, displacementRow;
mapping::VolumeMappingContext mappingContext;
constexpr double zeroPosition[3]{0.0, 0.0, 0.0};
for (const ElementPAData &data : m_elements) {
densityRow.SetSize(data.densityDofs.Size());
data.densityBasis->GetValues().MultTranspose(data.quadratureWeights, densityRow);
displacementRow.SetSize(data.displacementDofs.Size());
displacementRow = 0.0;
const auto basis = m_fem.GetReferenceTables().GetScalarTable(
*m_fem.displacementFes->GetFE(data.elementId), *data.integrationRule);
for (int q = 0; q < data.integrationRule->GetNPoints(); ++q) {
data.mappingContexts.Load(q, mappingContext);
add_interior_functional_row(
basis->GetGradients(q), basis->GetValues(), q, mappingContext.quadrature.J_inv,
data.density(q) * data.quadratureWeights(q), zeroPosition, displacementRow);
}
if (data.densityDofTransformation) data.densityDofTransformation->TransformDual(densityRow);
if (data.displacementDofTransformation) data.displacementDofTransformation->TransformDual(displacementRow);
m_densityJacobianLocal.AddElementVector(data.densityDofs, densityRow);
m_displacementJacobianLocal.AddElementVector(data.displacementDofs, displacementRow);
}
validate_finite_vector(m_densityJacobianLocal, "Prepared mass density row is non-finite.");
validate_finite_vector(m_displacementJacobianLocal, "Prepared mass displacement row is non-finite.");
m_jacobianRowsSupported = true;
m_jacobianRowsReady = true;
++m_jacobianRowPreparationCount;
return true;
}
std::uint64_t PreparedMassNormalizationOperator::GetJacobianRowPreparationCount() const noexcept {
return m_jacobianRowPreparationCount;
}
double PreparedMassNormalizationOperator::EvaluateDensityActionLocal(const mfem::Vector &direction) const {
if (!PrepareJacobianRows()) return EvaluateDensityActionLocalReference(direction);
true_to_local(*m_fem.densityFes, direction, m_densityVariationLocal);
return m_densityJacobianLocal * m_densityVariationLocal;
}
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocal(const mfem::Vector &direction) const {
if (!PrepareJacobianRows()) return EvaluateDisplacementActionLocalReference(direction);
true_to_local(*m_fem.displacementFes, direction, m_displacementVariationLocal);
return m_displacementJacobianLocal * m_displacementVariationLocal;
}
void PreparedMassNormalizationOperator::ApplyCompleteJacobianActionReference(
const mfem::Vector &densityVariation, const mfem::Vector &displacementVariation, mfem::Vector &action
) const {
VerifyPrepared();
validate_finite_vector(densityVariation, "Mass-normalization density direction is non-finite.");
validate_finite_vector(displacementVariation, "Mass-normalization displacement direction is non-finite.");
m_gravityContext.GetDensityMap().scatter(densityVariation, m_densityVariationTrue);
m_gravityContext.GetDisplacementMap().scatter(displacementVariation, m_displacementVariationTrue);
action.SetSize(1);
action(0) = GlobalSum(EvaluateDensityActionLocalReference(m_densityVariationTrue) +
EvaluateDisplacementActionLocalReference(m_displacementVariationTrue));
}
double PreparedMassNormalizationOperator::EvaluateDensityActionLocalReference(const mfem::Vector &densityVariation) const {
MFEM_VERIFY(
densityVariation.Size() == m_fem.densityFes->GetTrueVSize(),
"Mass-normalization density action received a vector with the "
@@ -635,7 +713,7 @@ namespace mean_field::operators {
return localAction;
}
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocal(
double PreparedMassNormalizationOperator::EvaluateDisplacementActionLocalReference(
const mfem::Vector &displacementVariation
) const {
MFEM_VERIFY(
@@ -898,8 +976,18 @@ namespace mean_field::operators {
VerifyPrepared();
MFEM_VERIFY(std::isfinite(residualDual), "Mass-normalization transpose action received a non-finite dual.");
AssembleDensityTransposeAction(residualDual, densityDual);
AssembleDisplacementTransposeAction(residualDual, displacementDual);
if (PrepareJacobianRows()) {
mfem::Vector trueDual;
local_to_true(*m_fem.densityFes, m_densityJacobianLocal, trueDual);
densityDual = m_gravityContext.GetDensityMap().gather(trueDual);
densityDual *= residualDual;
local_to_true(*m_fem.displacementFes, m_displacementJacobianLocal, trueDual);
displacementDual = m_gravityContext.GetDisplacementMap().gather(trueDual);
displacementDual *= residualDual;
} else {
AssembleDensityTransposeAction(residualDual, densityDual);
AssembleDisplacementTransposeAction(residualDual, displacementDual);
}
++m_actionStatistics.transposeApplications;
}