SERiF 0.0.1a
3+1D Stellar Structure and Evolution
Loading...
Searching...
No Matches
polytropeOperator.h
Go to the documentation of this file.
1/* ***********************************************************************
2//
3// Copyright (C) 2025 -- The 4D-STAR Collaboration
4// File Author: Emily Boudreaux
5// Last Modified: April 21, 2025
6//
7// 4DSSE is free software; you can use it and/or modify
8// it under the terms and restrictions the GNU General Library Public
9// License version 3 (GPLv3) as published by the Free Software Foundation.
10//
11// 4DSSE is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14// See the GNU Library General Public License for more details.
15//
16// You should have received a copy of the GNU Library General Public License
17// along with this software; if not, write to the Free Software
18// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19//
20// *********************************************************************** */
21#pragma once
22
23#include "mfem.hpp"
24#include "4DSTARTypes.h"
25#include <memory>
26
27#include "probe.h"
28
29namespace serif::polytrope {
30
36class SchurCompliment final : public mfem::Operator {
37public:
46 const mfem::SparseMatrix &QOp,
47 const mfem::SparseMatrix &DOp,
48 const mfem::SparseMatrix &MOp,
49 const mfem::Solver &GradInvOp
50 );
51
60 const mfem::SparseMatrix &QOp,
61 const mfem::SparseMatrix &DOp,
62 const mfem::SparseMatrix &MOp
63 );
64
68 ~SchurCompliment() override = default;
69
75 void Mult(const mfem::Vector &x, mfem::Vector &y) const override;
76
84 void SetOperator(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp, const mfem::Solver &GradInvOp);
85
90 void updateInverseNonlinearJacobian(const mfem::Solver &gradInv);
91
92private:
99 void updateConstantTerms(const mfem::SparseMatrix &QOp, const mfem::SparseMatrix &DOp, const mfem::SparseMatrix &MOp);
100
101private:
102 // Pointers to external operators (not owned by this class)
103 const mfem::SparseMatrix* m_QOp = nullptr;
104 const mfem::SparseMatrix* m_DOp = nullptr;
105 const mfem::SparseMatrix* m_MOp = nullptr;
106 const mfem::Solver* m_GradInvOp = nullptr;
107
108 // Dimensions
109 int m_nPhi = 0;
110 int m_nTheta = 0;
111
112 // Owned resources
113 mutable std::unique_ptr<mfem::SparseMatrix> m_matrixForm;
114};
115
119class GMRESInverter final : public mfem::Operator {
120public:
125 explicit GMRESInverter(const SchurCompliment& op);
126
130 ~GMRESInverter() override = default;
131
137 void Mult(const mfem::Vector &x, mfem::Vector &y) const override;
138
139private:
141 mfem::GMRESSolver m_solver;
142};
143
152class PolytropeOperator final : public mfem::Operator {
153public:
163 std::unique_ptr<mfem::MixedBilinearForm> M,
164 std::unique_ptr<mfem::MixedBilinearForm> Q,
165 std::unique_ptr<mfem::BilinearForm> D,
166 std::unique_ptr<mfem::BilinearForm> S,
167 std::unique_ptr<mfem::NonlinearForm> f,
168 const mfem::Array<int> &blockOffsets);
169
173 ~PolytropeOperator() override = default;
174
181 void Mult(const mfem::Vector &xFree, mfem::Vector &yFree) const override;
182
192 mfem::Operator& GetGradient(const mfem::Vector &xFree) const override;
193
200 void finalize(const mfem::Vector &initTheta);
201
206 bool isFinalized() const { return m_isFinalized; }
207
214 void set_essential_true_dofs(const serif::types::MFEMArrayPair& theta_ess_tdofs, const serif::types::MFEMArrayPair& phi_ess_tdofs);
215
221 void set_essential_true_dofs(const serif::types::MFEMArrayPairSet& ess_tdof_pair_set);
222
223
229 [[nodiscard]] const mfem::Vector &reconstruct_full_state_vector(const mfem::Vector &reducedState) const;
230
236 [[nodiscard]] const mfem::BlockVector reconstruct_full_block_state_vector(const mfem::Vector &reducedState) const;
237
243
245
250 const mfem::BlockOperator &get_jacobian_operator() const;
251
257 mfem::BlockDiagonalPreconditioner &get_preconditioner() const;
258
259
261
265 const mfem::Array<int>& get_free_dofs() const { return m_freeDofs; }
266
272 int get_reduced_system_size() const;
273
279
284 const mfem::Array<int>& get_block_offsets() const { return m_blockOffsets; }
285
290 const mfem::Array<int>& get_reduced_block_offsets() const {return m_reducedBlockOffsets; }
291
292private:
293 // --- Logging ---
295 quill::Logger* m_logger = m_logManager.getLogger("log");
296
297 // --- Input Bilinear/Nonlinear Forms (owned) ---
298 std::unique_ptr<mfem::MixedBilinearForm> m_M;
299 std::unique_ptr<mfem::MixedBilinearForm> m_Q;
300 std::unique_ptr<mfem::BilinearForm> m_D;
301 std::unique_ptr<mfem::BilinearForm> m_S;
302 std::unique_ptr<mfem::NonlinearForm> m_f;
303
304 // --- Full Matrix Representations (owned, derived from forms) ---
305 std::unique_ptr<mfem::SparseMatrix> m_Mmat;
306 std::unique_ptr<mfem::SparseMatrix> m_Qmat;
307 std::unique_ptr<mfem::SparseMatrix> m_Dmat;
308 std::unique_ptr<mfem::SparseMatrix> m_Smat;
309
310 // --- Reduced Matrix Representations (owned, after eliminating essential DOFs) ---
311 std::unique_ptr<mfem::SparseMatrix> m_MReduced;
312 std::unique_ptr<mfem::SparseMatrix> m_QReduced;
313 std::unique_ptr<mfem::SparseMatrix> m_DReduced;
314 std::unique_ptr<mfem::SparseMatrix> m_SReduced;
315 mutable std::unique_ptr<mfem::SparseMatrix> m_gradReduced;
316
317 // --- Scaled Reduced Matrix Representations (owned, after eliminating essential DOFs and scaling by stabilization coefficients) ---
318 std::unique_ptr<mfem::SparseMatrix> m_MScaledReduced;
319 std::unique_ptr<mfem::SparseMatrix> m_QScaledReduced;
320 std::unique_ptr<mfem::SparseMatrix> m_DScaledReduced;
321 std::unique_ptr<mfem::SparseMatrix> m_ScaledSReduced;
322
323
324 // --- Stabilization Coefficient --- (Perhapses this should be a user parameter...) // TODO: Sort out why this is negative (sign error?)
325 static constexpr double m_stabilizationCoefficient = -2.0;
327
328 // --- State Vectors and DOF Management ---
329 mutable mfem::Vector m_state;
330 mfem::Array<int> m_freeDofs;
331
332 // --- Block Offsets ---
333 const mfem::Array<int> m_blockOffsets;
334 mfem::Array<int> m_reducedBlockOffsets;
335
336 // --- Essential Boundary Conditions ---
339
340 // --- Jacobian and Preconditioner Components (owned, mutable) ---
341 std::unique_ptr<mfem::ScaledOperator> m_negQ_mat;
342 mutable std::unique_ptr<mfem::BlockOperator> m_jacobian;
343 mutable std::unique_ptr<SchurCompliment> m_schurCompliment;
344 mutable std::unique_ptr<GMRESInverter> m_invSchurCompliment;
345 mutable std::unique_ptr<mfem::Solver> m_invNonlinearJacobian;
346 mutable std::unique_ptr<mfem::BlockDiagonalPreconditioner> m_schurPreconditioner;
347
348 // --- State Flags ---
349 bool m_isFinalized = false;
350
351private:
357
363
370
376
381 void update_inverse_nonlinear_jacobian(const mfem::Operator &grad) const;
382
388
394 void update_preconditioner(const mfem::Operator &grad) const;
395};
396
397} // namespace serif::polytrope
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.
~GMRESInverter() override=default
Destructor.
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 θ.
quill::Logger * m_logger
Pointer to the specific logger instance.
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).
~PolytropeOperator() override=default
Destructor.
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(θ).
const mfem::Array< int > & get_free_dofs() const
— Getters for information on internal state —
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.
const mfem::Array< int > & get_block_offsets() const
Gets the block offsets for the full (unreduced) system.
bool isFinalized() const
Checks if the operator has been 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).
const mfem::Array< int > & get_reduced_block_offsets() const
Gets the block offsets for the reduced system (after eliminating essential DOFs).
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).
serif::probe::LogManager & m_logManager
Reference to the global log manager.
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.
~SchurCompliment() override=default
Destructor.
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.
std::unique_ptr< mfem::SparseMatrix > m_matrixForm
Optional: if a matrix representation is ever explicitly formed.
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.
Class to manage logging operations.
Definition probe.h:79
static LogManager & getInstance()
Get the singleton instance of LogManager.
Definition probe.h:103
std::pair< mfem::Array< int >, mfem::Array< double > > MFEMArrayPair
Definition 4DSTARTypes.h:27
std::pair< MFEMArrayPair, MFEMArrayPair > MFEMArrayPairSet
Definition 4DSTARTypes.h:28