fix(poly): added stabilization term

least squares stabalization term seems to have stabilized polytrope and mostly resolve the overshoot mode (in more non linear cases (n > 2) the mode does reapear; however, it is much less pronounced
This commit is contained in:
2025-06-11 10:43:09 -04:00
parent 1e85c48f33
commit 26febe7fbb
4 changed files with 120 additions and 45 deletions

View File

@@ -114,24 +114,25 @@ void PolySolver::assembleBlockSystem() {
const std::unique_ptr<formBundle> forms = buildIndividualForms(blockOffsets);
const double penalty_param = m_config.get<double>("Poly::Solver::ZeroDerivativePenalty", 1.0);
mfem::Array<int> thetaCenterDofs, phiCenterDofs;
std::tie(thetaCenterDofs, phiCenterDofs) = findCenterElement();
mfem::SparseMatrix& D_mat = forms->D->SpMat();
for (int i = 0; i < phiCenterDofs.Size(); ++i)
{
const int dof_idx = phiCenterDofs[i];
if (dof_idx >= 0 && dof_idx < D_mat.Height()) {
D_mat(dof_idx, dof_idx) += penalty_param;
}
}
// const double penalty_param = m_config.get<double>("Poly::Solver::ZeroDerivativePenalty", 1.0);
// mfem::Array<int> thetaCenterDofs, phiCenterDofs;
// std::tie(thetaCenterDofs, phiCenterDofs) = findCenterElement();
// mfem::SparseMatrix& D_mat = forms->D->SpMat();
//
// for (int i = 0; i < phiCenterDofs.Size(); ++i)
// {
// const int dof_idx = phiCenterDofs[i];
// if (dof_idx >= 0 && dof_idx < D_mat.Height()) {
// D_mat(dof_idx, dof_idx) += penalty_param;
// }
// }
// --- Build the BlockOperator ---
m_polytropOperator = std::make_unique<PolytropeOperator>(
std::move(forms->M),
std::move(forms->Q),
std::move(forms->D),
std::move(forms->S),
std::move(forms->f),
blockOffsets);
}
@@ -152,26 +153,26 @@ std::unique_ptr<formBundle> PolySolver::buildIndividualForms(const mfem::Array<i
std::make_unique<mfem::MixedBilinearForm>(m_fePhi.get(), m_feTheta.get()),
std::make_unique<mfem::MixedBilinearForm>(m_feTheta.get(), m_fePhi.get()),
std::make_unique<mfem::BilinearForm>(m_fePhi.get()),
std::make_unique<mfem::BilinearForm>(m_feTheta.get()),
std::make_unique<mfem::NonlinearForm>(m_feTheta.get())
);
// --- -M negation -> M ---
mfem::Vector negOneVec(m_mesh.SpaceDimension());
negOneVec = -1.0;
m_negationCoeff = std::make_unique<mfem::VectorConstantCoefficient>(negOneVec);
// --- Add the integrators to the forms ---
forms->M->AddDomainIntegrator(new mfem::MixedVectorWeakDivergenceIntegrator());
forms->Q->AddDomainIntegrator(new mfem::MixedVectorGradientIntegrator());
forms->D->AddDomainIntegrator(new mfem::VectorFEMassIntegrator());
forms->M->AddDomainIntegrator(new mfem::MixedVectorWeakDivergenceIntegrator()); // M ∫∇ψ^θ·N^φ dV
forms->Q->AddDomainIntegrator(new mfem::MixedVectorGradientIntegrator()); // Q ∫ψ^φ·∇N^θ dV
forms->D->AddDomainIntegrator(new mfem::VectorFEMassIntegrator()); // D ∫ψ^φ·N^φ dV
forms->S->AddDomainIntegrator(new mfem::DiffusionIntegrator()); // S ∫∇ψ^θ·∇N^θ dV
forms->f->AddDomainIntegrator(new polyMFEMUtils::NonlinearPowerIntegrator(m_polytropicIndex));
// --- Assemble and Finalize the forms ---
assembleAndFinalizeForm(forms->M);
assembleAndFinalizeForm(forms->Q);
assembleAndFinalizeForm(forms->D);
assembleAndFinalizeForm(forms->S);
// Note: The NonlinearForm does not need to / cannot be finalized, as it is not a matrix form. Rather, the operator
// will evaluate the nonlinear form during the solve phase.
forms->f->AddDomainIntegrator(new polyMFEMUtils::NonlinearPowerIntegrator(m_polytropicIndex));
return forms;
}
@@ -179,7 +180,7 @@ std::unique_ptr<formBundle> PolySolver::buildIndividualForms(const mfem::Array<i
void PolySolver::assembleAndFinalizeForm(auto &f) {
// This constructs / ensures the matrix representation for each form
// Assemble => Computes the local element matrices across the domain. Adds these to the global matrix . Adds these to the global matrix.
// Finalize => Builds the sparsity pattern and allows the SparseMatrix representation to be extracted.
// Finalize => Builds the sparsity pattern and allows the SparseMatrix representation to be extracted (CSR).
f->Assemble();
f->Finalize();
}

View File

@@ -49,6 +49,7 @@ struct formBundle {
std::unique_ptr<mfem::MixedBilinearForm> M; //<-- M ∫∇ψ^θ·N^φ dV
std::unique_ptr<mfem::MixedBilinearForm> Q; //<-- Q ∫ψ^φ·∇N^θ dV
std::unique_ptr<mfem::BilinearForm> D; //<-- D ∫ψ^φ·N^φ dV
std::unique_ptr<mfem::BilinearForm> S; //<-- S ∫∇ψ^θ·∇N^θ dV
std::unique_ptr<mfem::NonlinearForm> f; //<-- f(θ) ∫ψ^θ·θ^n dV
};
@@ -84,8 +85,6 @@ private: // Private Attributes
std::unique_ptr<mfem::OperatorJacobiSmoother> m_prec;
std::unique_ptr<mfem::VectorConstantCoefficient> m_negationCoeff;
private: // Private methods
PolySolver(mfem::Mesh& mesh, double n, double order);