oomph::GS< CRDoubleMatrix > Class Reference

#include <iterative_linear_solver.h>

+ Inheritance diagram for oomph::GS< CRDoubleMatrix >:

Public Member Functions

 GS ()
 Constructor. More...
 
virtual ~GS ()
 Destructor (cleanup storage) More...
 
 GS (const GS &)=delete
 Broken copy constructor. More...
 
void operator= (const GS &)=delete
 Broken assignment operator. More...
 
void smoother_solve (const DoubleVector &rhs, DoubleVector &result)
 
void disable_resolve ()
 Overload disable resolve so that it cleans up memory too. More...
 
void smoother_setup (DoubleMatrixBase *matrix_pt)
 Set up the smoother for the matrix specified by the pointer. More...
 
void setup_helper (DoubleMatrixBase *matrix_pt)
 
void solve (Problem *const &problem_pt, DoubleVector &result)
 
void solve (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
 
void solve (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
void resolve (const DoubleVector &rhs, DoubleVector &result)
 
double preconditioner_setup_time () const
 Returns the time taken to set up the preconditioner. More...
 
unsigned iterations () const
 Number of iterations taken. More...
 
- Public Member Functions inherited from oomph::Smoother
 Smoother ()
 Empty constructor. More...
 
virtual ~Smoother ()
 Virtual empty destructor. More...
 
template<typename MATRIX >
void check_validity_of_solve_helper_inputs (MATRIX *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution, const double &n_dof)
 
- Public Member Functions inherited from oomph::IterativeLinearSolver
 IterativeLinearSolver ()
 
 IterativeLinearSolver (const IterativeLinearSolver &)=delete
 Broken copy constructor. More...
 
void operator= (const IterativeLinearSolver &)=delete
 Broken assignment operator. More...
 
virtual ~IterativeLinearSolver ()
 Destructor (empty) More...
 
Preconditioner *& preconditioner_pt ()
 Access function to preconditioner. More...
 
Preconditioner *const & preconditioner_pt () const
 Access function to preconditioner (const version) More...
 
doubletolerance ()
 Access to convergence tolerance. More...
 
unsignedmax_iter ()
 Access to max. number of iterations. More...
 
void enable_doc_convergence_history ()
 Enable documentation of the convergence history. More...
 
void disable_doc_convergence_history ()
 Disable documentation of the convergence history. More...
 
void open_convergence_history_file_stream (const std::string &file_name, const std::string &zone_title="")
 
void close_convergence_history_file_stream ()
 Close convergence history output stream. More...
 
double jacobian_setup_time () const
 
double linear_solver_solution_time () const
 return the time taken to solve the linear system More...
 
void enable_setup_preconditioner_before_solve ()
 Setup the preconditioner before the solve. More...
 
void disable_setup_preconditioner_before_solve ()
 Don't set up the preconditioner before the solve. More...
 
void enable_error_after_max_iter ()
 Throw an error if we don't converge within max_iter. More...
 
void disable_error_after_max_iter ()
 Don't throw an error if we don't converge within max_iter (default). More...
 
void enable_iterative_solver_as_preconditioner ()
 
void disable_iterative_solver_as_preconditioner ()
 
- Public Member Functions inherited from oomph::LinearSolver
 LinearSolver ()
 Empty constructor, initialise the member data. More...
 
 LinearSolver (const LinearSolver &dummy)=delete
 Broken copy constructor. More...
 
void operator= (const LinearSolver &)=delete
 Broken assignment operator. More...
 
virtual ~LinearSolver ()
 Empty virtual destructor. More...
 
void enable_doc_time ()
 Enable documentation of solve times. More...
 
void disable_doc_time ()
 Disable documentation of solve times. More...
 
bool is_doc_time_enabled () const
 Is documentation of solve times enabled? More...
 
bool is_resolve_enabled () const
 Boolean flag indicating if resolves are enabled. More...
 
virtual void enable_resolve ()
 
virtual void solve_transpose (Problem *const &problem_pt, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &result)
 
virtual void solve_transpose (DoubleMatrixBase *const &matrix_pt, const Vector< double > &rhs, Vector< double > &result)
 
virtual void resolve_transpose (const DoubleVector &rhs, DoubleVector &result)
 
virtual void enable_computation_of_gradient ()
 
void disable_computation_of_gradient ()
 
void reset_gradient ()
 
void get_gradient (DoubleVector &gradient)
 function to access the gradient, provided it has been computed More...
 
- Public Member Functions inherited from oomph::DistributableLinearAlgebraObject
 DistributableLinearAlgebraObject ()
 Default constructor - create a distribution. More...
 
 DistributableLinearAlgebraObject (const DistributableLinearAlgebraObject &matrix)=delete
 Broken copy constructor. More...
 
void operator= (const DistributableLinearAlgebraObject &)=delete
 Broken assignment operator. More...
 
virtual ~DistributableLinearAlgebraObject ()
 Destructor. More...
 
LinearAlgebraDistributiondistribution_pt () const
 access to the LinearAlgebraDistribution More...
 
unsigned nrow () const
 access function to the number of global rows. More...
 
unsigned nrow_local () const
 access function for the num of local rows on this processor. More...
 
unsigned nrow_local (const unsigned &p) const
 access function for the num of local rows on this processor. More...
 
unsigned first_row () const
 access function for the first row on this processor More...
 
unsigned first_row (const unsigned &p) const
 access function for the first row on this processor More...
 
bool distributed () const
 distribution is serial or distributed More...
 
bool distribution_built () const
 
void build_distribution (const LinearAlgebraDistribution *const dist_pt)
 
void build_distribution (const LinearAlgebraDistribution &dist)
 

Private Member Functions

void solve_helper (DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
 General interface to solve function. More...
 
void clean_up_memory ()
 Clean up data that's stored for resolve (if any has been stored) More...
 

Private Attributes

CRDoubleMatrixMatrix_pt
 System matrix pointer in the format specified by the template argument. More...
 
unsigned Iterations
 Number of iterations taken. More...
 
bool Resolving
 
bool Matrix_can_be_deleted
 
Vector< intIndex_of_diagonal_entries
 

Additional Inherited Members

- Protected Member Functions inherited from oomph::DistributableLinearAlgebraObject
void clear_distribution ()
 
- Protected Attributes inherited from oomph::Smoother
bool Use_as_smoother
 
- Protected Attributes inherited from oomph::IterativeLinearSolver
bool Doc_convergence_history
 
std::ofstream Output_file_stream
 Output file stream for convergence history. More...
 
double Tolerance
 Convergence tolerance. More...
 
unsigned Max_iter
 Maximum number of iterations. More...
 
PreconditionerPreconditioner_pt
 Pointer to the preconditioner. More...
 
double Jacobian_setup_time
 Jacobian setup time. More...
 
double Solution_time
 linear solver solution time More...
 
double Preconditioner_setup_time
 Preconditioner setup time. More...
 
bool Setup_preconditioner_before_solve
 
bool Throw_error_after_max_iter
 
bool Use_iterative_solver_as_preconditioner
 Use the iterative solver as preconditioner. More...
 
bool First_time_solve_when_used_as_preconditioner
 
- Protected Attributes inherited from oomph::LinearSolver
bool Enable_resolve
 
bool Doc_time
 Boolean flag that indicates whether the time taken. More...
 
bool Compute_gradient
 
bool Gradient_has_been_computed
 flag that indicates whether the gradient was computed or not More...
 
DoubleVector Gradient_for_glob_conv_newton_solve
 
- Static Protected Attributes inherited from oomph::IterativeLinearSolver
static IdentityPreconditioner Default_preconditioner
 

Detailed Description

//////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// Explicit template specialisation of the Gauss Seidel method for compressed row format matrices

Constructor & Destructor Documentation

◆ GS() [1/2]

oomph::GS< CRDoubleMatrix >::GS ( )
inline

Constructor.

789  : Matrix_pt(0),
790  Iterations(0),
791  Resolving(false),
793  {
794  }
unsigned Iterations
Number of iterations taken.
Definition: iterative_linear_solver.h:976
bool Matrix_can_be_deleted
Definition: iterative_linear_solver.h:984
CRDoubleMatrix * Matrix_pt
System matrix pointer in the format specified by the template argument.
Definition: iterative_linear_solver.h:973
bool Resolving
Definition: iterative_linear_solver.h:980

◆ ~GS()

virtual oomph::GS< CRDoubleMatrix >::~GS ( )
inlinevirtual

Destructor (cleanup storage)

798  {
799  clean_up_memory();
800  }
void clean_up_memory()
Clean up data that's stored for resolve (if any has been stored)
Definition: iterative_linear_solver.h:958

References oomph::GS< MATRIX >::clean_up_memory().

◆ GS() [2/2]

oomph::GS< CRDoubleMatrix >::GS ( const GS< CRDoubleMatrix > &  )
delete

Broken copy constructor.

Member Function Documentation

◆ clean_up_memory()

void oomph::GS< CRDoubleMatrix >::clean_up_memory ( )
inlineprivatevirtual

Clean up data that's stored for resolve (if any has been stored)

Reimplemented from oomph::LinearSolver.

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

References oomph::GS< MATRIX >::Matrix_can_be_deleted, and oomph::GS< MATRIX >::Matrix_pt.

◆ disable_resolve()

void oomph::GS< CRDoubleMatrix >::disable_resolve ( )
inlinevirtual

Overload disable resolve so that it cleans up memory too.

Reimplemented from oomph::LinearSolver.

823  {
825  clean_up_memory();
826  } // End of disable_resolve
virtual void disable_resolve()
Definition: linear_solver.h:144

References oomph::GS< MATRIX >::clean_up_memory(), and oomph::LinearSolver::disable_resolve().

◆ iterations()

unsigned oomph::GS< CRDoubleMatrix >::iterations ( ) const
inlinevirtual

Number of iterations taken.

Implements oomph::IterativeLinearSolver.

946  {
947  // Return the number of iterations
948  return Iterations;
949  } // End of iterations

References oomph::GS< MATRIX >::Iterations.

◆ operator=()

void oomph::GS< CRDoubleMatrix >::operator= ( const GS< CRDoubleMatrix > &  )
delete

Broken assignment operator.

◆ preconditioner_setup_time()

double oomph::GS< CRDoubleMatrix >::preconditioner_setup_time ( ) const
inlinevirtual

Returns the time taken to set up the preconditioner.

Reimplemented from oomph::IterativeLinearSolver.

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
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
#define OOMPH_EXCEPTION_LOCATION
Definition: oomph_definitions.h:61
#define OOMPH_CURRENT_FUNCTION
Definition: oomph_definitions.h:86

References OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, and oomph::Global_string_for_annotation::string().

◆ resolve()

void oomph::GS< CRDoubleMatrix >::resolve ( const DoubleVector rhs,
DoubleVector result 
)
inlinevirtual

Re-solve the system defined by the last assembled Jacobian and the rhs vector specified here. Solution is returned in the vector result.

Reimplemented from oomph::LinearSolver.

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
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: iterative_linear_solver.cc:1362

References oomph::GS< MATRIX >::Matrix_pt, OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::GS< MATRIX >::Resolving, and oomph::GS< MATRIX >::solve().

◆ setup_helper()

void oomph::GS< CRDoubleMatrix >::setup_helper ( DoubleMatrixBase matrix_pt)

Generic setup function to sort out everything that needs to be set up with regards to the input matrix

Explicit template specialisation of the smoother_setup function for CR matrices. Set up the smoother for the matrix specified by the pointer. This definition of the smoother_setup has the added functionality that it sorts the entries in the given matrix so that the CRDoubleMatrix implementation of the solver can be used.

1436  {
1437  // Assume the matrix has been passed in from the outside so we must
1438  // not delete it. This is needed to avoid pre- and post-smoothers
1439  // deleting the same matrix in the MG solver. If this was originally
1440  // set to TRUE then this will be sorted out in the other functions
1441  // from which this was called
1442  Matrix_can_be_deleted = false;
1443 
1444  // Upcast the input matrix to system matrix to the type MATRIX
1445  Matrix_pt = dynamic_cast<CRDoubleMatrix*>(matrix_pt);
1446 
1447  // The system matrix here is a CRDoubleMatrix. To make use of the
1448  // specific implementation of the solver for this type of matrix we
1449  // need to make sure the entries are arranged correctly
1451 
1452  // Now get access to the vector Index_of_diagonal_entries
1454 
1455 #ifdef PARANOID
1456  // Create a boolean variable to store the result of whether or not
1457  // the entries are in the correct order
1458  bool is_matrix_sorted = true;
1459 
1460  // Check to make sure the entries have been sorted properly
1461  is_matrix_sorted = Matrix_pt->entries_are_sorted();
1462 
1463  // If the entries are not sorted properly
1464  if (!is_matrix_sorted)
1465  {
1466  // Throw an error; the solver won't work unless the matrix is sorted
1467  // properly
1468  throw OomphLibError("Matrix is not sorted correctly",
1471  }
1472 #endif
1473  } // End of setup_helper
void sort_entries()
Definition: matrices.cc:1449
const Vector< int > get_index_of_diagonal_entries() const
Definition: matrices.h:920
bool entries_are_sorted(const bool &doc_unordered_entries=false) const
Definition: matrices.cc:1366
Vector< int > Index_of_diagonal_entries
Definition: iterative_linear_solver.h:988

References oomph::GS< MATRIX >::Matrix_can_be_deleted, oomph::GS< MATRIX >::Matrix_pt, OOMPH_CURRENT_FUNCTION, and OOMPH_EXCEPTION_LOCATION.

◆ smoother_setup()

void oomph::GS< CRDoubleMatrix >::smoother_setup ( DoubleMatrixBase matrix_pt)
inlinevirtual

Set up the smoother for the matrix specified by the pointer.

Implements oomph::Smoother.

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
void setup_helper(DoubleMatrixBase *matrix_pt)
Definition: iterative_linear_solver.cc:1435

References oomph::GS< MATRIX >::Matrix_can_be_deleted.

◆ smoother_solve()

void oomph::GS< CRDoubleMatrix >::smoother_solve ( const DoubleVector rhs,
DoubleVector result 
)
inlinevirtual

The smoother_solve function performs fixed number of iterations on the system A*result=rhs. The number of (smoothing) iterations is the same as the max. number of iterations in the underlying IterativeLinearSolver class.

Implements oomph::Smoother.

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
void solve_helper(DoubleMatrixBase *const &matrix_pt, const DoubleVector &rhs, DoubleVector &solution)
General interface to solve function.
Definition: iterative_linear_solver.cc:1480
bool Use_as_smoother
Definition: iterative_linear_solver.h:585

References oomph::GS< MATRIX >::Matrix_pt, oomph::GS< MATRIX >::solve_helper(), and oomph::Smoother::Use_as_smoother.

◆ solve() [1/3]

void oomph::GS< CRDoubleMatrix >::solve ( DoubleMatrixBase *const &  matrix_pt,
const DoubleVector rhs,
DoubleVector solution 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system.

Reimplemented from oomph::LinearSolver.

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
void build_distribution(const LinearAlgebraDistribution *const dist_pt)
Definition: linear_algebra_distribution.h:507
bool Enable_resolve
Definition: linear_solver.h:73
void solution(const Vector< double > &x, Vector< double > &u)
Definition: two_d_biharmonic.cc:113

References oomph::DistributableLinearAlgebraObject::build_distribution(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::LinearSolver::Enable_resolve, oomph::GS< MATRIX >::Matrix_can_be_deleted, oomph::GS< MATRIX >::Matrix_pt, oomph::GS< MATRIX >::Resolving, BiharmonicTestFunctions1::solution(), oomph::GS< MATRIX >::solve_helper(), and oomph::Smoother::Use_as_smoother.

◆ solve() [2/3]

void oomph::GS< CRDoubleMatrix >::solve ( DoubleMatrixBase *const &  matrix_pt,
const Vector< double > &  rhs,
Vector< double > &  result 
)
inlinevirtual

Linear-algebra-type solver: Takes pointer to a matrix and rhs vector and returns the solution of the linear system Call the broken base-class version. If you want this, please implement it

Reimplemented from oomph::LinearSolver.

899  {
900  LinearSolver::solve(matrix_pt, rhs, result);
901  } // End of solve
virtual void solve(Problem *const &problem_pt, DoubleVector &result)=0

References oomph::LinearSolver::solve().

◆ solve() [3/3]

void oomph::GS< CRDoubleMatrix >::solve ( Problem *const &  problem_pt,
DoubleVector result 
)
virtual

Solver: Takes pointer to problem and returns the results vector which contains the solution of the linear system defined by the problem's fully assembled Jacobian and residual vector.

//////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////// Explicit template specialisation of the solver for CR matrices: Takes pointer to problem and returns the results vector which contains the solution of the linear system defined by the problem's fully assembled Jacobian and residual vector.

Implements oomph::LinearSolver.

1364  {
1365  // Reset the Use_as_smoother_flag as the solver is not being used
1366  // as a smoother
1367  Use_as_smoother = false;
1368 
1369  // Find # of degrees of freedom (variables)
1370  unsigned n_dof = problem_pt->ndof();
1371 
1372  // Initialise timer
1373  double t_start = TimingHelpers::timer();
1374 
1375  // We're not re-solving
1376  Resolving = false;
1377 
1378  // Get rid of any previously stored data
1379  clean_up_memory();
1380 
1381  // Set up the distribution
1382  LinearAlgebraDistribution dist(problem_pt->communicator_pt(), n_dof, false);
1383 
1384  // Build the distribution of the LinearSolver
1385  this->build_distribution(dist);
1386 
1387  // Allocate space for the Jacobian matrix in CRDoubleMatrix format
1388  Matrix_pt = new CRDoubleMatrix;
1389 
1390  // Build the matrix
1391  Matrix_pt->build(this->distribution_pt());
1392 
1393  // Allocate space for the residuals vector
1394  DoubleVector f;
1395 
1396  // Build it
1397  f.build(this->distribution_pt(), 0.0);
1398 
1399  // Get the global Jacobian and the accompanying residuals vector
1400  problem_pt->get_jacobian(f, *Matrix_pt);
1401 
1402  // Doc. time for setup
1403  double t_end = TimingHelpers::timer();
1404  Jacobian_setup_time = t_end - t_start;
1405 
1406  // Run the generic setup function
1408 
1409  // We've made the matrix, we can delete it...
1410  Matrix_can_be_deleted = true;
1411 
1412  // If time documentation is enabled
1413  if (Doc_time)
1414  {
1415  // Output the time for the assembly of the Jacobian to screen
1416  oomph_info << "Time for setup of Jacobian [sec]: " << Jacobian_setup_time
1417  << std::endl;
1418  }
1419 
1420  // Call linear algebra-style solver
1421  solve_helper(Matrix_pt, f, result);
1422 
1423  // Kill matrix unless it's still required for resolve
1425  } // End of solve
std::vector< double > DoubleVector
loads clump configuration
Definition: ClumpInput.h:26
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
Definition: matrices.cc:1672
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
double Jacobian_setup_time
Jacobian setup time.
Definition: iterative_linear_solver.h:248
bool Doc_time
Boolean flag that indicates whether the time taken.
Definition: linear_solver.h:77
static int f(const TensorMap< Tensor< int, 3 > > &tensor)
Definition: cxx11_tensor_map.cpp:237
double timer()
returns the time in seconds after some point in past
Definition: oomph_utilities.cc:1295
OomphInfo oomph_info
Definition: oomph_definitions.cc:319

References oomph::DistributableLinearAlgebraObject::build_distribution(), oomph::GS< MATRIX >::clean_up_memory(), oomph::Problem::communicator_pt(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::LinearSolver::Doc_time, oomph::LinearSolver::Enable_resolve, f(), oomph::Problem::get_jacobian(), oomph::IterativeLinearSolver::Jacobian_setup_time, oomph::GS< MATRIX >::Matrix_can_be_deleted, oomph::GS< MATRIX >::Matrix_pt, oomph::Problem::ndof(), oomph::oomph_info, oomph::GS< MATRIX >::Resolving, oomph::GS< MATRIX >::solve_helper(), oomph::TimingHelpers::timer(), and oomph::Smoother::Use_as_smoother.

◆ solve_helper()

void oomph::GS< CRDoubleMatrix >::solve_helper ( DoubleMatrixBase *const &  matrix_pt,
const DoubleVector rhs,
DoubleVector solution 
)
private

General interface to solve function.

Explicit template specialisation of the solve_helper function for CR matrices. Exploiting the sparsity of the given matrix allows for a much faster iterative solver.

1483  {
1484  // Get number of dofs
1485  unsigned n_dof = rhs.nrow();
1486 
1487 #ifdef PARANOID
1488  // Upcast the matrix to the appropriate type
1489  CRDoubleMatrix* cr_matrix_pt = dynamic_cast<CRDoubleMatrix*>(matrix_pt);
1490 
1491  // PARANOID Run the self-tests to check the inputs are correct
1492  this->check_validity_of_solve_helper_inputs<CRDoubleMatrix>(
1493  cr_matrix_pt, rhs, solution, n_dof);
1494 
1495  // We don't need the pointer any more but we do still need the matrix
1496  // so just make tmp_matrix_pt a null pointer
1497  cr_matrix_pt = 0;
1498 #endif
1499 
1500  // Setup the solution if it is not
1501  if (!solution.distribution_pt()->built())
1502  {
1503  solution.build(this->distribution_pt(), 0.0);
1504  }
1505  // If the solution is already set up
1506  else
1507  {
1508  // If we're inside the multigrid solver then as we traverse up the
1509  // hierarchy we use the smoother on the updated approximate solution.
1510  // As such, we should ONLY be resetting all the values to zero if
1511  // we're NOT inside the multigrid solver
1512  if (!Use_as_smoother)
1513  {
1514  // Initialise the vector with all entries set to zero
1515  solution.initialise(0.0);
1516  }
1517  } // if (!solution.distribution_pt()->built())
1518 
1519  // Initialise timer
1520  double t_start = TimingHelpers::timer();
1521 
1522  // Copy the solution vector into x
1524 
1525  // Create a vector to hold the residual. This will only be built if
1526  // we're not inside the multigrid solver
1527  DoubleVector current_residual;
1528 
1529  // Variable to hold the current residual norm. Only used if we're
1530  // not inside the multigrid solver
1531  double norm_res = 0.0;
1532 
1533  // Variables to hold the initial residual norm. Only used if we're
1534  // not inside the multigrid solver
1535  double norm_f = 0.0;
1536 
1537  // Initialise the value of Iterations
1538  Iterations = 0;
1539 
1540  // Calculate the residual only if we're not inside the multigrid solver
1541  if (!Use_as_smoother)
1542  {
1543  // Build the residual vector
1544  current_residual.build(this->distribution_pt(), 0.0);
1545 
1546  // Calculate the residual r=b-Ax
1547  matrix_pt->residual(x, rhs, current_residual);
1548 
1549  // Calculate the 2-norm of the residual vector
1550  norm_res = current_residual.norm();
1551 
1552  // Store the initial norm
1553  norm_f = norm_res;
1554 
1555  // If required will document convergence history to screen
1556  // or file (if stream is open)
1558  {
1559  if (!Output_file_stream.is_open())
1560  {
1561  oomph_info << Iterations << " " << norm_res << std::endl;
1562  }
1563  else
1564  {
1565  Output_file_stream << Iterations << " " << norm_res << std::endl;
1566  }
1567  } // if (!Use_as_smoother)
1568  } // if (Doc_convergence_history)
1569 
1570  // In each iteration of Gauss-Seidel we need to calculate
1571  // x_new=-inv(L+D)*U*x_old+inv(L+D)*rhs,
1572  // where L represents the strict lower triangular portion of A,
1573  // D represents the diagonal of A and U represents the strict upper
1574  // triangular portion of A. Since the value of inv(L+D)*rhs remains
1575  // constant throughout we shall calculate it now and store it to
1576  // avoid calculating it again with each iteration.
1577 
1578  // Create a temporary matrix pointer to allow for the extraction of the
1579  // row start, column index and value pointers
1580  CRDoubleMatrix* tmp_matrix_pt = dynamic_cast<CRDoubleMatrix*>(matrix_pt);
1581 
1582  // First acquire access to the value, row_start and column_index arrays
1583  // from the compressed row matrix
1584  const double* value_pt = tmp_matrix_pt->value();
1585  const int* row_start_pt = tmp_matrix_pt->row_start();
1586  const int* column_index_pt = tmp_matrix_pt->column_index();
1587 
1588  // We've finished using the temporary matrix pointer so make it a null
1589  // pointer
1590  tmp_matrix_pt = 0;
1591 
1592  // We can only calculate this constant term if the diagonal entries
1593  // of the matrix are nonzero so we check this first
1594  for (unsigned i = 0; i < n_dof; i++)
1595  {
1596  // Get the index of the last entry below or on the diagonal in row i
1597  unsigned diag_index = Index_of_diagonal_entries[i];
1598 
1599  if (unsigned(*(column_index_pt + diag_index)) != i)
1600  {
1601  std::string err_strng = "Gauss-Seidel cannot operate on a matrix with ";
1602  err_strng += "zero diagonal entries.";
1603  throw OomphLibError(
1605  }
1606  } // for (unsigned i=0;i<n_dof;i++)
1607 
1608  // If there were no zero diagonal entries we can calculate the vector
1609  // constant_term=inv(L+D)*rhs.
1610 
1611  // Create a vector to hold the constant term in the iteration
1612  DoubleVector constant_term(this->distribution_pt(), 0.0);
1613 
1614  // Copy the entries of rhs into the vector, constant_term
1615  constant_term = rhs;
1616 
1617  // Start by looping over the rows of constant_term
1618  for (unsigned i = 0; i < n_dof; i++)
1619  {
1620  // Get the index of the last entry below or on the diagonal in row i
1621  unsigned diag_index = Index_of_diagonal_entries[i];
1622 
1623  // Get the index of the first entry in row i
1624  unsigned row_i_start = *(row_start_pt + i);
1625 
1626  // If there are entries strictly below the diagonal then the
1627  // column index of the first entry in the i-th row cannot be
1628  // i (since we have ensured that nonzero entries exist on the
1629  // diagonal so this is the largest the column index of the
1630  // first entry in this row could be)
1631  if (unsigned(*(column_index_pt + row_i_start)) != i)
1632  {
1633  // Initialise the column index variable
1634  unsigned column_index = 0;
1635 
1636  // Loop over the entries below the diagonal on row i
1637  for (unsigned j = row_i_start; j < diag_index; j++)
1638  {
1639  // Find the column index of this nonzero entry
1640  column_index = *(column_index_pt + j);
1641 
1642  // Subtract the value of A(i,j)*constant_term(j) (where j<i)
1643  constant_term[i] -= (*(value_pt + j)) * constant_term[column_index];
1644  }
1645  } // if (*(column_index_pt+row_i_start)!=i)
1646 
1647  // Finish off by calculating constant_term(i)/A(i,i)
1648  constant_term[i] /= *(value_pt + diag_index);
1649  } // for (unsigned i=0;i<n_dof;i++)
1650 
1651  // Build a temporary vector to store the value of A*x with each iteration
1652  DoubleVector temp_vec(this->distribution_pt(), 0.0);
1653 
1654  // Outermost loop: Run max_iter times (the iteration number)
1655  for (unsigned iter_num = 0; iter_num < Max_iter; iter_num++)
1656  {
1657  // With each iteration we need to calculate
1658  // x_new=-inv(L+D)*U*x_old+inv(L+D)*rhs,
1659  // =-inv(L+D)*U*x_old+constant_term.
1660  // Since we've already calculated the vector constant_term, it remains
1661  // for us to calculate inv(L+D)*U*x. To do this we break the calculation
1662  // into two parts:
1663  // (1) The matrix-vector multiplication temp_vec=U*x, and;
1664  // (2) The matrix-vector multiplication inv(L+D)*temp_vec.
1665 
1666  //------------------------------
1667  // (1) Calculating temp_vec=U*x:
1668  //------------------------------
1669 
1670  // Auxiliary variable to store the index of the first entry on the
1671  // upper triangular portion of the matrix
1672  unsigned upper_tri_start = 0;
1673 
1674  // Auxiliary variable to store the index of the first entry in the
1675  // next row
1676  unsigned next_row_start = 0;
1677 
1678  // Set the temporary vector temp_vec to be initially be the zero vector
1679  temp_vec.initialise(0.0);
1680 
1681  // Loop over the rows of temp_vec (note: we do not loop over the final
1682  // row since all the entries on the last row of a strict upper triangular
1683  // matrix are zero)
1684  for (unsigned i = 0; i < n_dof - 1; i++)
1685  {
1686  // Get the index of the first entry on the upper triangular portion of
1687  // the matrix noting that the i-th entry in Index_of_diagonal_entries
1688  // will store the index of the diagonal entry of the i-th row
1689  upper_tri_start = Index_of_diagonal_entries[i] + 1;
1690 
1691  // Get the index of the first entry in the next row
1692  next_row_start = *(row_start_pt + i + 1);
1693 
1694  // Variable to store the column index of each entry
1695  unsigned column_index = 0;
1696 
1697  // Loop over all of the entries above the diagonal
1698  for (unsigned j = upper_tri_start; j < next_row_start; j++)
1699  {
1700  // Get the column index of this entry
1701  column_index = *(column_index_pt + j);
1702 
1703  // Update the value of temp_vec[i] by adding A(i,j)*x(j) (where j>i)
1704  temp_vec[i] += (*(value_pt + j)) * x[column_index];
1705  }
1706  } // for (unsigned i=0;i<n_dof;i++)
1707 
1708  //-----------------------------------
1709  // (2) Calculating inv(L+D)*temp_vec:
1710  //-----------------------------------
1711 
1712  // Now U*x=temp_vec has been calculated we need to calculate the vector
1713  // y=inv(L+D)*U*x=inv(L+D)*temp_vec.
1714  // Note: the i-th entry in y is given by
1715  // y(i)=(temp_vec(i)-\sum_{j=0}^{i-1}A(i,j)*y(j))/A(i,i).
1716  // We can see from this that to calculate the current entry in y we
1717  // use its previously calculated entries and the current entry in
1718  // temp_vec. As a result, we do not need two separate vectors y and
1719  // temp_vec for this calculation. Instead, we can just update the
1720  // entries in temp_vec (carefully!) using:
1721  // temp_vec(i)=(temp_vec(i)-\sum_{j=0}^{i-1}A(i,j)*temp_vec(j))/A(i,i).
1722 
1723  // Start by looping over the rows of rhs
1724  for (unsigned i = 0; i < n_dof; i++)
1725  {
1726  // Get the index of the last entry below or on the diagonal in row i
1727  unsigned diag_index = Index_of_diagonal_entries[i];
1728 
1729  // Get the index of the first entry in row i
1730  unsigned row_i_start = *(row_start_pt + i);
1731 
1732  // If there are no entries strictly below the diagonal then the
1733  // column index of the first entry in the i-th row will be greater
1734  // than or equal to i
1735  if (unsigned(*(column_index_pt + row_i_start)) != i)
1736  {
1737  // Initialise the column index variable
1738  unsigned column_index = 0;
1739 
1740  // Loop over the entries below the diagonal
1741  for (unsigned j = row_i_start; j < diag_index; j++)
1742  {
1743  // Find the column index of this nonzero entry
1744  column_index = *(column_index_pt + j);
1745 
1746  // Subtract the value of A(i,j)*y(j) (where j<i)
1747  temp_vec[i] -= (*(value_pt + j)) * temp_vec[column_index];
1748  }
1749  } // if (*(column_index_pt+row_i_start)!=i)
1750 
1751  // Finish off by calculating temp_vec(i)/A(i,i)
1752  temp_vec[i] /= *(value_pt + diag_index);
1753  } // for (unsigned i=0;i<n_dof;i++)
1754 
1755  //-------------------------
1756  // Updating the solution x:
1757  //-------------------------
1758 
1759  // The updated solution is given by
1760  // x_new=-inv(L+D)*U*x_old+inv(L+D)*rhs,
1761  // =-temp_vec+constant_term,
1762  // We have calculated both constant_term and temp_vec so we simply
1763  // need to calculate x now
1764 
1765  // Set x to be the vector, constant_term
1766  x = constant_term;
1767 
1768  // Update x to give the next iterate
1769  x -= temp_vec;
1770 
1771  // Increment the value of Iterations
1772  Iterations++;
1773 
1774  // Calculate the residual only if we're not inside the multigrid solver
1775  if (!Use_as_smoother)
1776  {
1777  // Get residual
1778  matrix_pt->residual(x, rhs, current_residual);
1779 
1780  // Calculate the relative residual norm (i.e.
1781  // \frac{\|r_{i}\|}{\|r_{0}\|})
1782  norm_res = current_residual.norm() / norm_f;
1783 
1784  // If required will document convergence history to screen or file (if
1785  // stream open)
1787  {
1788  if (!Output_file_stream.is_open())
1789  {
1790  oomph_info << iter_num << " " << norm_res << std::endl;
1791  }
1792  else
1793  {
1794  Output_file_stream << iter_num << " " << norm_res << std::endl;
1795  }
1796  } // if (Doc_convergence_history)
1797 
1798  // Check the tolerance only if the residual norm is being computed
1799  if (norm_res < Tolerance)
1800  {
1801  // Break out of the for-loop
1802  break;
1803  }
1804  } // if (!Use_as_smoother)
1805  } // for (unsigned iter_num=0;iter_num<max_iter;iter_num++)
1806 
1807  // Calculate the residual only if we're not inside the multigrid solver
1808  if (!Use_as_smoother)
1809  {
1810  // If time documentation is enabled
1811  if (Doc_time)
1812  {
1813  oomph_info << "\nGS converged. Residual norm: " << norm_res
1814  << "\nNumber of iterations to convergence: " << Iterations
1815  << "\n"
1816  << std::endl;
1817  }
1818  } // if (!Use_as_smoother)
1819 
1820  // Copy the solution into the solution vector
1821  solution = x;
1822 
1823  // Document the time for the solver
1824  double t_end = TimingHelpers::timer();
1825  Solution_time = t_end - t_start;
1826 
1827  // If time documentation is enabled
1828  if (Doc_time)
1829  {
1830  oomph_info << "Time for solve with Gauss-Seidel [sec]: " << Solution_time
1831  << std::endl;
1832  }
1833 
1834  // If the solver failed to converge and the user asked for an error if
1835  // this happened
1837  {
1838  std::string error_message =
1839  "Solver failed to converge and you requested ";
1840  error_message += "an error on convergence failures.";
1841  throw OomphLibError(
1843  }
1844  } // End of solve_helper
int i
Definition: BiCGSTAB_step_by_step.cpp:9
double Tolerance
Convergence tolerance.
Definition: iterative_linear_solver.h:239
bool Throw_error_after_max_iter
Definition: iterative_linear_solver.h:262
unsigned Max_iter
Maximum number of iterations.
Definition: iterative_linear_solver.h:242
double Solution_time
linear solver solution time
Definition: iterative_linear_solver.h:251
std::ofstream Output_file_stream
Output file stream for convergence history.
Definition: iterative_linear_solver.h:231
bool Doc_convergence_history
Definition: iterative_linear_solver.h:228
list x
Definition: plotDoE.py:28
std::ptrdiff_t j
Definition: tut_arithmetic_redux_minmax.cpp:2

References oomph::DoubleVector::build(), oomph::CRDoubleMatrix::column_index(), oomph::DistributableLinearAlgebraObject::distribution_pt(), oomph::IterativeLinearSolver::Doc_convergence_history, oomph::LinearSolver::Doc_time, i, oomph::DoubleVector::initialise(), oomph::GS< MATRIX >::Iterations, j, oomph::IterativeLinearSolver::Max_iter, oomph::DoubleVector::norm(), oomph::DistributableLinearAlgebraObject::nrow(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION, oomph::oomph_info, oomph::IterativeLinearSolver::Output_file_stream, oomph::DoubleMatrixBase::residual(), oomph::CRDoubleMatrix::row_start(), BiharmonicTestFunctions1::solution(), oomph::IterativeLinearSolver::Solution_time, oomph::Global_string_for_annotation::string(), oomph::IterativeLinearSolver::Throw_error_after_max_iter, oomph::TimingHelpers::timer(), oomph::IterativeLinearSolver::Tolerance, oomph::Smoother::Use_as_smoother, oomph::CRDoubleMatrix::value(), and plotDoE::x.

Member Data Documentation

◆ Index_of_diagonal_entries

Vector<int> oomph::GS< CRDoubleMatrix >::Index_of_diagonal_entries
private

Vector whose i'th entry contains the index of the last entry below or on the diagonal of the i'th row of the matrix

◆ Iterations

unsigned oomph::GS< CRDoubleMatrix >::Iterations
private

Number of iterations taken.

◆ Matrix_can_be_deleted

bool oomph::GS< CRDoubleMatrix >::Matrix_can_be_deleted
private

Boolean flag to indicate if the matrix pointed to be Matrix_pt can be deleted.

◆ Matrix_pt

CRDoubleMatrix* oomph::GS< CRDoubleMatrix >::Matrix_pt
private

System matrix pointer in the format specified by the template argument.

◆ Resolving

bool oomph::GS< CRDoubleMatrix >::Resolving
private

Boolean flag to indicate if the solve is done in re-solve mode, bypassing setup of matrix and preconditioner


The documentation for this class was generated from the following files: