fix(operator): changed MULT (residuals) to deal with negated M properly

This commit is contained in:
2025-04-30 07:32:56 -04:00
parent ed4b6404ab
commit dee6ca80f4

View File

@@ -26,9 +26,6 @@
#include "../../../../utils/debugUtils/MFEMAnalysisUtils/MFEMAnalysis-cpp/src/include/mfem_smout.h"
static int s_PolyOperatorMultCalledCount = 0;
static int s_PolyOperatorGradCalledCount = 0;
void approxJacobiInvert(const mfem::SparseMatrix& mat, std::unique_ptr<mfem::SparseMatrix>& invMat, const std::string& name="matrix") {
// PERF: This likely can be made much more efficient and will probably be called in tight loops, a good
// PERF: place for some easy optimization might be here.
@@ -99,7 +96,8 @@ void PolytropeOperator::finalize(const mfem::Vector &initTheta) {
// m_negM_op = std::make_unique<mfem::ScaledOperator>(m_Mmat.get(), -1.0);
// m_negQ_op = std::make_unique<mfem::ScaledOperator>(m_Qmat.get(), -1.0);
m_Mmat->operator*=(-1.0);
// TODO Replace this with a scaled operator when I am done writing these out to disk
m_Mmat->operator*=(-1.0); // Sparse matrix only defines an inplace operator*= not an operator* so we need to do this
m_Qmat->operator*=(-1.0);
// Set up the constant parts of the jacobian now
@@ -165,7 +163,7 @@ void PolytropeOperator::Mult(const mfem::Vector &x, mfem::Vector &y) const {
MFEM_ASSERT(m_f.get() != nullptr, "NonlinearForm m_f is null in PolytropeOperator::Mult");
m_f->Mult(x_theta, f_term); // fixme: this may be the wrong way to assemble m_f?
m_M->Mult(x_phi, Mphi_term);
m_M->Mult(x_phi, Mphi_term); // Does the order of operations work out between this and the next subtract to make Mφ negative properly? I think so but double check
m_D->Mult(x_phi, Dphi_term);
m_Q->Mult(x_theta, Qtheta_term);
@@ -175,16 +173,16 @@ void PolytropeOperator::Mult(const mfem::Vector &x, mfem::Vector &y) const {
// -- Apply essential boundary conditions --
for (int i = 0; i < m_theta_ess_tdofs.first.Size(); i++) {
if (int idx = m_theta_ess_tdofs.first[i]; idx >= 0 && idx < y_R0.Size()) {
// const double &targetValue = m_theta_ess_tdofs.second[i];
// y_block.GetBlock(0)[idx] = targetValue - x_theta(idx); // inhomogenous essential bc. This is commented out since seems it results in dramatic instabilies arrising
y_block.GetBlock(0)[idx] = 0; // Zero out the essential theta dofs in the bi-linear form // TODO Check if this is double zeroing (i.e if they were already removed maybe I am removing something that should not be removed here)
const double &targetValue = m_theta_ess_tdofs.second[i];
y_block.GetBlock(0)[idx] = x_theta(idx) - targetValue; // inhomogenous essential bc. This is commented out since seems it results in dramatic instabilies arrising
}
}
std::cout << "θ Norm: " << y_block.GetBlock(0).Norml2() << std::endl;
for (int i = 0; i < m_phi_ess_tdofs.first.Size(); i++) {
if (int idx = m_phi_ess_tdofs.first[i]; idx >= 0 && idx < y_R1.Size()) {
y_block.GetBlock(1)[idx] = 0; // Zero out the essential phi dofs in the bi-linear form // TODO Check if this is double zeroing (i.e if they were already removed maybe I am removing something that should not be removed here)
const double &targetValue = m_phi_ess_tdofs.second[i];
y_block.GetBlock(1)[idx] = x_phi(idx) - targetValue; // inhomogenous essential bc. This is commented out since seems it results in dramatic instabilies arrising
}
}
@@ -205,14 +203,15 @@ void PolytropeOperator::updateInverseSchurCompliment() const {
if (m_invNonlinearJacobian == nullptr) {
MFEM_ABORT("PolytropeOperator::updateInverseSchurCompliment called before updateInverseNonlinearJacobian");
}
mfem::SparseMatrix* schurCompliment(&m_D->SpMat()); // This is now a copy of D
mfem::SparseMatrix* schurCompliment(&m_D->SpMat()); // Represents S in the preconditioner, starts as a copy of D before being modified in place
// Calculate S = D - Q df^{-1} M
mfem::SparseMatrix* temp_QxdfInv = mfem::Mult(m_Q->SpMat(), *m_invNonlinearJacobian); // Q * df^{-1}
const mfem::SparseMatrix* temp_QxdfInvxM = mfem::Mult(*temp_QxdfInv, m_M->SpMat()); // Q * df^{-1} * M
mfem::SparseMatrix* temp_QxdfInv = mfem::Mult(*m_Qmat, *m_invNonlinearJacobian); // Q * df^{-1}
const mfem::SparseMatrix* temp_QxdfInvxM = mfem::Mult(*temp_QxdfInv, *m_Mmat); // Q * df^{-1} * M
// PERF: Could potentially add some caching in here to only update the preconditioner when some condition has been met
schurCompliment->Add(-1, *temp_QxdfInvxM); // D - Q * df^{-1} * M
schurCompliment->Add(1, *temp_QxdfInvxM); // D - Q * df^{-1} * M
saveSparseMatrixBinary(*schurCompliment, "schurCompliment.bin");
approxJacobiInvert(*schurCompliment, m_invSchurCompliment, "Schur Compliment");
if (m_schurPreconditioner == nullptr) {