Arcane  v4.1.10.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
HypreComparer.cc
1// -*- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature -*-
2//-----------------------------------------------------------------------------
3// Copyright 2000-2026 CEA (www.cea.fr) IFPEN (www.ifpenergiesnouvelles.com)
4// See the top-level COPYRIGHT file for details.
5// SPDX-License-Identifier: Apache-2.0
6//-----------------------------------------------------------------------------
7/*---------------------------------------------------------------------------*/
8/*---------------------------------------------------------------------------*/
9/*
10 * This file is based on the work on AMGCL library (version march 2026)
11 * which can be found at https://github.com/ddemidov/amgcl.
12 *
13 * Copyright (c) 2012-2022 Denis Demidov <dennis.demidov@gmail.com>
14 * SPDX-License-Identifier: MIT
15 */
16/*---------------------------------------------------------------------------*/
17/*---------------------------------------------------------------------------*/
18
19/******************************************************************************
20 * Copyright (c) 1998 Lawrence Livermore National Security, LLC and other
21 * HYPRE Project Developers. See the top-level COPYRIGHT file for details.
22 *
23 * SPDX-License-Identifier: (Apache-2.0 OR MIT)
24 ******************************************************************************/
25
26/*
27 Example 5
28
29 Interface: Linear-Algebraic (IJ)
30
31 Compile with: make ex5
32
33 Sample run: mpirun -np 4 ex5
34
35 Description: This example solves the 2-D Laplacian problem with zero boundary
36 conditions on an n x n grid. The number of unknowns is N=n^2.
37 The standard 5-point stencil is used, and we solve for the
38 interior nodes only.
39
40 This example solves the same problem as Example 3. Available
41 solvers are AMG, PCG, and PCG with AMG or Parasails
42 preconditioners. */
43
44#include <stdio.h>
45#include <stdlib.h>
46#include <string.h>
47#include <math.h>
48#include "HYPRE_krylov.h"
49#include "HYPRE.h"
50#include "HYPRE_parcsr_ls.h"
51
52/******************************************************************************
53 * Copyright (c) 1998 Lawrence Livermore National Security, LLC and other
54 * HYPRE Project Developers. See the top-level COPYRIGHT file for details.
55 *
56 * SPDX-License-Identifier: (Apache-2.0 OR MIT)
57 ******************************************************************************/
58
59/*--------------------------------------------------------------------------
60 * Header file for examples
61 *--------------------------------------------------------------------------*/
62
63#ifndef HYPRE_EXAMPLES_INCLUDES
64#define HYPRE_EXAMPLES_INCLUDES
65
66#include <HYPRE_config.h>
67
68#if defined(HYPRE_EXAMPLE_USING_CUDA)
69
70#include <cuda_runtime.h>
71
72#ifndef HYPRE_USING_UNIFIED_MEMORY
73#error *** Running the examples on GPUs requires Unified Memory. Please reconfigure and rebuild with --enable-unified-memory ***
74#endif
75
76static inline void*
77gpu_malloc(size_t size)
78{
79 void *ptr = NULL;
80 cudaMallocManaged(&ptr, size, cudaMemAttachGlobal);
81 return ptr;
82}
83
84static inline void*
85gpu_calloc(size_t num, size_t size)
86{
87 void *ptr = NULL;
88 cudaMallocManaged(&ptr, num * size, cudaMemAttachGlobal);
89 cudaMemset(ptr, 0, num * size);
90 return ptr;
91}
92
93#define malloc(size) gpu_malloc(size)
94#define calloc(num, size) gpu_calloc(num, size)
95#define free(ptr) ( cudaFree(ptr), ptr = NULL )
96#endif /* #if defined(HYPRE_EXAMPLE_USING_CUDA) */
97#endif /* #ifndef HYPRE_EXAMPLES_INCLUDES */
98
99#ifdef HYPRE_EXVIS
100#include "vis.c"
101#endif
102
103#include <memory>
104#include <vector>
105#include <iostream>
106
107#include "arcane/utils/Convert.h"
108#include "arcane/utils/FatalErrorException.h"
109#include "arccore/alina/Profiler.h"
110
111using namespace Arcane;
112
113int hypre_FlexGMRESModifyPCAMGExample(void *precond_data, int iterations,
114 double rel_residual_norm);
115
116#define my_min(a,b) (((a)<(b)) ? (a) : (b))
117
118extern "C++" void
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[])
126{
127 auto& prof = Alina::Profiler::globalProfiler();
128 auto t = prof.scoped_tic("Hypre");
129
130 std::cout << "DO_HYPRE nb_row=" << nb_row << "\n";
131 int i;
132 int myid, num_procs;
133 const int N = nb_row;
134
135 int ilower, iupper;
136 int local_size, extra;
137
138 int solver_id;
139 int vis, print_system;
140
141 //double h, h2;
142
143 HYPRE_IJMatrix A;
144 HYPRE_ParCSRMatrix parcsr_A;
145 HYPRE_IJVector b;
146 HYPRE_ParVector par_b;
147 HYPRE_IJVector x;
148 HYPRE_ParVector par_x;
149
150 HYPRE_Solver solver, precond;
151
152 /* Initialize MPI */
153 MPI_Init(&argc, &argv);
154 MPI_Comm_rank(MPI_COMM_WORLD, &myid);
155 MPI_Comm_size(MPI_COMM_WORLD, &num_procs);
156
157 /* Initialize HYPRE */
158 HYPRE_Initialize();
159
160 /* Print GPU info */
161 /* HYPRE_PrintDeviceInfo(); */
162#if defined(HYPRE_USING_GPU)
163 /* use vendor implementation for SpGEMM */
164 HYPRE_SetSpGemmUseVendor(0);
165#endif
166
167 /* Default problem parameters */
168 const int n = nb_row;
169 solver_id = 0;
170 vis = 0;
171 print_system = 0;
172
173 /* Parse command line */
174 {
175 int arg_index = 0;
176 int print_usage = 0;
177
178 while (arg_index < argc) {
179 if (strcmp(argv[arg_index], "-n") == 0) {
180 arg_index++;
181 //n = atoi(argv[arg_index++]);
182 }
183 else if (strcmp(argv[arg_index], "-solver") == 0) {
184 arg_index++;
185 solver_id = atoi(argv[arg_index++]);
186 }
187 else if (strcmp(argv[arg_index], "-vis") == 0) {
188 arg_index++;
189 vis = 1;
190 }
191 else if (strcmp(argv[arg_index], "-print_system") == 0) {
192 arg_index++;
193 print_system = 1;
194 }
195 else if (strcmp(argv[arg_index], "-help") == 0) {
196 print_usage = 1;
197 break;
198 }
199 else {
200 arg_index++;
201 }
202 }
203
204 if ((print_usage) && (myid == 0)) {
205 printf("\n");
206 printf("Usage: %s [<options>]\n", argv[0]);
207 printf("\n");
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");
217 printf("\n");
218 }
219
220 if (print_usage) {
221 MPI_Finalize();
222 return;
223 }
224 }
225
226 // Fill nb value per row.
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]);
230
231 // The column index is the same that '_col' from CSR Matrix
232 // but we do a copy if index size is différent between Hypre and Alina.
233 std::vector<HYPRE_BigInt> hypre_column_index(_col.begin(), _col.end());
234
235 // Id of each row (in sequential, this is the same that the index)
236 std::vector<HYPRE_Int> hypre_row_index(n);
237 for (int i = 0; i < n; ++i) {
238 hypre_row_index[i] = i;
239 }
240
241 /* Each processor knows only of its own rows - the range is denoted by ilower
242 and upper. Here we partition the rows. We account for the fact that
243 N may not divide evenly by the number of processors. */
244 local_size = N / num_procs;
245 extra = N - local_size * num_procs;
246
247 ilower = local_size * myid;
248 ilower += my_min(myid, extra);
249
250 iupper = local_size * (myid + 1);
251 iupper += my_min(myid + 1, extra);
252 iupper = iupper - 1;
253 std::cout << "LOWER=" << ilower << " UPPER=" << iupper << "\n";
254 /* How many rows do I have? */
255 local_size = iupper - ilower + 1;
256
257 {
258 auto t = prof.scoped_tic("IJMatrix Create");
259 /* Create the matrix.
260 Note that this is a square matrix, so we indicate the row partition
261 size twice (since number of rows = number of cols) */
262 HYPRE_IJMatrixCreate(MPI_COMM_WORLD, ilower, iupper, ilower, iupper, &A);
263
264 /* Choose a parallel csr format storage (see the User's Manual) */
265 HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
266
267 /* Initialize before setting coefficients */
268 HYPRE_IJMatrixInitialize(A);
269 }
270
271 // Fill the matrix.
272 {
273 auto t = prof.scoped_tic("IJMatrix SetValues");
274
275 HYPRE_IJMatrixSetValues(A, n,
276 nb_value_per_row.data(),
277 hypre_row_index.data(),
278 hypre_column_index.data(),
279 _val.data());
280 }
281
282 {
283 auto t = prof.scoped_tic("IJMatrix Assemble");
284 /* Assemble after setting the coefficients */
285 HYPRE_IJMatrixAssemble(A);
286 }
287
288 /* Note: for the testing of small problems, one may wish to read
289 in a matrix in IJ format (for the format, see the output files
290 from the -print_system option).
291 In this case, one would use the following routine:
292 HYPRE_IJMatrixRead( <filename>, MPI_COMM_WORLD,
293 HYPRE_PARCSR, &A );
294 <filename> = IJ.A.out to read in what has been printed out
295 by -print_system (processor numbers are omitted).
296 A call to HYPRE_IJMatrixRead is an *alternative* to the
297 following sequence of HYPRE_IJMatrix calls:
298 Create, SetObjectType, Initialize, SetValues, and Assemble
299 */
300
301 /* Get the parcsr matrix object to use */
302 HYPRE_IJMatrixGetObject(A, (void**)&parcsr_A);
303
304 /* Create the rhs and solution */
305 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper, &b);
306 HYPRE_IJVectorSetObjectType(b, HYPRE_PARCSR);
307 HYPRE_IJVectorInitialize(b);
308
309 HYPRE_IJVectorCreate(MPI_COMM_WORLD, ilower, iupper, &x);
310 HYPRE_IJVectorSetObjectType(x, HYPRE_PARCSR);
311 HYPRE_IJVectorInitialize(x);
312
313 /* Set the rhs values to h^2 and the solution to zero */
314 {
315 //double *rhs_values, *x_values;
316 int* rows;
317
318 //rhs_values = (double*)calloc(local_size, sizeof(double));
319 //x_values = (double*)calloc(local_size, sizeof(double));
320 rows = (int*)calloc(local_size, sizeof(int));
321
322 for (i = 0; i < local_size; i++) {
323 //rhs_values[i] = h2;
324 //x_values[i] = 0.0;
325 rows[i] = ilower + i;
326 }
327
328 HYPRE_IJVectorSetValues(b, local_size, rows, _rhs.data());
329 HYPRE_IJVectorSetValues(x, local_size, rows, _x.data());
330
331 //free(x_values);
332 //free(rhs_values);
333 free(rows);
334 }
335
336 HYPRE_IJVectorAssemble(b);
337 /* As with the matrix, for testing purposes, one may wish to read in a rhs:
338 HYPRE_IJVectorRead( <filename>, MPI_COMM_WORLD,
339 HYPRE_PARCSR, &b );
340 as an alternative to the
341 following sequence of HYPRE_IJVectors calls:
342 Create, SetObjectType, Initialize, SetValues, and Assemble
343 */
344 HYPRE_IJVectorGetObject(b, (void**)&par_b);
345
346 HYPRE_IJVectorAssemble(x);
347 HYPRE_IJVectorGetObject(x, (void**)&par_x);
348
349 /* Print out the system - files names will be IJ.out.A.XXXXX
350 and IJ.out.b.XXXXX, where XXXXX = processor id */
351 if (print_system) {
352 HYPRE_IJMatrixPrint(A, "IJ.out.A");
353 HYPRE_IJVectorPrint(b, "IJ.out.b");
354 }
355 solver_id = 0;
356 if (auto v = Convert::Type<Int32>::tryParseFromEnvironment("ALINA_HYPRE_SOLVER", true))
357 solver_id = v.value();
358
359 double solver_tolerance = 1.0e-8;
360
361 /* Choose a solver and solve the system */
362 std::cout << "FINISH ASSEMBLING solver_id=" << solver_id << "\n";
363 /* AMG */
364 if (solver_id == 0) {
365 auto t = prof.scoped_tic("HypreSolver AMG");
366 int num_iterations;
367 double final_res_norm;
368
369 /* Create solver */
370 HYPRE_BoomerAMGCreate(&solver);
371
372 /* Set some parameters (See Reference Manual for more parameters) */
373 HYPRE_BoomerAMGSetPrintLevel(solver, 3); /* print solve info + parameters */
374 HYPRE_BoomerAMGSetOldDefault(solver); /* Falgout coarsening with modified classical interpolaiton */
375 HYPRE_BoomerAMGSetRelaxType(solver, 3); /* G-S/Jacobi hybrid relaxation */
376 HYPRE_BoomerAMGSetRelaxOrder(solver, 1); /* uses C/F relaxation */
377 HYPRE_BoomerAMGSetNumSweeps(solver, 1); /* Sweeeps on each level */
378 HYPRE_BoomerAMGSetMaxLevels(solver, 20); /* maximum number of levels */
379 HYPRE_BoomerAMGSetTol(solver, solver_tolerance); /* conv. tolerance */
380
381 /* Now setup and solve! */
382 {
383 auto t = prof.scoped_tic("AMG Setup");
384 HYPRE_BoomerAMGSetup(solver, parcsr_A, par_b, par_x);
385 }
386 {
387 auto t = prof.scoped_tic("AMG Solve");
388 HYPRE_BoomerAMGSolve(solver, parcsr_A, par_b, par_x);
389 }
390
391 /* Run info - needed logging turned on */
392 HYPRE_BoomerAMGGetNumIterations(solver, &num_iterations);
393 HYPRE_BoomerAMGGetFinalRelativeResidualNorm(solver, &final_res_norm);
394 if (myid == 0) {
395 printf("\n");
396 printf("Iterations = %d\n", num_iterations);
397 printf("Final Relative Residual Norm = %e\n", final_res_norm);
398 printf("\n");
399 }
400
401 /* Destroy solver */
402 HYPRE_BoomerAMGDestroy(solver);
403 }
404 /* PCG */
405 else if (solver_id == 50) {
406 auto t = prof.scoped_tic("HypreSolver PCG");
407 int num_iterations;
408 double final_res_norm;
409
410 /* Create solver */
411 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
412
413 /* Set some parameters (See Reference Manual for more parameters) */
414 HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
415 HYPRE_PCGSetTol(solver, solver_tolerance); /* conv. tolerance */
416 HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
417 HYPRE_PCGSetPrintLevel(solver, 2); /* prints out the iteration info */
418 HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
419
420 /* Now setup and solve! */
421 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
422 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
423
424 /* Run info - needed logging turned on */
425 HYPRE_PCGGetNumIterations(solver, &num_iterations);
426 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
427 if (myid == 0) {
428 printf("\n");
429 printf("Iterations = %d\n", num_iterations);
430 printf("Final Relative Residual Norm = %e\n", final_res_norm);
431 printf("\n");
432 }
433
434 /* Destroy solver */
435 HYPRE_ParCSRPCGDestroy(solver);
436 }
437 /* PCG with AMG preconditioner */
438 else if (solver_id == 1) {
439 auto t = prof.scoped_tic("HypreSolver PCG-AMG");
440 int num_iterations;
441 double final_res_norm;
442
443 /* Create solver */
444 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
445
446 /* Set some parameters (See Reference Manual for more parameters) */
447 HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
448 HYPRE_PCGSetTol(solver, solver_tolerance); /* conv. tolerance */
449 HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
450 HYPRE_PCGSetPrintLevel(solver, 2); /* print solve info */
451 HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
452
453 /* Now set up the AMG preconditioner and specify any parameters */
454 HYPRE_BoomerAMGCreate(&precond);
455 HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* print amg solution info */
456 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
457 HYPRE_BoomerAMGSetOldDefault(precond);
458 HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Sym G.S./Jacobi hybrid */
459 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
460 HYPRE_BoomerAMGSetTol(precond, 0.0); /* conv. tolerance zero */
461 HYPRE_BoomerAMGSetMaxIter(precond, 1); /* do only one iteration! */
462
463 /* Set the PCG preconditioner */
464 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
465 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
466
467 /* Now setup and solve! */
468 prof.tic("Setup");
469 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
470 prof.toc("Setup");
471 prof.tic("Solve");
472 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
473 prof.toc("Solve");
474
475 /* Run info - needed logging turned on */
476 HYPRE_PCGGetNumIterations(solver, &num_iterations);
477 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
478 if (myid == 0) {
479 printf("\n");
480 printf("Iterations = %d\n", num_iterations);
481 printf("Final Relative Residual Norm = %e\n", final_res_norm);
482 printf("\n");
483 }
484
485 /* Destroy solver and preconditioner */
486 HYPRE_ParCSRPCGDestroy(solver);
487 HYPRE_BoomerAMGDestroy(precond);
488 }
489 /* PCG with Parasails Preconditioner */
490 else if (solver_id == 8) {
491 auto t = prof.scoped_tic("HypreSolver PCG - Parasails");
492 int num_iterations;
493 double final_res_norm;
494
495 int sai_max_levels = 1;
496 double sai_threshold = 0.1;
497 double sai_filter = 0.05;
498 int sai_sym = 1;
499
500 /* Create solver */
501 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
502
503 /* Set some parameters (See Reference Manual for more parameters) */
504 HYPRE_PCGSetMaxIter(solver, 1000); /* max iterations */
505 HYPRE_PCGSetTol(solver, solver_tolerance); /* conv. tolerance */
506 HYPRE_PCGSetTwoNorm(solver, 1); /* use the two norm as the stopping criteria */
507 HYPRE_PCGSetPrintLevel(solver, 2); /* print solve info */
508 HYPRE_PCGSetLogging(solver, 1); /* needed to get run info later */
509
510 /* Now set up the ParaSails preconditioner and specify any parameters */
511 HYPRE_ParaSailsCreate(MPI_COMM_WORLD, &precond);
512
513 /* Set some parameters (See Reference Manual for more parameters) */
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);
518
519 /* Set the PCG preconditioner */
520 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSolve,
521 (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSetup, precond);
522
523 /* Now setup and solve! */
524 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
525 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
526
527 /* Run info - needed logging turned on */
528 HYPRE_PCGGetNumIterations(solver, &num_iterations);
529 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
530 if (myid == 0) {
531 printf("\n");
532 printf("Iterations = %d\n", num_iterations);
533 printf("Final Relative Residual Norm = %e\n", final_res_norm);
534 printf("\n");
535 }
536
537 /* Destory solver and preconditioner */
538 HYPRE_ParCSRPCGDestroy(solver);
539 HYPRE_ParaSailsDestroy(precond);
540 }
541 /* Flexible GMRES with AMG Preconditioner */
542 else if (solver_id == 61) {
543 auto t = prof.scoped_tic("HypreSolver Flexible GMRES - AMG");
544 int num_iterations;
545 double final_res_norm;
546 int restart = 30;
547 int modify = 1;
548
549 /* Create solver */
550 HYPRE_ParCSRFlexGMRESCreate(MPI_COMM_WORLD, &solver);
551
552 /* Set some parameters (See Reference Manual for more parameters) */
553 HYPRE_FlexGMRESSetKDim(solver, restart);
554 HYPRE_FlexGMRESSetMaxIter(solver, 1000); /* max iterations */
555 HYPRE_FlexGMRESSetTol(solver, solver_tolerance); /* conv. tolerance */
556 HYPRE_FlexGMRESSetPrintLevel(solver, 2); /* print solve info */
557 HYPRE_FlexGMRESSetLogging(solver, 1); /* needed to get run info later */
558
559 /* Now set up the AMG preconditioner and specify any parameters */
560 HYPRE_BoomerAMGCreate(&precond);
561 HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* print amg solution info */
562 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
563 HYPRE_BoomerAMGSetOldDefault(precond);
564 HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Sym G.S./Jacobi hybrid */
565 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
566 HYPRE_BoomerAMGSetTol(precond, 0.0); /* conv. tolerance zero */
567 HYPRE_BoomerAMGSetMaxIter(precond, 1); /* do only one iteration! */
568
569 /* Set the FlexGMRES preconditioner */
570 HYPRE_FlexGMRESSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
571 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
572
573 if (modify) {
574 /* this is an optional call - if you don't call it, hypre_FlexGMRESModifyPCDefault
575 is used - which does nothing. Otherwise, you can define your own, similar to
576 the one used here */
577 HYPRE_FlexGMRESSetModifyPC(solver, (HYPRE_PtrToModifyPCFcn)hypre_FlexGMRESModifyPCAMGExample);
578 }
579
580 /* Now setup and solve! */
581 {
582 auto t = prof.scoped_tic("FlexGMRES Setup");
583 HYPRE_ParCSRFlexGMRESSetup(solver, parcsr_A, par_b, par_x);
584 }
585 {
586 auto t = prof.scoped_tic("FlexGMRES Solve");
587 HYPRE_ParCSRFlexGMRESSolve(solver, parcsr_A, par_b, par_x);
588 }
589
590 /* Run info - needed logging turned on */
591 HYPRE_FlexGMRESGetNumIterations(solver, &num_iterations);
592 HYPRE_FlexGMRESGetFinalRelativeResidualNorm(solver, &final_res_norm);
593 if (myid == 0) {
594 printf("\n");
595 printf("Iterations = %d\n", num_iterations);
596 printf("Final Relative Residual Norm = %e\n", final_res_norm);
597 printf("\n");
598 }
599
600 /* Destory solver and preconditioner */
601 HYPRE_ParCSRFlexGMRESDestroy(solver);
602 HYPRE_BoomerAMGDestroy(precond);
603 }
604 else {
605 if (myid == 0) {
606 ARCANE_FATAL("Invalid solver id '{0}' specified.", solver_id);
607 }
608 }
609
610 if (print_system)
611 HYPRE_IJVectorPrint(x, "IJ.out.x");
612
613 /* Save the solution for GLVis visualization, see vis/glvis-ex5.sh */
614 if (vis) {
615#ifdef HYPRE_EXVIS
616 FILE* file;
617 char filename[255];
618
619 int nvalues = local_size;
620 int* rows = (int*)calloc(nvalues, sizeof(int));
621 double* values = (double*)calloc(nvalues, sizeof(double));
622
623 for (i = 0; i < nvalues; i++) {
624 rows[i] = ilower + i;
625 }
626
627 /* get the local solution */
628 HYPRE_IJVectorGetValues(x, nvalues, rows, values);
629
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);
633 MPI_Finalize();
634 exit(1);
635 }
636
637 /* save solution */
638 for (i = 0; i < nvalues; i++) {
639 fprintf(file, "%.14e\n", values[i]);
640 }
641
642 fflush(file);
643 fclose(file);
644
645 free(rows);
646 free(values);
647
648 /* save global finite element mesh */
649 if (myid == 0) {
650 GLVis_PrintGlobalSquareMesh("vis/ex5.mesh", n - 1);
651 }
652#endif
653 }
654
655 /* Clean up */
656 HYPRE_IJMatrixDestroy(A);
657 HYPRE_IJVectorDestroy(b);
658 HYPRE_IJVectorDestroy(x);
659
660 /* Finalize HYPRE */
661 HYPRE_Finalize();
662
663 /* Finalize MPI*/
664 MPI_Finalize();
665
666 return;
667}
668
669/*--------------------------------------------------------------------------
670 hypre_FlexGMRESModifyPCAMGExample -
671
672 This is an example (not recommended)
673 of how we can modify things about AMG that
674 affect the solve phase based on how FlexGMRES is doing...For
675 another preconditioner it may make sense to modify the tolerance..
676 *--------------------------------------------------------------------------*/
677
678int hypre_FlexGMRESModifyPCAMGExample(void* precond_data, [[maybe_unused]] int iterations,
679 double rel_residual_norm)
680{
681
682 if (rel_residual_norm > .1) {
683 HYPRE_BoomerAMGSetNumSweeps((HYPRE_Solver)precond_data, 10);
684 }
685 else {
686 HYPRE_BoomerAMGSetNumSweeps((HYPRE_Solver)precond_data, 1);
687 }
688
689 return 0;
690}
#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 -*-