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"
42namespace Arcane::MatVec
55 Integer nb_row = matrix.nbRow();
58 full_matrix_values.fill(0.0);
59 solution_values.copy(vector_b.values());
60 for (
Integer row = 0; row < nb_row; ++row) {
61 for (
Integer j = rows[row]; j < rows[row + 1]; ++j) {
62 full_matrix_values[row * nb_row + columns[j]] = mat_values[j];
65 _solve(full_matrix_values, solution_values, nb_row);
66 vector_x.values().copy(solution_values);
77 throw FatalErrorException(
"DirectSolver",
"Null matrix");
78 vec_values[0] /= mat_values[0];
82 for (
Integer k = 0; k < size - 1; ++k) {
84 for (
Integer j = k + 1; j < size; ++j) {
86 Real factor = mat_values[j * size + k] / mat_values[k * size + k];
87 for (
Integer m = k + 1; m < size; ++m)
88 mat_values[j * size + m] -= factor * mat_values[k * size + m];
89 vec_values[j] -= factor * vec_values[k];
95 for (
Integer k = (size - 1); k > 0; --k) {
96 vec_values[k] /= mat_values[k * size + k];
97 for (
Integer j = 0; j < k; ++j) {
99 vec_values[j] -= vec_values[k] * mat_values[j * size + k];
103 vec_values[0] /= mat_values[0];
110matrixMatrixProduct(
const Matrix& left_matrix,
const Matrix& right_matrix)
112 Integer nb_left_col = left_matrix.nbColumn();
113 Integer nb_right_col = right_matrix.nbColumn();
114 Integer nb_right_row = right_matrix.nbRow();
115 Integer nb_left_row = left_matrix.nbRow();
116 if (nb_left_col != nb_right_row)
117 ARCANE_THROW(ArgumentException,
"Bad size nb_left_column={0} nb_right_row={1}",
118 nb_left_col, nb_right_row);
119 Integer nb_row_col = nb_left_col;
121 Matrix new_matrix(nb_left_row, nb_right_col);
126 for (
Integer i = 0; i < nb_left_row; ++i) {
128 for (
Integer j = 0; j < nb_right_col; ++j) {
130 for (
Integer k = 0; k < nb_row_col; ++k) {
139 v += left_matrix.value(i, k) * right_matrix.value(k, j);
143 new_matrix_columns.add(j);
144 new_matrix_values.add(v);
147 new_matrix_rows_size[i] = local_nb_col;
149 new_matrix.setRowsSize(new_matrix_rows_size);
150 new_matrix.setValues(new_matrix_columns, new_matrix_values);
158matrixMatrixProductFast(
const Matrix& left_matrix,
const Matrix& right_matrix)
160 Integer nb_left_col = left_matrix.nbColumn();
161 Integer nb_right_col = right_matrix.nbColumn();
162 Integer nb_right_row = right_matrix.nbRow();
163 Integer nb_left_row = left_matrix.nbRow();
164 if (nb_left_col != nb_right_row)
165 ARCANE_THROW(ArgumentException,
"Bad size nb_left_column={0} nb_right_row={1}",
166 nb_left_col, nb_right_row);
177 Matrix new_matrix(nb_left_row, nb_right_col);
188 col_right_columns_size.fill(0);
189 for (
Integer i = 0; i < nb_right_row; ++i) {
190 for (
Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
191 ++col_right_columns_size[right_columns[j]];
196 for (
Integer j = 0; j < nb_right_col; ++j) {
197 col_right_columns_index[j] = index;
198 index += col_right_columns_size[j];
200 col_right_columns_index[nb_right_col] = index;
202 col_right_rows.resize(index);
203 col_right_values.resize(index);
206 col_right_columns_size.fill(0);
207 for (
Integer i = 0; i < nb_right_row; ++i) {
208 for (
Integer j = right_rows_index[i]; j < right_rows_index[i + 1]; ++j) {
209 Integer col = right_columns[j];
210 Real value = right_values[j];
211 Integer col_index = col_right_columns_size[col] + col_right_columns_index[col];
212 ++col_right_columns_size[col];
213 col_right_rows[col_index] = i;
214 col_right_values[col_index] = value;
221 current_row_values.fill(0.0);
222 for (
Integer i = 0; i < nb_left_row; ++i) {
225 for (
Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z) {
226 current_row_values[left_columns[z]] = left_values[z];
237 for (
Integer j = 0; j < nb_right_col; ++j) {
239 for (
Integer zj = col_right_columns_index[j]; zj < col_right_columns_index[j + 1]; ++zj) {
248 v += col_right_values[zj] * current_row_values[col_right_rows[zj]];
252 new_matrix_columns.add(j);
253 new_matrix_values.add(v);
257 new_matrix_rows_size[i] = local_nb_col;
260 for (
Integer z = left_rows_index[i], zs = left_rows_index[i + 1]; z < zs; ++z)
261 current_row_values[left_columns[z]] = 0.0;
263 new_matrix.setRowsSize(new_matrix_rows_size);
264 new_matrix.setValues(new_matrix_columns, new_matrix_values);
271void MatrixOperation2::
275 Integer nb_col = columns_index.size() - 1;
276 o <<
"(ColumnMatrix nb_col=" << nb_col;
277 for (
Integer j = 0; j < nb_col; ++j) {
278 for (
Integer z = columns_index[j], zs = columns_index[j + 1]; z < zs; ++z) {
281 o <<
" [" << i <<
"," << j <<
"]=" << v;
291transpose(
const Matrix& matrix)
293 Integer nb_column = matrix.nbColumn();
294 Integer nb_row = matrix.nbRow();
296 Integer new_matrix_nb_row = nb_column;
297 Integer new_matrix_nb_column = nb_row;
298 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
303 for (
Integer i = 0; i < new_matrix_nb_row; ++i) {
305 for (
Integer j = 0; j < new_matrix_nb_column; ++j) {
306 Real v = matrix.value(j, i);
309 new_matrix_columns.add(j);
310 new_matrix_values.add(v);
313 new_matrix_rows_size[i] = local_nb_col;
315 new_matrix.setRowsSize(new_matrix_rows_size);
316 new_matrix.setValues(new_matrix_columns, new_matrix_values);
324transposeFast(
const Matrix& matrix)
326 Integer nb_column = matrix.nbColumn();
327 Integer nb_row = matrix.nbRow();
333 Integer new_matrix_nb_row = nb_column;
334 Integer new_matrix_nb_column = nb_row;
335 Matrix new_matrix(new_matrix_nb_row, new_matrix_nb_column);
340 new_matrix_rows_size.fill(0);
341 Integer nb_element = values.size();
342 for (
Integer i = 0, is = columns.size(); i < is; ++i) {
343 ++new_matrix_rows_size[columns[i]];
345 new_matrix.setRowsSize(new_matrix_rows_size);
348 new_matrix_rows_size.fill(0);
353 for (
Integer row = 0, is = nb_row; row < is; ++row) {
354 for (
Integer j = rows_index[row]; j < rows_index[row + 1]; ++j) {
355 Integer col_index = columns[j];
356 Integer pos = new_matrix_rows_index[col_index] + new_matrix_rows_size[col_index];
358 new_matrix_columns[pos] = row;
359 new_matrix_values[pos] = values[j];
360 ++new_matrix_rows_size[col_index];
364 new_matrix.setValues(new_matrix_columns, new_matrix_values);
372applyGalerkinOperator(
const Matrix& left_matrix,
const Matrix& matrix,
373 const Matrix& right_matrix)
375 Integer nb_original_row = matrix.nbRow();
376 Integer nb_final_row = left_matrix.nbRow();
401 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
403 p_marker[ic] = jj_counter;
404 jj_row_begining = jj_counter;
408 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
409 Integer i1 = left_matrix_columns[jj1];
412 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
413 Integer i2 = matrix_columns[jj2];
419 if (a_marker[i2] != ic) {
424 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
425 Integer i3 = right_matrix_columns[jj3];
431 if (p_marker[i3] < jj_row_begining) {
432 p_marker[i3] = jj_counter;
439 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
441 static Integer total_rap_size = 0;
442 total_rap_size += jj_counter;
444 std::cout <<
"** RAP_SIZE=" << jj_counter <<
" TOTAL=" << total_rap_size <<
'\n';
445 Matrix new_matrix(nb_final_row, nb_final_row);
446 new_matrix.setRowsSize(new_matrix_rows_size);
456 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
458 p_marker[ic] = jj_counter;
459 jj_row_begining = jj_counter;
460 new_matrix_columns[jj_counter] = ic;
461 new_matrix_values[jj_counter] = 0.0;
464 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
465 Integer i1 = left_matrix_columns[jj1];
466 Real r_entry = left_matrix_values[jj1];
469 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
470 Integer i2 = matrix_columns[jj2];
471 Real r_a_product = r_entry * matrix_values[jj2];
477 if (a_marker[i2] != ic) {
482 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
483 Integer i3 = right_matrix_columns[jj3];
484 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
490 if (p_marker[i3] < jj_row_begining) {
491 p_marker[i3] = jj_counter;
492 new_matrix_values[jj_counter] = r_a_p_product;
493 new_matrix_columns[jj_counter] = i3;
497 new_matrix_values[p_marker[i3]] += r_a_p_product;
506 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
507 Integer i3 = right_matrix_columns[jj3];
508 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
509 new_matrix_values[p_marker[i3]] += r_a_p_product;
522applyGalerkinOperator2(
const Matrix& left_matrix,
const Matrix& matrix,
523 const Matrix& right_matrix)
525 Integer nb_original_row = matrix.nbRow();
526 Integer nb_final_row = left_matrix.nbRow();
532 const Integer* left_matrix_rows = left_matrix.rowsIndex().data();
533 const Integer* left_matrix_columns = left_matrix.columns().data();
534 const Real* left_matrix_values = left_matrix.values().data();
536 const Integer* right_matrix_rows = right_matrix.rowsIndex().data();
537 const Integer* right_matrix_columns = right_matrix.columns().data();
538 const Real* right_matrix_values = right_matrix.values().data();
540 const Integer* matrix_rows = matrix.rowsIndex().data();
541 const Integer* matrix_columns = matrix.columns().data();
542 const Real* matrix_values = matrix.values().data();
551 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
553 p_marker[ic] = jj_counter;
554 jj_row_begining = jj_counter;
558 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
559 Integer i1 = left_matrix_columns[jj1];
562 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
563 Integer i2 = matrix_columns[jj2];
569 if (a_marker[i2] != ic) {
574 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
575 Integer i3 = right_matrix_columns[jj3];
581 if (p_marker[i3] < jj_row_begining) {
582 p_marker[i3] = jj_counter;
589 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
592 Matrix new_matrix(nb_final_row, nb_final_row);
593 new_matrix.setRowsSize(new_matrix_rows_size);
596 Integer* ARCANE_RESTRICT new_matrix_columns = new_matrix.columns().data();
597 Real* ARCANE_RESTRICT new_matrix_values = new_matrix.values().data();
603 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
605 p_marker[ic] = jj_counter;
606 jj_row_begining = jj_counter;
607 new_matrix_columns[jj_counter] = ic;
608 new_matrix_values[jj_counter] = 0.0;
611 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
612 Integer i1 = left_matrix_columns[jj1];
613 Real r_entry = left_matrix_values[jj1];
616 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
617 Integer i2 = matrix_columns[jj2];
618 Real r_a_product = r_entry * matrix_values[jj2];
624 if (a_marker[i2] != ic) {
629 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
630 Integer i3 = right_matrix_columns[jj3];
631 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
637 if (p_marker[i3] < jj_row_begining) {
638 p_marker[i3] = jj_counter;
639 new_matrix_values[jj_counter] = r_a_p_product;
640 new_matrix_columns[jj_counter] = i3;
644 new_matrix_values[p_marker[i3]] += r_a_p_product;
653 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
654 Integer i3 = right_matrix_columns[jj3];
655 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
656 new_matrix_values[p_marker[i3]] += r_a_p_product;
673 TYPE_SPECIAL_FINE = 3
687 , m_is_verbose(
false)
689 virtual ~AMGLevel() {}
693 virtual void buildLevel(
Matrix matrix,
Real alpha);
699 return m_fine_matrix;
703 return m_coarse_matrix;
705 Matrix prolongationMatrix()
707 return m_prolongation_matrix;
709 Matrix restrictionMatrix()
711 return m_restriction_matrix;
715 return m_coarse_matrix.nbRow();
719 return m_points_type;
721 void printLevelInfo();
728 Matrix m_prolongation_matrix;
729 Matrix m_restriction_matrix;
736 void _buildCoarsePoints(
Real alpha,
743 void _printLevelInfo(
Matrix matrix);
761 void build(
Matrix matrix);
778 void _relaxGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x,
780 void _relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x);
781 void _printResidualInfo(
const Matrix& matrix,
const Vector& vector_b,
791 for (
Integer i = 0; i < m_levels.size(); ++i)
801 Matrix current_matrix = matrix;
803 for (
Integer i = 1; i < 100; ++i) {
804 AMGLevel* level =
new AMGLevel(
traceMng(), i);
805 level->buildLevel(current_matrix, 0.25);
807 Integer nb_coarse_point = level->nbCoarsePoint();
808 if (nb_coarse_point < 20)
810 current_matrix = level->coarseMatrix();
826 for (
Integer i = 0; i < 20; ++i)
827 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
" X=" << vector_x.values()[i] <<
'\n';
828 for (
Integer i = 0; i < v_values.size(); ++i)
829 if (math::abs(v_values[i]) > 1e-5)
830 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
'\n';
831 info() <<
"VECTOR_F\n"
835 _solve(vector_b, vector_x, 0);
854 Vector r(vector_x.size());
855 MatrixOperation mat_op;
856 for (
Integer i = 0; i < nb_relax; ++i) {
858 mat_op.matrixVectorProduct(matrix, vector_x, r);
859 mat_op.negateVector(r);
860 mat_op.addVector(r, vector_b);
863 mat_op.addVector(vector_x, r);
874 Real epsilon = 1.0e-10;
875 DiagonalPreconditioner p(matrix);
876 ConjugateGradientSolver solver;
877 solver.setMaxIteration(nb_relax);
885 solver.solve(matrix, vector_b, vector_x, epsilon, &p);
909 Integer nb_row = matrix.nbRow();
915 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
916 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
" T=" << tmp_values[i] <<
'\n';
917 info() <<
"B = X=" << x_values.data() <<
" T=" << tmp_values.data() <<
"\n"
920 Real one_minus_weight = 1.0 - weight;
921 for (
Integer row = 0; row < nb_row; ++row) {
922 Real diag = mat_values[rows[row]];
925 Real res = b_values[row];
926 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
928 res -= mat_values[j] * tmp_values[col];
930 x_values[row] *= one_minus_weight;
931 x_values[row] += (weight * res) / diag;
936 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
937 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
960 const Integer* columns = matrix.columns().data();
961 const Real* mat_values = matrix.values().data();
963 Real* ARCANE_RESTRICT x_values = vector_x.values().data();
964 const Real* b_values = vector_b.values().data();
965 const Integer* points_type = points_type2.data();
968 Integer nb_row = matrix.nbRow();
970 info() <<
" RELAX nb_relax=" <<
" nb_row=" << nb_row
971 <<
" point_type=" << point_type;
974 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
975 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
979 for (
Integer row = 0; row < nb_row; ++row) {
980 Real diag = mat_values[rows[row]];
981 if (points_type[row] != point_type ||
math::isZero(diag))
983 Real res = b_values[row];
984 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
986 res -= mat_values[j] * x_values[col];
988 x_values[row] = res / diag;
993 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
994 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
1004_relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x)
1013 Integer nb_row = matrix.nbRow();
1016 for (
Integer row = 0; row < nb_row; ++row) {
1017 Real diag = mat_values[rows[row]];
1020 Real res = b_values[row];
1021 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1023 res -= mat_values[j] * x_values[col];
1025 x_values[row] = res / diag;
1028 for (
Integer row = nb_row - 1; row > -1; --row) {
1029 Real diag = mat_values[rows[row]];
1032 Real res = b_values[row];
1033 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1035 res -= mat_values[j] * x_values[col];
1037 x_values[row] = res / diag;
1047 AMGLevel* current_level = m_levels[level];
1049 Integer nb_coarse = current_level->nbCoarsePoint();
1050 Matrix fine_matrix = current_level->fineMatrix();
1051 Matrix restriction_matrix = current_level->restrictionMatrix();
1052 Matrix coarse_matrix = current_level->coarseMatrix();
1053 Matrix prolongation_matrix = current_level->prolongationMatrix();
1055 Integer new_nb_row = nb_coarse;
1056 Vector new_b(new_nb_row);
1057 Vector new_x(new_nb_row);
1058 Vector tmp(vector_size);
1060 MatrixOperation mat_op;
1062 bool is_final_level = (level + 1) == m_levels.size();
1064 const bool use_gauss_seidel =
false;
1066 Real jacobi_weight = 2.0 / 3.0;
1067 if (use_gauss_seidel) {
1068 for (
Integer i = 0; i < nb_relax1; ++i)
1069 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1070 for (
Integer i = 0; i < nb_relax1; ++i)
1071 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1076 for (
Integer i = 0; i < nb_relax1; ++i) {
1078 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1089 mat_op.matrixVectorProduct(fine_matrix, vector_x, tmp);
1092 mat_op.negateVector(tmp);
1093 mat_op.addVector(tmp, vector_b);
1096 mat_op.matrixVectorProduct(restriction_matrix, tmp, new_b);
1099 info() << ostr.str();
1106 if (is_final_level) {
1112 ds.solve(coarse_matrix, new_b, new_x);
1116 Real epsilon = 1.0e-14;
1117 DiagonalPreconditioner p(coarse_matrix);
1118 ConjugateGradientSolver solver;
1120 new_x.values().fill(0.0);
1121 solver.solve(coarse_matrix, new_b, new_x, epsilon, &p);
1128 info() <<
"SOLVE COARSE MATRIX nb_iter=" << solver.nbIteration();
1134 new_x.values().fill(0.0);
1135 _solve(new_b, new_x, level + 1);
1140 mat_op.matrixVectorProduct(prolongation_matrix, new_x, tmp);
1141 mat_op.addVector(vector_x, tmp);
1150 if (use_gauss_seidel) {
1151 for (
Integer i = 0; i < nb_relax1; ++i)
1152 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1153 for (
Integer i = 0; i < nb_relax1; ++i)
1154 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1159 for (
Integer i = 0; i < nb_relax1; ++i) {
1161 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1176 Vector tmp(b.size());
1178 MatrixOperation mat_op;
1179 mat_op.matrixVectorProduct(a, x, tmp);
1182 mat_op.negateVector(tmp);
1183 mat_op.addVector(tmp, b);
1184 Real r = mat_op.dot(tmp);
1187 for (
Integer i = 0; i < v; ++i)
1188 info() <<
"R_" << i <<
" = " << tmp.values()[i];
1190 info() <<
" AMG_RESIDUAL_NORM=" << r <<
" sqrt=" <<
math::sqrt(r);
1223 if (m_lambda == rhs.m_lambda)
1224 return m_index < rhs.m_index;
1225 return (m_lambda > rhs.m_lambda);
1235 _printLevelInfo(m_prolongation_matrix);
1236 _printLevelInfo(m_coarse_matrix);
1240_printLevelInfo(Matrix matrix)
1243 Integer nb_row = matrix.nbRow();
1244 Integer nb_column = matrix.nbColumn();
1254 max_val = values[0];
1255 min_val = values[0];
1258 Real max_row_sum = 0.0;
1259 Real min_row_sum = 0.0;
1260 for (
Integer row = 0; row < nb_row; ++row) {
1262 for (
Integer z = rows[row], zs = rows[row + 1]; z < zs; ++z) {
1272 max_row_sum = row_sum;
1273 min_row_sum = row_sum;
1275 if (row_sum > max_row_sum)
1276 max_row_sum = row_sum;
1277 if (row_sum < max_row_sum)
1278 min_row_sum = row_sum;
1283 ostr() <<
"level=" << m_level
1284 <<
" nb_row=" << nb_row
1285 <<
" nb_col=" << nb_column
1286 <<
" nb_nonzero=" << nb_value
1287 <<
" sparsity=" << sparsity
1288 <<
" min=" << min_val
1289 <<
" max=" << max_val
1290 <<
" min_row=" << min_row_sum
1291 <<
" max_row=" << max_row_sum;
1293 info() <<
"INFO: " << ostr.str();
1300_buildCoarsePoints(
Real alpha,
1302 UniqueArray<SharedArray<Integer>>& depends,
1308 Integer nb_row = m_fine_matrix.nbRow();
1312 UniqueArray<SharedArray<Integer>> influences(nb_row);
1313 depends.resize(nb_row);
1315 m_points_type.resize(nb_row);
1316 m_points_type.fill(TYPE_UNDEFINED);
1318 weak_depends.resize(mat_values.size());
1319 weak_depends.fill(0);
1321 const bool type_hypre =
true;
1323 rows_max_val.resize(nb_row);
1324 for (
Integer row = 0; row < nb_row; ++row) {
1327 Real diag_val = mat_values[rows_index[row]];
1329 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1331 Real mv = mat_values[z];
1343 rows_max_val[row] = max_val * alpha;
1345 rows_max_val[row] = min_val * alpha;
1348 rows_max_val[row] = max_val * alpha;
1351 for (
Integer row = 0; row < nb_row; ++row) {
1353 Real max_val = rows_max_val[row];
1354 Real diag_val = mat_values[rows_index[row]];
1355 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1357 Real mv = mat_values[z];
1359 if (diag_val < 0.0) {
1363 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1365 depends[row].add(column);
1366 influences[column].add(row);
1367 weak_depends[z] = 2;
1370 weak_depends[z] = 1;
1376 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1378 depends[row].add(column);
1379 influences[column].add(row);
1380 weak_depends[z] = 2;
1383 weak_depends[z] = 1;
1387 if (math::abs(mv) > max_val) {
1390 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1392 depends[row].add(column);
1393 influences[column].add(row);
1394 weak_depends[z] = 2;
1397 weak_depends[z] = 1;
1409 ostr() <<
"GRAPH\n";
1410 for (
Integer i = 0; i < n; ++i) {
1411 ostr() <<
" GRAPH I=" << i <<
" ";
1412 for (
Integer j = 0; j < depends[i].size(); ++j) {
1414 ostr() <<
" " << depends[i][j];
1416 ostr() <<
" index=" << index <<
'\n';
1418 ostr() <<
"\n MAXTRIX\n";
1420 for (
Integer i = 0; i < n; ++i) {
1421 ostr() <<
"MATRIX I=" << i <<
" ";
1422 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1424 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1426 ostr() <<
" index=" << index <<
'\n';
1428 info() << ostr.str();
1435 m_is_verbose =
false;
1438 for (
Integer row = 0; row < nb_row; ++row) {
1439 if (depends[row].size() == 0) {
1440 m_points_type[row] = TYPE_FINE;
1443 info() <<
"FIRST MARK FINE point=" << row;
1448 for (
Integer row = 0; row < nb_row; ++row) {
1449 if (m_points_type[row] != TYPE_FINE && lambdas[row] <= 0) {
1450 m_points_type[row] = TYPE_FINE;
1453 info() <<
"INIT MARK FINE NULL MEASURE point=" << row <<
" measure=" << lambdas[row];
1454 for (
Integer j = 0, js = depends[row].size(); j < js; ++j) {
1455 Integer col = depends[row][j];
1456 if (m_points_type[col] != TYPE_FINE)
1460 printf(
"ADD MEASURE NULL point=%d measure=%d\n", (
int)col, lambdas[col]);
1466 typedef std::set<PointInfo> PointSet;
1467 PointSet undefined_points;
1468 for (
Integer i = 0; i < nb_row; ++i) {
1469 if (m_points_type[i] == TYPE_UNDEFINED)
1470 undefined_points.insert(PointInfo(lambdas[i], i));
1473 while (nb_done < nb_row && nb_iter < 100000) {
1487 if (undefined_points.empty())
1488 fatal() <<
"Undefined points is empty";
1489 PointSet::iterator max_point = undefined_points.begin();
1490 Integer max_value_index = max_point->m_index;
1491 Integer max_value = max_point->m_lambda;
1492 m_points_type[max_value_index] = TYPE_COARSE;
1495 undefined_points.erase(max_point);
1497 std::cout <<
"MARK COARSE point=" << max_value_index
1498 <<
" measure=" << max_value
1499 <<
" left=" << (nb_row - nb_done)
1502 for (
Integer i = 0, is = point_influences.size(); i < is; ++i) {
1504 Integer pt = point_influences[i];
1506 if (m_points_type[pt] == TYPE_UNDEFINED) {
1507 m_points_type[pt] = TYPE_FINE;
1510 undefined_points.erase(PointInfo(lambdas[pt], pt));
1512 std::cout <<
"MARK FINE point=" << pt
1513 <<
" measure=" << lambdas[pt]
1514 <<
" left=" << (nb_row - nb_done)
1516 for (
Integer z = 0, zs = depends[pt].size(); z < zs; ++z) {
1520 if (m_points_type[pt2] == TYPE_UNDEFINED) {
1521 undefined_points.erase(PointInfo(lambdas[pt2], pt2));
1523 undefined_points.insert(PointInfo(lambdas[pt2], pt2));
1528 for (
Integer i = 0, is = depends[max_value_index].size(); i < is; ++i) {
1529 Integer pt3 = depends[max_value_index][i];
1530 if (m_points_type[pt3] == TYPE_UNDEFINED) {
1531 undefined_points.erase(PointInfo(lambdas[pt3], pt3));
1536 undefined_points.insert(PointInfo(lambdas[pt3], pt3));
1540 info() <<
"LAMBDA MAX = " << max_value <<
" index=" << max_value_index <<
" nb_done=" << nb_done;
1545 info() <<
"NB ROW=" << nb_row <<
" nb_done=" << nb_done <<
" nb_fine=" << nb_fine
1546 <<
" nb_coarse=" << nb_coarse <<
" nb_iter=" << nb_iter;
1547 if (nb_done != nb_row)
1548 fatal() <<
"Can not find all COARSE or FINE points nb_done=" << nb_done <<
" nb_point=" << nb_row;
1555 points_marker.fill(-1);
1558 bool C_i_nonempty =
false;
1559 for (
Integer row = 0; row < nb_row; ++row) {
1560 if ((ci_tilde_mark |= row))
1562 if (m_points_type[row] == TYPE_FINE) {
1563 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1566 Integer col = depends[row][z];
1567 if (m_points_type[col] == TYPE_COARSE)
1568 points_marker[col] = row;
1570 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1573 Integer col = depends[row][z];
1574 if (m_points_type[col] == TYPE_FINE) {
1575 bool set_empty =
true;
1576 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1579 Integer col2 = depends[row][z2];
1580 if (points_marker[col2] == row) {
1587 m_points_type[row] = TYPE_COARSE;
1589 if (ci_tilde > -1) {
1590 m_points_type[ci_tilde] = TYPE_FINE;
1592 printf(
"SECOND PASS MARK FINE point=%d\n", ci_tilde);
1595 C_i_nonempty =
false;
1599 ci_tilde_mark = row;
1600 m_points_type[col] = TYPE_COARSE;
1602 printf(
"SECOND PASS MARK COARSE2 point=%d\n", col);
1603 C_i_nonempty =
true;
1616 static int matrix_number = 0;
1618 info() <<
"READ HYPRE CF_marker n=" << matrix_number;
1619 StringBuilder fname(
"CF_marker-");
1620 fname += matrix_number;
1621 std::ifstream ifile(fname.toString().localstr());
1623 ifile >> std::ws >> nb_read_point >> std::ws;
1624 if (nb_read_point != nb_row)
1625 fatal() <<
"Bad number of points for reading Hypre CF_marker read=" << nb_read_point
1626 <<
" expected=" << nb_row <<
" matrix_number=" << matrix_number;
1629 for (
Integer i = 0; i < nb_row; ++i) {
1633 fatal() <<
"Can not read marker point number=" << i;
1634 if (pt == (-1) || pt == (-3)) {
1635 m_points_type[i] = TYPE_FINE;
1639 m_points_type[i] = TYPE_COARSE;
1643 fatal() <<
"Bad value read=" << pt <<
" expected 1 or -1";
1649 for (
Integer i = 0; i < nb_row; ++i) {
1650 if (m_points_type[i] == TYPE_UNDEFINED)
1651 fatal() <<
" Point " << i <<
" is undefined";
1652 if (m_points_type[i] != TYPE_FINE) {
1660 for(
Integer z=0, zs=depends[i].size(); z<zs; ++z ){
1661 if (m_points_type[depends[i][z]]==TYPE_COARSE){
1673 for (
Integer i = 0; i < nb_row; ++i) {
1674 ostr() <<
" POINT i=" << i <<
" type=" << m_points_type[i] <<
" depends=";
1675 for (
Integer j = 0, js = depends[i].size(); j < js; ++j)
1676 ostr() << depends[i][j] <<
' ';
1679 info() << ostr.str();
1682 nb_fine = nb_row - nb_coarse;
1684 for (
Integer i = 0; i < nb_row; ++i)
1685 graph_size += depends[i].size();
1687 info() <<
" NB COARSE=" << nb_coarse <<
" NB FINE=" << nb_fine
1688 <<
" MAXTRIX NON_ZEROS=" << m_fine_matrix.rowsIndex()[nb_row]
1689 <<
" GRAPH_SIZE=" << graph_size;
1690 bool dump_matrix =
false;
1691 bool has_error =
false;
1692 if (nb_fine == 0 || graph_size == 0) {
1702 ostr() <<
"GRAPH\n";
1703 for (
Integer i = 0; i < n; ++i) {
1704 ostr() <<
" GRAPH I=" << i <<
" ";
1705 for (
Integer j = 0; j < depends[i].size(); ++j) {
1707 ostr() <<
" " << depends[i][j];
1709 ostr() <<
" index=" << index <<
'\n';
1712 ostr() <<
"\n MAXTRIX\n";
1714 for (
Integer i = 0; i < n; ++i) {
1715 ostr() <<
"MATRIX I=" << i <<
" ";
1716 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1718 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1720 ostr() <<
" index=" << index <<
'\n';
1722 info() << ostr.str();
1725 throw FatalErrorException(
"AMGLevel::_buildCoarsePoints");
1738 m_fine_matrix = matrix;
1741 matrix.sortDiagonale();
1745 UniqueArray<SharedArray<Integer>> depends;
1748 _buildCoarsePoints(alpha, rows_max_val, depends, weak_depends);
1749 _buildInterpolationMatrix(rows_max_val, depends, weak_depends);
1757 UniqueArray<SharedArray<Integer>>& depends,
1760 ARCANE_UNUSED(rows_max_val);
1765 Integer nb_row = m_fine_matrix.nbRow();
1768 points_in_coarse.fill(-1);
1773 for (
Integer i = 0; i < nb_row; ++i) {
1774 if (m_points_type[i] == TYPE_COARSE) {
1775 points_in_coarse[i] = nb_coarse;
1780 bool type_hypre =
true;
1787 for (
Integer row = 0; row < nb_row; ++row) {
1789 if (m_points_type[row] == TYPE_FINE) {
1790 Real weak_connect_sum = 0.0;
1792 Real diag = mat_values[rows_index[row]];
1796 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1798 if (weak_depends[z] == 1) {
1799 Real mv = mat_values[z];
1801 weak_connect_sum += mv;
1804 weak_connect_sum += mv;
1812 info() <<
"ROW row=" << row <<
" weak_connect_sum=" << weak_connect_sum;
1815 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1816 Integer j_column = columns[z];
1817 if (m_points_type[j_column] != TYPE_COARSE)
1819 if (weak_depends[z] != 2)
1822 Real mv = mat_values[z];
1823 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1824 Integer k_column = depends[row][z2];
1827 if (m_points_type[k_column] != TYPE_FINE)
1829 Real sum_coarse = 0.0;
1834 for (
Integer z3 = 0, zs3 = depends[row].size(); z3 < zs3; ++z3) {
1835 Integer m_column = depends[row][z3];
1838 if (m_points_type[m_column] == TYPE_COARSE) {
1839 Real w = m_fine_matrix.value(k_column, m_column);
1851 sum_coarse += math::abs(w);
1859 Real akj = m_fine_matrix.value(k_column, j_column);
1860 bool do_add =
false;
1862 if ((akj * sign) < 0.0)
1868 akj = math::abs(akj);
1873 to_add = math::divide(m_fine_matrix.value(row, k_column) * akj, sum_coarse);
1877 Real weight = -(mv + num_add) / (diag + weak_connect_sum);
1878 Integer new_column = points_in_coarse[j_column];
1884 if (new_column >= nb_coarse || new_column < 0)
1885 fatal() <<
" BAD COLUMN for fine point column=" << new_column <<
" nb=" << nb_coarse
1886 <<
" jcolumn=" << j_column;
1887 prolongation_matrix_columns.add(new_column);
1888 prolongation_matrix_values.add(weight);
1894 Integer column = points_in_coarse[row];
1895 if (column >= nb_coarse || column < 0)
1896 fatal() <<
" BAD COLUMN for coarse point j=" << column <<
" nb=" << nb_coarse
1898 prolongation_matrix_columns.add(column);
1899 prolongation_matrix_values.add(1.0);
1902 prolongation_matrix_rows_size[row] = nb_column;
1905 m_prolongation_matrix = Matrix(nb_row, nb_coarse);
1906 m_prolongation_matrix.setRowsSize(prolongation_matrix_rows_size);
1908 m_prolongation_matrix.setValues(prolongation_matrix_columns, prolongation_matrix_values);
1917 for (
Integer i = 0; i < n; ++i) {
1918 ostr() <<
"PROLONG I=" << i <<
" ";
1919 for (
Integer j = p_rows[i]; j < p_rows[i + 1]; ++j) {
1921 ostr() <<
" " << p_columns[j] <<
" " << p_values[j];
1923 ostr() <<
" index=" << index <<
'\n';
1925 info() <<
"PROLONG\n"
1929 MatrixOperation2 mat_op2;
1931 m_restriction_matrix = mat_op2.transposeFast(m_prolongation_matrix);
1933 m_restriction_matrix = mat_op2.transpose(m_prolongation_matrix);
1936 ostr() <<
"PROLONGATION_MATRIX ";
1937 m_prolongation_matrix.dump(ostr());
1939 ostr() <<
"RESTRICTION_MATRIX ";
1940 m_restriction_matrix.dump(ostr());
1941 info() << ostr.str();
1946 const bool old =
false;
1948 Matrix n1 = mat_op2.matrixMatrixProductFast(m_fine_matrix, m_prolongation_matrix);
1952 info() <<
"N1_MATRIX " << ostr.str();
1954 m_coarse_matrix = mat_op2.matrixMatrixProductFast(m_restriction_matrix, n1);
1957 m_coarse_matrix = mat_op2.applyGalerkinOperator2(m_restriction_matrix, m_fine_matrix, m_prolongation_matrix);
1960 m_coarse_matrix.dump(ostr());
1961 info() <<
"level= " << m_level <<
" COARSE_MATRIX=" << ostr.str();
1977void AMGPreconditioner::
1980 m_amg->solve(vec, out_vec);
1986void AMGPreconditioner::
1987build(
const Matrix& matrix)
1990 m_amg =
new AMG(m_trace_mng);
1991 m_amg->build(matrix);
2010build(
const Matrix& matrix)
2013 m_amg =
new AMG(m_trace_mng);
2014 m_amg->build(matrix);
2023 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.
bool isZero(const BuiltInProxy< _Type > &a)
Teste si une valeur est exactement égale à zéro.
apfloat sqrt(apfloat v)
Racine carrée de v.
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.