Files
SERiF/src/poly/utils/public/operator.h

140 lines
5.1 KiB
C
Raw Normal View History

2025-04-21 08:56:45 -04:00
/* ***********************************************************************
//
// Copyright (C) 2025 -- The 4D-STAR Collaboration
// File Author: Emily Boudreaux
// Last Modified: April 21, 2025
//
// 4DSSE is free software; you can use it and/or modify
// it under the terms and restrictions the GNU General Library Public
// License version 3 (GPLv3) as published by the Free Software Foundation.
//
// 4DSSE is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
// See the GNU Library General Public License for more details.
//
// You should have received a copy of the GNU Library General Public License
// along with this software; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// *********************************************************************** */
#pragma once
#include "mfem.hpp"
#include "4DSTARTypes.h"
#include <memory>
#include "probe.h"
class SchurCompliment final : public mfem::Operator {
public:
SchurCompliment(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp, const mfem::Solver &GradInvOp);
SchurCompliment(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp);
~SchurCompliment() override = default;
void Mult(const mfem::Vector &x, mfem::Vector &y) const override;
void SetOperator(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp, const mfem::Solver &GradInvOp);
void updateInverseNonlinearJacobian(const mfem::Solver &gradInv);
private:
void updateConstantTerms(const mfem::MixedBilinearForm &QOp, const mfem::BilinearForm &DOp, const mfem::MixedBilinearForm &MOp);
private:
// Note that these are not owned by this class
const mfem::MixedBilinearForm* m_QOp = nullptr;
const mfem::BilinearForm* m_DOp = nullptr;
const mfem::MixedBilinearForm* m_MOp = nullptr;
const mfem::Solver* m_GradInvOp = nullptr;
int m_nPhi = 0;
int m_nTheta = 0;
mutable std::unique_ptr<mfem::SparseMatrix> m_matrixForm;
};
class GMRESInverter final : public mfem::Operator {
public:
explicit GMRESInverter(const SchurCompliment& op);
~GMRESInverter() override = default;
void Mult(const mfem::Vector &x, mfem::Vector &y) const override;
private:
const SchurCompliment& m_op;
mfem::GMRESSolver m_solver;
};
class PolytropeOperator final : 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,
const double index);
~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; }
2025-04-21 10:18:44 -04:00
void finalize(const mfem::Vector &initTheta);
const mfem::Array<int>& 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<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;
const mfem::Array<int> m_blockOffsets;
SSE::MFEMArrayPair m_theta_ess_tdofs;
SSE::MFEMArrayPair m_phi_ess_tdofs;
// std::unique_ptr<mfem::SparseMatrix> m_Mmat, m_Qmat, 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;
// mutable std::unique_ptr<mfem::SparseMatrix> m_invSchurCompliment;
// mutable std::unique_ptr<mfem::SparseMatrix> m_invNonlinearJacobian;
mutable std::unique_ptr<SchurCompliment> m_schurCompliment;
mutable std::unique_ptr<GMRESInverter> m_invSchurCompliment;
mutable std::unique_ptr<mfem::Solver> 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<mfem::BlockDiagonalPreconditioner> m_schurPreconditioner;
bool m_isFinalized = false;
private:
void updateInverseNonlinearJacobian(const mfem::Operator &grad) const;
void updateInverseSchurCompliment() const;
void updatePreconditioner(const mfem::Operator &grad) const;
};