2025-04-02 14:57:37 -04:00
|
|
|
#ifndef POLY_UTILS_OPERATOR_H
|
|
|
|
|
#define POLY_UTILS_OPERATOR_H
|
|
|
|
|
|
|
|
|
|
#include "mfem.hpp"
|
2025-04-09 15:17:55 -04:00
|
|
|
#include "4DSTARTypes.h"
|
2025-04-02 14:57:37 -04:00
|
|
|
#include <memory>
|
|
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
#include "probe.h"
|
|
|
|
|
|
2025-04-02 14:57:37 -04:00
|
|
|
class PolytropeOperator : public mfem::Operator {
|
|
|
|
|
public:
|
|
|
|
|
PolytropeOperator(
|
|
|
|
|
std::unique_ptr<mfem::MixedBilinearForm> M,
|
|
|
|
|
std::unique_ptr<mfem::MixedBilinearForm> Q,
|
|
|
|
|
std::unique_ptr<mfem::BilinearForm> D,
|
|
|
|
|
std::unique_ptr<mfem::NonlinearForm> f,
|
|
|
|
|
const mfem::Array<int> &blockOffsets);
|
|
|
|
|
~PolytropeOperator() override = default;
|
|
|
|
|
|
|
|
|
|
void Mult(const mfem::Vector &x, mfem::Vector &y) const override;
|
2025-04-09 15:17:55 -04:00
|
|
|
|
|
|
|
|
|
2025-04-02 14:57:37 -04:00
|
|
|
mfem::Operator& GetGradient(const mfem::Vector &x) const override;
|
|
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
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;
|
2025-04-02 14:57:37 -04:00
|
|
|
|
2025-04-03 11:14:50 -04:00
|
|
|
bool isFinalized() const { return m_isFinalized; }
|
|
|
|
|
|
|
|
|
|
void finalize();
|
|
|
|
|
|
|
|
|
|
const mfem::Array<int>& GetBlockOffsets() const { return m_blockOffsets; }
|
|
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
const mfem::BlockOperator &GetJacobianOperator() const;
|
|
|
|
|
|
2025-04-21 08:35:29 -04:00
|
|
|
mfem::BlockDiagonalPreconditioner &GetPreconditioner() const;
|
|
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
|
2025-04-02 14:57:37 -04:00
|
|
|
private:
|
2025-04-09 15:17:55 -04:00
|
|
|
Probe::LogManager& m_logManager = Probe::LogManager::getInstance();
|
|
|
|
|
quill::Logger* m_logger = m_logManager.getLogger("log");
|
2025-04-02 14:57:37 -04:00
|
|
|
std::unique_ptr<mfem::MixedBilinearForm> m_M;
|
|
|
|
|
std::unique_ptr<mfem::MixedBilinearForm> m_Q;
|
|
|
|
|
std::unique_ptr<mfem::BilinearForm> m_D;
|
|
|
|
|
std::unique_ptr<mfem::NonlinearForm> m_f;
|
|
|
|
|
|
2025-04-03 11:14:50 -04:00
|
|
|
const mfem::Array<int> m_blockOffsets;
|
2025-04-02 14:57:37 -04:00
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
SSE::MFEMArrayPair m_theta_ess_tdofs;
|
|
|
|
|
SSE::MFEMArrayPair m_phi_ess_tdofs;
|
2025-04-02 14:57:37 -04:00
|
|
|
|
|
|
|
|
std::unique_ptr<mfem::SparseMatrix> m_Mmat;
|
|
|
|
|
std::unique_ptr<mfem::SparseMatrix> m_Qmat;
|
|
|
|
|
std::unique_ptr<mfem::SparseMatrix> m_Dmat;
|
|
|
|
|
|
|
|
|
|
std::unique_ptr<mfem::ScaledOperator> m_negM_op;
|
|
|
|
|
std::unique_ptr<mfem::ScaledOperator> m_negQ_op;
|
|
|
|
|
mutable std::unique_ptr<mfem::BlockOperator> m_jacobian;
|
2025-04-03 11:14:50 -04:00
|
|
|
|
2025-04-09 15:17:55 -04:00
|
|
|
// TODO I think these need to be calculated in the GetGradient every time since they will always change
|
|
|
|
|
mutable std::unique_ptr<mfem::SparseMatrix> m_invSchurCompliment;
|
|
|
|
|
mutable std::unique_ptr<mfem::SparseMatrix> m_invNonlinearJacobian;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* The schur preconditioner has the form
|
|
|
|
|
*
|
2025-04-21 08:04:49 -04:00
|
|
|
* ⎡ḟ(θ)^-1 0 ⎤
|
|
|
|
|
* ⎣ 0 S^-1 ⎦
|
2025-04-09 15:17:55 -04:00
|
|
|
*
|
|
|
|
|
* Where S is the Schur compliment of the system
|
|
|
|
|
*
|
|
|
|
|
*/
|
|
|
|
|
|
2025-04-21 08:04:49 -04:00
|
|
|
mutable std::unique_ptr<mfem::BlockDiagonalPreconditioner> m_schurPreconditioner;
|
2025-04-09 15:17:55 -04:00
|
|
|
|
2025-04-03 11:14:50 -04:00
|
|
|
bool m_isFinalized = false;
|
2025-04-09 15:17:55 -04:00
|
|
|
|
|
|
|
|
private:
|
|
|
|
|
void updateInverseNonlinearJacobian(const mfem::Operator &grad) const;
|
|
|
|
|
void updateInverseSchurCompliment() const;
|
2025-04-02 14:57:37 -04:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif // POLY_UTILS_OPERATOR_H
|