37 namespace Lagrange_Enforced_Flow_Preconditioner_Subsidiary_Operator_Helper
43 #ifdef OOMPH_HAS_TRILINOS 55 prec_pt->max_iter() = 4;
57 prec_pt->solver_pt()->disable_doc_time();
60 std::ostringstream err_msg;
61 err_msg <<
"Inner CG preconditioner is unavailable.\n" 62 <<
"Please install Trilinos.\n";
64 OOMPH_CURRENT_FUNCTION,
65 OOMPH_EXCEPTION_LOCATION);
74 #ifdef OOMPH_HAS_HYPRE 99 return hypre_preconditioner_pt;
101 std::ostringstream err_msg;
102 err_msg <<
"hypre preconditioner is not available.\n" 103 <<
"Please install Hypre.\n";
105 OOMPH_CURRENT_FUNCTION,
106 OOMPH_EXCEPTION_LOCATION);
115 #ifdef OOMPH_HAS_HYPRE 140 return hypre_preconditioner_pt;
142 std::ostringstream err_msg;
143 err_msg <<
"hypre preconditioner is not available.\n" 144 <<
"Please install Hypre.\n";
146 OOMPH_CURRENT_FUNCTION,
147 OOMPH_EXCEPTION_LOCATION);
155 #ifdef OOMPH_HAS_HYPRE 180 return hypre_preconditioner_pt;
182 std::ostringstream err_msg;
183 err_msg <<
"hypre preconditioner is not available.\n" 184 <<
"Please install Hypre.\n";
186 OOMPH_CURRENT_FUNCTION,
187 OOMPH_EXCEPTION_LOCATION);
195 #ifdef OOMPH_HAS_HYPRE 220 return hypre_preconditioner_pt;
222 std::ostringstream err_msg;
223 err_msg <<
"hypre preconditioner is not available.\n" 224 <<
"Please install Hypre.\n";
226 OOMPH_CURRENT_FUNCTION,
227 OOMPH_EXCEPTION_LOCATION);
237 #ifdef OOMPH_HAS_HYPRE 262 return hypre_preconditioner_pt;
264 std::ostringstream err_msg;
265 err_msg <<
"hypre preconditioner is not available.\n" 266 <<
"Please install Hypre.\n";
268 OOMPH_CURRENT_FUNCTION,
269 OOMPH_EXCEPTION_LOCATION);
277 #ifdef OOMPH_HAS_HYPRE 302 return hypre_preconditioner_pt;
304 std::ostringstream err_msg;
305 err_msg <<
"hypre preconditioner is not available.\n" 306 <<
"Please install Hypre.\n";
308 OOMPH_CURRENT_FUNCTION,
309 OOMPH_EXCEPTION_LOCATION);
325 if (Preconditioner_has_been_setup==
false)
327 std::ostringstream error_message;
328 error_message <<
"setup() must be called before using " 329 <<
"preconditioner_solve()";
332 OOMPH_CURRENT_FUNCTION,
333 OOMPH_EXCEPTION_LOCATION);
339 std::ostringstream error_message;
340 error_message <<
"The vectors z and r must have the same number of " 344 OOMPH_CURRENT_FUNCTION,
345 OOMPH_EXCEPTION_LOCATION);
371 for(
unsigned l_i = 0; l_i < N_lagrange_doftypes; l_i++)
374 const unsigned l_ii = N_fluid_doftypes + l_i;
377 this->get_block_vector(l_ii,r,temp_vec);
380 const unsigned vec_nrow_local = temp_vec.
nrow_local();
381 double* vec_values_pt = temp_vec.
values_pt();
382 for (
unsigned i = 0;
i < vec_nrow_local;
i++)
385 = vec_values_pt[
i]*Inv_w_diag_values[l_i][
i];
389 this->return_block_vector(l_ii,temp_vec,z);
401 if(Using_superlu_ns_preconditioner)
405 for (
unsigned b = 0; b < N_fluid_doftypes; b++)
407 fluid_block_indices[b] = b;
410 this->get_concatenated_block_vector(fluid_block_indices,r,temp_vec);
413 Navier_stokes_preconditioner_pt
414 ->preconditioner_solve(temp_vec,another_temp_vec);
419 this->return_concatenated_block_vector(fluid_block_indices,
422 another_temp_vec.
clear();
428 Navier_stokes_preconditioner_pt->preconditioner_solve(r,z);
438 const unsigned nmesh = mesh_pt.size();
443 std::ostringstream err_msg;
444 err_msg <<
"There should be at least two meshes.\n";
446 OOMPH_CURRENT_FUNCTION,
447 OOMPH_EXCEPTION_LOCATION);
451 for(
unsigned mesh_i = 0; mesh_i < nmesh; mesh_i++)
453 if (mesh_pt[mesh_i]==0)
455 std::ostringstream err_msg;
456 err_msg <<
"The pointer mesh_pt[" << mesh_i <<
"] is null.\n";
458 OOMPH_CURRENT_FUNCTION,
459 OOMPH_EXCEPTION_LOCATION);
469 const unsigned elemental_dim = mesh_pt[0]->elemental_dimension();
473 const unsigned nodal_dim = mesh_pt[0]->nodal_dimension();
479 if (elemental_dim != nodal_dim)
481 std::ostringstream err_msg;
482 err_msg <<
"In the first mesh, the elements have elemental dimension " 483 <<
"of " << elemental_dim <<
",\n" 484 <<
"with a nodal dimension of " << nodal_dim <<
".\n" 485 <<
"The first mesh does not contain 'bulk' elements.\n" 486 <<
"Please re-order your mesh_pt vector.\n";
489 OOMPH_CURRENT_FUNCTION,
490 OOMPH_EXCEPTION_LOCATION);
495 this->set_nmesh(nmesh);
498 for(
unsigned mesh_i = 0; mesh_i < nmesh; mesh_i++)
500 this->set_mesh(mesh_i,mesh_pt[mesh_i]);
513 My_mesh_pt = mesh_pt;
528 this->clean_up_memory();
535 std::ostringstream err_msg;
536 err_msg <<
"There are no meshes set. Please call set_meshes(...)\n" 537 <<
"with at least two mesh.";
539 OOMPH_CURRENT_FUNCTION,
540 OOMPH_EXCEPTION_LOCATION);
591 if(My_ndof_types_in_mesh.size() == 0)
593 for (
unsigned mesh_i = 0; mesh_i < My_nmesh; mesh_i++)
595 My_ndof_types_in_mesh.push_back(My_mesh_pt[mesh_i]->ndof_types());
600 unsigned spatial_dim = My_mesh_pt[0]->nodal_dimension();
603 unsigned n_dof_types = ndof_types();
617 if(is_subsidiary_block_preconditioner())
619 unsigned tmp_ndof_types = 0;
620 for (
unsigned mesh_i = 0; mesh_i < My_nmesh; mesh_i++)
622 tmp_ndof_types += My_ndof_types_in_mesh[mesh_i];
625 if(tmp_ndof_types != n_dof_types)
627 std::ostringstream err_msg;
628 err_msg <<
"The number of DOF types are incorrect.\n" 629 <<
"The total DOF types from the meshes is: " 630 << tmp_ndof_types <<
".\n" 631 <<
"The number of DOF types from " 632 <<
"BlockPreconditioner::ndof_types() is " << n_dof_types <<
".\n";
634 OOMPH_CURRENT_FUNCTION,
635 OOMPH_EXCEPTION_LOCATION);
644 N_velocity_doftypes = My_nmesh*spatial_dim;
647 N_fluid_doftypes = N_velocity_doftypes + 1;
650 N_lagrange_doftypes = n_dof_types - N_fluid_doftypes;
721 unsigned temp_index = 0;
724 unsigned velocity_number = 0;
727 unsigned pres_lgr_number = N_velocity_doftypes;
730 for (
unsigned mesh_i = 0; mesh_i < My_nmesh; mesh_i++)
733 for (
unsigned dim_i = 0; dim_i < spatial_dim; dim_i++)
735 dof_to_block_map[temp_index++] = velocity_number++;
739 unsigned ndof_type_in_mesh_i = My_ndof_types_in_mesh[mesh_i];
740 for (
unsigned doftype_i = spatial_dim;
741 doftype_i < ndof_type_in_mesh_i; doftype_i++)
743 dof_to_block_map[temp_index++] = pres_lgr_number++;
748 this->block_setup(dof_to_block_map);
757 N_velocity_doftypes,0);
759 for(
unsigned row_i = 0; row_i < N_velocity_doftypes; row_i++)
761 for(
unsigned col_i = 0; col_i < N_velocity_doftypes; col_i++)
764 this->get_block(row_i,col_i,*v_aug_pt(row_i,col_i));
769 if(Use_norm_f_for_scaling_sigma)
776 if(Scaling_sigma == 0.0)
778 std::ostringstream warning_stream;
779 warning_stream <<
"WARNING: " << std::endl
780 <<
"The scaling (Scaling_sigma) is " 781 << Scaling_sigma <<
".\n" 782 <<
"Division by 0 will occur." <<
"\n";
784 OOMPH_CURRENT_FUNCTION,
785 OOMPH_EXCEPTION_LOCATION);
787 if(Scaling_sigma > 0.0)
789 std::ostringstream warning_stream;
790 warning_stream <<
"WARNING: " << std::endl
791 <<
"The scaling (Scaling_sigma) is positive: " 792 << Scaling_sigma << std::endl
793 <<
"Performance may be degraded." 796 OOMPH_CURRENT_FUNCTION,
797 OOMPH_EXCEPTION_LOCATION);
817 Inv_w_diag_values.clear();
818 for(
unsigned l_i = 0; l_i < N_lagrange_doftypes; l_i++)
827 const unsigned lgr_block_num = N_fluid_doftypes + l_i;
836 for(
unsigned col_i = 0; col_i < N_velocity_doftypes; col_i++)
840 this->get_block(lgr_block_num, col_i, *mm_temp_pt);
843 if(mm_temp_pt->
nnz() > 0)
845 mm_locations.push_back(col_i);
846 mm_pt.push_back(mm_temp_pt);
859 std::ostringstream warning_stream;
860 warning_stream <<
"WARNING:\n" 861 <<
"There are no mass matrices on Lagrange block row " 863 <<
"Perhaps the problem setup is incorrect." << std::endl;
865 OOMPH_CURRENT_FUNCTION,
866 OOMPH_EXCEPTION_LOCATION);
871 for(
unsigned mm_i = 0; mm_i < n_mm; mm_i++)
875 this->get_block(mm_locations[mm_i],lgr_block_num,*mm_temp_pt);
877 if(mm_temp_pt->
nnz() > 0)
879 mmt_pt.push_back(mm_temp_pt);
886 std::ostringstream warning_stream;
887 warning_stream <<
"WARNING:\n" 888 <<
"The mass matrix block " << mm_locations[mm_i]
889 <<
" in L^T block " << l_i <<
" is zero.\n" 890 <<
"Perhaps the problem setup is incorrect." << std::endl;
892 OOMPH_CURRENT_FUNCTION,
893 OOMPH_EXCEPTION_LOCATION);
906 unsigned long l_i_nrow_local
907 = this->Block_distribution_pt[lgr_block_num]->nrow_local();
910 unsigned l_i_first_row
911 = this->Block_distribution_pt[lgr_block_num]->first_row();
917 for(
unsigned m_i = 0; m_i < n_mm; m_i++)
921 temp_mm_sqrd.
build(mm_pt[m_i]->distribution_pt());
922 mm_pt[m_i]->multiply(*mmt_pt[m_i],temp_mm_sqrd);
928 for(
unsigned long row_i = 0; row_i < l_i_nrow_local; row_i++)
930 w_i_diag_values[row_i] += m_diag[row_i];
940 for(
unsigned long row_i = 0; row_i < l_i_nrow_local; row_i++)
942 invw_i_diag_values[row_i] = Scaling_sigma / w_i_diag_values[row_i];
944 w_i_column_indices[row_i] = row_i + l_i_first_row;
945 w_i_row_start[row_i] = row_i;
948 w_i_row_start[l_i_nrow_local] = l_i_nrow_local;
952 unsigned long l_i_nrow_global
953 = this->Block_distribution_pt[lgr_block_num]->nrow();
954 inv_w_pt->build(l_i_nrow_global,
959 Inv_w_diag_values.push_back(invw_i_diag_values);
968 for(
unsigned ii = 0; ii < n_mm; ii++)
971 unsigned aug_i = mm_locations[ii];
973 for(
unsigned jj = 0; jj < n_mm; jj++)
976 unsigned aug_j = mm_locations[jj];
983 mmt_pt[ii]->multiply((*inv_w_pt),(aug_block));
986 aug_block.
multiply(*mm_pt[jj],another_aug_block);
989 v_aug_pt(aug_i,aug_j)->add(another_aug_block,
990 *v_aug_pt(aug_i,aug_j));
995 delete inv_w_pt; inv_w_pt = 0;
996 for(
unsigned m_i = 0; m_i < n_mm; m_i++)
998 delete mm_pt[m_i]; mm_pt[m_i] = 0;
999 delete mmt_pt[m_i]; mmt_pt[m_i] = 0;
1015 for (
unsigned dof_i = 0; dof_i < n_dof_types; dof_i++)
1017 block_to_dof_map[dof_to_block_map[dof_i]] = dof_i;
1021 for (
unsigned block_row_i = 0;
1022 block_row_i < N_velocity_doftypes; block_row_i++)
1024 unsigned temp_dof_row_i = block_to_dof_map[block_row_i];
1025 for (
unsigned block_col_i = 0;
1026 block_col_i < N_velocity_doftypes; block_col_i++)
1028 unsigned temp_dof_col_i = block_to_dof_map[block_col_i];
1029 this->set_replacement_dof_block(
1030 temp_dof_row_i,temp_dof_col_i,
1031 v_aug_pt(block_row_i,block_col_i));
1047 navier_stokes_block_preconditioner_pt
1049 (Navier_stokes_preconditioner_pt);
1050 Navier_stokes_preconditioner_is_block_preconditioner =
true;
1051 if(navier_stokes_block_preconditioner_pt == 0)
1053 Navier_stokes_preconditioner_is_block_preconditioner =
false;
1058 if(Navier_stokes_preconditioner_is_block_preconditioner)
1109 unsigned temp_dof_number = 0;
1113 for(
unsigned mesh_i = 0; mesh_i < My_nmesh; mesh_i++)
1116 for(
unsigned dim_i = 0; dim_i < spatial_dim; dim_i++)
1118 dof_number_in_master_map.push_back(temp_dof_number + dim_i);
1122 temp_dof_number += My_ndof_types_in_mesh[mesh_i];
1126 dof_number_in_master_map.push_back(spatial_dim);
1148 for (
unsigned direction = 0; direction < spatial_dim; direction++)
1151 for (
unsigned mesh_i = 0; mesh_i < My_nmesh; mesh_i++)
1153 dir_doftypes_vec[mesh_i] = spatial_dim*mesh_i+direction;
1155 doftype_coarsen_map.push_back(dir_doftypes_vec);
1161 ns_p_vec[0] = My_nmesh*spatial_dim;
1163 doftype_coarsen_map.push_back(ns_p_vec);
1167 navier_stokes_block_preconditioner_pt
1169 this, dof_number_in_master_map, doftype_coarsen_map);
1172 navier_stokes_block_preconditioner_pt
1173 ->
setup(matrix_pt());
1183 for (
unsigned block_i = 0; block_i < N_fluid_doftypes; block_i++)
1185 for (
unsigned block_j = 0; block_j < N_fluid_doftypes; block_j++)
1187 f_aug_blocks[block_i][block_j].select_block(block_i,block_j,
true);
1193 = this->get_concatenated_block(f_aug_blocks);
1195 if(Using_superlu_ns_preconditioner)
1197 if(Navier_stokes_preconditioner_pt == 0)
1204 if(Navier_stokes_preconditioner_pt == 0)
1206 std::ostringstream err_msg;
1207 err_msg <<
"Not using SuperLUPreconditioner for NS block,\n" 1208 <<
"but the Navier_stokes_preconditioner_pt is null.\n";
1210 OOMPH_CURRENT_FUNCTION,
1211 OOMPH_EXCEPTION_LOCATION);
1216 Navier_stokes_preconditioner_pt->setup(&f_aug_block);
1221 const unsigned v_aug_nrow = v_aug_pt.
nrow();
1222 const unsigned v_aug_ncol = v_aug_pt.
ncol();
1223 for (
unsigned v_row = 0; v_row < v_aug_nrow; v_row++)
1225 for (
unsigned v_col = 0; v_col < v_aug_ncol; v_col++)
1227 delete v_aug_pt(v_row,v_col);
1228 v_aug_pt(v_row,v_col) = 0;
1232 Preconditioner_has_been_setup =
true;
1241 if(new_ns_preconditioner_pt == 0)
1243 std::ostringstream warning_stream;
1244 warning_stream <<
"WARNING: \n" 1245 <<
"The LSC preconditioner point is null.\n" 1246 <<
"Using default (SuperLU) preconditioner.\n" 1249 OOMPH_CURRENT_FUNCTION,
1250 OOMPH_EXCEPTION_LOCATION);
1252 Navier_stokes_preconditioner_pt = 0;
1253 Using_superlu_ns_preconditioner =
true;
1259 if (Using_superlu_ns_preconditioner
1260 && Navier_stokes_preconditioner_pt != 0)
1262 delete Navier_stokes_preconditioner_pt;
1263 Navier_stokes_preconditioner_pt = 0;
1266 Navier_stokes_preconditioner_pt = new_ns_preconditioner_pt;
1267 Using_superlu_ns_preconditioner =
false;
1277 this->clear_block_preconditioner_base();
1280 if(Using_superlu_ns_preconditioner &&
1281 Navier_stokes_preconditioner_pt != 0)
1283 delete Navier_stokes_preconditioner_pt;
1284 Navier_stokes_preconditioner_pt = 0;
1287 Preconditioner_has_been_setup =
false;
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
unsigned & amg_simple_smoother()
Access function to AMG_simple_smoother flag.
unsigned long nrow() const
Return the number of rows of the matrix.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the preconditioner. r is the residual (rhs), z will contain the solution.
void clear()
wipes the DoubleVector
void set_navier_stokes_preconditioner(Preconditioner *new_ns_preconditioner_pt=0)
Set a new Navier-Stokes matrix preconditioner (inexact solver)
void multiply(const DoubleVector &x, DoubleVector &soln) const
Multiply the matrix by the vector x: soln=Ax.
double inf_norm(const DenseMatrix< CRDoubleMatrix *> &matrix_pt)
Compute infinity (maximum) norm of sub blocks as if it was one matrix.
unsigned long ncol() const
Return the number of columns of the matrix.
double & amg_damping()
Access function to AMG_damping parameter.
double * values_pt()
access function to the underlying values
unsigned & amg_coarsening()
Access function to AMG_coarsening flag.
An interface to the Trilinos AztecOO classes allowing it to be used as an Oomph-lib LinearSolver...
void set_amg_iterations(const unsigned &amg_iterations)
Function to set the number of times to apply BoomerAMG.
Preconditioner * boomer_amg_for_2D_poisson_problem()
Hypre Boomer AMG setting for the 2D Poisson problem (for serial code).
Matrix-based diagonal preconditioner.
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
void setup()
Setup method for the LagrangeEnforcedFlowPreconditioner.
unsigned & amg_smoother_iterations()
Access function to AMG_smoother_iterations.
A preconditioner for performing inner iteration preconditioner solves. The template argument SOLVER s...
Preconditioner * boomer_amg_for_3D_poisson_problem()
Hypre Boomer AMG setting for the 3D Poisson problem (for serial code).
Preconditioner * get_w_cg_preconditioner()
CG with diagonal preconditioner for W-block subsidiary linear systems.
Vector< double > diagonal_entries() const
returns a Vector of diagonal entries of this matrix. This only works with square matrices. This condition may be relaxed in the future if need be.
void setup(DoubleMatrixBase *matrix_pt)
Setup the preconditioner: store the matrix pointer and the communicator pointer then call preconditio...
An interface to allow SuperLU to be used as an (exact) Preconditioner.
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
void set_meshes(const Vector< Mesh *> &mesh_pt)
Set the meshes, the first mesh in the vector must be the bulk mesh.
unsigned nrow() const
access function to the number of global rows.
double & amg_strength()
Access function to AMG_strength.
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 "...
unsigned nrow_local() const
access function for the num of local rows on this processor.
Class for dense matrices, storing all the values of the matrix as a pointer to a pointer with assorte...
A vector in the mathematical sense, initially developed for linear algebra type applications. If MPI then this vector can be distributed - its distribution is described by the LinearAlgebraDistribution object at Distribution_pt. Data is stored in a C-style pointer vector (double*)
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...
A class for compressed row matrices. This is a distributable object.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
void clean_up_memory()
Clears the memory.
Preconditioner * boomer_amg2v22_for_3D_momentum()
Hypre Boomer AMG setting for the augmented momentum block of a 3D Navier-Stokes problem (for serial c...
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 * 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...
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...