35 namespace Pseudo_Elastic_Preconditioner_Subsidiary_Operator_Helper
37 #ifdef OOMPH_HAS_HYPRE
43 HyprePreconditioner* hypre_preconditioner_pt =
44 new HyprePreconditioner(
"Hypre for diagonal blocks in pseudo-solid");
45 hypre_preconditioner_pt->set_amg_iterations(2);
46 hypre_preconditioner_pt->amg_using_simple_smoothing();
47 if (MPI_Helpers::communicator_pt()->nproc() > 1)
50 hypre_preconditioner_pt->amg_simple_smoother() = 0;
55 hypre_preconditioner_pt->amg_simple_smoother() = 1;
57 hypre_preconditioner_pt->hypre_method() = HyprePreconditioner::BoomerAMG;
58 hypre_preconditioner_pt->amg_damping() = 1.0;
59 hypre_preconditioner_pt->amg_coarsening() = 6;
60 return hypre_preconditioner_pt;
73 #ifdef OOMPH_HAS_TRILINOS
79 TrilinosMLPreconditioner* trilinos_prec_pt =
new TrilinosMLPreconditioner;
80 return trilinos_prec_pt;
87 InnerIterationPreconditioner<TrilinosAztecOOSolver,
88 MatrixBasedDiagPreconditioner>* prec_pt =
89 new InnerIterationPreconditioner<TrilinosAztecOOSolver,
90 MatrixBasedDiagPreconditioner>;
98 prec_pt->solver_pt()->solver_type() = TrilinosAztecOOSolver::CG;
99 prec_pt->solver_pt()->disable_doc_time();
123 std::ostringstream error_message;
124 error_message <<
"The elastic mesh must be set.";
126 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
130 std::ostringstream error_message;
131 error_message <<
"The Lagrange multiplier mesh must be set.";
133 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
143 unsigned n_solid_dof_types = 0;
144 unsigned n_dof_types = 0;
146 if (this->is_master_block_preconditioner())
149 n_solid_dof_types = this->ndof_types_in_mesh(0);
152 n_dof_types = n_solid_dof_types + this->ndof_types_in_mesh(1);
156 n_dof_types = this->ndof_types();
157 n_solid_dof_types = n_dof_types - (n_dof_types / 3);
160 if (n_dof_types % 3 != 0)
162 std::ostringstream error_message;
163 error_message <<
"This preconditioner requires DIM*3 types of DOF";
165 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
170 Dim = n_dof_types / 3;
174 CRDoubleMatrix* cr_matrix_pt =
dynamic_cast<CRDoubleMatrix*
>(matrix_pt());
176 if (cr_matrix_pt == 0)
178 std::ostringstream error_message;
179 error_message <<
"FSIPreconditioner only works with"
180 <<
" CRDoubleMatrix matrices" << std::endl;
182 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
201 Vector<unsigned> dof_list_for_block_setup(n_dof_types);
202 for (
unsigned dim_i = 0; dim_i <
Dim; dim_i++)
205 dof_list_for_block_setup[dim_i] = 2 * dim_i;
208 dof_list_for_block_setup[dim_i +
Dim] = 2 * dim_i + 1;
211 dof_list_for_block_setup[dim_i + 2 *
Dim] = 2 *
Dim + dim_i;
222 this->block_setup(dof_list_for_block_setup);
226 Vector<unsigned> dof_list_for_subsidiary_prec(n_solid_dof_types);
240 for (
unsigned dim_i = 0; dim_i <
Dim; dim_i++)
243 dof_list_for_subsidiary_prec[2 * dim_i] = dim_i;
246 dof_list_for_subsidiary_prec[2 * dim_i + 1] = dim_i +
Dim;
250 DenseMatrix<CRDoubleMatrix*> solid_matrix_pt(
251 n_solid_dof_types, n_solid_dof_types, 0);
253 for (
unsigned row_i = 0; row_i < n_solid_dof_types; row_i++)
255 for (
unsigned col_i = 0; col_i < n_solid_dof_types; col_i++)
257 solid_matrix_pt(row_i, col_i) =
new CRDoubleMatrix;
258 this->get_block(row_i, col_i, *solid_matrix_pt(row_i, col_i));
265 Scaling = CRDoubleMatrixHelpers::inf_norm(solid_matrix_pt);
273 for (
unsigned d = 0; d <
Dim; d++)
276 unsigned block_i = 2 * d + 1;
279 double* s_values = solid_matrix_pt(block_i, block_i)->value();
280 int* s_column_index = solid_matrix_pt(block_i, block_i)->column_index();
281 int* s_row_start = solid_matrix_pt(block_i, block_i)->row_start();
282 int s_nrow_local = solid_matrix_pt(block_i, block_i)->nrow_local();
283 int s_first_row = solid_matrix_pt(block_i, block_i)->first_row();
286 for (
int i = 0; i < s_nrow_local; i++)
289 for (
int j = s_row_start[i]; j < s_row_start[i + 1] && !found; j++)
291 if (s_column_index[j] == i + s_first_row)
301 std::ostringstream error_message;
302 error_message <<
"The diagonal entry for the constained block("
303 << block_i <<
"," << block_i <<
")\n"
304 <<
"on local row " << i <<
" does not exist."
306 throw OomphLibError(error_message.str(),
307 OOMPH_CURRENT_FUNCTION,
308 OOMPH_EXCEPTION_LOCATION);
319 ExactBlockPreconditioner<CRDoubleMatrix>* s_prec_pt =
320 new ExactBlockPreconditioner<CRDoubleMatrix>;
326 Vector<Vector<unsigned>> doftype_to_doftype_map(n_solid_dof_types,
327 Vector<unsigned>(1, 0));
329 for (
unsigned i = 0; i < n_solid_dof_types; i++)
331 doftype_to_doftype_map[i][0] = i;
334 s_prec_pt->turn_into_subsidiary_block_preconditioner(
335 this, dof_list_for_subsidiary_prec, doftype_to_doftype_map);
339 s_prec_pt->set_subsidiary_preconditioner_function(
344 for (
unsigned d = 0; d <
Dim; d++)
347 unsigned block_i = 2 * d + 1;
350 unsigned dof_block_i =
Dim + d;
351 this->set_replacement_dof_block(
352 dof_block_i, dof_block_i, solid_matrix_pt(block_i, block_i));
355 s_prec_pt->Preconditioner::setup(matrix_pt());
361 GeneralPurposeBlockPreconditioner<CRDoubleMatrix>* s_prec_pt = 0;
368 s_prec_pt =
new BlockDiagonalPreconditioner<CRDoubleMatrix>;
373 BlockTriangularPreconditioner<CRDoubleMatrix>*
374 block_triangular_prec_pt =
375 new BlockTriangularPreconditioner<CRDoubleMatrix>;
376 block_triangular_prec_pt->upper_triangular();
378 s_prec_pt = block_triangular_prec_pt;
383 BlockTriangularPreconditioner<CRDoubleMatrix>*
384 block_triangular_prec_pt =
385 new BlockTriangularPreconditioner<CRDoubleMatrix>;
386 block_triangular_prec_pt->lower_triangular();
388 s_prec_pt = block_triangular_prec_pt;
393 std::ostringstream error_msg;
395 <<
"There is no such block based preconditioner.\n"
396 <<
"Candidates are:\n"
397 <<
"PseudoElasticPreconditioner::Block_diagonal_preconditioner\n"
398 <<
"PseudoElasticPreconditioner::Block_upper_triangular_"
400 <<
"PseudoElasticPreconditioner::Block_lower_triangular_"
403 error_msg.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
414 Vector<Vector<unsigned>> doftype_to_doftype_map(
Dim,
415 Vector<unsigned>(2, 0));
416 Vector<unsigned> s_prec_dof_to_block_map(
Dim, 0);
418 unsigned tmp_index = 0;
419 for (
unsigned d = 0; d <
Dim; d++)
421 s_prec_dof_to_block_map[d] = d;
422 doftype_to_doftype_map[d][0] = tmp_index++;
423 doftype_to_doftype_map[d][1] = tmp_index++;
426 s_prec_pt->turn_into_subsidiary_block_preconditioner(
427 this, dof_list_for_subsidiary_prec, doftype_to_doftype_map);
431 s_prec_pt->set_subsidiary_preconditioner_function(
436 for (
unsigned d = 0; d <
Dim; d++)
439 unsigned block_i = 2 * d + 1;
442 unsigned dof_block_i =
Dim + d;
443 this->set_replacement_dof_block(
444 dof_block_i, dof_block_i, solid_matrix_pt(block_i, block_i));
447 s_prec_pt->set_dof_to_block_map(s_prec_dof_to_block_map);
448 s_prec_pt->Preconditioner::setup(matrix_pt());
454 for (
unsigned row_i = 0; row_i < n_solid_dof_types; row_i++)
456 for (
unsigned col_i = 0; col_i < n_solid_dof_types; col_i++)
458 delete solid_matrix_pt(row_i, col_i);
459 solid_matrix_pt(row_i, col_i) = 0;
465 for (
unsigned d = 0; d <
Dim; d++)
467 CRDoubleMatrix* b_pt =
new CRDoubleMatrix;
468 this->get_block(2 *
Dim + d, 2 * d + 1, *b_pt);
475 (*Lagrange_multiplier_subsidiary_preconditioner_function_pt)();
494 const DoubleVector& r, DoubleVector& z)
504 const DoubleVector& r, DoubleVector& z)
507 for (
unsigned d = 0; d <
Dim; d++)
510 this->get_block_vector(
Dim * 2 + d, r, x);
514 unsigned nrow_local = x.nrow_local();
515 double* x_pt = x.values_pt();
516 for (
unsigned i = 0; i < nrow_local; i++)
520 this->return_block_vector(
Dim * 2 + d, x, z);
530 this->clear_block_preconditioner_base();
538 for (
unsigned i = 0; i < sz; i++)
561 std::ostringstream error_message;
562 error_message <<
"The elastic mesh must be set.";
564 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
568 std::ostringstream error_message;
569 error_message <<
"The Lagrange multiplier mesh must be set.";
571 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
576 unsigned n_solid_dof_types = 0;
577 unsigned n_dof_types = 0;
580 if (this->is_master_block_preconditioner())
583 n_solid_dof_types = this->ndof_types_in_mesh(0);
586 n_dof_types = n_solid_dof_types + this->ndof_types_in_mesh(1);
590 n_dof_types = this->ndof_types();
591 n_solid_dof_types = n_dof_types - (n_dof_types / 3);
594 if (n_dof_types % 3 != 0)
596 std::ostringstream error_message;
597 error_message <<
"This preconditioner requires DIM*3 types of DOF";
599 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
604 Dim = n_dof_types / 3;
607 CRDoubleMatrix* cr_matrix_pt =
dynamic_cast<CRDoubleMatrix*
>(matrix_pt());
610 if (cr_matrix_pt == 0)
612 std::ostringstream error_message;
613 error_message <<
"FSIPreconditioner only works with"
614 <<
" CRDoubleMatrix matrices" << std::endl;
616 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
625 Vector<unsigned> dof_list_for_subsidiary_prec(n_solid_dof_types);
626 for (
unsigned i = 0; i < n_solid_dof_types; i++)
628 dof_list_for_subsidiary_prec[i] = i;
634 Vector<unsigned> dof_list(n_solid_dof_types);
635 for (
unsigned i = 0; i < n_solid_dof_types; i++)
660 Vector<unsigned> dof_list(n_solid_dof_types);
661 for (
unsigned i = 0; i < n_solid_dof_types; i++)
665 s_prec_pt->turn_into_subsidiary_block_preconditioner(
this, dof_list);
672 s_prec_pt->Preconditioner::setup(matrix_pt());
682 Vector<unsigned> dof_list(n_solid_dof_types);
683 for (
unsigned i = 0; i < n_solid_dof_types; i++)
687 s_prec_pt->turn_into_subsidiary_block_preconditioner(
this, dof_list);
716 s_prec_pt->Preconditioner::setup(matrix_pt());
722 for (
unsigned d = 0; d <
Dim; d++)
724 CRDoubleMatrix* b_pt =
new CRDoubleMatrix;
725 this->get_block(2 *
Dim + d,
Dim + d, *b_pt);
732 (*Lagrange_multiplier_subsidiary_preconditioner_function_pt)();
752 const DoubleVector& r, DoubleVector& z)
763 const DoubleVector& r, DoubleVector& z)
766 for (
unsigned d = 0; d <
Dim; d++)
769 this->get_block_vector(
Dim * 2 + d, r, x);
773 unsigned nrow_local = x.nrow_local();
774 double* x_pt = x.values_pt();
775 for (
unsigned i = 0; i < nrow_local; i++)
779 this->return_block_vector(
Dim * 2 + d, x, z);
789 this->clear_block_preconditioner_base();
797 for (
unsigned i = 0; i < sz; i++)
820 if (this->ndof_types() % 2 != 0)
822 std::ostringstream error_message;
824 <<
"This SUBSIDIARY preconditioner requires an even number of "
827 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
832 unsigned ndof_types = this->ndof_types();
833 Vector<unsigned> dof_to_block_map(ndof_types, 0);
834 for (
unsigned i = ndof_types / 2; i < ndof_types; i++)
836 dof_to_block_map[i] = 1;
839 this->block_setup(dof_to_block_map);
842 CRDoubleMatrix* s11_pt =
new CRDoubleMatrix;
843 this->get_block(1, 1, *s11_pt);
846 double* s11_values = s11_pt->value();
847 int* s11_column_index = s11_pt->column_index();
848 int* s11_row_start = s11_pt->row_start();
849 int s11_nrow_local = s11_pt->nrow_local();
850 int s11_first_row = s11_pt->first_row();
851 for (
int i = 0; i < s11_nrow_local; i++)
854 for (
int j = s11_row_start[i]; j < s11_row_start[i + 1] && !found; j++)
856 if (s11_column_index[j] == i + s11_first_row)
864 VectorMatrix<BlockSelector> required_blocks(2, 2);
865 const bool want_block =
true;
866 for (
unsigned b_i = 0; b_i < 2; b_i++)
868 for (
unsigned b_j = 0; b_j < 2; b_j++)
870 required_blocks[b_i][b_j].select_block(b_i, b_j, want_block);
874 required_blocks[1][1].set_replacement_block_pt(s11_pt);
876 CRDoubleMatrix s_prec_pt = this->get_concatenated_block(required_blocks);
900 this->get_block_ordered_preconditioner_vector(r, x);
903 this->return_block_ordered_preconditioner_vector(y, z);
922 for (
unsigned i = 0; i < n_block; i++)
928 for (
unsigned j = i + 1; j < n_block; j++)
936 for (
unsigned j = 0; j < i; j++)
945 this->clear_block_preconditioner_base();
957 unsigned n_dof_types = this->ndof_types();
961 if (n_dof_types % 2 != 0)
963 std::ostringstream error_message;
964 error_message <<
"This preconditioner requires DIM*3 types of DOF";
966 error_message.str(), OOMPH_CURRENT_FUNCTION, OOMPH_EXCEPTION_LOCATION);
971 unsigned dim = n_dof_types / 2;
974 Vector<unsigned> dof_to_block_map(n_dof_types, 0);
975 for (
unsigned d = 0; d < dim; d++)
977 dof_to_block_map[d] = d;
978 dof_to_block_map[d + dim] = d;
982 this->block_setup(dof_to_block_map);
991 for (
unsigned d = 0; d < dim; d++)
993 Vector<unsigned> dof_list(2);
995 dof_list[1] = d + dim;
1000 ->turn_into_subsidiary_block_preconditioner(
this, dof_list);
1004 ->set_subsidiary_preconditioner_function(
1025 for (
unsigned j = l; j < u; j++)
1027 CRDoubleMatrix* block_matrix_pt =
new CRDoubleMatrix;
1028 this->get_block(d, j, *block_matrix_pt);
1031 this->setup_matrix_vector_product(
1034 delete block_matrix_pt;
1035 block_matrix_pt = 0;
1048 DoubleVector r(res);
1053 n_block = this->nblock_types();
1056 int start = n_block - 1;
1080 for (
int i = start; i != end; i += step)
1090 for (
int j = i + step; j != end; j += step)
1093 this->get_block_vector(i, z, x);
1097 this->get_block_vector(j, r, x);
1099 this->return_block_vector(j, x, r);
void lagrange_multiplier_preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the lagrange multiplier subsidiary preconditioner.
Preconditioner * Elastic_preconditioner_pt
storage for the preconditioner for the solid system
Vector< Preconditioner * > Lagrange_multiplier_preconditioner_pt
lagrange multiplier preconditioner pt
void setup()
Broken assignment operator.
bool Use_inf_norm_of_s_scaling
boolean indicating whether the inf-norm of S should be used as scaling. Default = true;
SubsidiaryPreconditionerFctPt Elastic_subsidiary_preconditioner_function_pt
The solid subsidiary preconditioner function pointer.
Elastic_preconditioner_type E_preconditioner_type
An unsigned indicating which method should be used for preconditioning the solid component.
void elastic_preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the elastic subsidiary preconditioner.
double Scaling
The scaling. Defaults to infinity norm of S.
unsigned Dim
the dimension of the problem
@ Exact_block_preconditioner
@ Block_upper_triangular_preconditioner
@ Block_lower_triangular_preconditioner
@ Block_diagonal_preconditioner
SubsidiaryPreconditionerFctPt Lagrange_multiplier_subsidiary_preconditioner_function_pt
The Lagrange multiplier subsidary preconditioner function pointer.
Mesh * Elastic_mesh_pt
Pointer to the mesh containing the solid elements.
void clean_up_memory()
Clears the memory.
Mesh * Lagrange_multiplier_mesh_pt
Pointer to the mesh containing the Lagrange multiplier elements.
//////////////////////////////////////////////////////////////////////////// ////////////////////////...
double s_inf_norm()
Broken assignment operator.
///////////////////////////////////////////////////////////////////////////// ///////////////////////...
void use_block_diagonal_approximation()
use as a block diagonal preconditioner
void preconditioner_solve(const DoubleVector &res, DoubleVector &z)
Apply preconditioner to r.
SubsidiaryPreconditionerFctPt Subsidiary_preconditioner_function_pt
The SubisidaryPreconditionerFctPt.
void use_upper_triangular_approximation()
Use as an upper triangular preconditioner.
Vector< PseudoElasticPreconditionerSubsidiaryPreconditionerOld * > Diagonal_block_preconditioner_pt
Vector of SuperLU preconditioner pointers for storing the preconditioners for each diagonal block.
void setup()
Setup the preconditioner.
void use_lower_triangular_approximation()
Use as a lower triangular preconditioner.
double Scaling
The scaling. default 1.0.
unsigned Method
the preconditioning method. 0 - block diagonal 1 - upper triangular 2 - lower triangular
void set_subsidiary_preconditioner_function(SubsidiaryPreconditionerFctPt sub_prec_fn)
access function to set the subsidiary preconditioner function.
void clean_up_memory()
Broken assignment operator.
DenseMatrix< MatrixVectorProduct * > Off_diagonal_matrix_vector_products
Matrix of matrix vector product operators for the off diagonals.
double & scaling()
Specify the scaling. Default is 1.0 Must be set before setup(...).
///////////////////////////////////////////////////////////////////////////// ///////////////////////...
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the preconditioner.
SubsidiaryPreconditionerFctPt Subsidiary_preconditioner_function_pt
the SubisidaryPreconditionerFctPt
double & scaling()
Specify the scaling. Default is 1.0 Must be called before setup(...).
void clean_up_memory()
clears the memory
Preconditioner * Preconditioner_pt
the preconditioner pt
void setup()
Broken assignment operator.
void set_subsidiary_preconditioner_function(SubsidiaryPreconditionerFctPt sub_prec_fn)
access function to set the subsidiary preconditioner function.
SubsidiaryPreconditionerFctPt Lagrange_multiplier_subsidiary_preconditioner_function_pt
The Lagrange multiplier subsidiary preconditioner function pointer.
void lagrange_multiplier_preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the lagrange multiplier subsidiary preconditioner.
bool Use_inf_norm_of_s_scaling
boolean indicating whether the inf-norm of S should be used as scaling. Default = true;
double Scaling
The scaling. Defaults to infinity norm of S.
void setup()
Broken assignment operator.
Vector< Preconditioner * > Lagrange_multiplier_preconditioner_pt
lagrange multiplier preconditioner pt
void elastic_preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply the elastic subsidiary preconditioner.
Mesh * Lagrange_multiplier_mesh_pt
Pointer to the mesh containing the Lagrange multiplier elements.
SubsidiaryPreconditionerFctPt Elastic_subsidiary_preconditioner_function_pt
The solid subsidiary preconditioner function pointer.
Mesh * Elastic_mesh_pt
Pointer to the mesh containing the solid elements.
Elastic_preconditioner_type E_preconditioner_type
An unsigned indicating which method should be used for preconditioning the solid component.
@ Block_diagonal_preconditioner
@ Exact_block_preconditioner
@ Block_lower_triangular_preconditioner
@ Block_upper_triangular_preconditioner
void clean_up_memory()
Clears the memory.
Preconditioner * Elastic_preconditioner_pt
storage for the preconditioner for the solid system
unsigned Dim
the dimension of the problem
Preconditioner * get_lagrange_multiplier_preconditioner()
CG with diagonal preconditioner for the lagrange multiplier subsidiary linear systems.
Preconditioner * get_elastic_preconditioner()
AMG w/ GS smoothing for the augmented elastic subsidiary linear systems – calls Hypre version to stay...
Preconditioner * get_elastic_preconditioner_trilinos_ml()
TrilinosML smoothing for the augmented elastic subsidiary linear systems.
Preconditioner * get_elastic_preconditioner_hypre()
AMG w/ GS smoothing for the augmented elastic subsidiary linear systems.