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