11 #ifndef OOPS_ASSIMILATION_TRIDIAGSOLVE_H_
12 #define OOPS_ASSIMILATION_TRIDIAGSOLVE_H_
14 #include <Eigen/Dense>
15 #include <Eigen/Eigenvalues>
20 #include "oops/util/dot_product.h"
21 #include "oops/util/Logger.h"
25 void TriDiagSolve(
const std::vector<double> & diag,
const std::vector<double> & sub,
26 const std::vector<double> & rhs, std::vector<double> & sol) {
27 const double n = rhs.size();
28 ASSERT(sub.size() == n-1);
29 ASSERT(diag.size() == n);
31 std::vector<double> c(sub);
32 std::vector<double> d(rhs);
35 c[0] = c[0] / diag[0];
36 d[0] = d[0] / diag[0];
38 for (
int ii = 1; ii <= n-2; ++ii) {
39 double denom = diag[ii]-sub[ii-1]*c[ii-1];
41 d[ii] = (d[ii]-sub[ii-1]*d[ii-1])/denom;
44 d[n-1] = (d[n-1]-sub[n-2]*d[n-2])/(diag[n-1]-sub[n-2]*c[n-2]);
47 for (
int ii = n-2; ii >= 0; --ii) {
48 sol[ii] = (d[ii]-(c[ii]*sol[ii+1]));
55 const std::vector<Eigen::MatrixXd> & betas,
56 const Eigen::MatrixXd & beta0, Eigen::MatrixXd & ss,
59 const int iter = alphas.size();
60 complexValues =
false;
61 Eigen::MatrixXd TT = Eigen::MatrixXd::Zero(iter * members, iter * members);
63 for (
int ii = 0; ii < iter; ++ii) {
64 TT.block(ii*members, ii*members, members, members) = alphas[ii];
65 if (ii > 0) TT.block((ii-1)*members, ii*members, members, members) = (betas[ii-1]).transpose();
66 if (ii < iter - 1) TT.block((ii+1)*members, ii*members, members, members) = (betas[ii]);
69 Eigen::MatrixXd e1b0 = Eigen::MatrixXd::Zero(iter * members, members);
70 e1b0.block(0, 0, members, members) = beta0;
72 ss = TT.llt().solve(e1b0);
74 Eigen::VectorXcd eivals = TT.eigenvalues();
75 Eigen::MatrixXd eivalsImag = eivals.imag();
76 complexValues = (eivalsImag.array() != 0.0).any();
78 throw eckit::BadValue(
"T matrix has complex values.");
The namespace for the main oops code.
void TriDiagSolve(const std::vector< double > &diag, const std::vector< double > &sub, const std::vector< double > &rhs, std::vector< double > &sol)
void blockTriDiagSolve(const std::vector< Eigen::MatrixXd > &alphas, const std::vector< Eigen::MatrixXd > &betas, const Eigen::MatrixXd &beta0, Eigen::MatrixXd &ss, bool &complexValues, const int members)