spacetime_navier_stokes_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_SPACETIME_NAVIER_STOKES_BLOCK_PRECONDITIONERS_HEADER
28 #define OOMPH_SPACETIME_NAVIER_STOKES_BLOCK_PRECONDITIONERS_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 headers
36 #include "generic.h"
37 
38 // Space-time block preconditioning machinery
39 #include "../../SpaceTimeBlockPreconditioner/spacetime_block_preconditioner.cc"
40 
44 
45 namespace oomph
46 {
47  //=============================================================================
54  //=============================================================================
55  class SpaceTimeNavierStokesSubsidiaryPreconditioner
56  : public BlockPreconditioner<CRDoubleMatrix>
57  {
58  public:
62  {
63  // By default, don't store the memory statistics of this preconditioner
65 
66  // Initialise the value of Memory_usage_in_bytes
68 
69  // Flag to indicate that the preconditioner has been setup
70  // previously -- if setup() is called again, data can
71  // be wiped.
73 
74  // By default we use SuperLU for both p and f blocks
77 
78  // Set default preconditioners (inexact solvers) -- they are
79  // members of this class!
82 
83  // Null the momentum block matrix-vector product helper
84  F_mat_vec_pt = 0;
85 
86  // Null the gradient block matrix-vector product helper
87  G_mat_vec_pt = 0;
88  }
89 
92  {
93  // Call the auxiliary clean up function
94  this->clean_up_memory();
95  } // End of ~SpaceTimeNavierStokesSubsidiaryPreconditioner
96 
98  virtual void clean_up_memory()
99  {
100  // If we've actually set the preconditioner up
102  {
103  // Delete matvecs
104  delete F_mat_vec_pt;
105  F_mat_vec_pt = 0;
106 
107  delete G_mat_vec_pt;
108  G_mat_vec_pt = 0;
109 
110  // Delete stuff from velocity solve
112  {
113  delete F_preconditioner_pt;
115  }
116 
117  // Delete stuff from Schur complement approx
119  {
120  delete P_preconditioner_pt;
122  }
123  } // if (Preconditioner_has_been_setup)
124  } // End of clean_up_memory
125 
129 
132  delete;
133 
136  using Preconditioner::setup;
137 
139  void setup();
140 
143 
144 
147  {
150  } // End of enable_doc_memory_usage
151 
152 
155  {
158  } // End of disable_doc_memory_usage
159 
160 
163  {
164  // Has the preconditioner even been set up yet?
166  {
167  // Were we meant to compute the statistics?
169  {
170  // Return the appropriate variable value
171  return Memory_usage_in_bytes;
172  }
173  else
174  {
175  // Allocate storage for an output stream
176  std::ostringstream warning_message_stream;
177 
178  // Create a warning message
179  warning_message_stream
180  << "The memory statistics have not been calculated "
181  << "so I'm returning\nthe value zero." << std::endl;
182 
183  // Give the user a warning
184  OomphLibWarning(warning_message_stream.str(),
187 
188  // Return the value zero
189  return 0.0;
190  }
191  }
192  // If the preconditioner hasn't been set up yet
193  else
194  {
195  // Allocate storage for an output stream
196  std::ostringstream warning_message_stream;
197 
198  // Create a warning message
199  warning_message_stream
200  << "The preconditioner hasn't even been set up yet "
201  << "so I'm returning\nthe value zero." << std::endl;
202 
203  // Give the user a warning
204  OomphLibWarning(warning_message_stream.str(),
207 
208  // Return the value zero
209  return 0.0;
210  } // if (Preconditioner_has_been_setup)
211  } // End of get_memory_usage_in_bytes
212 
213  private:
216 
219 
222 
225 
229 
233 
236  double Memory_usage_in_bytes;
237 
240 
243  };
244 
245 
246  //=============================================================================
250  //=============================================================================
251  class GMRESBlockPreconditioner
252  : public IterativeLinearSolver,
253  public virtual BlockPreconditioner<CRDoubleMatrix>
254  {
255  public:
259  Matrix_pt(0),
261  Iterations(0),
263  Preconditioner_LHS(false)
264  {
265  // By default, don't store the memory statistics of this preconditioner
267 
268  // Initialise the value of Memory_usage_in_bytes
269  Memory_usage_in_bytes = 0.0;
270  } // End of GMRESBlockPreconditioner
271 
274  {
275  // Call the auxiliary clean up function
276  this->clean_up_memory();
277  } // End of ~GMRESBlockPreconditioner
278 
280  virtual void clean_up_memory()
281  {
282  // If the block preconditioner has been set up previously
284  {
285  // Delete the subsidiary preconditioner
287 
288  // Make it a null pointer
290 
291  // Delete the matrix!
292  delete Matrix_pt;
293 
294  // Make it a null pointer
295  Matrix_pt = 0;
296  }
297  } // End of clean_up_memory
298 
301 
303  void operator=(const GMRESBlockPreconditioner&) = delete;
304 
307  using Preconditioner::setup;
308 
310  void setup();
311 
314 
318  void solve(Problem* const& problem_pt, DoubleVector& result)
319  {
320  // Broken
321  throw OomphLibError("Can't use this interface!",
324  } // End of solve
325 
327  unsigned iterations() const
328  {
329  // Return the number of iterations
330  return Iterations;
331  } // End of iterations
332 
335  {
336  Preconditioner_LHS = true;
337  }
338 
341  {
342  Preconditioner_LHS = false;
343  }
344 
345 
348  {
351  } // End of enable_doc_memory_statistics
352 
353 
356  {
359  } // End of disable_doc_memory_statistics
360 
361 
364  {
365  // Has the preconditioner even been set up yet?
367  {
368  // Were we meant to compute the statistics?
370  {
371  // Return the appropriate variable value
372  return Memory_usage_in_bytes;
373  }
374  else
375  {
376  // Allocate storage for an output stream
377  std::ostringstream warning_message_stream;
378 
379  // Create a warning message
380  warning_message_stream
381  << "The memory statistics have not been calculated "
382  << "so I'm returning\nthe value zero." << std::endl;
383 
384  // Give the user a warning
385  OomphLibWarning(warning_message_stream.str(),
388 
389  // Return the value zero
390  return 0.0;
391  }
392  }
393  // If the preconditioner hasn't been set up yet
394  else
395  {
396  // Allocate storage for an output stream
397  std::ostringstream warning_message_stream;
398 
399  // Create a warning message
400  warning_message_stream
401  << "The preconditioner hasn't even been set up yet "
402  << "so I'm returning\nthe value zero." << std::endl;
403 
404  // Give the user a warning
405  OomphLibWarning(warning_message_stream.str(),
408 
409  // Return the value zero
410  return 0.0;
411  } // if (Preconditioner_has_been_setup)
412  } // End of get_memory_usage_in_bytes
413 
414 
418  const
419  {
420  // Return a pointer to the appropriate member data
422  } // End of navier_stokes_subsidiary_preconditioner_pt
423 
424  private:
427  void update(const unsigned& k,
428  const Vector<Vector<double>>& H,
429  const Vector<double>& s,
430  const Vector<DoubleVector>& v,
431  const DoubleVector& block_x_with_size_of_full_x,
432  DoubleVector& x)
433  {
434  // Make a local copy of s
435  Vector<double> y(s);
436 
437  // Backsolve:
438  for (int i = int(k); i >= 0; i--)
439  {
440  // Divide the i-th entry of y by the i-th diagonal entry of H
441  y[i] /= H[i][i];
442 
443  // Loop over the previous values of y and update
444  for (int j = i - 1; j >= 0; j--)
445  {
446  // Update the j-th entry of y
447  y[j] -= H[i][j] * y[i];
448  }
449  } // for (int i=int(k);i>=0;i--)
450 
451  // Store the number of rows in the result vector
452  unsigned n_x = x.nrow();
453 
454  // Build a temporary vector with entries initialised to 0.0
455  DoubleVector temp(x.distribution_pt(), 0.0);
456 
457  // Build a temporary vector with entries initialised to 0.0
458  DoubleVector z(x.distribution_pt(), 0.0);
459 
460  // Get access to the underlying values
461  double* temp_pt = temp.values_pt();
462 
463  // Calculate x=Vy
464  for (unsigned j = 0; j <= k; j++)
465  {
466  // Get access to j-th column of v
467  const double* vj_pt = v[j].values_pt();
468 
469  // Loop over the entries of the vector, temp
470  for (unsigned i = 0; i < n_x; i++)
471  {
472  temp_pt[i] += vj_pt[i] * y[j];
473  }
474  } // for (unsigned j=0;j<=k;j++)
475 
476  // If we're using LHS preconditioning
477  if (Preconditioner_LHS)
478  {
479  // Since we're using LHS preconditioning the preconditioner is applied
480  // to the matrix and RHS vector so we simply update the value of x
481  x += temp;
482  }
483  // If we're using RHS preconditioning
484  else
485  {
486  // This is pretty inefficient but there is no other way to do this with
487  // block sub preconditioners as far as I can tell because they demand
488  // to have the full r and z vectors...
489  DoubleVector block_z_with_size_of_full_z(
490  block_x_with_size_of_full_x.distribution_pt());
491  DoubleVector temp_with_size_of_full_rhs(
492  block_x_with_size_of_full_x.distribution_pt());
493 
494  // Reorder the entries of temp and put them into the global-sized vector
495  this->return_block_vector(0, temp, temp_with_size_of_full_rhs);
496 
497  // Solve on the global-sized vectors
499  temp_with_size_of_full_rhs, block_z_with_size_of_full_z);
500 
501  // Now reorder the entries and put them into z
502  this->get_block_vector(0, block_z_with_size_of_full_z, z);
503 
504  // Since we're using RHS preconditioning the preconditioner is applied
505  // to the solution vector
506  // preconditioner_pt()->preconditioner_solve(temp,z);
507 
508  // Use the update: x_m=x_0+inv(M)Vy [see Saad Y,"Iterative methods for
509  // sparse linear systems", p.284]
510  x += z;
511  }
512  } // End of update
513 
524  void generate_plane_rotation(double& dx, double& dy, double& cs, double& sn)
525  {
526  // If dy=0 then we do not need to apply a rotation
527  if (dy == 0.0)
528  {
529  // Using theta=0 gives cos(theta)=1
530  cs = 1.0;
531 
532  // Using theta=0 gives sin(theta)=0
533  sn = 0.0;
534  }
535  // If dx or dy is large using the normal form of calculting cs and sn
536  // is naive since this may overflow or underflow so instead we calculate
537  // r=sqrt(pow(dx,2)+pow(dy,2)) by using r=|dy|sqrt(1+pow(dx/dy,2)) if
538  // |dy|>|dx| [see <A
539  // HREF=https://en.wikipedia.org/wiki/Hypot">Hypot</A>.].
540  else if (fabs(dy) > fabs(dx))
541  {
542  // Since |dy|>|dx| calculate the ratio dx/dy
543  double temp = dx / dy;
544 
545  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))
546  sn = 1.0 / sqrt(1.0 + temp * temp);
547 
548  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))=(dx/dy)*sin(theta)
549  cs = temp * sn;
550  }
551  // Otherwise, we have |dx|>=|dy| so to, again, avoid overflow or underflow
552  // calculate the values of cs and sn using the method above
553  else
554  {
555  // Since |dx|>=|dy| calculate the ratio dy/dx
556  double temp = dy / dx;
557 
558  // Calculate cos(theta)=dx/sqrt(pow(dx,2)+pow(dy,2))
559  cs = 1.0 / sqrt(1.0 + temp * temp);
560 
561  // Calculate sin(theta)=dy/sqrt(pow(dx,2)+pow(dy,2))=(dy/dx)*cos(theta)
562  sn = temp * cs;
563  }
564  } // End of generate_plane_rotation
565 
569  void apply_plane_rotation(double& dx, double& dy, double& cs, double& sn)
570  {
571  // Calculate the value of dx but don't update it yet
572  double temp = cs * dx + sn * dy;
573 
574  // Set the value of dy
575  dy = -sn * dx + cs * dy;
576 
577  // Set the value of dx using the correct values of dx and dy
578  dx = temp;
579  } // End of apply_plane_rotation
580 
583 
587 
589  unsigned Iterations;
590 
594 
597  double Memory_usage_in_bytes;
598 
602 
605  bool Preconditioner_LHS;
606  };
607 } // End of namespace oomph
608 #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: spacetime_navier_stokes_block_preconditioner.h:569
unsigned iterations() const
Handle to the number of iterations taken.
Definition: spacetime_navier_stokes_block_preconditioner.h:327
GMRESBlockPreconditioner(const GMRESBlockPreconditioner &)=delete
Broken copy constructor.
void disable_doc_memory_statistics()
Don't document the memory usage!
Definition: spacetime_navier_stokes_block_preconditioner.h:355
virtual void clean_up_memory()
Clean up the memory (empty for now...)
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:273
void enable_doc_memory_statistics()
Document the memory usage.
Definition: spacetime_navier_stokes_block_preconditioner.h:347
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.
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: spacetime_navier_stokes_block_preconditioner.h:417
void set_preconditioner_RHS()
Enable right preconditioning.
Definition: spacetime_navier_stokes_block_preconditioner.h:340
GMRESBlockPreconditioner()
Constructor (empty)
Definition: spacetime_navier_stokes_block_preconditioner.h:257
bool Preconditioner_LHS
Definition: general_purpose_space_time_subsidiary_block_preconditioner.h:598
void solve(Problem *const &problem_pt, DoubleVector &result)
Definition: spacetime_navier_stokes_block_preconditioner.h:318
double get_memory_usage_in_bytes()
Get the memory statistics.
Definition: spacetime_navier_stokes_block_preconditioner.h:363
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: spacetime_navier_stokes_block_preconditioner.h:334
void setup()
Setup the preconditioner.
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: spacetime_navier_stokes_block_preconditioner.h:427
void generate_plane_rotation(double &dx, double &dy, double &cs, double &sn)
Definition: spacetime_navier_stokes_block_preconditioner.h:524
virtual ~GMRESBlockPreconditioner()
Destructor.
Definition: spacetime_navier_stokes_block_preconditioner.h:273
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: spacetime_navier_stokes_block_preconditioner.h:91
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
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: spacetime_navier_stokes_block_preconditioner.h:60
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.
void disable_doc_memory_usage()
Don't document the memory usage!
Definition: spacetime_navier_stokes_block_preconditioner.h:154
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: spacetime_navier_stokes_block_preconditioner.h:146
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: spacetime_navier_stokes_block_preconditioner.h:162
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