iterative_linear_solver.h
Go to the documentation of this file.
1 // LIC// ====================================================================
2 // LIC// This file forms part of oomph-lib, the object-oriented,
3 // LIC// multi-physics finite-element library, available
4 // LIC// at http://www.oomph-lib.org.
5 // LIC//
6 // LIC// Copyright (C) 2006-2022 Matthias Heil and Andrew Hazel
7 // LIC//
8 // LIC// This library is free software; you can redistribute it and/or
9 // LIC// modify it under the terms of the GNU Lesser General Public
10 // LIC// License as published by the Free Software Foundation; either
11 // LIC// version 2.1 of the License, or (at your option) any later version.
12 // LIC//
13 // LIC// This library is distributed in the hope that it will be useful,
14 // LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // LIC// Lesser General Public License for more details.
17 // LIC//
18 // LIC// You should have received a copy of the GNU Lesser General Public
19 // LIC// License along with this library; if not, write to the Free Software
20 // LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
21 // LIC// 02110-1301 USA.
22 // LIC//
23 // LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
24 // LIC//
25 // LIC//====================================================================
26 // This header defines a class for linear iterative solvers
27 
28 // Include guards
29 #ifndef OOMPH_ITERATIVE_LINEAR_SOLVER_HEADER
30 #define OOMPH_ITERATIVE_LINEAR_SOLVER_HEADER
31 
32 
33 // Config header generated by autoconfig
34 #ifdef HAVE_CONFIG_H
35 #include <oomph-lib-config.h>
36 #endif
37 
38 
39 // oomph-lib headers
40 #include "matrices.h"
41 #include "problem.h"
42 #include "linear_solver.h"
43 #include "preconditioner.h"
44 
45 
46 namespace oomph
47 {
48  //===========================================================================
52  //===========================================================================
54  {
55  public:
59  {
60  // Set pointer to default preconditioner
62 
63  // Set default convergence tolerance
64  Tolerance = 1.0e-8;
65 
66  // Set maximum number of iterations
67  Max_iter = 100;
68 
69  // set default for document convergence history
71 
72  // set default
74 
76 
77  // By default the iterative solver is not used as preconditioner
79 
80  // Indicates whether this is the first time we call the solve
81  // method
83  }
84 
87 
89  void operator=(const IterativeLinearSolver&) = delete;
90 
93 
96  {
97  return Preconditioner_pt;
98  }
99 
102  {
103  return Preconditioner_pt;
104  }
105 
107  double& tolerance()
108  {
109  return Tolerance;
110  }
111 
113  unsigned& max_iter()
114  {
115  return Max_iter;
116  }
117 
119  virtual unsigned iterations() const = 0;
120 
123  {
125  }
126 
129  {
130  Doc_convergence_history = false;
131  }
132 
139  const std::string& file_name, const std::string& zone_title = "")
140  {
141  // start docing
143 
144  // Close if it's open
145  if (Output_file_stream.is_open())
146  {
147  Output_file_stream.close();
148  }
149 
150  // Open new one
151  Output_file_stream.open(file_name.c_str());
152 
153  // Write tecplot zone header
154  Output_file_stream << "VARIABLES=\"iterations\", \"scaled residual\""
155  << std::endl;
156  Output_file_stream << "ZONE T=\"" << zone_title << "\"" << std::endl;
157  Output_file_stream << 0 << " " << 1.0 << std::endl;
158  }
159 
162  {
163  if (Output_file_stream.is_open()) Output_file_stream.close();
164  }
165 
168  double jacobian_setup_time() const
169  {
170  return Jacobian_setup_time;
171  }
172 
175  {
176  return Solution_time;
177  }
178 
180  virtual double preconditioner_setup_time() const
181  {
183  }
184 
187  {
189  }
190 
193  {
195  }
196 
199  {
201  }
202 
205  {
207  }
208 
213  {
215  }
216 
221  {
223  }
224 
225  protected:
229 
231  std::ofstream Output_file_stream;
232 
237 
239  double Tolerance;
240 
242  unsigned Max_iter;
243 
246 
249 
252 
255 
259 
263 
266 
271  };
272 
273 
277 
278 
279  //======================================================================
281  //======================================================================
282  template<typename MATRIX>
283  class CG : public IterativeLinearSolver
284  {
285  public:
287  CG()
288  : Iterations(0),
289  Matrix_pt(0),
290  Resolving(false),
292  {
293  }
294 
295 
297  virtual ~CG()
298  {
299  clean_up_memory();
300  }
301 
303  CG(const CG&) = delete;
304 
306  void operator=(const CG&) = delete;
307 
310  {
312  clean_up_memory();
313  }
314 
315 
319  void solve(Problem* const& problem_pt, DoubleVector& result);
320 
323  void solve(DoubleMatrixBase* const& matrix_pt,
324  const DoubleVector& rhs,
326  {
327  // Store the matrix if required
328  if ((Enable_resolve) && (!Resolving))
329  {
330  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
331 
332  // Matrix has been passed in from the outside so we must not
333  // delete it
334  Matrix_can_be_deleted = false;
335  }
336 
337  // set the distribution
338  if (dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt))
339  {
340  // the solver has the same distribution as the matrix if possible
341  this->build_distribution(
342  dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt)
343  ->distribution_pt());
344  }
345  else
346  {
347  // the solver has the same distribution as the RHS
348  this->build_distribution(rhs.distribution_pt());
349  }
350 
351  // Call the helper function
352  this->solve_helper(matrix_pt, rhs, solution);
353  }
354 
358  void resolve(const DoubleVector& rhs, DoubleVector& result);
359 
361  unsigned iterations() const
362  {
363  return Iterations;
364  }
365 
366 
367  private:
369  void solve_helper(DoubleMatrixBase* const& matrix_pt,
370  const DoubleVector& rhs,
372 
373 
376  {
377  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
378  {
379  delete Matrix_pt;
380  Matrix_pt = 0;
381  }
382  }
383 
385  unsigned Iterations;
386 
388  MATRIX* Matrix_pt;
389 
392  bool Resolving;
393 
397  };
398 
399 
403 
404 
405  //======================================================================
407  //======================================================================
408  template<typename MATRIX>
410  {
411  public:
414  : Iterations(0),
415  Matrix_pt(0),
416  Resolving(false),
418  {
419  }
420 
421 
423  virtual ~BiCGStab()
424  {
425  clean_up_memory();
426  }
427 
429  BiCGStab(const BiCGStab&) = delete;
430 
432  void operator=(const BiCGStab&) = delete;
433 
436  {
438  clean_up_memory();
439  }
440 
444  void solve(Problem* const& problem_pt, DoubleVector& result);
445 
448  void solve(DoubleMatrixBase* const& matrix_pt,
449  const DoubleVector& rhs,
451  {
452  // Store the matrix if required
453  if ((Enable_resolve) && (!Resolving))
454  {
455  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
456 
457  // Matrix has been passed in from the outside so we must not
458  // delete it
459  Matrix_can_be_deleted = false;
460  }
461 
462  // set the distribution
463  if (dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt))
464  {
465  // the solver has the same distribution as the matrix if possible
466  this->build_distribution(
467  dynamic_cast<DistributableLinearAlgebraObject*>(matrix_pt)
468  ->distribution_pt());
469  }
470  else
471  {
472  // the solver has the same distribution as the RHS
473  this->build_distribution(rhs.distribution_pt());
474  }
475 
476  // Call the helper function
477  this->solve_helper(matrix_pt, rhs, solution);
478  }
479 
484  void solve(DoubleMatrixBase* const& matrix_pt,
485  const Vector<double>& rhs,
486  Vector<double>& result)
487  {
488  LinearSolver::solve(matrix_pt, rhs, result);
489  }
490 
491 
495  void resolve(const DoubleVector& rhs, DoubleVector& result);
496 
497 
499  unsigned iterations() const
500  {
501  return Iterations;
502  }
503 
504 
505  private:
507  void solve_helper(DoubleMatrixBase* const& matrix_pt,
508  const DoubleVector& rhs,
510 
513  {
514  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
515  {
516  delete Matrix_pt;
517  Matrix_pt = 0;
518  }
519  }
520 
522  unsigned Iterations;
523 
525  MATRIX* Matrix_pt;
526 
529  bool Resolving;
530 
534  };
535 
536 
540 
541 
542  //====================================================================
548  //====================================================================
550  {
551  public:
553  Smoother() : Use_as_smoother(false) {}
554 
556  virtual ~Smoother(){};
557 
564  virtual void smoother_solve(const DoubleVector& rhs,
565  DoubleVector& result) = 0;
566 
568  virtual void smoother_setup(DoubleMatrixBase* matrix_pt) = 0;
569 
572  template<typename MATRIX>
573  void check_validity_of_solve_helper_inputs(MATRIX* const& matrix_pt,
574  const DoubleVector& rhs,
576  const double& n_dof);
577 
578  protected:
586  }; // End of Smoother
587 
588 
592 
593 
594  //=========================================================================
596  //=========================================================================
597  template<typename MATRIX>
598  class GS : public virtual Smoother
599  {
600  public:
602  GS()
603  : Matrix_pt(0),
604  Iterations(0),
605  Resolving(false),
607  {
608  }
609 
611  virtual ~GS()
612  {
613  clean_up_memory();
614  }
615 
617  GS(const GS&) = delete;
618 
620  void operator=(const GS&) = delete;
621 
624  {
626  clean_up_memory();
627  } // End of disable_resolve
628 
631  {
632  // Assume the matrix has been passed in from the outside so we must
633  // not delete it. This is needed to avoid pre- and post-smoothers
634  // deleting the same matrix in the MG solver. If this was originally
635  // set to TRUE then this will be sorted out in the other functions
636  // from which this was called
637  Matrix_can_be_deleted = false;
638 
639  // Upcast the input matrix to system matrix to the type MATRIX
640  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
641  } // End of smoother_setup
642 
647  void smoother_solve(const DoubleVector& rhs, DoubleVector& result)
648  {
649  // If you use a smoother but you don't want to calculate the residual
650  Use_as_smoother = true;
651 
652  // Call the helper function
653  solve_helper(Matrix_pt, rhs, result);
654  } // End of smoother_setup
655 
659  void solve(Problem* const& problem_pt, DoubleVector& result);
660 
663  void solve(DoubleMatrixBase* const& matrix_pt,
664  const DoubleVector& rhs,
666  {
667  // Reset the Use_as_smoother_flag as the solver is not being used
668  // as a smoother
669  Use_as_smoother = false;
670 
671  // Set up the distribution
672  this->build_distribution(rhs.distribution_pt());
673 
674  // Store the matrix if required
675  if ((Enable_resolve) && (!Resolving))
676  {
677  // Upcast to the appropriate matrix type
678  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
679  }
680 
681  // Matrix has been passed in from the outside so we must not delete it
682  Matrix_can_be_deleted = false;
683 
684  // Call the helper function
685  this->solve_helper(matrix_pt, rhs, solution);
686  } // End of solve
687 
692  void solve(DoubleMatrixBase* const& matrix_pt,
693  const Vector<double>& rhs,
694  Vector<double>& result)
695  {
696  LinearSolver::solve(matrix_pt, rhs, result);
697  } // End of solve
698 
702  void resolve(const DoubleVector& rhs, DoubleVector& result)
703  {
704  // We are re-solving
705  Resolving = true;
706 
707 #ifdef PARANOID
708  if (Matrix_pt == 0)
709  {
710  throw OomphLibError("No matrix was stored -- cannot re-solve",
713  }
714 #endif
715 
716  // Call linear algebra-style solver
717  solve(Matrix_pt, rhs, result);
718 
719  // Reset re-solving flag
720  Resolving = false;
721  } // End of resolve
722 
725  {
726  throw OomphLibError(
727  "Gauss Seidel is not a preconditionable iterative solver",
730  return 0;
731  } // End of preconditioner_setup_time
732 
734  unsigned iterations() const
735  {
736  return Iterations;
737  } // End of iterations
738 
739  private:
741  void solve_helper(DoubleMatrixBase* const& matrix_pt,
742  const DoubleVector& rhs,
744 
747  {
748  // If the matrix pointer isn't null and we're allowed to delete it
749  // delete the matrix and assign the pointer the value NULL
750  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
751  {
752  // Destroy the matrix
753  delete Matrix_pt;
754 
755  // Make it a null pointer
756  Matrix_pt = 0;
757  }
758  } // End of clean_up_memory
759 
761  MATRIX* Matrix_pt;
762 
764  unsigned Iterations;
765 
768  bool Resolving;
769 
773  };
774 
778 
779  //=========================================================================
782  //=========================================================================
783  template<>
784  class GS<CRDoubleMatrix> : public virtual Smoother
785  {
786  public:
788  GS()
789  : Matrix_pt(0),
790  Iterations(0),
791  Resolving(false),
793  {
794  }
795 
797  virtual ~GS()
798  {
799  clean_up_memory();
800  }
801 
803  GS(const GS&) = delete;
804 
806  void operator=(const GS&) = delete;
807 
812  void smoother_solve(const DoubleVector& rhs, DoubleVector& result)
813  {
814  // If you use a smoother but you don't want to calculate the residual
815  Use_as_smoother = true;
816 
817  // Call the helper function
818  solve_helper(Matrix_pt, rhs, result);
819  } // End of smoother_solve
820 
823  {
825  clean_up_memory();
826  } // End of disable_resolve
827 
830  {
831  // Assume the matrix has been passed in from the outside so we must
832  // not delete it. This is needed to avoid pre- and post-smoothers
833  // deleting the same matrix in the MG solver. If this was originally
834  // set to TRUE then this will be sorted out in the other functions
835  // from which this was called
836  Matrix_can_be_deleted = false;
837 
838  // Call the generic setup helper function
839  setup_helper(matrix_pt);
840  } // End of smoother_setup
841 
844  void setup_helper(DoubleMatrixBase* matrix_pt);
845 
849  void solve(Problem* const& problem_pt, DoubleVector& result);
850 
853  void solve(DoubleMatrixBase* const& matrix_pt,
854  const DoubleVector& rhs,
856  {
857  // Reset the Use_as_smoother_flag as the solver is not being used
858  // as a smoother
859  Use_as_smoother = false;
860 
861  // Set up the distribution
862  this->build_distribution(rhs.distribution_pt());
863 
864  // Store the matrix if required
865  if ((Enable_resolve) && (!Resolving))
866  {
867  // Upcast to the appropriate matrix type and sort the matrix entries
868  // out so that the CRDoubleMatrix implementation of the Gauss-Seidel
869  // solver can be used
870  Matrix_pt = dynamic_cast<CRDoubleMatrix*>(matrix_pt);
871  }
872  // We still need to sort the entries
873  else
874  {
875  // The system matrix here is a CRDoubleMatrix. To make use of the
876  // specific implementation of the solver for this type of matrix we
877  // need to make sure the entries are arranged correctly
878  dynamic_cast<CRDoubleMatrix*>(matrix_pt)->sort_entries();
879 
880  // Now get access to the vector Index_of_diagonal_entries
881  Index_of_diagonal_entries = dynamic_cast<CRDoubleMatrix*>(matrix_pt)
882  ->get_index_of_diagonal_entries();
883  }
884 
885  // Matrix has been passed in from the outside so we must not delete it
886  Matrix_can_be_deleted = false;
887 
888  // Call the helper function
889  solve_helper(matrix_pt, rhs, solution);
890  } // End of solve
891 
896  void solve(DoubleMatrixBase* const& matrix_pt,
897  const Vector<double>& rhs,
898  Vector<double>& result)
899  {
900  LinearSolver::solve(matrix_pt, rhs, result);
901  } // End of solve
902 
906  void resolve(const DoubleVector& rhs, DoubleVector& result)
907  {
908  // We are re-solving
909  Resolving = true;
910 
911 #ifdef PARANOID
912  // If the matrix pointer is null
913  if (this->Matrix_pt == 0)
914  {
915  throw OomphLibError("No matrix was stored -- cannot re-solve",
918  }
919 #endif
920 
921  // Call linear algebra-style solver
922  solve(Matrix_pt, rhs, result);
923 
924  // Reset re-solving flag
925  Resolving = false;
926  } // End of resolve
927 
930  {
931  // Create the error message
932  std::string error_output_string = "Gauss Seidel is not a ";
933  error_output_string += "preconditionable iterative solver";
934 
935  // Throw an error
936  throw OomphLibError(
937  error_output_string, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
938 
939  // Return a value so the compiler doesn't throw up an error about
940  // no input being returned
941  return 0;
942  } // End of preconditioner_setup_time
943 
945  unsigned iterations() const
946  {
947  // Return the number of iterations
948  return Iterations;
949  } // End of iterations
950 
951  private:
953  void solve_helper(DoubleMatrixBase* const& matrix_pt,
954  const DoubleVector& rhs,
956 
959  {
960  // If the matrix pointer isn't null AND we're allowed to delete the
961  // matrix which is only when we create the matrix ourselves
962  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
963  {
964  // Delete the matrix
965  delete Matrix_pt;
966 
967  // Assign the associated pointer the value NULL
968  Matrix_pt = 0;
969  }
970  } // End of clean_up_memory
971 
974 
976  unsigned Iterations;
977 
980  bool Resolving;
981 
985 
989  };
990 
994 
995  //=========================================================================
999  //=========================================================================
1000  template<typename MATRIX>
1001  class DampedJacobi : public virtual Smoother
1002  {
1003  public:
1005  DampedJacobi(const double& omega = 2.0 / 3.0) : Matrix_can_be_deleted(true)
1006  {
1007  // Damping factor
1008  Omega = omega;
1009  }
1010 
1013  {
1014  // Run the generic clean up function
1015  clean_up_memory();
1016  }
1017 
1019  DampedJacobi(const DampedJacobi&) = delete;
1020 
1022  void operator=(const DampedJacobi&) = delete;
1023 
1026  {
1027  // If the matrix pointer isn't null AND we're allowed to delete the
1028  // matrix which is only when we create the matrix ourselves
1029  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
1030  {
1031  // Delete the matrix
1032  delete Matrix_pt;
1033 
1034  // Assign the associated pointer the value NULL
1035  Matrix_pt = 0;
1036  }
1037  } // End of clean_up_memory
1038 
1041  {
1042  // Assume the matrix has been passed in from the outside so we must not
1043  // delete it
1044  Matrix_can_be_deleted = false;
1045 
1046  // Upcast to the appropriate matrix type
1047  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
1048 
1049  // Extract the diagonal entries of the matrix and store them
1050  extract_diagonal_entries(matrix_pt);
1051  } // End of smoother_setup
1052 
1055  {
1056  // If we're using a CRDoubleMatrix object
1057  if (dynamic_cast<CRDoubleMatrix*>(matrix_pt))
1058  {
1059  // The matrix diagonal (we need this when we need to calculate inv(D)
1060  // where D is the diagonal of A and it remains the same for all uses
1061  // of the iterative scheme so we can store it and call it in each
1062  // iteration)
1063  Matrix_diagonal =
1064  dynamic_cast<CRDoubleMatrix*>(Matrix_pt)->diagonal_entries();
1065  }
1066  // If we're using a complex matrix then diagonal entries has to be a
1067  // complex vector rather than a vector of doubles.
1068  else if (dynamic_cast<CCDoubleMatrix*>(matrix_pt))
1069  {
1070  // Make an ostringstream object to create an error message
1071  std::ostringstream error_message_stream;
1072 
1073  // Create the error message
1074  error_message_stream << "Damped Jacobi can only cater to real-valued "
1075  << "matrices. If you require a complex-valued "
1076  << "version, please write this yourself. "
1077  << "It is likely that the only difference will be "
1078  << "the use of complex vectors.";
1079 
1080  // Throw an error
1081  throw OomphLibError(error_message_stream.str(),
1084  }
1085  // Just extract the diagonal entries normally
1086  else
1087  {
1088  // Calculate the number of rows in the matrix
1089  unsigned n_row = Matrix_pt->nrow();
1090 
1091  // Loop over the rows of the matrix
1092  for (unsigned i = 0; i < n_row; i++)
1093  {
1094  // Assign the i-th value of Matrix_diagonal
1095  Matrix_diagonal[i] = (*Matrix_pt)(i, i);
1096  }
1097  } // if (dynamic_cast<CRDoubleMatrix*>(matrix_pt))
1098 
1099  // Calculate the n.d.o.f.
1100  unsigned n_dof = Matrix_diagonal.size();
1101 
1102  // Find the reciprocal of the entries of Matrix_diagonal
1103  for (unsigned i = 0; i < n_dof; i++)
1104  {
1105  Matrix_diagonal[i] = 1.0 / Matrix_diagonal[i];
1106  }
1107  } // End of extract_diagonal_entries
1108 
1114  {
1115  // If you use a smoother but you don't want to calculate the residual
1116  Use_as_smoother = true;
1117 
1118  // Call the helper function
1120  } // End of smoother_solve
1121 
1126  void solve(Problem* const& problem_pt, DoubleVector& result);
1127 
1130  void solve(DoubleMatrixBase* const& matrix_pt,
1131  const DoubleVector& rhs,
1133  {
1134  // Matrix has been passed in from the outside so we must not delete it
1135  Matrix_can_be_deleted = false;
1136 
1137  // Indicate that the solver is not being used as a smoother
1138  Use_as_smoother = false;
1139 
1140  // Set up the distribution
1141  this->build_distribution(rhs.distribution_pt());
1142 
1143  // Store the matrix if required
1144  if ((Enable_resolve) && (!Resolving))
1145  {
1146  // Upcast to the appropriate matrix type
1147  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
1148  }
1149 
1150  // Extract the diagonal entries of the matrix and store them
1151  extract_diagonal_entries(matrix_pt);
1152 
1153  // Call the helper function
1154  solve_helper(matrix_pt, rhs, solution);
1155  } // End of solve
1156 
1160  void resolve(const DoubleVector& rhs, DoubleVector& result)
1161  {
1162  // We are re-solving
1163  Resolving = true;
1164 
1165 #ifdef PARANOID
1166  if (Matrix_pt == 0)
1167  {
1168  throw OomphLibError("No matrix was stored -- cannot re-solve",
1171  }
1172 #endif
1173 
1174  // Call linear algebra-style solver
1175  solve(Matrix_pt, rhs, result);
1176 
1177  // Reset re-solving flag
1178  Resolving = false;
1179  } // End of resolve
1180 
1182  unsigned iterations() const
1183  {
1184  // Return the value of Iterations
1185  return Iterations;
1186  } // End of iterations
1187 
1188  private:
1191  void solve_helper(DoubleMatrixBase* const& matrix_pt,
1192  const DoubleVector& rhs,
1194 
1196  MATRIX* Matrix_pt;
1197 
1200 
1204 
1208 
1210  unsigned Iterations;
1211 
1213  double Omega;
1214  };
1215 
1216 
1220 
1221 
1222  //======================================================================
1224  //======================================================================
1225  template<typename MATRIX>
1227  {
1228  public:
1231  : Iterations(0),
1232  Matrix_pt(0),
1233  Resolving(false),
1234  Matrix_can_be_deleted(true),
1236  {
1237  Preconditioner_LHS = true;
1238  Iteration_restart = false;
1239  }
1240 
1242  virtual ~GMRES()
1243  {
1244  clean_up_memory();
1245  }
1246 
1248  GMRES(const GMRES&) = delete;
1249 
1251  void operator=(const GMRES&) = delete;
1252 
1255  {
1257  clean_up_memory();
1258  }
1259 
1262  {
1263  Compute_gradient = true;
1264  }
1265 
1269  void solve(Problem* const& problem_pt, DoubleVector& result);
1270 
1273  void solve(DoubleMatrixBase* const& matrix_pt,
1274  const DoubleVector& rhs,
1276  {
1277  // setup the distribution
1278  this->build_distribution(rhs.distribution_pt());
1279 
1280  // Store the matrix if required
1281  if ((Enable_resolve) && (!Resolving))
1282  {
1283  Matrix_pt = dynamic_cast<MATRIX*>(matrix_pt);
1284 
1285  // Matrix has been passed in from the outside so we must not
1286  // delete it
1287  Matrix_can_be_deleted = false;
1288  }
1289 
1290  // Call the helper function
1291  this->solve_helper(matrix_pt, rhs, solution);
1292  }
1293 
1294 
1299  void solve(DoubleMatrixBase* const& matrix_pt,
1300  const Vector<double>& rhs,
1301  Vector<double>& result)
1302  {
1303  LinearSolver::solve(matrix_pt, rhs, result);
1304  }
1305 
1309  void resolve(const DoubleVector& rhs, DoubleVector& result);
1310 
1312  unsigned iterations() const
1313  {
1314  return Iterations;
1315  }
1316 
1318  bool iteration_restart() const
1319  {
1320  return Iteration_restart;
1321  }
1322 
1326  void enable_iteration_restart(const unsigned& restart)
1327  {
1328  Restart = restart;
1329  Iteration_restart = true;
1330  }
1331 
1334  {
1335  Iteration_restart = false;
1336  }
1337 
1340  {
1341  Preconditioner_LHS = true;
1342  }
1343 
1346  {
1347  Preconditioner_LHS = false;
1348  }
1349 
1350  private:
1352  void solve_helper(DoubleMatrixBase* const& matrix_pt,
1353  const DoubleVector& rhs,
1355 
1358  {
1359  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
1360  {
1361  delete Matrix_pt;
1362  Matrix_pt = 0;
1363  }
1364  }
1365 
1368  void update(const unsigned& k,
1369  const Vector<Vector<double>>& H,
1370  const Vector<double>& s,
1371  const Vector<DoubleVector>& v,
1372  DoubleVector& x)
1373  {
1374  // Make a local copy of s
1375  Vector<double> y(s);
1376 
1377  // Backsolve:
1378  for (int i = int(k); i >= 0; i--)
1379  {
1380  // Divide the i-th entry of y by the i-th diagonal entry of H
1381  y[i] /= H[i][i];
1382 
1383  // Loop over the previous values of y and update
1384  for (int j = i - 1; j >= 0; j--)
1385  {
1386  // Update the j-th entry of y
1387  y[j] -= H[i][j] * y[i];
1388  }
1389  } // for (int i=int(k);i>=0;i--)
1390 
1391  // Store the number of rows in the result vector
1392  unsigned n_x = x.nrow();
1393 
1394  // Build a temporary vector with entries initialised to 0.0
1395  DoubleVector temp(x.distribution_pt(), 0.0);
1396 
1397  // Build a temporary vector with entries initialised to 0.0
1398  DoubleVector z(x.distribution_pt(), 0.0);
1399 
1400  // Get access to the underlying values
1401  double* temp_pt = temp.values_pt();
1402 
1403  // Calculate x=Vy
1404  for (unsigned j = 0; j <= k; j++)
1405  {
1406  // Get access to j-th column of v
1407  const double* vj_pt = v[j].values_pt();
1408 
1409  // Loop over the entries of the vector, temp
1410  for (unsigned i = 0; i < n_x; i++)
1411  {
1412  temp_pt[i] += vj_pt[i] * y[j];
1413  }
1414  } // for (unsigned j=0;j<=k;j++)
1415 
1416  // If we're using LHS preconditioning
1417  if (Preconditioner_LHS)
1418  {
1419  // Since we're using LHS preconditioning the preconditioner is applied
1420  // to the matrix and RHS vector so we simply update the value of x
1421  x += temp;
1422  }
1423  // If we're using RHS preconditioning
1424  else
1425  {
1426  // Start the timer
1427  double t_start_prec = TimingHelpers::timer();
1428 
1429  // Since we're using RHS preconditioning the preconditioner is applied
1430  // to the solution vector
1432 
1433  // Calculate the time taken for the preconditioner solve
1435  (TimingHelpers::timer() - t_start_prec);
1436 
1437  // Use the update: x_m=x_0+inv(M)Vy [see Saad Y,"Iterative methods for
1438  // sparse linear systems", p.284]
1439  x += z;
1440  }
1441  } // End of update
1442 
1453  void generate_plane_rotation(double& dx, double& dy, double& cs, double& sn)
1454  {
1455  // If dy=0 then we do not need to apply a rotation
1456  if (dy == 0.0)
1457  {
1458  // Using theta=0 gives cos(theta)=1
1459  cs = 1.0;
1460 
1461  // Using theta=0 gives sin(theta)=0
1462  sn = 0.0;
1463  }
1464  // If dx or dy is large using the normal form of calculting cs and sn
1465  // is naive since this may overflow or underflow so instead we calculate
1466  // r=sqrt(pow(dx,2)+pow(dy,2)) by using r=|dy|sqrt(1+pow(dx/dy,2)) if
1467  // |dy|>|dx| [see <A
1468  // HREF=https://en.wikipedia.org/wiki/Hypot">Hypot</A>.].
1469  else if (fabs(dy) > fabs(dx))
1470  {
1471  // Since |dy|>|dx| calculate the ratio dx/dy
1472  double temp = dx / dy;
1473 
1474  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))
1475  sn = 1.0 / sqrt(1.0 + temp * temp);
1476 
1477  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))=(dx/dy)*sin(theta)
1478  cs = temp * sn;
1479  }
1480  // Otherwise, we have |dx|>=|dy| so to, again, avoid overflow or underflow
1481  // calculate the values of cs and sn using the method above
1482  else
1483  {
1484  // Since |dx|>=|dy| calculate the ratio dy/dx
1485  double temp = dy / dx;
1486 
1487  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))
1488  cs = 1.0 / sqrt(1.0 + temp * temp);
1489 
1490  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))=(dy/dx)*cos(theta)
1491  sn = temp * cs;
1492  }
1493  } // End of generate_plane_rotation
1494 
1498  void apply_plane_rotation(double& dx, double& dy, double& cs, double& sn)
1499  {
1500  // Calculate the value of dx but don't update it yet
1501  double temp = cs * dx + sn * dy;
1502 
1503  // Set the value of dy
1504  dy = -sn * dx + cs * dy;
1505 
1506  // Set the value of dx using the correct values of dx and dy
1507  dx = temp;
1508  }
1509 
1511  unsigned Iterations;
1512 
1515  unsigned Restart;
1516 
1519 
1521  MATRIX* Matrix_pt;
1522 
1526 
1530 
1534 
1537  };
1538 
1539 
1543 
1544 
1545  //======================================================================
1547  //======================================================================
1549  {
1550  public:
1553  DoubleVector* c_pt,
1554  double* x_pt,
1555  double* rhs_pt)
1556  : Iterations(0),
1557  Matrix_pt(0),
1558  B_pt(b_pt),
1559  C_pt(c_pt),
1560  X_pt(x_pt),
1561  Rhs_pt(rhs_pt),
1563  Resolving(false),
1564  Matrix_can_be_deleted(true)
1565  {
1566  Preconditioner_LHS = true;
1567  Iteration_restart = false;
1568  }
1569 
1572  {
1573  clean_up_memory();
1574  }
1575 
1578 
1580  void operator=(const AugmentedProblemGMRES&) = delete;
1581 
1584  {
1586  clean_up_memory();
1587  } // End of disable_resolve
1588 
1592  void solve(Problem* const& problem_pt, DoubleVector& result);
1593 
1596  void solve(DoubleMatrixBase* const& matrix_pt,
1597  const DoubleVector& rhs,
1599  {
1600  // Upcast to a CRDoubleMatrix
1601  CRDoubleMatrix* cr_matrix_pt = dynamic_cast<CRDoubleMatrix*>(matrix_pt);
1602 
1603  // If we can't upcast to a CRDoubleMatrix then this won't work...
1604  if (cr_matrix_pt == 0)
1605  {
1606  // Throw an error
1607  throw OomphLibError("Can't upcast input matrix to a CRDoubleMatrix!",
1610  }
1611 
1612  // Set up the distribution
1613  this->build_distribution(cr_matrix_pt->distribution_pt());
1614 
1615  // Store the matrix if required
1616  if ((Enable_resolve) && (!Resolving))
1617  {
1618  // Store a pointer to the upcasted matrix
1619  Matrix_pt = cr_matrix_pt;
1620 
1621  // Matrix has been passed in from the outside so we must not
1622  // delete it
1623  Matrix_can_be_deleted = false;
1624  }
1625 
1626  // Call the helper function
1627  this->solve_helper(matrix_pt, rhs, solution);
1628  } // End of solve
1629 
1634  void solve(DoubleMatrixBase* const& matrix_pt,
1635  const Vector<double>& rhs,
1636  Vector<double>& result)
1637  {
1638  LinearSolver::solve(matrix_pt, rhs, result);
1639  }
1640 
1644  void resolve(const DoubleVector& rhs, DoubleVector& result);
1645 
1647  unsigned iterations() const
1648  {
1649  return Iterations;
1650  }
1651 
1653  bool iteration_restart() const
1654  {
1655  return Iteration_restart;
1656  }
1657 
1661  void enable_iteration_restart(const unsigned& restart)
1662  {
1663  Restart = restart;
1664  Iteration_restart = true;
1665  }
1666 
1669  {
1670  Iteration_restart = false;
1671  } // End of disable_iteration_restart
1672 
1675  {
1676  Preconditioner_LHS = true;
1677  }
1678 
1681  {
1682  Preconditioner_LHS = false;
1683  }
1684 
1685  private:
1688  {
1689  if ((Matrix_pt != 0) && (Matrix_can_be_deleted))
1690  {
1691  delete Matrix_pt;
1692  Matrix_pt = 0;
1693  }
1694  } // End of clean_up_memory
1695 
1698  const DoubleVector& x,
1699  DoubleVector& soln)
1700  {
1701  // How many dofs are there in the non-augmented system?
1702  unsigned n_dof = matrix_pt->nrow();
1703 
1704  // Allocate space for the non-augmented component of x
1705  DoubleVector x_small(this->distribution_pt(), 0.0);
1706 
1707  // Loop over the first n_dof entries of x
1708  for (unsigned i = 0; i < n_dof; i++)
1709  {
1710  // Copy the i-th entry over
1711  x_small[i] = x[i];
1712  }
1713 
1714  // Allocate space for the product of the matrix and x_small
1715  DoubleVector a_prod_xsmall(this->distribution_pt(), 0.0);
1716 
1717  // Now multiply the matrix and x_small
1718  matrix_pt->multiply(x_small, a_prod_xsmall);
1719 
1720  // Get the scalar component of x associated with the system augmentation
1721  double y = x[n_dof];
1722 
1723  // Loop over the first n_dof entries of soln
1724  for (unsigned i = 0; i < n_dof; i++)
1725  {
1726  // Compute the i-th entry
1727  soln[i] = a_prod_xsmall[i] + y * (*B_pt)[i];
1728  }
1729 
1730  // Compute the final entry of soln
1731  soln[n_dof] = C_pt->dot(x_small);
1732  } // End of augmented_matrix_multiply
1733 
1737  DoubleVector& soln)
1738  {
1739  // How many dofs are there in the non-augmented system?
1740  unsigned n_dof = this->distribution_pt()->nrow();
1741 
1742  // Compute the final entry of r first
1743  soln[n_dof] = rhs[n_dof] / Schur_complement_scalar;
1744 
1745  // Do we want to use a block-diagonal approximation? The default is to
1746  // use a block upper-triangular approximation for the preconditioner
1747  bool use_block_diagonal_preconditioner = false;
1748 
1749  // Allocate space for (the non-augmented part of) r satisfying b-Jx = Mr
1750  DoubleVector r_small(this->distribution_pt(), 0.0);
1751 
1752  // Allocate space for the non-augmented system part of the RHS vector
1753  DoubleVector rhs_small(this->distribution_pt(), 0.0);
1754 
1755  // Loop over the first n_dof entries of the RHS vector
1756  for (unsigned i = 0; i < n_dof; i++)
1757  {
1758  // If we want to use the block-diagonal preconditioner
1759  if (use_block_diagonal_preconditioner)
1760  {
1761  // Copy the i-th entry over
1762  rhs_small[i] = rhs[i];
1763  }
1764  // If we want to use the block upper-triangular preconditioner
1765  else
1766  {
1767  // Copy the i-th entry over
1768  rhs_small[i] = rhs[i] - soln[n_dof] * (*B_pt)[i];
1769  }
1770  } // for (unsigned i=0;i<n_dof;i++)
1771 
1772  // Apply the preconditioner
1773  preconditioner_pt()->preconditioner_solve(rhs_small, r_small);
1774 
1775  // Loop over the first n_dof entries of the solution vector
1776  for (unsigned i = 0; i < n_dof; i++)
1777  {
1778  // Copy the i-th entry over
1779  soln[i] = r_small[i];
1780  }
1781  } // End of apply_schur_complement_preconditioner
1782 
1784  void solve_helper(DoubleMatrixBase* const& matrix_pt,
1785  const DoubleVector& rhs,
1787 
1790  void update(const unsigned& k,
1791  const Vector<Vector<double>>& H,
1792  const Vector<double>& s,
1793  const Vector<DoubleVector>& v,
1794  DoubleVector& x)
1795  {
1796  // Make a local copy of s
1797  Vector<double> y(s);
1798 
1799  // Backsolve:
1800  for (int i = int(k); i >= 0; i--)
1801  {
1802  // Divide the i-th entry of y by the i-th diagonal entry of H
1803  y[i] /= H[i][i];
1804 
1805  // Loop over the previous values of y and update
1806  for (int j = i - 1; j >= 0; j--)
1807  {
1808  // Update the j-th entry of y
1809  y[j] -= H[i][j] * y[i];
1810  }
1811  } // for (int i=int(k);i>=0;i--)
1812 
1813  // Store the number of rows in the result vector
1814  unsigned n_x = x.nrow();
1815 
1816  // Build a temporary vector with entries initialised to 0.0
1817  DoubleVector temp(x.distribution_pt(), 0.0);
1818 
1819  // Build a temporary vector with entries initialised to 0.0
1820  DoubleVector z(x.distribution_pt(), 0.0);
1821 
1822  // Get access to the underlying values
1823  double* temp_pt = temp.values_pt();
1824 
1825  // Calculate x=Vy
1826  for (unsigned j = 0; j <= k; j++)
1827  {
1828  // Get access to j-th column of v
1829  const double* vj_pt = v[j].values_pt();
1830 
1831  // Loop over the entries of the vector, temp
1832  for (unsigned i = 0; i < n_x; i++)
1833  {
1834  temp_pt[i] += vj_pt[i] * y[j];
1835  }
1836  } // for (unsigned j=0;j<=k;j++)
1837 
1838  // If we're using LHS preconditioning
1839  if (Preconditioner_LHS)
1840  {
1841  // Since we're using LHS preconditioning the preconditioner is applied
1842  // to the matrix and RHS vector so we simply update the value of x
1843  x += temp;
1844  }
1845  // If we're using RHS preconditioning
1846  else
1847  {
1848  // Since we're using RHS preconditioning the preconditioner is applied
1849  // to the solution vector
1851 
1852  // Use the update: x_m=x_0+inv(M)Vy [see Saad Y,"Iterative methods for
1853  // sparse linear systems", p.284]
1854  x += z;
1855  }
1856  } // End of update
1857 
1868  void generate_plane_rotation(double& dx, double& dy, double& cs, double& sn)
1869  {
1870  // If dy=0 then we do not need to apply a rotation
1871  if (dy == 0.0)
1872  {
1873  // Using theta=0 gives cos(theta)=1
1874  cs = 1.0;
1875 
1876  // Using theta=0 gives sin(theta)=0
1877  sn = 0.0;
1878  }
1879  // If dx or dy is large using the normal form of calculting cs and sn
1880  // is naive since this may overflow or underflow so instead we calculate
1881  // r=sqrt(pow(dx,2)+pow(dy,2)) by using r=|dy|sqrt(1+pow(dx/dy,2)) if
1882  // |dy|>|dx| [see <A
1883  // HREF=https://en.wikipedia.org/wiki/Hypot">Hypot</A>.].
1884  else if (fabs(dy) > fabs(dx))
1885  {
1886  // Since |dy|>|dx| calculate the ratio dx/dy
1887  double temp = dx / dy;
1888 
1889  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))
1890  sn = 1.0 / sqrt(1.0 + temp * temp);
1891 
1892  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))=(dx/dy)*sin(theta)
1893  cs = temp * sn;
1894  }
1895  // Otherwise, we have |dx|>=|dy| so to, again, avoid overflow or underflow
1896  // calculate the values of cs and sn using the method above
1897  else
1898  {
1899  // Since |dx|>=|dy| calculate the ratio dy/dx
1900  double temp = dy / dx;
1901 
1902  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))
1903  cs = 1.0 / sqrt(1.0 + temp * temp);
1904 
1905  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))=(dy/dx)*cos(theta)
1906  sn = temp * cs;
1907  }
1908  } // End of generate_plane_rotation
1909 
1913  void apply_plane_rotation(double& dx, double& dy, double& cs, double& sn)
1914  {
1915  // Calculate the value of dx but don't update it yet
1916  double temp = cs * dx + sn * dy;
1917 
1918  // Set the value of dy
1919  dy = -sn * dx + cs * dy;
1920 
1921  // Set the value of dx using the correct values of dx and dy
1922  dx = temp;
1923  }
1924 
1926  unsigned Iterations;
1927 
1930  unsigned Restart;
1931 
1934 
1937 
1940 
1943 
1945  double* X_pt;
1946 
1948  double* Rhs_pt;
1949 
1952 
1956 
1960 
1964  };
1965 } // End of namespace oomph
1966 
1967 #endif
AnnoyingScalar sqrt(const AnnoyingScalar &x)
Definition: AnnoyingScalar.h:134
Array< int, Dynamic, 1 > v
Definition: Array_initializer_list_vector_cxx11.cpp:1
int i
Definition: BiCGSTAB_step_by_step.cpp:9
MatrixXf H
Definition: HessenbergDecomposition_matrixH.cpp:4
Definition: flowRule_restart.cpp:8
The GMRES method.
Definition: iterative_linear_solver.h:1549
AugmentedProblemGMRES(DoubleVector *b_pt, DoubleVector *c_pt, double *x_pt, double *rhs_pt)
Constructor.
Definition: iterative_linear_solver.h:1552
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:1647
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:1596
void apply_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: iterative_linear_solver.h:1913
bool Resolving
Definition: iterative_linear_solver.h:1955
DoubleVector * C_pt
Pointer to the row vector in the bordered system.
Definition: iterative_linear_solver.h:1942
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:2862
void update(const unsigned &k, const Vector< Vector< double >> &H, const Vector< double > &s, const Vector< DoubleVector > &v, DoubleVector &x)
Definition: iterative_linear_solver.h:1790
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.cc:2831
CRDoubleMatrix * Matrix_pt
Pointer to matrix.
Definition: iterative_linear_solver.h:1936
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:1583
bool Iteration_restart
boolean indicating if iteration restarting is used
Definition: iterative_linear_solver.h:1933
unsigned Restart
Definition: iterative_linear_solver.h:1930
void disable_iteration_restart()
Switches off iteration restart.
Definition: iterative_linear_solver.h:1668
AugmentedProblemGMRES(const AugmentedProblemGMRES &)=delete
Broken copy constructor.
bool iteration_restart() const
access function indicating whether restarted GMRES is used
Definition: iterative_linear_solver.h:1653
double * Rhs_pt
Pointer to the last entry of the RHS vector in the bordered system.
Definition: iterative_linear_solver.h:1948
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: iterative_linear_solver.h:1634
void apply_schur_complement_preconditioner(const DoubleVector &rhs, DoubleVector &soln)
Definition: iterative_linear_solver.h:1736
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:2746
void generate_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: iterative_linear_solver.h:1868
void enable_iteration_restart(const unsigned &restart)
Definition: iterative_linear_solver.h:1661
double Schur_complement_scalar
The scalar component of the Schur complement preconditioner.
Definition: iterative_linear_solver.h:1951
double * X_pt
Pointer to the last entry of the LHS vector in the bordered system.
Definition: iterative_linear_solver.h:1945
void augmented_matrix_multiply(CRDoubleMatrix *matrix_pt, const DoubleVector &x, DoubleVector &soln)
Multiply the vector x by the augmented system matrix.
Definition: iterative_linear_solver.h:1697
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:1926
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:1959
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:1687
void operator=(const AugmentedProblemGMRES &)=delete
Broken assignment operator.
DoubleVector * B_pt
Pointer to the column vector in the bordered system.
Definition: iterative_linear_solver.h:1939
virtual ~AugmentedProblemGMRES()
Destructor: Clean up storage.
Definition: iterative_linear_solver.h:1571
bool Preconditioner_LHS
Definition: iterative_linear_solver.h:1963
void set_preconditioner_RHS()
Enable right preconditioning.
Definition: iterative_linear_solver.h:1680
void set_preconditioner_LHS()
Set left preconditioning (the default)
Definition: iterative_linear_solver.h:1674
The conjugate gradient method.
Definition: iterative_linear_solver.h:410
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:499
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.cc:63
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:533
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:90
MATRIX * Matrix_pt
Pointer to matrix.
Definition: iterative_linear_solver.h:525
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:512
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:171
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:522
virtual ~BiCGStab()
Destructor (cleanup storage)
Definition: iterative_linear_solver.h:423
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:435
void operator=(const BiCGStab &)=delete
Broken assignment operator.
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: iterative_linear_solver.h:484
bool Resolving
Definition: iterative_linear_solver.h:529
BiCGStab(const BiCGStab &)=delete
Broken copy constructor.
BiCGStab()
Constructor.
Definition: iterative_linear_solver.h:413
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:448
A class for compressed column matrices that store doubles.
Definition: matrices.h:2791
The conjugate gradient method.
Definition: iterative_linear_solver.h:284
CG()
Constructor.
Definition: iterative_linear_solver.h:287
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:309
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:361
CG(const CG &)=delete
Broken copy constructor.
virtual ~CG()
Destructor (cleanup storage)
Definition: iterative_linear_solver.h:297
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:950
void operator=(const CG &)=delete
Broken assignment operator.
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:323
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:385
MATRIX * Matrix_pt
Pointer to matrix.
Definition: iterative_linear_solver.h:388
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.cc:922
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:396
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:375
bool Resolving
Definition: iterative_linear_solver.h:392
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:605
Definition: matrices.h:888
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
Definition: matrices.cc:1782
unsigned long nrow() const
Return the number of rows of the matrix.
Definition: matrices.h:1002
Definition: iterative_linear_solver.h:1002
DampedJacobi(const DampedJacobi &)=delete
Broken copy constructor.
bool Resolving
Definition: iterative_linear_solver.h:1203
~DampedJacobi()
Empty destructor.
Definition: iterative_linear_solver.h:1012
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:1207
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:1210
void operator=(const DampedJacobi &)=delete
Broken assignment operator.
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.h:1160
void extract_diagonal_entries(DoubleMatrixBase *matrix_pt)
Function to extract the diagonal entries from the matrix.
Definition: iterative_linear_solver.h:1054
double Omega
Damping factor.
Definition: iterative_linear_solver.h:1213
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.cc:1922
void smoother_setup(DoubleMatrixBase *matrix_pt)
Setup: Pass pointer to the matrix and store in cast form.
Definition: iterative_linear_solver.h:1040
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:1025
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:1182
DampedJacobi(const double &omega=2.0/3.0)
Empty constructor.
Definition: iterative_linear_solver.h:1005
Vector< double > Matrix_diagonal
Vector containing the diagonal entries of A.
Definition: iterative_linear_solver.h:1199
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:1858
MATRIX * Matrix_pt
Pointer to the matrix.
Definition: iterative_linear_solver.h:1196
void smoother_solve(const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:1113
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:1130
Definition: linear_algebra_distribution.h:435
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
Definition: matrices.h:261
Definition: double_vector.h:58
double * values_pt()
access function to the underlying values
Definition: double_vector.h:254
double dot(const DoubleVector &vec) const
compute the dot product of this vector with the vector vec.
Definition: double_vector.cc:805
The GMRES method.
Definition: iterative_linear_solver.h:1227
bool Resolving
Definition: iterative_linear_solver.h:1525
void enable_computation_of_gradient()
function to enable the computation of the gradient
Definition: iterative_linear_solver.h:1261
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.cc:2133
bool Preconditioner_LHS
Definition: iterative_linear_solver.h:1533
double Preconditioner_application_time
Storage for the time spent applying the preconditioner.
Definition: iterative_linear_solver.h:1536
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:2250
MATRIX * Matrix_pt
Pointer to matrix.
Definition: iterative_linear_solver.h:1521
void set_preconditioner_RHS()
Enable right preconditioning.
Definition: iterative_linear_solver.h:1345
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:1529
GMRES(const GMRES &)=delete
Broken copy constructor.
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:1254
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:1357
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:1511
GMRES()
Constructor.
Definition: iterative_linear_solver.h:1230
void operator=(const GMRES &)=delete
Broken assignment operator.
void update(const unsigned &k, const Vector< Vector< double >> &H, const Vector< double > &s, const Vector< DoubleVector > &v, DoubleVector &x)
Definition: iterative_linear_solver.h:1368
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:1312
void enable_iteration_restart(const unsigned &restart)
Definition: iterative_linear_solver.h:1326
virtual ~GMRES()
Destructor (cleanup storage)
Definition: iterative_linear_solver.h:1242
unsigned Restart
Definition: iterative_linear_solver.h:1515
void apply_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: iterative_linear_solver.h:1498
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: iterative_linear_solver.h:1299
void set_preconditioner_LHS()
Set left preconditioning (the default)
Definition: iterative_linear_solver.h:1339
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:1273
void generate_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: iterative_linear_solver.h:1453
void disable_iteration_restart()
switches off iteration restart
Definition: iterative_linear_solver.h:1333
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:2161
bool iteration_restart() const
access function indicating whether restarted GMRES is used
Definition: iterative_linear_solver.h:1318
bool Iteration_restart
boolean indicating if iteration restarting is used
Definition: iterative_linear_solver.h:1518
void smoother_solve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.h:812
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:945
GS(const GS &)=delete
Broken copy constructor.
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:976
GS()
Constructor.
Definition: iterative_linear_solver.h:788
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:853
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:822
void operator=(const GS &)=delete
Broken assignment operator.
void clean_up_memory()
Clean up data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:958
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:984
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: iterative_linear_solver.h:896
CRDoubleMatrix * Matrix_pt
System matrix pointer in the format specified by the template argument.
Definition: iterative_linear_solver.h:973
void smoother_setup(DoubleMatrixBase *matrix_pt)
Set up the smoother for the matrix specified by the pointer.
Definition: iterative_linear_solver.h:829
Vector< int > Index_of_diagonal_entries
Definition: iterative_linear_solver.h:988
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.h:906
double preconditioner_setup_time() const
Returns the time taken to set up the preconditioner.
Definition: iterative_linear_solver.h:929
virtual ~GS()
Destructor (cleanup storage)
Definition: iterative_linear_solver.h:797
bool Resolving
Definition: iterative_linear_solver.h:980
The Gauss Seidel method.
Definition: iterative_linear_solver.h:599
virtual ~GS()
Destructor (cleanup storage)
Definition: iterative_linear_solver.h:611
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:764
double preconditioner_setup_time() const
Returns the time taken to set up the preconditioner.
Definition: iterative_linear_solver.h:724
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:772
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:1164
void clean_up_memory()
Cleanup data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:746
void solve(DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
Definition: iterative_linear_solver.h:692
bool Resolving
Definition: iterative_linear_solver.h:768
void smoother_solve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.h:647
void solve(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
Definition: iterative_linear_solver.h:663
void smoother_setup(DoubleMatrixBase *matrix_pt)
Set up the smoother for the matrix specified by the pointer.
Definition: iterative_linear_solver.h:630
void disable_resolve()
Overload disable resolve so that it cleans up memory too.
Definition: iterative_linear_solver.h:623
MATRIX * Matrix_pt
System matrix pointer in the format specified by the template argument.
Definition: iterative_linear_solver.h:761
void operator=(const GS &)=delete
Broken assignment operator.
GS()
Constructor.
Definition: iterative_linear_solver.h:602
unsigned iterations() const
Number of iterations taken.
Definition: iterative_linear_solver.h:734
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:1104
GS(const GS &)=delete
Broken copy constructor.
void resolve(const DoubleVector &rhs, DoubleVector &result)
Definition: iterative_linear_solver.h:702
The Identity Preconditioner.
Definition: preconditioner.h:252
Definition: iterative_linear_solver.h:54
bool Use_iterative_solver_as_preconditioner
Use the iterative solver as preconditioner.
Definition: iterative_linear_solver.h:265
bool First_time_solve_when_used_as_preconditioner
Definition: iterative_linear_solver.h:270
void open_convergence_history_file_stream(const std::string &file_name, const std::string &zone_title="")
Definition: iterative_linear_solver.h:138
void close_convergence_history_file_stream()
Close convergence history output stream.
Definition: iterative_linear_solver.h:161
Preconditioner *const & preconditioner_pt() const
Access function to preconditioner (const version)
Definition: iterative_linear_solver.h:101
void enable_setup_preconditioner_before_solve()
Setup the preconditioner before the solve.
Definition: iterative_linear_solver.h:186
double Tolerance
Convergence tolerance.
Definition: iterative_linear_solver.h:239
void disable_error_after_max_iter()
Don't throw an error if we don't converge within max_iter (default).
Definition: iterative_linear_solver.h:204
Preconditioner * Preconditioner_pt
Pointer to the preconditioner.
Definition: iterative_linear_solver.h:245
void enable_doc_convergence_history()
Enable documentation of the convergence history.
Definition: iterative_linear_solver.h:122
void enable_iterative_solver_as_preconditioner()
Definition: iterative_linear_solver.h:212
virtual unsigned iterations() const =0
Number of iterations taken.
double linear_solver_solution_time() const
return the time taken to solve the linear system
Definition: iterative_linear_solver.h:174
virtual ~IterativeLinearSolver()
Destructor (empty)
Definition: iterative_linear_solver.h:92
void enable_error_after_max_iter()
Throw an error if we don't converge within max_iter.
Definition: iterative_linear_solver.h:198
bool Throw_error_after_max_iter
Definition: iterative_linear_solver.h:262
IterativeLinearSolver()
Definition: iterative_linear_solver.h:58
void disable_doc_convergence_history()
Disable documentation of the convergence history.
Definition: iterative_linear_solver.h:128
Preconditioner *& preconditioner_pt()
Access function to preconditioner.
Definition: iterative_linear_solver.h:95
double Preconditioner_setup_time
Preconditioner setup time.
Definition: iterative_linear_solver.h:254
double Jacobian_setup_time
Jacobian setup time.
Definition: iterative_linear_solver.h:248
static IdentityPreconditioner Default_preconditioner
Definition: iterative_linear_solver.h:236
virtual double preconditioner_setup_time() const
returns the the time taken to setup the preconditioner
Definition: iterative_linear_solver.h:180
void disable_iterative_solver_as_preconditioner()
Definition: iterative_linear_solver.h:220
unsigned Max_iter
Maximum number of iterations.
Definition: iterative_linear_solver.h:242
double & tolerance()
Access to convergence tolerance.
Definition: iterative_linear_solver.h:107
double Solution_time
linear solver solution time
Definition: iterative_linear_solver.h:251
void operator=(const IterativeLinearSolver &)=delete
Broken assignment operator.
IterativeLinearSolver(const IterativeLinearSolver &)=delete
Broken copy constructor.
std::ofstream Output_file_stream
Output file stream for convergence history.
Definition: iterative_linear_solver.h:231
void disable_setup_preconditioner_before_solve()
Don't set up the preconditioner before the solve.
Definition: iterative_linear_solver.h:192
unsigned & max_iter()
Access to max. number of iterations.
Definition: iterative_linear_solver.h:113
bool Doc_convergence_history
Definition: iterative_linear_solver.h:228
double jacobian_setup_time() const
Definition: iterative_linear_solver.h:168
bool Setup_preconditioner_before_solve
Definition: iterative_linear_solver.h:258
unsigned nrow() const
access function to the number of global rows.
Definition: linear_algebra_distribution.h:186
Definition: linear_solver.h:68
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0
bool Enable_resolve
Definition: linear_solver.h:73
virtual void disable_resolve()
Definition: linear_solver.h:144
bool Compute_gradient
Definition: linear_solver.h:81
Definition: oomph_definitions.h:222
Definition: preconditioner.h:54
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
Definition: problem.h:151
Definition: iterative_linear_solver.h:550
virtual ~Smoother()
Virtual empty destructor.
Definition: iterative_linear_solver.h:556
void check_validity_of_solve_helper_inputs(MATRIX *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution, const double &n_dof)
Definition: iterative_linear_solver.cc:1029
virtual void smoother_setup(DoubleMatrixBase *matrix_pt)=0
Set up the smoother for the matrix specified by the pointer.
virtual void smoother_solve(const DoubleVector &rhs, DoubleVector &result)=0
bool Use_as_smoother
Definition: iterative_linear_solver.h:585
Smoother()
Empty constructor.
Definition: iterative_linear_solver.h:553
Definition: restart2.cpp:8
Scalar * y
Definition: level1_cplx_impl.h:128
RealScalar s
Definition: level1_cplx_impl.h:130
char char char int int * k
Definition: level2_impl.h:374
void solution(const Vector< double > &x, Vector< double > &u)
Definition: two_d_biharmonic.cc:113
Vector::Scalar omega(const Vector &t, const Vector &s, RealScalar angle)
Definition: IDRS.h:36
string file_name
Definition: Particles2023AnalysisHung.py:321
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
list x
Definition: plotDoE.py:28
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2