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 if (values[i] != 0.0)
341 rtn += HYPRE_IJMatrixSetValues(m_hypre_ijmatrix, 1, col, &rows[i], &cols[i], &values[i]);
343 hypreCheck(
"HYPRE_IJMatrixSetValues", rtn);
345 debug() <<
"[AlephMatrixHypre::AlephMatrixFill] done";
357 HYPRE_ClearAllErrors();
358 const bool convergence_analyse = params->convergenceAnalyse();
361 const Real res0 = b->norm_max();
363 if (convergence_analyse)
364 info() <<
"convergence analysis: max norm of the right-hand side res0: " << res0;
366 const Real considered_as_null = params->minRHSNorm();
367 if (res0 < considered_as_null) {
368 HYPRE_ParVectorSetConstantValues(x->m_hypre_parvector, 0.0);
369 residual_norm[0] = res0;
370 if (convergence_analyse)
371 info() <<
"convergence analysis: the right-hand side of the linear system is less than: " << considered_as_null;
375 if (params->xoUser()) {
382 HYPRE_ParCSRMatrixMatvec(1.0, m_hypre_parmatrix, x->m_hypre_parvector, 0., tmp->m_hypre_parvector);
383 HYPRE_ParVectorAxpy(-1.0, b->m_hypre_parvector, tmp->m_hypre_parvector);
385 const Real residu = tmp->norm_max();
388 if (residu < considered_as_null) {
389 if (convergence_analyse) {
390 info() <<
"convergence analysis: |Ax0-b| is less than " << considered_as_null;
391 info() <<
"convergence analysis: x0 is already a solution to the system.";
393 residual_norm[0] = residu;
397 const Real relative_error = residu / res0;
398 if (convergence_analyse)
399 info() <<
"convergence analysis: initial residual : " << residu
400 <<
" --- initial relative residual (residu/res0) : " << residu / res0;
402 if (relative_error < (params->epsilon())) {
403 if (convergence_analyse)
404 info() <<
"convergence analysis: X is already a solution to the system";
405 residual_norm[0] = residu;
421 solver_param->setAmgCoarseningMethod(TypesSolver::AMG_COARSENING_AUTO);
422 const String func_name(
"SolverMatrixHypre::solve");
429 HYPRE_IJVector solution = ximpl->m_hypre_ijvector;
430 HYPRE_IJVector RHS = bimpl->m_hypre_ijvector;
433 HYPRE_IJMatrixGetObject(m_hypre_ijmatrix, &
object);
434 HYPRE_ParCSRMatrix M = (HYPRE_ParCSRMatrix)
object;
435 HYPRE_IJVectorGetObject(solution, &
object);
436 HYPRE_ParVector X = (HYPRE_ParVector)
object;
437 HYPRE_IJVectorGetObject(RHS, &
object);
438 HYPRE_ParVector B = (HYPRE_ParVector)
object;
445 if (isAlreadySolved(ximpl2, bimpl2, timpl2, residual_norm, solver_param)) {
446 ItacRegion(isAlreadySolved, AlephMatrixHypre);
447 debug() <<
"[AlephMatrixHypre::AlephMatrixSolve] isAlreadySolved !";
452 TypesSolver::ePreconditionerMethod preconditioner_method = solver_param->precond();
454 TypesSolver::eSolverMethod solver_method = solver_param->method();
457 HYPRE_Solver solver = 0;
459 switch (solver_method) {
460 case TypesSolver::PCG:
461 initSolverPCG(solver_param, solver);
463 case TypesSolver::BiCGStab:
464 initSolverBiCGStab(solver_param, solver);
466 case TypesSolver::GMRES:
467 initSolverGMRES(solver_param, solver);
474 HYPRE_Solver precond = 0;
476 switch (preconditioner_method) {
477 case TypesSolver::NONE:
479 case TypesSolver::DIAGONAL:
480 setDiagonalPreconditioner(solver_method, solver, precond);
482 case TypesSolver::ILU:
483 setILUPreconditioner(solver_method, solver, precond);
485 case TypesSolver::SPAIstat:
486 setSpaiStatPreconditioner(solver_method, solver, solver_param, precond);
488 case TypesSolver::AMG:
489 setAMGPreconditioner(solver_method, solver, solver_param, precond);
491 case TypesSolver::AINV:
493 case TypesSolver::SPAIdyn:
495 case TypesSolver::ILUp:
497 case TypesSolver::IC:
499 case TypesSolver::POLY:
506 HYPRE_Int iteration = 0;
507 double residue = 0.0;
509 switch (solver_method) {
510 case TypesSolver::PCG:
511 ierr = solvePCG(solver_param, solver, M, B, X, iteration, residue);
513 case TypesSolver::BiCGStab:
514 ierr = solveBiCGStab(solver, M, B, X, iteration, residue);
516 case TypesSolver::GMRES:
517 ierr = solveGMRES(solver, M, B, X, iteration, residue);
523 nb_iteration =
static_cast<Integer>(iteration);
524 residual_norm[0] =
static_cast<Real>(residue);
539 switch (preconditioner_method) {
540 case TypesSolver::NONE:
542 case TypesSolver::DIAGONAL:
544 case TypesSolver::ILU:
545 HYPRE_ParCSRPilutDestroy(precond);
547 case TypesSolver::SPAIstat:
548 HYPRE_ParCSRParaSailsDestroy(precond);
550 case TypesSolver::AMG:
551 HYPRE_BoomerAMGDestroy(precond);
557 if (iteration == solver_param->maxIter() && solver_param->stopErrorStrategy()) {
558 info() <<
"\n============================================================";
559 info() <<
"\nThis error is returned after " << iteration <<
"\n";
560 info() <<
"\nMaximum number of solver iterations reached.";
561 info() <<
"\nIt is possible to ask the code not to consider this error.";
562 info() <<
"\nSee the dataset documentation regarding the solver service.";
563 info() <<
"\n======================================================";
564 throw Exception(
"AlephMatrixHypre::Solve",
"Maximum number of solver iterations reached");
571 void writeToFile(
const String filename)
573 HYPRE_IJMatrixPrint(m_hypre_ijmatrix, filename.
localstr());
578 void initSolverPCG(
const AlephParams* solver_param, HYPRE_Solver& solver)
580 const String func_name =
"SolverMatrixHypre::initSolverPCG";
581 double epsilon = solver_param->epsilon();
582 int max_it = solver_param->maxIter();
583 int output_level = solver_param->getOutputLevel();
585 HYPRE_ParCSRPCGCreate(MPI_COMM_SUB, &solver);
586 HYPRE_ParCSRPCGSetMaxIter(solver, max_it);
587 HYPRE_ParCSRPCGSetTol(solver, epsilon);
588 HYPRE_ParCSRPCGSetTwoNorm(solver, 1);
589 HYPRE_ParCSRPCGSetPrintLevel(solver, output_level);
594 void initSolverBiCGStab(
const AlephParams* solver_param, HYPRE_Solver& solver)
596 const String func_name =
"SolverMatrixHypre::initSolverBiCGStab";
597 double epsilon = solver_param->epsilon();
598 int max_it = solver_param->maxIter();
599 int output_level = solver_param->getOutputLevel();
601 HYPRE_ParCSRBiCGSTABCreate(MPI_COMM_SUB, &solver);
602 HYPRE_ParCSRBiCGSTABSetMaxIter(solver, max_it);
603 HYPRE_ParCSRBiCGSTABSetTol(solver, epsilon);
604 HYPRE_ParCSRBiCGSTABSetPrintLevel(solver, output_level);
609 void initSolverGMRES(
const AlephParams* solver_param, HYPRE_Solver& solver)
611 const String func_name =
"SolverMatrixHypre::initSolverGMRES";
612 double epsilon = solver_param->epsilon();
613 int max_it = solver_param->maxIter();
614 int output_level = solver_param->getOutputLevel();
616 HYPRE_ParCSRGMRESCreate(MPI_COMM_SUB, &solver);
617 const int krylov_dim = 20;
618 HYPRE_ParCSRGMRESSetKDim(solver, krylov_dim);
619 HYPRE_ParCSRGMRESSetMaxIter(solver, max_it);
620 HYPRE_ParCSRGMRESSetTol(solver, epsilon);
621 HYPRE_ParCSRGMRESSetPrintLevel(solver, output_level);
626 void setDiagonalPreconditioner(
const TypesSolver::eSolverMethod solver_method,
627 const HYPRE_Solver& solver,
628 HYPRE_Solver& precond)
630 const String func_name =
"SolverMatrixHypre::setDiagonalPreconditioner";
631 switch (solver_method) {
632 case TypesSolver::PCG:
633 HYPRE_ParCSRPCGSetPrecond(solver,
634 HYPRE_ParCSRDiagScale,
635 HYPRE_ParCSRDiagScaleSetup,
638 case TypesSolver::BiCGStab:
639 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
640 HYPRE_ParCSRDiagScale,
641 HYPRE_ParCSRDiagScaleSetup,
644 case TypesSolver::GMRES:
645 HYPRE_ParCSRGMRESSetPrecond(solver,
646 HYPRE_ParCSRDiagScale,
647 HYPRE_ParCSRDiagScaleSetup,
651 throw ArgumentException(func_name,
"unknown solver for 'Diagonal' preconditioner");
657 void setILUPreconditioner(
const TypesSolver::eSolverMethod solver_method,
658 const HYPRE_Solver& solver,
659 HYPRE_Solver& precond)
661 const String func_name =
"SolverMatrixHypre::setILUPreconditioner";
662 switch (solver_method) {
663 case TypesSolver::PCG:
664 throw ArgumentException(func_name,
"PCG solver unavailable with 'ILU' preconditioner");
666 case TypesSolver::BiCGStab:
667 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB, &precond);
668 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
669 HYPRE_ParCSRPilutSolve,
670 HYPRE_ParCSRPilutSetup,
673 case TypesSolver::GMRES:
674 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB,
676 HYPRE_ParCSRGMRESSetPrecond(solver,
677 HYPRE_ParCSRPilutSolve,
678 HYPRE_ParCSRPilutSetup,
688 void setSpaiStatPreconditioner(
const TypesSolver::eSolverMethod solver_method,
689 const HYPRE_Solver& solver,
691 HYPRE_Solver& precond)
693 HYPRE_ParCSRParaSailsCreate(MPI_COMM_SUB, &precond);
694 double alpha = solver_param->alpha();
695 int gamma = solver_param->gamma();
700 HYPRE_ParCSRParaSailsSetParams(precond, alpha, gamma);
701 switch (solver_method) {
702 case TypesSolver::PCG:
703 HYPRE_ParCSRPCGSetPrecond(solver, HYPRE_ParCSRParaSailsSolve, HYPRE_ParCSRParaSailsSetup, precond);
705 case TypesSolver::BiCGStab:
706 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur 'BiCGStab' invalide pour preconditionnement 'SPAIstat'");
708 case TypesSolver::GMRES:
710 HYPRE_ParCSRParaSailsSetSym(precond, 0);
711 HYPRE_ParCSRGMRESSetPrecond(solver, HYPRE_ParaSailsSolve, HYPRE_ParaSailsSetup, precond);
714 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur inconnu pour preconditionnement 'SPAIstat'\n");
721 void setAMGPreconditioner(
const TypesSolver::eSolverMethod solver_method,
722 const HYPRE_Solver& solver,
724 HYPRE_Solver& precond)
728 double trunc_factor = 0.1;
729 int cycle_type = solver_param->getAmgCycle();
730 int coarsen_type = solver_param->amgCoarseningMethod();
732 int relax_default = 3;
738 int measure_type = 1;
739 double max_row_sum = 1.0;
742 const int gamma = solver_param->gamma();
746 double strong_threshold = 0.1;
747 const double alpha = solver_param->alpha();
749 strong_threshold = alpha;
751 Integer output_level = solver_param->getOutputLevel();
753 HYPRE_Int* num_grid_sweeps = _allocHypre<HYPRE_Int>(4);
754 HYPRE_Int* grid_relax_type = _allocHypre<HYPRE_Int>(4);
755 HYPRE_Int** grid_relax_points = _allocHypre<HYPRE_Int*>(4);
756 double* relax_weight = _allocHypre<double>(max_levels);
758 for (
int i = 0; i < max_levels; i++)
759 relax_weight[i] = 1.0;
761 if (coarsen_type == 5) {
763 num_grid_sweeps[0] = 3;
764 grid_relax_type[0] = relax_default;
765 grid_relax_points[0] = _allocHypre<HYPRE_Int>(3);
766 grid_relax_points[0][0] = -2;
767 grid_relax_points[0][1] = -1;
768 grid_relax_points[0][2] = 1;
771 num_grid_sweeps[1] = 4;
772 grid_relax_type[1] = relax_default;
773 grid_relax_points[1] = _callocHypre<HYPRE_Int>(4);
774 grid_relax_points[1][0] = -1;
775 grid_relax_points[1][1] = 1;
776 grid_relax_points[1][2] = -2;
777 grid_relax_points[1][3] = -2;
780 num_grid_sweeps[2] = 4;
781 grid_relax_type[2] = relax_default;
782 grid_relax_points[2] = _allocHypre<HYPRE_Int>(4);
783 grid_relax_points[2][0] = -2;
784 grid_relax_points[2][1] = -2;
785 grid_relax_points[2][2] = 1;
786 grid_relax_points[2][3] = -1;
790 num_grid_sweeps[0] = 2 * num_sweep;
791 grid_relax_type[0] = relax_default;
792 grid_relax_points[0] = _allocHypre<HYPRE_Int>(2 * num_sweep);
793 for (
int i = 0; i < 2 * num_sweep; i += 2) {
794 grid_relax_points[0][i] = -1;
795 grid_relax_points[0][i + 1] = 1;
799 num_grid_sweeps[1] = 2 * num_sweep;
800 grid_relax_type[1] = relax_default;
801 grid_relax_points[1] = _allocHypre<HYPRE_Int>(2 * num_sweep);
802 for (
int i = 0; i < 2 * num_sweep; i += 2) {
803 grid_relax_points[1][i] = -1;
804 grid_relax_points[1][i + 1] = 1;
808 num_grid_sweeps[2] = 2 * num_sweep;
809 grid_relax_type[2] = relax_default;
810 grid_relax_points[2] = _allocHypre<HYPRE_Int>(2 * num_sweep);
811 for (
int i = 0; i < 2 * num_sweep; i += 2) {
812 grid_relax_points[2][i] = -1;
813 grid_relax_points[2][i + 1] = 1;
818 num_grid_sweeps[3] = 1;
819 grid_relax_type[3] = 9;
820 grid_relax_points[3] = _allocHypre<HYPRE_Int>(1);
821 grid_relax_points[3][0] = 0;
825 HYPRE_BoomerAMGCreate(&precond);
826 HYPRE_BoomerAMGSetPrintLevel(precond, output_level);
827 HYPRE_BoomerAMGSetCoarsenType(precond, (hybrid * coarsen_type));
828 HYPRE_BoomerAMGSetMeasureType(precond, measure_type);
829 HYPRE_BoomerAMGSetStrongThreshold(precond, strong_threshold);
830 HYPRE_BoomerAMGSetTruncFactor(precond, trunc_factor);
831 HYPRE_BoomerAMGSetMaxIter(precond, 1);
832 HYPRE_BoomerAMGSetCycleType(precond, cycle_type);
833 HYPRE_BoomerAMGSetNumGridSweeps(precond, num_grid_sweeps);
834 HYPRE_BoomerAMGSetGridRelaxType(precond, grid_relax_type);
835 HYPRE_BoomerAMGSetRelaxWeight(precond, relax_weight);
836 HYPRE_BoomerAMGSetGridRelaxPoints(precond, grid_relax_points);
837 HYPRE_BoomerAMGSetTol(precond, 0.0);
838 HYPRE_BoomerAMGSetMaxLevels(precond, max_levels);
839 HYPRE_BoomerAMGSetMaxRowSum(precond, max_row_sum);
841 switch (solver_method) {
842 case TypesSolver::PCG:
843 HYPRE_ParCSRPCGSetPrecond(solver,
844 HYPRE_BoomerAMGSolve,
845 HYPRE_BoomerAMGSetup,
848 case TypesSolver::BiCGStab:
849 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
850 HYPRE_BoomerAMGSolve,
851 HYPRE_BoomerAMGSetup,
854 case TypesSolver::GMRES:
855 HYPRE_ParCSRGMRESSetPrecond(solver,
856 HYPRE_BoomerAMGSolve,
857 HYPRE_BoomerAMGSetup,
861 throw ArgumentException(
"AlephMatrixHypre::setAMGPreconditioner",
"solveur inconnu pour preconditionnement 'AMG'\n");
868 HYPRE_Solver& solver,
869 HYPRE_ParCSRMatrix& M,
872 HYPRE_Int& iteration,
875 const String func_name =
"SolverMatrixHypre::solvePCG";
876 const bool xo = solver_param->xoUser();
880 HYPRE_ParVectorSetConstantValues(X, 0.0);
881 HYPRE_ParCSRPCGSetup(solver, M, B, X);
882 HYPRE_ParCSRPCGSolve(solver, M, B, X);
883 HYPRE_ParCSRPCGGetNumIterations(solver, &iteration);
884 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver, &residue);
886 HYPRE_Int converged = 0;
887 HYPRE_PCGGetConverged(solver, &converged);
888 error |= (!converged);
890 HYPRE_ParCSRPCGDestroy(solver);
897 bool solveBiCGStab(HYPRE_Solver& solver,
898 HYPRE_ParCSRMatrix& M,
901 HYPRE_Int& iteration,
904 const String func_name =
"SolverMatrixHypre::solveBiCGStab";
906 HYPRE_ParVectorSetRandomValues(X, 775);
907 HYPRE_ParCSRBiCGSTABSetup(solver, M, B, X);
908 HYPRE_ParCSRBiCGSTABSolve(solver, M, B, X);
909 HYPRE_ParCSRBiCGSTABGetNumIterations(solver, &iteration);
910 HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(solver, &residue);
912 HYPRE_Int converged = 0;
913 hypre_BiCGSTABGetConverged(solver, &converged);
914 error |= (!converged);
916 HYPRE_ParCSRBiCGSTABDestroy(solver);
923 bool solveGMRES(HYPRE_Solver& solver,
924 HYPRE_ParCSRMatrix& M,
927 HYPRE_Int& iteration,
930 const String func_name =
"SolverMatrixHypre::solveGMRES";
932 HYPRE_ParCSRGMRESSetup(solver, M, B, X);
933 HYPRE_ParCSRGMRESSolve(solver, M, B, X);
934 HYPRE_ParCSRGMRESGetNumIterations(solver, &iteration);
935 HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(solver, &residue);
937 HYPRE_Int converged = 0;
938 HYPRE_GMRESGetConverged(solver, &converged);
939 error |= (!converged);
941 HYPRE_ParCSRGMRESDestroy(solver);
947 HYPRE_IJMatrix m_hypre_ijmatrix =
nullptr;
948 HYPRE_ParCSRMatrix m_hypre_parmatrix =
nullptr;