lagrange_enforced_flow_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-2023 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 #ifndef OOMPH_LAGRANGE_ENFORCED_FLOW_PRECONDITIONERS_HEADER
27 #define OOMPH_LAGRANGE_ENFORCED_FLOW_PRECONDITIONERS_HEADER
28 
29 
30 // Config header generated by autoconfig
31 #ifdef HAVE_CONFIG_H
32 #include <oomph-lib-config.h>
33 #endif
34 
35 // oomphlib headers
36 #include "../generic/matrices.h"
37 #include "../generic/assembly_handler.h"
38 #include "../generic/problem.h"
39 #include "../generic/block_preconditioner.h"
40 #include "../generic/preconditioner.h"
41 #include "../generic/SuperLU_preconditioner.h"
42 #include "../generic/matrix_vector_product.h"
43 #include "../generic/general_purpose_preconditioners.h"
44 #include "../generic/general_purpose_block_preconditioners.h"
45 #ifdef OOMPH_HAS_HYPRE
46 #include "../generic/hypre_solver.h"
47 #endif
48 #ifdef OOMPH_HAS_TRILINOS
49 #include "../generic/trilinos_solver.h"
50 #endif
51 
52 namespace oomph
53 {
54  //==========================================================================
55  /// Namespace for subsidiary preconditioner creation helper functions
56  //==========================================================================
57  namespace Lagrange_Enforced_Flow_Preconditioner_Subsidiary_Operator_Helper
58  {
59  /// CG with diagonal preconditioner for W-block subsidiary linear
60  /// systems.
61  extern Preconditioner* get_w_cg_preconditioner();
62 
63  /// Hypre Boomer AMG setting for the augmented momentum block
64  /// of a 2D Navier-Stokes problem using the simple form of the viscous
65  /// term (for serial code).
66  extern Preconditioner* boomer_amg_for_2D_momentum_simple_visc();
67 
68  /// Hypre Boomer AMG setting for the augmented momentum block
69  /// of a 2D Navier-Stokes problem using the stress divergence form of the
70  /// viscous term (for serial code).
71  extern Preconditioner* boomer_amg_for_2D_momentum_stressdiv_visc();
72 
73  /// Hypre Boomer AMG setting for the augmented momentum block
74  /// of a 3D Navier-Stokes problem (for serial code).
75  extern Preconditioner* boomer_amg_for_3D_momentum();
76 
77  /// Hypre Boomer AMG setting for the augmented momentum block
78  /// of a 3D Navier-Stokes problem (for serial code).
79  extern Preconditioner* boomer_amg2v22_for_3D_momentum();
80 
81  /// Hypre Boomer AMG setting for the 2D Poisson problem
82  /// (for serial code).
83  extern Preconditioner* boomer_amg_for_2D_poisson_problem();
84 
85  /// Hypre Boomer AMG setting for the 3D Poisson problem
86  /// (for serial code).
87  extern Preconditioner* boomer_amg_for_3D_poisson_problem();
88 
89  } // namespace
90  // Lagrange_Enforced_Flow_Preconditioner_Subsidiary_Operator_Helper
91 
92 
93  //==========================================================================
94  /// The preconditioner for the Lagrange multiplier constrained
95  /// Navier-Stokes equations. The velocity components are constrained by
96  /// Lagrange multiplier, which are applied via OOMPH-LIB's FACE elements.
97  ///
98  ///
99  /// The linearised Jacobian takes the block form:
100  ///
101  /// | F_ns | L^T |
102  /// |------------|
103  /// | L | 0 |
104  ///
105  /// where L correspond to the constrained block,
106  /// F_ns is the Navier-Stokes block with the following block structure
107  ///
108  /// | F | G^T |
109  /// |----------|
110  /// | D | 0 |
111  ///
112  /// Here F is the momentum block, G the discrete gradient operator,
113  /// and D the discrete divergence operator. For unstabilised elements,
114  /// we have D = G^T and in much of the literature the divergence matrix is
115  /// denoted by B.
116  ///
117  /// The Lagrange enforced flow preconditioner takes the form:
118  /// | F_aug | |
119  /// |-------|----|
120  /// | | Wd |
121  ///
122  /// where F_aug = F_ns + L^T*inv(Wd)*L is an augmented Navier-Stokes block
123  /// and Wd=(1/Scaling_sigma)*diag(LL^T).
124  ///
125  /// In our implementation of the preconditioner, the linear systems
126  /// associated with the (1,1) block can either be solved "exactly",
127  /// using SuperLU (in its incarnation as an exact preconditioner;
128  /// this is the default) or by any other Preconditioner (inexact solver)
129  /// specified via the access functions
130  ///
131  /// LagrangeEnforcedFlowPreconditioner::set_navier_stokes_preconditioner(...)
132  ///
133  /// Access to the elements is provided via meshes. However, a Vector of
134  /// meshes is taken, each mesh contains a different type of block
135  /// preconditionable element. This allows the (re-)classification of the
136  /// constrained velocity DOF types.
137  ///
138  /// The first mesh in the Vector Mesh_pt must be the 'bulk' mesh.
139  /// The rest are assumed to contain FACEELMENTS.
140  ///
141  /// Thus, the most general block structure (in 3D) is:
142  ///
143  /// 0 1 2 3 4 5 6 7 8 ..x x+0 x+1 x+2 x+3 x+4
144  /// [u v w p] [u v w l1 l2 ...] [u v w l1 l2 ...] ...
145  /// Bulk Surface 1 Surface 2 ...
146  ///
147  /// where the DOF types in [] are the DOF types associated with each mesh.
148  ///
149  /// For example, consider a unit cube domain [0,1]^3 with parallel outflow
150  /// imposed (in mesh 0) and tangential flow imposed (in mesh 1), then there
151  /// are 13 DOF types and our implementation respects the following
152  /// (natural) DOF type order:
153  ///
154  /// bulk mesh 0 mesh 1
155  /// [0 1 2 3] [4 5 6 7 8 ] [9 10 11 12 ]
156  /// [u v w p] [up vp wp Lp1 Lp2] [ut vt wt Lt1]
157  ///
158  /// Via the appropriate mapping, the block_setup(...) function will
159  /// re-order the DOF types into the following block types:
160  ///
161  /// 0 1 2 3 4 5 6 7 8 9 10 11 12 <- Block type
162  /// 0 4 9 1 5 10 2 6 11 3 7 8 12 <- DOF type
163  /// [u up ut v vp vt w wp wt ] [p] [Lp1 Lp2 Lt1]
164  ///
165  //==========================================================================
167  : public BlockPreconditioner<CRDoubleMatrix>
168  {
169  public:
170  /// This preconditioner includes the option to use subsidiary
171  /// operators other than SuperLUPreconditioner for this problem.
172  /// This is the typedef of a function that should return an instance
173  /// of a subsidiary preconditioning operator. This preconditioner is
174  /// responsible for the destruction of the subsidiary preconditioners.
175  typedef Preconditioner* (*SubsidiaryPreconditionerFctPt)();
176 
177  /// Constructor - initialise variables.
179  {
180  // The null pointer.
182 
183  // By default, the linear systems associated with the diagonal blocks
184  // are solved "exactly" using SuperLU (in its incarnation as an exact
185  // preconditioner. This is not a block preconditioner.
187 
188  // Flag to indicate to use SuperLU or not.
190 
191  // Empty vector of meshes and set the number of meshes to zero.
192  My_mesh_pt.resize(0, 0);
193  My_nmesh = 0;
194 
195  // The number of DOF types within the meshes.
196  My_ndof_types_in_mesh.resize(0, 0);
197 
198  // Initialise other variables.
200  Scaling_sigma = 0.0;
202  N_fluid_doftypes = 0;
205  } // constructor
206 
207  /// Destructor
209  {
210  this->clean_up_memory();
211  }
212 
213  /// Broken copy constructor
215  const LagrangeEnforcedFlowPreconditioner&) = delete;
216 
217  /// Broken assignment operator
219 
220  /// Setup method for the LagrangeEnforcedFlowPreconditioner.
221  void setup();
222 
223  /// Apply the preconditioner.
224  /// r is the residual (rhs), z will contain the solution.
226 
227  /// Set the meshes,
228  /// the first mesh in the vector must be the bulk mesh.
229  void set_meshes(const Vector<Mesh*>& mesh_pt);
230 
231  /// Set flag to use the infinite norm of the Navier-Stokes F matrix
232  /// as the scaling sigma. This is the default behaviour. Note: the norm of
233  /// the NS F matrix positive, however, we actually use the negative of
234  /// the norm. This is because the underlying Navier-Stokes Jacobian is
235  /// multiplied by -1. Ask Andrew/Matthias for more detail.
237  {
239  }
240 
241  /// Access function to set the scaling sigma.
242  /// Note: this also sets the flag to use the infinite norm of
243  /// the Navier-Stokes F matrix as the scaling sigma to false.
244  /// Warning is given if trying to set scaling sigma to be equal to
245  /// or greater than zero.
246  void set_scaling_sigma(const double& scaling_sigma)
247  {
248  // Check if scaling sigma is zero or positive.
249 #ifdef PARANOID
250  if (scaling_sigma == 0.0)
251  {
252  std::ostringstream warning_stream;
253  warning_stream << "WARNING: \n"
254  << "Setting scaling_sigma = 0.0 may cause values.\n";
255  OomphLibWarning(warning_stream.str(),
256  OOMPH_CURRENT_FUNCTION,
257  OOMPH_EXCEPTION_LOCATION);
258  }
259  if (scaling_sigma > 0.0)
260  {
261  std::ostringstream warning_stream;
262  warning_stream << "WARNING: " << std::endl
263  << "The scaling (scaling_sigma) is positive: "
264  << Scaling_sigma << "\n"
265  << "Performance may be degraded.\n";
266  OomphLibWarning(warning_stream.str(),
267  OOMPH_CURRENT_FUNCTION,
268  OOMPH_EXCEPTION_LOCATION);
269  }
270 #endif
271 
274  }
275 
276  /// Read (const) function to get the scaling sigma.
277  double scaling_sigma() const
278  {
279  return Scaling_sigma;
280  }
281 
282  /// Set a new Navier-Stokes matrix preconditioner
283  /// (inexact solver)
285  Preconditioner* new_ns_preconditioner_pt = 0);
286 
287  /// Set Navier-Stokes matrix preconditioner (inexact
288  /// solver) to SuperLU
290  {
292  {
296  }
297  }
298 
299  /// Clears the memory.
300  void clean_up_memory();
301 
302  private:
303  /// Control flag is true if the preconditioner has been setup
304  /// (used so we can wipe the data when the preconditioner is
305  /// called again)
307 
308  /// Scaling for the augmentation: Scaling_sigma*(LL^T)
310 
311  /// Flag to indicate if we want to use the infinite norm of the
312  /// Navier-Stokes momentum block for the scaling sigma.
314 
315  /// Inverse W values
317 
318  /// Pointer to the 'preconditioner' for the Navier-Stokes block
320 
321  /// Flag to indicate if the preconditioner for the Navier-Stokes
322  /// block is a block preconditioner or not.
324 
325  /// Flag to indicate whether the default NS preconditioner is used
327 
328  /// Storage for the meshes. In our implementation, the first mesh
329  /// must always be the Navier-Stokes (bulk) mesh, followed by surface
330  /// meshes.
332 
333  /// The number of DOF types in each mesh. This is used create
334  /// various lookup lists.
336 
337  /// The number of meshes. This is used to create various lookup
338  /// lists.
339  unsigned My_nmesh;
340 
341  /// The number of Lagrange multiplier DOF types.
343 
344  /// The number of fluid DOF types (including pressure).
346 
347  /// The number of velocity DOF types.
349 
350  }; // end of LagrangeEnforcedFlowPreconditioner class
351 
352 } // namespace oomph
353 #endif
Block Preconditioner base class. The block structure of the overall problem is determined from the Me...
const Mesh * mesh_pt(const unsigned &i) const
Access to i-th mesh (of the various meshes that contain block preconditionable elements of the same n...
A class for compressed row matrices. This is a distributable object.
Definition: matrices.h:888
A vector in the mathematical sense, initially developed for linear algebra type applications....
Definition: double_vector.h:58
The preconditioner for the Lagrange multiplier constrained Navier-Stokes equations....
Preconditioner * Navier_stokes_preconditioner_pt
Pointer to the 'preconditioner' for the Navier-Stokes block.
unsigned N_lagrange_doftypes
The number of Lagrange multiplier DOF types.
void set_scaling_sigma(const double &scaling_sigma)
Access function to set the scaling sigma. Note: this also sets the flag to use the infinite norm of t...
unsigned N_fluid_doftypes
The number of fluid DOF types (including pressure).
void set_navier_stokes_preconditioner(Preconditioner *new_ns_preconditioner_pt=0)
Set a new Navier-Stokes matrix preconditioner (inexact solver)
LagrangeEnforcedFlowPreconditioner(const LagrangeEnforcedFlowPreconditioner &)=delete
Broken copy constructor.
bool Preconditioner_has_been_setup
Control flag is true if the preconditioner has been setup (used so we can wipe the data when the prec...
bool Use_norm_f_for_scaling_sigma
Flag to indicate if we want to use the infinite norm of the Navier-Stokes momentum block for the scal...
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the preconditioner. r is the residual (rhs), z will contain the solution.
double scaling_sigma() const
Read (const) function to get the scaling sigma.
Vector< unsigned > My_ndof_types_in_mesh
The number of DOF types in each mesh. This is used create various lookup lists.
LagrangeEnforcedFlowPreconditioner()
Constructor - initialise variables.
Vector< Vector< double > > Inv_w_diag_values
Inverse W values.
void set_meshes(const Vector< Mesh * > &mesh_pt)
Set the meshes, the first mesh in the vector must be the bulk mesh.
unsigned My_nmesh
The number of meshes. This is used to create various lookup lists.
void use_norm_f_for_scaling_sigma()
Set flag to use the infinite norm of the Navier-Stokes F matrix as the scaling sigma....
void operator=(const LagrangeEnforcedFlowPreconditioner &)=delete
Broken assignment operator.
double Scaling_sigma
Scaling for the augmentation: Scaling_sigma*(LL^T)
void setup()
Setup method for the LagrangeEnforcedFlowPreconditioner.
bool Using_superlu_ns_preconditioner
Flag to indicate whether the default NS preconditioner is used.
bool Navier_stokes_preconditioner_is_block_preconditioner
Flag to indicate if the preconditioner for the Navier-Stokes block is a block preconditioner or not.
void set_superlu_for_navier_stokes_preconditioner()
Set Navier-Stokes matrix preconditioner (inexact solver) to SuperLU.
Vector< Mesh * > My_mesh_pt
Storage for the meshes. In our implementation, the first mesh must always be the Navier-Stokes (bulk)...
unsigned N_velocity_doftypes
The number of velocity DOF types.
An OomphLibWarning object which should be created as a temporary object to issue a warning....
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
An interface to allow SuperLU to be used as an (exact) Preconditioner.
A slight extension to the standard template vector class so that we can include "graceful" array rang...
Definition: Vector.h:58
Preconditioner * boomer_amg_for_2D_momentum_stressdiv_visc()
Hypre Boomer AMG setting for the augmented momentum block of a 2D Navier-Stokes problem using the str...
Preconditioner * boomer_amg_for_3D_momentum()
Hypre Boomer AMG setting for the augmented momentum block of a 3D Navier-Stokes problem (for serial c...
Preconditioner * get_w_cg_preconditioner()
CG with diagonal preconditioner for W-block subsidiary linear systems.
Preconditioner * boomer_amg_for_3D_poisson_problem()
Hypre Boomer AMG setting for the 3D Poisson problem (for serial code).
Preconditioner * boomer_amg_for_2D_poisson_problem()
Hypre Boomer AMG setting for the 2D Poisson problem (for serial code).
Preconditioner * boomer_amg_for_2D_momentum_simple_visc()
Hypre Boomer AMG setting for the augmented momentum block of a 2D Navier-Stokes problem using the sim...
Preconditioner * boomer_amg2v22_for_3D_momentum()
Hypre Boomer AMG setting for the augmented momentum block of a 3D Navier-Stokes problem (for serial c...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...