46 namespace Hypre_default_settings
117 namespace HypreHelpers
157 int err = HYPRE_GetError();
162 oomph_info <<
"Hypre error flag=" << err << std::endl;
163 char* error_message =
new char[128];
164 HYPRE_DescribeError(err, error_message);
165 message <<
"WARNING: " << std::endl
166 <<
"HYPRE error message: " << error_message
168 delete[] error_message;
187 HYPRE_IJVector& hypre_ij_vector,
188 HYPRE_ParVector& hypre_par_vector)
201 communicator_pt()->mpi_comm(),
202 lower,upper, &hypre_ij_vector);
204 HYPRE_IJVectorCreate(MPI_COMM_WORLD,
205 lower,upper, &hypre_ij_vector);
207 HYPRE_IJVectorSetObjectType(hypre_ij_vector, HYPRE_PARCSR);
208 HYPRE_IJVectorInitialize(hypre_ij_vector);
211 int* indices =
new int[nrow_local];
212 double* values =
new double[nrow_local];
213 const unsigned hypre_first_row = dist_pt->
first_row();
219 const double* o_pt = oomph_vec.
values_pt();
220 for (
unsigned i=0;
i<nrow_local;
i++)
222 indices[
i] = hypre_first_row +
i;
223 values[
i] = o_pt[j+
i];
227 HYPRE_IJVectorSetValues(hypre_ij_vector,nrow_local,indices,values);
230 HYPRE_IJVectorAssemble(hypre_ij_vector);
231 HYPRE_IJVectorGetObject(hypre_ij_vector, (
void **) &hypre_par_vector);
247 HYPRE_IJVector& hypre_ij_vector,
248 HYPRE_ParVector& hypre_par_vector)
258 lower,upper, &hypre_ij_vector);
260 HYPRE_IJVectorCreate(MPI_COMM_WORLD,
261 lower,upper, &hypre_ij_vector);
263 HYPRE_IJVectorSetObjectType(hypre_ij_vector, HYPRE_PARCSR);
264 HYPRE_IJVectorInitialize(hypre_ij_vector);
267 HYPRE_IJVectorAssemble(hypre_ij_vector);
268 HYPRE_IJVectorGetObject(hypre_ij_vector, (
void **) &hypre_par_vector);
279 HYPRE_IJMatrix& hypre_ij_matrix,
280 HYPRE_ParCSRMatrix& hypre_par_matrix,
285 if ( !oomph_matrix->
built() )
287 std::ostringstream error_message;
288 error_message <<
"The matrix has not been built";
290 OOMPH_CURRENT_FUNCTION,
291 OOMPH_EXCEPTION_LOCATION);
294 if ( oomph_matrix->
nrow() != oomph_matrix->
ncol() )
296 std::ostringstream error_message;
297 error_message <<
"create_HYPRE_Matrix require a square matrix. " 298 <<
"Matrix is " << oomph_matrix->
nrow()
299 <<
" by " << oomph_matrix->
ncol() << std::endl;
301 OOMPH_CURRENT_FUNCTION,
302 OOMPH_EXCEPTION_LOCATION);
311 std::ostringstream error_stream;
312 error_stream <<
"Oomph-lib has been compiled with MPI support and " 313 <<
"you are using HYPRE.\n" 315 "For this combination of flags, MPI must be initialised.\n" 316 <<
"Call MPI_Helpers::init() in the " 317 <<
"main() function of your driver code\n";
319 OOMPH_CURRENT_FUNCTION,
320 OOMPH_EXCEPTION_LOCATION);
325 const unsigned nrow = int(oomph_matrix->
nrow());
333 const double* matrix_vals = oomph_matrix->
value();
336 const int* matrix_row_start = oomph_matrix->
row_start();
345 bool distributed =
true;
356 unsigned upper = lower + dist_pt->
nrow_local() - 1;
366 HYPRE_IJMatrixCreate(MPI_COMM_WORLD,
373 HYPRE_IJMatrixSetObjectType(hypre_ij_matrix, HYPRE_PARCSR);
374 HYPRE_IJMatrixInitialize(hypre_ij_matrix);
378 const unsigned hypre_nrow_local = dist_pt->
nrow_local();
379 const unsigned hypre_first_row = dist_pt->
first_row();
380 int* ncols_per_row =
new int[hypre_nrow_local];
381 int* row_map =
new int[hypre_nrow_local];
382 for (
unsigned i = 0;
i < hypre_nrow_local;
i++)
387 j += hypre_first_row;
389 ncols_per_row[
i] = matrix_row_start[j+1] - matrix_row_start[j];
390 row_map[
i] = hypre_first_row +
i;
397 local_start += matrix_row_start[hypre_first_row];
401 HYPRE_IJMatrixSetValues(hypre_ij_matrix,
405 matrix_cols+local_start,
406 matrix_vals+local_start);
409 HYPRE_IJMatrixAssemble(hypre_ij_matrix);
410 HYPRE_IJMatrixGetObject(hypre_ij_matrix, (
void **) &hypre_par_matrix);
413 delete[] ncols_per_row;
422 const bool &use_row_scaling,
423 const bool &use_ilut,
425 const double &drop_tol,
426 const int &print_level,
427 HYPRE_Solver &euclid_object)
434 const char* args[22];
440 args[n_args++] =
"-bj";
441 if (use_block_jacobi)
443 args[n_args++] =
"1";
447 args[n_args++] =
"0";
451 args[n_args++] =
"-rowScale";
454 args[n_args++] =
"1";
458 args[n_args++] =
"0";
462 args[n_args++] =
"-level";
463 char level_value[10];
464 sprintf(level_value,
"%d",level);
465 args[n_args++] = level_value;
481 if (print_level == 0)
483 args[n_args++] =
"-eu_stats";
484 args[n_args++] =
"0";
485 args[n_args++] =
"-eu_mem";
486 args[n_args++] =
"0";
488 if (print_level == 1)
490 args[n_args++] =
"-eu_stats";
491 args[n_args++] =
"1";
492 args[n_args++] =
"-eu_mem";
493 args[n_args++] =
"0";
495 if (print_level == 2)
497 args[n_args++] =
"-eu_stats";
498 args[n_args++] =
"1";
499 args[n_args++] =
"-eu_mem";
500 args[n_args++] =
"1";
507 HYPRE_EuclidSetParams(euclid_object, n_args, const_cast<char**>(args));
538 <<
"Warning: HYPRE based solvers may fail if 2*number of processors " 539 <<
"is greater than the number of unknowns!" << std::endl;
547 Hypre_distribution_pt);
550 if (Hypre_error_messages)
552 std::ostringstream message;
557 "HypreSolver::hypre_matrix_setup()",
558 OOMPH_EXCEPTION_LOCATION);
563 if (Delete_input_data)
586 HYPRE_IJVector dummy_sol_ij;
587 HYPRE_ParVector dummy_sol_par;
588 HYPRE_IJVector dummy_rhs_ij;
589 HYPRE_ParVector dummy_rhs_par;
599 if ( (Hypre_method>=
CG) && (Hypre_method<=
BiCGStab) )
602 if (Internal_preconditioner==BoomerAMG)
615 if (AMG_using_simple_smoothing)
624 double* relaxweight = hypre_CTAlloc(
double, AMG_max_levels);
626 for (
unsigned i=0;
i<AMG_max_levels;
i++)
628 relaxweight[
i] = AMG_damping;
635 HYPRE_BoomerAMGSetSmoothType(
Preconditioner, AMG_complex_smoother);
636 HYPRE_BoomerAMGSetSmoothNumLevels(
Preconditioner, AMG_max_levels);
641 if(AMG_complex_smoother == 9)
644 (AMGEuclidSmoother_use_block_jacobi,
645 AMGEuclidSmoother_use_row_scaling,
646 AMGEuclidSmoother_use_ilut,
647 AMGEuclidSmoother_level,
648 AMGEuclidSmoother_drop_tol,
653 Existing_preconditioner = BoomerAMG;
657 else if (Internal_preconditioner==Euclid)
660 HYPRE_EuclidCreate(Hypre_distribution_pt->communicator_pt()->mpi_comm(),
668 (Euclid_using_BJ, Euclid_rowScale, Euclid_using_ILUT, Euclid_level,
671 Existing_preconditioner = Euclid;
675 else if (Internal_preconditioner==ParaSails)
678 HYPRE_ParaSailsCreate
679 (Hypre_distribution_pt->communicator_pt()->mpi_comm(), &
Preconditioner);
688 Existing_preconditioner = ParaSails;
692 if (Hypre_error_messages)
694 std::ostringstream message;
699 "HypreSolver::hypre_setup()",
700 OOMPH_EXCEPTION_LOCATION);
711 if (Hypre_method==BoomerAMG)
719 HYPRE_BoomerAMGCreate(&Solver);
720 HYPRE_BoomerAMGSetPrintLevel(Solver, AMG_print_level);
721 HYPRE_BoomerAMGSetMaxLevels(Solver, AMG_max_levels);
722 HYPRE_BoomerAMGSetMaxIter(Solver,
Max_iter);
723 HYPRE_BoomerAMGSetTol(Solver, Tolerance);
725 HYPRE_BoomerAMGSetStrongThreshold(Solver,
AMG_strength);
726 HYPRE_BoomerAMGSetMaxRowSum(Solver, AMG_max_row_sum);
729 if (AMG_using_simple_smoothing)
731 HYPRE_BoomerAMGSetRelaxType(Solver, AMG_simple_smoother);
738 double* relaxweight = hypre_CTAlloc(
double, AMG_max_levels);
740 for (
unsigned i=0;
i<AMG_max_levels;
i++)
742 relaxweight[
i] = AMG_damping;
744 HYPRE_BoomerAMGSetRelaxWeight(Solver, relaxweight);
748 HYPRE_BoomerAMGSetSmoothType(Solver, AMG_complex_smoother);
749 HYPRE_BoomerAMGSetSmoothNumLevels(Solver, AMG_max_levels);
762 if(AMG_complex_smoother == 9)
765 (AMGEuclidSmoother_use_block_jacobi,
766 AMGEuclidSmoother_use_row_scaling,
767 AMGEuclidSmoother_use_ilut,
768 AMGEuclidSmoother_level,
769 AMGEuclidSmoother_drop_tol,
779 HYPRE_BoomerAMGSetup(Solver,
787 Existing_solver = BoomerAMG;
791 else if (Hypre_method==Euclid)
798 HYPRE_EuclidCreate(Hypre_distribution_pt->communicator_pt()->mpi_comm(),
801 HYPRE_EuclidCreate(MPI_COMM_WORLD, &Solver);
806 (Euclid_using_BJ, Euclid_rowScale, Euclid_using_ILUT, Euclid_level,
809 HYPRE_EuclidSetup(Solver,
813 Existing_solver = Euclid;
817 else if (Hypre_method==ParaSails)
824 HYPRE_ParaSailsCreate(Hypre_distribution_pt->communicator_pt()->mpi_comm(),
827 HYPRE_ParaSailsCreate(MPI_COMM_WORLD, &Solver);
829 HYPRE_ParaSailsSetSym(Solver, ParaSails_symmetry);
830 HYPRE_ParaSailsSetParams(Solver,
833 HYPRE_ParaSailsSetFilter(Solver, ParaSails_filter);
835 HYPRE_ParaSailsSetup(Solver,
839 Existing_solver = ParaSails;
843 else if (Hypre_method==
CG)
851 HYPRE_ParCSRPCGCreate(Hypre_distribution_pt->communicator_pt()->mpi_comm(),
854 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &Solver);
856 HYPRE_PCGSetTol(Solver, Tolerance);
857 HYPRE_PCGSetLogging(Solver, 0);
858 HYPRE_PCGSetPrintLevel(Solver, Krylov_print_level);
859 HYPRE_PCGSetMaxIter(Solver,
Max_iter);
862 if (Internal_preconditioner==BoomerAMG)
866 oomph_info <<
" with BoomerAMG preconditioner, ";
869 HYPRE_PCGSetPrecond(Solver,
870 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve,
871 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup,
874 else if (Internal_preconditioner==Euclid)
878 oomph_info <<
" with Euclid ILU preconditioner, ";
881 HYPRE_PCGSetPrecond(Solver,
882 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSolve,
883 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSetup,
886 else if (Internal_preconditioner==ParaSails)
890 oomph_info <<
" with ParaSails approximate inverse preconditioner, ";
893 HYPRE_PCGSetPrecond(Solver,
894 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve,
895 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup,
907 HYPRE_PCGSetup(Solver,
908 (HYPRE_Matrix) Matrix_par,
909 (HYPRE_Vector) dummy_rhs_par,
910 (HYPRE_Vector) dummy_sol_par);
913 Existing_solver =
CG;
917 else if (Hypre_method==
GMRES)
925 HYPRE_ParCSRGMRESCreate
926 (Hypre_distribution_pt->communicator_pt()->mpi_comm(),&Solver);
928 HYPRE_ParCSRGMRESCreate(MPI_COMM_WORLD,&Solver);
930 HYPRE_GMRESSetTol(Solver, Tolerance);
931 HYPRE_GMRESSetKDim(Solver,
Max_iter);
932 HYPRE_GMRESSetLogging(Solver, 0);
933 HYPRE_GMRESSetPrintLevel(Solver, Krylov_print_level);
934 HYPRE_GMRESSetMaxIter(Solver,
Max_iter);
937 if (Internal_preconditioner==BoomerAMG)
941 oomph_info <<
" with BoomerAMG preconditioner, ";
944 HYPRE_GMRESSetPrecond(Solver,
945 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve,
946 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup,
949 else if (Internal_preconditioner==Euclid)
953 oomph_info <<
" with Euclid ILU preconditioner, ";
956 HYPRE_GMRESSetPrecond(Solver,
957 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSolve,
958 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSetup,
961 else if (Internal_preconditioner==ParaSails)
965 oomph_info <<
" with ParaSails approximate inverse preconditioner, ";
968 HYPRE_GMRESSetPrecond(Solver,
969 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve,
970 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup,
981 HYPRE_GMRESSetup(Solver,
982 (HYPRE_Matrix) Matrix_par,
983 (HYPRE_Vector) dummy_rhs_par,
984 (HYPRE_Vector) dummy_sol_par);
986 Existing_solver =
GMRES;
997 HYPRE_ParCSRBiCGSTABCreate
998 (Hypre_distribution_pt->communicator_pt()->mpi_comm(), &Solver);
1000 HYPRE_ParCSRBiCGSTABCreate(MPI_COMM_WORLD, &Solver);
1002 HYPRE_BiCGSTABSetTol(Solver, Tolerance);
1003 HYPRE_BiCGSTABSetLogging(Solver, 0);
1004 HYPRE_BiCGSTABSetPrintLevel(Solver, Krylov_print_level);
1005 HYPRE_BiCGSTABSetMaxIter(Solver,
Max_iter);
1008 if (Internal_preconditioner==BoomerAMG)
1012 oomph_info <<
" with BoomerAMG preconditioner, ";
1015 HYPRE_BiCGSTABSetPrecond(Solver,
1016 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSolve,
1017 (HYPRE_PtrToSolverFcn) HYPRE_BoomerAMGSetup,
1020 else if (Internal_preconditioner==Euclid)
1024 oomph_info <<
" with Euclid ILU preconditioner, ";
1027 HYPRE_BiCGSTABSetPrecond(Solver,
1028 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSolve,
1029 (HYPRE_PtrToSolverFcn) HYPRE_EuclidSetup,
1032 else if (Internal_preconditioner==ParaSails)
1036 oomph_info <<
" with ParaSails approximate inverse preconditioner, ";
1039 HYPRE_BiCGSTABSetPrecond(Solver,
1040 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSolve,
1041 (HYPRE_PtrToSolverFcn) HYPRE_ParaSailsSetup,
1052 HYPRE_BiCGSTABSetup(Solver,
1053 (HYPRE_Matrix) Matrix_par,
1054 (HYPRE_Vector) dummy_rhs_par,
1055 (HYPRE_Vector) dummy_sol_par);
1063 std::ostringstream error_message;
1064 error_message <<
"Solver has been set to an invalid value. " 1065 <<
"current value=" << Solver;
1067 OOMPH_CURRENT_FUNCTION,
1068 OOMPH_EXCEPTION_LOCATION);
1073 double solver_setup_time = t_end-t_start;
1076 HYPRE_IJVectorDestroy(dummy_sol_ij);
1077 HYPRE_IJVectorDestroy(dummy_rhs_ij);
1080 if (Hypre_error_messages)
1082 std::ostringstream message;
1087 "HypreSolver::hypre_solver_setup()",
1088 OOMPH_EXCEPTION_LOCATION);
1096 << solver_setup_time << std::endl;
1116 HYPRE_IJVector rhs_ij;
1117 HYPRE_ParVector rhs_par;
1120 HYPRE_IJVector solution_ij;
1121 HYPRE_ParVector solution_par;
1125 Hypre_distribution_pt,
1134 if (Hypre_error_messages)
1136 std::ostringstream message;
1141 "HypreSolver::hypre_solve()",
1142 OOMPH_EXCEPTION_LOCATION);
1154 const double rhs_norm = rhs.
norm();
1155 bool do_solving =
false;
1161 #ifdef OOMPH_HAS_MPI 1168 unsigned this_processor_do_solving = 0;
1169 unsigned all_processors_do_solving = 0;
1172 this_processor_do_solving = 1;
1177 MPI_Allreduce(&this_processor_do_solving,&all_processors_do_solving,
1178 1, MPI_UNSIGNED,MPI_SUM,comm_pt->mpi_comm());
1179 if (all_processors_do_solving > 0)
1189 if (Existing_solver==BoomerAMG)
1191 HYPRE_BoomerAMGSolve(Solver, Matrix_par, rhs_par, solution_par);
1192 HYPRE_BoomerAMGGetNumIterations(Solver, &iterations);
1193 HYPRE_BoomerAMGGetFinalRelativeResidualNorm(Solver, &norm);
1195 else if (Existing_solver==
CG)
1197 HYPRE_PCGSolve(Solver,
1198 (HYPRE_Matrix) Matrix_par,
1199 (HYPRE_Vector) rhs_par,
1200 (HYPRE_Vector) solution_par);
1201 HYPRE_PCGGetNumIterations(Solver, &iterations);
1202 HYPRE_PCGGetFinalRelativeResidualNorm(Solver, &norm);
1204 else if (Existing_solver==
GMRES)
1206 HYPRE_GMRESSolve(Solver,
1207 (HYPRE_Matrix) Matrix_par,
1208 (HYPRE_Vector) rhs_par,
1209 (HYPRE_Vector) solution_par);
1210 HYPRE_GMRESGetNumIterations(Solver, &iterations);
1211 HYPRE_GMRESGetFinalRelativeResidualNorm(Solver, &norm);
1213 else if (Existing_solver==
BiCGStab)
1215 HYPRE_BiCGSTABSolve(Solver,
1216 (HYPRE_Matrix) Matrix_par,
1217 (HYPRE_Vector) rhs_par,
1218 (HYPRE_Vector) solution_par);
1219 HYPRE_BiCGSTABGetNumIterations(Solver, &iterations);
1220 HYPRE_BiCGSTABGetFinalRelativeResidualNorm(Solver, &norm);
1222 else if (Existing_solver==Euclid)
1224 HYPRE_EuclidSolve(Solver, Matrix_par, rhs_par, solution_par);
1226 else if (Existing_solver==ParaSails)
1228 HYPRE_ParaSailsSolve(Solver, Matrix_par, rhs_par, solution_par);
1232 if (Hypre_error_messages)
1234 std::ostringstream message;
1239 "HypreSolver::hypre_solve()",
1240 OOMPH_EXCEPTION_LOCATION);
1247 unsigned nrow_local = Hypre_distribution_pt->nrow_local();
1248 unsigned first_row = Hypre_distribution_pt->first_row();
1249 int* indices =
new int[nrow_local];
1250 for (
unsigned i = 0;
i < nrow_local;
i++)
1252 indices[
i] = first_row +
i;
1255 if (solution.
built())
1263 solution.
build(Hypre_distribution_pt,0.0);
1264 HYPRE_IJVectorGetValues(solution_ij,
1270 delete soln_dist_pt;
1273 if (Hypre_error_messages)
1275 std::ostringstream message;
1280 "HypreSolver::hypre_solve()",
1281 OOMPH_EXCEPTION_LOCATION);
1286 HYPRE_IJVectorDestroy(solution_ij);
1287 HYPRE_IJVectorDestroy(rhs_ij);
1290 double solve_time=0;
1294 solve_time = t_end-t_start;
1301 << solve_time << std::endl;
1305 if ((Hypre_method>=
CG) && (Hypre_method<=BoomerAMG))
1309 if (Output_info)
oomph_info <<
"Number of iterations : " 1310 << iterations << std::endl;
1311 if (Output_info)
oomph_info <<
"Final Relative Residual Norm : " 1312 << norm << std::endl;
1325 if (Existing_solver != None)
1329 HYPRE_IJMatrixDestroy(Matrix_ij);
1332 if (Existing_solver==BoomerAMG)
1334 HYPRE_BoomerAMGDestroy(Solver);
1336 else if (Existing_solver==
CG)
1338 HYPRE_ParCSRPCGDestroy(Solver);
1340 else if (Existing_solver==
GMRES)
1342 HYPRE_ParCSRGMRESDestroy(Solver);
1344 else if (Existing_solver==
BiCGStab)
1346 HYPRE_ParCSRBiCGSTABDestroy(Solver);
1348 else if (Existing_solver==Euclid)
1350 HYPRE_EuclidDestroy(Solver);
1352 else if (Existing_solver==ParaSails)
1354 HYPRE_ParaSailsDestroy(Solver);
1356 Existing_solver = None;
1359 if (Existing_preconditioner==BoomerAMG)
1363 else if (Existing_preconditioner==Euclid)
1367 else if (Existing_preconditioner==ParaSails)
1371 Existing_preconditioner = None;
1374 if (Hypre_error_messages)
1376 std::ostringstream message;
1381 "HypreSolver::clean_up_memory()",
1382 OOMPH_EXCEPTION_LOCATION);
1411 Output_info = Doc_time;
1418 Delete_input_data =
true;
1428 oomph_info <<
"Time to generate Jacobian and residual [s] : ";
1434 hypre_matrix_setup(matrix);
1437 hypre_solver_setup();
1440 hypre_solve(residual, solution);
1443 if (!Enable_resolve)
1466 if ( matrix_pt->
nrow() != matrix_pt->
ncol() )
1468 std::ostringstream error_message;
1469 error_message <<
"HypreSolver require a square matrix. " 1470 <<
"Matrix is " << matrix_pt->
nrow()
1471 <<
" by " << matrix_pt->
ncol() << std::endl;
1473 OOMPH_CURRENT_FUNCTION,
1474 OOMPH_EXCEPTION_LOCATION);
1479 Output_info = Doc_time;
1486 Delete_input_data = Delete_matrix;
1502 std::ostringstream error_message;
1503 error_message <<
"The distribution of the rhs vector and the matrix " 1504 <<
" must be the same" << std::endl;
1506 OOMPH_CURRENT_FUNCTION,
1507 OOMPH_EXCEPTION_LOCATION);
1511 if (solution.
built())
1515 std::ostringstream error_message;
1516 error_message <<
"The distribution of the solution vector is setup " 1517 <<
"there it must be the same as the matrix." 1520 OOMPH_CURRENT_FUNCTION,
1521 OOMPH_EXCEPTION_LOCATION);
1526 hypre_matrix_setup(cr_matrix_pt);
1531 std::ostringstream error_message;
1532 error_message <<
"HypreSolver only work with " 1533 <<
"CRDoubleMatrix matrices" 1536 OOMPH_CURRENT_FUNCTION,
1537 OOMPH_EXCEPTION_LOCATION);
1542 hypre_solver_setup();
1545 hypre_solve(rhs, solution);
1548 if (!Enable_resolve)
1564 if (existing_solver()==None)
1566 std::ostringstream error_message;
1567 error_message <<
"resolve(...) requires that solver data has been " 1568 <<
"set up by a previous call to solve(...) after " 1569 <<
"a call to enable_resolve()" << std::endl;
1571 OOMPH_CURRENT_FUNCTION,
1572 OOMPH_EXCEPTION_LOCATION);
1578 std::ostringstream error_message;
1579 error_message <<
"The distribution of the rhs vector and the matrix " 1580 <<
" must be the same" << std::endl;
1582 OOMPH_CURRENT_FUNCTION,
1583 OOMPH_EXCEPTION_LOCATION);
1587 if (solution.
built())
1591 std::ostringstream error_message;
1592 error_message <<
"The distribution of the solution vector is setup " 1593 <<
"there it must be the same as the matrix." 1596 OOMPH_CURRENT_FUNCTION,
1597 OOMPH_EXCEPTION_LOCATION);
1603 Output_info = Doc_time;
1606 hypre_solve(rhs, solution);
1618 hypre_clean_up_memory();
1662 std::map<std::string,unsigned>
1680 oomph_info <<
"\n\n=====================================================\n";
1681 oomph_info <<
"Cumulative HyprePreconditioner solve time " 1682 << HyprePreconditioner::Cumulative_preconditioner_solve_time
1683 <<
" for " << Cumulative_npreconditioner_solve
1685 if (Cumulative_npreconditioner_solve!=0)
1688 << HyprePreconditioner::Cumulative_preconditioner_solve_time/
1689 double(Cumulative_npreconditioner_solve) <<
" per solve )";
1692 if (Context_based_cumulative_solve_time.size()>0)
1694 oomph_info <<
"Breakdown by context: " << std::endl;
1695 for (std::map<std::string,double>::iterator it=
1696 Context_based_cumulative_solve_time.begin();it!=
1697 Context_based_cumulative_solve_time.end();it++)
1699 oomph_info << (*it).first <<
" " << (*it).second <<
" for " 1700 << Context_based_cumulative_npreconditioner_solve[(*it).first]
1702 if (Context_based_cumulative_npreconditioner_solve[(*it).first]!=0)
1706 double(Context_based_cumulative_npreconditioner_solve[(*it).first])
1709 double(Context_based_cumulative_npreconditioner_solve[(*it).first])/
1710 double(Context_based_nrow[(*it).first])
1711 <<
" per solve per dof )";
1716 oomph_info <<
"\n=====================================================\n";
1725 Cumulative_preconditioner_solve_time=0.0;
1726 Context_based_cumulative_solve_time.clear();
1727 Cumulative_npreconditioner_solve=0;
1728 Context_based_cumulative_npreconditioner_solve.clear();
1729 Context_based_nrow.clear();
1741 Output_info = Doc_time;
1745 if ( matrix_pt()->nrow() != matrix_pt()->ncol() )
1747 std::ostringstream error_message;
1748 error_message <<
"HyprePreconditioner require a square matrix. " 1749 <<
"Matrix is " << matrix_pt()->nrow()
1750 <<
" by " << matrix_pt()->ncol() << std::endl;
1752 OOMPH_CURRENT_FUNCTION,
1753 OOMPH_EXCEPTION_LOCATION);
1762 Delete_input_data = Delete_matrix;
1771 hypre_matrix_setup(cr_matrix_pt);
1776 std::ostringstream error_message;
1777 error_message <<
"HyprePreconditioner only work with " 1778 <<
"CRDoubleMatrix matrices" 1781 OOMPH_CURRENT_FUNCTION,
1782 OOMPH_EXCEPTION_LOCATION);
1786 if (Context_string!=
"")
1788 oomph_info <<
"Setup of HyprePreconditioner in context \" " 1789 << Context_string <<
"\": nrow, nrow_local, nnz " 1790 << cr_matrix_pt->
nrow() <<
" " 1792 << cr_matrix_pt->
nnz() << std::endl;
1794 Context_based_nrow[Context_string]=cr_matrix_pt->
nrow();
1797 hypre_solver_setup();
1812 if (existing_solver()==None)
1814 std::ostringstream error_message;
1815 error_message <<
"preconditioner_solve(...) requires that data has " 1816 <<
"been set up using the function setup(...)" << std::endl;
1818 OOMPH_CURRENT_FUNCTION,
1819 OOMPH_EXCEPTION_LOCATION);
1825 std::ostringstream error_message;
1826 error_message <<
"The distribution of the rhs vector and the matrix " 1827 <<
" must be the same" << std::endl;
1829 OOMPH_CURRENT_FUNCTION,
1830 OOMPH_EXCEPTION_LOCATION);
1839 std::ostringstream error_message;
1840 error_message <<
"The distribution of the solution vector is setup " 1841 <<
"there it must be the same as the matrix." 1844 OOMPH_CURRENT_FUNCTION,
1845 OOMPH_EXCEPTION_LOCATION);
1851 Output_info =
false;
1858 Cumulative_preconditioner_solve_time+=(t_end-t_start);
1859 Cumulative_npreconditioner_solve++;
1860 My_cumulative_preconditioner_solve_time+=(t_end-t_start);
1861 if (Context_string!=
"")
1863 Context_based_cumulative_solve_time[Context_string]+=(t_end-t_start);
1864 Context_based_cumulative_npreconditioner_solve[Context_string]++;
1876 hypre_clean_up_memory();
int * column_index()
Access to C-style column index array.
unsigned long nnz() const
Return the number of nonzero entries (the local nnz)
unsigned & amg_simple_smoother()
Access function to AMG_simple_smoother flag.
void redistribute(const LinearAlgebraDistribution *const &dist_pt)
The contents of the vector are redistributed to match the new distribution. In a non-MPI rebuild this...
bool built() const
access function to the Built flag - indicates whether the matrix has been build - i...
void clean_up_memory()
Function deletes all solver data.
double & amg_damping()
Access function to AMG_damping parameter.
double * values_pt()
access function to the underlying values
void euclid_settings_helper(const bool &use_block_jacobi, const bool &use_row_scaling, const bool &use_ilut, const int &level, const double &drop_tol, const int &print_level, HYPRE_Solver &euclid_object)
Helper function to set Euclid options using a command line like array.
OomphCommunicator * communicator_pt() const
const access to the communicator pointer
void build(const OomphCommunicator *const comm_pt, const unsigned &first_row, const unsigned &nrow_local, const unsigned &nrow=0)
Sets the distribution. Takes first_row, nrow_local and nrow as arguments. If nrow is not provided or ...
unsigned & amg_coarsening()
Access function to AMG_coarsening flag.
static OomphCommunicator * communicator_pt()
access to the global oomph-lib communicator
unsigned first_row() const
access function for the first row on this processor. If not distributed then this is just zero...
bool distributed() const
access function to the distributed - indicates whether the distribution is serial or distributed ...
void hypre_matrix_setup(CRDoubleMatrix *matrix_pt)
Function which sets values of First_global_row, Last_global_row and other partitioning data and creat...
static bool mpi_has_been_initialised()
return true if MPI has been initialised
void set_amg_iterations(const unsigned &amg_iterations)
Function to set the number of times to apply BoomerAMG.
double * value()
Access to C-style value array.
The conjugate gradient method.
void solve(Problem *const &problem_pt, DoubleVector &solution)
Function which uses problem_pt's get_jacobian(...) function to generate a linear system which is then...
bool distributed() const
distribution is serial or distributed
double AMG_strength
Default for AMG strength (0.25 recommended for 2D problems; larger (0.5-0.75, say) for 3D...
Describes the distribution of a distributable linear algebra type object. Typically this is a contain...
void build(const DoubleVector &old_vector)
Just copys the argument DoubleVector.
unsigned long ncol() const
Return the number of columns of the matrix.
void amg_using_simple_smoothing()
Function to select use of 'simple' AMG smoothers as controlled by the flag AMG_simple_smoother.
void create_HYPRE_Vector(const LinearAlgebraDistribution *dist_pt, HYPRE_IJVector &hypre_ij_vector, HYPRE_ParVector &hypre_par_vector)
Helper function to create an empty HYPRE_IJVector and HYPRE_ParVector.
static unsigned Cumulative_npreconditioner_solve
Static unsigned that accumulates the number of preconditioner solves of all instantiations of this cl...
void hypre_solver_setup()
Sets up the data required for to use as an oomph-lib LinearSolver or Preconditioner. This must be called after the Hypre matrix has been generated using hypre_matrix_setup(...).
static std::map< std::string, double > Context_based_cumulative_solve_time
Static double that accumulates the preconditioner solve time of all instantiations of this class...
void create_HYPRE_Vector(const DoubleVector &oomph_vec, const LinearAlgebraDistribution *dist_pt, HYPRE_IJVector &hypre_ij_vector, HYPRE_ParVector &hypre_par_vector)
Helper function to create a HYPRE_IJVector and HYPRE_ParVector.
void set_defaults_for_3D_poisson_problem(HyprePreconditioner *hypre_preconditioner_pt)
Set default parameters for use as preconditioner in 3D Poisson-type problem.
void preconditioner_solve(const DoubleVector &r, DoubleVector &z)
Function applies solver to vector r for preconditioning. This requires a call to setup(...) first. Note: Hypre copies matrix data from oomph-lib's CRDoubleMatrix or DistributedCRDoubleMatrix into its own data structures, doubling the memory requirements for the matrix. As far as the Hypre solvers are concerned, the oomph-lib matrix is no longer required and could be deleted to save memory. However, this will not be the expected behaviour and therefore needs to be requested explicitly by the user with the delete_matrix() function.
unsigned nrow_local() const
access function for the num of local rows on this processor. If no MPI then Nrow is returned...
unsigned Max_iter
Max. # of Newton iterations.
unsigned & hypre_method()
Access function to Hypre_method flag – specified via enumeration.
void setup()
Function to set up a preconditioner for the linear system defined by matrix_pt. This function is requ...
double timer()
returns the time in seconds after some point in past
Preconditioner base class. Gives an interface to call all other preconditioners through and stores th...
virtual void get_jacobian(DoubleVector &residuals, DenseDoubleMatrix &jacobian)
Return the fully-assembled Jacobian and residuals for the problem Interface for the case when the Jac...
The conjugate gradient method.
double & amg_strength()
Access function to AMG_strength.
virtual unsigned long nrow() const =0
Return the number of rows of the matrix.
static double Cumulative_preconditioner_solve_time
Static double that accumulates the preconditioner solve time of all instantiations of this class...
void create_HYPRE_Matrix(CRDoubleMatrix *oomph_matrix, HYPRE_IJMatrix &hypre_ij_matrix, HYPRE_ParCSRMatrix &hypre_par_matrix, LinearAlgebraDistribution *dist_pt)
Helper function to create a serial HYPRE_IJMatrix and HYPRE_ParCSRMatrix from a CRDoubleMatrix.
void hypre_clean_up_memory()
Function deletes all solver data.
void hypre_solve(const DoubleVector &rhs, DoubleVector &solution)
Helper function performs a solve if any solver exists.
double AMG_truncation
AMG interpolation truncation factor.
unsigned nrow_local() const
access function for the num of local rows on this processor.
static void reset_cumulative_solve_times()
Reset cumulative solve times.
void clean_up_memory()
Function deletes all solver data.
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*)
unsigned long nrow() const
Return the number of rows of the matrix.
void set_defaults_for_navier_stokes_momentum_block(HyprePreconditioner *hypre_preconditioner_pt)
Set default parameters for use as preconditioner in for momentum block in Navier-Stokes problem...
double norm() const
compute the 2 norm of this vector
static std::map< std::string, unsigned > Context_based_nrow
Static unsigned that stores nrow for the most recent instantiations of this class, labeled by context string. Reset it manually, e.g. after every Newton solve, using reset_cumulative_solve_times().
int * row_start()
Access to C-style row_start array.
void resolve(const DoubleVector &rhs, DoubleVector &solution)
Function to resolve a linear system using the existing solver data, allowing a solve with a new right...
unsigned AMG_coarsening
Default AMG coarsening strategy. Coarsening types include: 0 = CLJP (parallel coarsening using indepe...
Abstract base class for matrices of doubles – adds abstract interfaces for solving, LU decomposition and multiplication by vectors.
A class for compressed row matrices. This is a distributable object.
LinearAlgebraDistribution * distribution_pt() const
access to the LinearAlgebraDistribution
virtual unsigned long ncol() const =0
Return the number of columns of the matrix.
static void report_cumulative_solve_times()
Report cumulative solve times of all instantiations of this class.
void set_defaults_for_2D_poisson_problem(HyprePreconditioner *hypre_preconditioner_pt)
Set default parameters for use as preconditioner in 2D Poisson-type problem.
static std::map< std::string, unsigned > Context_based_cumulative_npreconditioner_solve
Static unsigned that accumulates the number of preconditioner solves of all instantiations of this cl...
int check_HYPRE_error_flag(std::ostringstream &message)
Helper function to check the Hypre error flag, return the message associated with any error...
An oomph-lib wrapper to the MPI_Comm communicator object. Just contains an MPI_Comm object (which is ...
unsigned AMG_smoother_iterations
amg smoother iterations