15 #include "../general/forall.hpp"
16 #include "../general/table.hpp"
17 #include "../general/sort_pairs.hpp"
33 Rows(new RowNode *[nrows]),
45 for (
int i = 0; i < nrows; i++)
50 #ifdef MFEM_USE_MEMALLOC
65 A.
Wrap(data,
I[height],
true);
67 #ifdef MFEM_USE_MEMALLOC
73 bool ownij,
bool owna,
bool issorted)
83 A.
Wrap(data,
I[height], owna);
85 #ifdef MFEM_USE_MEMALLOC
93 for (
int i=0; i<nnz; ++i)
108 #ifdef MFEM_USE_MEMALLOC
112 J.
New(nrows * rowsize);
113 A.
New(nrows * rowsize);
115 for (
int i = 0; i <= nrows; i++)
145 #ifdef MFEM_USE_MEMALLOC
151 #ifdef MFEM_USE_MEMALLOC
155 for (
int i = 0; i <
height; i++)
157 RowNode **node_pp = &
Rows[i];
158 for (RowNode *node_p = mat.
Rows[i]; node_p; node_p = node_p->Prev)
160 #ifdef MFEM_USE_MEMALLOC
163 RowNode *new_node_p =
new RowNode;
165 new_node_p->Value = node_p->Value;
166 new_node_p->Column = node_p->Column;
167 *node_pp = new_node_p;
168 node_pp = &new_node_p->Prev;
194 #ifdef MFEM_USE_MEMALLOC
201 for (
int i = 0; i <=
height; i++)
206 for (
int r=0; r<
height; r++)
225 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
246 #ifdef MFEM_USE_MEMALLOC
262 return I[gi+1]-
I[gi];
266 RowNode *row =
Rows[gi];
267 for ( ; row != NULL; row = row->Prev)
268 if (row->Value != 0.0)
281 for (
int i=0; i <
height; ++i)
283 rowSize =
I[i+1]-
I[i];
284 out = (out > rowSize) ? out : rowSize;
289 for (
int i=0; i <
height; ++i)
292 out = (out > rowSize) ? out : rowSize;
301 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
308 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
315 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
322 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
329 if (newWidth ==
width)
334 else if (newWidth == -1)
340 else if (newWidth >
width)
351 ColPtrJ =
static_cast<int *
>(NULL);
359 "The new width needs to be bigger or equal to the actual width");
367 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
375 for (
int j = 0, i = 0; i <
height; i++)
379 for (
int k = 0; k < row.
Size(); k++)
385 for (
int k = 0; k < row.
Size(); k++, j++)
396 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
398 for (
int row = 0, end = 0; row <
height; row++)
402 for (j = start;
true; j++)
404 MFEM_VERIFY(j < end,
"diagonal entry not found in row = " << row);
405 if (
J[j] == row) {
break; }
407 const double diag =
A[j];
408 for ( ; j > start; j--)
430 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
431 "Trying to access element outside of the matrix. "
432 <<
"height = " <<
height <<
", "
433 <<
"width = " <<
width <<
", "
434 <<
"i = " << i <<
", "
437 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
439 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
447 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
453 static const double zero = 0.0;
455 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
456 "Trying to access element outside of the matrix. "
457 <<
"height = " <<
height <<
", "
458 <<
"width = " <<
width <<
", "
459 <<
"i = " << i <<
", "
464 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
474 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
476 if (node_p->Column == j)
478 return node_p->Value;
488 MFEM_VERIFY(
height ==
width,
"Matrix must be square, not height = "
490 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
495 for (
int i = 0; i <
height; i++)
499 for (j =
I[i]; j < end; j++)
517 int num_rows = this->
Height();
518 int num_cols = this->
Width();
533 for (
int r=0; r<
height; r++)
538 for (
int cj=0; cj<this->
RowSize(r); cj++)
540 B(r, col[cj]) = val[cj];
554 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
555 <<
") must match matrix width (" <<
width <<
")");
556 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
557 <<
") must match matrix height (" <<
height <<
")");
561 const double *xp = x.
GetData();
565 for (
int i = 0; i <
height; i++)
567 RowNode *row =
Rows[i];
569 for ( ; row != NULL; row = row->Prev)
571 b += row->Value * xp[row->Column];
579 #ifndef MFEM_USE_LEGACY_OPENMP
582 auto d_I =
Read(
I, height+1);
583 auto d_J =
Read(
J, nnz);
584 auto d_A =
Read(
A, nnz);
587 MFEM_FORALL(i, height,
590 const int end = d_I[i+1];
591 for (
int j = d_I[i]; j < end; j++)
593 d += d_A[j] * d_x[d_J[j]];
598 const double *Ap =
A, *xp = x.
GetData();
600 const int *Jp =
J, *Ip =
I;
602 #pragma omp parallel for
603 for (
int i = 0; i <
height; i++)
606 const int end = Ip[i+1];
607 for (
int j = Ip[i]; j < end; j++)
609 d += Ap[j] * xp[Jp[j]];
624 const double a)
const
627 <<
") must match matrix height (" <<
height <<
")");
628 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
629 <<
") must match matrix width (" <<
width <<
")");
635 for (
int i = 0; i <
height; i++)
637 RowNode *row =
Rows[i];
639 for ( ; row != NULL; row = row->Prev)
641 yp[row->Column] += row->Value * b;
654 "enabled; see BuildTranspose() for details.");
655 for (
int i = 0; i <
height; i++)
657 const double xi = a * x[i];
658 const int end =
I[i+1];
659 for (
int j =
I[i]; j < end; j++)
685 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
687 const int n = rows.
Size();
689 auto d_rows = rows.
Read();
691 auto d_J =
Read(
J, nnz);
692 auto d_A =
Read(
A, nnz);
694 auto d_y = y.
Write();
697 const int r = d_rows[i];
698 const int end = d_I[r + 1];
700 for (
int j = d_I[r]; j < end; j++)
702 a += d_A[j] * d_x[d_J[j]];
711 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
713 for (
int i = 0; i < rows.
Size(); i++)
718 for (
int j =
I[r]; j < end; j++)
720 val +=
A[j] * x(
J[j]);
728 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
729 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
730 <<
") must match matrix width (" <<
Width() <<
")");
736 auto d_I =
Read(
I, height+1);
737 auto d_J =
Read(
J, nnz);
740 MFEM_FORALL(i, height,
743 const int end = d_I[i+1];
744 for (
int j = d_I[i]; j < end; j++)
759 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
760 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
761 <<
") must match matrix height (" <<
Height() <<
")");
766 for (
int i = 0; i <
Height(); i++)
771 for (
int j =
I[i]; j < end; j++)
782 <<
" must be equal to Width() = " <<
Width());
784 <<
" must be equal to Height() = " <<
Height());
797 for (
int i = 0; i <
height; i++)
802 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
809 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
811 a += np->Value * x(np->Column);
822 for (
int i = 0; i <
height; i++)
827 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
834 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
845 MFEM_VERIFY(irow <
height,
846 "row " << irow <<
" not in matrix with height " <<
height);
851 for (
int j =
I[irow], end =
I[irow+1]; j < end; j++)
858 for (RowNode *np =
Rows[irow]; np != NULL; np = np->Prev)
860 a += fabs(np->Value);
869 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
871 atol = std::abs(tol);
873 fix_empty_rows =
height ==
width ? fix_empty_rows :
false;
881 for (i = 0, nz = 0; i <
height; i++)
884 for (j =
I[i]; j <
I[i+1]; j++)
885 if (std::abs(
A[j]) > atol)
890 if (fix_empty_rows && !found) { nz++; }
895 newA =
new double[nz];
898 for (i = 0, nz = 0; i <
height; i++)
902 for (j =
I[i]; j <
I[i+1]; j++)
903 if (std::abs(
A[j]) > atol)
908 if ( lastCol > newJ[nz] )
915 if (fix_empty_rows && !found)
923 I.
Wrap(newI, height+1,
true);
924 J.
Wrap(newJ,
I[height],
true);
925 A.
Wrap(newA,
I[height],
true);
943 for (i = 1; i <=
height; i++)
946 for (aux =
Rows[i-1]; aux != NULL; aux = aux->Prev)
948 if (!skip_zeros || aux->Value != 0.0) { nr++; }
950 if (fix_empty_rows && !nr) { nr = 1; }
959 for (j = i = 0; i <
height; i++)
963 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
965 if (!skip_zeros || aux->Value != 0.0)
970 if ( lastCol >
J[j] )
980 if (fix_empty_rows && !nr)
988 #ifdef MFEM_USE_MEMALLOC
992 for (i = 0; i <
height; i++)
994 RowNode *node_p =
Rows[i];
995 while (node_p != NULL)
998 node_p = node_p->Prev;
1011 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
1013 for (
int j = 0; j < bc; j++)
1015 for (
int i = 0; i < br; i++)
1017 int *bI =
new int[nr + 1];
1018 for (
int k = 0; k <= nr; k++)
1022 blocks(i,j) =
new SparseMatrix(bI, NULL, NULL, nr, nc);
1026 for (
int gr = 0; gr <
height; gr++)
1028 int bi = gr/nr, i = gr%nr + 1;
1031 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1035 blocks(bi,
J[j]/nc)->I[i]++;
1041 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1043 if (n_p->Value != 0.0)
1045 blocks(bi, n_p->Column/nc)->I[i]++;
1051 for (
int j = 0; j < bc; j++)
1053 for (
int i = 0; i < br; i++)
1057 for (
int k = 1; k <= nr; k++)
1059 rs = b.
I[k], b.
I[k] = nnz, nnz += rs;
1066 for (
int gr = 0; gr <
height; gr++)
1068 int bi = gr/nr, i = gr%nr + 1;
1071 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1076 b.
J[b.
I[i]] =
J[j] % nc;
1084 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1086 if (n_p->Value != 0.0)
1089 b.
J[b.
I[i]] = n_p->Column % nc;
1090 b.
A[b.
I[i]] = n_p->Value;
1112 for (
int i = 1; i <
height; i++)
1114 for (
int j =
I[i]; j <
I[i+1]; j++)
1118 symm = std::max(symm, std::abs(
A[j]-(*
this)(
J[j],i)));
1125 for (
int i = 0; i <
height; i++)
1127 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1129 int col = node_p->Column;
1132 symm = std::max(symm, std::abs(node_p->Value-(*
this)(col,i)));
1142 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1145 for (i = 1; i <
height; i++)
1147 for (j =
I[i]; j <
I[i+1]; j++)
1151 A[j] += (*this)(
J[j],i);
1153 (*this)(J[j],i) = A[j];
1169 for (
int i = 0; i <
height; i++)
1171 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1188 for (
int j = 0; j < nnz; j++)
1190 m = std::max(m, std::abs(
A[j]));
1195 for (
int i = 0; i <
height; i++)
1197 for (RowNode *n_p =
Rows[i]; n_p != NULL; n_p = n_p->Prev)
1199 m = std::max(m, std::abs(n_p->Value));
1213 const double *Ap =
A;
1215 for (
int i = 0; i < nz; i++)
1217 counter += (std::abs(Ap[i]) <= tol);
1222 for (
int i = 0; i <
height; i++)
1224 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1226 counter += (std::abs(aux->Value) <= tol);
1247 for (
int i = 0; i <
height; i++)
1249 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1267 MFEM_ASSERT(row < height && row >= 0,
1268 "Row " << row <<
" not in matrix of height " <<
height);
1270 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1272 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1274 rhs(aux->Column) -= sol * aux->Value;
1283 MFEM_ASSERT(row < height && row >= 0,
1284 "Row " << row <<
" not in matrix of height " <<
height);
1285 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1287 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1292 for (
int i=
I[row]; i <
I[row+1]; ++i)
1299 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1313 MFEM_ASSERT(col < width && col >= 0,
1314 "Col " << col <<
" not in matrix of width " <<
width);
1315 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1317 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1323 for (
int jpos = 0; jpos != nnz; ++jpos)
1333 for (
int i = 0; i <
height; i++)
1335 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1337 if (aux->Column == col)
1356 for (
int i = 0; i <
height; i++)
1358 for (
int jpos =
I[i]; jpos !=
I[i+1]; ++jpos)
1364 (*b)(i) -=
A[jpos] * (*x)(
J[jpos] );
1373 for (
int i = 0; i <
height; i++)
1375 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1377 if (cols[aux -> Column])
1381 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1393 MFEM_ASSERT(rc < height && rc >= 0,
1394 "Row " << rc <<
" not in matrix of height " <<
height);
1398 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1400 const int col =
J[j];
1406 rhs(rc) =
A[j] * sol;
1417 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1424 for (
int k = I[col]; 1; k++)
1428 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1430 else if (
J[k] == rc)
1432 rhs(col) -= sol *
A[k];
1442 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1444 const int col = aux->Column;
1450 rhs(rc) = aux->Value * sol;
1461 mfem_error(
"SparseMatrix::EliminateRowCol () #4");
1468 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1472 mfem_error(
"SparseMatrix::EliminateRowCol () #5");
1474 else if (node->Column == rc)
1476 rhs(col) -= sol * node->Value;
1490 MFEM_ASSERT(rc < height && rc >= 0,
1491 "Row " << rc <<
" not in matrix of height " <<
height);
1492 MFEM_ASSERT(sol.
Size() == rhs.
Width(),
"solution size (" << sol.
Size()
1493 <<
") must match rhs width (" << rhs.
Width() <<
")");
1495 const int num_rhs = rhs.
Width();
1498 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1500 const int col =
J[j];
1506 for (
int r = 0; r < num_rhs; r++)
1508 rhs(rc,r) =
A[j] * sol(r);
1513 for (
int r = 0; r < num_rhs; r++)
1520 for (
int r = 0; r < num_rhs; r++)
1526 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
1533 for (
int k = I[col]; 1; k++)
1537 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
1539 else if (
J[k] == rc)
1541 for (
int r = 0; r < num_rhs; r++)
1543 rhs(col,r) -= sol(r) *
A[k];
1554 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1556 const int col = aux->Column;
1562 for (
int r = 0; r < num_rhs; r++)
1564 rhs(rc,r) = aux->Value * sol(r);
1569 for (
int r = 0; r < num_rhs; r++)
1576 for (
int r = 0; r < num_rhs; r++)
1582 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #5");
1589 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1593 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #6");
1595 else if (node->Column == rc)
1597 for (
int r = 0; r < num_rhs; r++)
1599 rhs(col,r) -= sol(r) * node->Value;
1612 MFEM_ASSERT(rc < height && rc >= 0,
1613 "Row " << rc <<
" not in matrix of height " <<
height);
1617 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1619 const int col =
J[j];
1634 for (
int k = I[col]; 1; k++)
1638 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1640 else if (
J[k] == rc)
1651 RowNode *aux, *node;
1653 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1655 const int col = aux->Column;
1670 for (node =
Rows[col]; 1; node = node->Prev)
1674 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1676 else if (node->Column == rc)
1691 MFEM_ASSERT(rc < height && rc >= 0,
1692 "Row " << rc <<
" not in matrix of height " <<
height);
1696 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1698 const int col =
J[j];
1706 for (
int k = I[col]; 1; k++)
1710 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1712 else if (
J[k] == rc)
1723 RowNode *aux, *node;
1725 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1727 const int col = aux->Column;
1735 for (node =
Rows[col]; 1; node = node->Prev)
1739 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1741 else if (node->Column == rc)
1758 for (nd =
Rows[rc]; nd != NULL; nd = nd->Prev)
1760 const int col = nd->Column;
1766 Ae.
Add(rc, rc, nd->Value - 1.0);
1770 Ae.
Add(rc, rc, nd->Value);
1776 mfem_error(
"SparseMatrix::EliminateRowCol #1");
1782 Ae.
Add(rc, col, nd->Value);
1784 for (nd2 =
Rows[col]; 1; nd2 = nd2->Prev)
1788 mfem_error(
"SparseMatrix::EliminateRowCol #2");
1790 else if (nd2->Column == rc)
1792 Ae.
Add(col, rc, nd2->Value);
1802 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1804 const int col =
J[j];
1810 Ae.
Add(rc, rc,
A[j] - 1.0);
1814 Ae.
Add(rc, rc,
A[j]);
1820 mfem_error(
"SparseMatrix::EliminateRowCol #3");
1826 Ae.
Add(rc, col,
A[j]);
1828 for (
int k = I[col];
true; k++)
1832 mfem_error(
"SparseMatrix::EliminateRowCol #4");
1834 else if (
J[k] == rc)
1836 Ae.
Add(col, rc,
A[k]);
1848 for (
int i = 0; i <
height; i++)
1850 if (
I[i+1] ==
I[i]+1 && fabs(
A[
I[i]]) < 1e-16)
1859 for (
int i = 0; i <
height; i++)
1862 for (
int j =
I[i]; j <
I[i+1]; j++)
1866 if (zero <= threshold)
1868 for (
int j = I[i]; j < I[i+1]; j++)
1870 A[j] = (
J[j] == i) ? 1.0 : 0.0;
1881 const double *xp = x.
GetData();
1882 RowNode *diag_p, *n_p, **R =
Rows;
1885 for (
int i = 0; i < s; i++)
1889 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1891 const int c = n_p->Column;
1898 sum += n_p->Value * yp[c];
1902 if (diag_p != NULL && diag_p->Value != 0.0)
1904 yp[i] = (xp[i] - sum) / diag_p->Value;
1906 else if (xp[i] == sum)
1912 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
1926 for (
int i = 0, j = Ip[0]; i < s; i++)
1928 const int end = Ip[i+1];
1931 for ( ; j < end; j++)
1933 const int c = Jp[j];
1940 sum += Ap[j] * yp[c];
1944 if (d >= 0 && Ap[d] != 0.0)
1946 yp[i] = (xp[i] - sum) / Ap[d];
1948 else if (xp[i] == sum)
1954 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
1965 const double *xp = x.
GetData();
1966 RowNode *diag_p, *n_p, **R =
Rows;
1968 for (
int i =
height-1; i >= 0; i--)
1972 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1974 const int c = n_p->Column;
1981 sum += n_p->Value * yp[c];
1985 if (diag_p != NULL && diag_p->Value != 0.0)
1987 yp[i] = (xp[i] - sum) / diag_p->Value;
1989 else if (xp[i] == sum)
1995 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
2009 for (
int i = s-1, j = Ip[s]-1; i >= 0; i--)
2011 const int beg = Ip[i];
2014 for ( ; j >= beg; j--)
2016 const int c = Jp[j];
2023 sum += Ap[j] * yp[c];
2027 if (d >= 0 && Ap[d] != 0.0)
2029 yp[i] = (xp[i] - sum) / Ap[d];
2031 else if (xp[i] == sum)
2037 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
2045 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2048 for (
int i = 0; i <
height; i++)
2052 for (
int j =
I[i]; j <
I[i+1]; j++)
2060 if (d >= 0 &&
A[d] != 0.0)
2062 double a = 1.8 * fabs(
A[d]) / norm;
2070 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
2079 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2081 for (
int i = 0; i <
height; i++)
2085 for (
int j =
I[i]; j <
I[i+1]; j++)
2093 sum -=
A[j] * x0(
J[j]);
2096 if (d >= 0 &&
A[d] != 0.0)
2098 x1(i) = sc * (sum /
A[d]) + (1.0 - sc) * x0(i);
2109 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2111 bool scale = (sc != 1.0);
2112 for (
int i = 0, j = 0; i <
height; i++)
2117 MFEM_VERIFY(j != end,
"Couldn't find diagonal in row. i = " << i
2119 <<
", I[i+1] = " << end );
2122 MFEM_VERIFY(std::abs(
A[j]) > 0.0,
"Diagonal " << j <<
" must be nonzero");
2125 x(i) = sc * b(i) /
A[j];
2142 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2144 for (
int i = 0; i <
height; i++)
2146 double resi = b(i), norm = 0.0;
2147 for (
int j =
I[i]; j <
I[i+1]; j++)
2149 resi -=
A[j] * x0(
J[j]);
2154 x1(i) = x0(i) + sc * resi / norm;
2158 MFEM_ABORT(
"L1 norm of row " << i <<
" is zero.");
2166 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2168 for (
int i = 0; i <
height; i++)
2170 double resi = b(i), sum = 0.0;
2171 for (
int j =
I[i]; j <
I[i+1]; j++)
2173 resi -=
A[j] * x0(
J[j]);
2178 x1(i) = x0(i) + sc * resi / sum;
2182 MFEM_ABORT(
"sum of row " << i <<
" is zero.");
2190 int i, j, gi, gj, s, t;
2193 for (i = 0; i < rows.
Size(); i++)
2195 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2198 "Trying to insert a row " << gi <<
" outside the matrix height "
2201 for (j = 0; j < cols.
Size(); j++)
2203 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2205 MFEM_ASSERT(gj <
width,
2206 "Trying to insert a column " << gj <<
" outside the matrix width "
2209 if (skip_zeros && a == 0.0)
2213 if (&rows != &cols || subm(j, i) == 0.0)
2218 if (t < 0) { a = -a; }
2230 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2233 "Trying to set a row " << gi <<
" outside the matrix height "
2235 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2237 MFEM_ASSERT(gj <
width,
2238 "Trying to set a column " << gj <<
" outside the matrix width "
2240 if (t < 0) { a = -a; }
2249 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2252 "Trying to insert a row " << gi <<
" outside the matrix height "
2254 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2256 MFEM_ASSERT(gj <
width,
2257 "Trying to insert a column " << gj <<
" outside the matrix width "
2259 if (t < 0) { a = -a; }
2266 int i, j, gi, gj, s, t;
2269 for (i = 0; i < rows.
Size(); i++)
2271 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2274 "Trying to set a row " << gi <<
" outside the matrix height "
2277 for (j = 0; j < cols.
Size(); j++)
2280 if (skip_zeros && a == 0.0)
2284 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2286 MFEM_ASSERT(gj <
width,
2287 "Trying to set a column " << gj <<
" outside the matrix width "
2289 if (t < 0) { a = -a; }
2301 int i, j, gi, gj, s, t;
2304 for (i = 0; i < rows.
Size(); i++)
2306 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2309 "Trying to set a row " << gi <<
" outside the matrix height "
2312 for (j = 0; j < cols.
Size(); j++)
2315 if (skip_zeros && a == 0.0)
2319 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2321 MFEM_ASSERT(gj <
width,
2322 "Trying to set a column " << gj <<
" outside the matrix width "
2324 if (t < 0) { a = -a; }
2334 int i, j, gi, gj, s, t;
2337 for (i = 0; i < rows.
Size(); i++)
2339 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2342 "Trying to read a row " << gi <<
" outside the matrix height "
2345 for (j = 0; j < cols.
Size(); j++)
2347 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2349 MFEM_ASSERT(gj <
width,
2350 "Trying to read a column " << gj <<
" outside the matrix width "
2353 subm(i, j) = (t < 0) ? (-a) : (a);
2368 "Trying to query a row " << gi <<
" outside the matrix height "
2372 return (
Rows[gi] == NULL);
2376 return (
I[gi] ==
I[gi+1]);
2385 if ((gi=row) < 0) { gi = -1-gi; }
2387 "Trying to read a row " << gi <<
" outside the matrix height "
2391 for (n =
Rows[gi], j = 0; n; n = n->Prev)
2397 for (n =
Rows[gi], j = 0; n; n = n->Prev, j++)
2399 cols[j] = n->Column;
2412 cols.
MakeRef(const_cast<int*>((
const int*)
J) + j,
I[gi+1]-j);
2414 const_cast<double*>((
const double*)
A) + j, cols.
Size());
2415 MFEM_ASSERT(row >= 0,
"Row not valid: " << row <<
", height: " <<
height);
2426 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2429 "Trying to set a row " << gi <<
" outside the matrix height "
2435 for (
int j = 0; j < cols.
Size(); j++)
2437 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2439 MFEM_ASSERT(gj <
width,
2440 "Trying to set a column " << gj <<
" outside the matrix"
2441 " width " <<
width);
2443 if (t < 0) { a = -a; }
2451 MFEM_ASSERT(cols.
Size() == srow.
Size(),
"");
2453 for (
int i =
I[gi], j = 0; j < cols.
Size(); j++, i++)
2455 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2457 MFEM_ASSERT(gj <
width,
2458 "Trying to set a column " << gj <<
" outside the matrix"
2459 " width " <<
width);
2470 int j, gi, gj, s, t;
2473 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
2475 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2478 "Trying to insert a row " << gi <<
" outside the matrix height "
2481 for (j = 0; j < cols.
Size(); j++)
2483 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2485 MFEM_ASSERT(gj <
width,
2486 "Trying to insert a column " << gj <<
" outside the matrix width "
2493 if (t < 0) { a = -a; }
2511 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2513 aux -> Value *= scale;
2518 int j, end =
I[i+1];
2520 for (j =
I[i]; j < end; j++)
2533 for (
int i=0; i <
height; ++i)
2536 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2538 aux -> Value *= scale;
2546 for (
int i=0; i <
height; ++i)
2550 for (j =
I[i]; j < end; j++)
2563 for (
int i=0; i <
height; ++i)
2565 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2567 aux -> Value *= sr(aux->Column);
2575 for (
int i=0; i <
height; ++i)
2578 for (j =
I[i]; j < end; j++)
2589 "Mismatch of this matrix size and rhs. This height = "
2590 <<
height <<
", width = " <<
width <<
", B.height = "
2593 for (
int i = 0; i <
height; i++)
2598 for (RowNode *aux = B.
Rows[i]; aux != NULL; aux = aux->Prev)
2600 _Add_(aux->Column, aux->Value);
2605 for (
int j = B.
I[i]; j < B.
I[i+1]; j++)
2618 for (
int i = 0; i <
height; i++)
2623 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
2625 np->Value += a * B.
_Get_(np->Column);
2630 for (
int j =
I[i]; j <
I[i+1]; j++)
2643 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2650 for (
int i = 0; i <
height; i++)
2652 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2653 node_p = node_p -> Prev)
2655 node_p -> Value = a;
2667 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2674 for (
int i = 0; i <
height; i++)
2676 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2677 node_p = node_p -> Prev)
2679 node_p -> Value *= a;
2694 for (i = 0; i <
height; i++)
2696 out <<
"[row " << i <<
"]\n";
2697 for (nd =
Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
2699 out <<
" (" << nd->Column <<
"," << nd->Value <<
")";
2700 if ( !((j+1) % _width) )
2713 for (i = 0; i <
height; i++)
2715 out <<
"[row " << i <<
"]\n";
2716 for (j =
I[i]; j <
I[i+1]; j++)
2718 out <<
" (" <<
J[j] <<
"," <<
A[j] <<
")";
2719 if ( !((j+1-I[i]) % _width) )
2724 if ((j-I[i]) % _width)
2733 out <<
"% size " <<
height <<
" " <<
width <<
"\n";
2736 ios::fmtflags old_fmt = out.flags();
2737 out.setf(ios::scientific);
2738 std::streamsize old_prec = out.precision(14);
2740 for (i = 0; i <
height; i++)
2742 for (j =
I[i]; j <
I[i+1]; j++)
2744 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2747 out.precision(old_prec);
2754 ios::fmtflags old_fmt = out.flags();
2755 out.setf(ios::scientific);
2756 std::streamsize old_prec = out.precision(14);
2758 out <<
"%%MatrixMarket matrix coordinate real general" <<
'\n'
2759 <<
"% Generated by MFEM" <<
'\n';
2762 for (i = 0; i <
height; i++)
2764 for (j =
I[i]; j <
I[i+1]; j++)
2766 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2769 out.precision(old_prec);
2775 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2781 for (i = 0; i <=
height; i++)
2783 out <<
I[i]+1 <<
'\n';
2786 for (i = 0; i <
I[
height]; i++)
2788 out <<
J[i]+1 <<
'\n';
2791 for (i = 0; i < I[
height]; i++)
2793 out <<
A[i] <<
'\n';
2799 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2804 out <<
width <<
'\n';
2806 for (i = 0; i <=
height; i++)
2808 out <<
I[i] <<
'\n';
2811 for (i = 0; i <
I[
height]; i++)
2813 out <<
J[i] <<
'\n';
2816 for (i = 0; i < I[
height]; i++)
2818 out <<
A[i] <<
'\n';
2824 const double MiB = 1024.*1024;
2826 double pz = 100./nnz;
2836 "SparseMatrix statistics:\n"
2839 " Dimensions : " <<
height <<
" x " <<
width <<
"\n"
2840 " Number of entries (total) : " << nnz <<
"\n"
2841 " Number of entries (per row) : " << 1.*nnz/
Height() <<
"\n"
2842 " Number of stored zeros : " << nz*pz <<
"% (" << nz <<
")\n"
2843 " Number of Inf/Nan entries : " << nnf*pz <<
"% ("<< nnf <<
")\n"
2844 " Norm, max |a_ij| : " << max_norm <<
"\n"
2845 " Symmetry, max |a_ij-a_ji| : " << symm <<
"\n"
2846 " Number of small entries:\n"
2847 " |a_ij| <= 1e-12*Norm : " << ns12*pz <<
"% (" << ns12 <<
")\n"
2848 " |a_ij| <= 1e-15*Norm : " << ns15*pz <<
"% (" << ns15 <<
")\n"
2849 " |a_ij| <= 1e-18*Norm : " << ns18*pz <<
"% (" << ns18 <<
")\n";
2852 out <<
" Memory used by CSR : " <<
2853 (
sizeof(int)*(
height+1+nnz)+
sizeof(double)*nnz)/MiB <<
" MiB\n";
2857 size_t used_mem =
sizeof(RowNode*)*
height;
2858 #ifdef MFEM_USE_MEMALLOC
2861 for (
int i = 0; i <
height; i++)
2863 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2865 used_mem +=
sizeof(RowNode);
2869 out <<
" Memory used by LIL : " << used_mem/MiB <<
" MiB\n";
2881 #if !defined(MFEM_USE_MEMALLOC)
2882 for (
int i = 0; i <
height; i++)
2884 RowNode *aux, *node_p =
Rows[i];
2885 while (node_p != NULL)
2888 node_p = node_p->Prev;
2898 #ifdef MFEM_USE_MEMALLOC
2909 const int *start_j =
J;
2911 for (
const int *jptr = start_j; jptr != end_j; ++jptr)
2913 awidth = std::max(awidth, *jptr + 1);
2919 for (
int i = 0; i <
height; i++)
2921 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2923 awidth = std::max(awidth, aux->Column + 1);
2935 for (
int i = 0; i < n; i++)
2945 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
2948 const int *A_i, *A_j;
2949 int m, n, nnz, *At_i, *At_j;
2950 const double *A_data;
2960 At_i =
new int[n+1];
2961 At_j =
new int[nnz];
2962 At_data =
new double[nnz];
2964 for (i = 0; i <= n; i++)
2968 for (i = 0; i < nnz; i++)
2972 for (i = 1; i < n; i++)
2974 At_i[i+1] += At_i[i];
2977 for (i = j = 0; i < m; i++)
2980 for ( ; j < end; j++)
2982 At_j[At_i[A_j[j]]] = i;
2983 At_data[At_i[A_j[j]]] = A_data[j];
2988 for (i = n; i > 0; i--)
2990 At_i[i] = At_i[i-1];
3001 int m, n, nnz, *At_i, *At_j;
3011 for (i = 0; i < m; i++)
3013 A.
GetRow(i, Acols, Avals);
3031 At_i =
new int[n+1];
3032 At_j =
new int[nnz];
3033 At_data =
new double[nnz];
3035 for (i = 0; i <= n; i++)
3040 for (i = 0; i < m; i++)
3042 A.
GetRow(i, Acols, Avals);
3043 for (j = 0; j<Acols.
Size(); ++j)
3048 for (i = 1; i < n; i++)
3050 At_i[i+1] += At_i[i];
3053 for (i = 0; i < m; i++)
3055 A.
GetRow(i, Acols, Avals);
3056 for (j = 0; j<Acols.
Size(); ++j)
3058 At_j[At_i[Acols[j]]] = i;
3059 At_data[At_i[Acols[j]]] = Avals[j];
3064 for (i = n; i > 0; i--)
3066 At_i[i] = At_i[i-1];
3077 int nrowsA, ncolsA, nrowsB, ncolsB;
3078 const int *A_i, *A_j, *B_i, *B_j;
3079 int *C_i, *C_j, *B_marker;
3080 const double *A_data, *B_data;
3082 int ia, ib, ic, ja, jb, num_nonzeros;
3083 int row_start, counter;
3084 double a_entry, b_entry;
3092 MFEM_VERIFY(ncolsA == nrowsB,
3093 "number of columns of A (" << ncolsA
3094 <<
") must equal number of rows of B (" << nrowsB <<
")");
3103 B_marker =
new int[ncolsB];
3105 for (ib = 0; ib < ncolsB; ib++)
3112 C_i =
new int[nrowsA+1];
3114 C_i[0] = num_nonzeros = 0;
3115 for (ic = 0; ic < nrowsA; ic++)
3117 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3120 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3123 if (B_marker[jb] != ic)
3130 C_i[ic+1] = num_nonzeros;
3133 C_j =
new int[num_nonzeros];
3134 C_data =
new double[num_nonzeros];
3136 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3138 for (ib = 0; ib < ncolsB; ib++)
3147 MFEM_VERIFY(nrowsA == C -> Height() && ncolsB == C -> Width(),
3148 "Input matrix sizes do not match output sizes"
3149 <<
" nrowsA = " << nrowsA
3150 <<
", C->Height() = " << C->
Height()
3151 <<
" ncolsB = " << ncolsB
3152 <<
", C->Width() = " << C->
Width());
3156 C_data = C -> GetData();
3160 for (ic = 0; ic < nrowsA; ic++)
3163 row_start = counter;
3164 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3167 a_entry = A_data[ia];
3168 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3171 b_entry = B_data[ib];
3172 if (B_marker[jb] < row_start)
3174 B_marker[jb] = counter;
3179 C_data[counter] = a_entry*b_entry;
3184 C_data[B_marker[jb]] += a_entry*b_entry;
3192 "With pre-allocated output matrix, number of non-zeros ("
3194 <<
") did not match number of entries changed from matrix-matrix multiply, "
3213 int nrowsA, ncolsA, nrowsB, ncolsB;
3214 int *C_i, *C_j, *B_marker;
3216 int ia, ib, ic, ja, jb, num_nonzeros;
3217 int row_start, counter;
3218 double a_entry, b_entry;
3226 MFEM_VERIFY(ncolsA == nrowsB,
3227 "number of columns of A (" << ncolsA
3228 <<
") must equal number of rows of B (" << nrowsB <<
")");
3230 B_marker =
new int[ncolsB];
3232 for (ib = 0; ib < ncolsB; ib++)
3237 C_i =
new int[nrowsA+1];
3239 C_i[0] = num_nonzeros = 0;
3243 for (ic = 0; ic < nrowsA; ic++)
3245 A.
GetRow(ic, colsA, dataA);
3246 for (ia = 0; ia < colsA.
Size(); ia++)
3249 B.
GetRow(ja, colsB, dataB);
3250 for (ib = 0; ib < colsB.
Size(); ib++)
3253 if (B_marker[jb] != ic)
3260 C_i[ic+1] = num_nonzeros;
3263 C_j =
new int[num_nonzeros];
3264 C_data =
new double[num_nonzeros];
3266 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3268 for (ib = 0; ib < ncolsB; ib++)
3274 for (ic = 0; ic < nrowsA; ic++)
3276 row_start = counter;
3277 A.
GetRow(ic, colsA, dataA);
3278 for (ia = 0; ia < colsA.
Size(); ia++)
3281 a_entry = dataA[ia];
3282 B.
GetRow(ja, colsB, dataB);
3283 for (ib = 0; ib < colsB.
Size(); ib++)
3286 b_entry = dataB[ib];
3287 if (B_marker[jb] < row_start)
3289 B_marker[jb] = counter;
3291 C_data[counter] = a_entry*b_entry;
3296 C_data[B_marker[jb]] += a_entry*b_entry;
3311 for (
int j = 0; j < B.
Width(); ++j)
3315 A.
Mult(columnB, columnC);
3325 Mult (R, *AP, *_RAP);
3368 int i, At_nnz, *At_j;
3372 At_nnz = At -> NumNonZeroElems();
3373 At_j = At -> GetJ();
3374 At_data = At -> GetData();
3375 for (i = 0; i < At_nnz; i++)
3377 At_data[i] *= D(At_j[i]);
3388 int ncols = A.
Width();
3390 int * C_i =
new int[nrows+1];
3394 const int *A_i = A.
GetI();
3395 const int *A_j = A.
GetJ();
3396 const double *A_data = A.
GetData();
3398 const int *B_i = B.
GetI();
3399 const int *B_j = B.
GetJ();
3400 const double *B_data = B.
GetData();
3402 int * marker =
new int[ncols];
3403 std::fill(marker, marker+ncols, -1);
3405 int num_nonzeros = 0, jcol;
3407 for (
int ic = 0; ic < nrows; ic++)
3409 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3415 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3418 if (marker[jcol] != ic)
3424 C_i[ic+1] = num_nonzeros;
3427 C_j =
new int[num_nonzeros];
3428 C_data =
new double[num_nonzeros];
3430 for (
int ia = 0; ia < ncols; ia++)
3436 for (
int ic = 0; ic < nrows; ic++)
3438 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3442 C_data[pos] = a*A_data[ia];
3446 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3449 if (marker[jcol] < C_i[ic])
3452 C_data[pos] = b*B_data[ib];
3458 C_data[marker[jcol]] += b*B_data[ib];
3464 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
3469 return Add(1.,A,1.,B);
3474 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
3479 for (
int i=1; i < Ai.
Size(); ++i)
3481 result =
Add(*accumulate, *Ai[i]);
3487 accumulate = result;
3497 for (
int r = 0; r < B.
Height(); r++)
3501 for (
int i=0; i<A.
RowSize(r); i++)
3503 B(r, colA[i]) += alpha * valA[i];
3516 for (
int i=0; i<mA; i++)
3518 for (
int j=0; j<nA; j++)
3520 C->
AddMatrix(A(i,j), B, i * mB, j * nB);
3534 for (
int i=0; i<mA; i++)
3536 for (
int j=0; j<nA; j++)
3538 for (
int r=0; r<mB; r++)
3543 for (
int cj=0; cj<B.
RowSize(r); cj++)
3545 C->
Set(i * mB + r, j * nB + colB[cj], A(i,j) * valB[cj]);
3563 for (
int r=0; r<mA; r++)
3568 for (
int aj=0; aj<A.
RowSize(r); aj++)
3570 for (
int i=0; i<mB; i++)
3572 for (
int j=0; j<nB; j++)
3574 C->
Set(r * mB + i, colA[aj] * nB + j, valA[aj] * B(i, j));
3592 for (
int ar=0; ar<mA; ar++)
3597 for (
int aj=0; aj<A.
RowSize(ar); aj++)
3599 for (
int br=0; br<mB; br++)
3604 for (
int bj=0; bj<B.
RowSize(br); bj++)
3606 C->
Set(ar * mB + br, colA[aj] * nB + colB[bj],
3607 valA[aj] * valB[bj]);
3630 #ifdef MFEM_USE_MEMALLOC
Memory< int > I
Array with size (height+1) containing the row offsets.
double GetJacobiScaling() const
Determine appropriate scaling for Jacobi iteration.
int CheckFinite() const
Count the number of entries that are NOT finite, i.e. Inf or Nan.
int Size() const
Logical size of the array.
SparseMatrix * TransposeAbstractSparseMatrix(const AbstractSparseMatrix &A, int useActualWidth)
Transpose of a sparse matrix. A does not need to be a CSR matrix.
int RowSize(const int i) const
Returns the number of elements in row i.
int CheckFinite(const double *v, const int n)
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
void Add(const int i, const int j, const double a)
double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
void _Add_(const int col, const double a)
Add a value to an entry in the "current row". See SetColPtr().
void BuildTranspose() const
Build and store internally the transpose of this matrix which will be used in the methods AddMultTran...
void NewDataAndSize(double *d, int s)
Set the Vector data and size, deleting the old data, if owned.
void Clear()
Clear the contents of the SparseMatrix.
void EliminateCol(int col, DiagonalPolicy dpolicy=DIAG_ZERO)
Eliminates the column col from the matrix.
Memory< T > & GetMemory()
Return a reference to the Memory object used by the Array.
SparseMatrix * At
Transpose of A. Owned. Used to perform MultTranspose() on devices.
HypreParMatrix * RAP(const HypreParMatrix *A, const HypreParMatrix *P)
Returns the matrix P^t * A * P.
size_t MemoryUsage() const
void DiagScale(const Vector &b, Vector &x, double sc=1.0) const
virtual void Finalize(int skip_zeros=1)
Finalize the matrix initialization, switching the storage format from LIL to CSR. ...
void MakeRef(const SparseMatrix &master)
Clear the contents of the SparseMatrix and make it a reference to master.
void SetSize(int s)
Resize the vector to size s.
double & SearchRow(const int col)
Perform a fast search for an entry in the "current row". See SetColPtr().
void Delete()
Delete the owned pointers. The Memory is not reset by this method.
DenseMatrix * ToDenseMatrix() const
Produces a DenseMatrix from a SparseMatrix.
bool Empty() const
Check if the SparseMatrix is empty.
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
Set the diagonal value to zero.
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
int * GetJ()
Return the array J.
void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
Abstract data type for sparse matrices.
SparseMatrix & operator+=(const SparseMatrix &B)
Add the sparse matrix 'B' to '*this'. This operation will cause an error if '*this' is finalized and ...
T * Write(Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for write access to mem with the mfem::Device MemoryClass, if on_dev = true...
Data type dense matrix using column-major storage.
void AddMult(const Vector &x, Vector &y, const double a=1.0) const
y += A * x (default) or y += a * A * x
int Size() const
Returns the size of the vector.
int * GetI()
Return the array I.
void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const
y += At * x (default) or y += a * At * x
Abstract data type for matrix inverse.
void EliminateRowColMultipleRHS(int rc, const Vector &sol, DenseMatrix &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Similar to EliminateRowCol(int, const double, Vector &, DiagonalPolicy), but multiple values for elim...
virtual int NumNonZeroElems() const =0
Returns the number of non-zeros in a matrix.
void PrintInfo(std::ostream &out) const
Print various sparse matrix staticstics.
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
static bool IsDisabled()
The opposite of IsEnabled().
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
void AddRow(const int row, const Array< int > &cols, const Vector &srow)
double * GetRowEntries(const int row)
Return a pointer to the entries in a row.
double * GetData() const
Return a pointer to the beginning of the Vector data.
void SortColumnIndices()
Sort the column indices corresponding to each row.
void PrintMM(std::ostream &out=mfem::out) const
Prints matrix in Matrix Market sparse format.
int Capacity() const
Return the size of the allocated memory.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
void _Set_(const int col, const double a)
Set an entry in the "current row". See SetColPtr().
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, treating all entries as booleans (zero=false, nonzero=true).
SparseMatrix * Mult_AtDA(const SparseMatrix &A, const Vector &D, SparseMatrix *OAtDA)
Matrix multiplication A^t D A. All matrices must be finalized.
void PartAddMult(const Array< int > &rows, const Vector &x, Vector &y, const double a=1.0) const
bool RowIsEmpty(const int row) const
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
void ScaleRow(const int row, const double scale)
double * GetData()
Return the element data, i.e. the array A.
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
bool IsFinite(const double &val)
void MoveDiagonalFirst()
Move the diagonal entry to the first position in each row, preserving the order of the rest of the co...
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
void Wrap(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with type MemoryType::HOST.
const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
void ScaleColumns(const Vector &sr)
this = this * diag(sr);
void PrintCSR2(std::ostream &out) const
Prints a sparse matrix to stream out in CSR format.
double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const
Extract all column indices and values from a given row.
bool isSorted
Are the columns sorted already.
Memory< double > A
Array with size I[height], containing the actual entries of the sparse matrix, as indexed by the I ar...
SparseMatrix()
Create an empty SparseMatrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
static MemoryType GetMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
double IsSymmetric() const
Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix.
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
void SetDiagIdentity()
If a row contains only one diag entry of zero, set it to 1.
const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
void ScaleRows(const Vector &sl)
this = diag(sl) * this;
DenseMatrix * OuterProduct(const DenseMatrix &A, const DenseMatrix &B)
Produces a block matrix with blocks A_{ij}*B.
void Sort()
Sorts the array. This requires operator< to be defined for T.
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const =0
Gets the columns indexes and values for row row.
void PrintMatlab(std::ostream &out=mfem::out) const
Prints matrix in matlab format.
const T * Read(const Memory< T > &mem, int size, bool on_dev=true)
Get a pointer for read access to mem with the mfem::Device MemoryClass, if on_dev = true...
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Set the diagonal value to one.
Dynamic 2D array using row-major layout.
void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc) const
void SetSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void SparseMatrixFunction(SparseMatrix &S, double(*f)(double))
Applies f() to each element of the matrix (after it is finalized).
virtual MatrixInverse * Inverse() const
This virtual method is not supported: it always returns NULL.
void Swap(Array< T > &, Array< T > &)
void ClearOwnerFlags() const
Clear the ownership flags for the host and device pointers, as well as any internal data allocated by...
void EliminateRowColDiag(int rc, double value)
Perform elimination and set the diagonal entry to the given value.
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void SetHostPtrOwner(bool own) const
Set/clear the ownership flag for the host pointer. Ownership indicates whether the pointer will be de...
void SetSize(int nsize)
Change logical size of the array, keep existing entries.
void Set(const int i, const int j, const double a)
void EliminateRowCol(int rc, const double sol, Vector &rhs, DiagonalPolicy dpolicy=DIAG_ONE)
Eliminate row rc and column rc and modify the rhs using sol.
void GetColumnReference(int c, Vector &col)
void Threshold(double tol, bool fix_empty_rows=false)
Remove entries smaller in absolute value than a given tolerance tol. If fix_empty_rows is true...
void AddMatrix(DenseMatrix &A, int ro, int co)
Perform (ro+i,co+j)+=A(i,j) for 0<=i<A.Height, 0<=j<A.Width.
void Gauss_Seidel_back(const Vector &x, Vector &y) const
void Gauss_Seidel_forw(const Vector &x, Vector &y) const
Gauss-Seidel forward and backward iterations over a vector x.
RowNode ** Rows
Array of linked lists, one for every row. This array represents the linked list (LIL) storage format...
int height
Dimension of the output / number of rows in the matrix.
void EliminateRow(int row, const double sol, Vector &rhs)
Eliminates a column from the transpose matrix.
const T * HostRead(const Memory< T > &mem, int size)
Shortcut to Read(const Memory<T> &mem, int size, false)
int ActualWidth() const
Returns the actual Width of the matrix.
void GetDiag(Vector &d) const
Returns the Diagonal of A.
MemAlloc< RowNode, 1024 > RowNodeAlloc
double GetRowNorml1(int irow) const
For i = irow compute .
const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
void ResetTranspose() const
SparseMatrix * TransposeMult(const SparseMatrix &A, const SparseMatrix &B)
C = A^T B.
void New(int size)
Allocate host memory for size entries with type MemoryType::HOST.
virtual void EliminateZeroRows(const double threshold=1e-12)
If a row contains only zeros, set its diagonal to 1.
double & operator()(int i, int j)
Returns reference to A[i][j].
void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
void EliminateCols(const Array< int > &cols, const Vector *x=NULL, Vector *b=NULL)
Eliminate all columns i for which cols[i] != 0.
SparseMatrix & operator=(const SparseMatrix &rhs)
Assignment operator: deep copy.
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
SparseMatrix & operator*=(double a)
void SetRow(const int row, const Array< int > &cols, const Vector &srow)
void MakeRef(T *, int)
Make this Array a reference to a pointer.
void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
int MaxRowSize() const
Returns the maximum number of elements among all rows.
void Jacobi3(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
SparseMatrix * MultAbstractSparseMatrix(const AbstractSparseMatrix &A, const AbstractSparseMatrix &B)
Matrix product of sparse matrices. A and B do not need to be CSR matrices.
double _Get_(const int col) const
Read the value of an entry in the "current row". See SetColPtr().
void SetSize(int s)
Change the size of the DenseMatrix to s x s.
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
Memory< int > J
Array with size I[height], containing the column indices for all matrix entries, as indexed by the I ...
void Swap(SparseMatrix &other)
void PrintCSR(std::ostream &out) const
Prints matrix to stream out in hypre_CSRMatrix format.
double InnerProduct(const Vector &x, const Vector &y) const
Compute y^t A x.
int width
Dimension of the input / number of columns in the matrix.
int CountSmallElems(double tol) const
Count the number of entries with |a_ij| <= tol.
void PartMult(const Array< int > &rows, const Vector &x, Vector &y) const
void GetRowSums(Vector &x) const
For all i compute .
void Neg()
(*this) = -(*this)