14#include "arcane/utils/Array.h"
15#include "arcane/utils/ArgumentException.h"
16#include "arcane/utils/FatalErrorException.h"
17#include "arcane/utils/TraceAccessor.h"
18#include "arcane/utils/OStringStream.h"
19#include "arcane/utils/StringBuilder.h"
21#include "arcane/core/matvec/Matrix.h"
41namespace Arcane::MatVec
54 Integer nb_row = matrix.nbRow();
57 full_matrix_values.fill(0.0);
58 solution_values.copy(vector_b.values());
59 for (
Integer row = 0; row < nb_row; ++row) {
60 for (
Integer j = rows[row]; j < rows[row + 1]; ++j) {
61 full_matrix_values[row * nb_row + columns[j]] = mat_values[j];
64 _solve(full_matrix_values, solution_values, nb_row);
65 vector_x.values().copy(solution_values);
76 throw FatalErrorException(
"DirectSolver",
"Null matrix");
77 vec_values[0] /= mat_values[0];
81 for (
Integer k = 0; k < size - 1; ++k) {
83 for (
Integer j = k + 1; j < size; ++j) {
85 Real factor = mat_values[j * size + k] / mat_values[k * size + k];
86 for (
Integer m = k + 1; m < size; ++m)
87 mat_values[j * size + m] -= factor * mat_values[k * size + m];
88 vec_values[j] -= factor * vec_values[k];
94 for (
Integer k = (size - 1); k > 0; --k) {
95 vec_values[k] /= mat_values[k * size + k];
96 for (
Integer j = 0; j < k; ++j) {
98 vec_values[j] -= vec_values[k] * mat_values[j * size + k];
102 vec_values[0] /= mat_values[0];
109matrixMatrixProduct(
const Matrix& left_matrix,
const Matrix& right_matrix)
111 Integer nb_left_col = left_matrix.nbColumn();
112 Integer nb_right_col = right_matrix.nbColumn();
113 Integer nb_right_row = right_matrix.nbRow();
114 Integer nb_left_row = left_matrix.nbRow();
115 if (nb_left_col != nb_right_row)
116 ARCANE_THROW(ArgumentException,
"Bad size nb_left_column={0} nb_right_row={1}",
117 nb_left_col, nb_right_row);
118 Integer nb_row_col = nb_left_col;
120 Matrix new_matrix(nb_left_row, nb_right_col);
125 for (
Integer i = 0; i < nb_left_row; ++i) {
127 for (
Integer j = 0; j < nb_right_col; ++j) {
129 for (
Integer k = 0; k < nb_row_col; ++k) {
138 v += left_matrix.value(i, k) * right_matrix.value(k, j);
142 new_matrix_columns.add(j);
143 new_matrix_values.add(v);
146 new_matrix_rows_size[i] = local_nb_col;
148 new_matrix.setRowsSize(new_matrix_rows_size);
149 new_matrix.setValues(new_matrix_columns, new_matrix_values);
157matrixMatrixProductFast(
const Matrix& left_matrix,
const Matrix& right_matrix)
159 Integer nb_left_col = left_matrix.nbColumn();
160 Integer nb_right_col = right_matrix.nbColumn();
161 Integer nb_right_row = right_matrix.nbRow();
162 Integer nb_left_row = left_matrix.nbRow();
163 if (nb_left_col != nb_right_row)
164 ARCANE_THROW(ArgumentException,
"Bad size nb_left_column={0} nb_right_row={1}",
165 nb_left_col, nb_right_row);
176 Matrix new_matrix(nb_left_row, nb_right_col);
187 col_right_columns_size.fill(0);
188 for (
Integer i = 0; i < nb_right_row; ++i) {
189 for (
Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
190 ++col_right_columns_size[right_columns[j]];
195 for (
Integer j = 0; j < nb_right_col; ++j) {
196 col_right_columns_index[j] = index;
197 index += col_right_columns_size[j];
199 col_right_columns_index[nb_right_col] = index;
201 col_right_rows.resize(index);
202 col_right_values.resize(index);
205 col_right_columns_size.fill(0);
206 for (
Integer i = 0; i < nb_right_row; ++i) {
207 for (
Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
208 Integer col = right_columns[j];
209 Real value = right_values[j];
210 Integer col_index = col_right_columns_size[col] + col_right_columns_index[col];
211 ++col_right_columns_size[col];
212 col_right_rows[col_index] = i;
213 col_right_values[col_index] = value;
220 current_row_values.fill(0.0);
221 for (
Integer i = 0; i < nb_left_row; ++i) {
224 for (
Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z) {
225 current_row_values[left_columns[z]] = left_values[z];
236 for (
Integer j = 0; j < nb_right_col; ++j) {
238 for (
Integer zj = col_right_columns_index[j]; zj < col_right_columns_index[j + 1]; ++zj) {
247 v += col_right_values[zj] * current_row_values[col_right_rows[zj]];
251 new_matrix_columns.add(j);
252 new_matrix_values.add(v);
256 new_matrix_rows_size[i] = local_nb_col;
259 for (
Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z)
260 current_row_values[left_columns[z]] = 0.0;
262 new_matrix.setRowsSize(new_matrix_rows_size);
263 new_matrix.setValues(new_matrix_columns, new_matrix_values);
270void MatrixOperation2::
274 Integer nb_col = columns_index.size() - 1;
275 o <<
"(ColumnMatrix nb_col=" << nb_col;
276 for (
Integer j = 0; j < nb_col; ++j) {
277 for (
Integer z = columns_index[j], zs = columns_index[j + 1]; z < zs; ++z) {
280 o <<
" [" << i <<
"," << j <<
"]=" << v;
290transpose(
const Matrix& matrix)
292 Integer nb_column = matrix.nbColumn();
293 Integer nb_row = matrix.nbRow();
295 Integer new_matrix_nb_row = nb_column;
296 Integer new_matrix_nb_column = nb_row;
297 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
302 for (
Integer i = 0; i < new_matrix_nb_row; ++i) {
304 for (
Integer j = 0; j < new_matrix_nb_column; ++j) {
305 Real v = matrix.value(j, i);
308 new_matrix_columns.add(j);
309 new_matrix_values.add(v);
312 new_matrix_rows_size[i] = local_nb_col;
314 new_matrix.setRowsSize(new_matrix_rows_size);
315 new_matrix.setValues(new_matrix_columns, new_matrix_values);
323transposeFast(
const Matrix& matrix)
325 Integer nb_column = matrix.nbColumn();
326 Integer nb_row = matrix.nbRow();
332 Integer new_matrix_nb_row = nb_column;
333 Integer new_matrix_nb_column = nb_row;
334 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
339 new_matrix_rows_size.fill(0);
340 Integer nb_element = values.size();
341 for (
Integer i = 0, is = columns.size(); i < is; ++i) {
342 ++new_matrix_rows_size[columns[i]];
344 new_matrix.setRowsSize(new_matrix_rows_size);
347 new_matrix_rows_size.fill(0);
352 for (
Integer row = 0, is = nb_row; row < is; ++row) {
353 for (
Integer j = rows_index[row]; j < rows_index[row + 1]; ++j) {
354 Integer col_index = columns[j];
355 Integer pos = new_matrix_rows_index[col_index] + new_matrix_rows_size[col_index];
357 new_matrix_columns[pos] = row;
358 new_matrix_values[pos] = values[j];
359 ++new_matrix_rows_size[col_index];
363 new_matrix.setValues(new_matrix_columns, new_matrix_values);
371applyGalerkinOperator(
const Matrix& left_matrix,
const Matrix& matrix,
372 const Matrix& right_matrix)
374 Integer nb_original_row = matrix.nbRow();
375 Integer nb_final_row = left_matrix.nbRow();
400 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
402 p_marker[ic] = jj_counter;
403 jj_row_begining = jj_counter;
407 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
408 Integer i1 = left_matrix_columns[jj1];
411 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
412 Integer i2 = matrix_columns[jj2];
417 if (a_marker[i2] != ic) {
422 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
423 Integer i3 = right_matrix_columns[jj3];
429 if (p_marker[i3] < jj_row_begining) {
430 p_marker[i3] = jj_counter;
437 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
439 static Integer total_rap_size = 0;
440 total_rap_size += jj_counter;
442 cout <<
"** RAP_SIZE=" << jj_counter <<
" TOTAL=" << total_rap_size <<
'\n';
443 Matrix new_matrix(nb_final_row, nb_final_row);
444 new_matrix.setRowsSize(new_matrix_rows_size);
454 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
456 p_marker[ic] = jj_counter;
457 jj_row_begining = jj_counter;
458 new_matrix_columns[jj_counter] = ic;
459 new_matrix_values[jj_counter] = 0.0;
462 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
463 Integer i1 = left_matrix_columns[jj1];
464 Real r_entry = left_matrix_values[jj1];
467 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
468 Integer i2 = matrix_columns[jj2];
469 Real r_a_product = r_entry * matrix_values[jj2];
474 if (a_marker[i2] != ic) {
479 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
480 Integer i3 = right_matrix_columns[jj3];
481 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
487 if (p_marker[i3] < jj_row_begining) {
488 p_marker[i3] = jj_counter;
489 new_matrix_values[jj_counter] = r_a_p_product;
490 new_matrix_columns[jj_counter] = i3;
494 new_matrix_values[p_marker[i3]] += r_a_p_product;
503 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
504 Integer i3 = right_matrix_columns[jj3];
505 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
506 new_matrix_values[p_marker[i3]] += r_a_p_product;
519applyGalerkinOperator2(
const Matrix& left_matrix,
const Matrix& matrix,
520 const Matrix& right_matrix)
522 Integer nb_original_row = matrix.nbRow();
523 Integer nb_final_row = left_matrix.nbRow();
529 const Integer* left_matrix_rows = left_matrix.rowsIndex().data();
530 const Integer* left_matrix_columns = left_matrix.columns().data();
531 const Real* left_matrix_values = left_matrix.values().data();
533 const Integer* right_matrix_rows = right_matrix.rowsIndex().data();
534 const Integer* right_matrix_columns = right_matrix.columns().data();
535 const Real* right_matrix_values = right_matrix.values().data();
537 const Integer* matrix_rows = matrix.rowsIndex().data();
538 const Integer* matrix_columns = matrix.columns().data();
539 const Real* matrix_values = matrix.values().data();
548 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
550 p_marker[ic] = jj_counter;
551 jj_row_begining = jj_counter;
555 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
556 Integer i1 = left_matrix_columns[jj1];
559 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
560 Integer i2 = matrix_columns[jj2];
565 if (a_marker[i2] != ic) {
570 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
571 Integer i3 = right_matrix_columns[jj3];
577 if (p_marker[i3] < jj_row_begining) {
578 p_marker[i3] = jj_counter;
585 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
588 Matrix new_matrix(nb_final_row, nb_final_row);
589 new_matrix.setRowsSize(new_matrix_rows_size);
592 Integer* ARCANE_RESTRICT new_matrix_columns = new_matrix.columns().data();
593 Real* ARCANE_RESTRICT new_matrix_values = new_matrix.values().data();
599 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
601 p_marker[ic] = jj_counter;
602 jj_row_begining = jj_counter;
603 new_matrix_columns[jj_counter] = ic;
604 new_matrix_values[jj_counter] = 0.0;
607 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
608 Integer i1 = left_matrix_columns[jj1];
609 Real r_entry = left_matrix_values[jj1];
612 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
613 Integer i2 = matrix_columns[jj2];
614 Real r_a_product = r_entry * matrix_values[jj2];
619 if (a_marker[i2] != ic) {
624 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
625 Integer i3 = right_matrix_columns[jj3];
626 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
632 if (p_marker[i3] < jj_row_begining) {
633 p_marker[i3] = jj_counter;
634 new_matrix_values[jj_counter] = r_a_p_product;
635 new_matrix_columns[jj_counter] = i3;
639 new_matrix_values[p_marker[i3]] += r_a_p_product;
648 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
649 Integer i3 = right_matrix_columns[jj3];
650 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
651 new_matrix_values[p_marker[i3]] += r_a_p_product;
668 TYPE_SPECIAL_FINE = 3
682 , m_is_verbose(
false)
684 virtual ~AMGLevel() {}
688 virtual void buildLevel(
Matrix matrix,
Real alpha);
694 return m_fine_matrix;
698 return m_coarse_matrix;
700 Matrix prolongationMatrix()
702 return m_prolongation_matrix;
704 Matrix restrictionMatrix()
706 return m_restriction_matrix;
710 return m_coarse_matrix.nbRow();
714 return m_points_type;
716 void printLevelInfo();
723 Matrix m_prolongation_matrix;
724 Matrix m_restriction_matrix;
731 void _buildCoarsePoints(
Real alpha,
738 void _printLevelInfo(
Matrix matrix);
756 void build(
Matrix matrix);
773 void _relaxGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x,
775 void _relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x);
776 void _printResidualInfo(
const Matrix& matrix,
const Vector& vector_b,
786 for (
Integer i = 0; i < m_levels.size(); ++i)
796 Matrix current_matrix = matrix;
798 for (
Integer i = 1; i < 100; ++i) {
799 AMGLevel* level =
new AMGLevel(
traceMng(), i);
800 level->buildLevel(current_matrix, 0.25);
802 Integer nb_coarse_point = level->nbCoarsePoint();
803 if (nb_coarse_point < 20)
805 current_matrix = level->coarseMatrix();
821 for (
Integer i = 0; i < 20; ++i)
822 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
" X=" << vector_x.values()[i] <<
'\n';
823 for (
Integer i = 0; i < v_values.size(); ++i)
824 if (math::abs(v_values[i]) > 1e-5)
825 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
'\n';
826 info() <<
"VECTOR_F\n"
830 _solve(vector_b, vector_x, 0);
849 Vector r(vector_x.size());
850 MatrixOperation mat_op;
851 for (
Integer i = 0; i < nb_relax; ++i) {
853 mat_op.matrixVectorProduct(matrix, vector_x, r);
854 mat_op.negateVector(r);
855 mat_op.addVector(r, vector_b);
858 mat_op.addVector(vector_x, r);
869 Real epsilon = 1.0e-10;
870 DiagonalPreconditioner p(matrix);
871 ConjugateGradientSolver solver;
872 solver.setMaxIteration(nb_relax);
880 solver.solve(matrix, vector_b, vector_x, epsilon, &p);
904 Integer nb_row = matrix.nbRow();
910 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
911 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
" T=" << tmp_values[i] <<
'\n';
912 info() <<
"B = X=" << x_values.data() <<
" T=" << tmp_values.data() <<
"\n"
915 Real one_minus_weight = 1.0 - weight;
916 for (
Integer row = 0; row < nb_row; ++row) {
917 Real diag = mat_values[rows[row]];
920 Real res = b_values[row];
921 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
923 res -= mat_values[j] * tmp_values[col];
925 x_values[row] *= one_minus_weight;
926 x_values[row] += (weight * res) / diag;
931 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
932 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
955 const Integer* columns = matrix.columns().data();
956 const Real* mat_values = matrix.values().data();
958 Real* ARCANE_RESTRICT x_values = vector_x.values().data();
959 const Real* b_values = vector_b.values().data();
960 const Integer* points_type = points_type2.data();
963 Integer nb_row = matrix.nbRow();
965 info() <<
" RELAX nb_relax=" <<
" nb_row=" << nb_row
966 <<
" point_type=" << point_type;
969 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
970 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
974 for (
Integer row = 0; row < nb_row; ++row) {
975 Real diag = mat_values[rows[row]];
976 if (points_type[row] != point_type ||
math::isZero(diag))
978 Real res = b_values[row];
979 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
981 res -= mat_values[j] * x_values[col];
983 x_values[row] = res / diag;
988 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
989 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
999_relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x)
1008 Integer nb_row = matrix.nbRow();
1011 for (
Integer row = 0; row < nb_row; ++row) {
1012 Real diag = mat_values[rows[row]];
1015 Real res = b_values[row];
1016 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1018 res -= mat_values[j] * x_values[col];
1020 x_values[row] = res / diag;
1023 for (
Integer row = nb_row - 1; row > -1; --row) {
1024 Real diag = mat_values[rows[row]];
1027 Real res = b_values[row];
1028 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1030 res -= mat_values[j] * x_values[col];
1032 x_values[row] = res / diag;
1042 AMGLevel* current_level = m_levels[level];
1044 Integer nb_coarse = current_level->nbCoarsePoint();
1045 Matrix fine_matrix = current_level->fineMatrix();
1046 Matrix restriction_matrix = current_level->restrictionMatrix();
1047 Matrix coarse_matrix = current_level->coarseMatrix();
1048 Matrix prolongation_matrix = current_level->prolongationMatrix();
1050 Integer new_nb_row = nb_coarse;
1051 Vector new_b(new_nb_row);
1052 Vector new_x(new_nb_row);
1053 Vector tmp(vector_size);
1055 MatrixOperation mat_op;
1057 bool is_final_level = (level + 1) == m_levels.size();
1059 const bool use_gauss_seidel =
false;
1061 Real jacobi_weight = 2.0 / 3.0;
1062 if (use_gauss_seidel) {
1063 for (
Integer i = 0; i < nb_relax1; ++i)
1064 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1065 for (
Integer i = 0; i < nb_relax1; ++i)
1066 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1071 for (
Integer i = 0; i < nb_relax1; ++i) {
1073 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1084 mat_op.matrixVectorProduct(fine_matrix, vector_x, tmp);
1087 mat_op.negateVector(tmp);
1088 mat_op.addVector(tmp, vector_b);
1091 mat_op.matrixVectorProduct(restriction_matrix, tmp, new_b);
1094 info() << ostr.str();
1101 if (is_final_level) {
1107 ds.solve(coarse_matrix, new_b, new_x);
1111 Real epsilon = 1.0e-14;
1112 DiagonalPreconditioner p(coarse_matrix);
1113 ConjugateGradientSolver solver;
1115 new_x.values().fill(0.0);
1116 solver.solve(coarse_matrix, new_b, new_x, epsilon, &p);
1123 info() <<
"SOLVE COARSE MATRIX nb_iter=" << solver.nbIteration();
1129 new_x.values().fill(0.0);
1130 _solve(new_b, new_x, level + 1);
1135 mat_op.matrixVectorProduct(prolongation_matrix, new_x, tmp);
1136 mat_op.addVector(vector_x, tmp);
1145 if (use_gauss_seidel) {
1146 for (
Integer i = 0; i < nb_relax1; ++i)
1147 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1148 for (
Integer i = 0; i < nb_relax1; ++i)
1149 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1154 for (
Integer i = 0; i < nb_relax1; ++i) {
1156 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1171 Vector tmp(b.size());
1173 MatrixOperation mat_op;
1174 mat_op.matrixVectorProduct(a, x, tmp);
1177 mat_op.negateVector(tmp);
1178 mat_op.addVector(tmp, b);
1179 Real r = mat_op.dot(tmp);
1182 for (
Integer i = 0; i < v; ++i)
1183 info() <<
"R_" << i <<
" = " << tmp.values()[i];
1185 info() <<
" AMG_RESIDUAL_NORM=" << r <<
" sqrt=" <<
math::sqrt(r);
1218 if (m_lambda == rhs.m_lambda)
1219 return m_index < rhs.m_index;
1220 return (m_lambda > rhs.m_lambda);
1230 _printLevelInfo(m_prolongation_matrix);
1231 _printLevelInfo(m_coarse_matrix);
1235_printLevelInfo(Matrix matrix)
1238 Integer nb_row = matrix.nbRow();
1239 Integer nb_column = matrix.nbColumn();
1249 max_val = values[0];
1250 min_val = values[0];
1253 Real max_row_sum = 0.0;
1254 Real min_row_sum = 0.0;
1255 for (
Integer row = 0; row < nb_row; ++row) {
1257 for (
Integer z = rows[row], zs = rows[row + 1]; z < zs; ++z) {
1267 max_row_sum = row_sum;
1268 min_row_sum = row_sum;
1270 if (row_sum > max_row_sum)
1271 max_row_sum = row_sum;
1272 if (row_sum < max_row_sum)
1273 min_row_sum = row_sum;
1278 ostr() <<
"level=" << m_level
1279 <<
" nb_row=" << nb_row
1280 <<
" nb_col=" << nb_column
1281 <<
" nb_nonzero=" << nb_value
1282 <<
" sparsity=" << sparsity
1283 <<
" min=" << min_val
1284 <<
" max=" << max_val
1285 <<
" min_row=" << min_row_sum
1286 <<
" max_row=" << max_row_sum;
1288 info() <<
"INFO: " << ostr.str();
1295_buildCoarsePoints(
Real alpha,
1297 UniqueArray<SharedArray<Integer>>& depends,
1303 Integer nb_row = m_fine_matrix.nbRow();
1307 UniqueArray<SharedArray<Integer>> influences(nb_row);
1308 depends.resize(nb_row);
1310 m_points_type.resize(nb_row);
1311 m_points_type.fill(TYPE_UNDEFINED);
1313 weak_depends.resize(mat_values.size());
1314 weak_depends.fill(0);
1316 const bool type_hypre =
true;
1318 rows_max_val.resize(nb_row);
1319 for (
Integer row = 0; row < nb_row; ++row) {
1322 Real diag_val = mat_values[rows_index[row]];
1324 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1326 Real mv = mat_values[z];
1338 rows_max_val[row] = max_val * alpha;
1340 rows_max_val[row] = min_val * alpha;
1343 rows_max_val[row] = max_val * alpha;
1346 for (
Integer row = 0; row < nb_row; ++row) {
1348 Real max_val = rows_max_val[row];
1349 Real diag_val = mat_values[rows_index[row]];
1350 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1352 Real mv = mat_values[z];
1354 if (diag_val < 0.0) {
1358 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1360 depends[row].add(column);
1361 influences[column].add(row);
1362 weak_depends[z] = 2;
1365 weak_depends[z] = 1;
1371 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1373 depends[row].add(column);
1374 influences[column].add(row);
1375 weak_depends[z] = 2;
1378 weak_depends[z] = 1;
1382 if (math::abs(mv) > max_val) {
1385 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1387 depends[row].add(column);
1388 influences[column].add(row);
1389 weak_depends[z] = 2;
1392 weak_depends[z] = 1;
1404 ostr() <<
"GRAPH\n";
1405 for (
Integer i = 0; i < n; ++i) {
1406 ostr() <<
" GRAPH I=" << i <<
" ";
1407 for (
Integer j = 0; j < depends[i].size(); ++j) {
1409 ostr() <<
" " << depends[i][j];
1411 ostr() <<
" index=" << index <<
'\n';
1413 ostr() <<
"\n MAXTRIX\n";
1415 for (
Integer i = 0; i < n; ++i) {
1416 ostr() <<
"MATRIX I=" << i <<
" ";
1417 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1419 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1421 ostr() <<
" index=" << index <<
'\n';
1423 info() << ostr.str();
1430 m_is_verbose =
false;
1433 for (
Integer row = 0; row < nb_row; ++row) {
1434 if (depends[row].size() == 0) {
1435 m_points_type[row] = TYPE_FINE;
1438 info() <<
"FIRST MARK FINE point=" << row;
1443 for (
Integer row = 0; row < nb_row; ++row) {
1444 if (m_points_type[row] != TYPE_FINE && lambdas[row] <= 0) {
1445 m_points_type[row] = TYPE_FINE;
1448 info() <<
"INIT MARK FINE NULL MEASURE point=" << row <<
" measure=" << lambdas[row];
1449 for (
Integer j = 0, js = depends[row].size(); j < js; ++j) {
1450 Integer col = depends[row][j];
1451 if (m_points_type[col] != TYPE_FINE)
1455 printf(
"ADD MEASURE NULL point=%d measure=%d\n", (
int)col, lambdas[col]);
1461 typedef std::set<PointInfo> PointSet;
1462 PointSet undefined_points;
1463 for (
Integer i = 0; i < nb_row; ++i) {
1464 if (m_points_type[i] == TYPE_UNDEFINED)
1465 undefined_points.insert(PointInfo(lambdas[i], i));
1468 while (nb_done < nb_row && nb_iter < 100000) {
1482 if (undefined_points.empty())
1483 fatal() <<
"Undefined points is empty";
1484 PointSet::iterator max_point = undefined_points.begin();
1485 Integer max_value_index = max_point->m_index;
1486 Integer max_value = max_point->m_lambda;
1487 m_points_type[max_value_index] = TYPE_COARSE;
1490 undefined_points.erase(max_point);
1492 cout <<
"MARK COARSE point=" << max_value_index
1493 <<
" measure=" << max_value
1494 <<
" left=" << (nb_row - nb_done)
1497 for (
Integer i = 0, is = point_influences.size(); i < is; ++i) {
1499 Integer pt = point_influences[i];
1501 if (m_points_type[pt] == TYPE_UNDEFINED) {
1502 m_points_type[pt] = TYPE_FINE;
1505 undefined_points.erase(PointInfo(lambdas[pt], pt));
1507 cout <<
"MARK FINE point=" << pt
1508 <<
" measure=" << lambdas[pt]
1509 <<
" left=" << (nb_row - nb_done)
1511 for (
Integer z = 0, zs = depends[pt].size(); z < zs; ++z) {
1515 if (m_points_type[pt2] == TYPE_UNDEFINED) {
1516 undefined_points.erase(PointInfo(lambdas[pt2], pt2));
1518 undefined_points.insert(PointInfo(lambdas[pt2], pt2));
1523 for (
Integer i = 0, is = depends[max_value_index].size(); i < is; ++i) {
1524 Integer pt3 = depends[max_value_index][i];
1525 if (m_points_type[pt3] == TYPE_UNDEFINED) {
1526 undefined_points.erase(PointInfo(lambdas[pt3], pt3));
1531 undefined_points.insert(PointInfo(lambdas[pt3], pt3));
1535 info() <<
"LAMBDA MAX = " << max_value <<
" index=" << max_value_index <<
" nb_done=" << nb_done;
1540 info() <<
"NB ROW=" << nb_row <<
" nb_done=" << nb_done <<
" nb_fine=" << nb_fine
1541 <<
" nb_coarse=" << nb_coarse <<
" nb_iter=" << nb_iter;
1542 if (nb_done != nb_row)
1543 fatal() <<
"Can not find all COARSE or FINE points nb_done=" << nb_done <<
" nb_point=" << nb_row;
1550 points_marker.fill(-1);
1553 bool C_i_nonempty =
false;
1554 for (
Integer row = 0; row < nb_row; ++row) {
1555 if ((ci_tilde_mark |= row))
1557 if (m_points_type[row] == TYPE_FINE) {
1558 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1561 Integer col = depends[row][z];
1562 if (m_points_type[col] == TYPE_COARSE)
1563 points_marker[col] = row;
1565 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1568 Integer col = depends[row][z];
1569 if (m_points_type[col] == TYPE_FINE) {
1570 bool set_empty =
true;
1571 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1574 Integer col2 = depends[row][z2];
1575 if (points_marker[col2] == row) {
1582 m_points_type[row] = TYPE_COARSE;
1584 if (ci_tilde > -1) {
1585 m_points_type[ci_tilde] = TYPE_FINE;
1587 printf(
"SECOND PASS MARK FINE point=%d\n", ci_tilde);
1590 C_i_nonempty =
false;
1594 ci_tilde_mark = row;
1595 m_points_type[col] = TYPE_COARSE;
1597 printf(
"SECOND PASS MARK COARSE2 point=%d\n", col);
1598 C_i_nonempty =
true;
1611 static int matrix_number = 0;
1613 info() <<
"READ HYPRE CF_marker n=" << matrix_number;
1614 StringBuilder fname(
"CF_marker-");
1615 fname += matrix_number;
1616 std::ifstream ifile(fname.toString().localstr());
1618 ifile >> ws >> nb_read_point >> ws;
1619 if (nb_read_point != nb_row)
1620 fatal() <<
"Bad number of points for reading Hypre CF_marker read=" << nb_read_point
1621 <<
" expected=" << nb_row <<
" matrix_number=" << matrix_number;
1624 for (
Integer i = 0; i < nb_row; ++i) {
1628 fatal() <<
"Can not read marker point number=" << i;
1629 if (pt == (-1) || pt == (-3)) {
1630 m_points_type[i] = TYPE_FINE;
1634 m_points_type[i] = TYPE_COARSE;
1638 fatal() <<
"Bad value read=" << pt <<
" expected 1 or -1";
1644 for (
Integer i = 0; i < nb_row; ++i) {
1645 if (m_points_type[i] == TYPE_UNDEFINED)
1646 fatal() <<
" Point " << i <<
" is undefined";
1647 if (m_points_type[i] != TYPE_FINE) {
1655 for(
Integer z=0, zs=depends[i].size(); z<zs; ++z ){
1656 if (m_points_type[depends[i][z]]==TYPE_COARSE){
1668 for (
Integer i = 0; i < nb_row; ++i) {
1669 ostr() <<
" POINT i=" << i <<
" type=" << m_points_type[i] <<
" depends=";
1670 for (
Integer j = 0, js = depends[i].size(); j < js; ++j)
1671 ostr() << depends[i][j] <<
' ';
1674 info() << ostr.str();
1677 nb_fine = nb_row - nb_coarse;
1679 for (
Integer i = 0; i < nb_row; ++i)
1680 graph_size += depends[i].size();
1682 info() <<
" NB COARSE=" << nb_coarse <<
" NB FINE=" << nb_fine
1683 <<
" MAXTRIX NON_ZEROS=" << m_fine_matrix.rowsIndex()[nb_row]
1684 <<
" GRAPH_SIZE=" << graph_size;
1685 bool dump_matrix =
false;
1686 bool has_error =
false;
1687 if (nb_fine == 0 || graph_size == 0) {
1697 ostr() <<
"GRAPH\n";
1698 for (
Integer i = 0; i < n; ++i) {
1699 ostr() <<
" GRAPH I=" << i <<
" ";
1700 for (
Integer j = 0; j < depends[i].size(); ++j) {
1702 ostr() <<
" " << depends[i][j];
1704 ostr() <<
" index=" << index <<
'\n';
1707 ostr() <<
"\n MAXTRIX\n";
1709 for (
Integer i = 0; i < n; ++i) {
1710 ostr() <<
"MATRIX I=" << i <<
" ";
1711 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1713 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1715 ostr() <<
" index=" << index <<
'\n';
1717 info() << ostr.str();
1720 throw FatalErrorException(
"AMGLevel::_buildCoarsePoints");
1733 m_fine_matrix = matrix;
1736 matrix.sortDiagonale();
1740 UniqueArray<SharedArray<Integer>> depends;
1743 _buildCoarsePoints(alpha, rows_max_val, depends, weak_depends);
1744 _buildInterpolationMatrix(rows_max_val, depends, weak_depends);
1752 UniqueArray<SharedArray<Integer>>& depends,
1755 ARCANE_UNUSED(rows_max_val);
1760 Integer nb_row = m_fine_matrix.nbRow();
1763 points_in_coarse.fill(-1);
1768 for (
Integer i = 0; i < nb_row; ++i) {
1769 if (m_points_type[i] == TYPE_COARSE) {
1770 points_in_coarse[i] = nb_coarse;
1775 bool type_hypre =
true;
1782 for (
Integer row = 0; row < nb_row; ++row) {
1784 if (m_points_type[row] == TYPE_FINE) {
1785 Real weak_connect_sum = 0.0;
1787 Real diag = mat_values[rows_index[row]];
1791 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1793 if (weak_depends[z] == 1) {
1794 Real mv = mat_values[z];
1796 weak_connect_sum += mv;
1799 weak_connect_sum += mv;
1807 info() <<
"ROW row=" << row <<
" weak_connect_sum=" << weak_connect_sum;
1810 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1811 Integer j_column = columns[z];
1812 if (m_points_type[j_column] != TYPE_COARSE)
1814 if (weak_depends[z] != 2)
1817 Real mv = mat_values[z];
1818 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1819 Integer k_column = depends[row][z2];
1822 if (m_points_type[k_column] != TYPE_FINE)
1824 Real sum_coarse = 0.0;
1829 for (
Integer z3 = 0, zs3 = depends[row].size(); z3 < zs3; ++z3) {
1830 Integer m_column = depends[row][z3];
1833 if (m_points_type[m_column] == TYPE_COARSE) {
1834 Real w = m_fine_matrix.value(k_column, m_column);
1846 sum_coarse += math::abs(w);
1854 Real akj = m_fine_matrix.value(k_column, j_column);
1855 bool do_add =
false;
1857 if ((akj * sign) < 0.0)
1863 akj = math::abs(akj);
1868 to_add = math::divide(m_fine_matrix.value(row, k_column) * akj, sum_coarse);
1872 Real weight = -(mv + num_add) / (diag + weak_connect_sum);
1873 Integer new_column = points_in_coarse[j_column];
1879 if (new_column >= nb_coarse || new_column < 0)
1880 fatal() <<
" BAD COLUMN for fine point column=" << new_column <<
" nb=" << nb_coarse
1881 <<
" jcolumn=" << j_column;
1882 prolongation_matrix_columns.add(new_column);
1883 prolongation_matrix_values.add(weight);
1889 Integer column = points_in_coarse[row];
1890 if (column >= nb_coarse || column < 0)
1891 fatal() <<
" BAD COLUMN for coarse point j=" << column <<
" nb=" << nb_coarse
1893 prolongation_matrix_columns.add(column);
1894 prolongation_matrix_values.add(1.0);
1897 prolongation_matrix_rows_size[row] = nb_column;
1900 m_prolongation_matrix = Matrix(nb_row, nb_coarse);
1901 m_prolongation_matrix.setRowsSize(prolongation_matrix_rows_size);
1903 m_prolongation_matrix.setValues(prolongation_matrix_columns, prolongation_matrix_values);
1912 for (
Integer i = 0; i < n; ++i) {
1913 ostr() <<
"PROLONG I=" << i <<
" ";
1914 for (
Integer j = p_rows[i]; j < p_rows[i + 1]; ++j) {
1916 ostr() <<
" " << p_columns[j] <<
" " << p_values[j];
1918 ostr() <<
" index=" << index <<
'\n';
1920 info() <<
"PROLONG\n"
1924 MatrixOperation2 mat_op2;
1926 m_restriction_matrix = mat_op2.transposeFast(m_prolongation_matrix);
1928 m_restriction_matrix = mat_op2.transpose(m_prolongation_matrix);
1931 ostr() <<
"PROLONGATION_MATRIX ";
1932 m_prolongation_matrix.dump(ostr());
1934 ostr() <<
"RESTRICTION_MATRIX ";
1935 m_restriction_matrix.dump(ostr());
1936 info() << ostr.str();
1941 const bool old =
false;
1943 Matrix n1 = mat_op2.matrixMatrixProductFast(m_fine_matrix, m_prolongation_matrix);
1947 info() <<
"N1_MATRIX " << ostr.str();
1949 m_coarse_matrix = mat_op2.matrixMatrixProductFast(m_restriction_matrix, n1);
1952 m_coarse_matrix = mat_op2.applyGalerkinOperator2(m_restriction_matrix, m_fine_matrix, m_prolongation_matrix);
1955 m_coarse_matrix.dump(ostr());
1956 info() <<
"level= " << m_level <<
" COARSE_MATRIX=" << ostr.str();
1972void AMGPreconditioner::
1975 m_amg->solve(vec, out_vec);
1981void AMGPreconditioner::
1982build(
const Matrix& matrix)
1985 m_amg =
new AMG(m_trace_mng);
1986 m_amg->build(matrix);
2005build(
const Matrix& matrix)
2008 m_amg =
new AMG(m_trace_mng);
2009 m_amg->build(matrix);
2018 m_amg->solve(vector_b, vector_x);
#define ARCANE_THROW(exception_class,...)
Macro pour envoyer une exception avec formattage.
#define ARCANE_FATAL(...)
Macro envoyant une exception FatalErrorException.
void fill(const T &o) noexcept
Remplit le tableau avec la valeur o.
constexpr const_pointer data() const noexcept
Pointeur sur la mémoire allouée.
constexpr Integer size() const noexcept
Nombre d'éléments du tableau.
Interface du gestionnaire de traces.
Matrice avec stockage CSR.
bool operator<(const PointInfo &rhs) const
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.
Espace de nom pour les fonctions mathématiques.
__host__ __device__ double sqrt(double v)
Racine carrée de v.
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.
ArrayView< Integer > IntegerArrayView
Equivalent C d'un tableau à une dimension d'entiers.
Array< Integer > IntegerArray
Tableau dynamique à une dimension d'entiers.
UniqueArray< Int32 > Int32UniqueArray
Tableau dynamique à une dimension d'entiers 32 bits.
UniqueArray< Real > RealUniqueArray
Tableau dynamique à une dimension de réels.
double Real
Type représentant un réel.
Array< Real > RealArray
Tableau dynamique à une dimension de réels.
UniqueArray< Integer > IntegerUniqueArray
Tableau dynamique à une dimension d'entiers.
ConstArrayView< Integer > IntegerConstArrayView
Equivalent C d'un tableau à une dimension d'entiers.
ArrayView< Real > RealArrayView
Equivalent C d'un tableau à une dimension de réels.
ConstArrayView< Real > RealConstArrayView
Equivalent C d'un tableau à une dimension de réels.