Snapshot optimized solver and audit diagnostics before numerical experiments
This commit is contained in:
@@ -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.");
|
||||
|
||||
Reference in New Issue
Block a user