general_purpose_space_time_subsidiary_block_preconditioner.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 // Header file for SpaceTimeNavierStokes elements
27 #ifndef OOMPH_GENERAL_PURPOSE_SPACE_TIME_SUBSIDIARY_BLOCK_PRECONDITIONER_HEADER
28 #define OOMPH_GENERAL_PURPOSE_SPACE_TIME_SUBSIDIARY_BLOCK_PRECONDITIONER_HEADER
29 
30 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32 #include <oomph-lib-config.h>
33 #endif
34 
35 // oomph-lib includes
38 #include "generic/matrices.h"
39 
43 
44 namespace oomph
45 {
46  //=============================================================================
53  //=============================================================================
55  : public BlockPreconditioner<CRDoubleMatrix>
56  {
57  public:
61  {
62  // By default, don't store the memory statistics of this preconditioner
64 
65  // Initialise the value of Memory_usage_in_bytes
67 
68  // Flag to indicate that the preconditioner has been setup
69  // previously -- if setup() is called again, data can
70  // be wiped.
72 
73  // By default we use SuperLU for both p and f blocks
76 
77  // Set default preconditioners (inexact solvers) -- they are
78  // members of this class!
81 
82  // Null the momentum block matrix-vector product helper
83  F_mat_vec_pt = 0;
84 
85  // Null the gradient block matrix-vector product helper
86  G_mat_vec_pt = 0;
87  }
88 
91  {
92  // Call the auxiliary clean up function
93  this->clean_up_memory();
94  } // End of ~SpaceTimeNavierStokesSubsidiaryPreconditioner
95 
97  virtual void clean_up_memory()
98  {
99  // If we've actually set the preconditioner up
101  {
102  // Delete matvecs
103  delete F_mat_vec_pt;
104  F_mat_vec_pt = 0;
105 
106  delete G_mat_vec_pt;
107  G_mat_vec_pt = 0;
108 
109  // Delete the momentum block solver
110  delete F_preconditioner_pt;
112 
113  // Delete the Schur complement solver
114  delete P_preconditioner_pt;
116  } // if (Preconditioner_has_been_setup)
117  } // End of clean_up_memory
118 
122 
125  delete;
126 
129  using Preconditioner::setup;
130 
132  void setup();
133 
136 
137 
140  {
143  } // End of enable_doc_memory_usage
144 
145 
148  {
151  } // End of disable_doc_memory_usage
152 
153 
156  {
157  // Has the preconditioner even been set up yet?
159  {
160  // Were we meant to compute the statistics?
162  {
163  // Return the appropriate variable value
164  return Memory_usage_in_bytes;
165  }
166  else
167  {
168  // Allocate storage for an output stream
169  std::ostringstream warning_message_stream;
170 
171  // Create a warning message
172  warning_message_stream
173  << "The memory statistics have not been calculated "
174  << "so I'm returning\nthe value zero." << std::endl;
175 
176  // Give the user a warning
177  OomphLibWarning(warning_message_stream.str(),
180 
181  // Return the value zero
182  return 0.0;
183  }
184  }
185  // If the preconditioner hasn't been set up yet
186  else
187  {
188  // Allocate storage for an output stream
189  std::ostringstream warning_message_stream;
190 
191  // Create a warning message
192  warning_message_stream
193  << "The preconditioner hasn't even been set up yet "
194  << "so I'm returning\nthe value zero." << std::endl;
195 
196  // Give the user a warning
197  OomphLibWarning(warning_message_stream.str(),
200 
201  // Return the value zero
202  return 0.0;
203  } // if (Preconditioner_has_been_setup)
204  } // End of get_memory_usage_in_bytes
205 
206  private:
209 
212 
215 
218 
222 
226 
230 
233 
236  };
237 
238 
239  //=============================================================================
243  //=============================================================================
245  : public IterativeLinearSolver,
246  public virtual BlockPreconditioner<CRDoubleMatrix>
247  {
248  public:
252  Matrix_pt(0),
254  Iterations(0),
256  Preconditioner_LHS(false)
257  {
258  // By default, don't store the memory statistics of this preconditioner
260 
261  // Initialise the value of Memory_usage_in_bytes
262  Memory_usage_in_bytes = 0.0;
263  } // End of GMRESBlockPreconditioner
264 
267  {
268  // Call the auxiliary clean up function
269  this->clean_up_memory();
270  } // End of ~GMRESBlockPreconditioner
271 
273  virtual void clean_up_memory()
274  {
275  // If the block preconditioner has been set up previously
277  {
278  // Delete the subsidiary preconditioner
280 
281  // Make it a null pointer
283 
284  // Delete the matrix!
285  delete Matrix_pt;
286 
287  // Make it a null pointer
288  Matrix_pt = 0;
289  }
290  } // End of clean_up_memory
291 
294 
296  void operator=(const GMRESBlockPreconditioner&) = delete;
297 
300  using Preconditioner::setup;
301 
303  void setup();
304 
307 
311  void solve(Problem* const& problem_pt, DoubleVector& result)
312  {
313  // Broken
314  throw OomphLibError("Can't use this interface!",
317  } // End of solve
318 
320  unsigned iterations() const
321  {
322  // Return the number of iterations
323  return Iterations;
324  } // End of iterations
325 
328  {
329  Preconditioner_LHS = true;
330  }
331 
334  {
335  Preconditioner_LHS = false;
336  }
337 
338 
341  {
344  } // End of enable_doc_memory_usage
345 
346 
349  {
352  } // End of disable_doc_memory_usage
353 
354 
357  {
358  // Has the preconditioner even been set up yet?
360  {
361  // Were we meant to compute the statistics?
363  {
364  // Return the appropriate variable value
365  return Memory_usage_in_bytes;
366  }
367  else
368  {
369  // Allocate storage for an output stream
370  std::ostringstream warning_message_stream;
371 
372  // Create a warning message
373  warning_message_stream
374  << "The memory statistics have not been calculated "
375  << "so I'm returning\nthe value zero." << std::endl;
376 
377  // Give the user a warning
378  OomphLibWarning(warning_message_stream.str(),
381 
382  // Return the value zero
383  return 0.0;
384  }
385  }
386  // If the preconditioner hasn't been set up yet
387  else
388  {
389  // Allocate storage for an output stream
390  std::ostringstream warning_message_stream;
391 
392  // Create a warning message
393  warning_message_stream
394  << "The preconditioner hasn't even been set up yet "
395  << "so I'm returning\nthe value zero." << std::endl;
396 
397  // Give the user a warning
398  OomphLibWarning(warning_message_stream.str(),
401 
402  // Return the value zero
403  return 0.0;
404  } // if (Preconditioner_has_been_setup)
405  } // End of get_memory_usage_in_bytes
406 
407 
411  const
412  {
413  // Return a pointer to the appropriate member data
415  } // End of navier_stokes_subsidiary_preconditioner_pt
416 
417  private:
420  void update(const unsigned& k,
421  const Vector<Vector<double>>& H,
422  const Vector<double>& s,
423  const Vector<DoubleVector>& v,
424  const DoubleVector& block_x_with_size_of_full_x,
425  DoubleVector& x)
426  {
427  // Make a local copy of s
428  Vector<double> y(s);
429 
430  // Backsolve:
431  for (int i = int(k); i >= 0; i--)
432  {
433  // Divide the i-th entry of y by the i-th diagonal entry of H
434  y[i] /= H[i][i];
435 
436  // Loop over the previous values of y and update
437  for (int j = i - 1; j >= 0; j--)
438  {
439  // Update the j-th entry of y
440  y[j] -= H[i][j] * y[i];
441  }
442  } // for (int i=int(k);i>=0;i--)
443 
444  // Store the number of rows in the result vector
445  unsigned n_x = x.nrow();
446 
447  // Build a temporary vector with entries initialised to 0.0
448  DoubleVector temp(x.distribution_pt(), 0.0);
449 
450  // Build a temporary vector with entries initialised to 0.0
451  DoubleVector z(x.distribution_pt(), 0.0);
452 
453  // Get access to the underlying values
454  double* temp_pt = temp.values_pt();
455 
456  // Calculate x=Vy
457  for (unsigned j = 0; j <= k; j++)
458  {
459  // Get access to j-th column of v
460  const double* vj_pt = v[j].values_pt();
461 
462  // Loop over the entries of the vector, temp
463  for (unsigned i = 0; i < n_x; i++)
464  {
465  temp_pt[i] += vj_pt[i] * y[j];
466  }
467  } // for (unsigned j=0;j<=k;j++)
468 
469  // If we're using LHS preconditioning
470  if (Preconditioner_LHS)
471  {
472  // Since we're using LHS preconditioning the preconditioner is applied
473  // to the matrix and RHS vector so we simply update the value of x
474  x += temp;
475  }
476  // If we're using RHS preconditioning
477  else
478  {
479  // This is pretty inefficient but there is no other way to do this with
480  // block sub preconditioners as far as I can tell because they demand
481  // to have the full r and z vectors...
482  DoubleVector block_z_with_size_of_full_z(
483  block_x_with_size_of_full_x.distribution_pt());
484  DoubleVector temp_with_size_of_full_rhs(
485  block_x_with_size_of_full_x.distribution_pt());
486 
487  // Reorder the entries of temp and put them into the global-sized vector
488  this->return_block_vector(0, temp, temp_with_size_of_full_rhs);
489 
490  // Solve on the global-sized vectors
492  temp_with_size_of_full_rhs, block_z_with_size_of_full_z);
493 
494  // Now reorder the entries and put them into z
495  this->get_block_vector(0, block_z_with_size_of_full_z, z);
496 
497  // Since we're using RHS preconditioning the preconditioner is applied
498  // to the solution vector
499  // preconditioner_pt()->preconditioner_solve(temp,z);
500 
501  // Use the update: x_m=x_0+inv(M)Vy [see Saad Y,"Iterative methods for
502  // sparse linear systems", p.284]
503  x += z;
504  }
505  } // End of update
506 
517  void generate_plane_rotation(double& dx, double& dy, double& cs, double& sn)
518  {
519  // If dy=0 then we do not need to apply a rotation
520  if (dy == 0.0)
521  {
522  // Using theta=0 gives cos(theta)=1
523  cs = 1.0;
524 
525  // Using theta=0 gives sin(theta)=0
526  sn = 0.0;
527  }
528  // If dx or dy is large using the normal form of calculting cs and sn
529  // is naive since this may overflow or underflow so instead we calculate
530  // r=sqrt(pow(dx,2)+pow(dy,2)) by using r=|dy|sqrt(1+pow(dx/dy,2)) if
531  // |dy|>|dx| [see <A
532  // HREF=https://en.wikipedia.org/wiki/Hypot">Hypot</A>.].
533  else if (fabs(dy) > fabs(dx))
534  {
535  // Since |dy|>|dx| calculate the ratio dx/dy
536  double temp = dx / dy;
537 
538  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))
539  sn = 1.0 / sqrt(1.0 + temp * temp);
540 
541  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))=(dx/dy)*sin(theta)
542  cs = temp * sn;
543  }
544  // Otherwise, we have |dx|>=|dy| so to, again, avoid overflow or underflow
545  // calculate the values of cs and sn using the method above
546  else
547  {
548  // Since |dx|>=|dy| calculate the ratio dy/dx
549  double temp = dy / dx;
550 
551  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))
552  cs = 1.0 / sqrt(1.0 + temp * temp);
553 
554  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))=(dy/dx)*cos(theta)
555  sn = temp * cs;
556  }
557  } // End of generate_plane_rotation
558 
562  void apply_plane_rotation(double& dx, double& dy, double& cs, double& sn)
563  {
564  // Calculate the value of dx but don't update it yet
565  double temp = cs * dx + sn * dy;
566 
567  // Set the value of dy
568  dy = -sn * dx + cs * dy;
569 
570  // Set the value of dx using the correct values of dx and dy
571  dx = temp;
572  } // End of apply_plane_rotation
573 
576 
580 
582  unsigned Iterations;
583 
587 
591 
595 
599  };
600 } // End of namespace oomph
601 #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: block_preconditioner.h:422
void return_block_vector(const unsigned &n, const DoubleVector &b, DoubleVector &v) const
Definition: block_preconditioner.cc:4489
void get_block_vector(const unsigned &n, const DoubleVector &v, DoubleVector &b) const
Definition: block_preconditioner.cc:4186
Definition: matrices.h:888
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
Definition: linear_algebra_distribution.h:457
Definition: double_vector.h:58
double * values_pt()
access function to the underlying values
Definition: double_vector.h:254
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:247
void operator=(const GMRESBlockPreconditioner &)=delete
Broken assignment operator.
double Memory_usage_in_bytes
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:590
void apply_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:562
void disable_doc_memory_usage()
Don't document the memory usage!
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:348
unsigned iterations() const
Handle to the number of iterations taken.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:320
GMRESBlockPreconditioner(const GMRESBlockPreconditioner &)=delete
Broken copy constructor.
void enable_doc_memory_usage()
Document the memory usage.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:340
virtual void clean_up_memory()
Clean up the memory (empty for now...)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:273
SpaceTimeNavierStokesSubsidiaryPreconditioner * Navier_stokes_subsidiary_preconditioner_pt
Pointer to the preconditioner for the block matrix.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:579
bool Compute_memory_statistics
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:586
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.cc:729
bool Preconditioner_has_been_setup
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:594
unsigned Iterations
Number of iterations taken.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:582
SpaceTimeNavierStokesSubsidiaryPreconditioner * navier_stokes_subsidiary_preconditioner_pt() const
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:410
void set_preconditioner_RHS()
Enable right preconditioning.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:333
GMRESBlockPreconditioner()
Constructor (empty)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:250
bool Preconditioner_LHS
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:598
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:311
double get_memory_usage_in_bytes()
Get the memory statistics.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:356
CRDoubleMatrix * Matrix_pt
Pointer to matrix.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:575
void set_preconditioner_LHS()
Set left preconditioning (the default)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:327
void setup()
Setup the preconditioner.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.cc:575
void update(const unsigned &k, const Vector< Vector< double >> &H, const Vector< double > &s, const Vector< DoubleVector > &v, const DoubleVector &block_x_with_size_of_full_x, DoubleVector &x)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:420
void generate_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:517
virtual ~GMRESBlockPreconditioner()
Destructor.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:266
Definition: iterative_linear_solver.h:54
Definition: matrix_vector_product.h:51
Definition: oomph_definitions.h:222
Definition: oomph_definitions.h:267
Definition: preconditioner.h:54
virtual void setup()=0
Definition: problem.h:151
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:56
virtual ~SpaceTimeNavierStokesSubsidiaryPreconditioner()
Destructor - delete the preconditioner matrices.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:90
Preconditioner * P_preconditioner_pt
Pointer to the 'preconditioner' for the pressure matrix.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:211
double Memory_usage_in_bytes
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:229
void setup()
Setup the preconditioner.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.cc:61
bool Preconditioner_has_been_setup
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:221
bool Compute_memory_statistics
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:225
MatrixVectorProduct * G_mat_vec_pt
MatrixVectorProduct operator for G.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:235
void operator=(const SpaceTimeNavierStokesSubsidiaryPreconditioner &)=delete
Broken assignment operator.
SpaceTimeNavierStokesSubsidiaryPreconditioner()
Constructor. (By default this preconditioner is upper triangular).
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:59
MatrixVectorProduct * F_mat_vec_pt
MatrixVectorProduct operator for F.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:232
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.cc:482
void disable_doc_memory_usage()
Don't document the memory usage!
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:147
bool Using_default_f_preconditioner
Flag indicating whether the default F preconditioner is used.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:214
virtual void clean_up_memory()
Clean up the memory.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:97
void enable_doc_memory_usage()
Document the memory usage.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:139
bool Using_default_p_preconditioner
Flag indicating whether the default P preconditioner is used.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:217
double get_memory_usage_in_bytes()
Get the memory statistics.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:155
Preconditioner * F_preconditioner_pt
Pointer to the 'preconditioner' for the F matrix.
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:208
SpaceTimeNavierStokesSubsidiaryPreconditioner(const SpaceTimeNavierStokesSubsidiaryPreconditioner &)=delete
Broken copy constructor.
Definition: oomph-lib/src/generic/Vector.h:58
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
r
Definition: UniformPSDSelfTest.py:20
Real fabs(const Real &a)
Definition: boostmultiprec.cpp:117
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