15 #include "../general/table.hpp"
16 #include "../general/sort_pairs.hpp"
35 Rows(new RowNode *[nrows]),
43 for (
int i = 0; i < nrows; i++)
48 #ifdef MFEM_USE_MEMALLOC
65 #ifdef MFEM_USE_MEMALLOC
71 bool ownij,
bool owna,
bool issorted)
83 #ifdef MFEM_USE_MEMALLOC
91 A =
new double[ nnz ];
92 for (
int i=0; i<nnz; ++i)
108 #ifdef MFEM_USE_MEMALLOC
111 I =
new int[nrows + 1];
112 J =
new int[nrows * rowsize];
113 A =
new double[nrows * rowsize];
115 for (
int i = 0; i <= nrows; i++)
131 memcpy(
I, mat.
I,
sizeof(
int)*(
height+1));
132 memcpy(
J, mat.
J,
sizeof(
int)*nnz);
142 memcpy(
A, mat.
A,
sizeof(
double)*nnz);
146 #ifdef MFEM_USE_MEMALLOC
152 #ifdef MFEM_USE_MEMALLOC
156 for (
int i = 0; i <
height; i++)
158 RowNode **node_pp = &
Rows[i];
159 for (RowNode *node_p = mat.
Rows[i]; node_p; node_p = node_p->Prev)
161 #ifdef MFEM_USE_MEMALLOC
164 RowNode *new_node_p =
new RowNode;
166 new_node_p->Value = node_p->Value;
167 new_node_p->Column = node_p->Column;
168 *node_pp = new_node_p;
169 node_pp = &new_node_p->Prev;
199 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
218 #ifdef MFEM_USE_MEMALLOC
234 return I[gi+1]-
I[gi];
238 RowNode *row =
Rows[gi];
239 for ( ; row != NULL; row = row->Prev)
240 if (row->Value != 0.0)
253 for (
int i=0; i <
height; ++i)
255 rowSize =
I[i+1]-
I[i];
256 out = (out > rowSize) ? out : rowSize;
261 for (
int i=0; i <
height; ++i)
264 out = (out > rowSize) ? out : rowSize;
273 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
280 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
287 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
294 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
301 if (newWidth ==
width)
306 else if ( newWidth == -1)
312 else if (newWidth >
width)
323 ColPtrJ =
static_cast<int *
>(NULL);
331 "The new width needs to be bigger or equal to the actual width");
339 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
347 for (
int j = 0, i = 0; i <
height; i++)
351 for (
int k = 0; k < row.
Size(); k++)
357 for (
int k = 0; k < row.
Size(); k++, j++)
368 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
370 for (
int row = 0, end = 0; row <
height; row++)
374 for (j = start;
true; j++)
376 MFEM_VERIFY(j < end,
"diagonal entry not found in row = " << row);
377 if (
J[j] == row) {
break; }
379 const double diag =
A[j];
380 for ( ; j > start; j--)
402 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
403 "Trying to access element outside of the matrix. "
404 <<
"height = " <<
height <<
", "
405 <<
"width = " <<
width <<
", "
406 <<
"i = " << i <<
", "
409 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
411 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
419 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
425 static const double zero = 0.0;
427 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
428 "Trying to access element outside of the matrix. "
429 <<
"height = " <<
height <<
", "
430 <<
"width = " <<
width <<
", "
431 <<
"i = " << i <<
", "
436 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
446 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
448 if (node_p->Column == j)
450 return node_p->Value;
461 "Matrix must be square, not height = " <<
height <<
", width = " <<
width);
462 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
467 for (
int i = 0; i <
height; i++)
471 for (j =
I[i]; j < end; j++)
495 "Input vector size (" << x.
Size() <<
") must match matrix width (" <<
width
498 "Output vector size (" << y.
Size() <<
") must match matrix height (" <<
height
503 const double *xp = x.
GetData();
508 for (i = 0; i <
height; i++)
510 RowNode *row =
Rows[i];
512 for ( ; row != NULL; row = row->Prev)
514 b += row->Value * xp[row->Column];
522 int *Jp =
J, *Ip =
I;
526 #ifndef MFEM_USE_OPENMP
527 for (i = j = 0; i <
height; i++)
530 for (end = Ip[i+1]; j < end; j++)
532 d += Ap[j] * xp[Jp[j]];
537 #pragma omp parallel for private(j,end)
538 for (i = 0; i <
height; i++)
541 for (j = Ip[i], end = Ip[i+1]; j < end; j++)
543 d += Ap[j] * xp[Jp[j]];
551 for (i = j = 0; i <
height; i++)
554 for (end = Ip[i+1]; j < end; j++)
556 d += Ap[j] * xp[Jp[j]];
570 const double a)
const
573 "Input vector size (" << x.
Size() <<
") must match matrix height (" <<
height
576 "Output vector size (" << y.
Size() <<
") must match matrix width (" <<
width
585 for (i = 0; i <
height; i++)
587 RowNode *row =
Rows[i];
589 for ( ; row != NULL; row = row->Prev)
591 yp[row->Column] += row->Value * b;
597 for (i = 0; i <
height; i++)
599 double xi = a * x(i);
601 for (j =
I[i]; j < end; j++)
611 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
613 for (
int i = 0; i < rows.
Size(); i++)
618 for (
int j =
I[r]; j < end; j++)
629 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
631 for (
int i = 0; i < rows.
Size(); i++)
636 for (
int j =
I[r]; j < end; j++)
638 val +=
A[j] * x(
J[j]);
646 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
647 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
648 <<
") must match matrix width (" <<
Width() <<
")");
653 for (
int i = 0; i <
Height(); i++)
656 for (
int j =
I[i]; j < end; j++)
670 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
671 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
672 <<
") must match matrix height (" <<
Height() <<
")");
677 for (
int i = 0; i <
Height(); i++)
682 for (
int j =
I[i]; j < end; j++)
693 <<
" must be equal to Width() = " <<
Width());
695 <<
" must be equal to Height() = " <<
Height());
697 for (
int i = 0; i <
height; i++)
701 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
706 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
708 a += np->Value * x(np->Column);
718 for (
int i = 0; i <
height; i++)
722 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
727 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
737 MFEM_VERIFY(irow <
height,
738 "row " << irow <<
" not in matrix with height " <<
height);
742 for (
int j =
I[irow], end =
I[irow+1]; j < end; j++)
747 for (RowNode *np =
Rows[irow]; np != NULL; np = np->Prev)
749 a += fabs(np->Value);
770 for (i = 1; i <=
height; i++)
773 for (aux =
Rows[i-1]; aux != NULL; aux = aux->Prev)
774 if (!skip_zeros || aux->Value != 0.0)
778 if (fix_empty_rows && !nr) { nr = 1; }
787 for (j = i = 0; i <
height; i++)
791 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
793 if (!skip_zeros || aux->Value != 0.0)
798 if ( lastCol >
J[j] )
808 if (fix_empty_rows && !nr)
816 #ifdef MFEM_USE_MEMALLOC
820 for (i = 0; i <
height; i++)
822 RowNode *node_p =
Rows[i];
823 while (node_p != NULL)
826 node_p = node_p->Prev;
839 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
841 for (
int j = 0; j < bc; j++)
843 for (
int i = 0; i < br; i++)
845 int *bI =
new int[nr + 1];
846 for (
int k = 0; k <= nr; k++)
854 for (
int gr = 0; gr <
height; gr++)
856 int bi = gr/nr, i = gr%nr + 1;
859 for (
int j =
I[gr]; j <
I[gr+1]; j++)
863 blocks(bi,
J[j]/nc)->I[i]++;
869 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
871 if (n_p->Value != 0.0)
873 blocks(bi, n_p->Column/nc)->I[i]++;
879 for (
int j = 0; j < bc; j++)
881 for (
int i = 0; i < br; i++)
885 for (
int k = 1; k <= nr; k++)
887 rs = b.
I[k], b.
I[k] = nnz, nnz += rs;
890 b.
A =
new double[nnz];
894 for (
int gr = 0; gr <
height; gr++)
896 int bi = gr/nr, i = gr%nr + 1;
899 for (
int j =
I[gr]; j <
I[gr+1]; j++)
904 b.
J[b.
I[i]] =
J[j] % nc;
912 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
914 if (n_p->Value != 0.0)
917 b.
J[b.
I[i]] = n_p->Column % nc;
918 b.
A[b.
I[i]] = n_p->Value;
940 for (
int i = 1; i <
height; i++)
942 for (
int j =
I[i]; j <
I[i+1]; j++)
946 symm = std::max(symm, std::abs(
A[j]-(*
this)(
J[j],i)));
953 for (
int i = 0; i <
height; i++)
955 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
957 int col = node_p->Column;
960 symm = std::max(symm, std::abs(node_p->Value-(*
this)(col,i)));
970 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
973 for (i = 1; i <
height; i++)
974 for (j =
I[i]; j <
I[i+1]; j++)
977 A[j] += (*this)(
J[j],i);
979 (*this)(J[j],i) = A[j];
993 for (
int i = 0; i <
height; i++)
995 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1012 for (
int j = 0; j < nnz; j++)
1014 m = std::max(m, std::abs(
A[j]));
1019 for (
int i = 0; i <
height; i++)
1020 for (RowNode *n_p =
Rows[i]; n_p != NULL; n_p = n_p->Prev)
1022 m = std::max(m, std::abs(n_p->Value));
1035 const double *Ap =
A;
1037 for (
int i = 0; i < nz; i++)
1039 counter += (std::abs(Ap[i]) <= tol);
1044 for (
int i = 0; i <
height; i++)
1046 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1048 counter += (std::abs(aux->Value) <= tol);
1069 for (
int i = 0; i <
height; i++)
1071 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1089 MFEM_ASSERT(row < height && row >= 0,
1090 "Row " << row <<
" not in matrix of height " <<
height);
1092 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1094 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1096 rhs(aux->Column) -= sol * aux->Value;
1105 MFEM_ASSERT(row < height && row >= 0,
1106 "Row " << row <<
" not in matrix of height " <<
height);
1107 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1109 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1114 for (
int i=
I[row]; i <
I[row+1]; ++i)
1121 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1135 MFEM_ASSERT(col < width && col >= 0,
1136 "Col " << col <<
" not in matrix of width " <<
width);
1137 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1139 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1145 for (
int jpos = 0; jpos != nnz; ++jpos)
1155 for (
int i = 0; i <
height; i++)
1157 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1159 if (aux->Column == col)
1178 for (
int i = 0; i <
height; i++)
1179 for (
int jpos =
I[i]; jpos !=
I[i+1]; ++jpos)
1180 if (cols[
J[jpos]] )
1184 (*b)(i) -=
A[jpos] * (*x)(
J[jpos] );
1191 for (
int i = 0; i <
height; i++)
1192 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1193 if (cols[aux -> Column])
1197 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1209 MFEM_ASSERT(rc < height && rc >= 0,
1210 "Row " << rc <<
" not in matrix of height " <<
height);
1214 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1216 if ((col =
J[j]) == rc)
1221 rhs(rc) =
A[j] * sol;
1232 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1239 for (
int k = I[col]; 1; k++)
1243 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1245 else if (
J[k] == rc)
1247 rhs(col) -= sol *
A[k];
1257 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1259 if ((col = aux->Column) == rc)
1264 rhs(rc) = aux->Value * sol;
1275 mfem_error(
"SparseMatrix::EliminateRowCol () #4");
1282 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1286 mfem_error(
"SparseMatrix::EliminateRowCol () #5");
1288 else if (node->Column == rc)
1290 rhs(col) -= sol * node->Value;
1305 int num_rhs = rhs.
Width();
1307 MFEM_ASSERT(rc < height && rc >= 0,
1308 "Row " << rc <<
" not in matrix of height " <<
height);
1309 MFEM_ASSERT(sol.
Size() == num_rhs,
"solution size (" << sol.
Size()
1310 <<
") must match rhs width (" << num_rhs <<
")");
1314 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1316 if ((col =
J[j]) == rc)
1321 for (
int r = 0; r < num_rhs; r++)
1323 rhs(rc,r) =
A[j] * sol(r);
1328 for (
int r = 0; r < num_rhs; r++)
1335 for (
int r = 0; r < num_rhs; r++)
1341 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
1348 for (
int k = I[col]; 1; k++)
1352 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
1354 else if (
J[k] == rc)
1356 for (
int r = 0; r < num_rhs; r++)
1358 rhs(col,r) -= sol(r) *
A[k];
1369 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1371 if ((col = aux->Column) == rc)
1376 for (
int r = 0; r < num_rhs; r++)
1378 rhs(rc,r) = aux->Value * sol(r);
1383 for (
int r = 0; r < num_rhs; r++)
1390 for (
int r = 0; r < num_rhs; r++)
1396 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #5");
1403 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1407 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #6");
1409 else if (node->Column == rc)
1411 for (
int r = 0; r < num_rhs; r++)
1413 rhs(col,r) -= sol(r) * node->Value;
1428 MFEM_ASSERT(rc < height && rc >= 0,
1429 "Row " << rc <<
" not in matrix of height " <<
height);
1433 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1434 if ((col =
J[j]) == rc)
1448 for (
int k = I[col]; 1; k++)
1451 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1453 else if (
J[k] == rc)
1462 RowNode *aux, *node;
1464 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1466 if ((col = aux->Column) == rc)
1480 for (node =
Rows[col]; 1; node = node->Prev)
1483 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1485 else if (node->Column == rc)
1501 MFEM_ASSERT(rc < height && rc >= 0,
1502 "Row " << rc <<
" not in matrix of height " <<
height);
1506 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1507 if ((col =
J[j]) == rc)
1514 for (
int k = I[col]; 1; k++)
1517 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1519 else if (
J[k] == rc)
1528 RowNode *aux, *node;
1530 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1532 if ((col = aux->Column) == rc)
1539 for (node =
Rows[col]; 1; node = node->Prev)
1542 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1544 else if (node->Column == rc)
1562 for (nd =
Rows[rc]; nd != NULL; nd = nd->Prev)
1564 if ((col = nd->Column) == rc)
1569 Ae.
Add(rc, rc, nd->Value - 1.0);
1573 Ae.
Add(rc, rc, nd->Value);
1579 mfem_error(
"SparseMatrix::EliminateRowCol #1");
1585 Ae.
Add(rc, col, nd->Value);
1587 for (nd2 =
Rows[col]; 1; nd2 = nd2->Prev)
1591 mfem_error(
"SparseMatrix::EliminateRowCol #2");
1593 else if (nd2->Column == rc)
1595 Ae.
Add(col, rc, nd2->Value);
1605 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1607 if ((col =
J[j]) == rc)
1612 Ae.
Add(rc, rc,
A[j] - 1.0);
1616 Ae.
Add(rc, rc,
A[j]);
1622 mfem_error(
"SparseMatrix::EliminateRowCol #3");
1628 Ae.
Add(rc, col,
A[j]);
1630 for (
int k = I[col];
true; k++)
1634 mfem_error(
"SparseMatrix::EliminateRowCol #4");
1636 else if (
J[k] == rc)
1638 Ae.
Add(col, rc,
A[k]);
1650 for (
int i = 0; i <
height; i++)
1651 if (
I[i+1] ==
I[i]+1 && fabs(
A[
I[i]]) < 1e-16)
1662 for (i = 0; i <
height; i++)
1665 for (j =
I[i]; j <
I[i+1]; j++)
1669 if (zero <= threshold)
1671 for (j = I[i]; j < I[i+1]; j++)
1687 double sum, *yp = y.
GetData();
1688 const double *xp = x.
GetData();
1692 RowNode *diag_p, *n_p, **R =
Rows;
1694 for (i = 0; i < s; i++)
1698 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1699 if ((c = n_p->Column) == i)
1705 sum += n_p->Value * yp[c];
1708 if (diag_p != NULL && diag_p->Value != 0.0)
1710 yp[i] = (xp[i] - sum) / diag_p->Value;
1712 else if (xp[i] == sum)
1718 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
1724 int j, end, d, *Ip =
I, *Jp =
J;
1728 for (i = 0; i < s; i++)
1733 for ( ; j < end; j++)
1734 if ((c = Jp[j]) == i)
1740 sum += Ap[j] * yp[c];
1743 if (d >= 0 && Ap[d] != 0.0)
1745 yp[i] = (xp[i] - sum) / Ap[d];
1747 else if (xp[i] == sum)
1753 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
1762 double sum, *yp = y.
GetData();
1763 const double *xp = x.
GetData();
1767 RowNode *diag_p, *n_p, **R =
Rows;
1769 for (i =
height-1; i >= 0; i--)
1773 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1774 if ((c = n_p->Column) == i)
1780 sum += n_p->Value * yp[c];
1783 if (diag_p != NULL && diag_p->Value != 0.0)
1785 yp[i] = (xp[i] - sum) / diag_p->Value;
1787 else if (xp[i] == sum)
1793 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
1799 int j, beg, d, *Ip =
I, *Jp =
J;
1803 for (i =
height-1; i >= 0; i--)
1808 for ( ; j >= beg; j--)
1809 if ((c = Jp[j]) == i)
1815 sum += Ap[j] * yp[c];
1818 if (d >= 0 && Ap[d] != 0.0)
1820 yp[i] = (xp[i] - sum) / Ap[d];
1822 else if (xp[i] == sum)
1828 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
1836 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1839 for (
int i = 0; i <
height; i++)
1843 for (
int j =
I[i]; j <
I[i+1]; j++)
1851 if (d >= 0 &&
A[d] != 0.0)
1853 double a = 1.8 * fabs(
A[d]) / norm;
1861 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
1870 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1872 for (
int i = 0; i <
height; i++)
1876 for (
int j =
I[i]; j <
I[i+1]; j++)
1884 sum -=
A[j] * x0(
J[j]);
1887 if (d >= 0 &&
A[d] != 0.0)
1889 x1(i) = sc * (sum /
A[d]) + (1.0 - sc) * x0(i);
1900 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1902 bool scale = (sc != 1.0);
1903 for (
int i = 0, j = 0; i <
height; i++)
1908 MFEM_VERIFY(j != end,
"Couldn't find diagonal in row. i = " << i
1910 <<
", I[i+1] = " << end );
1913 MFEM_VERIFY(std::abs(
A[j]) > 0.0,
"Diagonal " << j <<
" must be nonzero");
1916 x(i) = sc * b(i) /
A[j];
1933 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1935 for (
int i = 0; i <
height; i++)
1937 double resi = b(i), norm = 0.0;
1938 for (
int j =
I[i]; j <
I[i+1]; j++)
1940 resi -=
A[j] * x0(
J[j]);
1945 x1(i) = x0(i) + sc * resi / norm;
1949 MFEM_ABORT(
"L1 norm of row " << i <<
" is zero.");
1957 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1959 for (
int i = 0; i <
height; i++)
1961 double resi = b(i), sum = 0.0;
1962 for (
int j =
I[i]; j <
I[i+1]; j++)
1964 resi -=
A[j] * x0(
J[j]);
1969 x1(i) = x0(i) + sc * resi / sum;
1973 MFEM_ABORT(
"sum of row " << i <<
" is zero.");
1981 int i, j, gi, gj, s, t;
1984 for (i = 0; i < rows.
Size(); i++)
1986 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
1989 "Trying to insert a row " << gi <<
" outside the matrix height "
1992 for (j = 0; j < cols.
Size(); j++)
1994 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1996 MFEM_ASSERT(gj <
width,
1997 "Trying to insert a column " << gj <<
" outside the matrix width "
2000 if (skip_zeros && a == 0.0)
2004 if (&rows != &cols || subm(j, i) == 0.0)
2009 if (t < 0) { a = -a; }
2021 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2024 "Trying to insert a row " << gi <<
" outside the matrix height "
2026 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2028 MFEM_ASSERT(gj <
width,
2029 "Trying to insert a column " << gj <<
" outside the matrix width "
2031 if (t < 0) { a = -a; }
2040 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2043 "Trying to insert a row " << gi <<
" outside the matrix height "
2045 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2047 MFEM_ASSERT(gj <
width,
2048 "Trying to insert a column " << gj <<
" outside the matrix width "
2050 if (t < 0) { a = -a; }
2057 int i, j, gi, gj, s, t;
2060 for (i = 0; i < rows.
Size(); i++)
2062 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2065 "Trying to insert a row " << gi <<
" outside the matrix height "
2068 for (j = 0; j < cols.
Size(); j++)
2071 if (skip_zeros && a == 0.0)
2075 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2077 MFEM_ASSERT(gj <
width,
2078 "Trying to insert a column " << gj <<
" outside the matrix width "
2080 if (t < 0) { a = -a; }
2092 int i, j, gi, gj, s, t;
2095 for (i = 0; i < rows.
Size(); i++)
2097 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2100 "Trying to insert a row " << gi <<
" outside the matrix height "
2103 for (j = 0; j < cols.
Size(); j++)
2106 if (skip_zeros && a == 0.0)
2110 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2112 MFEM_ASSERT(gj <
width,
2113 "Trying to insert a column " << gj <<
" outside the matrix width "
2115 if (t < 0) { a = -a; }
2125 int i, j, gi, gj, s, t;
2128 for (i = 0; i < rows.
Size(); i++)
2130 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2133 "Trying to insert a row " << gi <<
" outside the matrix height "
2136 for (j = 0; j < cols.
Size(); j++)
2138 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2140 MFEM_ASSERT(gj <
width,
2141 "Trying to insert a column " << gj <<
" outside the matrix width "
2144 subm(i, j) = (t < 0) ? (-a) : (a);
2159 "Trying to insert a row " << gi <<
" outside the matrix height "
2163 return (
Rows[gi] == NULL);
2167 return (
I[gi] ==
I[gi+1]);
2176 if ((gi=row) < 0) { gi = -1-gi; }
2178 "Trying to insert a row " << gi <<
" outside the matrix height "
2182 for (n =
Rows[gi], j = 0; n; n = n->Prev)
2188 for (n =
Rows[gi], j = 0; n; n = n->Prev, j++)
2190 cols[j] = n->Column;
2205 MFEM_ASSERT(row >= 0,
"Row not valid: " << row );
2216 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2219 "Trying to insert a row " << gi <<
" outside the matrix height "
2225 for (
int j = 0; j < cols.
Size(); j++)
2227 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2229 MFEM_ASSERT(gj <
width,
2230 "Trying to insert a column " << gj <<
" outside the matrix"
2231 " width " <<
width);
2233 if (t < 0) { a = -a; }
2241 MFEM_ASSERT(cols.
Size() == srow.
Size(),
"");
2243 for (
int i =
I[gi], j = 0; j < cols.
Size(); j++, i++)
2245 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2247 MFEM_ASSERT(gj <
width,
2248 "Trying to insert a column " << gj <<
" outside the matrix"
2249 " width " <<
width);
2261 int j, gi, gj, s, t;
2264 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
2266 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2269 "Trying to insert a row " << gi <<
" outside the matrix height "
2272 for (j = 0; j < cols.
Size(); j++)
2274 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2276 MFEM_ASSERT(gj <
width,
2277 "Trying to insert a column " << gj <<
" outside the matrix width "
2284 if (t < 0) { a = -a; }
2302 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2304 aux -> Value *= scale;
2309 int j, end =
I[i+1];
2311 for (j =
I[i]; j < end; j++)
2324 for (
int i=0; i <
height; ++i)
2327 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2329 aux -> Value *= scale;
2337 for (
int i=0; i <
height; ++i)
2341 for (j =
I[i]; j < end; j++)
2354 for (
int i=0; i <
height; ++i)
2356 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2358 aux -> Value *= sr(aux->Column);
2366 for (
int i=0; i <
height; ++i)
2369 for (j =
I[i]; j < end; j++)
2380 "Mismatch of this matrix size and rhs. This height = "
2381 <<
height <<
", width = " <<
width <<
", B.height = "
2384 for (
int i = 0; i <
height; i++)
2389 for (RowNode *aux = B.
Rows[i]; aux != NULL; aux = aux->Prev)
2391 _Add_(aux->Column, aux->Value);
2396 for (
int j = B.
I[i]; j < B.
I[i+1]; j++)
2409 for (
int i = 0; i <
height; i++)
2414 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
2416 np->Value += a * B.
_Get_(np->Column);
2421 for (
int j =
I[i]; j <
I[i+1]; j++)
2433 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2438 for (
int i = 0; i <
height; i++)
2439 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2440 node_p = node_p -> Prev)
2442 node_p -> Value = a;
2451 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2456 for (
int i = 0; i <
height; i++)
2457 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2458 node_p = node_p -> Prev)
2460 node_p -> Value *= a;
2473 for (i = 0; i <
height; i++)
2475 out <<
"[row " << i <<
"]\n";
2476 for (nd =
Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
2478 out <<
" (" << nd->Column <<
"," << nd->Value <<
")";
2479 if ( !((j+1) % _width) )
2492 for (i = 0; i <
height; i++)
2494 out <<
"[row " << i <<
"]\n";
2495 for (j =
I[i]; j <
I[i+1]; j++)
2497 out <<
" (" <<
J[j] <<
"," <<
A[j] <<
")";
2498 if ( !((j+1-I[i]) % _width) )
2503 if ((j-I[i]) % _width)
2512 out <<
"% size " <<
height <<
" " <<
width <<
"\n";
2515 ios::fmtflags old_fmt = out.flags();
2516 out.setf(ios::scientific);
2517 std::streamsize old_prec = out.precision(14);
2519 for (i = 0; i <
height; i++)
2520 for (j =
I[i]; j <
I[i+1]; j++)
2522 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2524 out.precision(old_prec);
2531 ios::fmtflags old_fmt = out.flags();
2532 out.setf(ios::scientific);
2533 std::streamsize old_prec = out.precision(14);
2535 out <<
"%%MatrixMarket matrix coordinate real general" <<
'\n'
2536 <<
"% Generated by MFEM" <<
'\n';
2539 for (i = 0; i <
height; i++)
2540 for (j =
I[i]; j <
I[i+1]; j++)
2542 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
2544 out.precision(old_prec);
2550 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2556 for (i = 0; i <=
height; i++)
2558 out <<
I[i]+1 <<
'\n';
2561 for (i = 0; i <
I[
height]; i++)
2563 out <<
J[i]+1 <<
'\n';
2566 for (i = 0; i < I[
height]; i++)
2568 out <<
A[i] <<
'\n';
2574 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2579 out <<
width <<
'\n';
2581 for (i = 0; i <=
height; i++)
2583 out <<
I[i] <<
'\n';
2586 for (i = 0; i <
I[
height]; i++)
2588 out <<
J[i] <<
'\n';
2591 for (i = 0; i < I[
height]; i++)
2593 out <<
A[i] <<
'\n';
2599 const double MiB = 1024.*1024;
2601 double pz = 100./nnz;
2611 "SparseMatrix statistics:\n"
2614 " Dimensions : " <<
height <<
" x " <<
width <<
"\n"
2615 " Number of entries (total) : " << nnz <<
"\n"
2616 " Number of entries (per row) : " << 1.*nnz/
Height() <<
"\n"
2617 " Number of stored zeros : " << nz*pz <<
"% (" << nz <<
")\n"
2618 " Number of Inf/Nan entries : " << nnf*pz <<
"% ("<< nnf <<
")\n"
2619 " Norm, max |a_ij| : " << max_norm <<
"\n"
2620 " Symmetry, max |a_ij-a_ji| : " << symm <<
"\n"
2621 " Number of small entries:\n"
2622 " |a_ij| <= 1e-12*Norm : " << ns12*pz <<
"% (" << ns12 <<
")\n"
2623 " |a_ij| <= 1e-15*Norm : " << ns15*pz <<
"% (" << ns15 <<
")\n"
2624 " |a_ij| <= 1e-18*Norm : " << ns18*pz <<
"% (" << ns18 <<
")\n";
2627 out <<
" Memory used by CSR : " <<
2628 (
sizeof(int)*(
height+1+nnz)+
sizeof(double)*nnz)/MiB <<
" MiB\n";
2632 size_t used_mem =
sizeof(RowNode*)*
height;
2633 #ifdef MFEM_USE_MEMALLOC
2636 for (
int i = 0; i <
height; i++)
2638 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2640 used_mem +=
sizeof(RowNode);
2644 out <<
" Memory used by LIL : " << used_mem/MiB <<
" MiB\n";
2665 #if !defined(MFEM_USE_MEMALLOC)
2666 for (
int i = 0; i <
height; i++)
2668 RowNode *aux, *node_p =
Rows[i];
2669 while (node_p != NULL)
2672 node_p = node_p->Prev;
2688 #ifdef MFEM_USE_MEMALLOC
2703 for (
int *jptr = start_j; jptr != end_j; ++jptr)
2705 awidth = std::max(awidth, *jptr + 1);
2711 for (
int i = 0; i <
height; i++)
2713 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
2715 awidth = std::max(awidth, aux->Column + 1);
2727 for (
int i = 0; i < n; i++)
2737 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
2740 int m, n, nnz, *A_i, *A_j, *At_i, *At_j;
2741 double *A_data, *At_data;
2750 At_i =
new int[n+1];
2751 At_j =
new int[nnz];
2752 At_data =
new double[nnz];
2754 for (i = 0; i <= n; i++)
2758 for (i = 0; i < nnz; i++)
2762 for (i = 1; i < n; i++)
2764 At_i[i+1] += At_i[i];
2767 for (i = j = 0; i < m; i++)
2770 for ( ; j < end; j++)
2772 At_j[At_i[A_j[j]]] = i;
2773 At_data[At_i[A_j[j]]] = A_data[j];
2778 for (i = n; i > 0; i--)
2780 At_i[i] = At_i[i-1];
2791 int m, n, nnz, *At_i, *At_j;
2801 for (i = 0; i < m; i++)
2803 A.
GetRow(i, Acols, Avals);
2821 At_i =
new int[n+1];
2822 At_j =
new int[nnz];
2823 At_data =
new double[nnz];
2825 for (i = 0; i <= n; i++)
2830 for (i = 0; i < m; i++)
2832 A.
GetRow(i, Acols, Avals);
2833 for (j = 0; j<Acols.
Size(); ++j)
2838 for (i = 1; i < n; i++)
2840 At_i[i+1] += At_i[i];
2843 for (i = 0; i < m; i++)
2845 A.
GetRow(i, Acols, Avals);
2846 for (j = 0; j<Acols.
Size(); ++j)
2848 At_j[At_i[Acols[j]]] = i;
2849 At_data[At_i[Acols[j]]] = Avals[j];
2854 for (i = n; i > 0; i--)
2856 At_i[i] = At_i[i-1];
2867 int nrowsA, ncolsA, nrowsB, ncolsB;
2868 int *A_i, *A_j, *B_i, *B_j, *C_i, *C_j, *B_marker;
2869 double *A_data, *B_data, *C_data;
2870 int ia, ib, ic, ja, jb, num_nonzeros;
2871 int row_start, counter;
2872 double a_entry, b_entry;
2880 MFEM_VERIFY(ncolsA == nrowsB,
2881 "number of columns of A (" << ncolsA
2882 <<
") must equal number of rows of B (" << nrowsB <<
")");
2891 B_marker =
new int[ncolsB];
2893 for (ib = 0; ib < ncolsB; ib++)
2900 C_i =
new int[nrowsA+1];
2902 C_i[0] = num_nonzeros = 0;
2903 for (ic = 0; ic < nrowsA; ic++)
2905 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2908 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
2911 if (B_marker[jb] != ic)
2918 C_i[ic+1] = num_nonzeros;
2921 C_j =
new int[num_nonzeros];
2922 C_data =
new double[num_nonzeros];
2924 C =
new SparseMatrix (C_i, C_j, C_data, nrowsA, ncolsB);
2926 for (ib = 0; ib < ncolsB; ib++)
2935 MFEM_VERIFY(nrowsA == C -> Height() && ncolsB == C -> Width(),
2936 "Input matrix sizes do not match output sizes"
2937 <<
" nrowsA = " << nrowsA
2938 <<
", C->Height() = " << C->
Height()
2939 <<
" ncolsB = " << ncolsB
2940 <<
", C->Width() = " << C->
Width());
2944 C_data = C -> GetData();
2948 for (ic = 0; ic < nrowsA; ic++)
2951 row_start = counter;
2952 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2955 a_entry = A_data[ia];
2956 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
2959 b_entry = B_data[ib];
2960 if (B_marker[jb] < row_start)
2962 B_marker[jb] = counter;
2967 C_data[counter] = a_entry*b_entry;
2972 C_data[B_marker[jb]] += a_entry*b_entry;
2980 "With pre-allocated output matrix, number of non-zeros ("
2982 <<
") did not match number of entries changed from matrix-matrix multiply, "
2993 int nrowsA, ncolsA, nrowsB, ncolsB;
2994 int *C_i, *C_j, *B_marker;
2996 int ia, ib, ic, ja, jb, num_nonzeros;
2997 int row_start, counter;
2998 double a_entry, b_entry;
3006 MFEM_VERIFY(ncolsA == nrowsB,
3007 "number of columns of A (" << ncolsA
3008 <<
") must equal number of rows of B (" << nrowsB <<
")");
3010 B_marker =
new int[ncolsB];
3012 for (ib = 0; ib < ncolsB; ib++)
3017 C_i =
new int[nrowsA+1];
3019 C_i[0] = num_nonzeros = 0;
3023 for (ic = 0; ic < nrowsA; ic++)
3025 A.
GetRow(ic, colsA, dataA);
3026 for (ia = 0; ia < colsA.
Size(); ia++)
3029 B.
GetRow(ja, colsB, dataB);
3030 for (ib = 0; ib < colsB.
Size(); ib++)
3033 if (B_marker[jb] != ic)
3040 C_i[ic+1] = num_nonzeros;
3043 C_j =
new int[num_nonzeros];
3044 C_data =
new double[num_nonzeros];
3046 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3048 for (ib = 0; ib < ncolsB; ib++)
3054 for (ic = 0; ic < nrowsA; ic++)
3056 row_start = counter;
3057 A.
GetRow(ic, colsA, dataA);
3058 for (ia = 0; ia < colsA.
Size(); ia++)
3061 a_entry = dataA[ia];
3062 B.
GetRow(ja, colsB, dataB);
3063 for (ib = 0; ib < colsB.
Size(); ib++)
3066 b_entry = dataB[ib];
3067 if (B_marker[jb] < row_start)
3069 B_marker[jb] = counter;
3071 C_data[counter] = a_entry*b_entry;
3076 C_data[B_marker[jb]] += a_entry*b_entry;
3091 for (
int j = 0; j < B.
Width(); ++j)
3095 A.
Mult(columnB, columnC);
3105 Mult (R, *AP, *_RAP);
3135 int i, At_nnz, *At_j;
3139 At_nnz = At -> NumNonZeroElems();
3140 At_j = At -> GetJ();
3141 At_data = At -> GetData();
3142 for (i = 0; i < At_nnz; i++)
3144 At_data[i] *= D(At_j[i]);
3155 int ncols = A.
Width();
3157 int * C_i =
new int[nrows+1];
3161 int * A_i = A.
GetI();
3162 int * A_j = A.
GetJ();
3163 double * A_data = A.
GetData();
3165 int * B_i = B.
GetI();
3166 int * B_j = B.
GetJ();
3167 double * B_data = B.
GetData();
3169 int * marker =
new int[ncols];
3170 std::fill(marker, marker+ncols, -1);
3172 int num_nonzeros = 0, jcol;
3174 for (
int ic = 0; ic < nrows; ic++)
3176 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3182 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3185 if (marker[jcol] != ic)
3191 C_i[ic+1] = num_nonzeros;
3194 C_j =
new int[num_nonzeros];
3195 C_data =
new double[num_nonzeros];
3197 for (
int ia = 0; ia < ncols; ia++)
3203 for (
int ic = 0; ic < nrows; ic++)
3205 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3209 C_data[pos] = a*A_data[ia];
3213 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3216 if (marker[jcol] < C_i[ic])
3219 C_data[pos] = b*B_data[ib];
3225 C_data[marker[jcol]] += b*B_data[ib];
3231 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
3236 return Add(1.,A,1.,B);
3241 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
3246 for (
int i=1; i < Ai.
Size(); ++i)
3248 result =
Add(*accumulate, *Ai[i]);
3254 accumulate = result;
3272 #ifdef MFEM_USE_MEMALLOC
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)
void _Add_(const int col, const double a)
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.
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)
bool Empty() const
Check if the SparseMatrix is empty.
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
int * I
Array with size (height+1) containing the row offsets.
Set the diagonal value to zero.
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, but treat all elements 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().
Abstract data type for sparse matrices.
SparseMatrix & operator+=(const SparseMatrix &B)
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.
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.
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.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
void _Set_(const int col, const double a)
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, but treat all elements 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
void GetBlocks(Array2D< SparseMatrix * > &blocks) const
void ScaleRow(const int row, const double scale)
int ActualWidth()
Returns the actual Width of the matrix.
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 ScaleColumns(const Vector &sr)
void PrintCSR2(std::ostream &out) const
Prints a sparse matrix to stream out in CSR format.
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.
SparseMatrix()
Create an empty SparseMatrix.
bool ownData
Say whether we own the pointers for A (should we free them?).
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.
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.
void Transpose(const Table &A, Table &At, int _ncols_A)
Transpose a Table.
void ScaleRows(const Vector &sl)
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.
double * GetData() const
Return element data, i.e. array A.
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
Set the diagonal value to one.
int * GetI() const
Return the array I.
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 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
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
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)
int * J
Array with size I[height], containing the column indices for all matrix entries, as indexed by the I ...
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.
double * A
Array with size I[height], containing the actual entries of the sparse matrix, as indexed by the I ar...
void GetDiag(Vector &d) const
Returns the Diagonal of A.
MemAlloc< RowNode, 1024 > RowNodeAlloc
double GetRowNorml1(int irow) const
For i = irow compute .
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.
bool ownGraph
Say whether we own the pointers for I and J (should we free them?).
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
OutStream out(std::cout)
Global stream used by the library for standard output. Initially it uses the same std::streambuf as s...
void Swap(SparseMatrix &other)
int * GetJ() const
Return the array J.
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)