Arcane  4.2.1.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 * Ce fichier est basé sur le travail sur la bibliothèque AMGCL (version mars 2026)
11 * qui peut être trouvée à 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 Exemple 5
28
29 Interface: Linéaire-Algébrique (IJ)
30
31 Compiler avec: make ex5
32
33 Exécution d'exemple: mpirun -np 4 ex5
34
35 Description: Cet exemple résout le problème de Laplacien en 2-D avec des
36 conditions aux limites nulles sur une grille n x n. Le nombre
37 d'inconnues est N=n^2. La méthode de stencil standard à 5 points est
38 utilisée, et nous résolvons uniquement pour les nœuds intérieurs.
39
40 Cet exemple résout le même problème que l'Exemple 3. Les solveurs
41 disponibles sont AMG, PCG, et PCG avec des préconditionneurs AMG ou
42 Parasails. */
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 * Fichier d'en-tête pour les exemples
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 *** L'exécution des exemples sur des GPU nécessite une mémoire unifiée. Veuillez reconfigurer et reconstruire avec --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 "arccore/base/Convert.h"
108#include "arccore/base/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 /* Initialisation de 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 /* Initialisation de HYPRE */
158 HYPRE_Initialize();
159
160 /* Affichage des informations GPU */
161 /* HYPRE_PrintDeviceInfo(); */
162#if defined(HYPRE_USING_GPU)
163 /* Utilise l'implémentation du fournisseur pour SpGEMM */
164 HYPRE_SetSpGemmUseVendor(0);
165#endif
166
167 /* Paramètres par défaut du problème */
168 const int n = nb_row;
169 solver_id = 0;
170 vis = 0;
171 print_system = 0;
172
173 /* Analyse de la ligne de commande */
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("Utilisation: %s [<options>]\n", argv[0]);
207 printf("\n");
208 printf(" -n <n> : taille du problème dans chaque direction (par défaut: 33)\n");
209 printf(" -solver <ID> : ID du solveur\n");
210 printf(" 0 - AMG (par défaut) \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 : enregistrer la solution pour la visualisation GLVis\n");
216 printf(" -print_system : imprimer la matrice et le rhs\n");
217 printf("\n");
218 }
219
220 if (print_usage) {
221 MPI_Finalize();
222 return;
223 }
224 }
225
226 // Remplit la valeur nb par ligne.
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 // L'index de colonne est le même que '_col' de la matrice CSR
232 // mais nous faisons une copie si la taille de l'index est différente entre Hypre et Alina.
233 std::vector<HYPRE_BigInt> hypre_column_index(_col.begin(), _col.end());
234
235 // ID de chaque ligne (en séquentiel, c'est le même que l'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 /* Chaque processeur ne connaît que ses propres lignes - la plage est indiquée par ilower
242 et upper. Ici, nous partitionnons les lignes. Nous prenons en compte le fait que
243 N peut ne pas être divisible uniformément par le nombre de processeurs. */
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 /* Combien de lignes ai-je ? */
255 local_size = iupper - ilower + 1;
256
257 {
258 auto t = prof.scoped_tic("Création de IJMatrix");
259 /* Crée la matrice.
260 Notez qu'il s'agit d'une matrice carrée, nous indiquons donc la taille de la partition
261 de ligne deux fois (car le nombre de lignes = nombre de colonnes) */
262 HYPRE_IJMatrixCreate(MPI_COMM_WORLD, ilower, iupper, ilower, iupper, &A);
263
264 /* Choisis un stockage de format csr parallèle (voir le Manuel de l'utilisateur) */
265 HYPRE_IJMatrixSetObjectType(A, HYPRE_PARCSR);
266
267 /* Initialise avant de définir les coefficients */
268 HYPRE_IJMatrixInitialize(A);
269 }
270
271 // Remplis la matrice.
272 {
273 auto t = prof.scoped_tic("Définition des valeurs de IJMatrix");
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("Assemblage de IJMatrix");
284 /* Assemble après avoir défini les coefficients */
285 HYPRE_IJMatrixAssemble(A);
286 }
287
288 /* Remarque : pour le test de petits problèmes, on peut souhaiter lire
289 une matrice au format IJ (pour le format, voir les fichiers de sortie
290 de l'option -print_system).
291 Dans ce cas, on utiliserait la routine suivante:
292 HYPRE_IJMatrixRead( <nom_de_fichier>, MPI_COMM_WORLD,
293 HYPRE_PARCSR, &A );
294 <nom_de_fichier> = IJ.A.out pour lire ce qui a été imprimé par
295 -print_system (les numéros de processeur sont omis).
296 Un appel à HYPRE_IJMatrixRead est une *alternative* à la
297 séquence suivante d'appels HYPRE_IJMatrix:
298 Create, SetObjectType, Initialize, SetValues, et Assemble
299 */
300
301 /* Récupérer l'objet matrice parcsr pour l'utiliser */
302 HYPRE_IJMatrixGetObject(A, (void**)&parcsr_A);
303
304 /* Crée le rhs et la 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 /* Définit les valeurs du rhs à h^2 et la solution à zéro */
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 /* Tout comme pour la matrice, pour des tests, on peut souhaiter lire un rhs:
338 HYPRE_IJVectorRead( <nom_de_fichier>, MPI_COMM_WORLD,
339 HYPRE_PARCSR, &b );
340 comme alternative à la
341 séquence suivante d'appels HYPRE_IJVectors:
342 Create, SetObjectType, Initialize, SetValues, et Assemble
343 */
344 HYPRE_IJVectorGetObject(b, (void**)&par_b);
345
346 HYPRE_IJVectorAssemble(x);
347 HYPRE_IJVectorGetObject(x, (void**)&par_x);
348
349 /* Imprime le système - les noms de fichiers seront IJ.out.A.XXXXX
350 et IJ.out.b.XXXXX, où XXXXX = ID du processeur */
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 /* Choisit un solveur et résoudre le système */
362 std::cout << "FIN DE L'ASSEMBLAGE 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 /* Crée le solveur */
370 HYPRE_BoomerAMGCreate(&solver);
371
372 /* Définit certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
373 HYPRE_BoomerAMGSetPrintLevel(solver, 3); /* imprimer les informations de résolution + paramètres */
374 HYPRE_BoomerAMGSetOldDefault(solver); /* Raffinement Falgout avec interpolation classique modifiée */
375 HYPRE_BoomerAMGSetRelaxType(solver, 3); /* Relaxation hybride G-S/Jacobi */
376 HYPRE_BoomerAMGSetRelaxOrder(solver, 1); /* utilise la relaxation C/F */
377 HYPRE_BoomerAMGSetNumSweeps(solver, 1); /* Balayages à chaque niveau */
378 HYPRE_BoomerAMGSetMaxLevels(solver, 20); /* nombre maximum de niveaux */
379 HYPRE_BoomerAMGSetTol(solver, solver_tolerance); /* tolérance de convergence */
380
381 /* Maintenant, configurer et résoudre ! */
382 {
383 auto t = prof.scoped_tic("Configuration AMG");
384 HYPRE_BoomerAMGSetup(solver, parcsr_A, par_b, par_x);
385 }
386 {
387 auto t = prof.scoped_tic("Résolution AMG");
388 HYPRE_BoomerAMGSolve(solver, parcsr_A, par_b, par_x);
389 }
390
391 /* Informations d'exécution - nécessaire si le journal est activé */
392 HYPRE_BoomerAMGGetNumIterations(solver, &num_iterations);
393 HYPRE_BoomerAMGGetFinalRelativeResidualNorm(solver, &final_res_norm);
394 if (myid == 0) {
395 printf("\n");
396 printf("Itérations = %d\n", num_iterations);
397 printf("Norme résiduelle relative finale = %e\n", final_res_norm);
398 printf("\n");
399 }
400
401 /* Détruit le solveur */
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 /* Crée le solveur */
411 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
412
413 /* Définit certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
414 HYPRE_PCGSetMaxIter(solver, 1000); /* itérations max */
415 HYPRE_PCGSetTol(solver, solver_tolerance); /* tolérance de convergence */
416 HYPRE_PCGSetTwoNorm(solver, 1); /* utiliser la double norme comme critère d'arrêt */
417 HYPRE_PCGSetPrintLevel(solver, 2); /* affiche les informations d'itération */
418 HYPRE_PCGSetLogging(solver, 1); /* nécessaire pour obtenir les informations d'exécution plus tard */
419
420 /* Maintenant, configurer et résoudre ! */
421 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
422 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
423
424 /* Informations d'exécution - nécessaire si le journal est activé */
425 HYPRE_PCGGetNumIterations(solver, &num_iterations);
426 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
427 if (myid == 0) {
428 printf("\n");
429 printf("Itérations = %d\n", num_iterations);
430 printf("Norme résiduelle relative finale = %e\n", final_res_norm);
431 printf("\n");
432 }
433
434 /* Détruit le solveur */
435 HYPRE_ParCSRPCGDestroy(solver);
436 }
437 /* PCG avec préconditionneur AMG */
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 /* Crée le solveur */
444 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
445
446 /* Définit certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
447 HYPRE_PCGSetMaxIter(solver, 1000); /* itérations max */
448 HYPRE_PCGSetTol(solver, solver_tolerance); /* tolérance de convergence */
449 HYPRE_PCGSetTwoNorm(solver, 1); /* utiliser la double norme comme critère d'arrêt */
450 HYPRE_PCGSetPrintLevel(solver, 2); /* affiche les informations de résolution */
451 HYPRE_PCGSetLogging(solver, 1); /* nécessaire pour obtenir les informations d'exécution plus tard */
452
453 /* Maintenant, configurer le préconditionneur AMG et spécifier les paramètres */
454 HYPRE_BoomerAMGCreate(&precond);
455 HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* imprimer les informations de résolution AMG */
456 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
457 HYPRE_BoomerAMGSetOldDefault(precond);
458 HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Hybride G.S./Jacobi symétrique */
459 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
460 HYPRE_BoomerAMGSetTol(precond, 0.0); /* tolérance de convergence zéro */
461 HYPRE_BoomerAMGSetMaxIter(precond, 1); /* faire seulement une itération ! */
462
463 /* Définit le préconditionneur PCG */
464 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
465 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
466
467 /* Maintenant, configurer et résoudre ! */
468 prof.tic("Configuration");
469 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
470 prof.toc("Configuration");
471 prof.tic("Résolution");
472 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
473 prof.toc("Résolution");
474
475 /* Informations d'exécution - nécessaire si le journal est activé */
476 HYPRE_PCGGetNumIterations(solver, &num_iterations);
477 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
478 if (myid == 0) {
479 printf("\n");
480 printf("Itérations = %d\n", num_iterations);
481 printf("Norme résiduelle relative finale = %e\n", final_res_norm);
482 printf("\n");
483 }
484
485 /* Détruit le solveur et le préconditionneur */
486 HYPRE_ParCSRPCGDestroy(solver);
487 HYPRE_BoomerAMGDestroy(precond);
488 }
489 /* PCG avec préconditionneur Parasails */
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 /* Crée le solveur */
501 HYPRE_ParCSRPCGCreate(MPI_COMM_WORLD, &solver);
502
503 /* Définit certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
504 HYPRE_PCGSetMaxIter(solver, 1000); /* itérations max */
505 HYPRE_PCGSetTol(solver, solver_tolerance); /* tolérance de convergence */
506 HYPRE_PCGSetTwoNorm(solver, 1); /* utiliser la double norme comme critère d'arrêt */
507 HYPRE_PCGSetPrintLevel(solver, 2); /* affiche les informations de résolution */
508 HYPRE_PCGSetLogging(solver, 1); /* nécessaire pour obtenir les informations d'exécution plus tard */
509
510 /* Maintenant, configurer le préconditionneur ParaSails et spécifier les paramètres */
511 HYPRE_ParaSailsCreate(MPI_COMM_WORLD, &precond);
512
513 /* Définir certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
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 /* Définit le préconditionneur PCG */
520 HYPRE_PCGSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSolve,
521 (HYPRE_PtrToSolverFcn)HYPRE_ParaSailsSetup, precond);
522
523 /* Maintenant, configurer et résoudre ! */
524 HYPRE_ParCSRPCGSetup(solver, parcsr_A, par_b, par_x);
525 HYPRE_ParCSRPCGSolve(solver, parcsr_A, par_b, par_x);
526
527 /* Informations d'exécution - nécessaire si le journal est activé */
528 HYPRE_PCGGetNumIterations(solver, &num_iterations);
529 HYPRE_PCGGetFinalRelativeResidualNorm(solver, &final_res_norm);
530 if (myid == 0) {
531 printf("\n");
532 printf("Itérations = %d\n", num_iterations);
533 printf("Norme résiduelle relative finale = %e\n", final_res_norm);
534 printf("\n");
535 }
536
537 /* Détruit le solveur et le préconditionneur */
538 HYPRE_ParCSRPCGDestroy(solver);
539 HYPRE_ParaSailsDestroy(precond);
540 }
541 /* Flexible GMRES avec préconditionneur AMG */
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 /* Crée le solveur */
550 HYPRE_ParCSRFlexGMRESCreate(MPI_COMM_WORLD, &solver);
551
552 /* Définit certains paramètres (Voir le Manuel de Référence pour plus de paramètres) */
553 HYPRE_FlexGMRESSetKDim(solver, restart);
554 HYPRE_FlexGMRESSetMaxIter(solver, 1000); /* itérations max */
555 HYPRE_FlexGMRESSetTol(solver, solver_tolerance); /* tolérance de convergence */
556 HYPRE_FlexGMRESSetPrintLevel(solver, 2); /* affiche les informations de résolution */
557 HYPRE_FlexGMRESSetLogging(solver, 1); /* nécessaire pour obtenir les informations d'exécution plus tard */
558
559 /* Maintenant, configurer le préconditionneur AMG et spécifier les paramètres */
560 HYPRE_BoomerAMGCreate(&precond);
561 HYPRE_BoomerAMGSetPrintLevel(precond, 1); /* imprimer les informations de résolution AMG */
562 HYPRE_BoomerAMGSetCoarsenType(precond, 6);
563 HYPRE_BoomerAMGSetOldDefault(precond);
564 HYPRE_BoomerAMGSetRelaxType(precond, 6); /* Hybride G.S./Jacobi symétrique */
565 HYPRE_BoomerAMGSetNumSweeps(precond, 1);
566 HYPRE_BoomerAMGSetTol(precond, 0.0); /* tolérance de convergence zéro */
567 HYPRE_BoomerAMGSetMaxIter(precond, 1); /* faire seulement une itération ! */
568
569 /* Définit le préconditionneur FlexGMRES */
570 HYPRE_FlexGMRESSetPrecond(solver, (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSolve,
571 (HYPRE_PtrToSolverFcn)HYPRE_BoomerAMGSetup, precond);
572
573 if (modify) {
574 /* ceci est un appel optionnel - si vous ne l'appelez pas, hypre_FlexGMRESModifyPCDefault
575 est utilisé - ce qui ne fait rien. Sinon, vous pouvez en définir un propre, similaire à
576 celui utilisé ici */
577 HYPRE_FlexGMRESSetModifyPC(solver, (HYPRE_PtrToModifyPCFcn)hypre_FlexGMRESModifyPCAMGExample);
578 }
579
580 /* Maintenant, configurer et résoudre ! */
581 {
582 auto t = prof.scoped_tic("Configuration FlexGMRES");
583 HYPRE_ParCSRFlexGMRESSetup(solver, parcsr_A, par_b, par_x);
584 }
585 {
586 auto t = prof.scoped_tic("Résolution FlexGMRES");
587 HYPRE_ParCSRFlexGMRESSolve(solver, parcsr_A, par_b, par_x);
588 }
589
590 /* Informations d'exécution - nécessaire si le journal est activé */
591 HYPRE_FlexGMRESGetNumIterations(solver, &num_iterations);
592 HYPRE_FlexGMRESGetFinalRelativeResidualNorm(solver, &final_res_norm);
593 if (myid == 0) {
594 printf("\n");
595 printf("Itérations = %d\n", num_iterations);
596 printf("Norme résiduelle relative finale = %e\n", final_res_norm);
597 printf("\n");
598 }
599
600 /* Détruit le solveur et le préconditionneur */
601 HYPRE_ParCSRFlexGMRESDestroy(solver);
602 HYPRE_BoomerAMGDestroy(precond);
603 }
604 else {
605 if (myid == 0) {
606 ARCCORE_FATAL("ID de solveur '{0}' spécifié invalide.", solver_id);
607 }
608 }
609
610 if (print_system)
611 HYPRE_IJVectorPrint(x, "IJ.out.x");
612
613 /* Enregistre la solution pour la visualisation GLVis, voir 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 /* récupère la solution locale */
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("Erreur: impossible d'ouvrir le fichier de sortie %s\n", filename);
633 MPI_Finalize();
634 exit(1);
635 }
636
637 /* enregistre la 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 /* enregistre le maillage global des éléments finis */
649 if (myid == 0) {
650 GLVis_PrintGlobalSquareMesh("vis/ex5.mesh", n - 1);
651 }
652#endif
653 }
654
655 /* Nettoyage */
656 HYPRE_IJMatrixDestroy(A);
657 HYPRE_IJVectorDestroy(b);
658 HYPRE_IJVectorDestroy(x);
659
660 /* Finalise HYPRE */
661 HYPRE_Finalize();
662
663 /* Finalise MPI*/
664 MPI_Finalize();
665
666 return;
667}
668
669/*--------------------------------------------------------------------------
670 hypre_FlexGMRESModifyPCAMGExample -
671
672 Ceci est un exemple (non recommandé)
673 de la façon dont nous pouvons modifier les choses concernant AMG qui
674 affectent la phase de résolution en fonction de la manière dont FlexGMRES progresse...
675 Pour un autre préconditionneur, il pourrait être judicieux de modifier la tolérance..
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 ARCCORE_FATAL(...)
Macro envoyant une exception FatalErrorException.
Classe template pour convertir un type.
-- tab-width: 2; indent-tabs-mode: nil; coding: utf-8-with-signature --