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];
418 if (a_marker[i2] != ic) {
423 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
424 Integer i3 = right_matrix_columns[jj3];
430 if (p_marker[i3] < jj_row_begining) {
431 p_marker[i3] = jj_counter;
438 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
440 static Integer total_rap_size = 0;
441 total_rap_size += jj_counter;
443 std::cout <<
"** RAP_SIZE=" << jj_counter <<
" TOTAL=" << total_rap_size <<
'\n';
444 Matrix new_matrix(nb_final_row, nb_final_row);
445 new_matrix.setRowsSize(new_matrix_rows_size);
455 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
457 p_marker[ic] = jj_counter;
458 jj_row_begining = jj_counter;
459 new_matrix_columns[jj_counter] = ic;
460 new_matrix_values[jj_counter] = 0.0;
463 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
464 Integer i1 = left_matrix_columns[jj1];
465 Real r_entry = left_matrix_values[jj1];
468 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
469 Integer i2 = matrix_columns[jj2];
470 Real r_a_product = r_entry * matrix_values[jj2];
475 if (a_marker[i2] != ic) {
480 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
481 Integer i3 = right_matrix_columns[jj3];
482 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
488 if (p_marker[i3] < jj_row_begining) {
489 p_marker[i3] = jj_counter;
490 new_matrix_values[jj_counter] = r_a_p_product;
491 new_matrix_columns[jj_counter] = i3;
495 new_matrix_values[p_marker[i3]] += r_a_p_product;
504 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
505 Integer i3 = right_matrix_columns[jj3];
506 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
507 new_matrix_values[p_marker[i3]] += r_a_p_product;
520applyGalerkinOperator2(
const Matrix& left_matrix,
const Matrix& matrix,
521 const Matrix& right_matrix)
523 Integer nb_original_row = matrix.nbRow();
524 Integer nb_final_row = left_matrix.nbRow();
530 const Integer* left_matrix_rows = left_matrix.rowsIndex().data();
531 const Integer* left_matrix_columns = left_matrix.columns().data();
532 const Real* left_matrix_values = left_matrix.values().data();
534 const Integer* right_matrix_rows = right_matrix.rowsIndex().data();
535 const Integer* right_matrix_columns = right_matrix.columns().data();
536 const Real* right_matrix_values = right_matrix.values().data();
538 const Integer* matrix_rows = matrix.rowsIndex().data();
539 const Integer* matrix_columns = matrix.columns().data();
540 const Real* matrix_values = matrix.values().data();
549 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
551 p_marker[ic] = jj_counter;
552 jj_row_begining = jj_counter;
556 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
557 Integer i1 = left_matrix_columns[jj1];
560 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
561 Integer i2 = matrix_columns[jj2];
566 if (a_marker[i2] != ic) {
571 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
572 Integer i3 = right_matrix_columns[jj3];
578 if (p_marker[i3] < jj_row_begining) {
579 p_marker[i3] = jj_counter;
586 new_matrix_rows_size[ic] = jj_counter - jj_row_begining;
589 Matrix new_matrix(nb_final_row, nb_final_row);
590 new_matrix.setRowsSize(new_matrix_rows_size);
593 Integer* ARCANE_RESTRICT new_matrix_columns = new_matrix.columns().data();
594 Real* ARCANE_RESTRICT new_matrix_values = new_matrix.values().data();
600 for (
Integer ic = 0; ic < nb_final_row; ++ic) {
602 p_marker[ic] = jj_counter;
603 jj_row_begining = jj_counter;
604 new_matrix_columns[jj_counter] = ic;
605 new_matrix_values[jj_counter] = 0.0;
608 for (
Integer jj1 = left_matrix_rows[ic]; jj1 < left_matrix_rows[ic + 1]; ++jj1) {
609 Integer i1 = left_matrix_columns[jj1];
610 Real r_entry = left_matrix_values[jj1];
613 for (
Integer jj2 = matrix_rows[i1]; jj2 < matrix_rows[i1 + 1]; ++jj2) {
614 Integer i2 = matrix_columns[jj2];
615 Real r_a_product = r_entry * matrix_values[jj2];
620 if (a_marker[i2] != ic) {
625 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
626 Integer i3 = right_matrix_columns[jj3];
627 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
633 if (p_marker[i3] < jj_row_begining) {
634 p_marker[i3] = jj_counter;
635 new_matrix_values[jj_counter] = r_a_p_product;
636 new_matrix_columns[jj_counter] = i3;
640 new_matrix_values[p_marker[i3]] += r_a_p_product;
649 for (
Integer jj3 = right_matrix_rows[i2]; jj3 < right_matrix_rows[i2 + 1]; ++jj3) {
650 Integer i3 = right_matrix_columns[jj3];
651 Real r_a_p_product = r_a_product * right_matrix_values[jj3];
652 new_matrix_values[p_marker[i3]] += r_a_p_product;
669 TYPE_SPECIAL_FINE = 3
683 , m_is_verbose(
false)
685 virtual ~AMGLevel() {}
689 virtual void buildLevel(
Matrix matrix,
Real alpha);
695 return m_fine_matrix;
699 return m_coarse_matrix;
701 Matrix prolongationMatrix()
703 return m_prolongation_matrix;
705 Matrix restrictionMatrix()
707 return m_restriction_matrix;
711 return m_coarse_matrix.nbRow();
715 return m_points_type;
717 void printLevelInfo();
724 Matrix m_prolongation_matrix;
725 Matrix m_restriction_matrix;
732 void _buildCoarsePoints(
Real alpha,
739 void _printLevelInfo(
Matrix matrix);
757 void build(
Matrix matrix);
774 void _relaxGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x,
776 void _relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x);
777 void _printResidualInfo(
const Matrix& matrix,
const Vector& vector_b,
787 for (
Integer i = 0; i < m_levels.size(); ++i)
797 Matrix current_matrix = matrix;
799 for (
Integer i = 1; i < 100; ++i) {
800 AMGLevel* level =
new AMGLevel(
traceMng(), i);
801 level->buildLevel(current_matrix, 0.25);
803 Integer nb_coarse_point = level->nbCoarsePoint();
804 if (nb_coarse_point < 20)
806 current_matrix = level->coarseMatrix();
822 for (
Integer i = 0; i < 20; ++i)
823 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
" X=" << vector_x.values()[i] <<
'\n';
824 for (
Integer i = 0; i < v_values.size(); ++i)
825 if (math::abs(v_values[i]) > 1e-5)
826 ostr() <<
"VECTOR_F_" << i <<
" = " << v_values[i] <<
'\n';
827 info() <<
"VECTOR_F\n"
831 _solve(vector_b, vector_x, 0);
850 Vector r(vector_x.size());
851 MatrixOperation mat_op;
852 for (
Integer i = 0; i < nb_relax; ++i) {
854 mat_op.matrixVectorProduct(matrix, vector_x, r);
855 mat_op.negateVector(r);
856 mat_op.addVector(r, vector_b);
859 mat_op.addVector(vector_x, r);
870 Real epsilon = 1.0e-10;
871 DiagonalPreconditioner p(matrix);
872 ConjugateGradientSolver solver;
873 solver.setMaxIteration(nb_relax);
881 solver.solve(matrix, vector_b, vector_x, epsilon, &p);
905 Integer nb_row = matrix.nbRow();
911 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
912 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
" T=" << tmp_values[i] <<
'\n';
913 info() <<
"B = X=" << x_values.data() <<
" T=" << tmp_values.data() <<
"\n"
916 Real one_minus_weight = 1.0 - weight;
917 for (
Integer row = 0; row < nb_row; ++row) {
918 Real diag = mat_values[rows[row]];
921 Real res = b_values[row];
922 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
924 res -= mat_values[j] * tmp_values[col];
926 x_values[row] *= one_minus_weight;
927 x_values[row] += (weight * res) / diag;
932 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
933 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
956 const Integer* columns = matrix.columns().data();
957 const Real* mat_values = matrix.values().data();
959 Real* ARCANE_RESTRICT x_values = vector_x.values().data();
960 const Real* b_values = vector_b.values().data();
961 const Integer* points_type = points_type2.data();
964 Integer nb_row = matrix.nbRow();
966 info() <<
" RELAX nb_relax=" <<
" nb_row=" << nb_row
967 <<
" point_type=" << point_type;
970 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
971 ostr() <<
"BEFORE_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
975 for (
Integer row = 0; row < nb_row; ++row) {
976 Real diag = mat_values[rows[row]];
977 if (points_type[row] != point_type ||
math::isZero(diag))
979 Real res = b_values[row];
980 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
982 res -= mat_values[j] * x_values[col];
984 x_values[row] = res / diag;
989 for (
Integer i = (nb_row - 1); i > (nb_row - v); --i)
990 ostr() <<
"AFTER_B=" << i <<
"=" << b_values[i] <<
" U=" << x_values[i] <<
'\n';
1000_relaxSymmetricGaussSeidel(
const Matrix& matrix,
const Vector& vector_b,
Vector& vector_x)
1009 Integer nb_row = matrix.nbRow();
1012 for (
Integer row = 0; row < nb_row; ++row) {
1013 Real diag = mat_values[rows[row]];
1016 Real res = b_values[row];
1017 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1019 res -= mat_values[j] * x_values[col];
1021 x_values[row] = res / diag;
1024 for (
Integer row = nb_row - 1; row > -1; --row) {
1025 Real diag = mat_values[rows[row]];
1028 Real res = b_values[row];
1029 for (
Integer j = rows[row] + 1; j < rows[row + 1]; ++j) {
1031 res -= mat_values[j] * x_values[col];
1033 x_values[row] = res / diag;
1043 AMGLevel* current_level = m_levels[level];
1045 Integer nb_coarse = current_level->nbCoarsePoint();
1046 Matrix fine_matrix = current_level->fineMatrix();
1047 Matrix restriction_matrix = current_level->restrictionMatrix();
1048 Matrix coarse_matrix = current_level->coarseMatrix();
1049 Matrix prolongation_matrix = current_level->prolongationMatrix();
1051 Integer new_nb_row = nb_coarse;
1052 Vector new_b(new_nb_row);
1053 Vector new_x(new_nb_row);
1054 Vector tmp(vector_size);
1056 MatrixOperation mat_op;
1058 bool is_final_level = (level + 1) == m_levels.size();
1060 const bool use_gauss_seidel =
false;
1062 Real jacobi_weight = 2.0 / 3.0;
1063 if (use_gauss_seidel) {
1064 for (
Integer i = 0; i < nb_relax1; ++i)
1065 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1066 for (
Integer i = 0; i < nb_relax1; ++i)
1067 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1072 for (
Integer i = 0; i < nb_relax1; ++i) {
1074 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1085 mat_op.matrixVectorProduct(fine_matrix, vector_x, tmp);
1088 mat_op.negateVector(tmp);
1089 mat_op.addVector(tmp, vector_b);
1092 mat_op.matrixVectorProduct(restriction_matrix, tmp, new_b);
1095 info() << ostr.str();
1102 if (is_final_level) {
1108 ds.solve(coarse_matrix, new_b, new_x);
1112 Real epsilon = 1.0e-14;
1113 DiagonalPreconditioner p(coarse_matrix);
1114 ConjugateGradientSolver solver;
1116 new_x.values().fill(0.0);
1117 solver.solve(coarse_matrix, new_b, new_x, epsilon, &p);
1124 info() <<
"SOLVE COARSE MATRIX nb_iter=" << solver.nbIteration();
1130 new_x.values().fill(0.0);
1131 _solve(new_b, new_x, level + 1);
1136 mat_op.matrixVectorProduct(prolongation_matrix, new_x, tmp);
1137 mat_op.addVector(vector_x, tmp);
1146 if (use_gauss_seidel) {
1147 for (
Integer i = 0; i < nb_relax1; ++i)
1148 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_FINE, current_level->pointsType());
1149 for (
Integer i = 0; i < nb_relax1; ++i)
1150 _relaxGaussSeidel(fine_matrix, vector_b, vector_x, TYPE_COARSE, current_level->pointsType());
1155 for (
Integer i = 0; i < nb_relax1; ++i) {
1157 _relaxJacobi(fine_matrix, vector_b, vector_x, jacobi_weight);
1172 Vector tmp(b.size());
1174 MatrixOperation mat_op;
1175 mat_op.matrixVectorProduct(a, x, tmp);
1178 mat_op.negateVector(tmp);
1179 mat_op.addVector(tmp, b);
1180 Real r = mat_op.dot(tmp);
1183 for (
Integer i = 0; i < v; ++i)
1184 info() <<
"R_" << i <<
" = " << tmp.values()[i];
1186 info() <<
" AMG_RESIDUAL_NORM=" << r <<
" sqrt=" <<
math::sqrt(r);
1219 if (m_lambda == rhs.m_lambda)
1220 return m_index < rhs.m_index;
1221 return (m_lambda > rhs.m_lambda);
1231 _printLevelInfo(m_prolongation_matrix);
1232 _printLevelInfo(m_coarse_matrix);
1236_printLevelInfo(Matrix matrix)
1239 Integer nb_row = matrix.nbRow();
1240 Integer nb_column = matrix.nbColumn();
1250 max_val = values[0];
1251 min_val = values[0];
1254 Real max_row_sum = 0.0;
1255 Real min_row_sum = 0.0;
1256 for (
Integer row = 0; row < nb_row; ++row) {
1258 for (
Integer z = rows[row], zs = rows[row + 1]; z < zs; ++z) {
1268 max_row_sum = row_sum;
1269 min_row_sum = row_sum;
1271 if (row_sum > max_row_sum)
1272 max_row_sum = row_sum;
1273 if (row_sum < max_row_sum)
1274 min_row_sum = row_sum;
1279 ostr() <<
"level=" << m_level
1280 <<
" nb_row=" << nb_row
1281 <<
" nb_col=" << nb_column
1282 <<
" nb_nonzero=" << nb_value
1283 <<
" sparsity=" << sparsity
1284 <<
" min=" << min_val
1285 <<
" max=" << max_val
1286 <<
" min_row=" << min_row_sum
1287 <<
" max_row=" << max_row_sum;
1289 info() <<
"INFO: " << ostr.str();
1296_buildCoarsePoints(
Real alpha,
1298 UniqueArray<SharedArray<Integer>>& depends,
1304 Integer nb_row = m_fine_matrix.nbRow();
1308 UniqueArray<SharedArray<Integer>> influences(nb_row);
1309 depends.resize(nb_row);
1311 m_points_type.resize(nb_row);
1312 m_points_type.fill(TYPE_UNDEFINED);
1314 weak_depends.resize(mat_values.size());
1315 weak_depends.fill(0);
1317 const bool type_hypre =
true;
1319 rows_max_val.resize(nb_row);
1320 for (
Integer row = 0; row < nb_row; ++row) {
1323 Real diag_val = mat_values[rows_index[row]];
1325 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1327 Real mv = mat_values[z];
1339 rows_max_val[row] = max_val * alpha;
1341 rows_max_val[row] = min_val * alpha;
1344 rows_max_val[row] = max_val * alpha;
1347 for (
Integer row = 0; row < nb_row; ++row) {
1349 Real max_val = rows_max_val[row];
1350 Real diag_val = mat_values[rows_index[row]];
1351 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1353 Real mv = mat_values[z];
1355 if (diag_val < 0.0) {
1359 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1361 depends[row].add(column);
1362 influences[column].add(row);
1363 weak_depends[z] = 2;
1366 weak_depends[z] = 1;
1372 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1374 depends[row].add(column);
1375 influences[column].add(row);
1376 weak_depends[z] = 2;
1379 weak_depends[z] = 1;
1383 if (math::abs(mv) > max_val) {
1386 info() <<
" ADD INFLUENCE: ROW=" << row <<
" COL=" << column;
1388 depends[row].add(column);
1389 influences[column].add(row);
1390 weak_depends[z] = 2;
1393 weak_depends[z] = 1;
1405 ostr() <<
"GRAPH\n";
1406 for (
Integer i = 0; i < n; ++i) {
1407 ostr() <<
" GRAPH I=" << i <<
" ";
1408 for (
Integer j = 0; j < depends[i].size(); ++j) {
1410 ostr() <<
" " << depends[i][j];
1412 ostr() <<
" index=" << index <<
'\n';
1414 ostr() <<
"\n MAXTRIX\n";
1416 for (
Integer i = 0; i < n; ++i) {
1417 ostr() <<
"MATRIX I=" << i <<
" ";
1418 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1420 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1422 ostr() <<
" index=" << index <<
'\n';
1424 info() << ostr.str();
1431 m_is_verbose =
false;
1434 for (
Integer row = 0; row < nb_row; ++row) {
1435 if (depends[row].size() == 0) {
1436 m_points_type[row] = TYPE_FINE;
1439 info() <<
"FIRST MARK FINE point=" << row;
1444 for (
Integer row = 0; row < nb_row; ++row) {
1445 if (m_points_type[row] != TYPE_FINE && lambdas[row] <= 0) {
1446 m_points_type[row] = TYPE_FINE;
1449 info() <<
"INIT MARK FINE NULL MEASURE point=" << row <<
" measure=" << lambdas[row];
1450 for (
Integer j = 0, js = depends[row].size(); j < js; ++j) {
1451 Integer col = depends[row][j];
1452 if (m_points_type[col] != TYPE_FINE)
1456 printf(
"ADD MEASURE NULL point=%d measure=%d\n", (
int)col, lambdas[col]);
1462 typedef std::set<PointInfo> PointSet;
1463 PointSet undefined_points;
1464 for (
Integer i = 0; i < nb_row; ++i) {
1465 if (m_points_type[i] == TYPE_UNDEFINED)
1466 undefined_points.insert(PointInfo(lambdas[i], i));
1469 while (nb_done < nb_row && nb_iter < 100000) {
1483 if (undefined_points.empty())
1484 fatal() <<
"Undefined points is empty";
1485 PointSet::iterator max_point = undefined_points.begin();
1486 Integer max_value_index = max_point->m_index;
1487 Integer max_value = max_point->m_lambda;
1488 m_points_type[max_value_index] = TYPE_COARSE;
1491 undefined_points.erase(max_point);
1493 std::cout <<
"MARK COARSE point=" << max_value_index
1494 <<
" measure=" << max_value
1495 <<
" left=" << (nb_row - nb_done)
1498 for (
Integer i = 0, is = point_influences.size(); i < is; ++i) {
1500 Integer pt = point_influences[i];
1502 if (m_points_type[pt] == TYPE_UNDEFINED) {
1503 m_points_type[pt] = TYPE_FINE;
1506 undefined_points.erase(PointInfo(lambdas[pt], pt));
1508 std::cout <<
"MARK FINE point=" << pt
1509 <<
" measure=" << lambdas[pt]
1510 <<
" left=" << (nb_row - nb_done)
1512 for (
Integer z = 0, zs = depends[pt].size(); z < zs; ++z) {
1516 if (m_points_type[pt2] == TYPE_UNDEFINED) {
1517 undefined_points.erase(PointInfo(lambdas[pt2], pt2));
1519 undefined_points.insert(PointInfo(lambdas[pt2], pt2));
1524 for (
Integer i = 0, is = depends[max_value_index].size(); i < is; ++i) {
1525 Integer pt3 = depends[max_value_index][i];
1526 if (m_points_type[pt3] == TYPE_UNDEFINED) {
1527 undefined_points.erase(PointInfo(lambdas[pt3], pt3));
1532 undefined_points.insert(PointInfo(lambdas[pt3], pt3));
1536 info() <<
"LAMBDA MAX = " << max_value <<
" index=" << max_value_index <<
" nb_done=" << nb_done;
1541 info() <<
"NB ROW=" << nb_row <<
" nb_done=" << nb_done <<
" nb_fine=" << nb_fine
1542 <<
" nb_coarse=" << nb_coarse <<
" nb_iter=" << nb_iter;
1543 if (nb_done != nb_row)
1544 fatal() <<
"Can not find all COARSE or FINE points nb_done=" << nb_done <<
" nb_point=" << nb_row;
1551 points_marker.fill(-1);
1554 bool C_i_nonempty =
false;
1555 for (
Integer row = 0; row < nb_row; ++row) {
1556 if ((ci_tilde_mark |= row))
1558 if (m_points_type[row] == TYPE_FINE) {
1559 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1562 Integer col = depends[row][z];
1563 if (m_points_type[col] == TYPE_COARSE)
1564 points_marker[col] = row;
1566 for (
Integer z = 0, zs = depends[row].size(); z < zs; ++z) {
1569 Integer col = depends[row][z];
1570 if (m_points_type[col] == TYPE_FINE) {
1571 bool set_empty =
true;
1572 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1575 Integer col2 = depends[row][z2];
1576 if (points_marker[col2] == row) {
1583 m_points_type[row] = TYPE_COARSE;
1585 if (ci_tilde > -1) {
1586 m_points_type[ci_tilde] = TYPE_FINE;
1588 printf(
"SECOND PASS MARK FINE point=%d\n", ci_tilde);
1591 C_i_nonempty =
false;
1595 ci_tilde_mark = row;
1596 m_points_type[col] = TYPE_COARSE;
1598 printf(
"SECOND PASS MARK COARSE2 point=%d\n", col);
1599 C_i_nonempty =
true;
1612 static int matrix_number = 0;
1614 info() <<
"READ HYPRE CF_marker n=" << matrix_number;
1615 StringBuilder fname(
"CF_marker-");
1616 fname += matrix_number;
1617 std::ifstream ifile(fname.toString().localstr());
1619 ifile >> std::ws >> nb_read_point >> std::ws;
1620 if (nb_read_point != nb_row)
1621 fatal() <<
"Bad number of points for reading Hypre CF_marker read=" << nb_read_point
1622 <<
" expected=" << nb_row <<
" matrix_number=" << matrix_number;
1625 for (
Integer i = 0; i < nb_row; ++i) {
1629 fatal() <<
"Can not read marker point number=" << i;
1630 if (pt == (-1) || pt == (-3)) {
1631 m_points_type[i] = TYPE_FINE;
1635 m_points_type[i] = TYPE_COARSE;
1639 fatal() <<
"Bad value read=" << pt <<
" expected 1 or -1";
1645 for (
Integer i = 0; i < nb_row; ++i) {
1646 if (m_points_type[i] == TYPE_UNDEFINED)
1647 fatal() <<
" Point " << i <<
" is undefined";
1648 if (m_points_type[i] != TYPE_FINE) {
1656 for(
Integer z=0, zs=depends[i].size(); z<zs; ++z ){
1657 if (m_points_type[depends[i][z]]==TYPE_COARSE){
1669 for (
Integer i = 0; i < nb_row; ++i) {
1670 ostr() <<
" POINT i=" << i <<
" type=" << m_points_type[i] <<
" depends=";
1671 for (
Integer j = 0, js = depends[i].size(); j < js; ++j)
1672 ostr() << depends[i][j] <<
' ';
1675 info() << ostr.str();
1678 nb_fine = nb_row - nb_coarse;
1680 for (
Integer i = 0; i < nb_row; ++i)
1681 graph_size += depends[i].size();
1683 info() <<
" NB COARSE=" << nb_coarse <<
" NB FINE=" << nb_fine
1684 <<
" MAXTRIX NON_ZEROS=" << m_fine_matrix.rowsIndex()[nb_row]
1685 <<
" GRAPH_SIZE=" << graph_size;
1686 bool dump_matrix =
false;
1687 bool has_error =
false;
1688 if (nb_fine == 0 || graph_size == 0) {
1698 ostr() <<
"GRAPH\n";
1699 for (
Integer i = 0; i < n; ++i) {
1700 ostr() <<
" GRAPH I=" << i <<
" ";
1701 for (
Integer j = 0; j < depends[i].size(); ++j) {
1703 ostr() <<
" " << depends[i][j];
1705 ostr() <<
" index=" << index <<
'\n';
1708 ostr() <<
"\n MAXTRIX\n";
1710 for (
Integer i = 0; i < n; ++i) {
1711 ostr() <<
"MATRIX I=" << i <<
" ";
1712 for (
Integer j = rows_index[i]; j < rows_index[i + 1]; ++j) {
1714 ostr() <<
" " << columns[j] <<
" " << mat_values[j];
1716 ostr() <<
" index=" << index <<
'\n';
1718 info() << ostr.str();
1721 throw FatalErrorException(
"AMGLevel::_buildCoarsePoints");
1734 m_fine_matrix = matrix;
1737 matrix.sortDiagonale();
1741 UniqueArray<SharedArray<Integer>> depends;
1744 _buildCoarsePoints(alpha, rows_max_val, depends, weak_depends);
1745 _buildInterpolationMatrix(rows_max_val, depends, weak_depends);
1753 UniqueArray<SharedArray<Integer>>& depends,
1756 ARCANE_UNUSED(rows_max_val);
1761 Integer nb_row = m_fine_matrix.nbRow();
1764 points_in_coarse.fill(-1);
1769 for (
Integer i = 0; i < nb_row; ++i) {
1770 if (m_points_type[i] == TYPE_COARSE) {
1771 points_in_coarse[i] = nb_coarse;
1776 bool type_hypre =
true;
1783 for (
Integer row = 0; row < nb_row; ++row) {
1785 if (m_points_type[row] == TYPE_FINE) {
1786 Real weak_connect_sum = 0.0;
1788 Real diag = mat_values[rows_index[row]];
1792 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1794 if (weak_depends[z] == 1) {
1795 Real mv = mat_values[z];
1797 weak_connect_sum += mv;
1800 weak_connect_sum += mv;
1808 info() <<
"ROW row=" << row <<
" weak_connect_sum=" << weak_connect_sum;
1811 for (
Integer z = rows_index[row] + 1, zs = rows_index[row + 1]; z < zs; ++z) {
1812 Integer j_column = columns[z];
1813 if (m_points_type[j_column] != TYPE_COARSE)
1815 if (weak_depends[z] != 2)
1818 Real mv = mat_values[z];
1819 for (
Integer z2 = 0, zs2 = depends[row].size(); z2 < zs2; ++z2) {
1820 Integer k_column = depends[row][z2];
1823 if (m_points_type[k_column] != TYPE_FINE)
1825 Real sum_coarse = 0.0;
1830 for (
Integer z3 = 0, zs3 = depends[row].size(); z3 < zs3; ++z3) {
1831 Integer m_column = depends[row][z3];
1834 if (m_points_type[m_column] == TYPE_COARSE) {
1835 Real w = m_fine_matrix.value(k_column, m_column);
1847 sum_coarse += math::abs(w);
1855 Real akj = m_fine_matrix.value(k_column, j_column);
1856 bool do_add =
false;
1858 if ((akj * sign) < 0.0)
1864 akj = math::abs(akj);
1869 to_add = math::divide(m_fine_matrix.value(row, k_column) * akj, sum_coarse);
1873 Real weight = -(mv + num_add) / (diag + weak_connect_sum);
1874 Integer new_column = points_in_coarse[j_column];
1880 if (new_column >= nb_coarse || new_column < 0)
1881 fatal() <<
" BAD COLUMN for fine point column=" << new_column <<
" nb=" << nb_coarse
1882 <<
" jcolumn=" << j_column;
1883 prolongation_matrix_columns.add(new_column);
1884 prolongation_matrix_values.add(weight);
1890 Integer column = points_in_coarse[row];
1891 if (column >= nb_coarse || column < 0)
1892 fatal() <<
" BAD COLUMN for coarse point j=" << column <<
" nb=" << nb_coarse
1894 prolongation_matrix_columns.add(column);
1895 prolongation_matrix_values.add(1.0);
1898 prolongation_matrix_rows_size[row] = nb_column;
1901 m_prolongation_matrix = Matrix(nb_row, nb_coarse);
1902 m_prolongation_matrix.setRowsSize(prolongation_matrix_rows_size);
1904 m_prolongation_matrix.setValues(prolongation_matrix_columns, prolongation_matrix_values);
1913 for (
Integer i = 0; i < n; ++i) {
1914 ostr() <<
"PROLONG I=" << i <<
" ";
1915 for (
Integer j = p_rows[i]; j < p_rows[i + 1]; ++j) {
1917 ostr() <<
" " << p_columns[j] <<
" " << p_values[j];
1919 ostr() <<
" index=" << index <<
'\n';
1921 info() <<
"PROLONG\n"
1925 MatrixOperation2 mat_op2;
1927 m_restriction_matrix = mat_op2.transposeFast(m_prolongation_matrix);
1929 m_restriction_matrix = mat_op2.transpose(m_prolongation_matrix);
1932 ostr() <<
"PROLONGATION_MATRIX ";
1933 m_prolongation_matrix.dump(ostr());
1935 ostr() <<
"RESTRICTION_MATRIX ";
1936 m_restriction_matrix.dump(ostr());
1937 info() << ostr.str();
1942 const bool old =
false;
1944 Matrix n1 = mat_op2.matrixMatrixProductFast(m_fine_matrix, m_prolongation_matrix);
1948 info() <<
"N1_MATRIX " << ostr.str();
1950 m_coarse_matrix = mat_op2.matrixMatrixProductFast(m_restriction_matrix, n1);
1953 m_coarse_matrix = mat_op2.applyGalerkinOperator2(m_restriction_matrix, m_fine_matrix, m_prolongation_matrix);
1956 m_coarse_matrix.dump(ostr());
1957 info() <<
"level= " << m_level <<
" COARSE_MATRIX=" << ostr.str();
1973void AMGPreconditioner::
1976 m_amg->solve(vec, out_vec);
1982void AMGPreconditioner::
1983build(
const Matrix& matrix)
1986 m_amg =
new AMG(m_trace_mng);
1987 m_amg->build(matrix);
2006build(
const Matrix& matrix)
2009 m_amg =
new AMG(m_trace_mng);
2010 m_amg->build(matrix);
2019 m_amg->solve(vector_b, vector_x);
#define ARCANE_THROW(exception_class,...)
Macro for throwing an exception with formatting.
#define ARCANE_FATAL(...)
Macro throwing a FatalErrorException.
void fill(const T &o) noexcept
Fills the array with the value o.
constexpr const_pointer data() const noexcept
Pointer to the allocated memory.
constexpr Integer size() const noexcept
Number of elements in the array.
bool operator<(const PointInfo &rhs) const
Matrix class, to be used by user.
1D vector of data with reference semantics.
TraceAccessor(ITraceMng *m)
Constructs an accessor via the trace manager m.
TraceMessage fatal() const
Flow for a fatal error message.
TraceMessage info() const
Flow for an information message.
ITraceMng * traceMng() const
Trace manager.
1D data vector with value semantics (STL style).
__host__ __device__ Real2 min(Real2 a, Real2 b)
Returns the minimum of two Real2.
Namespace for mathematical functions.
bool isZero(const BuiltInProxy< _Type > &a)
Tests if a value is exactly equal to zero.
apfloat sqrt(apfloat v)
Square root of v.
Int32 Integer
Type representing an integer.
ConstArrayView< Int32 > Int32ConstArrayView
C equivalent of a 1D array of 32-bit integers.
ArrayView< Integer > IntegerArrayView
C equivalent of a 1D array of integers.
Array< Integer > IntegerArray
Dynamic one-dimensional array of integers.
UniqueArray< Int32 > Int32UniqueArray
Dynamic 1D array of 32-bit integers.
UniqueArray< Real > RealUniqueArray
Dynamic 1D array of reals.
double Real
Type representing a real number.
Array< Real > RealArray
Dynamic one-dimensional array of reals.
UniqueArray< Integer > IntegerUniqueArray
Dynamic 1D array of integers.
ConstArrayView< Integer > IntegerConstArrayView
C equivalent of a 1D array of integers.
ArrayView< Real > RealArrayView
C equivalent of a 1D array of reals.
ConstArrayView< Real > RealConstArrayView
C equivalent of a 1D array of reals.