32 #include <oomph-lib-config.h> 43 #ifdef OOMPH_HAS_HYPRE 50 namespace Biharmonic_schur_complement_Hypre_defaults
93 oomph_info <<
"Re-assigned number of v cycles: " 100 oomph_info <<
"Current number of amg smoother iterations: " 105 oomph_info <<
"Re-assigned number of amg smoother iterations: " 117 this->clean_up_memory();
121 if (Bulk_element_mesh_pt==0)
123 std::ostringstream error_message;
125 <<
"The bulk element mesh has not been passed to bulk_element_mesh_pt()";
127 OOMPH_CURRENT_FUNCTION,
128 OOMPH_EXCEPTION_LOCATION);
133 this->set_mesh(0,Bulk_element_mesh_pt);
151 if (Preconditioner_type != 0 &&
152 Preconditioner_type != 1 &&
153 Preconditioner_type != 2 &&
154 Preconditioner_type != 3 )
156 std::ostringstream error_message;
158 <<
"Preconditioner_type must be equal to 0 (BBD exact), 1 (inexact BBD with LU)," 159 <<
" 2 (inexact BBD with AMG) or 3 (exact BD).";
161 OOMPH_CURRENT_FUNCTION,
162 OOMPH_EXCEPTION_LOCATION);
168 bool retain_all_blocks=
false;
169 switch(Preconditioner_type)
174 retain_all_blocks=
false;
175 Sub_preconditioner_1_pt =
186 Sub_preconditioner_1_pt =
197 Sub_preconditioner_1_pt =
206 retain_all_blocks=
true;
207 Sub_preconditioner_1_pt =
217 OOMPH_CURRENT_FUNCTION,
218 OOMPH_EXCEPTION_LOCATION);
223 Sub_preconditioner_1_pt->setup(matrix_pt());
227 this->get_block(3,3,*j_33_pt);
228 Sub_preconditioner_2_pt->setup(j_33_pt);
229 delete j_33_pt; j_33_pt = 0;
235 if (this->nblock_types() == 5)
239 this->get_block(4,4,*j_44_pt);
243 Hijacked_sub_block_preconditioner_pt->
setup(j_44_pt);
244 delete j_44_pt; j_44_pt = 0;
260 Sub_preconditioner_1_pt->preconditioner_solve(r,z);
264 get_block_vector(3,r,block_r);
266 Sub_preconditioner_2_pt->preconditioner_solve(block_r,block_z);
267 return_block_vector(3,block_z,z);
270 if (this->nblock_types() == 5)
274 get_block_vector(4,r,block_r);
275 Hijacked_sub_block_preconditioner_pt->
276 preconditioner_solve(block_r,block_z);
277 return_block_vector(4,block_z,z);
287 this->clean_up_memory();
293 unsigned n_block_types = this->nblock_types();
297 if (n_block_types != 3)
299 std::ostringstream error_message;
301 <<
"This preconditioner requires 3 block types.\n" 302 <<
"It is sub preconditioner for the BiharmonicPreconditioner.\n";
304 OOMPH_CURRENT_FUNCTION,
305 OOMPH_EXCEPTION_LOCATION);
315 const bool want_block =
true;
316 for (
unsigned b_i = 0; b_i < n_block_types; b_i++)
318 for (
unsigned b_j = 0; b_j < n_block_types; b_j++)
320 required_blocks[b_i][b_j].select_block(b_i,b_j,want_block);
325 if (!Retain_all_blocks)
327 required_blocks[1][2].do_not_want_block();
328 required_blocks[2][1].do_not_want_block();
333 = this->get_concatenated_block(required_blocks);
337 Sub_preconditioner_pt->
setup(&preconditioner_matrix);
354 get_block_ordered_preconditioner_vector(r,sub_r);
357 Sub_preconditioner_pt->preconditioner_solve(sub_r,sub_z);
360 return_block_ordered_preconditioner_vector(sub_z,z);
370 this->clean_up_memory();
376 unsigned n_block_types = this->nblock_types();
380 if (n_block_types != 3)
382 std::ostringstream error_message;
384 <<
"This preconditioner requires 3 block types.\n" 385 <<
"It is sub preconditioner for the BiharmonicPreconditioner.\n";
387 OOMPH_CURRENT_FUNCTION,
388 OOMPH_EXCEPTION_LOCATION);
394 required_blocks(0,0) =
true;
395 required_blocks(0,1) =
true;
396 required_blocks(1,0) =
true;
397 required_blocks(1,1) =
true;
398 required_blocks(0,2) =
true;
399 required_blocks(2,0) =
true;
400 required_blocks(2,2) =
true;
403 Matrix_of_block_pointers.resize(n_block_types,n_block_types,0);
406 this->get_blocks(required_blocks, Matrix_of_block_pointers);
409 Lumped_J_11_preconditioner_pt =
411 Lumped_J_11_preconditioner_pt->
412 setup(Matrix_of_block_pointers(1,1));
414 delete Matrix_of_block_pointers(1,1);
415 Matrix_of_block_pointers(1,1) = 0;
418 Lumped_J_22_preconditioner_pt =
420 Lumped_J_22_preconditioner_pt->
setup(Matrix_of_block_pointers(2,2));
421 delete Matrix_of_block_pointers(2,2);
422 Matrix_of_block_pointers(2,2) = 0;
425 compute_inexact_schur_complement();
430 #ifdef OOMPH_HAS_HYPRE 434 set_defaults(static_cast<HyprePreconditioner*>(S_00_preconditioner_pt));
436 std::ostringstream error_message;
438 <<
"Request AMG solver but oomph-lib does not have HYPRE";
440 OOMPH_CURRENT_FUNCTION,
441 OOMPH_EXCEPTION_LOCATION);
450 S_00_preconditioner_pt->
setup(S_00_pt);
465 int* J_01_row_start = 0;
466 int* J_01_column_index = 0;
467 double* J_01_value = 0;
468 int* J_10_row_start = 0;
469 int* J_10_column_index = 0;
472 J_01_row_start = Matrix_of_block_pointers(0,1)->row_start();
473 J_01_column_index = Matrix_of_block_pointers(0,1)->column_index();
474 J_01_value = Matrix_of_block_pointers(0,1)->value();
477 J_10_row_start = Matrix_of_block_pointers(1,0)->row_start();
478 J_10_column_index = Matrix_of_block_pointers(1,0)->column_index();
481 int* J_02_row_start = 0;
482 int* J_02_column_index = 0;
483 double* J_02_value = 0;
484 int* J_20_row_start = 0;
485 int* J_20_column_index = 0;
488 J_02_row_start = Matrix_of_block_pointers(0,2)->row_start();
489 J_02_column_index = Matrix_of_block_pointers(0,2)->column_index();
490 J_02_value = Matrix_of_block_pointers(0,2)->value();
493 J_20_row_start = Matrix_of_block_pointers(2,0)->row_start();
494 J_20_column_index = Matrix_of_block_pointers(2,0)->column_index();
497 double* J_11_lumped_and_inverted = 0;
498 J_11_lumped_and_inverted =
499 Lumped_J_11_preconditioner_pt->inverse_lumped_vector_pt();
502 double* J_22_lumped_and_inverted = 0;
503 J_22_lumped_and_inverted =
504 Lumped_J_22_preconditioner_pt->inverse_lumped_vector_pt();
507 unsigned J_00_nrow = Matrix_of_block_pointers(0,0)->nrow();
515 unsigned n_element_x =
518 (this->master_block_preconditioner_pt())->bulk_element_mesh_pt())
519 ->nelement_in_dim(0);
522 unsigned S_00_nnz = 0;
525 for (
unsigned i = 0;
i < J_00_nrow;
i++)
529 S_00_row_start[
i] = S_00_nnz;
551 band_position[0].first=std::max(0,static_cast<int>(
i-n_element_x*2-5));
552 band_position[0].second=
554 std::min(static_cast<int>(J_00_nrow-1),
555 static_cast<int>(
i-n_element_x*2+5)));
556 band_position[1].first=
557 std::max(band_position[0].second+1,
558 std::max(0,static_cast<int>(
i-n_element_x-3)));
559 band_position[1].second=
560 std::max(0,std::min(static_cast<int>(J_00_nrow-1),
561 static_cast<int>(
i-n_element_x+3)));
562 band_position[2].first=
563 std::max(band_position[1].second+1,std::max(0,static_cast<int>(
i-3)));
564 band_position[2].second=
565 std::max(0,std::min(static_cast<int>(J_00_nrow-1),
566 static_cast<int>(
i+3)));
567 band_position[3].first=
568 std::max(band_position[2].second+1,
569 std::max(0,static_cast<int>(
i+n_element_x-3)));
570 band_position[3].second=
571 std::max(0,std::min(static_cast<int>(J_00_nrow-1),
572 static_cast<int>(
i+n_element_x+3)));
573 band_position[4].first=
574 std::max(band_position[3].second+1,
575 std::max(0,static_cast<int>(
i+n_element_x*2-5)));
576 band_position[4].second
577 =std::max(0,std::min(static_cast<int>(J_00_nrow-1),
578 static_cast<int>(
i+n_element_x*2+5)));
584 for (
unsigned b = 0; b < n_band; b++)
588 for (
unsigned j = static_cast<unsigned>(band_position[b].first);
589 j <= static_cast<unsigned>(band_position[b].second);j++)
593 double temp_value = Matrix_of_block_pointers(0,0)->operator()(
i,j);
596 for (
int k = J_01_row_start[
i]; k < J_01_row_start[
i+1]; k++)
598 if ( J_10_column_index[J_10_row_start[J_01_column_index[k]]] <=
599 static_cast<int>(j) &&
static_cast<int>(j) <=
600 J_10_column_index[J_10_row_start[J_01_column_index[k]+1]-1] )
602 temp_value -= J_01_value[k] * Matrix_of_block_pointers(1,0)
603 ->operator()(J_01_column_index[k],j)*
604 J_11_lumped_and_inverted[J_01_column_index[k]];
611 for (
int k = J_02_row_start[
i]; k < J_02_row_start[
i+1]; k++)
613 if ( J_20_column_index[J_20_row_start[J_02_column_index[k]]] <=
614 static_cast<int>(j) &&
static_cast<int>(j) <=
615 J_20_column_index[J_20_row_start[J_02_column_index[k]+1]-1] )
617 temp_value -= J_02_value[k] * Matrix_of_block_pointers(2,0)
618 ->operator()(J_02_column_index[k],j)*
619 J_22_lumped_and_inverted[J_02_column_index[k]];
624 if (temp_value != 0.0)
627 S_00_value.push_back(temp_value);
628 S_00_column_index.push_back(j);
635 S_00_row_start[J_00_nrow] = S_00_nnz;
638 S_00_pt =
new CRDoubleMatrix(this->block_distribution_pt(0),J_00_nrow,
639 S_00_value,S_00_column_index,S_00_row_start);
642 unsigned J_01_nnz = Matrix_of_block_pointers(0,1)->nnz();
643 for (
unsigned i = 0;
i < J_01_nnz;
i++)
645 J_01_value[
i] *= J_11_lumped_and_inverted[J_01_column_index[
i]];
649 unsigned J_02_nnz = Matrix_of_block_pointers(0,2)->nnz();
650 for (
unsigned i = 0;
i < J_02_nnz;
i++)
652 J_02_value[
i] *= J_22_lumped_and_inverted[J_02_column_index[
i]];
666 get_block_vectors(r,block_r);
671 Matrix_of_block_pointers(0,1)->multiply(block_r[1],temp);
674 Matrix_of_block_pointers(0,2)->multiply(block_r[2],temp);
679 S_00_preconditioner_pt->preconditioner_solve(block_r[0],temp);
680 return_block_vector(0,temp,z);
685 Matrix_of_block_pointers(1,0)->multiply(temp,temp2);
688 Lumped_J_11_preconditioner_pt->preconditioner_solve(block_r[1],z_1);
689 return_block_vector(1,z_1,z);
694 Matrix_of_block_pointers(2,0)->multiply(temp,temp2);
697 Lumped_J_22_preconditioner_pt->preconditioner_solve(block_r[2],z_2);
698 return_block_vector(2,z_2,z);
double AMG_strength
amg strength parameter: 0.25 – optimal for 2d
void set_defaults(HyprePreconditioner *hypre_prec_pt)
set the defaults
unsigned & amg_simple_smoother()
Access function to AMG_simple_smoother flag.
unsigned & amg_iterations()
Return function for Max_iter.
void clear()
wipes the DoubleVector
void compute_inexact_schur_complement()
Computes the inexact schur complement of the block J_00 using lumping as an approximate inverse of bl...
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
A two dimensional Hermite bicubic element quadrilateral mesh for a topologically rectangular domain...
void setup()
Setup the preconditioner (store diagonal) from the fully assembled matrix.
unsigned AMG_smoother
smoother type - Gauss Seidel: 1
unsigned & amg_coarsening()
Access function to AMG_coarsening flag.
unsigned N_cycle
number of V cycles: 2
void setup()
Function to set up a preconditioner for the linear system defined by matrix_pt. This function must be...
Matrix-based diagonal preconditioner.
void setup()
Setup terminate helper.
void setup()
Setup the preconditioner.
Matrix-based lumped preconditioner.
double AMG_jacobi_damping
jacobi damping – hierher not used 0.1
Sub Biharmonic Preconditioner - an exact preconditioner for the 3x3 top left hand corner sub block ma...
void initialise(const double &v)
initialise the whole vector with value v
unsigned & amg_smoother_iterations()
Access function to AMG_smoother_iterations.
void setup()
Setup the preconditioner (store diagonal) from the fully assembled matrix. Problem pointer is ignored...
unsigned & hypre_method()
Access function to Hypre_method flag – specified via enumeration.
void setup()
Setup the preconditioner.
An interface to allow SuperLU to be used as an (exact) Preconditioner.
unsigned AMG_coarsening
amg coarsening strategy: classical Ruge Stueben: 1
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
double & amg_strength()
Access function to AMG_strength.
void setup()
Setup the preconditioner.
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*)
SubBiharmonic Preconditioner - an inexact preconditioner for the 3x3 top left hand corner sub block m...
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Apply preconditioner to r.
A class for compressed row matrices. This is a distributable object.
unsigned AMG_smoother_iterations
amg smoother iterations
Biharmonic Preconditioner - for two dimensional problems.