248class AlephMatrixHypre
257 : IAlephMatrix(tm, kernel, index)
258 , m_hypre_ijmatrix(0)
260 debug() <<
"[AlephMatrixHypre] new AlephMatrixHypre";
265 debug() <<
"[~AlephMatrixHypre]";
266 if (m_hypre_ijmatrix)
267 HYPRE_IJMatrixDestroy(m_hypre_ijmatrix);
283 void AlephMatrixCreate(
void)
285 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE MatrixCreate idx:" << m_index;
289 for (
int iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
290 if (m_kernel->rank() != m_kernel->solverRanks(m_index)[iCpu])
293 ilower = m_kernel->topology()->gathered_nb_row(iCpu);
294 iupper = m_kernel->topology()->gathered_nb_row(iCpu + 1) - 1;
296 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] ilower=" << ilower <<
", iupper=" << iupper;
300 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] jlower=" << jlower <<
", jupper=" << jupper;
302 hypreCheck(
"HYPRE_IJMatrixCreate",
303 HYPRE_IJMatrixCreate(MPI_COMM_SUB,
308 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixSetObjectType";
309 HYPRE_IJMatrixSetObjectType(m_hypre_ijmatrix, HYPRE_PARCSR);
310 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixSetRowSizes";
311 HYPRE_IJMatrixSetRowSizes(m_hypre_ijmatrix, m_kernel->topology()->gathered_nb_row_elements().data());
312 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixInitialize";
313 HYPRE_IJMatrixInitialize(m_hypre_ijmatrix);
314 HYPRE_IJMatrixGetObject(m_hypre_ijmatrix, &
object);
315 m_hypre_parmatrix = (HYPRE_ParCSRMatrix)
object;
320 void AlephMatrixSetFilled(
bool) {}
324 int AlephMatrixAssemble(
void)
326 debug() <<
"[AlephMatrixHypre::AlephMatrixAssemble]";
327 hypreCheck(
"HYPRE_IJMatrixAssemble",
328 HYPRE_IJMatrixAssemble(m_hypre_ijmatrix));
334 void AlephMatrixFill(
int size, HYPRE_Int* rows, HYPRE_Int* cols,
double* values)
336 debug() <<
"[AlephMatrixHypre::AlephMatrixFill] size=" << size;
338 HYPRE_Int col[1] = { 1 };
339 for (
int i = 0; i < size; i++) {
340 rtn += HYPRE_IJMatrixSetValues(m_hypre_ijmatrix, 1, col, &rows[i], &cols[i], &values[i]);
342 hypreCheck(
"HYPRE_IJMatrixSetValues", rtn);
344 debug() <<
"[AlephMatrixHypre::AlephMatrixFill] done";
356 HYPRE_ClearAllErrors();
357 const bool convergence_analyse = params->convergenceAnalyse();
360 const Real res0 = b->norm_max();
362 if (convergence_analyse)
363 info() <<
"convergence analysis: max norm of the right-hand side res0: " << res0;
365 const Real considered_as_null = params->minRHSNorm();
366 if (res0 < considered_as_null) {
367 HYPRE_ParVectorSetConstantValues(x->m_hypre_parvector, 0.0);
368 residual_norm[0] = res0;
369 if (convergence_analyse)
370 info() <<
"convergence analysis: the right-hand side of the linear system is less than: " << considered_as_null;
374 if (params->xoUser()) {
381 HYPRE_ParCSRMatrixMatvec(1.0, m_hypre_parmatrix, x->m_hypre_parvector, 0., tmp->m_hypre_parvector);
382 HYPRE_ParVectorAxpy(-1.0, b->m_hypre_parvector, tmp->m_hypre_parvector);
384 const Real residu = tmp->norm_max();
387 if (residu < considered_as_null) {
388 if (convergence_analyse) {
389 info() <<
"convergence analysis: |Ax0-b| is less than " << considered_as_null;
390 info() <<
"convergence analysis: x0 is already a solution to the system.";
392 residual_norm[0] = residu;
396 const Real relative_error = residu / res0;
397 if (convergence_analyse)
398 info() <<
"convergence analysis: initial residual : " << residu
399 <<
" --- initial relative residual (residu/res0) : " << residu / res0;
401 if (relative_error < (params->epsilon())) {
402 if (convergence_analyse)
403 info() <<
"convergence analysis: X is already a solution to the system";
404 residual_norm[0] = residu;
420 solver_param->setAmgCoarseningMethod(TypesSolver::AMG_COARSENING_AUTO);
421 const String func_name(
"SolverMatrixHypre::solve");
428 HYPRE_IJVector solution = ximpl->m_hypre_ijvector;
429 HYPRE_IJVector RHS = bimpl->m_hypre_ijvector;
432 HYPRE_IJMatrixGetObject(m_hypre_ijmatrix, &
object);
433 HYPRE_ParCSRMatrix M = (HYPRE_ParCSRMatrix)
object;
434 HYPRE_IJVectorGetObject(solution, &
object);
435 HYPRE_ParVector X = (HYPRE_ParVector)
object;
436 HYPRE_IJVectorGetObject(RHS, &
object);
437 HYPRE_ParVector B = (HYPRE_ParVector)
object;
444 if (isAlreadySolved(ximpl2, bimpl2, timpl2, residual_norm, solver_param)) {
445 ItacRegion(isAlreadySolved, AlephMatrixHypre);
446 debug() <<
"[AlephMatrixHypre::AlephMatrixSolve] isAlreadySolved !";
451 TypesSolver::ePreconditionerMethod preconditioner_method = solver_param->precond();
453 TypesSolver::eSolverMethod solver_method = solver_param->method();
456 HYPRE_Solver solver = 0;
458 switch (solver_method) {
459 case TypesSolver::PCG:
460 initSolverPCG(solver_param, solver);
462 case TypesSolver::BiCGStab:
463 initSolverBiCGStab(solver_param, solver);
465 case TypesSolver::GMRES:
466 initSolverGMRES(solver_param, solver);
473 HYPRE_Solver precond = 0;
475 switch (preconditioner_method) {
476 case TypesSolver::NONE:
478 case TypesSolver::DIAGONAL:
479 setDiagonalPreconditioner(solver_method, solver, precond);
481 case TypesSolver::ILU:
482 setILUPreconditioner(solver_method, solver, precond);
484 case TypesSolver::SPAIstat:
485 setSpaiStatPreconditioner(solver_method, solver, solver_param, precond);
487 case TypesSolver::AMG:
488 setAMGPreconditioner(solver_method, solver, solver_param, precond);
490 case TypesSolver::AINV:
492 case TypesSolver::SPAIdyn:
494 case TypesSolver::ILUp:
496 case TypesSolver::IC:
498 case TypesSolver::POLY:
505 HYPRE_Int iteration = 0;
506 double residue = 0.0;
508 switch (solver_method) {
509 case TypesSolver::PCG:
510 ierr = solvePCG(solver_param, solver, M, B, X, iteration, residue);
512 case TypesSolver::BiCGStab:
513 ierr = solveBiCGStab(solver, M, B, X, iteration, residue);
515 case TypesSolver::GMRES:
516 ierr = solveGMRES(solver, M, B, X, iteration, residue);
522 nb_iteration =
static_cast<Integer>(iteration);
523 residual_norm[0] =
static_cast<Real>(residue);
538 switch (preconditioner_method) {
539 case TypesSolver::NONE:
541 case TypesSolver::DIAGONAL:
543 case TypesSolver::ILU:
544 HYPRE_ParCSRPilutDestroy(precond);
546 case TypesSolver::SPAIstat:
547 HYPRE_ParCSRParaSailsDestroy(precond);
549 case TypesSolver::AMG:
550 HYPRE_BoomerAMGDestroy(precond);
556 if (iteration == solver_param->maxIter() && solver_param->stopErrorStrategy()) {
557 info() <<
"\n============================================================";
558 info() <<
"\nThis error is returned after " << iteration <<
"\n";
559 info() <<
"\nMaximum number of solver iterations reached.";
560 info() <<
"\nIt is possible to ask the code not to consider this error.";
561 info() <<
"\nSee the dataset documentation regarding the solver service.";
562 info() <<
"\n======================================================";
563 throw Exception(
"AlephMatrixHypre::Solve",
"Maximum number of solver iterations reached");
570 void writeToFile(
const String filename)
572 HYPRE_IJMatrixPrint(m_hypre_ijmatrix, filename.
localstr());
577 void initSolverPCG(
const AlephParams* solver_param, HYPRE_Solver& solver)
579 const String func_name =
"SolverMatrixHypre::initSolverPCG";
580 double epsilon = solver_param->epsilon();
581 int max_it = solver_param->maxIter();
582 int output_level = solver_param->getOutputLevel();
584 HYPRE_ParCSRPCGCreate(MPI_COMM_SUB, &solver);
585 HYPRE_ParCSRPCGSetMaxIter(solver, max_it);
586 HYPRE_ParCSRPCGSetTol(solver, epsilon);
587 HYPRE_ParCSRPCGSetTwoNorm(solver, 1);
588 HYPRE_ParCSRPCGSetPrintLevel(solver, output_level);
593 void initSolverBiCGStab(
const AlephParams* solver_param, HYPRE_Solver& solver)
595 const String func_name =
"SolverMatrixHypre::initSolverBiCGStab";
596 double epsilon = solver_param->epsilon();
597 int max_it = solver_param->maxIter();
598 int output_level = solver_param->getOutputLevel();
600 HYPRE_ParCSRBiCGSTABCreate(MPI_COMM_SUB, &solver);
601 HYPRE_ParCSRBiCGSTABSetMaxIter(solver, max_it);
602 HYPRE_ParCSRBiCGSTABSetTol(solver, epsilon);
603 HYPRE_ParCSRBiCGSTABSetPrintLevel(solver, output_level);
608 void initSolverGMRES(
const AlephParams* solver_param, HYPRE_Solver& solver)
610 const String func_name =
"SolverMatrixHypre::initSolverGMRES";
611 double epsilon = solver_param->epsilon();
612 int max_it = solver_param->maxIter();
613 int output_level = solver_param->getOutputLevel();
615 HYPRE_ParCSRGMRESCreate(MPI_COMM_SUB, &solver);
616 const int krylov_dim = 20;
617 HYPRE_ParCSRGMRESSetKDim(solver, krylov_dim);
618 HYPRE_ParCSRGMRESSetMaxIter(solver, max_it);
619 HYPRE_ParCSRGMRESSetTol(solver, epsilon);
620 HYPRE_ParCSRGMRESSetPrintLevel(solver, output_level);
625 void setDiagonalPreconditioner(
const TypesSolver::eSolverMethod solver_method,
626 const HYPRE_Solver& solver,
627 HYPRE_Solver& precond)
629 const String func_name =
"SolverMatrixHypre::setDiagonalPreconditioner";
630 switch (solver_method) {
631 case TypesSolver::PCG:
632 HYPRE_ParCSRPCGSetPrecond(solver,
633 HYPRE_ParCSRDiagScale,
634 HYPRE_ParCSRDiagScaleSetup,
637 case TypesSolver::BiCGStab:
638 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
639 HYPRE_ParCSRDiagScale,
640 HYPRE_ParCSRDiagScaleSetup,
643 case TypesSolver::GMRES:
644 HYPRE_ParCSRGMRESSetPrecond(solver,
645 HYPRE_ParCSRDiagScale,
646 HYPRE_ParCSRDiagScaleSetup,
650 throw ArgumentException(func_name,
"unknown solver for 'Diagonal' preconditioner");
656 void setILUPreconditioner(
const TypesSolver::eSolverMethod solver_method,
657 const HYPRE_Solver& solver,
658 HYPRE_Solver& precond)
660 const String func_name =
"SolverMatrixHypre::setILUPreconditioner";
661 switch (solver_method) {
662 case TypesSolver::PCG:
663 throw ArgumentException(func_name,
"PCG solver unavailable with 'ILU' preconditioner");
665 case TypesSolver::BiCGStab:
666 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB, &precond);
667 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
668 HYPRE_ParCSRPilutSolve,
669 HYPRE_ParCSRPilutSetup,
672 case TypesSolver::GMRES:
673 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB,
675 HYPRE_ParCSRGMRESSetPrecond(solver,
676 HYPRE_ParCSRPilutSolve,
677 HYPRE_ParCSRPilutSetup,
687 void setSpaiStatPreconditioner(
const TypesSolver::eSolverMethod solver_method,
688 const HYPRE_Solver& solver,
690 HYPRE_Solver& precond)
692 HYPRE_ParCSRParaSailsCreate(MPI_COMM_SUB, &precond);
693 double alpha = solver_param->alpha();
694 int gamma = solver_param->gamma();
699 HYPRE_ParCSRParaSailsSetParams(precond, alpha, gamma);
700 switch (solver_method) {
701 case TypesSolver::PCG:
702 HYPRE_ParCSRPCGSetPrecond(solver, HYPRE_ParCSRParaSailsSolve, HYPRE_ParCSRParaSailsSetup, precond);
704 case TypesSolver::BiCGStab:
705 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur 'BiCGStab' invalide pour preconditionnement 'SPAIstat'");
707 case TypesSolver::GMRES:
709 HYPRE_ParCSRParaSailsSetSym(precond, 0);
710 HYPRE_ParCSRGMRESSetPrecond(solver, HYPRE_ParaSailsSolve, HYPRE_ParaSailsSetup, precond);
713 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur inconnu pour preconditionnement 'SPAIstat'\n");
720 void setAMGPreconditioner(
const TypesSolver::eSolverMethod solver_method,
721 const HYPRE_Solver& solver,
723 HYPRE_Solver& precond)
727 double trunc_factor = 0.1;
728 int cycle_type = solver_param->getAmgCycle();
729 int coarsen_type = solver_param->amgCoarseningMethod();
731 int relax_default = 3;
737 int measure_type = 1;
738 double max_row_sum = 1.0;
741 const int gamma = solver_param->gamma();
745 double strong_threshold = 0.1;
746 const double alpha = solver_param->alpha();
748 strong_threshold = alpha;
750 Integer output_level = solver_param->getOutputLevel();
752 HYPRE_Int* num_grid_sweeps = _allocHypre<HYPRE_Int>(4);
753 HYPRE_Int* grid_relax_type = _allocHypre<HYPRE_Int>(4);
754 HYPRE_Int** grid_relax_points = _allocHypre<HYPRE_Int*>(4);
755 double* relax_weight = _allocHypre<double>(max_levels);
757 for (
int i = 0; i < max_levels; i++)
758 relax_weight[i] = 1.0;
760 if (coarsen_type == 5) {
762 num_grid_sweeps[0] = 3;
763 grid_relax_type[0] = relax_default;
764 grid_relax_points[0] = _allocHypre<HYPRE_Int>(3);
765 grid_relax_points[0][0] = -2;
766 grid_relax_points[0][1] = -1;
767 grid_relax_points[0][2] = 1;
770 num_grid_sweeps[1] = 4;
771 grid_relax_type[1] = relax_default;
772 grid_relax_points[1] = _callocHypre<HYPRE_Int>(4);
773 grid_relax_points[1][0] = -1;
774 grid_relax_points[1][1] = 1;
775 grid_relax_points[1][2] = -2;
776 grid_relax_points[1][3] = -2;
779 num_grid_sweeps[2] = 4;
780 grid_relax_type[2] = relax_default;
781 grid_relax_points[2] = _allocHypre<HYPRE_Int>(4);
782 grid_relax_points[2][0] = -2;
783 grid_relax_points[2][1] = -2;
784 grid_relax_points[2][2] = 1;
785 grid_relax_points[2][3] = -1;
789 num_grid_sweeps[0] = 2 * num_sweep;
790 grid_relax_type[0] = relax_default;
791 grid_relax_points[0] = _allocHypre<HYPRE_Int>(2 * num_sweep);
792 for (
int i = 0; i < 2 * num_sweep; i += 2) {
793 grid_relax_points[0][i] = -1;
794 grid_relax_points[0][i + 1] = 1;
798 num_grid_sweeps[1] = 2 * num_sweep;
799 grid_relax_type[1] = relax_default;
800 grid_relax_points[1] = _allocHypre<HYPRE_Int>(2 * num_sweep);
801 for (
int i = 0; i < 2 * num_sweep; i += 2) {
802 grid_relax_points[1][i] = -1;
803 grid_relax_points[1][i + 1] = 1;
807 num_grid_sweeps[2] = 2 * num_sweep;
808 grid_relax_type[2] = relax_default;
809 grid_relax_points[2] = _allocHypre<HYPRE_Int>(2 * num_sweep);
810 for (
int i = 0; i < 2 * num_sweep; i += 2) {
811 grid_relax_points[2][i] = -1;
812 grid_relax_points[2][i + 1] = 1;
817 num_grid_sweeps[3] = 1;
818 grid_relax_type[3] = 9;
819 grid_relax_points[3] = _allocHypre<HYPRE_Int>(1);
820 grid_relax_points[3][0] = 0;
824 HYPRE_BoomerAMGCreate(&precond);
825 HYPRE_BoomerAMGSetPrintLevel(precond, output_level);
826 HYPRE_BoomerAMGSetCoarsenType(precond, (hybrid * coarsen_type));
827 HYPRE_BoomerAMGSetMeasureType(precond, measure_type);
828 HYPRE_BoomerAMGSetStrongThreshold(precond, strong_threshold);
829 HYPRE_BoomerAMGSetTruncFactor(precond, trunc_factor);
830 HYPRE_BoomerAMGSetMaxIter(precond, 1);
831 HYPRE_BoomerAMGSetCycleType(precond, cycle_type);
832 HYPRE_BoomerAMGSetNumGridSweeps(precond, num_grid_sweeps);
833 HYPRE_BoomerAMGSetGridRelaxType(precond, grid_relax_type);
834 HYPRE_BoomerAMGSetRelaxWeight(precond, relax_weight);
835 HYPRE_BoomerAMGSetGridRelaxPoints(precond, grid_relax_points);
836 HYPRE_BoomerAMGSetTol(precond, 0.0);
837 HYPRE_BoomerAMGSetMaxLevels(precond, max_levels);
838 HYPRE_BoomerAMGSetMaxRowSum(precond, max_row_sum);
840 switch (solver_method) {
841 case TypesSolver::PCG:
842 HYPRE_ParCSRPCGSetPrecond(solver,
843 HYPRE_BoomerAMGSolve,
844 HYPRE_BoomerAMGSetup,
847 case TypesSolver::BiCGStab:
848 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
849 HYPRE_BoomerAMGSolve,
850 HYPRE_BoomerAMGSetup,
853 case TypesSolver::GMRES:
854 HYPRE_ParCSRGMRESSetPrecond(solver,
855 HYPRE_BoomerAMGSolve,
856 HYPRE_BoomerAMGSetup,
860 throw ArgumentException(
"AlephMatrixHypre::setAMGPreconditioner",
"solveur inconnu pour preconditionnement 'AMG'\n");
867 HYPRE_Solver& solver,
868 HYPRE_ParCSRMatrix& M,
871 HYPRE_Int& iteration,
874 const String func_name =
"SolverMatrixHypre::solvePCG";
875 const bool xo = solver_param->xoUser();
879 HYPRE_ParVectorSetConstantValues(X, 0.0);
880 HYPRE_ParCSRPCGSetup(solver, M, B, X);
881 HYPRE_ParCSRPCGSolve(solver, M, B, X);
882 HYPRE_ParCSRPCGGetNumIterations(solver, &iteration);
883 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver, &residue);
885 HYPRE_Int converged = 0;
886 HYPRE_PCGGetConverged(solver, &converged);
887 error |= (!converged);
889 HYPRE_ParCSRPCGDestroy(solver);
896 bool solveBiCGStab(HYPRE_Solver& solver,
897 HYPRE_ParCSRMatrix& M,
900 HYPRE_Int& iteration,
903 const String func_name =
"SolverMatrixHypre::solveBiCGStab";
905 HYPRE_ParVectorSetRandomValues(X, 775);
906 HYPRE_ParCSRBiCGSTABSetup(solver, M, B, X);
907 HYPRE_ParCSRBiCGSTABSolve(solver, M, B, X);
908 HYPRE_ParCSRBiCGSTABGetNumIterations(solver, &iteration);
909 HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(solver, &residue);
911 HYPRE_Int converged = 0;
912 hypre_BiCGSTABGetConverged(solver, &converged);
913 error |= (!converged);
915 HYPRE_ParCSRBiCGSTABDestroy(solver);
922 bool solveGMRES(HYPRE_Solver& solver,
923 HYPRE_ParCSRMatrix& M,
926 HYPRE_Int& iteration,
929 const String func_name =
"SolverMatrixHypre::solveGMRES";
931 HYPRE_ParCSRGMRESSetup(solver, M, B, X);
932 HYPRE_ParCSRGMRESSolve(solver, M, B, X);
933 HYPRE_ParCSRGMRESGetNumIterations(solver, &iteration);
934 HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(solver, &residue);
936 HYPRE_Int converged = 0;
937 HYPRE_GMRESGetConverged(solver, &converged);
938 error |= (!converged);
940 HYPRE_ParCSRGMRESDestroy(solver);
946 HYPRE_IJMatrix m_hypre_ijmatrix =
nullptr;
947 HYPRE_ParCSRMatrix m_hypre_parmatrix =
nullptr;