26#include "mfem_smout.h"
37 const mfem::SparseMatrix &QOp,
38 const mfem::SparseMatrix &DOp,
39 const mfem::SparseMatrix &MOp,
40 const mfem::Solver &GradInvOp ) :
41mfem::Operator(DOp.Height(), DOp.Width()) {
49 const mfem::SparseMatrix &QOp,
50 const mfem::SparseMatrix &DOp,
51 const mfem::SparseMatrix &MOp) :
52mfem::Operator(DOp.Height(), DOp.Width())
63 MFEM_ABORT(
"Input vector x has size " + std::to_string(x.Size()) +
", expected " + std::to_string(
m_nPhi));
66 MFEM_ABORT(
"Output vector y has size " + std::to_string(y.Size()) +
", expected " + std::to_string(
m_nPhi));
70 if (
m_QOp ==
nullptr) {
71 MFEM_ABORT(
"QOp is null in SchurCompliment::Mult");
73 if (
m_DOp ==
nullptr) {
74 MFEM_ABORT(
"DOp is null in SchurCompliment::Mult");
76 if (
m_MOp ==
nullptr) {
77 MFEM_ABORT(
"MOp is null in SchurCompliment::Mult");
80 MFEM_ABORT(
"GradInvOp is null in SchurCompliment::Mult");
98void SchurCompliment::SetOperator(
const mfem::SparseMatrix &QOp,
const mfem::SparseMatrix &DOp,
const mfem::SparseMatrix &MOp,
const mfem::Solver &GradInvOp) {
119mfem::Operator(op.Height(), op.Width()),
136 std::unique_ptr<mfem::MixedBilinearForm> M,
137 std::unique_ptr<mfem::MixedBilinearForm> Q,
138 std::unique_ptr<mfem::BilinearForm> D,
139 std::unique_ptr<mfem::BilinearForm> S,
140 std::unique_ptr<mfem::NonlinearForm> f,
141 const mfem::Array<int> &blockOffsets) :
144 mfem::Operator(blockOffsets.Last()),
163 MFEM_ABORT(
"PolytropeOperator::Mult called before finalize");
176 const mfem::Vector &x_theta = x_block.GetBlock(0);
177 const mfem::Vector &x_phi = x_block.GetBlock(1);
178 mfem::Vector &y_R0 = y_block.GetBlock(0);
179 mfem::Vector &y_R1 = y_block.GetBlock(1);
184 mfem::Vector f_term(theta_size);
185 mfem::Vector Mphi_term(theta_size);
186 mfem::Vector Dphi_term(phi_size);
187 mfem::Vector Qtheta_term(phi_size);
188 mfem::Vector Stheta_term(theta_size);
195 MFEM_ASSERT(
m_f.get() !=
nullptr,
"NonlinearForm m_f is null in PolytropeOperator::Mult");
197 m_f->Mult(x_theta, f_term);
198 m_M->Mult(x_phi, Mphi_term);
199 m_D->Mult(x_phi, Dphi_term);
200 m_Q->Mult(x_theta, Qtheta_term);
201 m_S->Mult(x_theta, Stheta_term);
209 mfem::Vector y_R0_temp(theta_size);
210 add(f_term, Mphi_term, y_R0_temp);
211 add(y_R0_temp, Stheta_term, y_R0);
212 subtract(Dphi_term, Qtheta_term, y_R1);
216 MFEM_ASSERT(
m_freeDofs.Size() ==
m_reducedBlockOffsets.Last(),
"PolytropeOperator::Mult: Size of free dofs does not match reduced block offsets size.");
217 for (
int i = 0, j = 0; i < y.Size(); ++i) {
227 MFEM_ABORT(
"PolytropeOperator::GetGradient called before finalize");
232 const mfem::Vector& x_theta = x_block.GetBlock(0);
235 auto &grad =
m_f->GetGradient(x_theta);
237 const auto gradMatrix =
dynamic_cast<mfem::SparseMatrix*
>(&grad);
239 if (gradMatrix ==
nullptr) {
240 MFEM_ABORT(
"PolytropeOperator::GetGradient: Gradient is not a SparseMatrix.");
293 m_f->SetEssentialTrueDofs(theta_ess_tdofs.first);
295 MFEM_ABORT(
"m_f is null in PolytropeOperator::SetEssentialTrueDofs");
310 MFEM_ABORT(
"Jacobian has not been initialized before GetJacobianOperator() call.");
313 MFEM_ABORT(
"PolytropeOperator not finalized prior to call to GetJacobianOperator().");
321 MFEM_ABORT(
"Schur preconditioner has not been initialized before GetPreconditioner() call.");
324 MFEM_ABORT(
"PolytropeOperator not finalized prior to call to GetPreconditioner().");
331 MFEM_ABORT(
"PolytropeOperator not finalized prior to call to GetReducedSystemSize().");
352 const int thetaSearchIndex = i;
354 if (phiSearchIndex < 0){
369 m_Mmat = std::make_unique<mfem::SparseMatrix>(
m_M->SpMat());
370 m_Qmat = std::make_unique<mfem::SparseMatrix>(
m_Q->SpMat());
371 m_Dmat = std::make_unique<mfem::SparseMatrix>(
m_D->SpMat());
372 m_Smat = std::make_unique<mfem::SparseMatrix>(
m_S->SpMat());
375 m_MReduced = std::make_unique<mfem::SparseMatrix>(
381 m_QReduced = std::make_unique<mfem::SparseMatrix>(
387 m_DReduced = std::make_unique<mfem::SparseMatrix>(
393 m_SReduced = std::make_unique<mfem::SparseMatrix>(
455 m_state.SetSubVector(phiDofIndices, phiStateValues);
467 MFEM_ABORT(
"PolytropeOperator::updateInverseSchurCompliment called before finalize");
470 MFEM_ABORT(
"PolytropeOperator::updateInverseSchurCompliment called before updateInverseNonlinearJacobian");
473 MFEM_ABORT(
"PolytropeOperator::updateInverseSchurCompliment called before updateInverseSchurCompliment");
const SchurCompliment & m_op
Reference to the SchurCompliment operator to be inverted.
GMRESInverter(const SchurCompliment &op)
Constructs a GMRESInverter.
mfem::GMRESSolver m_solver
GMRES solver instance.
void Mult(const mfem::Vector &x, mfem::Vector &y) const override
Applies the GMRES solver to approximate op^-1 * x.
std::unique_ptr< mfem::BilinearForm > m_S
Bilinear form S, used for least squares stabilization.
mfem::Array< int > m_freeDofs
Array of indices for free (non-essential) DOFs.
std::unique_ptr< mfem::MixedBilinearForm > m_Q
Bilinear form Q, coupling φ and θ.
std::unique_ptr< mfem::BlockDiagonalPreconditioner > m_schurPreconditioner
Block diagonal preconditioner for the system.
std::unique_ptr< mfem::SparseMatrix > m_Qmat
Sparse matrix representation of Q.
std::unique_ptr< SchurCompliment > m_schurCompliment
Schur complement S = D_reduced - Q_reduced * G_inv_reduced * M_reduced.
const mfem::BlockVector reconstruct_full_block_state_vector(const mfem::Vector &reducedState) const
void finalize(const mfem::Vector &initTheta)
Finalizes the operator setup. This must be called after setting essential true DOFs and before using ...
std::unique_ptr< mfem::SparseMatrix > m_QScaledReduced
Scaled Q matrix (free DOFs only, scaled by stabilization coefficient).
std::unique_ptr< mfem::MixedBilinearForm > m_M
Bilinear form M, coupling θ and φ.
void Mult(const mfem::Vector &xFree, mfem::Vector &yFree) const override
Applies the PolytropeOperator: y = F(x). This computes the residual of the nonlinear system.
void populate_free_dof_array()
Populates the internal array of free (non-essential) degree of freedom indices. This is called during...
std::unique_ptr< mfem::SparseMatrix > m_DScaledReduced
Scaled D matrix (free DOFs only, scaled by stabilization coefficient).
std::unique_ptr< mfem::NonlinearForm > m_f
Nonlinear form f, acting on θ.
void construct_reduced_block_offsets()
Constructs the block offsets for the reduced system. Called during finalize().
std::unique_ptr< mfem::SparseMatrix > m_MScaledReduced
Scaled M matrix (free DOFs only, scaled by stabilization coefficient).
mfem::Operator & GetGradient(const mfem::Vector &xFree) const override
Computes the Jacobian of the PolytropeOperator at a given state xFree. The Jacobian is of the form: J...
std::unique_ptr< mfem::SparseMatrix > m_ScaledSReduced
Scaled S matrix (free DOFs only, scaled by stabilization coefficient).
std::unique_ptr< mfem::SparseMatrix > m_gradReduced
Reduced gradient operator (G) for the nonlinear part f(θ).
PolytropeOperator(std::unique_ptr< mfem::MixedBilinearForm > M, std::unique_ptr< mfem::MixedBilinearForm > Q, std::unique_ptr< mfem::BilinearForm > D, std::unique_ptr< mfem::BilinearForm > S, std::unique_ptr< mfem::NonlinearForm > f, const mfem::Array< int > &blockOffsets)
Constructs the PolytropeOperator.
void update_preconditioner(const mfem::Operator &grad) const
Updates the preconditioner components. This involves updating the inverse nonlinear Jacobian and then...
mfem::Vector m_state
Full state vector [θ, φ]^T, including essential DOFs.
void set_essential_true_dofs(const serif::types::MFEMArrayPair &theta_ess_tdofs, const serif::types::MFEMArrayPair &phi_ess_tdofs)
Sets the essential true degrees of freedom for both θ and φ variables. Marks the operator as not fina...
const mfem::BlockOperator & get_jacobian_operator() const
— Getters for key internal state and operators —
mfem::Array< int > m_reducedBlockOffsets
Block offsets for the reduced system (free DOFs).
const mfem::Array< int > m_blockOffsets
Block offsets for the full system [0, size(θ), size(θ)+size(φ)].
serif::types::MFEMArrayPairSet get_essential_true_dofs() const
Gets the currently set essential true degrees of freedom.
const mfem::Vector & reconstruct_full_state_vector(const mfem::Vector &reducedState) const
Reconstructs the full state vector (including essential DOFs) from a reduced state vector (free DOFs)...
void scatter_boundary_conditions()
Scatters the values of essential boundary conditions into the full state vector. Called during finali...
int get_reduced_system_size() const
Gets the size of the reduced system (number of free DOFs). Asserts that the operator is finalized.
std::unique_ptr< GMRESInverter > m_invSchurCompliment
Approximate inverse of the Schur complement.
void construct_matrix_representations()
Constructs the sparse matrix representations of M, Q, and D, and their reduced forms....
serif::types::MFEMArrayPair m_phi_ess_tdofs
Essential true DOFs for φ (indices and values).
std::unique_ptr< mfem::SparseMatrix > m_MReduced
Reduced M matrix (free DOFs only).
static constexpr double m_stabilizationCoefficient
Stabilization coefficient for the system, used to more tightly couple ∇θ and φ.
serif::types::MFEMArrayPair m_theta_ess_tdofs
Essential true DOFs for θ (indices and values).
std::unique_ptr< mfem::SparseMatrix > m_Smat
std::unique_ptr< mfem::Solver > m_invNonlinearJacobian
Solver for the inverse of the G block (gradient of f(θ)_reduced).
std::unique_ptr< mfem::SparseMatrix > m_Dmat
Sparse matrix representation of D.
std::unique_ptr< mfem::SparseMatrix > m_Mmat
Sparse matrix representation of M.
void update_inverse_schur_compliment() const
Updates the inverse Schur complement operator and its components. This is typically called after the ...
static constexpr double m_IncrementedStabilizationCoefficient
1 + Stabilization coefficient for the system, used to more tightly couple ∇θ and φ.
bool m_isFinalized
Flag indicating if finalize() has been called.
mfem::BlockDiagonalPreconditioner & get_preconditioner() const
Gets the block diagonal preconditioner for the Schur complement system. Asserts that the operator is ...
std::unique_ptr< mfem::SparseMatrix > m_SReduced
Reduced S matrix (free DOFs only, used for least squares stabilization).
void construct_jacobian_constant_terms()
Constructs the constant terms of the Jacobian operator (M, -Q, D). The (0,0) block (gradient of f) is...
std::unique_ptr< mfem::SparseMatrix > m_DReduced
Reduced D matrix (free DOFs only).
std::unique_ptr< mfem::ScaledOperator > m_negQ_mat
Scaled operator for -Q_reduced.
void update_inverse_nonlinear_jacobian(const mfem::Operator &grad) const
Updates the solver for the inverse of the nonlinear Jacobian block (G_00).
std::unique_ptr< mfem::BlockOperator > m_jacobian
Jacobian operator J = [G M; -Q D]_reduced.
std::unique_ptr< mfem::SparseMatrix > m_QReduced
Reduced Q matrix (free DOFs only).
std::unique_ptr< mfem::BilinearForm > m_D
Bilinear form D, acting on φ.
Represents the Schur complement operator used in the solution process.
SchurCompliment(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp, const mfem::Solver &GradInvOp)
Constructs a SchurCompliment operator.
const mfem::Solver * m_GradInvOp
Pointer to the inverse of the gradient operator.
int m_nPhi
Dimension related to the phi variable (typically number of rows/cols of D).
void updateInverseNonlinearJacobian(const mfem::Solver &gradInv)
Updates the inverse of the nonlinear Jacobian (GradInv).
void Mult(const mfem::Vector &x, mfem::Vector &y) const override
Applies the Schur complement operator: y = (D - Q * GradInv * M) * x.
int m_nTheta
Dimension related to the theta variable (typically number of rows of M).
const mfem::SparseMatrix * m_QOp
Pointer to the Q matrix operator.
const mfem::SparseMatrix * m_DOp
Pointer to the D matrix operator.
const mfem::SparseMatrix * m_MOp
Pointer to the M matrix operator.
void updateConstantTerms(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp)
Updates the constant matrix terms (Q, D, M).
void SetOperator(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp, const mfem::Solver &GradInvOp)
Sets all operators for the Schur complement.
std::pair< mfem::Array< int >, mfem::Array< double > > MFEMArrayPair
std::pair< MFEMArrayPair, MFEMArrayPair > MFEMArrayPairSet
mfem::SparseMatrix build_reduced_matrix(const mfem::SparseMatrix &matrix, const mfem::Array< int > &trialEssentialDofs, const mfem::Array< int > &testEssentialDofs)