247class AlephMatrixHypre
256 : IAlephMatrix(tm, kernel, index)
257 , m_hypre_ijmatrix(0)
259 debug() <<
"[AlephMatrixHypre] new AlephMatrixHypre";
264 debug() <<
"[~AlephMatrixHypre]";
265 if (m_hypre_ijmatrix)
266 HYPRE_IJMatrixDestroy(m_hypre_ijmatrix);
282 void AlephMatrixCreate(
void)
284 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE MatrixCreate idx:" << m_index;
288 for (
int iCpu = 0; iCpu < m_kernel->size(); ++iCpu) {
289 if (m_kernel->rank() != m_kernel->solverRanks(m_index)[iCpu])
292 ilower = m_kernel->topology()->gathered_nb_row(iCpu);
293 iupper = m_kernel->topology()->gathered_nb_row(iCpu + 1) - 1;
295 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] ilower=" << ilower <<
", iupper=" << iupper;
299 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] jlower=" << jlower <<
", jupper=" << jupper;
301 hypreCheck(
"HYPRE_IJMatrixCreate",
302 HYPRE_IJMatrixCreate(MPI_COMM_SUB,
307 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixSetObjectType";
308 HYPRE_IJMatrixSetObjectType(m_hypre_ijmatrix, HYPRE_PARCSR);
309 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixSetRowSizes";
310 HYPRE_IJMatrixSetRowSizes(m_hypre_ijmatrix, m_kernel->topology()->gathered_nb_row_elements().data());
311 debug() <<
"[AlephMatrixHypre::AlephMatrixCreate] HYPRE IJMatrixInitialize";
312 HYPRE_IJMatrixInitialize(m_hypre_ijmatrix);
313 HYPRE_IJMatrixGetObject(m_hypre_ijmatrix, &
object);
314 m_hypre_parmatrix = (HYPRE_ParCSRMatrix)
object;
319 void AlephMatrixSetFilled(
bool) {}
323 int AlephMatrixAssemble(
void)
325 debug() <<
"[AlephMatrixHypre::AlephMatrixAssemble]";
326 hypreCheck(
"HYPRE_IJMatrixAssemble",
327 HYPRE_IJMatrixAssemble(m_hypre_ijmatrix));
333 void AlephMatrixFill(
int size, HYPRE_Int* rows, HYPRE_Int* cols,
double* values)
335 debug() <<
"[AlephMatrixHypre::AlephMatrixFill] size=" << size;
337 HYPRE_Int col[1] = { 1 };
338 for (
int i = 0; i < size; i++) {
339 rtn += HYPRE_IJMatrixSetValues(m_hypre_ijmatrix, 1, col, &rows[i], &cols[i], &values[i]);
341 hypreCheck(
"HYPRE_IJMatrixSetValues", rtn);
343 debug() <<
"[AlephMatrixHypre::AlephMatrixFill] done";
355 HYPRE_ClearAllErrors();
356 const bool convergence_analyse = params->convergenceAnalyse();
359 const Real res0 = b->norm_max();
361 if (convergence_analyse)
362 info() <<
"analyse convergence : norme max du second membre res0 : " << res0;
364 const Real considered_as_null = params->minRHSNorm();
365 if (res0 < considered_as_null) {
366 HYPRE_ParVectorSetConstantValues(x->m_hypre_parvector, 0.0);
367 residual_norm[0] = res0;
368 if (convergence_analyse)
369 info() <<
"analyse convergence : le second membre du système linéaire est inférieur à : " << considered_as_null;
373 if (params->xoUser()) {
380 HYPRE_ParCSRMatrixMatvec(1.0, m_hypre_parmatrix, x->m_hypre_parvector, 0., tmp->m_hypre_parvector);
381 HYPRE_ParVectorAxpy(-1.0, b->m_hypre_parvector, tmp->m_hypre_parvector);
383 const Real residu = tmp->norm_max();
386 if (residu < considered_as_null) {
387 if (convergence_analyse) {
388 info() <<
"analyse convergence : |Ax0-b| est inférieur à " << considered_as_null;
389 info() <<
"analyse convergence : x0 est déjà solution du système.";
391 residual_norm[0] = residu;
395 const Real relative_error = residu / res0;
396 if (convergence_analyse)
397 info() <<
"analyse convergence : résidu initial : " << residu
398 <<
" --- residu relatif initial (residu/res0) : " << residu / res0;
400 if (relative_error < (params->epsilon())) {
401 if (convergence_analyse)
402 info() <<
"analyse convergence : X est déjà solution du système";
403 residual_norm[0] = residu;
419 solver_param->setAmgCoarseningMethod(TypesSolver::AMG_COARSENING_AUTO);
420 const String func_name(
"SolverMatrixHypre::solve");
427 HYPRE_IJVector solution = ximpl->m_hypre_ijvector;
428 HYPRE_IJVector RHS = bimpl->m_hypre_ijvector;
431 HYPRE_IJMatrixGetObject(m_hypre_ijmatrix, &
object);
432 HYPRE_ParCSRMatrix M = (HYPRE_ParCSRMatrix)
object;
433 HYPRE_IJVectorGetObject(solution, &
object);
434 HYPRE_ParVector X = (HYPRE_ParVector)
object;
435 HYPRE_IJVectorGetObject(RHS, &
object);
436 HYPRE_ParVector B = (HYPRE_ParVector)
object;
443 if (isAlreadySolved(ximpl2, bimpl2, timpl2, residual_norm, solver_param)) {
444 ItacRegion(isAlreadySolved, AlephMatrixHypre);
445 debug() <<
"[AlephMatrixHypre::AlephMatrixSolve] isAlreadySolved !";
450 TypesSolver::ePreconditionerMethod preconditioner_method = solver_param->precond();
452 TypesSolver::eSolverMethod solver_method = solver_param->method();
455 HYPRE_Solver solver = 0;
457 switch (solver_method) {
458 case TypesSolver::PCG:
459 initSolverPCG(solver_param, solver);
461 case TypesSolver::BiCGStab:
462 initSolverBiCGStab(solver_param, solver);
464 case TypesSolver::GMRES:
465 initSolverGMRES(solver_param, solver);
472 HYPRE_Solver precond = 0;
474 switch (preconditioner_method) {
475 case TypesSolver::NONE:
477 case TypesSolver::DIAGONAL:
478 setDiagonalPreconditioner(solver_method, solver, precond);
480 case TypesSolver::ILU:
481 setILUPreconditioner(solver_method, solver, precond);
483 case TypesSolver::SPAIstat:
484 setSpaiStatPreconditioner(solver_method, solver, solver_param, precond);
486 case TypesSolver::AMG:
487 setAMGPreconditioner(solver_method, solver, solver_param, precond);
489 case TypesSolver::AINV:
491 case TypesSolver::SPAIdyn:
493 case TypesSolver::ILUp:
495 case TypesSolver::IC:
497 case TypesSolver::POLY:
504 HYPRE_Int iteration = 0;
505 double residue = 0.0;
507 switch (solver_method) {
508 case TypesSolver::PCG:
509 ierr = solvePCG(solver_param, solver, M, B, X, iteration, residue);
511 case TypesSolver::BiCGStab:
512 ierr = solveBiCGStab(solver, M, B, X, iteration, residue);
514 case TypesSolver::GMRES:
515 ierr = solveGMRES(solver, M, B, X, iteration, residue);
521 nb_iteration =
static_cast<Integer>(iteration);
522 residual_norm[0] =
static_cast<Real>(residue);
537 switch (preconditioner_method) {
538 case TypesSolver::NONE:
540 case TypesSolver::DIAGONAL:
542 case TypesSolver::ILU:
543 HYPRE_ParCSRPilutDestroy(precond);
545 case TypesSolver::SPAIstat:
546 HYPRE_ParCSRParaSailsDestroy(precond);
548 case TypesSolver::AMG:
549 HYPRE_BoomerAMGDestroy(precond);
555 if (iteration == solver_param->maxIter() && solver_param->stopErrorStrategy()) {
556 info() <<
"\n============================================================";
557 info() <<
"\nCette erreur est retournée après " << iteration <<
"\n";
558 info() <<
"\nOn a atteind le nombre max d'itérations du solveur.";
559 info() <<
"\nIl est possible de demander au code de ne pas tenir compte de cette erreur.";
560 info() <<
"\nVoir la documentation du jeu de données concernant le service solveur.";
561 info() <<
"\n======================================================";
562 throw Exception(
"AlephMatrixHypre::Solve",
"On a atteind le nombre max d'itérations du solveur");
569 void writeToFile(
const String filename)
571 HYPRE_IJMatrixPrint(m_hypre_ijmatrix, filename.
localstr());
576 void initSolverPCG(
const AlephParams* solver_param, HYPRE_Solver& solver)
578 const String func_name =
"SolverMatrixHypre::initSolverPCG";
579 double epsilon = solver_param->epsilon();
580 int max_it = solver_param->maxIter();
581 int output_level = solver_param->getOutputLevel();
583 HYPRE_ParCSRPCGCreate(MPI_COMM_SUB, &solver);
584 HYPRE_ParCSRPCGSetMaxIter(solver, max_it);
585 HYPRE_ParCSRPCGSetTol(solver, epsilon);
586 HYPRE_ParCSRPCGSetTwoNorm(solver, 1);
587 HYPRE_ParCSRPCGSetPrintLevel(solver, output_level);
592 void initSolverBiCGStab(
const AlephParams* solver_param, HYPRE_Solver& solver)
594 const String func_name =
"SolverMatrixHypre::initSolverBiCGStab";
595 double epsilon = solver_param->epsilon();
596 int max_it = solver_param->maxIter();
597 int output_level = solver_param->getOutputLevel();
599 HYPRE_ParCSRBiCGSTABCreate(MPI_COMM_SUB, &solver);
600 HYPRE_ParCSRBiCGSTABSetMaxIter(solver, max_it);
601 HYPRE_ParCSRBiCGSTABSetTol(solver, epsilon);
602 HYPRE_ParCSRBiCGSTABSetPrintLevel(solver, output_level);
607 void initSolverGMRES(
const AlephParams* solver_param, HYPRE_Solver& solver)
609 const String func_name =
"SolverMatrixHypre::initSolverGMRES";
610 double epsilon = solver_param->epsilon();
611 int max_it = solver_param->maxIter();
612 int output_level = solver_param->getOutputLevel();
614 HYPRE_ParCSRGMRESCreate(MPI_COMM_SUB, &solver);
615 const int krylov_dim = 20;
616 HYPRE_ParCSRGMRESSetKDim(solver, krylov_dim);
617 HYPRE_ParCSRGMRESSetMaxIter(solver, max_it);
618 HYPRE_ParCSRGMRESSetTol(solver, epsilon);
619 HYPRE_ParCSRGMRESSetPrintLevel(solver, output_level);
624 void setDiagonalPreconditioner(
const TypesSolver::eSolverMethod solver_method,
625 const HYPRE_Solver& solver,
626 HYPRE_Solver& precond)
628 const String func_name =
"SolverMatrixHypre::setDiagonalPreconditioner";
629 switch (solver_method) {
630 case TypesSolver::PCG:
631 HYPRE_ParCSRPCGSetPrecond(solver,
632 HYPRE_ParCSRDiagScale,
633 HYPRE_ParCSRDiagScaleSetup,
636 case TypesSolver::BiCGStab:
637 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
638 HYPRE_ParCSRDiagScale,
639 HYPRE_ParCSRDiagScaleSetup,
642 case TypesSolver::GMRES:
643 HYPRE_ParCSRGMRESSetPrecond(solver,
644 HYPRE_ParCSRDiagScale,
645 HYPRE_ParCSRDiagScaleSetup,
649 throw ArgumentException(func_name,
"solveur inconnu pour le préconditionneur 'Diagonal'");
655 void setILUPreconditioner(
const TypesSolver::eSolverMethod solver_method,
656 const HYPRE_Solver& solver,
657 HYPRE_Solver& precond)
659 const String func_name =
"SolverMatrixHypre::setILUPreconditioner";
660 switch (solver_method) {
661 case TypesSolver::PCG:
662 throw ArgumentException(func_name,
"solveur PCG indisponible avec le préconditionneur 'ILU'");
664 case TypesSolver::BiCGStab:
665 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB, &precond);
666 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
667 HYPRE_ParCSRPilutSolve,
668 HYPRE_ParCSRPilutSetup,
671 case TypesSolver::GMRES:
672 HYPRE_ParCSRPilutCreate(MPI_COMM_SUB,
674 HYPRE_ParCSRGMRESSetPrecond(solver,
675 HYPRE_ParCSRPilutSolve,
676 HYPRE_ParCSRPilutSetup,
680 throw ArgumentException(func_name,
"solveur inconnu pour le préconditionneur ILU\n");
686 void setSpaiStatPreconditioner(
const TypesSolver::eSolverMethod solver_method,
687 const HYPRE_Solver& solver,
689 HYPRE_Solver& precond)
691 HYPRE_ParCSRParaSailsCreate(MPI_COMM_SUB, &precond);
692 double alpha = solver_param->alpha();
693 int gamma = solver_param->gamma();
698 HYPRE_ParCSRParaSailsSetParams(precond, alpha, gamma);
699 switch (solver_method) {
700 case TypesSolver::PCG:
701 HYPRE_ParCSRPCGSetPrecond(solver, HYPRE_ParCSRParaSailsSolve, HYPRE_ParCSRParaSailsSetup, precond);
703 case TypesSolver::BiCGStab:
704 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur 'BiCGStab' invalide pour préconditionnement 'SPAIstat'");
706 case TypesSolver::GMRES:
708 HYPRE_ParCSRParaSailsSetSym(precond, 0);
709 HYPRE_ParCSRGMRESSetPrecond(solver, HYPRE_ParaSailsSolve, HYPRE_ParaSailsSetup, precond);
712 throw ArgumentException(
"AlephMatrixHypre::setSpaiStatPreconditioner",
"solveur inconnu pour le préconditionneur 'SPAIstat'\n");
719 void setAMGPreconditioner(
const TypesSolver::eSolverMethod solver_method,
720 const HYPRE_Solver& solver,
722 HYPRE_Solver& precond)
726 double trunc_factor = 0.1;
727 int cycle_type = solver_param->getAmgCycle();
728 int coarsen_type = solver_param->amgCoarseningMethod();
730 int relax_default = 3;
736 int measure_type = 1;
737 double max_row_sum = 1.0;
740 const int gamma = solver_param->gamma();
744 double strong_threshold = 0.1;
745 const double alpha = solver_param->alpha();
747 strong_threshold = alpha;
749 Integer output_level = solver_param->getOutputLevel();
751 HYPRE_Int* num_grid_sweeps = _allocHypre<HYPRE_Int>(4);
752 HYPRE_Int* grid_relax_type = _allocHypre<HYPRE_Int>(4);
753 HYPRE_Int** grid_relax_points = _allocHypre<HYPRE_Int*>(4);
754 double* relax_weight = _allocHypre<double>(max_levels);
756 for (
int i = 0; i < max_levels; i++)
757 relax_weight[i] = 1.0;
759 if (coarsen_type == 5) {
761 num_grid_sweeps[0] = 3;
762 grid_relax_type[0] = relax_default;
763 grid_relax_points[0] = _allocHypre<HYPRE_Int>(3);
764 grid_relax_points[0][0] = -2;
765 grid_relax_points[0][1] = -1;
766 grid_relax_points[0][2] = 1;
769 num_grid_sweeps[1] = 4;
770 grid_relax_type[1] = relax_default;
771 grid_relax_points[1] = _callocHypre<HYPRE_Int>(4);
772 grid_relax_points[1][0] = -1;
773 grid_relax_points[1][1] = 1;
774 grid_relax_points[1][2] = -2;
775 grid_relax_points[1][3] = -2;
778 num_grid_sweeps[2] = 4;
779 grid_relax_type[2] = relax_default;
780 grid_relax_points[2] = _allocHypre<HYPRE_Int>(4);
781 grid_relax_points[2][0] = -2;
782 grid_relax_points[2][1] = -2;
783 grid_relax_points[2][2] = 1;
784 grid_relax_points[2][3] = -1;
788 num_grid_sweeps[0] = 2 * num_sweep;
789 grid_relax_type[0] = relax_default;
790 grid_relax_points[0] = _allocHypre<HYPRE_Int>(2 * num_sweep);
791 for (
int i = 0; i < 2 * num_sweep; i += 2) {
792 grid_relax_points[0][i] = -1;
793 grid_relax_points[0][i + 1] = 1;
797 num_grid_sweeps[1] = 2 * num_sweep;
798 grid_relax_type[1] = relax_default;
799 grid_relax_points[1] = _allocHypre<HYPRE_Int>(2 * num_sweep);
800 for (
int i = 0; i < 2 * num_sweep; i += 2) {
801 grid_relax_points[1][i] = -1;
802 grid_relax_points[1][i + 1] = 1;
806 num_grid_sweeps[2] = 2 * num_sweep;
807 grid_relax_type[2] = relax_default;
808 grid_relax_points[2] = _allocHypre<HYPRE_Int>(2 * num_sweep);
809 for (
int i = 0; i < 2 * num_sweep; i += 2) {
810 grid_relax_points[2][i] = -1;
811 grid_relax_points[2][i + 1] = 1;
816 num_grid_sweeps[3] = 1;
817 grid_relax_type[3] = 9;
818 grid_relax_points[3] = _allocHypre<HYPRE_Int>(1);
819 grid_relax_points[3][0] = 0;
823 HYPRE_BoomerAMGCreate(&precond);
824 HYPRE_BoomerAMGSetPrintLevel(precond, output_level);
825 HYPRE_BoomerAMGSetCoarsenType(precond, (hybrid * coarsen_type));
826 HYPRE_BoomerAMGSetMeasureType(precond, measure_type);
827 HYPRE_BoomerAMGSetStrongThreshold(precond, strong_threshold);
828 HYPRE_BoomerAMGSetTruncFactor(precond, trunc_factor);
829 HYPRE_BoomerAMGSetMaxIter(precond, 1);
830 HYPRE_BoomerAMGSetCycleType(precond, cycle_type);
831 HYPRE_BoomerAMGSetNumGridSweeps(precond, num_grid_sweeps);
832 HYPRE_BoomerAMGSetGridRelaxType(precond, grid_relax_type);
833 HYPRE_BoomerAMGSetRelaxWeight(precond, relax_weight);
834 HYPRE_BoomerAMGSetGridRelaxPoints(precond, grid_relax_points);
835 HYPRE_BoomerAMGSetTol(precond, 0.0);
836 HYPRE_BoomerAMGSetMaxLevels(precond, max_levels);
837 HYPRE_BoomerAMGSetMaxRowSum(precond, max_row_sum);
839 switch (solver_method) {
840 case TypesSolver::PCG:
841 HYPRE_ParCSRPCGSetPrecond(solver,
842 HYPRE_BoomerAMGSolve,
843 HYPRE_BoomerAMGSetup,
846 case TypesSolver::BiCGStab:
847 HYPRE_ParCSRBiCGSTABSetPrecond(solver,
848 HYPRE_BoomerAMGSolve,
849 HYPRE_BoomerAMGSetup,
852 case TypesSolver::GMRES:
853 HYPRE_ParCSRGMRESSetPrecond(solver,
854 HYPRE_BoomerAMGSolve,
855 HYPRE_BoomerAMGSetup,
859 throw ArgumentException(
"AlephMatrixHypre::setAMGPreconditioner",
"solveur inconnu pour préconditionnement 'AMG'\n");
866 HYPRE_Solver& solver,
867 HYPRE_ParCSRMatrix& M,
870 HYPRE_Int& iteration,
873 const String func_name =
"SolverMatrixHypre::solvePCG";
874 const bool xo = solver_param->xoUser();
878 HYPRE_ParVectorSetConstantValues(X, 0.0);
879 HYPRE_ParCSRPCGSetup(solver, M, B, X);
880 HYPRE_ParCSRPCGSolve(solver, M, B, X);
881 HYPRE_ParCSRPCGGetNumIterations(solver, &iteration);
882 HYPRE_ParCSRPCGGetFinalRelativeResidualNorm(solver, &residue);
884 HYPRE_Int converged = 0;
885 HYPRE_PCGGetConverged(solver, &converged);
886 error |= (!converged);
888 HYPRE_ParCSRPCGDestroy(solver);
895 bool solveBiCGStab(HYPRE_Solver& solver,
896 HYPRE_ParCSRMatrix& M,
899 HYPRE_Int& iteration,
902 const String func_name =
"SolverMatrixHypre::solveBiCGStab";
904 HYPRE_ParVectorSetRandomValues(X, 775);
905 HYPRE_ParCSRBiCGSTABSetup(solver, M, B, X);
906 HYPRE_ParCSRBiCGSTABSolve(solver, M, B, X);
907 HYPRE_ParCSRBiCGSTABGetNumIterations(solver, &iteration);
908 HYPRE_ParCSRBiCGSTABGetFinalRelativeResidualNorm(solver, &residue);
910 HYPRE_Int converged = 0;
911 hypre_BiCGSTABGetConverged(solver, &converged);
912 error |= (!converged);
914 HYPRE_ParCSRBiCGSTABDestroy(solver);
921 bool solveGMRES(HYPRE_Solver& solver,
922 HYPRE_ParCSRMatrix& M,
925 HYPRE_Int& iteration,
928 const String func_name =
"SolverMatrixHypre::solveGMRES";
930 HYPRE_ParCSRGMRESSetup(solver, M, B, X);
931 HYPRE_ParCSRGMRESSolve(solver, M, B, X);
932 HYPRE_ParCSRGMRESGetNumIterations(solver, &iteration);
933 HYPRE_ParCSRGMRESGetFinalRelativeResidualNorm(solver, &residue);
935 HYPRE_Int converged = 0;
936 HYPRE_GMRESGetConverged(solver, &converged);
937 error |= (!converged);
939 HYPRE_ParCSRGMRESDestroy(solver);
945 HYPRE_IJMatrix m_hypre_ijmatrix =
nullptr;
946 HYPRE_ParCSRMatrix m_hypre_parmatrix =
nullptr;