fix(PolytropeOperator): seperated boundary aware and unaware operators for M, Q, and D
residual calculation needs to be done when boundary degrees of freedom have not been removed (since their removal takes place in the Mult step in order to introduce the proper restoring force). Whereas jacobian calculation needs to always work from the boundary aware operators (these are sparse matrices) The other thing to note here is that this seems contrary to a matrix free design. While true it is common practive to assemble linear terms since they are cheap. We still never assemble the non linear matrix form.
This commit is contained in:
@@ -54,24 +54,34 @@ void PolytropeOperator::finalize(const mfem::Vector &initTheta) {
|
||||
return;
|
||||
}
|
||||
|
||||
m_M -> EliminateTestEssentialBC(m_theta_ess_tdofs.first);
|
||||
m_M -> EliminateTrialEssentialBC(m_phi_ess_tdofs.first);
|
||||
m_Mmat = std::make_unique<mfem::SparseMatrix>(m_M->SpMat());
|
||||
m_Qmat = std::make_unique<mfem::SparseMatrix>(m_Q->SpMat());
|
||||
m_Dmat = std::make_unique<mfem::SparseMatrix>(m_D->SpMat());
|
||||
|
||||
m_Q -> EliminateTestEssentialBC(m_phi_ess_tdofs.first);
|
||||
m_Q -> EliminateTrialEssentialBC(m_theta_ess_tdofs.first);
|
||||
// Remove the essential dofs from the constant matrices
|
||||
for (const auto& dof: m_theta_ess_tdofs.first) {
|
||||
m_Mmat->EliminateRow(dof);
|
||||
m_Qmat->EliminateCol(dof);
|
||||
}
|
||||
|
||||
m_D -> EliminateEssentialBC(m_phi_ess_tdofs.first);
|
||||
for (const auto& dof: m_phi_ess_tdofs.first) {
|
||||
m_Mmat->EliminateCol(dof);
|
||||
m_Qmat->EliminateRow(dof);
|
||||
m_Dmat->EliminateRowCol(dof);
|
||||
}
|
||||
|
||||
m_negM_op = std::make_unique<mfem::ScaledOperator>(m_M.get(), -1.0);
|
||||
m_negQ_op = std::make_unique<mfem::ScaledOperator>(m_Q.get(), -1.0);
|
||||
m_negM_mat = std::make_unique<mfem::ScaledOperator>(m_Mmat.get(), -1.0);
|
||||
m_negQ_mat = std::make_unique<mfem::ScaledOperator>(m_Qmat.get(), -1.0);
|
||||
|
||||
m_schurCompliment = std::make_unique<SchurCompliment>(*m_Q, *m_D, *m_M);
|
||||
m_schurCompliment = std::make_unique<SchurCompliment>(*m_Qmat, *m_Dmat, *m_Mmat);
|
||||
|
||||
// Set up the constant parts of the jacobian now
|
||||
|
||||
// We use the assembled matrices with their boundary conditions already removed for the jacobian
|
||||
m_jacobian = std::make_unique<mfem::BlockOperator>(m_blockOffsets);
|
||||
m_jacobian->SetBlock(0, 1, m_negM_op.get()); //<- -M (constant)
|
||||
m_jacobian->SetBlock(1, 0, m_negQ_op.get()); //<- -Q (constant)
|
||||
m_jacobian->SetBlock(1, 1, m_D.get()); //<- D (constant)
|
||||
m_jacobian->SetBlock(0, 1, m_negM_mat.get()); //<- -M (constant)
|
||||
m_jacobian->SetBlock(1, 0, m_negQ_mat.get()); //<- -Q (constant)
|
||||
m_jacobian->SetBlock(1, 1, m_Dmat.get()); //<- D (constant)
|
||||
|
||||
m_invSchurCompliment = std::make_unique<GMRESInverter>(*m_schurCompliment);
|
||||
|
||||
@@ -240,9 +250,9 @@ void GMRESInverter::Mult(const mfem::Vector &x, mfem::Vector &y) const {
|
||||
|
||||
|
||||
SchurCompliment::SchurCompliment(
|
||||
const mfem::MixedBilinearForm &QOp,
|
||||
const mfem::BilinearForm &DOp,
|
||||
const mfem::MixedBilinearForm &MOp,
|
||||
const mfem::SparseMatrix &QOp,
|
||||
const mfem::SparseMatrix &DOp,
|
||||
const mfem::SparseMatrix &MOp,
|
||||
const mfem::Solver &GradInvOp) :
|
||||
mfem::Operator(DOp.Height(), DOp.Width())
|
||||
{
|
||||
@@ -252,9 +262,9 @@ mfem::Operator(DOp.Height(), DOp.Width())
|
||||
}
|
||||
|
||||
SchurCompliment::SchurCompliment(
|
||||
const mfem::MixedBilinearForm &QOp,
|
||||
const mfem::BilinearForm &DOp,
|
||||
const mfem::MixedBilinearForm &MOp) :
|
||||
const mfem::SparseMatrix &QOp,
|
||||
const mfem::SparseMatrix &DOp,
|
||||
const mfem::SparseMatrix &MOp) :
|
||||
mfem::Operator(DOp.Height(), DOp.Width())
|
||||
{
|
||||
updateConstantTerms(QOp, DOp, MOp);
|
||||
@@ -262,7 +272,7 @@ mfem::Operator(DOp.Height(), DOp.Width())
|
||||
m_nTheta = m_MOp->Height();
|
||||
}
|
||||
|
||||
void SchurCompliment::SetOperator(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp, const mfem::Solver &GradInvOp) {
|
||||
void SchurCompliment::SetOperator(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp, const mfem::Solver &GradInvOp) {
|
||||
updateConstantTerms(QOp, DOp, MOp);
|
||||
updateInverseNonlinearJacobian(GradInvOp);
|
||||
}
|
||||
@@ -271,7 +281,7 @@ void SchurCompliment::updateInverseNonlinearJacobian(const mfem::Solver &gradInv
|
||||
m_GradInvOp = &gradInv;
|
||||
}
|
||||
|
||||
void SchurCompliment::updateConstantTerms(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp) {
|
||||
void SchurCompliment::updateConstantTerms(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp) {
|
||||
m_QOp = &QOp;
|
||||
m_DOp = &DOp;
|
||||
m_MOp = &MOp;
|
||||
|
||||
Reference in New Issue
Block a user