/*
* Copyright © 2004-2011 Ondra Kamenik
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
* Dynare is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Dynare 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Dynare. If not, see .
*/
#ifndef TRIANGULAR_SYLVESTER_H
#define TRIANGULAR_SYLVESTER_H
#include "SylvesterSolver.hh"
#include "KronVector.hh"
#include "QuasiTriangular.hh"
#include "QuasiTriangularZero.hh"
#include "SimilarityDecomp.hh"
#include
class TriangularSylvester : public SylvesterSolver
{
const std::unique_ptr matrixKK;
const std::unique_ptr matrixFF;
public:
TriangularSylvester(const QuasiTriangular &k, const QuasiTriangular &f);
TriangularSylvester(const SchurDecompZero &kdecomp, const SchurDecomp &fdecomp);
TriangularSylvester(const SchurDecompZero &kdecomp, const SimilarityDecomp &fdecomp);
~TriangularSylvester() override = default;
void print() const;
void solve(SylvParams &pars, KronVector &d) const override;
void solvi(double r, KronVector &d, double &eig_min) const;
void solvii(double alpha, double beta1, double beta2,
KronVector &d1, KronVector &d2,
double &eig_min) const;
void solviip(double alpha, double betas,
KronVector &d, double &eig_min) const;
/* Computes:
⎛x₁⎞ ⎛d₁⎞ ⎛ α −β₁⎞ ⎛d₁⎞
⎢ ⎥=⎢ ⎥+⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥
⎝x₂⎠ ⎝d₂⎠ ⎝−β₂ α ⎠ ⎝d₂⎠
*/
void linEval(double alpha, double beta1, double beta2,
KronVector &x1, KronVector &x2,
const ConstKronVector &d1, const ConstKronVector &d2) const;
void
linEval(double alpha, double beta1, double beta2,
KronVector &x1, KronVector &x2,
const KronVector &d1, const KronVector &d2) const
{
linEval(alpha, beta1, beta2, x1, x2,
ConstKronVector(d1), ConstKronVector(d2));
}
/* Computes:
⎛x₁⎞ ⎛d₁⎞ ⎛γ −δ₁⎞ ⎛d₁⎞ ⎛γ −δ₁⎞² ⎛d₁⎞
⎢ ⎥=⎢ ⎥+2α⎢ ⎥⊗Fᵀ⊗Fᵀ⊗…⊗K·⎢ ⎥+(α²+β)⎢ ⎥ ⊗Fᵀ²⊗Fᵀ²⊗…⊗K²·⎢ ⎥
⎝x₂⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠ ⎝δ₂ γ ⎠ ⎝d₂⎠
*/
void quaEval(double alpha, double betas,
double gamma, double delta1, double delta2,
KronVector &x1, KronVector &x2,
const ConstKronVector &d1, const ConstKronVector &d2) const;
void
quaEval(double alpha, double betas,
double gamma, double delta1, double delta2,
KronVector &x1, KronVector &x2,
const KronVector &d1, const KronVector &d2) const
{
quaEval(alpha, betas, gamma, delta1, delta2, x1, x2,
ConstKronVector(d1), ConstKronVector(d2));
}
private:
/* Returns square of size of minimal eigenvalue of the system solved,
now obsolete */
double getEigSep(int depth) const;
// Recursively calculates kronecker product of complex vectors (used in getEigSep)
static void multEigVector(KronVector &eig, const Vector &feig, const Vector &keig);
using const_diag_iter = QuasiTriangular::const_diag_iter;
using const_row_iter = QuasiTriangular::const_row_iter;
// Called from solvi
void solviRealAndEliminate(double r, const_diag_iter di,
KronVector &d, double &eig_min) const;
void solviComplexAndEliminate(double r, const_diag_iter di,
KronVector &d, double &eig_min) const;
// Called from solviip
void solviipRealAndEliminate(double alpha, double betas,
const_diag_iter di, const_diag_iter dsi,
KronVector &d, double &eig_min) const;
void solviipComplexAndEliminate(double alpha, double betas,
const_diag_iter di, const_diag_iter dsi,
KronVector &d, double &eig_min) const;
// Eliminations
void solviEliminateReal(const_diag_iter di, KronVector &d,
const KronVector &y, double divisor) const;
void solviEliminateComplex(const_diag_iter di, KronVector &d,
const KronVector &y1, const KronVector &y2,
double divisor) const;
void solviipEliminateReal(const_diag_iter di, const_diag_iter dsi,
KronVector &d,
const KronVector &y1, const KronVector &y2,
double divisor, double divisor2) const;
void solviipEliminateComplex(const_diag_iter di, const_diag_iter dsi,
KronVector &d,
const KronVector &y1, const KronVector &y11,
const KronVector &y2, const KronVector &y22,
double divisor) const;
// Lemma 2
void solviipComplex(double alpha, double betas, double gamma,
double delta1, double delta2,
KronVector &d1, KronVector &d2,
double &eig_min) const;
// Norms for what we consider zero on diagonal of F
static constexpr double diag_zero = 1.e-15;
static constexpr double diag_zero_sq = diag_zero*diag_zero;
};
#endif /* TRIANGULAR_SYLVESTER_H */