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)
84 #ifdef MFEM_USE_MEMALLOC
90 A.
Wrap(data,
I[height], owna);
96 for (
int i=0; i<nnz; ++i)
111 #ifdef MFEM_USE_MEMALLOC
115 J.
New(nrows * rowsize);
116 A.
New(nrows * rowsize);
118 for (
int i = 0; i <= nrows; i++)
148 #ifdef MFEM_USE_MEMALLOC
154 #ifdef MFEM_USE_MEMALLOC
158 for (
int i = 0; i <
height; i++)
160 RowNode **node_pp = &
Rows[i];
161 for (RowNode *node_p = mat.
Rows[i]; node_p; node_p = node_p->Prev)
163 #ifdef MFEM_USE_MEMALLOC
166 RowNode *new_node_p =
new RowNode;
168 new_node_p->Value = node_p->Value;
169 new_node_p->Column = node_p->Column;
170 *node_pp = new_node_p;
171 node_pp = &new_node_p->Prev;
197 #ifdef MFEM_USE_MEMALLOC
204 for (
int i = 0; i <=
height; i++)
209 for (
int r=0; r<
height; r++)
228 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
249 #ifdef MFEM_USE_MEMALLOC
265 return I[gi+1]-
I[gi];
269 RowNode *row =
Rows[gi];
270 for ( ; row != NULL; row = row->Prev)
271 if (row->Value != 0.0)
284 for (
int i=0; i <
height; ++i)
286 rowSize =
I[i+1]-
I[i];
287 out = (out > rowSize) ? out : rowSize;
292 for (
int i=0; i <
height; ++i)
295 out = (out > rowSize) ? out : rowSize;
304 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
311 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
318 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
325 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
332 if (newWidth ==
width)
337 else if (newWidth == -1)
343 else if (newWidth >
width)
354 ColPtrJ =
static_cast<int *
>(NULL);
362 "The new width needs to be bigger or equal to the actual width");
370 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
378 for (
int j = 0, i = 0; i <
height; i++)
382 for (
int k = 0; k < row.
Size(); k++)
388 for (
int k = 0; k < row.
Size(); k++, j++)
399 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
401 for (
int row = 0, end = 0; row <
height; row++)
405 for (j = start;
true; j++)
407 MFEM_VERIFY(j < end,
"diagonal entry not found in row = " << row);
408 if (
J[j] == row) {
break; }
410 const double diag =
A[j];
411 for ( ; j > start; j--)
433 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
434 "Trying to access element outside of the matrix. "
435 <<
"height = " <<
height <<
", "
436 <<
"width = " <<
width <<
", "
437 <<
"i = " << i <<
", "
440 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
442 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
450 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
456 static const double zero = 0.0;
458 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
459 "Trying to access element outside of the matrix. "
460 <<
"height = " <<
height <<
", "
461 <<
"width = " <<
width <<
", "
462 <<
"i = " << i <<
", "
467 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
477 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
479 if (node_p->Column == j)
481 return node_p->Value;
491 MFEM_VERIFY(
height ==
width,
"Matrix must be square, not height = "
493 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
498 for (
int i = 0; i <
height; i++)
502 for (j =
I[i]; j < end; j++)
520 int num_rows = this->
Height();
521 int num_cols = this->
Width();
536 for (
int r=0; r<
height; r++)
541 for (
int cj=0; cj<this->
RowSize(r); cj++)
543 B(r, col[cj]) = val[cj];
557 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
558 <<
") must match matrix width (" <<
width <<
")");
559 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
560 <<
") must match matrix height (" <<
height <<
")");
568 for (
int i = 0; i <
height; i++)
570 RowNode *row =
Rows[i];
572 for ( ; row != NULL; row = row->Prev)
574 b += row->Value * xp[row->Column];
582 #ifndef MFEM_USE_LEGACY_OPENMP
585 auto d_I =
Read(
I, height+1);
586 auto d_J =
Read(
J, nnz);
587 auto d_A =
Read(
A, nnz);
590 MFEM_FORALL(i, height,
593 const int end = d_I[i+1];
594 for (
int j = d_I[i]; j < end; j++)
596 d += d_A[j] * d_x[d_J[j]];
601 const double *Ap =
A, *xp = x.
GetData();
603 const int *Jp =
J, *Ip =
I;
605 #pragma omp parallel for
606 for (
int i = 0; i <
height; i++)
609 const int end = Ip[i+1];
610 for (
int j = Ip[i]; j < end; j++)
612 d += Ap[j] * xp[Jp[j]];
627 const double a)
const
630 <<
") must match matrix height (" <<
height <<
")");
631 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
632 <<
") must match matrix width (" <<
width <<
")");
638 for (
int i = 0; i <
height; i++)
640 RowNode *row =
Rows[i];
642 for ( ; row != NULL; row = row->Prev)
644 yp[row->Column] += row->Value *
b;
657 "enabled; see BuildTranspose() for details.");
658 for (
int i = 0; i <
height; i++)
660 const double xi = a * x[i];
661 const int end =
I[i+1];
662 for (
int j =
I[i]; j < end; j++)
688 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
690 const int n = rows.
Size();
692 auto d_rows = rows.
Read();
694 auto d_J =
Read(
J, nnz);
695 auto d_A =
Read(
A, nnz);
697 auto d_y = y.
Write();
700 const int r = d_rows[i];
701 const int end = d_I[r + 1];
703 for (
int j = d_I[r]; j < end; j++)
705 a += d_A[j] * d_x[d_J[j]];
714 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
716 for (
int i = 0; i < rows.
Size(); i++)
721 for (
int j =
I[r]; j < end; j++)
723 val +=
A[j] * x(
J[j]);
731 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
732 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
733 <<
") must match matrix width (" <<
Width() <<
")");
739 auto d_I =
Read(
I, height+1);
740 auto d_J =
Read(
J, nnz);
743 MFEM_FORALL(i, height,
746 const int end = d_I[i+1];
747 for (
int j = d_I[i]; j < end; j++)
762 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
763 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
764 <<
") must match matrix height (" <<
Height() <<
")");
769 for (
int i = 0; i <
Height(); i++)
774 for (
int j =
I[i]; j < end; j++)
785 <<
" must be equal to Width() = " <<
Width());
787 <<
" must be equal to Height() = " <<
Height());
800 for (
int i = 0; i <
height; i++)
805 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
812 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
814 a += np->Value * x(np->Column);
825 for (
int i = 0; i <
height; i++)
830 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
837 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
848 MFEM_VERIFY(irow <
height,
849 "row " << irow <<
" not in matrix with height " <<
height);
854 for (
int j =
I[irow], end =
I[irow+1]; j < end; j++)
861 for (RowNode *np =
Rows[irow]; np != NULL; np = np->Prev)
863 a += fabs(np->Value);
872 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
874 atol = std::abs(tol);
876 fix_empty_rows =
height ==
width ? fix_empty_rows :
false;
884 for (i = 0, nz = 0; i <
height; i++)
887 for (j =
I[i]; j <
I[i+1]; j++)
888 if (std::abs(
A[j]) > atol)
893 if (fix_empty_rows && !found) { nz++; }
901 for (i = 0, nz = 0; i <
height; i++)
905 for (j =
I[i]; j <
I[i+1]; j++)
906 if (std::abs(
A[j]) > atol)
911 if ( lastCol > newJ[nz] )
918 if (fix_empty_rows && !found)
926 I.
Wrap(newI, height+1,
true);
927 J.
Wrap(newJ,
I[height],
true);
928 A.
Wrap(newA,
I[height],
true);
946 for (i = 1; i <=
height; i++)
949 for (aux =
Rows[i-1]; aux != NULL; aux = aux->Prev)
951 if (!skip_zeros || aux->Value != 0.0) { nr++; }
953 if (fix_empty_rows && !nr) { nr = 1; }
962 for (j = i = 0; i <
height; i++)
966 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
968 if (!skip_zeros || aux->Value != 0.0)
973 if ( lastCol >
J[j] )
983 if (fix_empty_rows && !nr)
991 #ifdef MFEM_USE_MEMALLOC
995 for (i = 0; i <
height; i++)
997 RowNode *node_p =
Rows[i];
998 while (node_p != NULL)
1001 node_p = node_p->Prev;
1014 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
1016 for (
int j = 0; j < bc; j++)
1018 for (
int i = 0; i < br; i++)
1021 for (
int k = 0; k <= nr; k++)
1025 blocks(i,j) =
new SparseMatrix(bI, NULL, NULL, nr, nc);
1029 for (
int gr = 0; gr <
height; gr++)
1031 int bi = gr/nr, i = gr%nr + 1;
1034 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1038 blocks(bi,
J[j]/nc)->I[i]++;
1044 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1046 if (n_p->Value != 0.0)
1048 blocks(bi, n_p->Column/nc)->I[i]++;
1054 for (
int j = 0; j < bc; j++)
1056 for (
int i = 0; i < br; i++)
1060 for (
int k = 1; k <= nr; k++)
1062 rs = b.
I[k], b.
I[k] = nnz, nnz += rs;
1069 for (
int gr = 0; gr <
height; gr++)
1071 int bi = gr/nr, i = gr%nr + 1;
1074 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1079 b.
J[b.
I[i]] =
J[j] % nc;
1087 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1089 if (n_p->Value != 0.0)
1092 b.
J[b.
I[i]] = n_p->Column % nc;
1093 b.
A[b.
I[i]] = n_p->Value;
1115 for (
int i = 1; i <
height; i++)
1117 for (
int j =
I[i]; j <
I[i+1]; j++)
1121 symm = std::max(symm, std::abs(
A[j]-(*
this)(
J[j],i)));
1128 for (
int i = 0; i <
height; i++)
1130 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1132 int col = node_p->Column;
1135 symm = std::max(symm, std::abs(node_p->Value-(*
this)(col,i)));
1145 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1148 for (i = 1; i <
height; i++)
1150 for (j =
I[i]; j <
I[i+1]; j++)
1154 A[j] += (*this)(
J[j],i);
1156 (*this)(J[j],i) = A[j];
1172 for (
int i = 0; i <
height; i++)
1174 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1191 for (
int j = 0; j < nnz; j++)
1193 m = std::max(m, std::abs(
A[j]));
1198 for (
int i = 0; i <
height; i++)
1200 for (RowNode *n_p =
Rows[i]; n_p != NULL; n_p = n_p->Prev)
1202 m = std::max(m, std::abs(n_p->Value));
1216 const double *Ap =
A;
1218 for (
int i = 0; i < nz; i++)
1220 counter += (std::abs(Ap[i]) <= tol);
1225 for (
int i = 0; i <
height; i++)
1227 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1229 counter += (std::abs(aux->Value) <= tol);
1250 for (
int i = 0; i <
height; i++)
1252 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1270 MFEM_ASSERT(row < height && row >= 0,
1271 "Row " << row <<
" not in matrix of height " <<
height);
1273 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1275 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1277 rhs(aux->Column) -= sol * aux->Value;
1286 MFEM_ASSERT(row < height && row >= 0,
1287 "Row " << row <<
" not in matrix of height " <<
height);
1288 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1290 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1295 for (
int i=
I[row]; i <
I[row+1]; ++i)
1302 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1316 MFEM_ASSERT(col < width && col >= 0,
1317 "Col " << col <<
" not in matrix of width " <<
width);
1318 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1320 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1326 for (
int jpos = 0; jpos != nnz; ++jpos)
1336 for (
int i = 0; i <
height; i++)
1338 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1340 if (aux->Column == col)
1359 for (
int i = 0; i <
height; i++)
1361 for (
int jpos =
I[i]; jpos !=
I[i+1]; ++jpos)
1367 (*b)(i) -=
A[jpos] * (*x)(
J[jpos] );
1376 for (
int i = 0; i <
height; i++)
1378 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1380 if (cols[aux -> Column])
1384 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1398 for (
int row = 0; row <
height; row++)
1400 for (nd =
Rows[row]; nd != NULL; nd = nd->Prev)
1402 if (col_marker[nd->Column])
1404 Ae.
Add(row, nd->Column, nd->Value);
1412 for (
int row = 0; row <
height; row++)
1414 for (
int j =
I[row]; j <
I[row+1]; j++)
1416 if (col_marker[
J[j]])
1418 Ae.
Add(row,
J[j],
A[j]);
1430 MFEM_ASSERT(rc < height && rc >= 0,
1431 "Row " << rc <<
" not in matrix of height " <<
height);
1435 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1437 const int col =
J[j];
1443 rhs(rc) =
A[j] * sol;
1454 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1461 for (
int k = I[col]; 1; k++)
1465 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1467 else if (
J[k] == rc)
1469 rhs(col) -= sol *
A[k];
1479 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1481 const int col = aux->Column;
1487 rhs(rc) = aux->Value * sol;
1498 mfem_error(
"SparseMatrix::EliminateRowCol () #4");
1505 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1509 mfem_error(
"SparseMatrix::EliminateRowCol () #5");
1511 else if (node->Column == rc)
1513 rhs(col) -= sol * node->Value;
1527 MFEM_ASSERT(rc < height && rc >= 0,
1528 "Row " << rc <<
" not in matrix of height " <<
height);
1529 MFEM_ASSERT(sol.
Size() == rhs.
Width(),
"solution size (" << sol.
Size()
1530 <<
") must match rhs width (" << rhs.
Width() <<
")");
1532 const int num_rhs = rhs.
Width();
1535 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1537 const int col =
J[j];
1543 for (
int r = 0; r < num_rhs; r++)
1545 rhs(rc,r) =
A[j] * sol(r);
1550 for (
int r = 0; r < num_rhs; r++)
1557 for (
int r = 0; r < num_rhs; r++)
1563 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
1570 for (
int k = I[col]; 1; k++)
1574 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
1576 else if (
J[k] == rc)
1578 for (
int r = 0; r < num_rhs; r++)
1580 rhs(col,r) -= sol(r) *
A[k];
1591 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1593 const int col = aux->Column;
1599 for (
int r = 0; r < num_rhs; r++)
1601 rhs(rc,r) = aux->Value * sol(r);
1606 for (
int r = 0; r < num_rhs; r++)
1613 for (
int r = 0; r < num_rhs; r++)
1619 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #5");
1626 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1630 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #6");
1632 else if (node->Column == rc)
1634 for (
int r = 0; r < num_rhs; r++)
1636 rhs(col,r) -= sol(r) * node->Value;
1649 MFEM_ASSERT(rc < height && rc >= 0,
1650 "Row " << rc <<
" not in matrix of height " <<
height);
1654 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1656 const int col =
J[j];
1671 for (
int k = I[col]; 1; k++)
1675 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1677 else if (
J[k] == rc)
1688 RowNode *aux, *node;
1690 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1692 const int col = aux->Column;
1707 for (node =
Rows[col]; 1; node = node->Prev)
1711 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1713 else if (node->Column == rc)
1728 MFEM_ASSERT(rc < height && rc >= 0,
1729 "Row " << rc <<
" not in matrix of height " <<
height);
1733 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1735 const int col =
J[j];
1743 for (
int k = I[col]; 1; k++)
1747 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1749 else if (
J[k] == rc)
1760 RowNode *aux, *node;
1762 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1764 const int col = aux->Column;
1772 for (node =
Rows[col]; 1; node = node->Prev)
1776 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1778 else if (node->Column == rc)
1795 for (nd =
Rows[rc]; nd != NULL; nd = nd->Prev)
1797 const int col = nd->Column;
1803 Ae.
Add(rc, rc, nd->Value - 1.0);
1807 Ae.
Add(rc, rc, nd->Value);
1813 mfem_error(
"SparseMatrix::EliminateRowCol #1");
1819 Ae.
Add(rc, col, nd->Value);
1821 for (nd2 =
Rows[col]; 1; nd2 = nd2->Prev)
1825 mfem_error(
"SparseMatrix::EliminateRowCol #2");
1827 else if (nd2->Column == rc)
1829 Ae.
Add(col, rc, nd2->Value);
1839 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1841 const int col =
J[j];
1847 Ae.
Add(rc, rc,
A[j] - 1.0);
1851 Ae.
Add(rc, rc,
A[j]);
1857 mfem_error(
"SparseMatrix::EliminateRowCol #3");
1863 Ae.
Add(rc, col,
A[j]);
1865 for (
int k = I[col];
true; k++)
1869 mfem_error(
"SparseMatrix::EliminateRowCol #4");
1871 else if (
J[k] == rc)
1873 Ae.
Add(col, rc,
A[k]);
1885 for (
int i = 0; i <
height; i++)
1887 if (
I[i+1] ==
I[i]+1 && fabs(
A[
I[i]]) < 1e-16)
1896 for (
int i = 0; i <
height; i++)
1899 for (
int j =
I[i]; j <
I[i+1]; j++)
1903 if (zero <= threshold)
1905 for (
int j = I[i]; j < I[i+1]; j++)
1907 A[j] = (
J[j] == i) ? 1.0 : 0.0;
1918 const double *xp = x.
GetData();
1919 RowNode *diag_p, *n_p, **R =
Rows;
1922 for (
int i = 0; i < s; i++)
1926 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1928 const int c = n_p->Column;
1935 sum += n_p->Value * yp[c];
1939 if (diag_p != NULL && diag_p->Value != 0.0)
1941 yp[i] = (xp[i] - sum) / diag_p->Value;
1943 else if (xp[i] == sum)
1949 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
1963 for (
int i = 0, j = Ip[0]; i < s; i++)
1965 const int end = Ip[i+1];
1968 for ( ; j < end; j++)
1970 const int c = Jp[j];
1977 sum += Ap[j] * yp[c];
1981 if (d >= 0 && Ap[d] != 0.0)
1983 yp[i] = (xp[i] - sum) / Ap[d];
1985 else if (xp[i] == sum)
1991 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
2002 const double *xp = x.
GetData();
2003 RowNode *diag_p, *n_p, **R =
Rows;
2005 for (
int i =
height-1; i >= 0; i--)
2009 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
2011 const int c = n_p->Column;
2018 sum += n_p->Value * yp[c];
2022 if (diag_p != NULL && diag_p->Value != 0.0)
2024 yp[i] = (xp[i] - sum) / diag_p->Value;
2026 else if (xp[i] == sum)
2032 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
2046 for (
int i = s-1, j = Ip[s]-1; i >= 0; i--)
2048 const int beg = Ip[i];
2051 for ( ; j >= beg; j--)
2053 const int c = Jp[j];
2060 sum += Ap[j] * yp[c];
2064 if (d >= 0 && Ap[d] != 0.0)
2066 yp[i] = (xp[i] - sum) / Ap[d];
2068 else if (xp[i] == sum)
2074 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
2082 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2085 for (
int i = 0; i <
height; i++)
2089 for (
int j =
I[i]; j <
I[i+1]; j++)
2097 if (d >= 0 &&
A[d] != 0.0)
2099 double a = 1.8 * fabs(
A[d]) / norm;
2107 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
2116 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2118 for (
int i = 0; i <
height; i++)
2122 for (
int j =
I[i]; j <
I[i+1]; j++)
2130 sum -=
A[j] * x0(
J[j]);
2133 if (d >= 0 &&
A[d] != 0.0)
2135 x1(i) = sc * (sum /
A[d]) + (1.0 - sc) * x0(i);
2146 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2148 bool scale = (sc != 1.0);
2149 for (
int i = 0, j = 0; i <
height; i++)
2154 MFEM_VERIFY(j != end,
"Couldn't find diagonal in row. i = " << i
2156 <<
", I[i+1] = " << end );
2159 MFEM_VERIFY(std::abs(
A[j]) > 0.0,
"Diagonal " << j <<
" must be nonzero");
2162 x(i) = sc *
b(i) /
A[j];
2179 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2181 for (
int i = 0; i <
height; i++)
2183 double resi =
b(i), norm = 0.0;
2184 for (
int j =
I[i]; j <
I[i+1]; j++)
2186 resi -=
A[j] * x0(
J[j]);
2191 x1(i) = x0(i) + sc * resi / norm;
2195 MFEM_ABORT(
"L1 norm of row " << i <<
" is zero.");
2203 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2205 for (
int i = 0; i <
height; i++)
2207 double resi =
b(i), sum = 0.0;
2208 for (
int j =
I[i]; j <
I[i+1]; j++)
2210 resi -=
A[j] * x0(
J[j]);
2215 x1(i) = x0(i) + sc * resi / sum;
2219 MFEM_ABORT(
"sum of row " << i <<
" is zero.");
2227 int i, j, gi, gj, s, t;
2230 for (i = 0; i < rows.
Size(); i++)
2232 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2235 "Trying to insert a row " << gi <<
" outside the matrix height "
2238 for (j = 0; j < cols.
Size(); j++)
2240 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2242 MFEM_ASSERT(gj <
width,
2243 "Trying to insert a column " << gj <<
" outside the matrix width "
2246 if (skip_zeros && a == 0.0)
2250 if (&rows != &cols || subm(j, i) == 0.0)
2255 if (t < 0) { a = -
a; }
2267 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2270 "Trying to set a row " << gi <<
" outside the matrix height "
2272 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2274 MFEM_ASSERT(gj <
width,
2275 "Trying to set a column " << gj <<
" outside the matrix width "
2277 if (t < 0) { a = -
a; }
2286 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2289 "Trying to insert a row " << gi <<
" outside the matrix height "
2291 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2293 MFEM_ASSERT(gj <
width,
2294 "Trying to insert a column " << gj <<
" outside the matrix width "
2296 if (t < 0) { a = -
a; }
2303 int i, j, gi, gj, s, t;
2306 for (i = 0; i < rows.
Size(); i++)
2308 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2311 "Trying to set a row " << gi <<
" outside the matrix height "
2314 for (j = 0; j < cols.
Size(); j++)
2317 if (skip_zeros && a == 0.0)
2321 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2323 MFEM_ASSERT(gj <
width,
2324 "Trying to set a column " << gj <<
" outside the matrix width "
2326 if (t < 0) { a = -
a; }
2338 int i, j, gi, gj, s, t;
2341 for (i = 0; i < rows.
Size(); i++)
2343 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2346 "Trying to set a row " << gi <<
" outside the matrix height "
2349 for (j = 0; j < cols.
Size(); j++)
2352 if (skip_zeros && a == 0.0)
2356 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2358 MFEM_ASSERT(gj <
width,
2359 "Trying to set a column " << gj <<
" outside the matrix width "
2361 if (t < 0) { a = -
a; }
2371 int i, j, gi, gj, s, t;
2374 for (i = 0; i < rows.
Size(); i++)
2376 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2379 "Trying to read a row " << gi <<
" outside the matrix height "
2382 for (j = 0; j < cols.
Size(); j++)
2384 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2386 MFEM_ASSERT(gj <
width,
2387 "Trying to read a column " << gj <<
" outside the matrix width "
2390 subm(i, j) = (t < 0) ? (-a) : (
a);
2405 "Trying to query a row " << gi <<
" outside the matrix height "
2409 return (
Rows[gi] == NULL);
2413 return (
I[gi] ==
I[gi+1]);
2422 if ((gi=row) < 0) { gi = -1-gi; }
2424 "Trying to read a row " << gi <<
" outside the matrix height "
2428 for (n =
Rows[gi], j = 0; n; n = n->Prev)
2434 for (n =
Rows[gi], j = 0; n; n = n->Prev, j++)
2436 cols[j] = n->Column;
2449 cols.
MakeRef(const_cast<int*>((
const int*)
J) + j,
I[gi+1]-j);
2451 const_cast<double*>((
const double*)
A) + j, cols.
Size());
2452 MFEM_ASSERT(row >= 0,
"Row not valid: " << row <<
", height: " <<
height);
2463 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2466 "Trying to set a row " << gi <<
" outside the matrix height "
2472 for (
int j = 0; j < cols.
Size(); j++)
2474 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2476 MFEM_ASSERT(gj <
width,
2477 "Trying to set a column " << gj <<
" outside the matrix"
2478 " width " <<
width);
2480 if (t < 0) { a = -
a; }
2488 MFEM_ASSERT(cols.
Size() == srow.
Size(),
"");
2490 for (
int i =
I[gi], j = 0; j < cols.
Size(); j++, i++)
2492 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2494 MFEM_ASSERT(gj <
width,
2495 "Trying to set a column " << gj <<
" outside the matrix"
2496 " width " <<
width);
2507 int j, gi, gj, s, t;
2510 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
2512 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2515 "Trying to insert a row " << gi <<
" outside the matrix height "
2518 for (j = 0; j < cols.
Size(); j++)
2520 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2522 MFEM_ASSERT(gj <
width,
2523 "Trying to insert a column " << gj <<
" outside the matrix width "
2530 if (t < 0) { a = -
a; }
2548 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2550 aux -> Value *= scale;
2555 int j, end =
I[i+1];
2557 for (j =
I[i]; j < end; j++)
2570 for (
int i=0; i <
height; ++i)
2573 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2575 aux -> Value *= scale;
2583 for (
int i=0; i <
height; ++i)
2587 for (j =
I[i]; j < end; j++)
2600 for (
int i=0; i <
height; ++i)
2602 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2604 aux -> Value *= sr(aux->Column);
2612 for (
int i=0; i <
height; ++i)
2615 for (j =
I[i]; j < end; j++)
2626 "Mismatch of this matrix size and rhs. This height = "
2627 <<
height <<
", width = " <<
width <<
", B.height = "
2630 for (
int i = 0; i <
height; i++)
2635 for (RowNode *aux = B.
Rows[i]; aux != NULL; aux = aux->Prev)
2637 _Add_(aux->Column, aux->Value);
2642 for (
int j = B.
I[i]; j < B.
I[i+1]; j++)
2655 for (
int i = 0; i <
height; i++)
2660 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
2662 np->Value += a * B.
_Get_(np->Column);
2667 for (
int j =
I[i]; j <
I[i+1]; j++)
2682 for (
int i = 0; i < nnz; i++)
2689 for (
int i = 0; i <
height; i++)
2691 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2692 node_p = node_p -> Prev)
2694 node_p -> Value =
a;
2706 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2713 for (
int i = 0; i <
height; i++)
2715 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2716 node_p = node_p -> Prev)
2718 node_p -> Value *=
a;
2733 for (i = 0; i <
height; i++)
2735 out <<
"[row " << i <<
"]\n";
2736 for (nd =
Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
2738 out <<
" (" << nd->Column <<
"," << nd->Value <<
")";
2739 if ( !((j+1) % _width) )
2752 for (i = 0; i <
height; i++)
2754 out <<
"[row " << i <<
"]\n";
2755 for (j =
I[i]; j <
I[i+1]; j++)
2757 out <<
" (" <<
J[j] <<
"," <<
A[j] <<
")";
2758 if ( !((j+1-I[i]) % _width) )
2763 if ((j-I[i]) % _width)
2772 out <<
"% size " <<
height <<
" " <<
width <<
"\n";
2775 ios::fmtflags old_fmt = out.flags();
2776 out.setf(ios::scientific);
2777 std::streamsize old_prec = out.precision(14);
2779 for (i = 0; i <
height; i++)
2781 for (j =
I[i]; j <
I[i+1]; j++)
2783 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2786 out.precision(old_prec);
2793 ios::fmtflags old_fmt = out.flags();
2794 out.setf(ios::scientific);
2795 std::streamsize old_prec = out.precision(14);
2797 out <<
"%%MatrixMarket matrix coordinate real general" <<
'\n'
2798 <<
"% Generated by MFEM" <<
'\n';
2801 for (i = 0; i <
height; i++)
2803 for (j =
I[i]; j <
I[i+1]; j++)
2805 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2808 out.precision(old_prec);
2814 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2820 for (i = 0; i <=
height; i++)
2822 out <<
I[i]+1 <<
'\n';
2825 for (i = 0; i <
I[
height]; i++)
2827 out <<
J[i]+1 <<
'\n';
2830 for (i = 0; i < I[
height]; i++)
2832 out <<
A[i] <<
'\n';
2838 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2843 out <<
width <<
'\n';
2845 for (i = 0; i <=
height; i++)
2847 out <<
I[i] <<
'\n';
2850 for (i = 0; i <
I[
height]; i++)
2852 out <<
J[i] <<
'\n';
2855 for (i = 0; i < I[
height]; i++)
2857 out <<
A[i] <<
'\n';
2863 const double MiB = 1024.*1024;
2865 double pz = 100./nnz;
2875 "SparseMatrix statistics:\n"
2878 " Dimensions : " <<
height <<
" x " <<
width <<
"\n"
2879 " Number of entries (total) : " << nnz <<
"\n"
2880 " Number of entries (per row) : " << 1.*nnz/
Height() <<
"\n"
2881 " Number of stored zeros : " << nz*pz <<
"% (" << nz <<
")\n"
2882 " Number of Inf/Nan entries : " << nnf*pz <<
"% ("<< nnf <<
")\n"
2883 " Norm, max |a_ij| : " << max_norm <<
"\n"
2884 " Symmetry, max |a_ij-a_ji| : " << symm <<
"\n"
2885 " Number of small entries:\n"
2886 " |a_ij| <= 1e-12*Norm : " << ns12*pz <<
"% (" << ns12 <<
")\n"
2887 " |a_ij| <= 1e-15*Norm : " << ns15*pz <<
"% (" << ns15 <<
")\n"
2888 " |a_ij| <= 1e-18*Norm : " << ns18*pz <<
"% (" << ns18 <<
")\n";
2891 out <<
" Memory used by CSR : " <<
2892 (
sizeof(int)*(
height+1+nnz)+
sizeof(double)*nnz)/MiB <<
" MiB\n";
2896 size_t used_mem =
sizeof(RowNode*)*
height;
2897 #ifdef MFEM_USE_MEMALLOC
2900 for (
int i = 0; i <
height; i++)
2902 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2904 used_mem +=
sizeof(RowNode);
2908 out <<
" Memory used by LIL : " << used_mem/MiB <<
" MiB\n";
2920 #if !defined(MFEM_USE_MEMALLOC)
2921 for (
int i = 0; i <
height; i++)
2923 RowNode *aux, *node_p =
Rows[i];
2924 while (node_p != NULL)
2927 node_p = node_p->Prev;
2937 #ifdef MFEM_USE_MEMALLOC
2948 const int *start_j =
J;
2950 for (
const int *jptr = start_j; jptr != end_j; ++jptr)
2952 awidth = std::max(awidth, *jptr + 1);
2958 for (
int i = 0; i <
height; i++)
2960 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2962 awidth = std::max(awidth, aux->Column + 1);
2974 for (
int i = 0; i < n; i++)
2984 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
2987 const int *A_i, *A_j;
2988 int m, n, nnz, *At_i, *At_j;
2989 const double *A_data;
3003 for (i = 0; i <= n; i++)
3007 for (i = 0; i < nnz; i++)
3011 for (i = 1; i < n; i++)
3013 At_i[i+1] += At_i[i];
3016 for (i = j = 0; i < m; i++)
3019 for ( ; j < end; j++)
3021 At_j[At_i[A_j[j]]] = i;
3022 At_data[At_i[A_j[j]]] = A_data[j];
3027 for (i = n; i > 0; i--)
3029 At_i[i] = At_i[i-1];
3040 int m, n, nnz, *At_i, *At_j;
3050 for (i = 0; i < m; i++)
3052 A.
GetRow(i, Acols, Avals);
3074 for (i = 0; i <= n; i++)
3079 for (i = 0; i < m; i++)
3081 A.
GetRow(i, Acols, Avals);
3082 for (j = 0; j<Acols.
Size(); ++j)
3087 for (i = 1; i < n; i++)
3089 At_i[i+1] += At_i[i];
3092 for (i = 0; i < m; i++)
3094 A.
GetRow(i, Acols, Avals);
3095 for (j = 0; j<Acols.
Size(); ++j)
3097 At_j[At_i[Acols[j]]] = i;
3098 At_data[At_i[Acols[j]]] = Avals[j];
3103 for (i = n; i > 0; i--)
3105 At_i[i] = At_i[i-1];
3116 int nrowsA, ncolsA, nrowsB, ncolsB;
3117 const int *A_i, *A_j, *B_i, *B_j;
3118 int *C_i, *C_j, *B_marker;
3119 const double *A_data, *B_data;
3121 int ia, ib, ic, ja, jb, num_nonzeros;
3122 int row_start, counter;
3123 double a_entry, b_entry;
3131 MFEM_VERIFY(ncolsA == nrowsB,
3132 "number of columns of A (" << ncolsA
3133 <<
") must equal number of rows of B (" << nrowsB <<
")");
3142 B_marker =
new int[ncolsB];
3144 for (ib = 0; ib < ncolsB; ib++)
3153 C_i[0] = num_nonzeros = 0;
3154 for (ic = 0; ic < nrowsA; ic++)
3156 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3159 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3162 if (B_marker[jb] != ic)
3169 C_i[ic+1] = num_nonzeros;
3175 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3177 for (ib = 0; ib < ncolsB; ib++)
3186 MFEM_VERIFY(nrowsA == C -> Height() && ncolsB == C -> Width(),
3187 "Input matrix sizes do not match output sizes"
3188 <<
" nrowsA = " << nrowsA
3189 <<
", C->Height() = " << C->
Height()
3190 <<
" ncolsB = " << ncolsB
3191 <<
", C->Width() = " << C->
Width());
3195 C_data = C -> GetData();
3199 for (ic = 0; ic < nrowsA; ic++)
3202 row_start = counter;
3203 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3206 a_entry = A_data[ia];
3207 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3210 b_entry = B_data[ib];
3211 if (B_marker[jb] < row_start)
3213 B_marker[jb] = counter;
3218 C_data[counter] = a_entry*b_entry;
3223 C_data[B_marker[jb]] += a_entry*b_entry;
3231 "With pre-allocated output matrix, number of non-zeros ("
3233 <<
") did not match number of entries changed from matrix-matrix multiply, "
3252 int nrowsA, ncolsA, nrowsB, ncolsB;
3253 int *C_i, *C_j, *B_marker;
3255 int ia, ib, ic, ja, jb, num_nonzeros;
3256 int row_start, counter;
3257 double a_entry, b_entry;
3265 MFEM_VERIFY(ncolsA == nrowsB,
3266 "number of columns of A (" << ncolsA
3267 <<
") must equal number of rows of B (" << nrowsB <<
")");
3269 B_marker =
new int[ncolsB];
3271 for (ib = 0; ib < ncolsB; ib++)
3278 C_i[0] = num_nonzeros = 0;
3282 for (ic = 0; ic < nrowsA; ic++)
3284 A.
GetRow(ic, colsA, dataA);
3285 for (ia = 0; ia < colsA.
Size(); ia++)
3288 B.
GetRow(ja, colsB, dataB);
3289 for (ib = 0; ib < colsB.
Size(); ib++)
3292 if (B_marker[jb] != ic)
3299 C_i[ic+1] = num_nonzeros;
3305 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3307 for (ib = 0; ib < ncolsB; ib++)
3313 for (ic = 0; ic < nrowsA; ic++)
3315 row_start = counter;
3316 A.
GetRow(ic, colsA, dataA);
3317 for (ia = 0; ia < colsA.
Size(); ia++)
3320 a_entry = dataA[ia];
3321 B.
GetRow(ja, colsB, dataB);
3322 for (ib = 0; ib < colsB.
Size(); ib++)
3325 b_entry = dataB[ib];
3326 if (B_marker[jb] < row_start)
3328 B_marker[jb] = counter;
3330 C_data[counter] = a_entry*b_entry;
3335 C_data[B_marker[jb]] += a_entry*b_entry;
3350 for (
int j = 0; j < B.
Width(); ++j)
3354 A.
Mult(columnB, columnC);
3364 Mult (R, *AP, *_RAP);
3407 int i, At_nnz, *At_j;
3411 At_nnz = At -> NumNonZeroElems();
3412 At_j = At -> GetJ();
3413 At_data = At -> GetData();
3414 for (i = 0; i < At_nnz; i++)
3416 At_data[i] *= D(At_j[i]);
3427 int ncols = A.
Width();
3433 const int *A_i = A.
GetI();
3434 const int *A_j = A.
GetJ();
3435 const double *A_data = A.
GetData();
3437 const int *B_i = B.
GetI();
3438 const int *B_j = B.
GetJ();
3439 const double *B_data = B.
GetData();
3441 int * marker =
new int[ncols];
3442 std::fill(marker, marker+ncols, -1);
3444 int num_nonzeros = 0, jcol;
3446 for (
int ic = 0; ic < nrows; ic++)
3448 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3454 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3457 if (marker[jcol] != ic)
3463 C_i[ic+1] = num_nonzeros;
3469 for (
int ia = 0; ia < ncols; ia++)
3475 for (
int ic = 0; ic < nrows; ic++)
3477 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3481 C_data[pos] = a*A_data[ia];
3485 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3488 if (marker[jcol] < C_i[ic])
3491 C_data[pos] = b*B_data[ib];
3497 C_data[marker[jcol]] += b*B_data[ib];
3503 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
3508 return Add(1.,A,1.,B);
3513 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
3518 for (
int i=1; i < Ai.
Size(); ++i)
3520 result =
Add(*accumulate, *Ai[i]);
3526 accumulate = result;
3536 for (
int r = 0; r < B.
Height(); r++)
3540 for (
int i=0; i<A.
RowSize(r); i++)
3542 B(r, colA[i]) += alpha * valA[i];
3555 for (
int i=0; i<mA; i++)
3557 for (
int j=0; j<nA; j++)
3559 C->
AddMatrix(A(i,j), B, i * mB, j * nB);
3573 for (
int i=0; i<mA; i++)
3575 for (
int j=0; j<nA; j++)
3577 for (
int r=0; r<mB; r++)
3582 for (
int cj=0; cj<B.
RowSize(r); cj++)
3584 C->
Set(i * mB + r, j * nB + colB[cj], A(i,j) * valB[cj]);
3602 for (
int r=0; r<mA; r++)
3607 for (
int aj=0; aj<A.
RowSize(r); aj++)
3609 for (
int i=0; i<mB; i++)
3611 for (
int j=0; j<nB; j++)
3613 C->
Set(r * mB + i, colA[aj] * nB + j, valA[aj] * B(i, j));
3631 for (
int ar=0; ar<mA; ar++)
3636 for (
int aj=0; aj<A.
RowSize(ar); aj++)
3638 for (
int br=0; br<mB; br++)
3643 for (
int bj=0; bj<B.
RowSize(br); bj++)
3645 C->
Set(ar * mB + br, colA[aj] * nB + colB[bj],
3646 valA[aj] * valB[bj]);
3669 #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, i.e. it will, generally, not be Empty() after this call.
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's DeviceMemoryClass, 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 statistics.
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...
unsigned flags
Bit flags defined from the FlagMask enum.
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 the current host memory type returned by MemoryMa...
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 GetDeviceMemoryType()
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's DeviceMemoryClass, 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)
bool Finalized() const
Returns whether or not CSR format has been finalized.
T * HostWrite(Memory< T > &mem, int size)
Shortcut to Write(const Memory<T> &mem, int size, false)
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 the current host memory type returned by MemoryManager::Ge...
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)