48#include "HYPRE_krylov.h"
50#include "HYPRE_parcsr_ls.h"
63#ifndef HYPRE_EXAMPLES_INCLUDES
64#define HYPRE_EXAMPLES_INCLUDES
66#include <HYPRE_config.h>
68#if defined(HYPRE_EXAMPLE_USING_CUDA)
70#include <cuda_runtime.h>
72#ifndef HYPRE_USING_UNIFIED_MEMORY
73#error *** Running the examples on GPUs requires Unified Memory. Please reconfigure and rebuild with --enable-unified-memory ***
77gpu_malloc(
size_t size)
80 cudaMallocManaged(&ptr, size, cudaMemAttachGlobal);
85gpu_calloc(
size_t num,
size_t size)
88 cudaMallocManaged(&ptr, num * size, cudaMemAttachGlobal);
89 cudaMemset(ptr, 0, num * size);
93#define malloc(size) gpu_malloc(size)
94#define calloc(num, size) gpu_calloc(num, size)
95#define free(ptr) ( cudaFree(ptr), ptr = NULL )
107#include "arcane/utils/Convert.h"
108#include "arcane/utils/FatalErrorException.h"
109#include "arccore/alina/Profiler.h"
113int hypre_FlexGMRESModifyPCAMGExample(
void *precond_data,
int iterations,
114 double rel_residual_norm);
116#define my_min(a,b) (((a)<(b)) ? (a) : (b))
119_doHypreSolver(
int nb_row,
120 std::vector<ptrdiff_t>
const& _ptr,
121 std::vector<ptrdiff_t>
const& _col,
122 std::vector<double>
const& _val,
123 std::vector<double>
const& _rhs,
124 std::vector<double>& _x,
125 int argc,
char* argv[])
127 auto& prof = Alina::Profiler::globalProfiler();
128 auto t = prof.scoped_tic(
"Hypre");
130 std::cout <<
"DO_HYPRE nb_row=" << nb_row <<
"\n";
133 const int N = nb_row;
136 int local_size, extra;
139 int vis, print_system;
144 HYPRE_ParCSRMatrix parcsr_A;
146 HYPRE_ParVector par_b;
148 HYPRE_ParVector par_x;
150 HYPRE_Solver solver, precond;
153 MPI_Init(&argc, &argv);
154 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
155 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
162#if defined(HYPRE_USING_GPU)
164 HYPRE_SetSpGemmUseVendor(0);
168 const int n = nb_row;
178 while (arg_index < argc) {
179 if (strcmp(argv[arg_index],
"-n") == 0) {
183 else if (strcmp(argv[arg_index],
"-solver") == 0) {
185 solver_id = atoi(argv[arg_index++]);
187 else if (strcmp(argv[arg_index],
"-vis") == 0) {
191 else if (strcmp(argv[arg_index],
"-print_system") == 0) {
195 else if (strcmp(argv[arg_index],
"-help") == 0) {
204 if ((print_usage) && (myid == 0)) {
206 printf(
"Usage: %s [<options>]\n", argv[0]);
208 printf(
" -n <n> : problem size in each direction (default: 33)\n");
209 printf(
" -solver <ID> : solver ID\n");
210 printf(
" 0 - AMG (default) \n");
211 printf(
" 1 - AMG-PCG\n");
212 printf(
" 8 - ParaSails-PCG\n");
213 printf(
" 50 - PCG\n");
214 printf(
" 61 - AMG-FlexGMRES\n");
215 printf(
" -vis : save the solution for GLVis visualization\n");
216 printf(
" -print_system : print the matrix and rhs\n");
227 std::vector<int> nb_value_per_row(n);
228 for (
int i = 0; i < n; ++i)
229 nb_value_per_row[i] =
static_cast<HYPRE_BigInt
>(_ptr[i + 1] - _ptr[i]);
233 std::vector<HYPRE_BigInt> hypre_column_index(_col.begin(), _col.end());
236 std::vector<HYPRE_Int> hypre_row_index(n);
237 for (
int i = 0; i < n; ++i) {
238 hypre_row_index[i] = i;
244 local_size = N / num_procs;
245 extra = N - local_size * num_procs;
247 ilower = local_size * myid;
248 ilower += my_min(myid, extra);
250 iupper = local_size * (myid + 1);
251 iupper += my_min(myid + 1, extra);
253 std::cout <<
"LOWER=" << ilower <<
" UPPER=" << iupper <<
"\n";
255 local_size = iupper - ilower + 1;
258 auto t = prof.scoped_tic(
"IJMatrix Create");
262 HYPRE_IJMatrixCreate(MPI_COMM_WORLD, ilower, iupper, ilower, iupper, &A);
265 HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
268 HYPRE_IJMatrixInitialize(A);
273 auto t = prof.scoped_tic(
"IJMatrix SetValues");
275 HYPRE_IJMatrixSetValues(A, n,
276 nb_value_per_row.data(),
277 hypre_row_index.data(),
278 hypre_column_index.data(),
283 auto t = prof.scoped_tic(
"IJMatrix Assemble");
285 HYPRE_IJMatrixAssemble(A);
302 HYPRE_IJMatrixGetObject(A, (
void**)&parcsr_A);
305 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper, &b);
306 HYPRE_IJVectorSetObjectType(b, HYPRE_PARCSR);
307 HYPRE_IJVectorInitialize(b);
309 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper, &x);
310 HYPRE_IJVectorSetObjectType(x, HYPRE_PARCSR);
311 HYPRE_IJVectorInitialize(x);
320 rows = (
int*)calloc(local_size,
sizeof(
int));
322 for (i = 0; i < local_size; i++) {
325 rows[i] = ilower + i;
328 HYPRE_IJVectorSetValues(b, local_size, rows, _rhs.data());
329 HYPRE_IJVectorSetValues(x, local_size, rows, _x.data());
336 HYPRE_IJVectorAssemble(b);
344 HYPRE_IJVectorGetObject(b, (
void**)&par_b);
346 HYPRE_IJVectorAssemble(x);
347 HYPRE_IJVectorGetObject(x, (
void**)&par_x);
352 HYPRE_IJMatrixPrint(A,
"IJ.out.A");
353 HYPRE_IJVectorPrint(b,
"IJ.out.b");
357 solver_id = v.value();
359 double solver_tolerance = 1.0e-8;
362 std::cout <<
"FINISH ASSEMBLING solver_id=" << solver_id <<
"\n";
364 if (solver_id == 0) {
365 auto t = prof.scoped_tic(
"HypreSolver AMG");
367 double final_res_norm;
370 HYPRE_BoomerAMGCreate(&solver);
373 HYPRE_BoomerAMGSetPrintLevel(solver, 3);
374 HYPRE_BoomerAMGSetOldDefault(solver);
375 HYPRE_BoomerAMGSetRelaxType(solver, 3);
376 HYPRE_BoomerAMGSetRelaxOrder(solver, 1);
377 HYPRE_BoomerAMGSetNumSweeps(solver, 1);
378 HYPRE_BoomerAMGSetMaxLevels(solver, 20);
379 HYPRE_BoomerAMGSetTol(solver, solver_tolerance);
383 auto t = prof.scoped_tic(
"AMG Setup");
384 HYPRE_BoomerAMGSetup(solver, parcsr_A, par_b, par_x);
387 auto t = prof.scoped_tic(
"AMG Solve");
388 HYPRE_BoomerAMGSolve(solver, parcsr_A, par_b, par_x);
392 HYPRE_BoomerAMGGetNumIterations(solver, &num_iterations);
393 HYPRE_BoomerAMGGetFinalRelativeResidualNorm(solver, &final_res_norm);
396 printf(
"Iterations = %d\n", num_iterations);
397 printf(
"Final Relative Residual Norm = %e\n", final_res_norm);
402 HYPRE_BoomerAMGDestroy(solver);
405 else if (solver_id == 50) {
406 auto t = prof.scoped_tic(
"HypreSolver PCG");
408 double final_res_norm;
411 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
414 HYPRE_PCGSetMaxIter(solver, 1000);
415 HYPRE_PCGSetTol(solver, solver_tolerance);
416 HYPRE_PCGSetTwoNorm(solver, 1);
417 HYPRE_PCGSetPrintLevel(solver, 2);
418 HYPRE_PCGSetLogging(solver, 1);
421 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
422 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
425 HYPRE_PCGGetNumIterations(solver, &num_iterations);
426 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
429 printf(
"Iterations = %d\n", num_iterations);
430 printf(
"Final Relative Residual Norm = %e\n", final_res_norm);
435 HYPRE_ParCSRPCGDestroy(solver);
438 else if (solver_id == 1) {
439 auto t = prof.scoped_tic(
"HypreSolver PCG-AMG");
441 double final_res_norm;
444 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
447 HYPRE_PCGSetMaxIter(solver, 1000);
448 HYPRE_PCGSetTol(solver, solver_tolerance);
449 HYPRE_PCGSetTwoNorm(solver, 1);
450 HYPRE_PCGSetPrintLevel(solver, 2);
451 HYPRE_PCGSetLogging(solver, 1);
454 HYPRE_BoomerAMGCreate(&precond);
455 HYPRE_BoomerAMGSetPrintLevel(precond, 1);
456 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
457 HYPRE_BoomerAMGSetOldDefault(precond);
458 HYPRE_BoomerAMGSetRelaxType(precond, 6);
459 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
460 HYPRE_BoomerAMGSetTol(precond, 0.0);
461 HYPRE_BoomerAMGSetMaxIter(precond, 1);
464 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
465 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
469 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
472 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
476 HYPRE_PCGGetNumIterations(solver, &num_iterations);
477 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
480 printf(
"Iterations = %d\n", num_iterations);
481 printf(
"Final Relative Residual Norm = %e\n", final_res_norm);
486 HYPRE_ParCSRPCGDestroy(solver);
487 HYPRE_BoomerAMGDestroy(precond);
490 else if (solver_id == 8) {
491 auto t = prof.scoped_tic(
"HypreSolver PCG - Parasails");
493 double final_res_norm;
495 int sai_max_levels = 1;
496 double sai_threshold = 0.1;
497 double sai_filter = 0.05;
501 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
504 HYPRE_PCGSetMaxIter(solver, 1000);
505 HYPRE_PCGSetTol(solver, solver_tolerance);
506 HYPRE_PCGSetTwoNorm(solver, 1);
507 HYPRE_PCGSetPrintLevel(solver, 2);
508 HYPRE_PCGSetLogging(solver, 1);
511 HYPRE_ParaSailsCreate(MPI_COMM_WORLD, &precond);
514 HYPRE_ParaSailsSetParams(precond, sai_threshold, sai_max_levels);
515 HYPRE_ParaSailsSetFilter(precond, sai_filter);
516 HYPRE_ParaSailsSetSym(precond, sai_sym);
517 HYPRE_ParaSailsSetLogging(precond, 3);
520 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSolve,
521 (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSetup, precond);
524 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
525 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
528 HYPRE_PCGGetNumIterations(solver, &num_iterations);
529 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
532 printf(
"Iterations = %d\n", num_iterations);
533 printf(
"Final Relative Residual Norm = %e\n", final_res_norm);
538 HYPRE_ParCSRPCGDestroy(solver);
539 HYPRE_ParaSailsDestroy(precond);
542 else if (solver_id == 61) {
543 auto t = prof.scoped_tic(
"HypreSolver Flexible GMRES - AMG");
545 double final_res_norm;
550 HYPRE_ParCSRFlexGMRESCreate(MPI_COMM_WORLD, &solver);
553 HYPRE_FlexGMRESSetKDim(solver, restart);
554 HYPRE_FlexGMRESSetMaxIter(solver, 1000);
555 HYPRE_FlexGMRESSetTol(solver, solver_tolerance);
556 HYPRE_FlexGMRESSetPrintLevel(solver, 2);
557 HYPRE_FlexGMRESSetLogging(solver, 1);
560 HYPRE_BoomerAMGCreate(&precond);
561 HYPRE_BoomerAMGSetPrintLevel(precond, 1);
562 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
563 HYPRE_BoomerAMGSetOldDefault(precond);
564 HYPRE_BoomerAMGSetRelaxType(precond, 6);
565 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
566 HYPRE_BoomerAMGSetTol(precond, 0.0);
567 HYPRE_BoomerAMGSetMaxIter(precond, 1);
570 HYPRE_FlexGMRESSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
571 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
577 HYPRE_FlexGMRESSetModifyPC(solver, (HYPRE_PtrToModifyPCFcn)hypre_FlexGMRESModifyPCAMGExample);
582 auto t = prof.scoped_tic(
"FlexGMRES Setup");
583 HYPRE_ParCSRFlexGMRESSetup(solver, parcsr_A, par_b, par_x);
586 auto t = prof.scoped_tic(
"FlexGMRES Solve");
587 HYPRE_ParCSRFlexGMRESSolve(solver, parcsr_A, par_b, par_x);
591 HYPRE_FlexGMRESGetNumIterations(solver, &num_iterations);
592 HYPRE_FlexGMRESGetFinalRelativeResidualNorm(solver, &final_res_norm);
595 printf(
"Iterations = %d\n", num_iterations);
596 printf(
"Final Relative Residual Norm = %e\n", final_res_norm);
601 HYPRE_ParCSRFlexGMRESDestroy(solver);
602 HYPRE_BoomerAMGDestroy(precond);
606 ARCANE_FATAL(
"Invalid solver id '{0}' specified.", solver_id);
611 HYPRE_IJVectorPrint(x,
"IJ.out.x");
619 int nvalues = local_size;
620 int* rows = (
int*)calloc(nvalues,
sizeof(
int));
621 double* values = (
double*)calloc(nvalues,
sizeof(
double));
623 for (i = 0; i < nvalues; i++) {
624 rows[i] = ilower + i;
628 HYPRE_IJVectorGetValues(x, nvalues, rows, values);
630 sprintf(filename,
"%s.%06d",
"vis/ex5.sol", myid);
631 if ((file = fopen(filename,
"w")) == NULL) {
632 printf(
"Error: can't open output file %s\n", filename);
638 for (i = 0; i < nvalues; i++) {
639 fprintf(file,
"%.14e\n", values[i]);
650 GLVis_PrintGlobalSquareMesh(
"vis/ex5.mesh", n - 1);
656 HYPRE_IJMatrixDestroy(A);
657 HYPRE_IJVectorDestroy(b);
658 HYPRE_IJVectorDestroy(x);
678int hypre_FlexGMRESModifyPCAMGExample(
void* precond_data, [[maybe_unused]]
int iterations,
679 double rel_residual_norm)
682 if (rel_residual_norm > .1) {
683 HYPRE_BoomerAMGSetNumSweeps((HYPRE_Solver)precond_data, 10);
686 HYPRE_BoomerAMGSetNumSweeps((HYPRE_Solver)precond_data, 1);
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classe template pour convertir un type.
-*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-