33 namespace Lagrange_Enforced_Flow_Preconditioner_Subsidiary_Operator_Helper
39 #ifdef OOMPH_HAS_TRILINOS
51 prec_pt->max_iter() = 4;
53 prec_pt->solver_pt()->disable_doc_time();
56 std::ostringstream err_msg;
57 err_msg <<
"Inner CG preconditioner is unavailable.\n"
58 <<
"Please install Trilinos.\n";
60 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
69 #ifdef OOMPH_HAS_HYPRE
94 return hypre_preconditioner_pt;
96 std::ostringstream err_msg;
97 err_msg <<
"hypre preconditioner is not available.\n"
98 <<
"Please install Hypre.\n";
100 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
109 #ifdef OOMPH_HAS_HYPRE
134 return hypre_preconditioner_pt;
136 std::ostringstream err_msg;
137 err_msg <<
"hypre preconditioner is not available.\n"
138 <<
"Please install Hypre.\n";
140 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
148 #ifdef OOMPH_HAS_HYPRE
173 return hypre_preconditioner_pt;
175 std::ostringstream err_msg;
176 err_msg <<
"hypre preconditioner is not available.\n"
177 <<
"Please install Hypre.\n";
179 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
187 #ifdef OOMPH_HAS_HYPRE
212 return hypre_preconditioner_pt;
214 std::ostringstream err_msg;
215 err_msg <<
"hypre preconditioner is not available.\n"
216 <<
"Please install Hypre.\n";
218 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
227 #ifdef OOMPH_HAS_HYPRE
252 return hypre_preconditioner_pt;
254 std::ostringstream err_msg;
255 err_msg <<
"hypre preconditioner is not available.\n"
256 <<
"Please install Hypre.\n";
258 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
266 #ifdef OOMPH_HAS_HYPRE
291 return hypre_preconditioner_pt;
293 std::ostringstream err_msg;
294 err_msg <<
"hypre preconditioner is not available.\n"
295 <<
"Please install Hypre.\n";
297 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
316 std::ostringstream error_message;
317 error_message <<
"setup() must be called before using "
318 <<
"preconditioner_solve()";
320 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
326 std::ostringstream error_message;
327 error_message <<
"The vectors z and r must have the same number of "
330 OOMPH_CURRENT_FUNCTION,
331 OOMPH_EXCEPTION_LOCATION);
366 const unsigned vec_nrow_local = temp_vec.
nrow_local();
367 double* vec_values_pt = temp_vec.
values_pt();
368 for (
unsigned i = 0;
i < vec_nrow_local;
i++)
392 fluid_block_indices[b] = b;
405 fluid_block_indices, another_temp_vec, z);
407 another_temp_vec.
clear();
428 std::ostringstream err_msg;
429 err_msg <<
"There should be at least two meshes.\n";
431 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
435 for (
unsigned mesh_i = 0; mesh_i <
nmesh; mesh_i++)
439 std::ostringstream err_msg;
440 err_msg <<
"The pointer mesh_pt[" << mesh_i <<
"] is null.\n";
442 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
462 if (elemental_dim != nodal_dim)
464 std::ostringstream err_msg;
465 err_msg <<
"In the first mesh, the elements have elemental dimension "
466 <<
"of " << elemental_dim <<
",\n"
467 <<
"with a nodal dimension of " << nodal_dim <<
".\n"
468 <<
"The first mesh does not contain 'bulk' elements.\n"
469 <<
"Please re-order your mesh_pt vector.\n";
472 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
480 for (
unsigned mesh_i = 0; mesh_i <
nmesh; mesh_i++)
517 std::ostringstream err_msg;
518 err_msg <<
"There are no meshes set. Please call set_meshes(...)\n"
519 <<
"with at least two mesh.";
521 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
574 for (
unsigned mesh_i = 0; mesh_i <
My_nmesh; mesh_i++)
581 unsigned spatial_dim =
My_mesh_pt[0]->nodal_dimension();
600 unsigned tmp_ndof_types = 0;
601 for (
unsigned mesh_i = 0; mesh_i <
My_nmesh; mesh_i++)
606 if (tmp_ndof_types != n_dof_types)
608 std::ostringstream err_msg;
609 err_msg <<
"The number of DOF types are incorrect.\n"
610 <<
"The total DOF types from the meshes is: " << tmp_ndof_types
612 <<
"The number of DOF types from "
613 <<
"BlockPreconditioner::ndof_types() is " << n_dof_types
616 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
702 unsigned temp_index = 0;
705 unsigned velocity_number = 0;
711 for (
unsigned mesh_i = 0; mesh_i <
My_nmesh; mesh_i++)
714 for (
unsigned dim_i = 0; dim_i < spatial_dim; dim_i++)
716 dof_to_block_map[temp_index++] = velocity_number++;
721 for (
unsigned doftype_i = spatial_dim; doftype_i < ndof_type_in_mesh_i;
724 dof_to_block_map[temp_index++] = pres_lgr_number++;
745 this->
get_block(row_i, col_i, *v_aug_pt(row_i, col_i));
759 std::ostringstream warning_stream;
760 warning_stream <<
"WARNING: " << std::endl
763 <<
"Division by 0 will occur."
766 warning_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
770 std::ostringstream warning_stream;
771 warning_stream <<
"WARNING: " << std::endl
772 <<
"The scaling (Scaling_sigma) is positive: "
774 <<
"Performance may be degraded." << std::endl;
776 warning_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
819 this->
get_block(lgr_block_num, col_i, *mm_temp_pt);
822 if (mm_temp_pt->
nnz() > 0)
824 mm_locations.push_back(col_i);
825 mm_pt.push_back(mm_temp_pt);
838 std::ostringstream warning_stream;
839 warning_stream <<
"WARNING:\n"
840 <<
"There are no mass matrices on Lagrange block row "
842 <<
"Perhaps the problem setup is incorrect."
845 OOMPH_CURRENT_FUNCTION,
846 OOMPH_EXCEPTION_LOCATION);
851 for (
unsigned mm_i = 0; mm_i < n_mm; mm_i++)
855 this->
get_block(mm_locations[mm_i], lgr_block_num, *mm_temp_pt);
857 if (mm_temp_pt->
nnz() > 0)
859 mmt_pt.push_back(mm_temp_pt);
866 std::ostringstream warning_stream;
867 warning_stream <<
"WARNING:\n"
868 <<
"The mass matrix block " << mm_locations[mm_i]
869 <<
" in L^T block " << l_i <<
" is zero.\n"
870 <<
"Perhaps the problem setup is incorrect."
873 OOMPH_CURRENT_FUNCTION,
874 OOMPH_EXCEPTION_LOCATION);
887 unsigned long l_i_nrow_local =
891 unsigned l_i_first_row =
898 for (
unsigned m_i = 0; m_i < n_mm; m_i++)
903 mm_pt[m_i]->multiply(*mmt_pt[m_i], temp_mm_sqrd);
909 for (
unsigned long row_i = 0; row_i < l_i_nrow_local; row_i++)
911 w_i_diag_values[row_i] += m_diag[row_i];
921 for (
unsigned long row_i = 0; row_i < l_i_nrow_local; row_i++)
923 invw_i_diag_values[row_i] =
Scaling_sigma / w_i_diag_values[row_i];
925 w_i_column_indices[row_i] = row_i + l_i_first_row;
926 w_i_row_start[row_i] = row_i;
929 w_i_row_start[l_i_nrow_local] = l_i_nrow_local;
933 unsigned long l_i_nrow_global =
936 l_i_nrow_global, invw_i_diag_values, w_i_column_indices, w_i_row_start);
947 for (
unsigned ii = 0; ii < n_mm; ii++)
950 unsigned aug_i = mm_locations[ii];
952 for (
unsigned jj = 0; jj < n_mm; jj++)
955 unsigned aug_j = mm_locations[jj];
962 mmt_pt[ii]->multiply((*inv_w_pt), (aug_block));
965 aug_block.
multiply(*mm_pt[jj], another_aug_block);
968 v_aug_pt(aug_i, aug_j)
969 ->add(another_aug_block, *v_aug_pt(aug_i, aug_j));
976 for (
unsigned m_i = 0; m_i < n_mm; m_i++)
997 for (
unsigned dof_i = 0; dof_i < n_dof_types; dof_i++)
999 block_to_dof_map[dof_to_block_map[dof_i]] = dof_i;
1006 unsigned temp_dof_row_i = block_to_dof_map[block_row_i];
1010 unsigned temp_dof_col_i = block_to_dof_map[block_col_i];
1012 temp_dof_row_i, temp_dof_col_i, v_aug_pt(block_row_i, block_col_i));
1031 if (navier_stokes_block_preconditioner_pt == 0)
1089 unsigned temp_dof_number = 0;
1093 for (
unsigned mesh_i = 0; mesh_i <
My_nmesh; mesh_i++)
1096 for (
unsigned dim_i = 0; dim_i < spatial_dim; dim_i++)
1098 dof_number_in_master_map.push_back(temp_dof_number + dim_i);
1106 dof_number_in_master_map.push_back(spatial_dim);
1128 for (
unsigned direction = 0; direction < spatial_dim; direction++)
1131 for (
unsigned mesh_i = 0; mesh_i <
My_nmesh; mesh_i++)
1133 dir_doftypes_vec[mesh_i] = spatial_dim * mesh_i + direction;
1135 doftype_coarsen_map.push_back(dir_doftypes_vec);
1141 ns_p_vec[0] =
My_nmesh * spatial_dim;
1143 doftype_coarsen_map.push_back(ns_p_vec);
1147 navier_stokes_block_preconditioner_pt
1149 this, dof_number_in_master_map, doftype_coarsen_map);
1166 f_aug_blocks[block_i][block_j].select_block(block_i, block_j,
true);
1184 std::ostringstream err_msg;
1185 err_msg <<
"Not using SuperLUPreconditioner for NS block,\n"
1186 <<
"but the Navier_stokes_preconditioner_pt is null.\n";
1188 err_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
1198 const unsigned v_aug_nrow = v_aug_pt.
nrow();
1199 const unsigned v_aug_ncol = v_aug_pt.
ncol();
1200 for (
unsigned v_row = 0; v_row < v_aug_nrow; v_row++)
1202 for (
unsigned v_col = 0; v_col < v_aug_ncol; v_col++)
1204 delete v_aug_pt(v_row, v_col);
1205 v_aug_pt(v_row, v_col) = 0;
1218 if (new_ns_preconditioner_pt == 0)
1220 std::ostringstream warning_stream;
1221 warning_stream <<
"WARNING: \n"
1222 <<
"The LSC preconditioner point is null.\n"
1223 <<
"Using default (SuperLU) preconditioner.\n"
1226 warning_stream.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
unsigned nmesh() const
Return the number of meshes in Mesh_pt.
void return_block_vector(const unsigned &n, const DoubleVector &b, DoubleVector &v) const
Takes the n-th block ordered vector, b, and copies its entries to the appropriate entries in the natu...
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...
CRDoubleMatrix get_concatenated_block(const VectorMatrix< BlockSelector > &selected_block)
Returns a concatenation of the block matrices specified by the argument selected_block....
Vector< LinearAlgebraDistribution * > Block_distribution_pt
The distribution for the blocks.
void return_concatenated_block_vector(const Vector< unsigned > &block_vec_number, const DoubleVector &b, DoubleVector &v) const
Takes concatenated block ordered vector, b, and copies its entries to the appropriate entries in the ...
void get_block(const unsigned &i, const unsigned &j, CRDoubleMatrix &output_matrix, const bool &ignore_replacement_block=false) const
Put block (i,j) into output_matrix. This block accounts for any coarsening of dof types and any repla...
void clear_block_preconditioner_base()
Clears all BlockPreconditioner data. Called by the destructor and the block_setup(....
void get_block_vector(const unsigned &n, const DoubleVector &v, DoubleVector &b) const
Takes the naturally ordered vector, v and returns the n-th block vector, b. Here n is the block numbe...
void set_replacement_dof_block(const unsigned &block_i, const unsigned &block_j, CRDoubleMatrix *replacement_dof_block_pt)
Set replacement dof-level blocks. Only dof-level blocks can be set. This is important due to how the ...
CRDoubleMatrix * matrix_pt() const
Access function to matrix_pt. If this is the master then cast the matrix pointer to MATRIX*,...
bool is_subsidiary_block_preconditioner() const
Return true if this preconditioner is a subsidiary preconditioner.
unsigned ndof_types() const
Return the total number of DOF types.
void turn_into_subsidiary_block_preconditioner(BlockPreconditioner< MATRIX > *master_block_prec_pt, const Vector< unsigned > &doftype_in_master_preconditioner_coarse)
Function to turn this preconditioner into a subsidiary preconditioner that operates within a bigger "...
void set_nmesh(const unsigned &n)
Specify the number of meshes required by this block preconditioner. Note: elements in different meshe...
virtual void block_setup()
Determine the size of the matrix blocks and setup the lookup schemes relating the global degrees of f...
void get_concatenated_block_vector(const Vector< unsigned > &block_vec_number, const DoubleVector &v, DoubleVector &b)
Takes the naturally ordered vector and extracts the blocks indicated by the block number (the values)...
void set_mesh(const unsigned &i, const Mesh *const mesh_pt, const bool &allow_multiple_element_type_in_mesh=false)
Set the i-th mesh for this block preconditioner. Note: The method set_nmesh(...) must be called befor...
A class for compressed row matrices. This is a distributable object.
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
Vector< double > diagonal_entries() const
returns a Vector of diagonal entries of this matrix. This only works with square matrices....
void build(const LinearAlgebraDistribution *distribution_pt, const unsigned &ncol, const Vector< double > &value, const Vector< int > &column_index, const Vector< int > &row_start)
build method: vector of values, vector of column indices, vector of row starts and number of rows and...
//////////////////////////////////////////////////////////////////////////// ////////////////////////...
unsigned long nrow() const
Return the number of rows of the matrix.
unsigned long ncol() const
Return the number of columns of the matrix.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
unsigned nrow() const
access function to the number of global rows.
unsigned nrow_local() const
access function for the num of local rows on this processor.
A vector in the mathematical sense, initially developed for linear algebra type applications....
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
double * values_pt()
access function to the underlying values
void clear()
wipes the DoubleVector
///////////////////////////////////////////////////////////////////// ///////////////////////////////...
unsigned & amg_smoother_iterations()
Access function to AMG_smoother_iterations.
unsigned & amg_simple_smoother()
Access function to AMG_simple_smoother flag.
double & amg_strength()
Access function to AMG_strength.
double & amg_damping()
Access function to AMG_damping parameter.
void set_amg_iterations(const unsigned &amg_iterations)
Function to set the number of times to apply BoomerAMG.
unsigned & amg_coarsening()
Access function to AMG_coarsening flag.
A preconditioner for performing inner iteration preconditioner solves. The template argument SOLVER s...
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.
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)
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.
Vector< unsigned > My_ndof_types_in_mesh
The number of DOF types in each mesh. This is used create various lookup lists.
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.
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 clean_up_memory()
Clears the memory.
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.
bool built() const
if the communicator_pt is null then the distribution is not setup then false is returned,...
Matrix-based diagonal preconditioner.
unsigned nodal_dimension() const
Return number of nodal dimension in mesh.
unsigned elemental_dimension() const
Return number of elemental dimension in mesh.
An OomphLibError object which should be thrown when an run-time error is encountered....
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...
void setup(DoubleMatrixBase *matrix_pt)
Setup the preconditioner: store the matrix pointer and the communicator pointer then call preconditio...
virtual void preconditioner_solve(const DoubleVector &r, DoubleVector &z)=0
Apply the preconditioner. Pure virtual generic interface function. This method should apply the preco...
An interface to allow SuperLU to be used as an (exact) Preconditioner.
An interface to the Trilinos AztecOO classes allowing it to be used as an Oomph-lib LinearSolver....
VectorMatrix is a generalised, STL-map-based, matrix based on a Vector of Vectors.
double inf_norm(const DenseMatrix< CRDoubleMatrix * > &matrix_pt)
Compute infinity (maximum) norm of sub blocks as if it was one matrix.
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...
//////////////////////////////////////////////////////////////////// ////////////////////////////////...