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