#ifndef POLY_UTILS_OPERATOR_H #define POLY_UTILS_OPERATOR_H #include "mfem.hpp" #include "4DSTARTypes.h" #include #include "probe.h" class PolytropeOperator : public mfem::Operator { public: PolytropeOperator( std::unique_ptr M, std::unique_ptr Q, std::unique_ptr D, std::unique_ptr f, const mfem::Array &blockOffsets); ~PolytropeOperator() override = default; void Mult(const mfem::Vector &x, mfem::Vector &y) const override; mfem::Operator& GetGradient(const mfem::Vector &x) const override; void SetEssentialTrueDofs(const SSE::MFEMArrayPair& theta_ess_tdofs, const SSE::MFEMArrayPair& phi_ess_tdofs); void SetEssentialTrueDofs(const SSE::MFEMArrayPairSet& ess_tdof_pair_set); SSE::MFEMArrayPairSet GetEssentialTrueDofs() const; bool isFinalized() const { return m_isFinalized; } void finalize(); const mfem::Array& GetBlockOffsets() const { return m_blockOffsets; } const mfem::BlockOperator &GetJacobianOperator() const; mfem::BlockDiagonalPreconditioner &GetPreconditioner() const; private: Probe::LogManager& m_logManager = Probe::LogManager::getInstance(); quill::Logger* m_logger = m_logManager.getLogger("log"); std::unique_ptr m_M; std::unique_ptr m_Q; std::unique_ptr m_D; std::unique_ptr m_f; const mfem::Array m_blockOffsets; SSE::MFEMArrayPair m_theta_ess_tdofs; SSE::MFEMArrayPair m_phi_ess_tdofs; std::unique_ptr m_Mmat; std::unique_ptr m_Qmat; std::unique_ptr m_Dmat; std::unique_ptr m_negM_op; std::unique_ptr m_negQ_op; mutable std::unique_ptr m_jacobian; // TODO I think these need to be calculated in the GetGradient every time since they will always change mutable std::unique_ptr m_invSchurCompliment; mutable std::unique_ptr m_invNonlinearJacobian; /* * The schur preconditioner has the form * * ⎡ḟ(θ)^-1 0 ⎤ * ⎣ 0 S^-1 ⎦ * * Where S is the Schur compliment of the system * */ mutable std::unique_ptr m_schurPreconditioner; bool m_isFinalized = false; private: void updateInverseNonlinearJacobian(const mfem::Operator &grad) const; void updateInverseSchurCompliment() const; }; #endif // POLY_UTILS_OPERATOR_H