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:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user