2 #ifndef _BLOCK_DIAG_MATRIX_H_ 3 #define _BLOCK_DIAG_MATRIX_H_ 5 #include <unordered_map> 15 template<
class el_type>
16 std::ostream& operator<< (std::ostream& os, const std::vector<el_type>& vec)
21 for (
typename std::vector<el_type>::size_type index = 0; index < vec.size() - 1; index ++)
23 os << vec[index] <<
", ";
26 os << vec[vec.size()-1];
38 template<
class el_type>
43 typedef std::unordered_map<int, el_type> int_elt_map;
44 typedef std::vector<el_type> elt_vector_type;
70 void resize(
int n, el_type default_value) {
73 main_diag.resize(n, default_value);
108 return main_diag.at(i);
115 if (!off_diag.count(i)) {
116 off_diag.insert(std::make_pair(i, 0));
129 if (off_diag.count(i)) {
131 }
else if (off_diag.count(i-1)) {
143 void sqrt_solve(
const elt_vector_type& b, elt_vector_type& x,
bool transposed =
false) {
144 assert(b.size() == x.size());
146 const double eps = 1e-8;
147 double alpha, beta, gamma, eig0, eig1, disc;
148 double Q[2][2], tx[2];
151 alpha = main_diag[i];
152 beta = main_diag[i+1];
155 disc = sqrt((alpha-beta)*(alpha-beta) + 4*gamma*gamma);
156 eig0 = 0.5*(alpha+beta+disc);
157 eig1 = 0.5*(alpha+beta-disc);
159 if (abs(gamma/std::min(alpha, beta)) < eps) {
160 eig0 = alpha; eig1 = beta;
161 Q[0][0] = 1; Q[1][0] = 0;
162 Q[0][1] = 0; Q[1][1] = 1;
164 double sin2t = 2*gamma/disc, cos2t = (alpha-beta)/disc;
165 double theta = 0.5*atan2(sin2t, cos2t);
167 Q[0][0] = cos(theta); Q[0][1] = -sin(theta);
168 Q[1][0] = sin(theta); Q[1][1] = cos(theta);
174 tx[0] = Q[0][0] * b[i] + Q[1][0] * b[i+1];
175 tx[1] = Q[0][1] * b[i] + Q[1][1] * b[i+1];
178 x[i] = tx[0]/sqrt(abs(eig0));
179 x[i+1] = tx[1]/sqrt(abs(eig1));
182 tx[0] = b[i]/sqrt(abs(eig0));
183 tx[1] = b[i+1]/sqrt(abs(eig1));
186 x[i] = Q[0][0] * tx[0] + Q[0][1] * tx[1];
187 x[i+1] = Q[1][0] * tx[0] + Q[1][1] * tx[1];
190 x[i] = b[i]/sqrt(abs(main_diag[i]));
199 void solve(
const elt_vector_type& b, elt_vector_type& x) {
200 assert(b.size() == x.size());
211 x[i] = (d*b[i] - c*b[i+1])/det;
212 x[i+1] = (-c*b[i] + a*b[i+1])/det;
214 x[i] = b[i]/main_diag[i];
226 bool save(std::string filename)
const;
235 #include "block_diag_matrix_to_string.h" 236 #include "block_diag_matrix_save.h" el_type & operator[](int i)
Definition: block_diag_matrix.h:107
el_type & off_diagonal(int i)
Definition: block_diag_matrix.h:114
int_elt_map off_diag
Stores off-diagonal elements of 2x2 pivots.
Definition: block_diag_matrix.h:56
int n_rows() const
Definition: block_diag_matrix.h:87
elt_vector_type main_diag
Stores main diagonal elements.
Definition: block_diag_matrix.h:55
int nnz_count
Number of non-zeros in the matrix.
Definition: block_diag_matrix.h:54
void solve(const elt_vector_type &b, elt_vector_type &x)
Solves the system Dx = b.
Definition: block_diag_matrix.h:199
void sqrt_solve(const elt_vector_type &b, elt_vector_type &x, bool transposed=false)
Solves the preconditioned problem |D| = Q|V|Q', where QVQ' is the eigendecomposition of D...
Definition: block_diag_matrix.h:143
block_diag_matrix(int n_rows=0, int n_cols=0)
Constructor for diagonal class. Initializes a 0x0 matrix when given no arguments. ...
Definition: block_diag_matrix.h:60
bool save(std::string filename) const
Definition: block_diag_matrix_save.h:6
void resize(int n, el_type default_value)
Resizes this matrix to an n*n matrix with default_value on the main diagonal.
Definition: block_diag_matrix.h:70
friend std::ostream & operator<<(std::ostream &os, const block_diag_matrix &D)
Definition: block_diag_matrix.h:47
~block_diag_matrix()
Generic class destructor.
Definition: block_diag_matrix.h:230
A quick implementation of a diagonal matrix with 1x1 and 2x2 blocks.
Definition: block_diag_matrix.h:39
int nnz() const
Definition: block_diag_matrix.h:99
std::string to_string() const
Definition: block_diag_matrix_to_string.h:9
void resize(int n)
Resizes this matrix to an n*n matrix.
Definition: block_diag_matrix.h:80
int n_cols() const
Definition: block_diag_matrix.h:93
int m_n_size
Dimension of the matrix.
Definition: block_diag_matrix.h:51
int block_size(int i) const
Definition: block_diag_matrix.h:128