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

@@ -3,6 +3,7 @@ module;
#include <cmath>
#include <memory>
#include <mfem.hpp>
#include <mpi.h>
#include <stdexcept>
module mean_field;
@@ -41,9 +42,33 @@ namespace mean_field::preconditioning {
return assembled;
}
const mfem::HypreParMatrix &PreparedGravityDivergenceCache::Get(const fem::FEM &f) {
if (!f.mesh || !f.gravityFluxFes || !f.gravityPotentialFes || !f.quadratureFactory)
throw std::invalid_argument("Fixed divergence caching requires a complete gravity discretization.");
const auto *mesh = f.mesh.get();
const auto *flux = f.gravityFluxFes.get(), *potential = f.gravityPotentialFes.get();
const int localChanged = !m_matrix || m_mesh != mesh || m_flux != flux || m_potential != potential ||
m_policy != f.quadratureFactory.get() || m_meshSequence != mesh->GetSequence() ||
m_nodesSequence != mesh->GetNodesSequence() || m_fluxSequence != flux->GetSequence() ||
m_potentialSequence != potential->GetSequence();
int changed = 0;
if (MPI_Allreduce(&localChanged, &changed, 1, MPI_INT, MPI_MAX, f.mesh->GetComm()) != MPI_SUCCESS)
throw std::runtime_error("Could not synchronize fixed divergence cache validity.");
if (changed) {
auto matrix = assembleGravityDivergenceSurrogate(f);
m_matrix = std::move(matrix);
m_mesh = mesh; m_flux = flux; m_potential = potential; m_policy = f.quadratureFactory.get();
m_meshSequence = mesh->GetSequence(); m_nodesSequence = mesh->GetNodesSequence();
m_fluxSequence = flux->GetSequence(); m_potentialSequence = potential->GetSequence();
++m_builds;
}
return *m_matrix;
}
std::unique_ptr<mfem::HypreParMatrix> assembleGravityPotentialSchurSurrogate(
const fem::FEM &f,
const mfem::Vector &trueMassDiagonal
const mfem::Vector &trueMassDiagonal,
PreparedGravityDivergenceCache *divergenceCache
) {
if (f.gravityFluxFes == nullptr || trueMassDiagonal.Size() != f.gravityFluxFes->GetTrueVSize()) {
throw std::invalid_argument(
@@ -62,12 +87,14 @@ namespace mean_field::preconditioning {
inverseMassDiagonal(index) = 1.0 / entry;
}
std::unique_ptr<mfem::HypreParMatrix> divergence = assembleGravityDivergenceSurrogate(f);
std::unique_ptr<mfem::HypreParMatrix> inverseMassDivergenceTranspose(divergence->Transpose());
std::unique_ptr<mfem::HypreParMatrix> uncachedDivergence;
if (!divergenceCache) uncachedDivergence = assembleGravityDivergenceSurrogate(f);
const mfem::HypreParMatrix &divergence = divergenceCache ? divergenceCache->Get(f) : *uncachedDivergence;
std::unique_ptr<mfem::HypreParMatrix> inverseMassDivergenceTranspose(divergence.Transpose());
inverseMassDivergenceTranspose->ScaleRows(inverseMassDiagonal);
std::unique_ptr<mfem::HypreParMatrix> schur(
mfem::ParMult(divergence.get(), inverseMassDivergenceTranspose.get())
mfem::ParMult(&divergence, inverseMassDivergenceTranspose.get())
);
if (schur == nullptr) {
throw std::runtime_error("MFEM did not assemble the gravity potential-Schur surrogate.");