Arcane  4.2.1.0
Documentation développeur
Chargement...
Recherche...
Aucune correspondance
AMG.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/* AMG.cc (C) 2000-2026 */
9/* */
10/* Multi-grille algébrique. */
11/*---------------------------------------------------------------------------*/
12/*---------------------------------------------------------------------------*/
13
14#include "arcane/utils/Array.h"
15#include "arcane/utils/ArgumentException.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/TraceAccessor.h"
18#include "arcane/utils/OStringStream.h"
19#include "arcane/utils/StringBuilder.h"
20
21#include "arcane/core/matvec/Matrix.h"
22
23#include <set>
24#include <fstream>
25
26/*---------------------------------------------------------------------------*/
27/*---------------------------------------------------------------------------*/
28
29namespace Arcane::math
30{
31Real divide(Real a, Real b)
32{
33 if (b == 0.0)
34 ARCANE_FATAL("Division by zero");
35 return a / b;
36}
37} // namespace Arcane::math
38
39/*---------------------------------------------------------------------------*/
40/*---------------------------------------------------------------------------*/
41
42namespace Arcane::MatVec
43{
44
45/*---------------------------------------------------------------------------*/
46/*---------------------------------------------------------------------------*/
47
48void DirectSolver::
49solve(const Matrix& matrix, const Vector& vector_b, Vector& vector_x)
50{
51 IntegerConstArrayView rows = matrix.rowsIndex();
52 IntegerConstArrayView columns = matrix.columns();
53 RealConstArrayView mat_values = matrix.values();
54
55 Integer nb_row = matrix.nbRow();
56 RealUniqueArray solution_values(nb_row);
57 RealUniqueArray full_matrix_values(nb_row * nb_row);
58 full_matrix_values.fill(0.0);
59 solution_values.copy(vector_b.values());
60 for (Integer row = 0; row < nb_row; ++row) {
61 for (Integer j = rows[row]; j < rows[row + 1]; ++j) {
62 full_matrix_values[row * nb_row + columns[j]] = mat_values[j];
63 }
64 }
65 _solve(full_matrix_values, solution_values, nb_row);
66 vector_x.values().copy(solution_values);
67}
68
69/*---------------------------------------------------------------------------*/
70/*---------------------------------------------------------------------------*/
71
72void DirectSolver::
73_solve(RealArrayView mat_values, RealArrayView vec_values, Integer size)
74{
75 if (size == 1) {
76 if (math::isZero(mat_values[0]))
77 throw FatalErrorException("DirectSolver", "Null matrix");
78 vec_values[0] /= mat_values[0];
79 return;
80 }
81
82 for (Integer k = 0; k < size - 1; ++k) {
83 if (!math::isZero(mat_values[k * size + k])) {
84 for (Integer j = k + 1; j < size; ++j) {
85 if (!math::isZero(mat_values[j * size + k])) {
86 Real factor = mat_values[j * size + k] / mat_values[k * size + k];
87 for (Integer m = k + 1; m < size; ++m)
88 mat_values[j * size + m] -= factor * mat_values[k * size + m];
89 vec_values[j] -= factor * vec_values[k];
90 }
91 }
92 }
93 }
94
95 for (Integer k = (size - 1); k > 0; --k) {
96 vec_values[k] /= mat_values[k * size + k];
97 for (Integer j = 0; j < k; ++j) {
98 if (!math::isZero(mat_values[j * size + k]))
99 vec_values[j] -= vec_values[k] * mat_values[j * size + k];
100 }
101 }
102
103 vec_values[0] /= mat_values[0];
104}
105
106/*---------------------------------------------------------------------------*/
107/*---------------------------------------------------------------------------*/
108
109Matrix MatrixOperation2::
110matrixMatrixProduct(const Matrix& left_matrix, const Matrix& right_matrix)
111{
112 Integer nb_left_col = left_matrix.nbColumn();
113 Integer nb_right_col = right_matrix.nbColumn();
114 Integer nb_right_row = right_matrix.nbRow();
115 Integer nb_left_row = left_matrix.nbRow();
116 if (nb_left_col != nb_right_row)
117 ARCANE_THROW(ArgumentException, "Bad size nb_left_column={0} nb_right_row={1}",
118 nb_left_col, nb_right_row);
119 Integer nb_row_col = nb_left_col;
120
121 Matrix new_matrix(nb_left_row, nb_right_col);
122 IntegerUniqueArray new_matrix_rows_size(nb_left_row);
123 RealUniqueArray new_matrix_values;
124 IntegerUniqueArray new_matrix_columns;
125
126 for (Integer i = 0; i < nb_left_row; ++i) {
127 Integer local_nb_col = 0;
128 for (Integer j = 0; j < nb_right_col; ++j) {
129 Real v = 0.0;
130 for (Integer k = 0; k < nb_row_col; ++k) {
131 //if (i==1 && j==0){
132 // Real v0 = left_matrix.value(i,k) * right_matrix.value(k,j);
133 // cout << "** CHECK CONTRIBUTION k=" << k
134 // << " l=" << left_matrix.value(i,k) << " r=" << right_matrix.value(k,j) << '\n';
135 // if (!math::isZero(v0))
136 // cout << "** ADD CONTRIBUTION k=" << k << " v0=" << v0
137 // << " l=" << left_matrix.value(i,k) << " r=" << right_matrix.value(k,j) << '\n';
138 // }
139 v += left_matrix.value(i, k) * right_matrix.value(k, j);
140 }
141 if (!math::isZero(v)) {
142 ++local_nb_col;
143 new_matrix_columns.add(j);
144 new_matrix_values.add(v);
145 }
146 }
147 new_matrix_rows_size[i] = local_nb_col;
148 }
149 new_matrix.setRowsSize(new_matrix_rows_size);
150 new_matrix.setValues(new_matrix_columns, new_matrix_values);
151 return new_matrix;
152}
153
154/*---------------------------------------------------------------------------*/
155/*---------------------------------------------------------------------------*/
156
157Matrix MatrixOperation2::
158matrixMatrixProductFast(const Matrix& left_matrix, const Matrix& right_matrix)
159{
160 Integer nb_left_col = left_matrix.nbColumn();
161 Integer nb_right_col = right_matrix.nbColumn();
162 Integer nb_right_row = right_matrix.nbRow();
163 Integer nb_left_row = left_matrix.nbRow();
164 if (nb_left_col != nb_right_row)
165 ARCANE_THROW(ArgumentException, "Bad size nb_left_column={0} nb_right_row={1}",
166 nb_left_col, nb_right_row);
167 //Integer nb_row_col = nb_left_col;
168
169 IntegerConstArrayView left_rows_index = left_matrix.rowsIndex();
170 IntegerConstArrayView left_columns = left_matrix.columns();
171 RealConstArrayView left_values = left_matrix.values();
172
173 IntegerConstArrayView right_rows_index = right_matrix.rowsIndex();
174 IntegerConstArrayView right_columns = right_matrix.columns();
175 RealConstArrayView right_values = right_matrix.values();
176
177 Matrix new_matrix(nb_left_row, nb_right_col);
178 IntegerUniqueArray new_matrix_rows_size(nb_left_row);
179 RealUniqueArray new_matrix_values;
180 IntegerUniqueArray new_matrix_columns;
181
182 IntegerUniqueArray col_right_columns_index(nb_right_col + 1);
183 IntegerUniqueArray col_right_rows;
184 RealUniqueArray col_right_values;
185 IntegerUniqueArray col_right_columns_size(nb_right_col);
186 {
187 // Calcule le nombre d'éléments de chaque colonne
188 col_right_columns_size.fill(0);
189 for (Integer i = 0; i < nb_right_row; ++i) {
190 for (Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
191 ++col_right_columns_size[right_columns[j]];
192 }
193 }
194 // Calcule l'index du premier élément de chaque colonne.
195 Integer index = 0;
196 for (Integer j = 0; j < nb_right_col; ++j) {
197 col_right_columns_index[j] = index;
198 index += col_right_columns_size[j];
199 }
200 col_right_columns_index[nb_right_col] = index;
201
202 col_right_rows.resize(index);
203 col_right_values.resize(index);
204 index = 0;
205 // Remplit les valeurs par colonne
206 col_right_columns_size.fill(0);
207 for (Integer i = 0; i < nb_right_row; ++i) {
208 for (Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
209 Integer col = right_columns[j];
210 Real value = right_values[j];
211 Integer col_index = col_right_columns_size[col] + col_right_columns_index[col];
212 ++col_right_columns_size[col];
213 col_right_rows[col_index] = i;
214 col_right_values[col_index] = value;
215 }
216 }
217 }
218 //_dumpColumnMatrix(cout,col_right_columns_index,col_right_rows,col_right_values);
219 //cout << '\n';
220 RealUniqueArray current_row_values(nb_left_col);
221 current_row_values.fill(0.0);
222 for (Integer i = 0; i < nb_left_row; ++i) {
223 Integer local_nb_col = 0;
224 // Remplit la ligne avec les valeurs courantes
225 for (Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z) {
226 current_row_values[left_columns[z]] = left_values[z];
227 //if (i==1)
228 //cout << " ** FILL VALUE col=" << left_columns[z] << " v=" << left_values[z] << '\n';
229 }
230 //if (i==1){
231 //for( Integer z=0; z<nb_left_col; ++z ){
232 //current_row_values[ left_columns[z] ] = left_values[z];
233 // cout << " ** VALUE col=" << z << " v=" << current_row_values[z] << '\n';
234 //}
235 //}
236
237 for (Integer j = 0; j < nb_right_col; ++j) {
238 Real v = 0.0;
239 for (Integer zj = col_right_columns_index[j]; zj < col_right_columns_index[j + 1]; ++zj) {
240 //if (i==1 && j==0){
241 // Real v0 = col_right_values[zj] * current_row_values[ col_right_rows[zj] ];
242 // cout << "** CHECK CONTRIBUTION2 k=" << col_right_rows[zj]
243 // << " l=" << current_row_values[ col_right_rows[zj] ] << " r=" << col_right_values[zj] << '\n';
244 // if (!math::isZero(v0))
245 // cout << "** ADD CONTRIBUTION2 k=" << col_right_rows[zj] << " v0=" << v0
246 // << " l=" << current_row_values[ col_right_rows[zj] ] << " r=" << col_right_values[zj] << '\n';
247 // }
248 v += col_right_values[zj] * current_row_values[col_right_rows[zj]];
249 }
250 if (!math::isZero(v)) {
251 ++local_nb_col;
252 new_matrix_columns.add(j);
253 new_matrix_values.add(v);
254 }
255 }
256
257 new_matrix_rows_size[i] = local_nb_col;
258
259 // Remet des zeros dans la ligne courante.
260 for (Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z)
261 current_row_values[left_columns[z]] = 0.0;
262 }
263 new_matrix.setRowsSize(new_matrix_rows_size);
264 new_matrix.setValues(new_matrix_columns, new_matrix_values);
265 return new_matrix;
266}
267
268/*---------------------------------------------------------------------------*/
269/*---------------------------------------------------------------------------*/
270
271void MatrixOperation2::
272_dumpColumnMatrix(std::ostream& o, IntegerConstArrayView columns_index, IntegerConstArrayView rows,
273 RealConstArrayView values)
274{
275 Integer nb_col = columns_index.size() - 1;
276 o << "(ColumnMatrix nb_col=" << nb_col;
277 for (Integer j = 0; j < nb_col; ++j) {
278 for (Integer z = columns_index[j], zs = columns_index[j + 1]; z < zs; ++z) {
279 Integer i = rows[z];
280 Real v = values[z];
281 o << " [" << i << "," << j << "]=" << v;
282 }
283 }
284 o << ")";
285}
286
287/*---------------------------------------------------------------------------*/
288/*---------------------------------------------------------------------------*/
289
290Matrix MatrixOperation2::
291transpose(const Matrix& matrix)
292{
293 Integer nb_column = matrix.nbColumn();
294 Integer nb_row = matrix.nbRow();
295
296 Integer new_matrix_nb_row = nb_column;
297 Integer new_matrix_nb_column = nb_row;
298 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
299 IntegerUniqueArray new_matrix_rows_size(new_matrix_nb_row);
300 RealUniqueArray new_matrix_values;
301 IntegerUniqueArray new_matrix_columns;
302
303 for (Integer i = 0; i < new_matrix_nb_row; ++i) {
304 Integer local_nb_col = 0;
305 for (Integer j = 0; j < new_matrix_nb_column; ++j) {
306 Real v = matrix.value(j, i);
307 if (!math::isZero(v)) {
308 ++local_nb_col;
309 new_matrix_columns.add(j);
310 new_matrix_values.add(v);
311 }
312 }
313 new_matrix_rows_size[i] = local_nb_col;
314 }
315 new_matrix.setRowsSize(new_matrix_rows_size);
316 new_matrix.setValues(new_matrix_columns, new_matrix_values);
317 return new_matrix;
318}
319
320/*---------------------------------------------------------------------------*/
321/*---------------------------------------------------------------------------*/
322
323Matrix MatrixOperation2::
324transposeFast(const Matrix& matrix)
325{
326 Integer nb_column = matrix.nbColumn();
327 Integer nb_row = matrix.nbRow();
328
329 IntegerConstArrayView rows_index = matrix.rowsIndex();
330 IntegerConstArrayView columns = matrix.columns();
331 RealConstArrayView values = matrix.values();
332
333 Integer new_matrix_nb_row = nb_column;
334 Integer new_matrix_nb_column = nb_row;
335 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
336
337 IntegerUniqueArray new_matrix_rows_size(new_matrix_nb_row);
338
339 // Calcul le nombre de colonnes de chaque ligne de la transposee.
340 new_matrix_rows_size.fill(0);
341 Integer nb_element = values.size();
342 for (Integer i = 0, is = columns.size(); i < is; ++i) {
343 ++new_matrix_rows_size[columns[i]];
344 }
345 new_matrix.setRowsSize(new_matrix_rows_size);
346
347 IntegerConstArrayView new_matrix_rows_index = new_matrix.rowsIndex();
348 new_matrix_rows_size.fill(0);
349
350 RealUniqueArray new_matrix_values(nb_element);
351 IntegerUniqueArray new_matrix_columns(nb_element);
352
353 for (Integer row = 0, is = nb_row; row < is; ++row) {
354 for (Integer j = rows_index[row]; j < rows_index[row + 1]; ++j) {
355 Integer col_index = columns[j];
356 Integer pos = new_matrix_rows_index[col_index] + new_matrix_rows_size[col_index];
357 //cout << "** CURRENT row=" << row << " col=" << col_index << " v=" << values[col_index]
358 new_matrix_columns[pos] = row;
359 new_matrix_values[pos] = values[j];
360 ++new_matrix_rows_size[col_index];
361 }
362 }
363
364 new_matrix.setValues(new_matrix_columns, new_matrix_values);
365 return new_matrix;
366}
367
368/*---------------------------------------------------------------------------*/
369/*---------------------------------------------------------------------------*/
370
371Matrix MatrixOperation2::
372applyGalerkinOperator(const Matrix& left_matrix, const Matrix& matrix,
373 const Matrix& right_matrix)
374{
375 Integer nb_original_row = matrix.nbRow();
376 Integer nb_final_row = left_matrix.nbRow();
377 IntegerUniqueArray p_marker(nb_final_row);
378 IntegerUniqueArray a_marker(nb_original_row);
379 p_marker.fill(-1);
380 a_marker.fill(-1);
381
382 IntegerConstArrayView left_matrix_rows = left_matrix.rowsIndex();
383 IntegerConstArrayView left_matrix_columns = left_matrix.columns();
384 RealConstArrayView left_matrix_values = left_matrix.values();
385
386 IntegerConstArrayView right_matrix_rows = right_matrix.rowsIndex();
387 IntegerConstArrayView right_matrix_columns = right_matrix.columns();
388 RealConstArrayView right_matrix_values = right_matrix.values();
389
390 IntegerConstArrayView matrix_rows = matrix.rowsIndex();
391 IntegerConstArrayView matrix_columns = matrix.columns();
392 RealConstArrayView matrix_values = matrix.values();
393
394 Integer jj_counter = 0;
395 Integer jj_row_begining = 0;
396
397 IntegerUniqueArray new_matrix_rows_size(nb_final_row);
398
399 // D'abord, détermine le nombre de colonnes de chaque ligne de la
400 // matrice finale
401 for (Integer ic = 0; ic < nb_final_row; ++ic) {
402 // Ajoute la diagonale
403 p_marker[ic] = jj_counter;
404 jj_row_begining = jj_counter;
405 ++jj_counter;
406
407 // Boucle sur les colonnes de la ligne \a ic de \a matrix
408 for (Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
409 Integer i1 = left_matrix_columns[jj1];
410
411 // Boucle sur les colonnes de la ligne \a i1 de \a matrix
412 for (Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
413 Integer i2 = matrix_columns[jj2];
414 /*--------------------------------------------------------------
415 * Vérifie A_marker pour voir si le point i2 a déjà été
416 * visité. Les nouvelles entrées dans RAP ne proviennent que
417 * des points non marqués.
418 *--------------------------------------------------------------*/
419 if (a_marker[i2] != ic) {
420 a_marker[i2] = ic;
421 /*-----------------------------------------------------------
422 * Boucle sur les entrées de la ligne i2 de P.
423 *-----------------------------------------------------------*/
424 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
425 Integer i3 = right_matrix_columns[jj3];
426 /*--------------------------------------------------------
427 * Vérifie P_marker pour s'assurer que RAP_{ic,i3} n'a pas déjà
428 * été pris en compte. Si ce n'est pas le cas, le marque et incrémente
429 * le compteur.
430 *--------------------------------------------------------*/
431 if (p_marker[i3] < jj_row_begining) {
432 p_marker[i3] = jj_counter;
433 ++jj_counter;
434 }
435 }
436 }
437 }
438 }
439 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
440 }
441 static Integer total_rap_size = 0;
442 total_rap_size += jj_counter;
443
444 std::cout << "** RAP_SIZE=" << jj_counter << " TOTAL=" << total_rap_size << '\n';
445 Matrix new_matrix(nb_final_row, nb_final_row);
446 new_matrix.setRowsSize(new_matrix_rows_size);
447
448 //IntegerConstArrayView new_matrix_rows = new_matrix.rowsIndex();
449 IntegerArrayView new_matrix_columns = new_matrix.columns();
450 RealArrayView new_matrix_values = new_matrix.values();
451
452 // Maintenant, remplit les coefficients de la matrice
453 p_marker.fill(-1);
454 a_marker.fill(-1);
455 jj_counter = 0;
456 for (Integer ic = 0; ic < nb_final_row; ++ic) {
457 // Ajoute la diagonale
458 p_marker[ic] = jj_counter;
459 jj_row_begining = jj_counter;
460 new_matrix_columns[jj_counter] = ic;
461 new_matrix_values[jj_counter] = 0.0;
462 ++jj_counter;
463 // Boucle sur les colonnes de la ligne \a ic de \a matrix
464 for (Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
465 Integer i1 = left_matrix_columns[jj1];
466 Real r_entry = left_matrix_values[jj1];
467
468 // Boucle sur les colonnes de la ligne \a i1 de \a matrix
469 for (Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
470 Integer i2 = matrix_columns[jj2];
471 Real r_a_product = r_entry * matrix_values[jj2];
472 /*--------------------------------------------------------------
473 * Vérifie A_marker pour voir si le point i2 a déjà été
474 * visité. Les nouvelles entrées dans RAP ne proviennent que
475 * des points non marqués.
476 *--------------------------------------------------------------*/
477 if (a_marker[i2] != ic) {
478 a_marker[i2] = ic;
479 /*-----------------------------------------------------------
480 * Boucle sur les entrées de la ligne i2 de P.
481 *-----------------------------------------------------------*/
482 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
483 Integer i3 = right_matrix_columns[jj3];
484 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
485 /*--------------------------------------------------------
486 * Vérifie P_marker pour s'assurer que RAP_{ic,i3} n'a pas déjà
487 * été pris en compte. Si ce n'est pas le cas, crée une nouvelle entrée.
488 * S'il l'est, ajoute la nouvelle contribution.
489 *--------------------------------------------------------*/
490 if (p_marker[i3] < jj_row_begining) {
491 p_marker[i3] = jj_counter;
492 new_matrix_values[jj_counter] = r_a_p_product;
493 new_matrix_columns[jj_counter] = i3;
494 ++jj_counter;
495 }
496 else {
497 new_matrix_values[p_marker[i3]] += r_a_p_product;
498 }
499 }
500 }
501 else {
502 /*--------------------------------------------------------------
503 * Si i2 a déjà été visité ( A_marker[12]=ic ) cela ne produit
504 * aucune nouvelle entrée dans RAP et peut simplement ajouter de nouvelles contributions.
505 *--------------------------------------------------------------*/
506 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
507 Integer i3 = right_matrix_columns[jj3];
508 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
509 new_matrix_values[p_marker[i3]] += r_a_p_product;
510 }
511 }
512 }
513 }
514 }
515 return new_matrix;
516}
517
518/*---------------------------------------------------------------------------*/
519/*---------------------------------------------------------------------------*/
520
521Matrix MatrixOperation2::
522applyGalerkinOperator2(const Matrix& left_matrix, const Matrix& matrix,
523 const Matrix& right_matrix)
524{
525 Integer nb_original_row = matrix.nbRow();
526 Integer nb_final_row = left_matrix.nbRow();
527 IntegerUniqueArray p_marker(nb_final_row);
528 IntegerUniqueArray a_marker(nb_original_row);
529 p_marker.fill(-1);
530 a_marker.fill(-1);
531
532 const Integer* left_matrix_rows = left_matrix.rowsIndex().data();
533 const Integer* left_matrix_columns = left_matrix.columns().data();
534 const Real* left_matrix_values = left_matrix.values().data();
535
536 const Integer* right_matrix_rows = right_matrix.rowsIndex().data();
537 const Integer* right_matrix_columns = right_matrix.columns().data();
538 const Real* right_matrix_values = right_matrix.values().data();
539
540 const Integer* matrix_rows = matrix.rowsIndex().data();
541 const Integer* matrix_columns = matrix.columns().data();
542 const Real* matrix_values = matrix.values().data();
543
544 Integer jj_counter = 0;
545 Integer jj_row_begining = 0;
546
547 IntegerUniqueArray new_matrix_rows_size(nb_final_row);
548
549 // D'abord, détermine le nombre de colonnes de chaque ligne de la
550 // matrice finale
551 for (Integer ic = 0; ic < nb_final_row; ++ic) {
552 // Ajoute la diagonale
553 p_marker[ic] = jj_counter;
554 jj_row_begining = jj_counter;
555 ++jj_counter;
556
557 // Boucle sur les colonnes de la ligne \a ic de \a matrix
558 for (Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
559 Integer i1 = left_matrix_columns[jj1];
560
561 // Boucle sur les colonnes de la ligne \a i1 de \a matrix
562 for (Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
563 Integer i2 = matrix_columns[jj2];
564 /*--------------------------------------------------------------
565 * Vérifie A_marker pour voir si le point i2 a déjà été
566 * visité. Les nouvelles entrées dans RAP ne proviennent que
567 * des points non marqués.
568 *--------------------------------------------------------------*/
569 if (a_marker[i2] != ic) {
570 a_marker[i2] = ic;
571 /*-----------------------------------------------------------
572 * Boucle sur les entrées de la ligne i2 de P.
573 *-----------------------------------------------------------*/
574 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
575 Integer i3 = right_matrix_columns[jj3];
576 /*--------------------------------------------------------
577 * Vérifie P_marker pour s'assurer que RAP_{ic,i3} n'a pas déjà
578 * été pris en compte. Si ce n'est pas le cas, le marque et incrémente
579 * le compteur.
580 *--------------------------------------------------------*/
581 if (p_marker[i3] < jj_row_begining) {
582 p_marker[i3] = jj_counter;
583 ++jj_counter;
584 }
585 }
586 }
587 }
588 }
589 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
590 }
591
592 Matrix new_matrix(nb_final_row, nb_final_row);
593 new_matrix.setRowsSize(new_matrix_rows_size);
594
595 //Integer* new_matrix_rows = new_matrix.rowsIndex();
596 Integer* ARCANE_RESTRICT new_matrix_columns = new_matrix.columns().data();
597 Real* ARCANE_RESTRICT new_matrix_values = new_matrix.values().data();
598
599 // Maintenant, remplit les coefficients de la matrice
600 p_marker.fill(-1);
601 a_marker.fill(-1);
602 jj_counter = 0;
603 for (Integer ic = 0; ic < nb_final_row; ++ic) {
604 // Ajoute la diagonale
605 p_marker[ic] = jj_counter;
606 jj_row_begining = jj_counter;
607 new_matrix_columns[jj_counter] = ic;
608 new_matrix_values[jj_counter] = 0.0;
609 ++jj_counter;
610 // Boucle sur les colonnes de la ligne \a ic de \a matrix
611 for (Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
612 Integer i1 = left_matrix_columns[jj1];
613 Real r_entry = left_matrix_values[jj1];
614
615 // Boucle sur les colonnes de la ligne \a i1 de \a matrix
616 for (Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
617 Integer i2 = matrix_columns[jj2];
618 Real r_a_product = r_entry * matrix_values[jj2];
619 /*--------------------------------------------------------------
620 * Vérifie A_marker pour voir si le point i2 a déjà été
621 * visité. Les nouvelles entrées dans RAP ne proviennent que
622 * des points non marqués.
623 *--------------------------------------------------------------*/
624 if (a_marker[i2] != ic) {
625 a_marker[i2] = ic;
626 /*-----------------------------------------------------------
627 * Boucle sur les entrées de la ligne i2 de P.
628 *-----------------------------------------------------------*/
629 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
630 Integer i3 = right_matrix_columns[jj3];
631 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
632 /*--------------------------------------------------------
633 * Vérifie P_marker pour s'assurer que RAP_{ic,i3} n'a pas déjà
634 * été pris en compte. Si ce n'est pas le cas, crée une nouvelle entrée.
635 * S'il l'est, ajoute la nouvelle contribution.
636 *--------------------------------------------------------*/
637 if (p_marker[i3] < jj_row_begining) {
638 p_marker[i3] = jj_counter;
639 new_matrix_values[jj_counter] = r_a_p_product;
640 new_matrix_columns[jj_counter] = i3;
641 ++jj_counter;
642 }
643 else {
644 new_matrix_values[p_marker[i3]] += r_a_p_product;
645 }
646 }
647 }
648 else {
649 /*--------------------------------------------------------------
650 * Si i2 a déjà été visité ( A_marker[12]=ic ) cela ne produit
651 * aucune nouvelle entrée dans RAP et peut simplement ajouter de nouvelles contributions.
652 *--------------------------------------------------------------*/
653 for (Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
654 Integer i3 = right_matrix_columns[jj3];
655 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
656 new_matrix_values[p_marker[i3]] += r_a_p_product;
657 }
658 }
659 }
660 }
661 }
662 return new_matrix;
663}
664
665/*---------------------------------------------------------------------------*/
666/*---------------------------------------------------------------------------*/
667
668enum
669{
670 TYPE_UNDEFINED = 0,
671 TYPE_COARSE = 1,
672 TYPE_FINE = 2,
673 TYPE_SPECIAL_FINE = 3
674};
675
676/*---------------------------------------------------------------------------*/
677/*---------------------------------------------------------------------------*/
678
679class AMGLevel
680: public TraceAccessor
681{
682 public:
683
684 AMGLevel(ITraceMng* tm, Integer level)
685 : TraceAccessor(tm)
686 , m_level(level)
687 , m_is_verbose(false)
688 {}
689 virtual ~AMGLevel() {}
690
691 public:
692
693 virtual void buildLevel(Matrix matrix, Real alpha);
694
695 public:
696
697 Matrix fineMatrix()
698 {
699 return m_fine_matrix;
700 }
701 Matrix coarseMatrix()
702 {
703 return m_coarse_matrix;
704 }
705 Matrix prolongationMatrix()
706 {
707 return m_prolongation_matrix;
708 }
709 Matrix restrictionMatrix()
710 {
711 return m_restriction_matrix;
712 }
713 Integer nbCoarsePoint() const
714 {
715 return m_coarse_matrix.nbRow();
716 }
717 Int32ConstArrayView pointsType() const
718 {
719 return m_points_type;
720 }
721 void printLevelInfo();
722
723 private:
724
725 Integer m_level;
726 Matrix m_fine_matrix;
727 Matrix m_coarse_matrix;
728 Matrix m_prolongation_matrix;
729 Matrix m_restriction_matrix;
730 Int32UniqueArray m_points_type;
731
732 bool m_is_verbose;
733
734 private:
735
736 void _buildCoarsePoints(Real alpha,
737 RealArray& rows_max_val,
739 IntegerArray& weak_depends);
740 void _buildInterpolationMatrix(RealConstArrayView rows_max_val,
742 IntegerArray& weak_depends);
743 void _printLevelInfo(Matrix matrix);
744};
745
746/*---------------------------------------------------------------------------*/
747/*---------------------------------------------------------------------------*/
748
749class AMG
750: public TraceAccessor
751{
752 public:
753
754 AMG(ITraceMng* tm)
755 : TraceAccessor(tm)
756 {}
757 ~AMG();
758
759 public:
760
761 void build(Matrix matrix);
762 void solve(const Vector& vector_b, Vector& vector_x);
763
764 private:
765
766 UniqueArray<AMGLevel*> m_levels;
767 Matrix m_matrix;
768
769 private:
770
771 void _solve(const Vector& vector_b, Vector& vector_x, Integer level);
772 void _relax(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
773 Integer nb_relax);
774 void _relax1(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
775 Integer nb_relax);
776 void _relaxJacobi(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
777 Real weight);
778 void _relaxGaussSeidel(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
779 Integer point_type, Int32ConstArrayView points_type);
780 void _relaxSymmetricGaussSeidel(const Matrix& matrix, const Vector& vector_b, Vector& vector_x);
781 void _printResidualInfo(const Matrix& matrix, const Vector& vector_b,
782 const Vector& vector_x);
783};
784
785/*---------------------------------------------------------------------------*/
786/*---------------------------------------------------------------------------*/
787
788AMG::
789~AMG()
790{
791 for (Integer i = 0; i < m_levels.size(); ++i)
792 delete m_levels[i];
793}
794
795/*---------------------------------------------------------------------------*/
796/*---------------------------------------------------------------------------*/
797
798void AMG::
799build(Matrix matrix)
800{
801 Matrix current_matrix = matrix;
802 m_matrix = matrix;
803 for (Integer i = 1; i < 100; ++i) {
804 AMGLevel* level = new AMGLevel(traceMng(), i);
805 level->buildLevel(current_matrix, 0.25);
806 m_levels.add(level);
807 Integer nb_coarse_point = level->nbCoarsePoint();
808 if (nb_coarse_point < 20)
809 break;
810 current_matrix = level->coarseMatrix();
811 }
812 //for( Integer i=0; i<m_levels.size(); ++i )
813 //m_levels[i]->printLevelInfo();
814}
815
816/*---------------------------------------------------------------------------*/
817/*---------------------------------------------------------------------------*/
818
819void AMG::
820solve(const Vector& vector_b, Vector& vector_x)
821{
822 //info() << "AMG::solve";
823 if (0) {
824 OStringStream ostr;
825 RealConstArrayView v_values(vector_b.values());
826 for (Integer i = 0; i < 20; ++i)
827 ostr() << "VECTOR_F_" << i << " = " << v_values[i] << " X=" << vector_x.values()[i] << '\n';
828 for (Integer i = 0; i < v_values.size(); ++i)
829 if (math::abs(v_values[i]) > 1e-5)
830 ostr() << "VECTOR_F_" << i << " = " << v_values[i] << '\n';
831 info() << "VECTOR_F\n"
832 << ostr.str();
833 }
834 //_printResidualInfo(m_matrix,vector_b,vector_x);
835 _solve(vector_b, vector_x, 0);
836 //info() << "END SOLVE";
837 //_printResidualInfo(m_matrix,vector_b,vector_x);
838 //info() << "END AMG::solve";
839 /*{
840 OStringStream ostr;
841 ostr() << "\nVECTOR_X ";
842 vector_x.dump(ostr());
843 info() << ostr.str();
844 }*/
845}
846
847/*---------------------------------------------------------------------------*/
848/*---------------------------------------------------------------------------*/
849
850void AMG::
851_relax1(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
852 Integer nb_relax)
853{
854 Vector r(vector_x.size());
855 MatrixOperation mat_op;
856 for (Integer i = 0; i < nb_relax; ++i) {
857 // r = b - A * x
858 mat_op.matrixVectorProduct(matrix, vector_x, r);
859 mat_op.negateVector(r);
860 mat_op.addVector(r, vector_b);
861
862 // x = x + r
863 mat_op.addVector(vector_x, r);
864 }
865}
866
867/*---------------------------------------------------------------------------*/
868/*---------------------------------------------------------------------------*/
869
870void AMG::
871_relax(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
872 Integer nb_relax)
873{
874 Real epsilon = 1.0e-10;
875 DiagonalPreconditioner p(matrix);
876 ConjugateGradientSolver solver;
877 solver.setMaxIteration(nb_relax);
878 //mat_op.matrixVectorProduct(restriction_matrix,vector_x,new_x);
879 //new_x.values().fill(0.0);
880
881 //OStringStream ostr;
882 //vector_x.dump(ostr());
883 //info() << " RELAX BEFORE VECTOR_X=" << ostr.str();
884
885 solver.solve(matrix, vector_b, vector_x, epsilon, &p);
886 //OStringStream ostr;
887 //ostr() << " COARSE_B=";
888 //new_b.dump(ostr());
889 //ostr() << "\nCOARSE_X=";
890 //new_x.dump(ostr());
891 //info() << "SOLVE COARSE MATRIX nb_iter=" << solver.nbIteration()
892 // << ostr.str();
893}
894
895/*---------------------------------------------------------------------------*/
896/*---------------------------------------------------------------------------*/
897
898void AMG::
899_relaxJacobi(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
900 Real weight)
901{
902 IntegerConstArrayView rows = matrix.rowsIndex();
903 IntegerConstArrayView columns = matrix.columns();
904 RealConstArrayView mat_values = matrix.values();
905
906 RealArrayView x_values = vector_x.values();
907 RealConstArrayView b_values = vector_b.values();
908
909 Integer nb_row = matrix.nbRow();
910 RealConstArrayView cx_values(vector_x.values());
911 RealUniqueArray tmp_values(cx_values);
912 if (0) {
913 Integer v = math::min(40, nb_row);
914 OStringStream ostr;
915 for (Integer i = (nb_row - 1); i > (nb_row - v); --i)
916 ostr() << "BEFORE_B=" << i << "=" << b_values[i] << " U=" << x_values[i] << " T=" << tmp_values[i] << '\n';
917 info() << "B = X=" << x_values.data() << " T=" << tmp_values.data() << "\n"
918 << ostr.str();
919 }
920 Real one_minus_weight = 1.0 - weight;
921 for (Integer row = 0; row < nb_row; ++row) {
922 Real diag = mat_values[rows[row]];
923 if (math::isZero(diag))
924 continue;
925 Real res = b_values[row];
926 for (Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
927 Integer col = columns[j];
928 res -= mat_values[j] * tmp_values[col];
929 }
930 x_values[row] *= one_minus_weight;
931 x_values[row] += (weight * res) / diag;
932 }
933 if (0) {
934 Integer v = math::min(40, nb_row);
935 OStringStream ostr;
936 for (Integer i = (nb_row - 1); i > (nb_row - v); --i)
937 ostr() << "AFTER_B=" << i << "=" << b_values[i] << " U=" << x_values[i] << '\n';
938 info() << "B\n"
939 << ostr.str();
940 }
941}
942
943/*---------------------------------------------------------------------------*/
944/*---------------------------------------------------------------------------*/
945
946void AMG::
947_relaxGaussSeidel(const Matrix& matrix, const Vector& vector_b, Vector& vector_x,
948 Integer point_type, Int32ConstArrayView points_type2)
949{
950#if 1
951 IntegerConstArrayView rows = matrix.rowsIndex();
952 IntegerConstArrayView columns = matrix.columns();
953 RealConstArrayView mat_values = matrix.values();
954
955 RealArrayView x_values = vector_x.values();
956 RealConstArrayView b_values = vector_b.values();
957 Int32ConstArrayView points_type = points_type2;
958#else
959 const Integer* rows = matrix.rowsIndex().data();
960 const Integer* columns = matrix.columns().data();
961 const Real* mat_values = matrix.values().data();
962
963 Real* ARCANE_RESTRICT x_values = vector_x.values().data();
964 const Real* b_values = vector_b.values().data();
965 const Integer* points_type = points_type2.data();
966#endif
967
968 Integer nb_row = matrix.nbRow();
969 if (0) {
970 info() << " RELAX nb_relax=" << " nb_row=" << nb_row
971 << " point_type=" << point_type;
972 Integer v = math::min(40, nb_row);
973 OStringStream ostr;
974 for (Integer i = (nb_row - 1); i > (nb_row - v); --i)
975 ostr() << "BEFORE_B=" << i << "=" << b_values[i] << " U=" << x_values[i] << '\n';
976 info() << "B\n"
977 << ostr.str();
978 }
979 for (Integer row = 0; row < nb_row; ++row) {
980 Real diag = mat_values[rows[row]];
981 if (points_type[row] != point_type || math::isZero(diag))
982 continue;
983 Real res = b_values[row];
984 for (Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
985 Integer col = columns[j];
986 res -= mat_values[j] * x_values[col];
987 }
988 x_values[row] = res / diag;
989 }
990 if (0) {
991 Integer v = math::min(40, nb_row);
992 OStringStream ostr;
993 for (Integer i = (nb_row - 1); i > (nb_row - v); --i)
994 ostr() << "AFTER_B=" << i << "=" << b_values[i] << " U=" << x_values[i] << '\n';
995 info() << "B\n"
996 << ostr.str();
997 }
998}
999
1000/*---------------------------------------------------------------------------*/
1001/*---------------------------------------------------------------------------*/
1002
1003void AMG::
1004_relaxSymmetricGaussSeidel(const Matrix& matrix, const Vector& vector_b, Vector& vector_x)
1005{
1006 IntegerConstArrayView rows = matrix.rowsIndex();
1007 IntegerConstArrayView columns = matrix.columns();
1008 RealConstArrayView mat_values = matrix.values();
1009
1010 RealArrayView x_values = vector_x.values();
1011 RealConstArrayView b_values = vector_b.values();
1012
1013 Integer nb_row = matrix.nbRow();
1014 //info() << " RELAX nb_relax=" << nb_relax << " nb_row=" << nb_row
1015 // << " point_type=" << point_type;
1016 for (Integer row = 0; row < nb_row; ++row) {
1017 Real diag = mat_values[rows[row]];
1018 if (math::isZero(diag))
1019 continue;
1020 Real res = b_values[row];
1021 for (Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1022 Integer col = columns[j];
1023 res -= mat_values[j] * x_values[col];
1024 }
1025 x_values[row] = res / diag;
1026 }
1027
1028 for (Integer row = nb_row - 1; row > -1; --row) {
1029 Real diag = mat_values[rows[row]];
1030 if (math::isZero(diag))
1031 continue;
1032 Real res = b_values[row];
1033 for (Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1034 Integer col = columns[j];
1035 res -= mat_values[j] * x_values[col];
1036 }
1037 x_values[row] = res / diag;
1038 }
1039}
1040
1041/*---------------------------------------------------------------------------*/
1042/*---------------------------------------------------------------------------*/
1043
1044void AMG::
1045_solve(const Vector& vector_b, Vector& vector_x, Integer level)
1046{
1047 AMGLevel* current_level = m_levels[level];
1048 Integer vector_size = vector_b.size();
1049 Integer nb_coarse = current_level->nbCoarsePoint();
1050 Matrix fine_matrix = current_level->fineMatrix();
1051 Matrix restriction_matrix = current_level->restrictionMatrix();
1052 Matrix coarse_matrix = current_level->coarseMatrix();
1053 Matrix prolongation_matrix = current_level->prolongationMatrix();
1054
1055 Integer new_nb_row = nb_coarse;
1056 Vector new_b(new_nb_row);
1057 Vector new_x(new_nb_row);
1058 Vector tmp(vector_size);
1059
1060 MatrixOperation mat_op;
1061
1062 bool is_final_level = (level + 1) == m_levels.size();
1063
1064 const bool use_gauss_seidel = false;
1065 Integer nb_relax1 = 2;
1066 Real jacobi_weight = 2.0 / 3.0;
1067 if (use_gauss_seidel) {
1068 for (Integer i = 0; i < nb_relax1; ++i)
1069 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1070 for (Integer i = 0; i < nb_relax1; ++i)
1071 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1072 }
1073 else {
1074 //info() << "BEFORE SMOOTH";
1075 //_printResidualInfo(fine_matrix,vector_b,vector_x);
1076 for (Integer i = 0; i < nb_relax1; ++i) {
1077 //_relaxSymmetricGaussSeidel(fine_matrix,vector_b,vector_x);
1078 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1079 }
1080 //info() << "AFTER SMOOTH";
1081 //_printResidualInfo(fine_matrix,vector_b,vector_x);
1082 //_relax(fine_matrix,vector_b,vector_x,nb_relax1);
1083 }
1084
1085 // Restreint le nouveau b à partir du b actuel
1086 // b(k+1) = I * (b(k) - A * x)
1087 {
1088 OStringStream ostr;
1089 mat_op.matrixVectorProduct(fine_matrix, vector_x, tmp);
1090 //ostr() << "\nCOARSE_B TMP(A*x) level=" << level << " ";
1091 //tmp.dump(ostr());
1092 mat_op.negateVector(tmp);
1093 mat_op.addVector(tmp, vector_b);
1094 //ostr() << "\nCOARSE_B TMP(b-A*x) level=" << level << " ";
1095 //tmp.dump(ostr());
1096 mat_op.matrixVectorProduct(restriction_matrix, tmp, new_b);
1097 //ostr() << "\nCOARSE_B level=" << level << " ";
1098 //new_b.dump(ostr());
1099 info() << ostr.str();
1100 }
1101
1102 //mat_op.matrixVectorProduct(transpose_prolongation_matrix,vector_x,tmp);
1103
1104 // Si le niveau final est atteint, résoudre la matrice.
1105 // Sinon, continuer en restreignant la matrice à nouveau
1106 if (is_final_level) {
1107
1108 //info() << " SOLVE FINAL LEVEL";
1109
1110 if (1) {
1111 DirectSolver ds;
1112 ds.solve(coarse_matrix, new_b, new_x);
1113 //_printResidualInfo(coarse_matrix,new_b,new_x);
1114 }
1115 else {
1116 Real epsilon = 1.0e-14;
1117 DiagonalPreconditioner p(coarse_matrix);
1118 ConjugateGradientSolver solver;
1119 //mat_op.matrixVectorProduct(restriction_matrix,vector_x,new_x);
1120 new_x.values().fill(0.0);
1121 solver.solve(coarse_matrix, new_b, new_x, epsilon, &p);
1122 OStringStream ostr;
1123 //ostr() << " COARSE_B=";
1124 //new_b.dump(ostr());
1125 //ostr() << "\nCOARSE_X=";
1126 //new_x.dump(ostr());
1127 //if (m_is_verbose)
1128 info() << "SOLVE COARSE MATRIX nb_iter=" << solver.nbIteration();
1129 // << ostr.str();
1130 //_printResidualInfo(coarse_matrix,new_b,new_x);
1131 }
1132 }
1133 else {
1134 new_x.values().fill(0.0);
1135 _solve(new_b, new_x, level + 1);
1136 }
1137
1138 // Interpole le nouveau x à partir de la solution trouvée
1139 // x(k) = x(k) + tI * x(k+1)
1140 mat_op.matrixVectorProduct(prolongation_matrix, new_x, tmp);
1141 mat_op.addVector(vector_x, tmp);
1142 /*{
1143 OStringStream ostr;
1144 vector_x.dump(ostr());
1145 info() << "NEW_X level=" << level << " X=" << ostr.str();
1146 _printResidualInfo(fine_matrix,vector_b,vector_x);
1147 }*/
1148
1149 // Relaxation de Richardson
1150 if (use_gauss_seidel) {
1151 for (Integer i = 0; i < nb_relax1; ++i)
1152 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1153 for (Integer i = 0; i < nb_relax1; ++i)
1154 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1155 }
1156 else {
1157 //info() << "BEFORE SMOOTH 2";
1158 //_printResidualInfo(fine_matrix,vector_b,vector_x);
1159 for (Integer i = 0; i < nb_relax1; ++i) {
1160 //_relaxSymmetricGaussSeidel(fine_matrix,vector_b,vector_x);
1161 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1162 }
1163 //info() << "AFTER SMOOTH 2";
1164 //_printResidualInfo(fine_matrix,vector_b,vector_x);
1165 //_relax(fine_matrix,vector_b,vector_x,nb_relax2);
1166 }
1167}
1168
1169/*---------------------------------------------------------------------------*/
1170/*---------------------------------------------------------------------------*/
1171
1172void AMG::
1173_printResidualInfo(const Matrix& a, const Vector& b, const Vector& x)
1174{
1175 OStringStream ostr;
1176 Vector tmp(b.size());
1177 // tmp = b - Ax
1178 MatrixOperation mat_op;
1179 mat_op.matrixVectorProduct(a, x, tmp);
1180 //ostr() << "\nAX=";
1181 //tmp.dump(ostr());
1182 mat_op.negateVector(tmp);
1183 mat_op.addVector(tmp, b);
1184 Real r = mat_op.dot(tmp);
1185 if (0) {
1186 Integer v = math::min(10, tmp.size());
1187 for (Integer i = 0; i < v; ++i)
1188 info() << "R_" << i << " = " << tmp.values()[i];
1189 }
1190 info() << " AMG_RESIDUAL_NORM=" << r << " sqrt=" << math::sqrt(r);
1191
1192 //ostr() << "\nR=";
1193 //tmp.dump(ostr());
1194 //info() << " AMG_RESIDUAL_NORM=" << r << " AMG_RESIDUAL=" << ostr.str();
1195}
1196
1197/*---------------------------------------------------------------------------*/
1198/*---------------------------------------------------------------------------*/
1199
1200/*---------------------------------------------------------------------------*/
1201/*---------------------------------------------------------------------------*/
1202
1203class PointInfo
1204{
1205 public:
1206
1207 PointInfo()
1208 : m_lambda(0)
1209 , m_index(0)
1210 {}
1211 PointInfo(Integer lambda, Integer index)
1212 : m_lambda(lambda)
1213 , m_index(index)
1214 {}
1215 Integer m_lambda;
1216 Integer m_index;
1221 bool operator<(const PointInfo& rhs) const
1222 {
1223 if (m_lambda == rhs.m_lambda)
1224 return m_index < rhs.m_index;
1225 return (m_lambda > rhs.m_lambda);
1226 }
1227};
1228
1229/*---------------------------------------------------------------------------*/
1230/*---------------------------------------------------------------------------*/
1231
1232void AMGLevel::
1233printLevelInfo()
1234{
1235 _printLevelInfo(m_prolongation_matrix);
1236 _printLevelInfo(m_coarse_matrix);
1237}
1238
1239void AMGLevel::
1240_printLevelInfo(Matrix matrix)
1241{
1242 OStringStream ostr;
1243 Integer nb_row = matrix.nbRow();
1244 Integer nb_column = matrix.nbColumn();
1245
1246 IntegerConstArrayView rows = matrix.rowsIndex();
1247 //IntegerConstArrayView columns = matrix.columns();
1248 RealConstArrayView values = matrix.values();
1249 Integer nb_value = values.size();
1250
1251 Real max_val = 0.0;
1252 Real min_val = 0.0;
1253 if (nb_value > 0) {
1254 max_val = values[0];
1255 min_val = values[0];
1256 }
1257
1258 Real max_row_sum = 0.0;
1259 Real min_row_sum = 0.0;
1260 for (Integer row = 0; row < nb_row; ++row) {
1261 Real row_sum = 0.0;
1262 for (Integer z = rows[row], zs = rows[row + 1]; z < zs; ++z) {
1263 //Integer col = columns[z];
1264 Real v = values[z];
1265 if (v > max_val)
1266 max_val = v;
1267 if (v < min_val)
1268 min_val = v;
1269 row_sum += v;
1270 }
1271 if (row == 0) {
1272 max_row_sum = row_sum;
1273 min_row_sum = row_sum;
1274 }
1275 if (row_sum > max_row_sum)
1276 max_row_sum = row_sum;
1277 if (row_sum < max_row_sum)
1278 min_row_sum = row_sum;
1279 }
1280
1281 Real sparsity = ((Real)nb_value) / ((Real)nb_row * (Real)nb_column);
1282
1283 ostr() << "level=" << m_level
1284 << " nb_row=" << nb_row
1285 << " nb_col=" << nb_column
1286 << " nb_nonzero=" << nb_value
1287 << " sparsity=" << sparsity
1288 << " min=" << min_val
1289 << " max=" << max_val
1290 << " min_row=" << min_row_sum
1291 << " max_row=" << max_row_sum;
1292
1293 info() << "INFO: " << ostr.str();
1294}
1295
1296/*---------------------------------------------------------------------------*/
1297/*---------------------------------------------------------------------------*/
1298
1299void AMGLevel::
1300_buildCoarsePoints(Real alpha,
1301 RealArray& rows_max_val,
1302 UniqueArray<SharedArray<Integer>>& depends,
1303 IntegerArray& weak_depends)
1304{
1305 IntegerConstArrayView rows_index = m_fine_matrix.rowsIndex();
1306 IntegerConstArrayView columns = m_fine_matrix.columns();
1307 RealConstArrayView mat_values = m_fine_matrix.values();
1308 Integer nb_row = m_fine_matrix.nbRow();
1309
1310 Int32UniqueArray lambdas(nb_row);
1311 lambdas.fill(0);
1312 UniqueArray<SharedArray<Integer>> influences(nb_row);
1313 depends.resize(nb_row);
1314 //UniqueArray<IntegerUniqueArray> weak_depends(nb_row);
1315 m_points_type.resize(nb_row);
1316 m_points_type.fill(TYPE_UNDEFINED);
1317
1318 weak_depends.resize(mat_values.size());
1319 weak_depends.fill(0);
1320
1321 const bool type_hypre = true;
1322 // Valeurs de chaque ligne qui influence
1323 rows_max_val.resize(nb_row);
1324 for (Integer row = 0; row < nb_row; ++row) {
1325 Real max_val = 0.0;
1326 Real min_val = 0.0;
1327 Real diag_val = mat_values[rows_index[row]];
1328 // Cherche le max (en valeur absolue) de la colonne, autre que la diagonale
1329 for (Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1330 //Real mv = math::abs(mat_values[z]);
1331 Real mv = mat_values[z];
1332 if (!type_hypre)
1333 mv = math::abs(mv);
1334 if (mv > max_val)
1335 max_val = mv;
1336 if (mv < min_val)
1337 min_val = mv;
1338 }
1339 // Prend tous les éléments supérieurs à alpha * max_val
1340 //rows_max_val[row] = max_val * alpha;
1341 if (type_hypre) {
1342 if (diag_val < 0.0)
1343 rows_max_val[row] = max_val * alpha;
1344 else
1345 rows_max_val[row] = min_val * alpha;
1346 }
1347 else
1348 rows_max_val[row] = max_val * alpha;
1349 }
1350
1351 for (Integer row = 0; row < nb_row; ++row) {
1352 // Prend tous les éléments supérieurs à max_val
1353 Real max_val = rows_max_val[row];
1354 Real diag_val = mat_values[rows_index[row]];
1355 for (Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1356 //Real mv = math::abs(mat_values[z]);
1357 Real mv = mat_values[z];
1358 if (type_hypre) {
1359 if (diag_val < 0.0) {
1360 if (mv > max_val) {
1361 Integer column = columns[z];
1362 if (m_is_verbose)
1363 info() << " ADD INFLUENCE: ROW=" << row << " COL=" << column;
1364 ++lambdas[column];
1365 depends[row].add(column);
1366 influences[column].add(row);
1367 weak_depends[z] = 2;
1368 }
1369 else
1370 weak_depends[z] = 1;
1371 }
1372 else {
1373 if (mv < max_val) {
1374 Integer column = columns[z];
1375 if (m_is_verbose)
1376 info() << " ADD INFLUENCE: ROW=" << row << " COL=" << column;
1377 ++lambdas[column];
1378 depends[row].add(column);
1379 influences[column].add(row);
1380 weak_depends[z] = 2;
1381 }
1382 else
1383 weak_depends[z] = 1;
1384 }
1385 }
1386 else {
1387 if (math::abs(mv) > max_val) {
1388 Integer column = columns[z];
1389 if (m_is_verbose)
1390 info() << " ADD INFLUENCE: ROW=" << row << " COL=" << column;
1391 ++lambdas[column];
1392 depends[row].add(column);
1393 influences[column].add(row);
1394 weak_depends[z] = 2;
1395 }
1396 else {
1397 weak_depends[z] = 1;
1398 }
1399 }
1400 //else
1401 //weak_depends[row].add(column);
1402 }
1403 }
1404
1405 if (0) {
1406 OStringStream ostr;
1407 Integer index = 0;
1408 int n = math::min(nb_row, 800);
1409 ostr() << "GRAPH\n";
1410 for (Integer i = 0; i < n; ++i) {
1411 ostr() << " GRAPH I=" << i << " ";
1412 for (Integer j = 0; j < depends[i].size(); ++j) {
1413 ++index;
1414 ostr() << " " << depends[i][j];
1415 }
1416 ostr() << " index=" << index << '\n';
1417 }
1418 ostr() << "\n MAXTRIX\n";
1419 index = 0;
1420 for (Integer i = 0; i < n; ++i) {
1421 ostr() << "MATRIX I=" << i << " ";
1422 for (Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1423 ++index;
1424 ostr() << " " << columns[j] << " " << mat_values[j];
1425 }
1426 ostr() << " index=" << index << '\n';
1427 }
1428 info() << ostr.str();
1429 }
1430
1431 Integer nb_done = 0;
1432 Integer nb_iter = 0;
1433 Integer nb_fine = 0;
1434 Integer nb_coarse = 0;
1435 m_is_verbose = false;
1436 {
1437 // Marque comme point fin tous les points n'ayant aucune dépendance
1438 for (Integer row = 0; row < nb_row; ++row) {
1439 if (depends[row].size() == 0) {
1440 m_points_type[row] = TYPE_FINE;
1441 ++nb_done;
1442 if (m_is_verbose)
1443 info() << "FIRST MARK FINE point=" << row;
1444 }
1445 }
1446
1447 // Les points qui n'influencent personne sont forcément fins.
1448 for (Integer row = 0; row < nb_row; ++row) {
1449 if (m_points_type[row] != TYPE_FINE && lambdas[row] <= 0) {
1450 m_points_type[row] = TYPE_FINE;
1451 ++nb_done;
1452 if (m_is_verbose)
1453 info() << "INIT MARK FINE NULL MEASURE point=" << row << " measure=" << lambdas[row];
1454 for (Integer j = 0, js = depends[row].size(); j < js; ++j) {
1455 Integer col = depends[row][j];
1456 if (m_points_type[col] != TYPE_FINE)
1457 if (col < row) {
1458 ++lambdas[col];
1459 if (m_is_verbose)
1460 printf("ADD MEASURE NULL point=%d measure=%d\n", (int)col, lambdas[col]);
1461 }
1462 }
1463 }
1464 }
1465
1466 typedef std::set<PointInfo> PointSet;
1467 PointSet undefined_points;
1468 for (Integer i = 0; i < nb_row; ++i) {
1469 if (m_points_type[i] == TYPE_UNDEFINED)
1470 undefined_points.insert(PointInfo(lambdas[i], i));
1471 }
1472
1473 while (nb_done < nb_row && nb_iter < 100000) {
1474 ++nb_iter;
1475 //for( PointSet::const_iterator i(undefined_points.data()); i!=undefined_points.end(); ++i ){
1476 //info() << " SET index=" << i->m_index << " value=" << i->m_lambda;
1477 //}
1478 // Prend le lambda max et note le point C
1479 //Integer max_value = -1;
1480 //Integer max_value_index = -1;
1481 //for( Integer i=0; i<nb_row; ++i ){
1482 //if (lambdas[i]>max_value && points_type[i]==TYPE_UNDEFINED){
1483 // max_value = lambdas[i];
1484 // max_value_index = i;
1485 //}
1486 //}
1487 if (undefined_points.empty())
1488 fatal() << "Undefined points is empty";
1489 PointSet::iterator max_point = undefined_points.begin();
1490 Integer max_value_index = max_point->m_index;
1491 Integer max_value = max_point->m_lambda;
1492 m_points_type[max_value_index] = TYPE_COARSE;
1493 ++nb_done;
1494 ++nb_coarse;
1495 undefined_points.erase(max_point);
1496 if (m_is_verbose)
1497 std::cout << "MARK COARSE point=" << max_value_index
1498 << " measure=" << max_value
1499 << " left=" << (nb_row - nb_done)
1500 << "\n";
1501 IntegerConstArrayView point_influences = influences[max_value_index];
1502 for (Integer i = 0, is = point_influences.size(); i < is; ++i) {
1503 //for( Integer i=0, is=depends[max_value_index].size(); i<is; ++i ){
1504 Integer pt = point_influences[i];
1505 //Integer pt = depends[max_value_index][i];
1506 if (m_points_type[pt] == TYPE_UNDEFINED) {
1507 m_points_type[pt] = TYPE_FINE;
1508 ++nb_done;
1509 ++nb_fine;
1510 undefined_points.erase(PointInfo(lambdas[pt], pt));
1511 if (m_is_verbose)
1512 std::cout << "MARK FINE point=" << pt
1513 << " measure=" << lambdas[pt]
1514 << " left=" << (nb_row - nb_done)
1515 << "\n";
1516 for (Integer z = 0, zs = depends[pt].size(); z < zs; ++z) {
1517 Integer pt2 = depends[pt][z];
1518 //for( Integer z=0, zs=point_influences.size(); z<zs; ++z ){
1519 //Integer pt2 = point_influences[z];
1520 if (m_points_type[pt2] == TYPE_UNDEFINED) {
1521 undefined_points.erase(PointInfo(lambdas[pt2], pt2));
1522 ++lambdas[pt2];
1523 undefined_points.insert(PointInfo(lambdas[pt2], pt2));
1524 }
1525 }
1526 }
1527 }
1528 for (Integer i = 0, is = depends[max_value_index].size(); i < is; ++i) {
1529 Integer pt3 = depends[max_value_index][i];
1530 if (m_points_type[pt3] == TYPE_UNDEFINED) {
1531 undefined_points.erase(PointInfo(lambdas[pt3], pt3));
1532 Integer n = lambdas[pt3];
1533 if (n < 0)
1534 info() << "N < 0";
1535 --lambdas[pt3];
1536 undefined_points.insert(PointInfo(lambdas[pt3], pt3));
1537 }
1538 }
1539 if (m_is_verbose)
1540 info() << "LAMBDA MAX = " << max_value << " index=" << max_value_index << " nb_done=" << nb_done;
1541 }
1542 }
1543
1544 if (m_is_verbose)
1545 info() << "NB ROW=" << nb_row << " nb_done=" << nb_done << " nb_fine=" << nb_fine
1546 << " nb_coarse=" << nb_coarse << " nb_iter=" << nb_iter;
1547 if (nb_done != nb_row)
1548 fatal() << "Can not find all COARSE or FINE points nb_done=" << nb_done << " nb_point=" << nb_row;
1549
1550 {
1551 //Maintenant, nous devons nous assurer que deux connexions F-F ont au moins un
1552 // point C commun. Sinon, le premier F est changé en C
1553 //info() << "SECOND PASS !!!";
1554 Int32UniqueArray points_marker(nb_row);
1555 points_marker.fill(-1);
1556 Integer ci_tilde_mark = -1;
1557 Integer ci_tilde = -1;
1558 bool C_i_nonempty = false;
1559 for (Integer row = 0; row < nb_row; ++row) {
1560 if ((ci_tilde_mark |= row))
1561 ci_tilde = -1;
1562 if (m_points_type[row] == TYPE_FINE) {
1563 for (Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1564 //for( Integer z=rows_index[row] ,zs=rows_index[row+1]; z<zs; ++z ){
1565 //Integer col = columns[z];
1566 Integer col = depends[row][z];
1567 if (m_points_type[col] == TYPE_COARSE)
1568 points_marker[col] = row;
1569 }
1570 for (Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1571 //for( Integer z=rows_index[row] ,zs=rows_index[row+1]; z<zs; ++z ){
1572 //Integer col = columns[z];
1573 Integer col = depends[row][z];
1574 if (m_points_type[col] == TYPE_FINE) {
1575 bool set_empty = true;
1576 for (Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1577 //for( Integer z2=rows_index[row] ,zs2=rows_index[row+1]; z2<zs2; ++z2 ){
1578 //Integer col2 = columns[z2];
1579 Integer col2 = depends[row][z2];
1580 if (points_marker[col2] == row) {
1581 set_empty = false;
1582 break;
1583 }
1584 }
1585 if (set_empty) {
1586 if (C_i_nonempty) {
1587 m_points_type[row] = TYPE_COARSE;
1588 //printf("SECOND PASS MARK COARSE1 point=%d\n",row);
1589 if (ci_tilde > -1) {
1590 m_points_type[ci_tilde] = TYPE_FINE;
1591 if (m_is_verbose)
1592 printf("SECOND PASS MARK FINE point=%d\n", ci_tilde);
1593 ci_tilde = -1;
1594 }
1595 C_i_nonempty = false;
1596 }
1597 else {
1598 ci_tilde = col;
1599 ci_tilde_mark = row;
1600 m_points_type[col] = TYPE_COARSE;
1601 if (m_is_verbose)
1602 printf("SECOND PASS MARK COARSE2 point=%d\n", col);
1603 C_i_nonempty = true;
1604 --row;
1605 break;
1606 }
1607 }
1608 }
1609 }
1610 }
1611 }
1612 }
1613
1614 if (0) {
1615 //Lecture depuis Hypre
1616 static int matrix_number = 0;
1617 ++matrix_number;
1618 info() << "READ HYPRE CF_marker n=" << matrix_number;
1619 StringBuilder fname("CF_marker-");
1620 fname += matrix_number;
1621 std::ifstream ifile(fname.toString().localstr());
1622 Integer nb_read_point = 0;
1623 ifile >> std::ws >> nb_read_point >> std::ws;
1624 if (nb_read_point != nb_row)
1625 fatal() << "Bad number of points for reading Hypre CF_marker read=" << nb_read_point
1626 << " expected=" << nb_row << " matrix_number=" << matrix_number;
1627 nb_coarse = 0;
1628 nb_fine = 0;
1629 for (Integer i = 0; i < nb_row; ++i) {
1630 int pt = 0;
1631 ifile >> pt;
1632 if (!ifile)
1633 fatal() << "Can not read marker point number=" << i;
1634 if (pt == (-1) || pt == (-3)) {
1635 m_points_type[i] = TYPE_FINE;
1636 ++nb_fine;
1637 }
1638 else if (pt == 1) {
1639 m_points_type[i] = TYPE_COARSE;
1640 ++nb_coarse;
1641 }
1642 else
1643 fatal() << "Bad value read=" << pt << " expected 1 or -1";
1644 }
1645 }
1646
1647 // Vérifie que tous les points fins ont au moins un point d'influence
1648 nb_coarse = 0;
1649 for (Integer i = 0; i < nb_row; ++i) {
1650 if (m_points_type[i] == TYPE_UNDEFINED)
1651 fatal() << " Point " << i << " is undefined";
1652 if (m_points_type[i] != TYPE_FINE) {
1653 ++nb_coarse;
1654 continue;
1655 }
1656#if 0
1657 bool is_ok = false;
1658 //info() << "CHECK POINT point=" << i
1659 // << " depend_size=" << depends[i].size();
1660 for( Integer z=0, zs=depends[i].size(); z<zs; ++z ){
1661 if (m_points_type[depends[i][z]]==TYPE_COARSE){
1662 is_ok = true;
1663 break;
1664 }
1665 }
1666 //if (!is_ok)
1667 // fatal() << " Point " << i << " has no coarse point";
1668#endif
1669 }
1670
1671 if (m_is_verbose) {
1672 OStringStream ostr;
1673 for (Integer i = 0; i < nb_row; ++i) {
1674 ostr() << " POINT i=" << i << " type=" << m_points_type[i] << " depends=";
1675 for (Integer j = 0, js = depends[i].size(); j < js; ++j)
1676 ostr() << depends[i][j] << ' ';
1677 ostr() << '\n';
1678 }
1679 info() << ostr.str();
1680 }
1681
1682 nb_fine = nb_row - nb_coarse;
1683 Integer graph_size = 0;
1684 for (Integer i = 0; i < nb_row; ++i)
1685 graph_size += depends[i].size();
1686
1687 info() << " NB COARSE=" << nb_coarse << " NB FINE=" << nb_fine
1688 << " MAXTRIX NON_ZEROS=" << m_fine_matrix.rowsIndex()[nb_row]
1689 << " GRAPH_SIZE=" << graph_size;
1690 bool dump_matrix = false;
1691 bool has_error = false;
1692 if (nb_fine == 0 || graph_size == 0) {
1693 has_error = true;
1694 dump_matrix = true;
1695 }
1696
1697 if (dump_matrix) {
1698 OStringStream ostr;
1699 Integer index = 0;
1700 int n = math::min(nb_row, 40);
1701 if (0) {
1702 ostr() << "GRAPH\n";
1703 for (Integer i = 0; i < n; ++i) {
1704 ostr() << " GRAPH I=" << i << " ";
1705 for (Integer j = 0; j < depends[i].size(); ++j) {
1706 ++index;
1707 ostr() << " " << depends[i][j];
1708 }
1709 ostr() << " index=" << index << '\n';
1710 }
1711 }
1712 ostr() << "\n MAXTRIX\n";
1713 index = 0;
1714 for (Integer i = 0; i < n; ++i) {
1715 ostr() << "MATRIX I=" << i << " ";
1716 for (Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1717 ++index;
1718 ostr() << " " << columns[j] << " " << mat_values[j];
1719 }
1720 ostr() << " index=" << index << '\n';
1721 }
1722 info() << ostr.str();
1723 }
1724 if (has_error)
1725 throw FatalErrorException("AMGLevel::_buildCoarsePoints");
1726}
1727
1728/*---------------------------------------------------------------------------*/
1729/*---------------------------------------------------------------------------*/
1730
1731void AMGLevel::
1732buildLevel(Matrix matrix, Real alpha)
1733{
1734 //Integer nb_row = matrix.nbRow();
1735 //if (nb_row<20)
1736 //return;
1737
1738 m_fine_matrix = matrix;
1739
1740 //bool is_verbose = false;
1741 matrix.sortDiagonale();
1742
1743 IntegerUniqueArray points_type;
1744 RealUniqueArray rows_max_val;
1745 UniqueArray<SharedArray<Integer>> depends;
1746 IntegerUniqueArray weak_depends;
1747
1748 _buildCoarsePoints(alpha, rows_max_val, depends, weak_depends);
1749 _buildInterpolationMatrix(rows_max_val, depends, weak_depends);
1750}
1751
1752/*---------------------------------------------------------------------------*/
1753/*---------------------------------------------------------------------------*/
1754
1755void AMGLevel::
1756_buildInterpolationMatrix(RealConstArrayView rows_max_val,
1757 UniqueArray<SharedArray<Integer>>& depends,
1758 IntegerArray& weak_depends)
1759{
1760 ARCANE_UNUSED(rows_max_val);
1761
1762 IntegerConstArrayView rows_index = m_fine_matrix.rowsIndex();
1763 IntegerConstArrayView columns = m_fine_matrix.columns();
1764 RealConstArrayView mat_values = m_fine_matrix.values();
1765 Integer nb_row = m_fine_matrix.nbRow();
1766
1767 IntegerUniqueArray points_in_coarse(nb_row);
1768 points_in_coarse.fill(-1);
1769 Integer nb_coarse = 0;
1770 {
1771 //Integer index = 0;
1772 nb_coarse = 0;
1773 for (Integer i = 0; i < nb_row; ++i) {
1774 if (m_points_type[i] == TYPE_COARSE) {
1775 points_in_coarse[i] = nb_coarse;
1776 ++nb_coarse;
1777 }
1778 }
1779 }
1780 bool type_hypre = true;
1781
1782 // Maintenant,calcule les éléments de la matrice d'influence
1783 IntegerUniqueArray prolongation_matrix_columns;
1784 RealUniqueArray prolongation_matrix_values;
1785 IntegerUniqueArray prolongation_matrix_rows_size(nb_row);
1786
1787 for (Integer row = 0; row < nb_row; ++row) {
1788 Integer nb_column = 0;
1789 if (m_points_type[row] == TYPE_FINE) {
1790 Real weak_connect_sum = 0.0;
1791 //Real max_value = rows_max_val[row];
1792 Real diag = mat_values[rows_index[row]];
1793 Real sign = 1.0;
1794 if (diag < 0.0)
1795 sign = -1.0;
1796 for (Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1797 //Integer column = columns[z];
1798 if (weak_depends[z] == 1) {
1799 Real mv = mat_values[z];
1800 if (type_hypre)
1801 weak_connect_sum += mv;
1802 else {
1803 //weak_connect_sum += math::abs(mv);
1804 weak_connect_sum += mv;
1805 }
1806 //if (m_is_verbose || row<=5)
1807 //info() << "ADD WEAK_SUM mv=" << mv << " sum=" << weak_connect_sum
1808 // << " row=" << row << " column=" << column;
1809 }
1810 }
1811 if (m_is_verbose)
1812 info() << "ROW row=" << row << " weak_connect_sum=" << weak_connect_sum;
1813 //for( Integer z=0, zs=depends[row].size(); z<zs; ++ z){
1814 //Integer j_column = dependcolumns[z];
1815 for (Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1816 Integer j_column = columns[z];
1817 if (m_points_type[j_column] != TYPE_COARSE)
1818 continue;
1819 if (weak_depends[z] != 2)
1820 continue;
1821 Real num_add = 0.0;
1822 Real mv = mat_values[z];
1823 for (Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1824 Integer k_column = depends[row][z2];
1825 //if (m_is_verbose || row<=5)
1826 //info() << "CHECK K_COLUMN row=" << row << " col=" << k_column << " val=" << mv;
1827 if (m_points_type[k_column] != TYPE_FINE)
1828 continue;
1829 Real sum_coarse = 0.0;
1830 //if (m_is_verbose || row<=5)
1831 //info() << "CHECK COARSE row=" << row;
1832 //for( Integer z3=rows_index[row]+1 ,zs3=rows_index[row+1]; z3<zs3; ++z3 ){
1833 //Integer m_column = columns[z3];
1834 for (Integer z3 = 0, zs3 = depends[row].size(); z3 < zs3; ++z3) {
1835 Integer m_column = depends[row][z3];
1836 //if (m_is_verbose || row<=5)
1837 //info() << "CHECK COLUMN column=" << m_column;
1838 if (m_points_type[m_column] == TYPE_COARSE) {
1839 Real w = m_fine_matrix.value(k_column, m_column);
1840 //if (m_is_verbose || row<=5)
1841 //info() << "ADD SUM k=" << k_column << " m="<< m_column << " w=" << w;
1842 //if (math::isZero(w)){
1843 //fatal() << "WEIGHT is null k=" << k_column << " m=" << m_column << " row=" << row
1844 // << " j=" << j_column;
1845 //}
1846 if (type_hypre) {
1847 if (w * sign < 0.0)
1848 sum_coarse += w;
1849 }
1850 else {
1851 sum_coarse += math::abs(w);
1852 //if (w*sign<0.0)
1853 //sum_coarse += w;
1854 }
1855 }
1856 }
1857 Real to_add = 0.0;
1858 if (!math::isZero(sum_coarse)) {
1859 Real akj = m_fine_matrix.value(k_column, j_column);
1860 bool do_add = false;
1861 if (type_hypre) {
1862 if ((akj * sign) < 0.0)
1863 do_add = true;
1864 }
1865 else {
1866 //if ((akj*sign)<0.0)
1867 //do_add = true;
1868 akj = math::abs(akj);
1869 do_add = true;
1870 }
1871 if (do_add)
1872 //fatal() << "SUM_WEIGHT is null k=" << k_column << " row=" << row << " j=" << j_column;
1873 to_add = math::divide(m_fine_matrix.value(row, k_column) * akj, sum_coarse);
1874 }
1875 num_add += to_add;
1876 }
1877 Real weight = -(mv + num_add) / (diag + weak_connect_sum);
1878 Integer new_column = points_in_coarse[j_column];
1879 //if (m_is_verbose || row<=5)
1880 //info() << " ** WEIGHT row=" << row << " j_column=" << j_column
1881 // << " weight=" << weight << " num_add=" << num_add << " mv=" << mv << " new_column=" << new_column
1882 // << " diag=" << diag << " weak_sum=" << weak_connect_sum
1883 // << " diag+wk=" << (diag+weak_connect_sum);
1884 if (new_column >= nb_coarse || new_column < 0)
1885 fatal() << " BAD COLUMN for fine point column=" << new_column << " nb=" << nb_coarse
1886 << " jcolumn=" << j_column;
1887 prolongation_matrix_columns.add(new_column);
1888 prolongation_matrix_values.add(weight);
1889 ++nb_column;
1890 }
1891 }
1892 else {
1893 // Point grossier, met 1.0 dans la diagonale
1894 Integer column = points_in_coarse[row];
1895 if (column >= nb_coarse || column < 0)
1896 fatal() << " BAD COLUMN for coarse point j=" << column << " nb=" << nb_coarse
1897 << " row=" << row;
1898 prolongation_matrix_columns.add(column);
1899 prolongation_matrix_values.add(1.0);
1900 ++nb_column;
1901 }
1902 prolongation_matrix_rows_size[row] = nb_column;
1903 }
1904
1905 m_prolongation_matrix = Matrix(nb_row, nb_coarse);
1906 m_prolongation_matrix.setRowsSize(prolongation_matrix_rows_size);
1907 //info() << "PROLONGATION_MATRIX_SIZE=" << m_prolongation_matrix.rowsIndex()[nb_row];
1908 m_prolongation_matrix.setValues(prolongation_matrix_columns, prolongation_matrix_values);
1909
1910 if (0) {
1911 OStringStream ostr;
1912 Integer index = 0;
1913 int n = math::min(nb_row, 50);
1914 IntegerConstArrayView p_rows(m_prolongation_matrix.rowsIndex());
1915 IntegerConstArrayView p_columns(m_prolongation_matrix.columns());
1916 RealConstArrayView p_values(m_prolongation_matrix.values());
1917 for (Integer i = 0; i < n; ++i) {
1918 ostr() << "PROLONG I=" << i << " ";
1919 for (Integer j = p_rows[i]; j < p_rows[i + 1]; ++j) {
1920 ++index;
1921 ostr() << " " << p_columns[j] << " " << p_values[j];
1922 }
1923 ostr() << " index=" << index << '\n';
1924 }
1925 info() << "PROLONG\n"
1926 << ostr.str();
1927 }
1928
1929 MatrixOperation2 mat_op2;
1930 if (1)
1931 m_restriction_matrix = mat_op2.transposeFast(m_prolongation_matrix);
1932 else
1933 m_restriction_matrix = mat_op2.transpose(m_prolongation_matrix);
1934 if (m_is_verbose) {
1935 OStringStream ostr;
1936 ostr() << "PROLONGATION_MATRIX ";
1937 m_prolongation_matrix.dump(ostr());
1938 ostr() << '\n';
1939 ostr() << "RESTRICTION_MATRIX ";
1940 m_restriction_matrix.dump(ostr());
1941 info() << ostr.str();
1942 }
1943 //info() << " ** TOTAL SUM=" << total_sum;
1944 // Calcule la matrice grossiere Ak+1 = I * Ak * tI
1945 //MatrixOperation mat_op;
1946 const bool old = false;
1947 if (old) {
1948 Matrix n1 = mat_op2.matrixMatrixProductFast(m_fine_matrix, m_prolongation_matrix);
1949 if (m_is_verbose) {
1950 OStringStream ostr;
1951 n1.dump(ostr());
1952 info() << "N1_MATRIX " << ostr.str();
1953 }
1954 m_coarse_matrix = mat_op2.matrixMatrixProductFast(m_restriction_matrix, n1);
1955 }
1956 else
1957 m_coarse_matrix = mat_op2.applyGalerkinOperator2(m_restriction_matrix, m_fine_matrix, m_prolongation_matrix);
1958 if (m_is_verbose) {
1959 OStringStream ostr;
1960 m_coarse_matrix.dump(ostr());
1961 info() << "level= " << m_level << " COARSE_MATRIX=" << ostr.str();
1962 }
1963}
1964
1965/*---------------------------------------------------------------------------*/
1966/*---------------------------------------------------------------------------*/
1967
1968AMGPreconditioner::
1969~AMGPreconditioner()
1970{
1971 delete m_amg;
1972}
1973
1974/*---------------------------------------------------------------------------*/
1975/*---------------------------------------------------------------------------*/
1976
1977void AMGPreconditioner::
1978apply(Vector& out_vec, const Vector& vec)
1979{
1980 m_amg->solve(vec, out_vec);
1981}
1982
1983/*---------------------------------------------------------------------------*/
1984/*---------------------------------------------------------------------------*/
1985
1986void AMGPreconditioner::
1987build(const Matrix& matrix)
1988{
1989 delete m_amg;
1990 m_amg = new AMG(m_trace_mng);
1991 m_amg->build(matrix);
1992}
1993
1994/*---------------------------------------------------------------------------*/
1995/*---------------------------------------------------------------------------*/
1996
1997/*---------------------------------------------------------------------------*/
1998/*---------------------------------------------------------------------------*/
1999
2000AMGSolver::
2001~AMGSolver()
2002{
2003 delete m_amg;
2004}
2005
2006/*---------------------------------------------------------------------------*/
2007/*---------------------------------------------------------------------------*/
2008
2009void AMGSolver::
2010build(const Matrix& matrix)
2011{
2012 delete m_amg;
2013 m_amg = new AMG(m_trace_mng);
2014 m_amg->build(matrix);
2015}
2016
2017/*---------------------------------------------------------------------------*/
2018/*---------------------------------------------------------------------------*/
2019
2020void AMGSolver::
2021solve(const Vector& vector_b, Vector& vector_x)
2022{
2023 m_amg->solve(vector_b, vector_x);
2024}
2025
2026/*---------------------------------------------------------------------------*/
2027/*---------------------------------------------------------------------------*/
2028
2029} // namespace Arcane::MatVec
2030
2031/*---------------------------------------------------------------------------*/
2032/*---------------------------------------------------------------------------*/
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void fill(const T &o) noexcept
Remplit le tableau avec la valeur o.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Interface du gestionnaire de traces.
Matrice avec stockage CSR.
bool operator<(const PointInfo &rhs) const
Definition AMG.cc:1221
Vecteur d'algèbre linéraire.
Matrix class, to be used by user.
Vecteur 1D de données avec sémantique par référence.
TraceAccessor(ITraceMng *m)
Construit un accesseur via le gestionnaire de trace m.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
TraceMessage info() const
Flot pour un message d'information.
ITraceMng * traceMng() const
Gestionnaire de trace.
Vecteur 1D de données avec sémantique par valeur (style STL).
__host__ __device__ Real2 min(Real2 a, Real2 b)
Retourne le minimum de deux Real2.
Definition MathUtils.h:346
Espace de nom pour les fonctions mathématiques.
Definition MathUtils.h:36
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
apfloat sqrt(apfloat v)
Racine carrée de v.
Definition MathApfloat.h:65
Int32 Integer
Type représentant un entier.
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:480
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:455
Array< Integer > IntegerArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:127
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:339
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:347
double Real
Type représentant un réel.
Array< Real > RealArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:129
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:345
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:484
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:457
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:486