general_purpose_block_preconditioners.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 
27 // Include guards
28 #ifndef OOMPH_GENERAL_BLOCK_PRECONDITIONERS
29 #define OOMPH_GENERAL_BLOCK_PRECONDITIONERS
30 
31 
32 // Config header generated by autoconfig
33 #ifdef HAVE_CONFIG_H
34 #include <oomph-lib-config.h>
35 #endif
36 
37 // c++ include
38 // #include<list>
39 
40 // oomph-lib includes
41 #include "matrices.h"
42 // #include "mesh.h"
43 // #include "problem.h"
44 #include "block_preconditioner.h"
45 #include "SuperLU_preconditioner.h"
46 #include "preconditioner_array.h"
47 #include "matrix_vector_product.h"
48 
49 
50 namespace oomph
51 {
52  namespace PreconditionerCreationFunctions
53  {
58  {
59  return new SuperLUPreconditioner;
60  }
61  } // namespace PreconditionerCreationFunctions
62 
63 
64  //============================================================================
74  //============================================================================
75  template<typename MATRIX>
77  {
78  public:
84  typedef Preconditioner* (*SubsidiaryPreconditionerFctPt)();
85 
88  : BlockPreconditioner<MATRIX>(),
90  &PreconditionerCreationFunctions::create_super_lu_preconditioner)
91  {
92  // Make sure that the Gp_mesh_pt container is size zero.
93  Gp_mesh_pt.resize(0);
94  }
95 
99  {
100  this->clean_up_memory();
101 
102  for (unsigned j = 0, nj = Subsidiary_preconditioner_pt.size(); j < nj;
103  j++)
104  {
106  }
107  }
108 
112  virtual void clean_up_memory()
113  {
114  // Call clean up in any subsidiary precondtioners that are set.
115  for (unsigned j = 0, nj = Subsidiary_preconditioner_pt.size(); j < nj;
116  j++)
117  {
119  {
120  Subsidiary_preconditioner_pt[j]->clean_up_memory();
121  }
122  }
123 
124  // Clean up the block preconditioner base class stuff
126  }
127 
130  const GeneralPurposeBlockPreconditioner&) = delete;
131 
134 
137  SubsidiaryPreconditionerFctPt sub_prec_fn)
138  {
140  }
141 
144  {
147  }
155  const unsigned& i)
156  {
157  // If the vector is currently too small to hold that many
158  // preconditioners then expand it and fill with nulls.
159  if (Subsidiary_preconditioner_pt.size() < i + 1)
160  {
161  Subsidiary_preconditioner_pt.resize(i + 1, 0);
162  }
163  // Note: the size of the vector is checked by
164  // fill_in_subsidiary_preconditioners(..) when we know what size it
165  // should be.
166 
167  // I'm assuming that the number of preconditioners is always "small"
168  // compared to Jacobian size, so a resize doesn't waste much time.
169 
170  // Put the pointer in the vector
172  }
173 
177  {
179  }
180 
182  void set_dof_to_block_map(Vector<unsigned>& dof_to_block_map)
183  {
184  Dof_to_block_map = dof_to_block_map;
185  }
186 
191  void add_mesh(const Mesh* mesh_pt,
192  const bool& allow_multiple_element_type_in_mesh = false)
193  {
194 #ifdef PARANOID
195  // Check that the mesh pointer is not null.
196  if (mesh_pt == 0)
197  {
198  std::ostringstream err_msg;
199  err_msg << "The mesh_pt is null, please point it to a mesh.\n";
200  throw OomphLibError(
202  }
203 #endif
204  // Push back the mesh pointer and the boolean in a pair.
205  Gp_mesh_pt.push_back(
206  std::make_pair(mesh_pt, allow_multiple_element_type_in_mesh));
207  }
208 
211  unsigned gp_nmesh()
212  {
213  return Gp_mesh_pt.size();
214  }
215 
216  protected:
219  {
220  const unsigned nmesh = gp_nmesh();
221 #ifdef PARANOID
222  if (nmesh == 0)
223  {
224  std::ostringstream err_msg;
225  err_msg << "There are no meshes set.\n"
226  << "Have you remembered to call add_mesh(...)?\n";
227  throw OomphLibError(
229  }
230 #endif
231 
232  this->set_nmesh(nmesh);
233  for (unsigned mesh_i = 0; mesh_i < nmesh; mesh_i++)
234  {
235  this->set_mesh(
236  mesh_i, Gp_mesh_pt[mesh_i].first, Gp_mesh_pt[mesh_i].second);
237  }
238  }
239 
242  {
243  if (Dof_to_block_map.size() > 0)
244  {
246  }
247  else
248  {
250  }
251  }
252 
256  void fill_in_subsidiary_preconditioners(const unsigned& nprec_needed)
257  {
258  // If it's empty then fill it in with null pointers.
259  if (Subsidiary_preconditioner_pt.empty())
260  {
261  Subsidiary_preconditioner_pt.assign(nprec_needed, 0);
262  }
263  else
264  {
265  // Otherwise check we have the right number of them
266 #ifdef PARANOID
267  if (Subsidiary_preconditioner_pt.size() != nprec_needed)
268  {
269  using namespace StringConversion;
270  std::string error_msg = "Wrong number of precondtioners in";
271  error_msg += "Subsidiary_preconditioner_pt, should have ";
272  error_msg += to_string(nprec_needed) + " but we actually have ";
273  error_msg += to_string(Subsidiary_preconditioner_pt.size());
274  throw OomphLibError(
276  }
277 #endif
278  }
279 
280 
281  // Now replace any null pointers with new preconditioners
282  for (unsigned j = 0, nj = Subsidiary_preconditioner_pt.size(); j < nj;
283  j++)
284  {
286  {
288  (*Subsidiary_preconditioner_creation_function_pt)();
289  }
290  }
291  }
292 
295 
300 
301  private:
304 
308  };
309 
310 
311  //=============================================================================
317  //=============================================================================
318  template<typename MATRIX>
320  : public GeneralPurposeBlockPreconditioner<MATRIX>
321  {
322  public:
325  {
326  // by default we do not use two level parallelism
327  Use_two_level_parallelisation = false;
328 
329  // null the Preconditioner array pt
330  Preconditioner_array_pt = 0;
331 
332  // Don't doc by default
333  Doc_time_during_preconditioner_solve = false;
334  }
335 
338  {
339  this->clean_up_memory();
340  }
341 
343  virtual void clean_up_memory()
344  {
345  if (Use_two_level_parallelisation)
346  {
347  delete Preconditioner_array_pt;
348  Preconditioner_array_pt = 0;
349  }
350 
351  // Clean up the base class too
353  }
354 
357 
359  void operator=(const BlockDiagonalPreconditioner&) = delete;
360 
363 
365  virtual void setup();
366 
369  {
370 #ifndef OOMPH_HAS_MPI
371  throw OomphLibError("Cannot do any parallelism since we don't have MPI.",
374 #endif
375  Use_two_level_parallelisation = true;
376  }
377 
380  {
381  Use_two_level_parallelisation = false;
382  }
383 
386  {
387  Doc_time_during_preconditioner_solve = true;
388  }
389 
392  {
393  Doc_time_during_preconditioner_solve = false;
394  }
395 
396  void fill_in_subsidiary_preconditioners(const unsigned& nprec_needed)
397  {
398 #ifdef PARANOID
399  if ((Use_two_level_parallelisation) &&
400  !this->Subsidiary_preconditioner_pt.empty())
401  {
402  std::string err_msg =
403  "Two level parallelism diagonal block preconditioners cannot have";
404  err_msg +=
405  " any preset preconditioners (due to weird memory management";
406  err_msg += " in the PreconditionerArray, you could try fixing it).";
407  throw OomphLibError(
409  }
410 #endif
411 
412  // Now call the real function
414  MATRIX>::fill_in_subsidiary_preconditioners(nprec_needed);
415  }
416 
417  protected:
423  virtual unsigned get_other_diag_ds(const unsigned& i,
424  const unsigned& nblock) const
425  {
426  return i;
427  }
428 
429 
430  private:
433 
436 
439  };
440 
441 
445 
446 
447  //=============================================================================
455  //=============================================================================
456  template<typename MATRIX>
458  : public GeneralPurposeBlockPreconditioner<MATRIX>
459  {
460  public:
464  {
465  // default to upper triangular
466  Upper_triangular = true;
467  }
468 
471  {
472  this->clean_up_memory();
473  }
474 
476  virtual void clean_up_memory()
477  {
478  // Delete anything in Off_diagonal_matrix_vector_products
479  for (unsigned i = 0, ni = Off_diagonal_matrix_vector_products.nrow();
480  i < ni;
481  i++)
482  {
483  for (unsigned j = 0, nj = Off_diagonal_matrix_vector_products.ncol();
484  j < nj;
485  j++)
486  {
487  delete Off_diagonal_matrix_vector_products(i, j);
488  Off_diagonal_matrix_vector_products(i, j) = 0;
489  }
490  }
491 
492  // Clean up the base class too
494  }
495 
498  delete;
499 
502 
505 
507  void setup();
508 
511  {
512  Upper_triangular = true;
513  }
514 
517  {
518  Upper_triangular = false;
519  }
520 
521  private:
524 
527  };
528 
529 
533 
534 
535  //=============================================================================
538  //=============================================================================
539  template<typename MATRIX>
541  : public GeneralPurposeBlockPreconditioner<MATRIX>
542  {
543  public:
546 
549 
552 
554  void operator=(const ExactBlockPreconditioner&) = delete;
555 
558 
560  void setup();
561 
565  {
566  return this->Subsidiary_preconditioner_pt[0];
567  }
568  };
569 
570 
571  // =================================================================
575  // =================================================================
576  template<typename MATRIX>
578  : public BlockDiagonalPreconditioner<MATRIX>
579  {
580  protected:
586  unsigned get_other_diag_ds(const unsigned& i, const unsigned& nblock) const
587  {
588  return nblock - i - 1;
589  }
590  };
591 
592 
593  // =================================================================
596  // =================================================================
597  template<typename MATRIX>
599  : public GeneralPurposeBlockPreconditioner<MATRIX>
600  {
601  public:
604 
607 
610 
612  void operator=(const DummyBlockPreconditioner&) = delete;
613 
616  {
617  z.build(r);
618  }
619 
621  void setup()
622  {
623  // Set up the block look up schemes
624  this->block_setup();
625  }
626  };
627 
628 } // namespace oomph
629 #endif
int i
Definition: BiCGSTAB_step_by_step.cpp:9
Definition: general_purpose_block_preconditioners.h:579
unsigned get_other_diag_ds(const unsigned &i, const unsigned &nblock) const
Definition: general_purpose_block_preconditioners.h:586
Definition: general_purpose_block_preconditioners.h:321
void disable_doc_time_during_preconditioner_solve()
Disable Doc timings in application of block sub-preconditioners.
Definition: general_purpose_block_preconditioners.h:391
virtual ~BlockDiagonalPreconditioner()
Destructor - delete the preconditioner matrices.
Definition: general_purpose_block_preconditioners.h:337
void fill_in_subsidiary_preconditioners(const unsigned &nprec_needed)
Definition: general_purpose_block_preconditioners.h:396
void enable_two_level_parallelisation()
Use two level parallelisation.
Definition: general_purpose_block_preconditioners.h:368
bool Doc_time_during_preconditioner_solve
Doc timings in application of block sub-preconditioners?
Definition: general_purpose_block_preconditioners.h:438
void operator=(const BlockDiagonalPreconditioner &)=delete
Broken assignment operator.
void enable_doc_time_during_preconditioner_solve()
Enable Doc timings in application of block sub-preconditioners.
Definition: general_purpose_block_preconditioners.h:385
void disable_two_level_parallelisation()
Don't use two-level parallelisation.
Definition: general_purpose_block_preconditioners.h:379
BlockDiagonalPreconditioner(const BlockDiagonalPreconditioner &)=delete
Broken copy constructor.
BlockDiagonalPreconditioner()
constructor - when the preconditioner is used as a master preconditioner
Definition: general_purpose_block_preconditioners.h:324
virtual unsigned get_other_diag_ds(const unsigned &i, const unsigned &nblock) const
Definition: general_purpose_block_preconditioners.h:423
virtual void clean_up_memory()
clean up the memory
Definition: general_purpose_block_preconditioners.h:343
PreconditionerArray * Preconditioner_array_pt
pointer for the PreconditionerArray
Definition: general_purpose_block_preconditioners.h:432
bool Use_two_level_parallelisation
Use two level parallelism using the PreconditionerArray.
Definition: general_purpose_block_preconditioners.h:435
Definition: block_preconditioner.h:422
unsigned nmesh() const
Definition: block_preconditioner.h:1816
const Mesh * mesh_pt(const unsigned &i) const
Definition: block_preconditioner.h:1782
void clear_block_preconditioner_base()
Definition: block_preconditioner.h:2159
void set_nmesh(const unsigned &n)
Definition: block_preconditioner.h:2851
virtual void block_setup()
Definition: block_preconditioner.cc:2483
void set_mesh(const unsigned &i, const Mesh *const mesh_pt, const bool &allow_multiple_element_type_in_mesh=false)
Definition: block_preconditioner.h:2866
Definition: general_purpose_block_preconditioners.h:459
virtual ~BlockTriangularPreconditioner()
Destructor - delete the preconditioner matrices.
Definition: general_purpose_block_preconditioners.h:470
DenseMatrix< MatrixVectorProduct * > Off_diagonal_matrix_vector_products
Matrix of matrix vector product operators for the off diagonals.
Definition: general_purpose_block_preconditioners.h:523
void upper_triangular()
Use as an upper triangular preconditioner.
Definition: general_purpose_block_preconditioners.h:510
BlockTriangularPreconditioner()
Constructor. (By default this preconditioner is upper triangular).
Definition: general_purpose_block_preconditioners.h:462
void operator=(const BlockTriangularPreconditioner &)=delete
Broken assignment operator.
BlockTriangularPreconditioner(const BlockTriangularPreconditioner &)=delete
Broken copy constructor.
void lower_triangular()
Use as a lower triangular preconditioner.
Definition: general_purpose_block_preconditioners.h:516
virtual void clean_up_memory()
clean up the memory
Definition: general_purpose_block_preconditioners.h:476
bool Upper_triangular
Boolean indicating upper or lower triangular.
Definition: general_purpose_block_preconditioners.h:526
Definition: matrices.h:386
Definition: double_vector.h:58
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
Definition: double_vector.cc:35
Definition: general_purpose_block_preconditioners.h:600
DummyBlockPreconditioner(const DummyBlockPreconditioner &)=delete
Broken copy constructor.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r (just copy r to z).
Definition: general_purpose_block_preconditioners.h:615
DummyBlockPreconditioner()
Constructor.
Definition: general_purpose_block_preconditioners.h:603
void setup()
Setup the preconditioner.
Definition: general_purpose_block_preconditioners.h:621
~DummyBlockPreconditioner()
Destructor.
Definition: general_purpose_block_preconditioners.h:606
void operator=(const DummyBlockPreconditioner &)=delete
Broken assignment operator.
Definition: general_purpose_block_preconditioners.h:542
ExactBlockPreconditioner()
constructor
Definition: general_purpose_block_preconditioners.h:545
void operator=(const ExactBlockPreconditioner &)=delete
Broken assignment operator.
ExactBlockPreconditioner(const ExactBlockPreconditioner &)=delete
Broken copy constructor.
virtual ~ExactBlockPreconditioner()
Destructor.
Definition: general_purpose_block_preconditioners.h:548
Preconditioner *& preconditioner_pt()
Definition: general_purpose_block_preconditioners.h:564
Definition: general_purpose_block_preconditioners.h:77
void operator=(const GeneralPurposeBlockPreconditioner &)=delete
Broken assignment operator.
Vector< unsigned > Dof_to_block_map
the set of dof to block maps for this preconditioner
Definition: general_purpose_block_preconditioners.h:303
void set_dof_to_block_map(Vector< unsigned > &dof_to_block_map)
Specify a DOF to block map.
Definition: general_purpose_block_preconditioners.h:182
virtual void clean_up_memory()
Definition: general_purpose_block_preconditioners.h:112
GeneralPurposeBlockPreconditioner()
constructor
Definition: general_purpose_block_preconditioners.h:87
virtual ~GeneralPurposeBlockPreconditioner()
Definition: general_purpose_block_preconditioners.h:98
Preconditioner *(* SubsidiaryPreconditionerFctPt)()
Definition: general_purpose_block_preconditioners.h:84
SubsidiaryPreconditionerFctPt Subsidiary_preconditioner_creation_function_pt
Definition: general_purpose_block_preconditioners.h:299
Vector< Preconditioner * > Subsidiary_preconditioner_pt
List of preconditioners to use for the blocks to be solved.
Definition: general_purpose_block_preconditioners.h:294
Vector< std::pair< const Mesh *, bool > > Gp_mesh_pt
Definition: general_purpose_block_preconditioners.h:307
Preconditioner * subsidiary_preconditioner_pt(const unsigned &i) const
Definition: general_purpose_block_preconditioners.h:176
void reset_subsidiary_preconditioner_function_to_default()
Reset the subsidiary preconditioner function to its default.
Definition: general_purpose_block_preconditioners.h:143
void add_mesh(const Mesh *mesh_pt, const bool &allow_multiple_element_type_in_mesh=false)
Definition: general_purpose_block_preconditioners.h:191
void gp_preconditioner_set_all_meshes()
Set the mesh in the block preconditioning framework.
Definition: general_purpose_block_preconditioners.h:218
GeneralPurposeBlockPreconditioner(const GeneralPurposeBlockPreconditioner &)=delete
Broken copy constructor.
void fill_in_subsidiary_preconditioners(const unsigned &nprec_needed)
Definition: general_purpose_block_preconditioners.h:256
void set_subsidiary_preconditioner_pt(Preconditioner *prec, const unsigned &i)
Definition: general_purpose_block_preconditioners.h:154
void gp_preconditioner_block_setup()
Modified block setup for general purpose block preconditioners.
Definition: general_purpose_block_preconditioners.h:241
void set_subsidiary_preconditioner_function(SubsidiaryPreconditionerFctPt sub_prec_fn)
access function to set the subsidiary preconditioner function.
Definition: general_purpose_block_preconditioners.h:136
unsigned gp_nmesh()
Definition: general_purpose_block_preconditioners.h:211
Definition: mesh.h:67
Definition: oomph_definitions.h:222
Definition: preconditioner_array.h:50
Definition: preconditioner.h:54
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
virtual void setup()=0
An interface to allow SuperLU to be used as an (exact) Preconditioner.
Definition: SuperLU_preconditioner.h:40
r
Definition: UniformPSDSelfTest.py:20
std::string string(const unsigned &i)
Definition: oomph_definitions.cc:286
Preconditioner * create_super_lu_preconditioner()
Definition: general_purpose_block_preconditioners.h:57
std::string to_string(T object, unsigned float_precision=8)
Definition: oomph_utilities.h:189
DRAIG: Change all instances of (SPATIAL_DIM) to (DIM-1).
Definition: AnisotropicHookean.h:10
#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