Multiscale Universal Interface  2.0
A Concurrent Framework for Coupling Heterogeneous Solvers
solver_bicgstab.h
Go to the documentation of this file.
1 /*****************************************************************************
2 * Multiscale Universal Interface Code Coupling Library *
3 * *
4 * Copyright (C) 2023 W. Liu *
5 * *
6 * This software is jointly licensed under the Apache License, Version 2.0 *
7 * and the GNU General Public License version 3, you may use it according *
8 * to either. *
9 * *
10 * ** Apache License, version 2.0 ** *
11 * *
12 * Licensed under the Apache License, Version 2.0 (the "License"); *
13 * you may not use this file except in compliance with the License. *
14 * You may obtain a copy of the License at *
15 * *
16 * http://www.apache.org/licenses/LICENSE-2.0 *
17 * *
18 * Unless required by applicable law or agreed to in writing, software *
19 * distributed under the License is distributed on an "AS IS" BASIS, *
20 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. *
21 * See the License for the specific language governing permissions and *
22 * limitations under the License. *
23 * *
24 * ** GNU General Public License, version 3 ** *
25 * *
26 * This program is free software: you can redistribute it and/or modify *
27 * it under the terms of the GNU General Public License as published by *
28 * the Free Software Foundation, either version 3 of the License, or *
29 * (at your option) any later version. *
30 * *
31 * This program is distributed in the hope that it will be useful, *
32 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
33 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
34 * GNU General Public License for more details. *
35 * *
36 * You should have received a copy of the GNU General Public License *
37 * along with this program. If not, see <http://www.gnu.org/licenses/>. *
38 *****************************************************************************/
39 
48 #ifndef MUI_BICONJUGATE_GRADIENT_STABILIZED_H_
49 #define MUI_BICONJUGATE_GRADIENT_STABILIZED_H_
50 
51 #include <cmath>
52 
53 namespace mui {
54 namespace linalg {
55 
56 // Constructor for one-dimensional Biconjugate Gradient Stabilized solver
57 template<typename ITYPE, typename VTYPE>
59  : A_(A),
60  b_(b),
61  bicgstab_solve_tol_(bicgstab_solve_tol),
62  bicgstab_max_iter_(bicgstab_max_iter),
63  M_(M){
64  assert(b_.get_cols() == 1 &&
65  "MUI Error [solver_bicgstab.h]: Number of column of b matrix must be 1");
66  x_.resize(A_.get_rows(),1);
67  r_.resize(A_.get_rows(),1);
68  rTilde_.resize(A_.get_rows(),1);
69  v_.resize(A_.get_rows(),1);
70  t_.resize(A_.get_rows(),1);
71  p_.resize(A_.get_rows(),1);
72  s_.resize(A_.get_rows(),1);
73  h_.resize(A_.get_rows(),1);
74  y_.resize(A_.get_rows(),1);
75  z_.resize(A_.get_rows(),1);
76  alpha_ = 1.0;
77  beta_ = 0.0;
78  omega_ = 1.0;
79  rho_ = 1.0;
80  rhoTilde_ = 1.0;
81 }
82 
83 // Constructor for multidimensional Conjugate Gradient solver
84 template<typename ITYPE, typename VTYPE>
86  : A_(A),
87  b_(b),
88  bicgstab_solve_tol_(bicgstab_solve_tol),
89  bicgstab_max_iter_(bicgstab_max_iter),
90  M_(M){
91  assert(A_.get_rows() == b_.get_rows() &&
92  "MUI Error [solver_bicgstab.h]: Number of rows of A matrix must be the same as the number of rows of b matrix");
93  b_column_.resize(b_.get_rows(),1);
94  x_.resize(b_.get_rows(),b_.get_cols());
95  x_init_column_.resize(b_.get_rows(),1);
96 }
97 
98 // Destructor for one-dimensional Conjugate Gradient solver
99 template<typename ITYPE, typename VTYPE>
101  // Deallocate the memory for matrices
102  A_.set_zero();
103  x_.set_zero();
104  b_.set_zero();
105  r_.set_zero();
106  rTilde_.set_zero();
107  v_.set_zero();
108  t_.set_zero();
109  p_.set_zero();
110  s_.set_zero();
111  h_.set_zero();
112  y_.set_zero();
113  z_.set_zero();
114  // Set properties to null
115  alpha_ = 0.0;
116  beta_ = 0.0;
117  omega_ = 0.0;
118  rho_ = 0.0;
119  rhoTilde_ = 0.0;
120  bicgstab_solve_tol_ = 0;
121  bicgstab_max_iter_ = 0;
122  // Deallocate the memory for preconditioner pointer
123  if(M_!=nullptr) {
124  M_ = nullptr;
125  delete[] M_;
126  }
127 }
128 
129 // Destructor for multidimensional Conjugate Gradient solver
130 template<typename ITYPE, typename VTYPE>
132  // Deallocate the memory for matrices
133  A_.set_zero();
134  x_.set_zero();
135  b_.set_zero();
136  b_column_.set_zero();
137  x_init_column_.set_zero();
138  // Set properties to null
139  bicgstab_solve_tol_ = 0;
140  bicgstab_max_iter_ = 0;
141  // Deallocate the memory for preconditioner pointer
142  if(M_!=nullptr) {
143  M_ = nullptr;
144  delete[] M_;
145  }
146 }
147 
148 // Member function for one-dimensional Conjugate Gradient solver to solve
149 template<typename ITYPE, typename VTYPE>
151  if (!x_init.empty()){
152  assert(((x_init.get_rows() == x_.get_rows()) && (x_init.get_cols() == x_.get_cols())) &&
153  "MUI Error [solver_bicgstab.h]: Size of x_init matrix mismatch with size of x_ matrix");
154  // Initialize x_ with x_init
155  x_.copy(x_init);
156  // Initialise r_ with b-Ax0
157  sparse_matrix<ITYPE,VTYPE> Ax0 = A_* x_init;
158  r_.copy(b_-Ax0);
159  } else {
160  // Initialise r_ with b
161  r_.copy(b_);
162  }
163 
164  // Initialise rTilde_ with r_
165  rTilde_.copy(r_);
166  // Initialise p_ with r_
167  p_.copy(r_);
168 
169  bool debug_switch = true;
170 
171  if (M_) {
172  std::cout << "MUI Warning [solver_bicgstab.h]: Preconditioner is not yet supported by BiCGStab yet. "
173  << "The preconditioner is ignored."<< std::endl;
174  debug_switch = false;
175  }
176 
177  if (M_ && debug_switch) {
178  sparse_matrix<ITYPE,VTYPE> tempR(r_.get_rows(), r_.get_cols());
179  tempR = M_->apply(r_);
180  r_.set_zero();
181  r_.copy(tempR);
182  rTilde_.set_zero();
183  rTilde_.copy(r_);
184  }
185 
186  VTYPE r_norm0 = r_.dot_product(r_);
187  assert(std::abs(r_norm0) >= std::numeric_limits<VTYPE>::min() &&
188  "MUI Error [solver_bicgstab.h]: Divide by zero assert for r_norm0");
189  VTYPE r_norm = r_norm0;
190  VTYPE r_norm_rel = std::sqrt(r_norm/r_norm0);
191 
192  ITYPE kIter;
193  if(bicgstab_max_iter_ == 0) {
195  } else {
196  kIter = bicgstab_max_iter_;
197  }
198 
199  ITYPE acturalKIterCount = 0;
200 
201  for (ITYPE k = 0; k < kIter; ++k) {
202  ++acturalKIterCount;
203 
204  rho_ = rTilde_.dot_product(r_);
205  assert(std::abs(rhoTilde_) >= std::numeric_limits<VTYPE>::min() &&
206  "MUI Error [solver_bicgstab.h]: Divide by zero assert for rhoTilde_");
207  assert(std::abs(omega_) >= std::numeric_limits<VTYPE>::min() &&
208  "MUI Error [solver_bicgstab.h]: Divide by zero assert for omega_");
209  if (k>0) {
210  beta_ = (rho_ / rhoTilde_) * (alpha_ / omega_);
211  sparse_matrix<ITYPE,VTYPE> omega_dot_v = omega_ * v_;
212  sparse_matrix<ITYPE,VTYPE> beta_p_omega_dot_v = beta_ * (p_ - omega_dot_v);
213  p_.set_zero();
214  p_.copy(r_ + beta_p_omega_dot_v);
215  } else {
216  p_.set_zero();
217  p_.copy(r_);
218  }
219 
220  y_.set_zero();
221  y_.copy(p_);
222  if (M_ && debug_switch) {
223  sparse_matrix<ITYPE,VTYPE> tempY(y_.get_rows(), y_.get_cols());
224  tempY = M_->apply(y_);
225  y_.set_zero();
226  y_.copy(tempY);
227  }
228 
229  v_.set_zero();
230  v_.copy(A_*y_);
231  VTYPE rTilde_dot_v = rTilde_.dot_product(v_);
232  assert(std::abs(rTilde_dot_v) >= std::numeric_limits<VTYPE>::min() &&
233  "MUI Error [solver_bicgstab.h]: Divide by zero assert for rTilde_dot_v");
234  alpha_ = rho_ / rTilde_dot_v;
235  sparse_matrix<ITYPE,VTYPE> alpha_dot_p = alpha_ * p_;
236  h_.set_zero();
237  h_.copy(x_ + alpha_dot_p);
238  sparse_matrix<ITYPE,VTYPE> alpha_dot_v = alpha_ * v_;
239  s_.set_zero();
240  s_.copy(r_ - alpha_dot_v);
241 
242  z_.set_zero();
243  z_.copy(s_);
244  if (M_ && debug_switch) {
245  sparse_matrix<ITYPE,VTYPE> tempZ(z_.get_rows(), z_.get_cols());
246  tempZ = M_->apply(z_);
247  z_.set_zero();
248  z_.copy(tempZ);
249  }
250 
251  t_.set_zero();
252  t_.copy(A_ * z_);
253  VTYPE t_dot_t = t_.dot_product(t_);
254  assert(std::abs(t_dot_t) >= std::numeric_limits<VTYPE>::min() &&
255  "MUI Error [solver_bicgstab.h]: Divide by zero assert for t_dot_t");
256  omega_ = t_.dot_product(s_) / t_dot_t;
257  sparse_matrix<ITYPE,VTYPE> omega_dot_s = omega_ * s_;
258  x_.set_zero();
259  x_.copy(h_ + omega_dot_s);
260  sparse_matrix<ITYPE,VTYPE> omega_dot_t = omega_ * t_;
261  r_.set_zero();
262  r_.copy(s_ - omega_dot_t);
263 
264  if (M_ && debug_switch) {
265  sparse_matrix<ITYPE,VTYPE> tempR(r_.get_rows(), r_.get_cols());
266  tempR = M_->apply(r_);
267  r_.set_zero();
268  r_.copy(tempR);
269  rTilde_.set_zero();
270  rTilde_.copy(r_);
271  }
272 
273  r_norm = r_.dot_product(r_);
274  r_norm_rel = std::sqrt(r_norm/r_norm0);
275  if (r_norm_rel <= bicgstab_solve_tol_) {
276  break;
277  }
278 
279  rhoTilde_ = rho_;
280  }
281  return std::make_pair(acturalKIterCount,r_norm_rel);
282 }
283 
284 // Member function for multidimensional Conjugate Gradient solver to solve
285 template<typename ITYPE, typename VTYPE>
287  if (!x_init.empty()){
288  assert(((x_init.get_rows() == b_.get_rows()) && (x_init.get_cols() == b_.get_cols())) &&
289  "MUI Error [solver_bicgstab.h]: Size of x_init matrix mismatch with size of b_ matrix");
290  }
291 
292  std::pair<ITYPE, VTYPE> bicgstabReturn;
293  for (ITYPE j = 0; j < b_.get_cols(); ++j) {
294  b_column_.set_zero();
295  b_column_ = b_.segment(0,(b_.get_rows()-1),j,j);
296  biconjugate_gradient_stabilized_1d<ITYPE, VTYPE> bicgstab(A_, b_column_, bicgstab_solve_tol_, bicgstab_max_iter_, M_);
297  if (!x_init.empty()) {
298  x_init_column_.set_zero();
299  x_init_column_ = x_init.segment(0,(x_init.get_rows()-1),j,j);
300  }
301  std::pair<ITYPE, VTYPE> bicgstabReturnTemp = bicgstab.solve(x_init_column_);
302  if (bicgstabReturn.first < bicgstabReturnTemp.first)
303  bicgstabReturn.first = bicgstabReturnTemp.first;
304  bicgstabReturn.second += bicgstabReturnTemp.second;
305  sparse_matrix<ITYPE,VTYPE> x_column(b_.get_rows(),1);
306  x_column = bicgstab.getSolution();
307  for (ITYPE i = 0; i < x_column.get_rows(); ++i) {
308  x_.set_value(i, j, x_column.get_value(i,0));
309  }
310  }
311  bicgstabReturn.second /= b_.get_cols();
312 
313  return bicgstabReturn;
314 }
315 
316 // Member function for one-dimensional Conjugate Gradient solver to get the solution
317 template<typename ITYPE, typename VTYPE>
319  return x_;
320 }
321 
322 // Member function for multidimensional Conjugate Gradient solver to get the solution
323 template<typename ITYPE, typename VTYPE>
325  return x_;
326 }
327 
328 } // linalg
329 } // mui
330 
331 #endif /* MUI_BICONJUGATE_GRADIENT_STABILIZED_H_ */
sparse_matrix< ITYPE, VTYPE > getSolution()
Definition: solver_bicgstab.h:318
biconjugate_gradient_stabilized_1d(sparse_matrix< ITYPE, VTYPE >, sparse_matrix< ITYPE, VTYPE >, VTYPE=1e-6, ITYPE=0, preconditioner< ITYPE, VTYPE > *=nullptr)
Definition: solver_bicgstab.h:58
std::pair< ITYPE, VTYPE > solve(sparse_matrix< ITYPE, VTYPE >=sparse_matrix< ITYPE, VTYPE >())
Definition: solver_bicgstab.h:150
~biconjugate_gradient_stabilized_1d()
Definition: solver_bicgstab.h:100
~biconjugate_gradient_stabilized()
Definition: solver_bicgstab.h:131
biconjugate_gradient_stabilized(sparse_matrix< ITYPE, VTYPE >, sparse_matrix< ITYPE, VTYPE >, VTYPE=1e-6, ITYPE=0, preconditioner< ITYPE, VTYPE > *=nullptr)
Definition: solver_bicgstab.h:85
sparse_matrix< ITYPE, VTYPE > getSolution()
Definition: solver_bicgstab.h:324
std::pair< ITYPE, VTYPE > solve(sparse_matrix< ITYPE, VTYPE >=sparse_matrix< ITYPE, VTYPE >())
Definition: solver_bicgstab.h:286
Definition: preconditioner.h:55
Definition: matrix.h:61
ITYPE get_rows() const
Definition: matrix_io_info.h:579
void set_zero()
Definition: matrix_manipulation.h:418
VTYPE get_value(ITYPE, ITYPE) const
Definition: matrix_io_info.h:523
sparse_matrix< ITYPE, VTYPE > segment(ITYPE, ITYPE, ITYPE, ITYPE, bool=true)
Definition: matrix_manipulation.h:153
ITYPE get_cols() const
Definition: matrix_io_info.h:585
void copy(const sparse_matrix< ITYPE, VTYPE > &)
Definition: matrix_manipulation.h:79
bool empty() const
Definition: matrix_io_info.h:665
u u u u u u min
Definition: dim.h:289
Definition: comm.h:54
SCALAR max(vexpr< E, SCALAR, D > const &u)
Definition: point.h:350