fsi_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// Version 1.0; svn revision $LastChangedRevision$
7 //LIC//
8 //LIC// $LastChangedDate$
9 //LIC//
10 //LIC// Copyright (C) 2006-2016 Matthias Heil and Andrew Hazel
11 //LIC//
12 //LIC// This library is free software; you can redistribute it and/or
13 //LIC// modify it under the terms of the GNU Lesser General Public
14 //LIC// License as published by the Free Software Foundation; either
15 //LIC// version 2.1 of the License, or (at your option) any later version.
16 //LIC//
17 //LIC// This library is distributed in the hope that it will be useful,
18 //LIC// but WITHOUT ANY WARRANTY; without even the implied warranty of
19 //LIC// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 //LIC// Lesser General Public License for more details.
21 //LIC//
22 //LIC// You should have received a copy of the GNU Lesser General Public
23 //LIC// License along with this library; if not, write to the Free Software
24 //LIC// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 //LIC// 02110-1301 USA.
26 //LIC//
27 //LIC// The authors may be contacted at oomph-lib@maths.man.ac.uk.
28 //LIC//
29 //LIC//====================================================================
30 #ifndef OOMPH_FSI_PRECONDITIONERS_HEADER
31 #define OOMPH_FSI_PRECONDITIONERS_HEADER
32 
33 
34 
35 #include "../navier_stokes/navier_stokes_preconditioners.h"
36 
37 namespace oomph
38 {
39 
40 
41 ///////////////////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////////////////
43 ///////////////////////////////////////////////////////////////////////////////
44 
45 
46 
47 //============================================================================
48 /// \short FSI preconditioner. This extracts upper/lower triangular
49 /// blocks in the 3x3 overall block matrix structure arising from
50 /// the monolithic discretisation of FSI problems with algebraic
51 /// node updates. Dofs are decomposed into fluid velocity, pressure
52 /// and solid unknowns. NavierStokesSchurComplementPreconditioner is used
53 /// as the inexact solver for the fluid block; SuperLU (in
54 /// its incarnation as an "exact" preconditioner) is used for
55 /// the solid block. By default we retain the fluid on solid off
56 /// diagonal blocks.
57 //=============================================================================
58 class FSIPreconditioner : public BlockPreconditioner<CRDoubleMatrix>
59 {
60 
61 public :
62 
63  /// \short Constructor: By default use block triangular form with retained
64  /// fluid on solid terms. A problem pointer is required for the underlying
65  /// NavierStokesSchurComplementPreconditioner.
66  FSIPreconditioner(Problem* problem_pt)
67  {
68  // set the mesh pointers
69  this->set_nmesh(2);
71  Wall_mesh_pt = 0;
72 
73  // Initially assume that there are no multiple element types in the meshes.
76 
77  // Default setting: Fluid onto solid as it this was shown to be
78  // marginally faster than solid onto fluid; see Heil CMAME 193 (2004)
81 
82  // Create the Navier Stokes Schur complement preconditioner
84  new NavierStokesSchurComplementPreconditioner(problem_pt);
85 
86  // Create the Solid preconditioner
87  Solid_preconditioner_pt = new SuperLUPreconditioner;
88 
89  // Preconditioner hasn't been set up yet.
91 
92  // Create the matrix vector product operators
93  Matrix_vector_product_0_1_pt = new MatrixVectorProduct;
94  Matrix_vector_product_1_0_pt = new MatrixVectorProduct;
95 
96  // set Doc_time to false
97  Doc_time = false;
98  }
99 
100 
101  /// Destructor: Clean up.
103  {
104  //Delete the Navier-Stokes preconditioner (inexact solver)
106 
107  //Delete the solid preconditioner (inexact solver)
109 
110  // delete the matrix vector product operators
113  }
114 
115 
116  /// Broken copy constructor
118  {
119  BrokenCopy::broken_copy("FSIPreconditioner");
120  }
121 
122 
123  /// Broken assignment operator
124 //Commented out broken assignment operator because this can lead to a conflict warning
125 //when used in the virtual inheritence hierarchy. Essentially the compiler doesn't
126 //realise that two separate implementations of the broken function are the same and so,
127 //quite rightly, it shouts.
128  /*void operator=(const FSIPreconditioner&)
129  {
130  BrokenCopy::broken_assign("FSIPreconditioner");
131  }*/
132 
133 /// Set solid preconditioner (deletes existing one)
135  {
136  // Kill existing one
138  {
140  }
142  }
143 
144  /// Read-only access to solid preconditoner (use set_... to set it)
145  Preconditioner* solid_preconditioner_pt() const
146  {
148  }
149 
150 
151  /// Switch to block-diagonal preconditioner
153  {
156  }
157 
158  /// \short Switch to block-triangular preconditioner in which
159  /// action of fluid dofs onto solid equations is retained
161  {
164  }
165 
166  /// \short Switch to block-triangular preconditioner in which
167  /// action of solid dofs onto fluid equations is retained
169  {
172  }
173 
174  /// \short Setter function for the mesh containing the block-preconditionable
175  /// Navier-Stokes elements. The optional argument indicates if there are more
176  /// than one type of elements in same mesh.
178  (Mesh* mesh_pt,
179  const bool& allow_multiple_element_type_in_navier_stokes_mesh = false)
180  {
181  // Store the mesh pointer.
182  Navier_stokes_mesh_pt = mesh_pt;
183 
184  // Are there multiple element types in the Navier-Stokes mesh?
186  = allow_multiple_element_type_in_navier_stokes_mesh;
187  }
188 
189  /// \short Setter function for the mesh containing the block-preconditionable
190  /// FSI solid elements. The optional argument indicates if there are more
191  /// than one type of elements in the same mesh.
193  Mesh* mesh_pt, const bool& allow_multiple_element_type_in_wall_mesh = false)
194  {
195  // Store the mesh pointer
196  Wall_mesh_pt = mesh_pt;
197 
198  // Are there multiple element types in the wall mesh?
200  = allow_multiple_element_type_in_wall_mesh;
201  }
202 
203  /// \short Setup the preconditioner
204  void setup();
205 
206  /// \short Apply preconditioner to r
207  void preconditioner_solve(const DoubleVector &r,
208  DoubleVector &z);
209 
210  /// Access function to the Navier Stokes preconditioner (inexact solver)
211  NavierStokesSchurComplementPreconditioner*
213  {
215  }
216 
217  ///Enable documentation of time
218  void enable_doc_time() {Doc_time = true;}
219 
220  ///Disable documentation of time
221  void disable_doc_time() {Doc_time = false;}
222 
223 
224 private:
225 
226  /// Pointer the Navier Stokes preconditioner (inexact solver)
227  NavierStokesSchurComplementPreconditioner* Navier_stokes_preconditioner_pt;
228 
229  /// Pointer to the solid preconditioner (inexact solver)
230  Preconditioner* Solid_preconditioner_pt;
231 
232  /// Pointer to fluid/solid interaction matrix
233  MatrixVectorProduct* Matrix_vector_product_0_1_pt;
234 
235  /// Pointer to solid/fluid solid interaction matrix
236  MatrixVectorProduct* Matrix_vector_product_1_0_pt;
237 
238  /// Boolean indicating the preconditioner has been set up
240 
241  /// \short Boolean flag used to indicate that the solid onto fluid
242  /// interaction terms are to be retained
244 
245  /// \short Boolean flag used to indicate that the fluid onto solid
246  /// interaction terms are to be retained
248 
249  /// Set Doc_time to true for outputting results of timings
250  bool Doc_time;
251 
252  /// Pointer to the navier stokes mesh
254 
255  /// pointer to the solid mesh
257 
258  /// Flag to indicate if there are multiple element types in the Navier-Stokes
259  /// mesh.
261 
262  // Flag to indicate if there are multiple element types in the Wall mesh.
264  };
265 
266 
267 //////////////////////////////////////////////////////////////////////////////
268 //////////////////////////////////////////////////////////////////////////////
269 // FSI preconditioner member functions
270 //////////////////////////////////////////////////////////////////////////////
271 //////////////////////////////////////////////////////////////////////////////
272 
273 
274 
275 
276 //=============================================================================
277 /// Setup the preconditioner. Note: Matrix must be a CRDoubleMatrix.
278 //=============================================================================
280 {
281 
282  // check the meshes have been set
283 #ifdef PARANOID
284  if (Navier_stokes_mesh_pt==0)
285  {
286  std::ostringstream error_message;
287  error_message << "Pointer to fluid mesh hasn't been set!\n";
288  throw OomphLibError(error_message.str(),
289  OOMPH_CURRENT_FUNCTION,
290  OOMPH_EXCEPTION_LOCATION);
291  }
292  if (Wall_mesh_pt==0)
293  {
294  std::ostringstream error_message;
295  error_message << "Pointer to solid mesh hasn't been set!\n";
296  throw OomphLibError(error_message.str(),
297  OOMPH_CURRENT_FUNCTION,
298  OOMPH_EXCEPTION_LOCATION);
299  }
300 #endif
301 
302  // setup the meshes
303  this->set_mesh(0,Navier_stokes_mesh_pt,
306 
307  // get the number of fluid dofs from teh first element in the mesh
308  unsigned n_fluid_dof = this->ndof_types_in_mesh(0);
309  unsigned n_dof = n_fluid_dof + this->ndof_types_in_mesh(1);
310 
311  // this fsi preconditioner has two types of DOF fluid dofs and solid dofs
312  Vector<unsigned> dof_to_block_map(n_dof,0);
313  for (unsigned i = n_fluid_dof; i < n_dof; i++)
314  {
315  dof_to_block_map[i] = 1;
316  }
317 
318  // Call block setup for this preconditioner
319  this->block_setup(dof_to_block_map);
320 
321  // Block mapping for the subsidiary Navier Stokes preconditioner:
322  // blocks 0 and 1 in the FSI preconditioner are also blocks 0 and 1
323  // in the subsidiary Navier Stokes one.
324  Vector<unsigned> ns_dof_lookup(n_fluid_dof);
325  for (unsigned i = 0; i < n_fluid_dof; i++)
326  {
327  ns_dof_lookup[i] = i;
328  }
329 
330  // Turn the Navier Stokes Schur complement preconditioner into a
331  // subsidiary preconditioner of this preconditioner
333  turn_into_subsidiary_block_preconditioner(this,ns_dof_lookup);
334 
335  // Setup the navier stokes preconditioner: Tell it about the
336  // Navier Stokes mesh and set it up.
339  Navier_stokes_preconditioner_pt->setup(matrix_pt());
340 
341  // Extract the additional blocks we need for FSI:
342 
343  // Solid tangent stiffness matrix
344  CRDoubleMatrix block_matrix_1_1;
345  this->get_block(1,1,block_matrix_1_1);
346 
347  // Setup the solid preconditioner (inexact solver)
348  double t_start = TimingHelpers::timer();
349  Solid_preconditioner_pt->setup(&block_matrix_1_1);
350  double t_end = TimingHelpers::timer();
351  block_matrix_1_1.clear();
352  double setup_time= t_end-t_start;
353 
354  // Solid on fluid terms (if needed)
356  {
357  CRDoubleMatrix block_matrix_0_1 = get_block(0,1);
358  this->setup_matrix_vector_product(Matrix_vector_product_0_1_pt,
359  &block_matrix_0_1,1);
360  }
361 
362  // Fluid on solid terms (if needed)
364  {
365  CRDoubleMatrix block_matrix_1_0 = get_block(1,0);
366  this->setup_matrix_vector_product(Matrix_vector_product_1_0_pt,
367  &block_matrix_1_0,0);
368  }
369 
370  // Output times
371  if(Doc_time)
372  {
373  oomph_info << "Solid sub-preconditioner setup time [sec]: "
374  << setup_time << "\n";
375  }
376 
377  // We're done (and we stored some data)
379 }
380 
381 
382 //======================================================================
383 /// Apply preconditioner to Vector r
384 //======================================================================
385 void FSIPreconditioner::preconditioner_solve(const DoubleVector &r,
386  DoubleVector &z)
387 {
388  // if z is not setup then give it the same distribution
389  if (!z.built())
390  {
391  z.build(r.distribution_pt(),0.0);
392  }
393 
394  // Make copy of residual vector (to overcome const-ness
395  DoubleVector res(r);
396 
397 
398  // Retain off-diagonals that represent effect of solid on fluid
399  //-------------------------------------------------------------
401  {
402  // Working vectors
403  DoubleVector temp_solid_vec;
404  DoubleVector temp_fluid_vec;
405 
406  // Copy solid values from residual to temp_vec:
407  // Loop over all entries in the global vector (this one
408  // includes solid, velocity and pressure dofs in some random fashion)
409  get_block_vector(1,res,temp_solid_vec);
410 
411  // Solve solid system by back-substitution
412  // with LU-decomposed stiffness matrix
413  DoubleVector temp_solid_vec2;
414  Solid_preconditioner_pt->preconditioner_solve(temp_solid_vec,
415  temp_solid_vec2);
416  this->return_block_vector(1,temp_solid_vec2,z);
417 
418  // NOTE: temp_solid_vec now contains z_s = S^{-1} r_s
419 
420  // Multiply C_{us} by z_s
421  Matrix_vector_product_0_1_pt->multiply(temp_solid_vec2,temp_fluid_vec);
422  temp_solid_vec.clear();
423 
424  // Subtract from fluid residual vector for fluid solve
425  DoubleVector another_temp_vec;
426  this->get_block_vector(0,res,another_temp_vec);
427  another_temp_vec -= temp_fluid_vec;
428  this->return_block_vector(0,another_temp_vec,res);
429 
430  // now apply the navier stokes lsc preconditioner
431  Navier_stokes_preconditioner_pt->preconditioner_solve(res,z);
432  }
433 
434 
435  // Retain off-diagonals that represent effect of fluid on solid
436  //-------------------------------------------------------------
437  // (or diagonal preconditioner)
438  //-----------------------------
439  else
440  {
441 
442  // Call fluid preconditioner for fluid block
443  Navier_stokes_preconditioner_pt->preconditioner_solve(res,z);
444 
445  // Working vectors
446  DoubleVector temp_solid_vec;
447 
448  // get the solid vector
449  get_block_vector(1,res,temp_solid_vec);
450 
451  // Do matrix vector products with fluid onto solid coupling matrices:
453  {
454  DoubleVector temp_fluid_vec;
455  get_block_vector(0,z,temp_fluid_vec);
456 
457  // Auxiliary vector to hold the matrix vector product of the
458  // fluid-onto-solid coupling matrices with the fluid solutions:
459  DoubleVector aux_vec;
460 
461  // Multiply C_{su} by z_u
462  Matrix_vector_product_1_0_pt->multiply(temp_fluid_vec, aux_vec);
463 
464  // ...and subtract from r_s:
465  temp_solid_vec-=aux_vec;
466  }
467 
468  // Solve solid system by back-substitution
469  // with LU-decomposed stiffness matrix
470  DoubleVector temp_solid_vec2;
471  Solid_preconditioner_pt->preconditioner_solve(temp_solid_vec,
472  temp_solid_vec2);
473 
474  // Now copy result_vec (i.e. z_s) back into the global vector z.
475  // Loop over all entries in the global results vector z:
476  return_block_vector(1,temp_solid_vec2,z);
477  }
478 }
479 
480 
481 
482 ///////////////////////////////////////////////////////////////////////////
483 ///////////////////////////////////////////////////////////////////////////
484 ///////////////////////////////////////////////////////////////////////////
485 
486 
487 
488 //============================================================================
489 /// \short FSI preconditioner. This extracts upper/lower triangular
490 /// blocks in the 3x3 overall block matrix structure arising from
491 /// the monolithic discretisation of FSI problems with algebraic
492 /// node updates. Dofs are decomposed into fluid velocity, pressure
493 /// and solid unknowns. Blocks are then re-assembled into one global
494 /// matrix and solved with a direct solver (SuperLU in its incarnation
495 /// as an exact preconditioner). By default we retain the fluid on solid off
496 /// diagonal blocks.
497 //=============================================================================
498 template<typename MATRIX>
499 class SimpleFSIPreconditioner : public BlockPreconditioner<MATRIX>
500 {
501 
502 public :
503 
504  /// Constructor.
505  SimpleFSIPreconditioner() : BlockPreconditioner<MATRIX>()
506  {
507  // set the mesh pointers
509  Wall_mesh_pt = 0;
510  this->set_nmesh(2);
511 
512  // Default setting: Retain fluid on solid
515 
516  // Null the preconditioner pointer (inexact solver)
517  Preconditioner_pt = 0;
518 
519  // Initially assume that there are no multiple element types in
520  // the same mesh.
523  }
524 
525 
526  /// Destructor: Clean up
528  {
529  // Wiping preconditioner (inexact solver) wipes the stored
530  // LU decompositon
531  if (Preconditioner_pt != 0)
532  {
533  delete Preconditioner_pt;
534  Preconditioner_pt = 0;
535  }
536  }
537 
538 
539  /// Broken copy constructor
541  {
542  BrokenCopy::broken_copy("SimpleFSIPreconditioner");
543  }
544 
545 
546  /// Broken assignment operator
547  /*void operator=(const SimpleFSIPreconditioner&)
548  {
549  BrokenCopy::broken_assign("SimpleFSIPreconditioner");
550  }*/
551 
552  /// \short Setter function for the mesh containing the block-preconditionable
553  /// Navier-Stokes elements.
555  (Mesh* mesh_pt,
556  const bool& allow_multiple_element_type_in_navier_stokes_mesh = false)
557  {
558  // Store the mesh pointer.
559  Navier_stokes_mesh_pt = mesh_pt;
560 
561  // Are there multiple elements in this mesh?
563  = allow_multiple_element_type_in_navier_stokes_mesh;
564  }
565 
566  /// \short Setter function for the mesh containing the block-preconditionable
567  /// FSI solid elements.
568  void set_wall_mesh
569  (Mesh* mesh_pt,
570  const bool& allow_multiple_element_type_in_wall_mesh = false)
571  {
572  // Store the mesh pointer
573  Wall_mesh_pt = mesh_pt;
574 
575  // Are the multiple elements in this mesh?
577  = allow_multiple_element_type_in_wall_mesh;
578  }
579 
580  /// \short Setup the preconditioner
581  void setup();
582 
583  /// \short Apply preconditioner to r
584  void preconditioner_solve(const DoubleVector &r,
585  DoubleVector &z);
586 
587  /// Switch to block-diagonal preconditioner
589  {
592  }
593 
594  /// \short Switch to block-triangular preconditioner in which
595  /// action of fluid dofs onto solid equations is retained
597  {
600  }
601 
602  /// \short Switch to block-triangular preconditioner in which
603  /// action of solid dofs onto fluid equations is retained
605  {
608  }
609 
610 private:
611 
612  /// \short Preconditioner (inexact solver)
613  Preconditioner* Preconditioner_pt;
614 
615  /// \short Boolean flag used to indicate that the solid onto fluid
616  /// interaction terms are to be retained
618 
619  /// \short Boolean flag used to indicate that the fluid onto solid
620  /// interaction terms are to be retained
622 
623  /// \short Identify the required blocks: Here we only need
624  /// the momentum, gradient and divergence blocks of the
625  /// 2x2 block-structured fluid matrix, the 1x1 solid block
626  /// and the selected FSI-off diagonals.
627  virtual void identify_required_blocks(DenseMatrix<bool>& required_blocks);
628 
629  /// Pointer to the navier stokes mesh
631 
632  /// pointer to the solid mesh
634 
635  /// Flag for multiple element types in the Navier-Stokes mesh.
637 
638  /// Flag for multiple element types in the Wall mesh
640 };
641 
642 
643 ////////////////////////////////////////////////////////////////////////
644 ////////////////////////////////////////////////////////////////////////
645 // FSI preconditioner member functions
646 ////////////////////////////////////////////////////////////////////////
647 ////////////////////////////////////////////////////////////////////////
648 
649 
650 
651 //===========================================================================
652 /// Identify the required blocks: Here we only need
653 /// the momentum, gradient and divergence blocks of the
654 /// 2x2 block-structured fluid matrix, the 1x1 solid block
655 /// and the selected FSI-off diagonals.
656 //===========================================================================
657 template<typename MATRIX>
659  DenseMatrix<bool>& required_blocks)
660 {
661 
662  // find number of block types
663  unsigned n_dof = this->nblock_types();
664 
665  // Initialise all blocks to false
666  for (unsigned i=0;i<n_dof;i++)
667  {
668  for (unsigned j=0;j<n_dof;j++)
669  {
670  required_blocks(i,j)=false;
671  }
672  }
673 
674  // Fluid: Only need momentum, gradient and divergence blocks
675  required_blocks(0,0) = true;
676  required_blocks(1,0) = true;
677  required_blocks(0,1) = true;
678 
679  // Always retain the solid block
680  required_blocks(2,2) = true;
681 
682  // Switch on the required off-diagonals
684  {
685  required_blocks(0,2)=true;
686  required_blocks(1,2)=true;
687  }
689  {
690  required_blocks(2,0)=true;
691  required_blocks(2,1)=true;
693  {
694  std::ostringstream error_message;
695  error_message << "Can't retain all off-diagonal blocks!\n";
696  throw OomphLibError(error_message.str(),
697  OOMPH_CURRENT_FUNCTION,
698  OOMPH_EXCEPTION_LOCATION);
699  }
700  }
701 
702 }
703 
704 
705 //=============================================================================
706 /// Setup the preconditioner: Copy the upper/lower triangular
707 /// block matrices back into a big matrix (with the entries
708 /// re-ordered relative to the original Jacobian matrix).
709 //=============================================================================
710  template<typename MATRIX>
713  {
714 
715  // Clean up memory
716  if (Preconditioner_pt != 0)
717  {
718  delete Preconditioner_pt;
719  Preconditioner_pt = 0;
720  }
721  #ifdef PARANOID
722  if (Navier_stokes_mesh_pt==0)
723  {
724  std::ostringstream error_message;
725  error_message << "Pointer to fluid mesh hasn't been set!\n";
726  throw OomphLibError(error_message.str(),
727  OOMPH_CURRENT_FUNCTION,
728  OOMPH_EXCEPTION_LOCATION);
729  }
730  if (Wall_mesh_pt==0)
731  {
732  std::ostringstream error_message;
733  error_message << "Pointer to solid mesh hasn't been set!\n";
734  throw OomphLibError(error_message.str(),
735  OOMPH_CURRENT_FUNCTION,
736  OOMPH_EXCEPTION_LOCATION);
737  }
738 #endif
739 
740  // setup the meshes
741  this->set_mesh(0,Navier_stokes_mesh_pt,
744 
745  // get the number of fluid dofs from the first element in the mesh
746  unsigned n_fluid_dof = this->ndof_types_in_mesh(0);
747  unsigned n_dof = n_fluid_dof + this->ndof_types_in_mesh(1);
748 
749  // this fsi preconditioner has two types of DOF fluid dofs and solid dofs
750  Vector<unsigned> dof_to_block_map(n_dof,0);
751  dof_to_block_map[n_fluid_dof-1]=1; // pressure
752  for (unsigned i = n_fluid_dof; i < n_dof; i++) //solid
753  {
754  dof_to_block_map[i] = 2;
755  }
756 
757  // Set up the blocks look up schemes
758  this->block_setup(dof_to_block_map);
759 
760  // find number of block types
761  n_dof = this->nblock_types();
762 
763  // Create matrix that indicates which blocks are required
764  DenseMatrix<bool> required_blocks(n_dof,n_dof);
765 
766  // Identify required blocks
767  identify_required_blocks(required_blocks);
768 
769  VectorMatrix<BlockSelector> selected_blocks(n_dof,n_dof);
770 
771  for (unsigned dof_i = 0; dof_i < n_dof; dof_i++)
772  {
773  for (unsigned dof_j = 0; dof_j < n_dof; dof_j++)
774  {
775  selected_blocks[dof_i][dof_j].select_block(dof_i,dof_j,false,0);
776 
777  if(required_blocks(dof_i,dof_j))
778  {
779  selected_blocks[dof_i][dof_j].want_block();
780  }
781  }
782  }
783 
784  CRDoubleMatrix P_matrix = this->get_concatenated_block(selected_blocks);
785 
786  // Setup preconditioner (i.e. inexact solver) -- does the LU decomposition
787  Preconditioner_pt = new SuperLUPreconditioner;
788  Preconditioner_pt->setup(&P_matrix);
789  }
790 
791 
792 //======================================================================
793 /// Apply preconditioner to Vector r
794 //======================================================================
795 template<typename MATRIX>
797 preconditioner_solve(const DoubleVector &r, DoubleVector &z)
798 {
799  // create a temporary vector to hold the result of preconditioning
800  DoubleVector temp_vec;
801 
802  // get the reordered vector
803  this->get_block_ordered_preconditioner_vector(r,temp_vec);
804 
805  // apply preconditioner to z and store in r
806  Preconditioner_pt->preconditioner_solve(temp_vec,temp_vec);
807 
808  // copy the solution back
809  this->return_block_ordered_preconditioner_vector(temp_vec,z);
810 }
811 
812 
813 
814 ///////////////////////////////////////////////////////////////////////////
815 ///////////////////////////////////////////////////////////////////////////
816 ///////////////////////////////////////////////////////////////////////////
817 
818 
819 }
820 
821 #endif
Mesh * Navier_stokes_mesh_pt
Pointer to the navier stokes mesh.
void use_block_triangular_version_with_fluid_on_solid()
Switch to block-triangular preconditioner in which action of fluid dofs onto solid equations is retai...
Mesh * Wall_mesh_pt
pointer to the solid mesh
Preconditioner * Preconditioner_pt
Preconditioner (inexact solver)
NavierStokesSchurComplementPreconditioner * Navier_stokes_preconditioner_pt
Pointer the Navier Stokes preconditioner (inexact solver)
void disable_doc_time()
Disable documentation of time.
Preconditioner * solid_preconditioner_pt() const
Read-only access to solid preconditoner (use set_... to set it)
FSI preconditioner. This extracts upper/lower triangular blocks in the 3x3 overall block matrix struc...
bool Allow_multiple_element_type_in_navier_stokes_mesh
Flag for multiple element types in the Navier-Stokes mesh.
void enable_doc_time()
Enable documentation of time.
void set_wall_mesh(Mesh *mesh_pt, const bool &allow_multiple_element_type_in_wall_mesh=false)
Setter function for the mesh containing the block-preconditionable FSI solid elements. The optional argument indicates if there are more than one type of elements in the same mesh.
virtual void identify_required_blocks(DenseMatrix< bool > &required_blocks)
Identify the required blocks: Here we only need the momentum, gradient and divergence blocks of the 2...
NavierStokesSchurComplementPreconditioner * navier_stokes_preconditioner_pt() const
Access function to the Navier Stokes preconditioner (inexact solver)
void use_block_diagonal_version()
Switch to block-diagonal preconditioner.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
bool Allow_multiple_element_type_in_wall_mesh
Flag for multiple element types in the Wall mesh.
bool Retain_solid_onto_fluid_terms
Boolean flag used to indicate that the solid onto fluid interaction terms are to be retained...
void use_block_triangular_version_with_solid_on_fluid()
Switch to block-triangular preconditioner in which action of solid dofs onto fluid equations is retai...
Preconditioner * Solid_preconditioner_pt
Pointer to the solid preconditioner (inexact solver)
Mesh * Wall_mesh_pt
pointer to the solid mesh
MatrixVectorProduct * Matrix_vector_product_0_1_pt
Pointer to fluid/solid interaction matrix.
FSI preconditioner. This extracts upper/lower triangular blocks in the 3x3 overall block matrix struc...
bool Retain_solid_onto_fluid_terms
Boolean flag used to indicate that the solid onto fluid interaction terms are to be retained...
FSIPreconditioner(const FSIPreconditioner &)
Broken copy constructor.
SimpleFSIPreconditioner(const SimpleFSIPreconditioner &)
Broken copy constructor.
~SimpleFSIPreconditioner()
Destructor: Clean up.
void setup()
Setup the preconditioner.
bool Retain_fluid_onto_solid_terms
Boolean flag used to indicate that the fluid onto solid interaction terms are to be retained...
FSIPreconditioner(Problem *problem_pt)
Constructor: By default use block triangular form with retained fluid on solid terms. A problem pointer is required for the underlying NavierStokesSchurComplementPreconditioner.
bool Retain_fluid_onto_solid_terms
Boolean flag used to indicate that the fluid onto solid interaction terms are to be retained...
void set_navier_stokes_mesh(Mesh *mesh_pt, const bool &allow_multiple_element_type_in_navier_stokes_mesh=false)
Setter function for the mesh containing the block-preconditionable Navier-Stokes elements. The optional argument indicates if there are more than one type of elements in same mesh.
MatrixVectorProduct * Matrix_vector_product_1_0_pt
Pointer to solid/fluid solid interaction matrix.
void use_block_diagonal_version()
Switch to block-diagonal preconditioner.
bool Doc_time
Set Doc_time to true for outputting results of timings.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
void use_block_triangular_version_with_solid_on_fluid()
Switch to block-triangular preconditioner in which action of solid dofs onto fluid equations is retai...
~FSIPreconditioner()
Destructor: Clean up.
bool Preconditioner_has_been_setup
Boolean indicating the preconditioner has been set up.
void set_solid_preconditioner_pt(Preconditioner *solid_preconditioner_pt)
Broken assignment operator.
void setup()
Setup the preconditioner.
Mesh * Navier_stokes_mesh_pt
Pointer to the navier stokes mesh.
void use_block_triangular_version_with_fluid_on_solid()
Switch to block-triangular preconditioner in which action of fluid dofs onto solid equations is retai...