Arcane  v3.14.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-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
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,
722 );
723 void _buildInterpolationMatrix(RealConstArrayView rows_max_val,
726 );
727 void _printLevelInfo(Matrix matrix);
728};
729
730/*---------------------------------------------------------------------------*/
731/*---------------------------------------------------------------------------*/
732
733class AMG
734: public TraceAccessor
735{
736 public:
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,
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
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/*---------------------------------------------------------------------------*/
Tableau d'items de types quelconques.
Lecteur des fichiers de maillage via la bibliothèque LIMA.
Definition Lima.cc:120
Matrice avec stockage CSR.
void sortDiagonale()
Arrange le stockage pour que la diagonale soit le premier élément.
Definition Matrix.cc:180
IntegerConstArrayView rowsIndex() const
Indices des premiers éléments de chaque ligne.
Definition Matrix.cc:208
Real value(Integer row, Integer column) const
Retourne la valeur d'un élément de la matrice.
Definition Matrix.cc:235
void setRowsSize(IntegerConstArrayView rows_size)
Positionne le nombre d'éléments non nuls de chaque ligne.
Definition Matrix.cc:253
void setValues(IntegerConstArrayView columns, RealConstArrayView values)
Positionne les valeurs des éléments de la matrice.
Definition Matrix.cc:244
IntegerConstArrayView columns() const
Indices des colonnes des valeurs.
Definition Matrix.cc:298
void dump(std::ostream &o) const
Imprime la matrice.
Definition Matrix.cc:217
RealConstArrayView values() const
Valeurs de la matrice.
Definition Matrix.cc:262
bool operator<(const PointInfo &rhs) const
Definition AMG.cc:1185
Vecteur d'algèbre linéraire.
Matrix class, to be used by user.
void fill(const T &o) noexcept
Remplit le tableau avec la valeur o.
void resize(Int64 s)
Change le nombre d'éléments du tableau à s.
void fill(ConstReferenceType value)
Remplit le tableau avec la valeur value.
Vue constante d'un tableau de type T.
Interface du gestionnaire de traces.
ITraceMng * traceMng() const
Gestionnaire de trace.
TraceMessage info() const
Flot pour un message d'information.
TraceMessage fatal() const
Flot pour un message d'erreur fatale.
Vecteur 1D de données avec sémantique par valeur (style STL).
ARCCORE_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
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
ARCCORE_HOST_DEVICE double sqrt(double v)
Racine carrée de v.
Definition Math.h:135
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:615
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:646
ConstArrayView< Int32 > Int32ConstArrayView
Equivalent C d'un tableau à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:640
Array< Integer > IntegerArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:331
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
Definition UtilsTypes.h:515
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:521
Array< Real > RealArray
Tableau dynamique à une dimension de réels.
Definition UtilsTypes.h:333
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
Definition UtilsTypes.h:519
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Definition UtilsTypes.h:644
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
Definition UtilsTypes.h:617
Int32 Integer
Type représentant un entier.