15 #include "../general/table.hpp"
16 #include "../general/sort_pairs.hpp"
34 Rows(new RowNode *[nrows]),
42 for (
int i = 0; i < nrows; i++)
47 #ifdef MFEM_USE_MEMALLOC
64 #ifdef MFEM_USE_MEMALLOC
70 bool ownij,
bool owna,
bool issorted)
82 #ifdef MFEM_USE_MEMALLOC
90 A =
new double[ nnz ];
91 for (
int i=0; i<nnz; ++i)
103 const int nnz = mat.I[
height];
108 memcpy(I, mat.I,
sizeof(
int)*(
height+1));
109 memcpy(J, mat.J,
sizeof(
int)*nnz);
119 memcpy(A, mat.A,
sizeof(
double)*nnz);
123 #ifdef MFEM_USE_MEMALLOC
129 #ifdef MFEM_USE_MEMALLOC
132 Rows =
new RowNode *[
height];
133 for (
int i = 0; i <
height; i++)
135 RowNode **node_pp = &Rows[i];
136 for (RowNode *node_p = mat.Rows[i]; node_p; node_p = node_p->Prev)
138 #ifdef MFEM_USE_MEMALLOC
139 RowNode *new_node_p = NodesMem->
Alloc();
141 RowNode *new_node_p =
new RowNode;
143 new_node_p->Value = node_p->Value;
144 new_node_p->Column = node_p->Column;
145 *node_pp = new_node_p;
146 node_pp = &new_node_p->Prev;
161 isSorted = mat.isSorted;
166 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
175 void SparseMatrix::SetEmpty()
184 #ifdef MFEM_USE_MEMALLOC
187 ownGraph = ownData = isSorted =
false;
200 return I[gi+1]-I[gi];
204 RowNode *row = Rows[gi];
205 for ( ; row != NULL; row = row->Prev)
206 if (row->Value != 0.0)
219 for (
int i=0; i <
height; ++i)
221 rowSize = I[i+1]-I[i];
222 out = (out > rowSize) ? out : rowSize;
227 for (
int i=0; i <
height; ++i)
230 out = (out > rowSize) ? out : rowSize;
239 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
246 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
253 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
260 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
267 if (newWidth ==
width)
272 else if ( newWidth == -1)
278 else if (newWidth >
width)
283 delete [] ColPtrNode;
284 ColPtrNode =
static_cast<RowNode **
>(NULL);
289 ColPtrJ =
static_cast<int *
>(NULL);
297 "The new width needs to be bigger or equal to the actual width");
305 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
313 for (
int j = 0, i = 0; i <
height; i++)
317 for (
int k = 0; k < row.
Size(); k++)
323 for (
int k = 0; k < row.Size(); k++, j++)
346 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
347 "Trying to access element outside of the matrix. "
348 <<
"height = " <<
height <<
", "
349 <<
"width = " <<
width <<
", "
350 <<
"i = " << i <<
", "
353 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
356 for (k = I[i]; k < end; k++)
362 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
369 static const double zero = 0.0;
371 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
372 "Trying to access element outside of the matrix. "
373 <<
"height = " <<
height <<
", "
374 <<
"width = " <<
width <<
", "
375 <<
"i = " << i <<
", "
378 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
380 for (k = I[i]; k < end; k++)
392 "Matrix must be square, not height = " <<
height <<
", width = " <<
width);
393 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
398 for (
int i = 0; i <
height; i++)
402 for (j = I[i]; j < end; j++)
426 "Input vector size (" << x.
Size() <<
") must match matrix width (" <<
width
429 "Output vector size (" << y.
Size() <<
") must match matrix height (" <<
height
433 double *Ap = A, *yp = y.
GetData();
434 const double *xp = x.
GetData();
439 for (i = 0; i <
height; i++)
441 RowNode *row = Rows[i];
443 for ( ; row != NULL; row = row->Prev)
445 b += row->Value * xp[row->Column];
453 int *Jp = J, *Ip = I;
457 #ifndef MFEM_USE_OPENMP
458 for (i = j = 0; i <
height; i++)
461 for (end = Ip[i+1]; j < end; j++)
463 d += Ap[j] * xp[Jp[j]];
468 #pragma omp parallel for private(j,end)
469 for (i = 0; i <
height; i++)
472 for (j = Ip[i], end = Ip[i+1]; j < end; j++)
474 d += Ap[j] * xp[Jp[j]];
481 for (i = j = 0; i <
height; i++)
484 for (end = Ip[i+1]; j < end; j++)
486 d += Ap[j] * xp[Jp[j]];
499 const double a)
const
502 "Input vector size (" << x.
Size() <<
") must match matrix height (" <<
height
505 "Output vector size (" << y.
Size() <<
") must match matrix width (" <<
width
514 for (i = 0; i <
height; i++)
516 RowNode *row = Rows[i];
518 for ( ; row != NULL; row = row->Prev)
520 yp[row->Column] += row->Value * b;
526 for (i = 0; i <
height; i++)
528 double xi = a * x(i);
530 for (j = I[i]; j < end; j++)
540 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
542 for (
int i = 0; i < rows.
Size(); i++)
547 for (
int j = I[r]; j < end; j++)
558 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
560 for (
int i = 0; i < rows.
Size(); i++)
565 for (
int j = I[r]; j < end; j++)
567 val += A[j] * x(J[j]);
575 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
576 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
577 <<
") must match matrix width (" <<
Width() <<
")");
582 for (
int i = 0; i <
Height(); i++)
585 for (
int j = I[i]; j < end; j++)
599 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
600 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
601 <<
") must match matrix height (" <<
Height() <<
")");
606 for (
int i = 0; i <
Height(); i++)
611 for (
int j = I[i]; j < end; j++)
622 for (
int i = 0; i <
height; i++)
626 for (
int j = I[i], end = I[i+1]; j < end; j++)
631 for (RowNode *np = Rows[i]; np != NULL; np = np->Prev)
633 a += np->Value * x(np->Column);
643 for (
int i = 0; i <
height; i++)
647 for (
int j = I[i], end = I[i+1]; j < end; j++)
652 for (RowNode *np = Rows[i]; np != NULL; np = np->Prev)
662 MFEM_VERIFY(irow <
height,
663 "row " << irow <<
" not in matrix with height " <<
height);
667 for (
int j = I[irow], end = I[irow+1]; j < end; j++)
672 for (RowNode *np = Rows[irow]; np != NULL; np = np->Prev)
674 a += fabs(np->Value);
690 delete [] ColPtrNode;
695 for (i = 1; i <=
height; i++)
698 for (aux = Rows[i-1]; aux != NULL; aux = aux->Prev)
699 if (!skip_zeros || aux->Value != 0.0)
711 for (j = i = 0; i <
height; i++)
714 for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
716 if (!skip_zeros || aux->Value != 0.0)
721 if ( lastCol > J[j] )
732 #ifdef MFEM_USE_MEMALLOC
736 for (i = 0; i <
height; i++)
738 RowNode *node_p = Rows[i];
739 while (node_p != NULL)
742 node_p = node_p->Prev;
755 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
757 for (
int j = 0; j < bc; j++)
759 for (
int i = 0; i < br; i++)
761 int *bI =
new int[nr + 1];
762 for (
int k = 0; k <= nr; k++)
770 for (
int gr = 0; gr <
height; gr++)
772 int bi = gr/nr, i = gr%nr + 1;
775 for (
int j = I[gr]; j < I[gr+1]; j++)
779 blocks(bi, J[j]/nc)->I[i]++;
785 for (RowNode *n_p = Rows[gr]; n_p != NULL; n_p = n_p->Prev)
787 if (n_p->Value != 0.0)
789 blocks(bi, n_p->Column/nc)->I[i]++;
795 for (
int j = 0; j < bc; j++)
797 for (
int i = 0; i < br; i++)
801 for (
int k = 1; k <= nr; k++)
803 rs = b.I[k], b.I[k] = nnz, nnz += rs;
806 b.A =
new double[nnz];
810 for (
int gr = 0; gr <
height; gr++)
812 int bi = gr/nr, i = gr%nr + 1;
815 for (
int j = I[gr]; j < I[gr+1]; j++)
820 b.J[b.I[i]] = J[j] % nc;
828 for (RowNode *n_p = Rows[gr]; n_p != NULL; n_p = n_p->Prev)
830 if (n_p->Value != 0.0)
833 b.J[b.I[i]] = n_p->Column % nc;
834 b.A[b.I[i]] = n_p->Value;
844 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
850 for (i = 1; i <
height; i++)
851 for (j = I[i]; j < I[i+1]; j++)
854 a = fabs ( A[j] - (*
this)(J[j],i) );
866 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
869 for (i = 1; i <
height; i++)
870 for (j = I[i]; j < I[i+1]; j++)
873 A[j] += (*this)(J[j],i);
875 (*this)(J[j],i) = A[j];
889 for (
int i = 0; i <
height; i++)
890 for (RowNode *node_p = Rows[i]; node_p != NULL; node_p = node_p->Prev)
906 for (
int j = 0; j < nnz; j++)
908 m = std::max(m, fabs(A[j]));
913 for (
int i = 0; i <
height; i++)
914 for (RowNode *n_p = Rows[i]; n_p != NULL; n_p = n_p->Prev)
916 m = std::max(m, fabs(n_p->Value));
931 for (i = 0; i < nz; i++)
932 if (fabs(Ap[i]) < tol)
941 for (i = 0; i <
height; i++)
942 for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
943 if (fabs(aux -> Value) < tol)
961 MFEM_ASSERT(row < height && row >= 0,
962 "Row " << row <<
" not in matrix of height " <<
height);
964 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
966 for (aux = Rows[row]; aux != NULL; aux = aux->Prev)
968 rhs(aux->Column) -= sol * aux->Value;
977 MFEM_ASSERT(row < height && row >= 0,
978 "Row " << row <<
" not in matrix of height " <<
height);
980 "if setOneDiagonal, must be rectangular matrix, not height = "
984 for (
int i=I[row]; i < I[row+1]; ++i)
989 for (aux = Rows[row]; aux != NULL; aux = aux->Prev)
1004 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1006 for (
int i = 0; i <
height; i++)
1007 for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
1008 if (aux -> Column == col)
1018 for (
int i = 0; i <
height; i++)
1019 for (
int jpos = I[i]; jpos != I[i+1]; ++jpos)
1020 if (cols[ J[jpos]] )
1024 (*b)(i) -= A[jpos] * (*x)( J[jpos] );
1032 for (
int i = 0; i <
height; i++)
1033 for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
1034 if (cols[aux -> Column])
1038 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1050 MFEM_ASSERT(rc < height && rc >= 0,
1051 "Row " << rc <<
" not in matrix of height " <<
height);
1055 for (
int j = I[rc]; j < I[rc+1]; j++)
1057 if ((col = J[j]) == rc)
1061 rhs(rc) = A[j] * sol;
1072 for (
int k = I[col]; 1; k++)
1076 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1078 else if (J[k] == rc)
1080 rhs(col) -= sol * A[k];
1090 for (RowNode *aux = Rows[rc]; aux != NULL; aux = aux->Prev)
1092 if ((col = aux->Column) == rc)
1096 rhs(rc) = aux->Value * sol;
1107 for (RowNode *node = Rows[col]; 1; node = node->Prev)
1111 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1113 else if (node->Column == rc)
1115 rhs(col) -= sol * node->Value;
1129 int num_rhs = rhs.
Width();
1131 MFEM_ASSERT(rc < height && rc >= 0,
1132 "Row " << rc <<
" not in matrix of height " <<
height);
1133 MFEM_ASSERT(sol.
Size() == num_rhs,
"solution size (" << sol.
Size()
1134 <<
") must match rhs width (" << num_rhs <<
")");
1137 for (
int j = I[rc]; j < I[rc+1]; j++)
1138 if ((col = J[j]) == rc)
1141 for (
int r = 0; r < num_rhs; r++)
1143 rhs(rc,r) = A[j] * sol(r);
1149 for (
int r = 0; r < num_rhs; r++)
1157 for (
int k = I[col]; 1; k++)
1160 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
1162 else if (J[k] == rc)
1164 for (
int r = 0; r < num_rhs; r++)
1166 rhs(col,r) -= sol(r) * A[k];
1173 for (RowNode *aux = Rows[rc]; aux != NULL; aux = aux->Prev)
1174 if ((col = aux->Column) == rc)
1177 for (
int r = 0; r < num_rhs; r++)
1179 rhs(rc,r) = aux->Value * sol(r);
1185 for (
int r = 0; r < num_rhs; r++)
1193 for (RowNode *node = Rows[col]; 1; node = node->Prev)
1196 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
1198 else if (node->Column == rc)
1200 for (
int r = 0; r < num_rhs; r++)
1202 rhs(col,r) -= sol(r) * node->Value;
1214 MFEM_ASSERT(rc < height && rc >= 0,
1215 "Row " << rc <<
" not in matrix of height " <<
height);
1219 for (
int j = I[rc]; j < I[rc+1]; j++)
1220 if ((col = J[j]) == rc)
1230 for (
int k = I[col]; 1; k++)
1233 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1235 else if (J[k] == rc)
1244 RowNode *aux, *node;
1246 for (aux = Rows[rc]; aux != NULL; aux = aux->Prev)
1248 if ((col = aux->Column) == rc)
1258 for (node = Rows[col]; 1; node = node->Prev)
1261 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1263 else if (node->Column == rc)
1279 MFEM_ASSERT(rc < height && rc >= 0,
1280 "Row " << rc <<
" not in matrix of height " <<
height);
1284 for (
int j = I[rc]; j < I[rc+1]; j++)
1285 if ((col = J[j]) == rc)
1292 for (
int k = I[col]; 1; k++)
1295 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1297 else if (J[k] == rc)
1306 RowNode *aux, *node;
1308 for (aux = Rows[rc]; aux != NULL; aux = aux->Prev)
1310 if ((col = aux->Column) == rc)
1317 for (node = Rows[col]; 1; node = node->Prev)
1320 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1322 else if (node->Column == rc)
1339 for (nd = Rows[rc]; nd != NULL; nd = nd->Prev)
1341 if ((col = nd->Column) == rc)
1345 Ae.
Add(rc, rc, nd->Value - 1.0);
1351 Ae.
Add(rc, col, nd->Value);
1353 for (nd2 = Rows[col]; 1; nd2 = nd2->Prev)
1359 else if (nd2->Column == rc)
1361 Ae.
Add(col, rc, nd2->Value);
1371 for (
int j = I[rc]; j < I[rc+1]; j++)
1373 if ((col = J[j]) == rc)
1377 Ae.
Add(rc, rc, A[j] - 1.0);
1383 Ae.
Add(rc, col, A[j]);
1385 for (
int k = I[col];
true; k++)
1391 else if (J[k] == rc)
1393 Ae.
Add(col, rc, A[k]);
1405 for (
int i = 0; i <
height; i++)
1406 if (I[i+1] == I[i]+1 && fabs(A[I[i]]) < 1e-16)
1417 for (i = 0; i <
height; i++)
1420 for (j = I[i]; j < I[i+1]; j++)
1426 for (j = I[i]; j < I[i+1]; j++)
1442 double sum, *yp = y.
GetData();
1443 const double *xp = x.
GetData();
1447 RowNode *diag_p, *n_p, **R = Rows;
1449 for (i = 0; i < s; i++)
1453 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1454 if ((c = n_p->Column) == i)
1460 sum += n_p->Value * yp[c];
1463 if (diag_p != NULL && diag_p->Value != 0.0)
1465 yp[i] = (xp[i] - sum) / diag_p->Value;
1467 else if (xp[i] == sum)
1473 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
1479 int j, end, d, *Ip = I, *Jp = J;
1483 for (i = 0; i < s; i++)
1488 for ( ; j < end; j++)
1489 if ((c = Jp[j]) == i)
1495 sum += Ap[j] * yp[c];
1498 if (d >= 0 && Ap[d] != 0.0)
1500 yp[i] = (xp[i] - sum) / Ap[d];
1502 else if (xp[i] == sum)
1508 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
1517 double sum, *yp = y.
GetData();
1518 const double *xp = x.
GetData();
1522 RowNode *diag_p, *n_p, **R = Rows;
1524 for (i =
height-1; i >= 0; i--)
1528 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
1529 if ((c = n_p->Column) == i)
1535 sum += n_p->Value * yp[c];
1538 if (diag_p != NULL && diag_p->Value != 0.0)
1540 yp[i] = (xp[i] - sum) / diag_p->Value;
1542 else if (xp[i] == sum)
1548 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
1554 int j, beg, d, *Ip = I, *Jp = J;
1558 for (i =
height-1; i >= 0; i--)
1563 for ( ; j >= beg; j--)
1564 if ((c = Jp[j]) == i)
1570 sum += Ap[j] * yp[c];
1573 if (d >= 0 && Ap[d] != 0.0)
1575 yp[i] = (xp[i] - sum) / Ap[d];
1577 else if (xp[i] == sum)
1583 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
1591 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1594 for (
int i = 0; i <
height; i++)
1598 for (
int j = I[i]; j < I[i+1]; j++)
1606 if (d >= 0 && A[d] != 0.0)
1608 double a = 1.8 * fabs(A[d]) / norm;
1616 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
1625 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1627 for (
int i = 0; i <
height; i++)
1631 for (
int j = I[i]; j < I[i+1]; j++)
1639 sum -= A[j] * x0(J[j]);
1642 if (d >= 0 && A[d] != 0.0)
1644 x1(i) = sc * (sum / A[d]) + (1.0 - sc) * x0(i);
1655 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1657 bool scale = (sc != 1.0);
1658 for (
int i = 0, j = 0; i <
height; i++)
1663 MFEM_VERIFY(j != end,
"Couldn't find diagonal in row. i = " << i
1665 <<
", I[i+1] = " << end );
1668 MFEM_VERIFY(std::abs(A[j]) > 0.0,
"Diagonal " << j <<
" must be nonzero");
1671 x(i) = sc * b(i) / A[j];
1688 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1690 for (
int i = 0; i <
height; i++)
1692 double resi = b(i), norm = 0.0;
1693 for (
int j = I[i]; j < I[i+1]; j++)
1695 resi -= A[j] * x0(J[j]);
1700 x1(i) = x0(i) + sc * resi / norm;
1704 MFEM_ABORT(
"L1 norm of row " << i <<
" is zero.");
1712 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1714 for (
int i = 0; i <
height; i++)
1716 double resi = b(i), sum = 0.0;
1717 for (
int j = I[i]; j < I[i+1]; j++)
1719 resi -= A[j] * x0(J[j]);
1724 x1(i) = x0(i) + sc * resi / sum;
1728 MFEM_ABORT(
"sum of row " << i <<
" is zero.");
1736 int i, j, gi, gj, s, t;
1739 for (i = 0; i < rows.
Size(); i++)
1741 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
1744 "Trying to insert a row " << gi <<
" outside the matrix height "
1747 for (j = 0; j < cols.
Size(); j++)
1749 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1751 MFEM_ASSERT(gj <
width,
1752 "Trying to insert a column " << gj <<
" outside the matrix width "
1755 if (skip_zeros && a == 0.0)
1759 if (&rows != &cols || subm(j, i) == 0.0)
1764 if (t < 0) { a = -a; }
1776 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
1779 "Trying to insert a row " << gi <<
" outside the matrix height "
1781 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
1783 MFEM_ASSERT(gj <
width,
1784 "Trying to insert a column " << gj <<
" outside the matrix width "
1786 if (t < 0) { a = -a; }
1795 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
1798 "Trying to insert a row " << gi <<
" outside the matrix height "
1800 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
1802 MFEM_ASSERT(gj <
width,
1803 "Trying to insert a column " << gj <<
" outside the matrix width "
1805 if (t < 0) { a = -a; }
1812 int i, j, gi, gj, s, t;
1815 for (i = 0; i < rows.
Size(); i++)
1817 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
1820 "Trying to insert a row " << gi <<
" outside the matrix height "
1823 for (j = 0; j < cols.
Size(); j++)
1826 if (skip_zeros && a == 0.0)
1830 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1832 MFEM_ASSERT(gj <
width,
1833 "Trying to insert a column " << gj <<
" outside the matrix width "
1835 if (t < 0) { a = -a; }
1847 int i, j, gi, gj, s, t;
1850 for (i = 0; i < rows.
Size(); i++)
1852 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
1855 "Trying to insert a row " << gi <<
" outside the matrix height "
1858 for (j = 0; j < cols.
Size(); j++)
1861 if (skip_zeros && a == 0.0)
1865 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1867 MFEM_ASSERT(gj <
width,
1868 "Trying to insert a column " << gj <<
" outside the matrix width "
1870 if (t < 0) { a = -a; }
1880 int i, j, gi, gj, s, t;
1883 for (i = 0; i < rows.
Size(); i++)
1885 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
1888 "Trying to insert a row " << gi <<
" outside the matrix height "
1891 for (j = 0; j < cols.
Size(); j++)
1893 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1895 MFEM_ASSERT(gj <
width,
1896 "Trying to insert a column " << gj <<
" outside the matrix width "
1899 subm(i, j) = (t < 0) ? (-a) : (a);
1914 "Trying to insert a row " << gi <<
" outside the matrix height "
1918 return (Rows[gi] == NULL);
1922 return (I[gi] == I[gi+1]);
1931 if ((gi=row) < 0) { gi = -1-gi; }
1933 "Trying to insert a row " << gi <<
" outside the matrix height "
1937 for (n = Rows[gi], j = 0; n; n = n->Prev)
1943 for (n = Rows[gi], j = 0; n; n = n->Prev, j++)
1945 cols[j] = n->Column;
1958 cols.
MakeRef(J + j, I[gi+1]-j);
1960 MFEM_ASSERT(row >= 0,
"Row not valid: " << row );
1968 int j, gi, gj, s, t;
1971 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1973 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
1976 "Trying to insert a row " << gi <<
" outside the matrix height "
1979 for (j = 0; j < cols.
Size(); j++)
1981 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
1983 MFEM_ASSERT(gj <
width,
1984 "Trying to insert a column " << gj <<
" outside the matrix width "
1987 if (t < 0) { a = -a; }
1996 int j, gi, gj, s, t;
1999 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
2001 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2004 "Trying to insert a row " << gi <<
" outside the matrix height "
2007 for (j = 0; j < cols.
Size(); j++)
2009 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2011 MFEM_ASSERT(gj <
width,
2012 "Trying to insert a column " << gj <<
" outside the matrix width "
2019 if (t < 0) { a = -a; }
2037 for (aux = Rows[i]; aux != NULL; aux = aux -> Prev)
2039 aux -> Value *= scale;
2044 int j, end = I[i+1];
2046 for (j = I[i]; j < end; j++)
2059 for (
int i=0; i <
height; ++i)
2062 for (aux = Rows[i]; aux != NULL; aux = aux -> Prev)
2064 aux -> Value *= scale;
2072 for (
int i=0; i <
height; ++i)
2076 for (j = I[i]; j < end; j++)
2089 for (
int i=0; i <
height; ++i)
2091 for (aux = Rows[i]; aux != NULL; aux = aux -> Prev)
2093 aux -> Value *= sr(aux->Column);
2101 for (
int i=0; i <
height; ++i)
2104 for (j = I[i]; j < end; j++)
2115 "Mismatch of this matrix size and rhs. This height = "
2116 <<
height <<
", width = " <<
width <<
", B.height = "
2119 for (
int i = 0; i <
height; i++)
2124 for (RowNode *aux = B.Rows[i]; aux != NULL; aux = aux->Prev)
2126 _Add_(aux->Column, aux->Value);
2131 for (
int j = B.I[i]; j < B.I[i+1]; j++)
2133 _Add_(B.J[j], B.A[j]);
2144 for (
int i = 0; i <
height; i++)
2149 for (RowNode *np = Rows[i]; np != NULL; np = np->Prev)
2151 np->Value += a * B.
_Get_(np->Column);
2156 for (
int j = I[i]; j < I[i+1]; j++)
2158 A[j] += a * B.
_Get_(J[j]);
2168 for (
int i = 0, nnz = I[
height]; i < nnz; i++)
2173 for (
int i = 0; i <
height; i++)
2174 for (RowNode *node_p = Rows[i]; node_p != NULL;
2175 node_p = node_p -> Prev)
2177 node_p -> Value = a;
2186 for (
int i = 0, nnz = I[
height]; i < nnz; i++)
2191 for (
int i = 0; i <
height; i++)
2192 for (RowNode *node_p = Rows[i]; node_p != NULL;
2193 node_p = node_p -> Prev)
2195 node_p -> Value *= a;
2208 for (i = 0; i <
height; i++)
2210 out <<
"[row " << i <<
"]\n";
2211 for (nd = Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
2213 out <<
" (" << nd->Column <<
"," << nd->Value <<
")";
2214 if ( !((j+1) % _width) )
2227 for (i = 0; i <
height; i++)
2229 out <<
"[row " << i <<
"]\n";
2230 for (j = I[i]; j < I[i+1]; j++)
2232 out <<
" (" << J[j] <<
"," << A[j] <<
")";
2233 if ( !((j+1-I[i]) % _width) )
2238 if ((j-I[i]) % _width)
2247 out <<
"% size " <<
height <<
" " <<
width <<
"\n";
2250 ios::fmtflags old_fmt = out.flags();
2251 out.setf(ios::scientific);
2252 std::streamsize old_prec = out.precision(14);
2254 for (i = 0; i <
height; i++)
2255 for (j = I[i]; j < I[i+1]; j++)
2257 out << i+1 <<
" " << J[j]+1 <<
" " << A[j] <<
'\n';
2259 out.precision(old_prec);
2266 ios::fmtflags old_fmt = out.flags();
2267 out.setf(ios::scientific);
2268 std::streamsize old_prec = out.precision(14);
2270 out <<
"%%MatrixMarket matrix coordinate real general" <<
'\n'
2271 <<
"% Generated by MFEM" <<
'\n';
2274 for (i = 0; i <
height; i++)
2275 for (j = I[i]; j < I[i+1]; j++)
2277 out << i+1 <<
" " << J[j]+1 <<
" " << A[j] <<
'\n';
2279 out.precision(old_prec);
2285 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2291 for (i = 0; i <=
height; i++)
2293 out << I[i]+1 <<
'\n';
2296 for (i = 0; i < I[
height]; i++)
2298 out << J[i]+1 <<
'\n';
2301 for (i = 0; i < I[
height]; i++)
2303 out << A[i] <<
'\n';
2309 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2314 out <<
width <<
'\n';
2316 for (i = 0; i <=
height; i++)
2318 out << I[i] <<
'\n';
2321 for (i = 0; i < I[
height]; i++)
2323 out << J[i] <<
'\n';
2326 for (i = 0; i < I[
height]; i++)
2328 out << A[i] <<
'\n';
2332 void SparseMatrix::Destroy()
2334 if (I != NULL && ownGraph)
2338 if (J != NULL && ownGraph)
2342 if (A != NULL && ownData)
2349 #if !defined(MFEM_USE_MEMALLOC)
2350 for (
int i = 0; i <
height; i++)
2352 RowNode *aux, *node_p = Rows[i];
2353 while (node_p != NULL)
2356 node_p = node_p->Prev;
2364 if (ColPtrJ != NULL)
2368 if (ColPtrNode != NULL)
2370 delete [] ColPtrNode;
2372 #ifdef MFEM_USE_MEMALLOC
2373 if (NodesMem != NULL)
2386 int * end_j(J + I[height]);
2387 for (
int * jptr(start_j); jptr != end_j; ++jptr)
2389 awidth = (*jptr > awidth) ? *jptr : awidth;
2395 for (
int i = 0; i <
height; i++)
2396 for (aux = Rows[i]; aux != NULL; aux = aux->Prev)
2398 awidth =(aux->Column > awidth) ? aux->Column : awidth;
2412 for (
int i = 0; i < n; i++)
2422 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
2425 int m, n, nnz, *A_i, *A_j, *At_i, *At_j;
2426 double *A_data, *At_data;
2435 At_i =
new int[n+1];
2436 At_j =
new int[nnz];
2437 At_data =
new double[nnz];
2439 for (i = 0; i <= n; i++)
2443 for (i = 0; i < nnz; i++)
2447 for (i = 1; i < n; i++)
2449 At_i[i+1] += At_i[i];
2452 for (i = j = 0; i < m; i++)
2455 for ( ; j < end; j++)
2457 At_j[At_i[A_j[j]]] = i;
2458 At_data[At_i[A_j[j]]] = A_data[j];
2463 for (i = n; i > 0; i--)
2465 At_i[i] = At_i[i-1];
2476 int m, n, nnz, *At_i, *At_j;
2486 for (i = 0; i < m; i++)
2488 A.
GetRow(i, Acols, Avals);
2506 At_i =
new int[n+1];
2507 At_j =
new int[nnz];
2508 At_data =
new double[nnz];
2510 for (i = 0; i <= n; i++)
2515 for (i = 0; i < m; i++)
2517 A.
GetRow(i, Acols, Avals);
2518 for (j = 0; j<Acols.
Size(); ++j)
2523 for (i = 1; i < n; i++)
2525 At_i[i+1] += At_i[i];
2528 for (i = 0; i < m; i++)
2530 A.
GetRow(i, Acols, Avals);
2531 for (j = 0; j<Acols.
Size(); ++j)
2533 At_j[At_i[Acols[j]]] = i;
2534 At_data[At_i[Acols[j]]] = Avals[j];
2539 for (i = n; i > 0; i--)
2541 At_i[i] = At_i[i-1];
2552 int nrowsA, ncolsA, nrowsB, ncolsB;
2553 int *A_i, *A_j, *B_i, *B_j, *C_i, *C_j, *B_marker;
2554 double *A_data, *B_data, *C_data;
2555 int ia, ib, ic, ja, jb, num_nonzeros;
2556 int row_start, counter;
2557 double a_entry, b_entry;
2565 MFEM_VERIFY(ncolsA == nrowsB,
2566 "number of columns of A (" << ncolsA
2567 <<
") must equal number of rows of B (" << nrowsB <<
")");
2576 B_marker =
new int[ncolsB];
2578 for (ib = 0; ib < ncolsB; ib++)
2585 C_i =
new int[nrowsA+1];
2587 C_i[0] = num_nonzeros = 0;
2588 for (ic = 0; ic < nrowsA; ic++)
2590 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2593 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
2596 if (B_marker[jb] != ic)
2603 C_i[ic+1] = num_nonzeros;
2606 C_j =
new int[num_nonzeros];
2607 C_data =
new double[num_nonzeros];
2609 C =
new SparseMatrix (C_i, C_j, C_data, nrowsA, ncolsB);
2611 for (ib = 0; ib < ncolsB; ib++)
2620 MFEM_VERIFY(nrowsA == C -> Height() && ncolsB == C -> Width(),
2621 "Input matrix sizes do not match output sizes"
2622 <<
" nrowsA = " << nrowsA
2623 <<
", C->Height() = " << C->
Height()
2624 <<
" ncolsB = " << ncolsB
2625 <<
", C->Width() = " << C->
Width());
2629 C_data = C -> GetData();
2633 for (ic = 0; ic < nrowsA; ic++)
2636 row_start = counter;
2637 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2640 a_entry = A_data[ia];
2641 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
2644 b_entry = B_data[ib];
2645 if (B_marker[jb] < row_start)
2647 B_marker[jb] = counter;
2652 C_data[counter] = a_entry*b_entry;
2657 C_data[B_marker[jb]] += a_entry*b_entry;
2665 "With pre-allocated output matrix, number of non-zeros ("
2667 <<
") did not match number of entries changed from matrix-matrix multiply, "
2678 int nrowsA, ncolsA, nrowsB, ncolsB;
2679 int *C_i, *C_j, *B_marker;
2681 int ia, ib, ic, ja, jb, num_nonzeros;
2682 int row_start, counter;
2683 double a_entry, b_entry;
2691 MFEM_VERIFY(ncolsA == nrowsB,
2692 "number of columns of A (" << ncolsA
2693 <<
") must equal number of rows of B (" << nrowsB <<
")");
2695 B_marker =
new int[ncolsB];
2697 for (ib = 0; ib < ncolsB; ib++)
2702 C_i =
new int[nrowsA+1];
2704 C_i[0] = num_nonzeros = 0;
2708 for (ic = 0; ic < nrowsA; ic++)
2710 A.
GetRow(ic, colsA, dataA);
2711 for (ia = 0; ia < colsA.
Size(); ia++)
2714 B.
GetRow(ja, colsB, dataB);
2715 for (ib = 0; ib < colsB.
Size(); ib++)
2718 if (B_marker[jb] != ic)
2725 C_i[ic+1] = num_nonzeros;
2728 C_j =
new int[num_nonzeros];
2729 C_data =
new double[num_nonzeros];
2731 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
2733 for (ib = 0; ib < ncolsB; ib++)
2739 for (ic = 0; ic < nrowsA; ic++)
2741 row_start = counter;
2742 A.
GetRow(ic, colsA, dataA);
2743 for (ia = 0; ia < colsA.
Size(); ia++)
2746 a_entry = dataA[ia];
2747 B.
GetRow(ja, colsB, dataB);
2748 for (ib = 0; ib < colsB.
Size(); ib++)
2751 b_entry = dataB[ib];
2752 if (B_marker[jb] < row_start)
2754 B_marker[jb] = counter;
2756 C_data[counter] = a_entry*b_entry;
2761 C_data[B_marker[jb]] += a_entry*b_entry;
2797 int i, At_nnz, *At_j;
2801 At_nnz = At -> NumNonZeroElems();
2802 At_j = At -> GetJ();
2803 At_data = At -> GetData();
2804 for (i = 0; i < At_nnz; i++)
2806 At_data[i] *= D(At_j[i]);
2817 int ncols = A.
Width();
2819 int * C_i =
new int[nrows+1];
2823 int * A_i = A.
GetI();
2824 int * A_j = A.
GetJ();
2825 double * A_data = A.
GetData();
2827 int * B_i = B.
GetI();
2828 int * B_j = B.
GetJ();
2829 double * B_data = B.
GetData();
2831 int * marker =
new int[ncols];
2832 std::fill(marker, marker+ncols, -1);
2834 int num_nonzeros = 0, jcol;
2836 for (
int ic = 0; ic < nrows; ic++)
2838 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2844 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
2847 if (marker[jcol] != ic)
2853 C_i[ic+1] = num_nonzeros;
2856 C_j =
new int[num_nonzeros];
2857 C_data =
new double[num_nonzeros];
2859 for (
int ia = 0; ia < ncols; ia++)
2865 for (
int ic = 0; ic < nrows; ic++)
2867 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
2871 C_data[pos] = a*A_data[ia];
2875 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
2878 if (marker[jcol] < C_i[ic])
2881 C_data[pos] = b*B_data[ib];
2887 C_data[marker[jcol]] += b*B_data[ib];
2893 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
2898 return Add(1.,A,1.,B);
2903 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
2908 for (
int i=1; i < Ai.
Size(); ++i)
2910 result =
Add(*accumulate, *Ai[i]);
2916 accumulate = result;
2934 #ifdef MFEM_USE_MEMALLOC
double GetJacobiScaling() const
Determine appropriate scaling for Jacobi iteration.
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.
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)
void Clear()
Clear the contents of the SparseMatrix.
void Print(std::ostream &out=std::cout, int width_=4) const
Prints matrix to stream out.
void DiagScale(const Vector &b, Vector &x, double sc=1.0) const
void MakeRef(const SparseMatrix &master)
void SetSize(int s)
Resizes the vector if the new size is different.
double & SearchRow(const int col)
void PrintMM(std::ostream &out=std::cout) const
Prints matrix in Matrix Market sparse format.
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
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.
template void SortPairs< int, double >(Pair< int, double > *, int)
void EliminateRowCol(int rc, const double sol, Vector &rhs, int d=0)
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.
virtual int NumNonZeroElems() const =0
Returns the number of non-zeros in a matrix.
void EliminateRowColMultipleRHS(int rc, const Vector &sol, DenseMatrix &rhs, int d=0)
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.
void SortColumnIndices()
Sort the column indices corresponding to each row.
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)
void Add(const DenseMatrix &A, const DenseMatrix &B, double alpha, DenseMatrix &C)
C = A + alpha*B.
void EliminateCol(int col)
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
SparseMatrix()
Create an empty SparseMatrix.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows.
void EliminateCols(Array< int > &cols, Vector *x=NULL, Vector *b=NULL)
Eliminate all columns 'i' for which cols[i] != 0.
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
HypreParMatrix * RAP(HypreParMatrix *A, HypreParMatrix *P)
Returns the matrix P^t * A * P.
double IsSymmetric() const
Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix.
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)
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const =0
virtual void Finalize(int skip_zeros=1)
void EliminateZeroRows()
If a row contains only zeros, set its diagonal to 1.
double * GetData() const
Return element data.
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
int * GetI() const
Return the array I.
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
Returns a pointer to approximation of the matrix inverse.
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
SparseMatrix & operator=(double a)
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void mfem_error(const char *msg)
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 PrintMatlab(std::ostream &out=std::cout) const
Prints matrix in matlab format.
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.
void EliminateRow(int row, const double sol, Vector &rhs)
Eliminates a column from the transpose matrix.
void GetDiag(Vector &d) const
Returns the Diagonal of A.
double GetRowNorml1(int irow) const
For i = irow compute .
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.
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 GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm)
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
SparseMatrix & operator+=(SparseMatrix &B)
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 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)