15 #include "../general/forall.hpp"
16 #include "../general/table.hpp"
17 #include "../general/sort_pairs.hpp"
45 cusparseCreate(&handle);
52 Rows(new RowNode *[nrows]),
64 for (
int i = 0; i < nrows; i++)
69 #ifdef MFEM_USE_MEMALLOC
86 A.
Wrap(data,
I[height],
true);
88 #ifdef MFEM_USE_MEMALLOC
96 bool ownij,
bool owna,
bool issorted)
107 #ifdef MFEM_USE_MEMALLOC
113 A.
Wrap(data,
I[height], owna);
119 for (
int i=0; i<nnz; ++i)
136 #ifdef MFEM_USE_MEMALLOC
140 J.
New(nrows * rowsize);
141 A.
New(nrows * rowsize);
143 for (
int i = 0; i <= nrows; i++)
175 #ifdef MFEM_USE_MEMALLOC
181 #ifdef MFEM_USE_MEMALLOC
185 for (
int i = 0; i <
height; i++)
187 RowNode **node_pp = &
Rows[i];
188 for (RowNode *node_p = mat.
Rows[i]; node_p; node_p = node_p->Prev)
190 #ifdef MFEM_USE_MEMALLOC
193 RowNode *new_node_p =
new RowNode;
195 new_node_p->Value = node_p->Value;
196 new_node_p->Column = node_p->Column;
197 *node_pp = new_node_p;
198 node_pp = &new_node_p->Prev;
226 #ifdef MFEM_USE_MEMALLOC
233 for (
int i = 0; i <=
height; i++)
238 for (
int r=0; r<
height; r++)
259 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
280 #ifdef MFEM_USE_MEMALLOC
306 return I[gi+1]-
I[gi];
310 RowNode *row =
Rows[gi];
311 for ( ; row != NULL; row = row->Prev)
312 if (row->Value != 0.0)
325 for (
int i=0; i <
height; ++i)
327 rowSize =
I[i+1]-
I[i];
328 out = (out > rowSize) ? out : rowSize;
333 for (
int i=0; i <
height; ++i)
336 out = (out > rowSize) ? out : rowSize;
345 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
352 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
359 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
366 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
373 if (newWidth ==
width)
378 else if (newWidth == -1)
384 else if (newWidth >
width)
395 ColPtrJ =
static_cast<int *
>(NULL);
403 "The new width needs to be bigger or equal to the actual width");
411 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
419 for (
int j = 0, i = 0; i <
height; i++)
423 for (
int k = 0; k < row.
Size(); k++)
429 for (
int k = 0; k < row.
Size(); k++, j++)
440 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
442 for (
int row = 0, end = 0; row <
height; row++)
446 for (j = start;
true; j++)
448 MFEM_VERIFY(j < end,
"diagonal entry not found in row = " << row);
449 if (
J[j] == row) {
break; }
451 const double diag =
A[j];
452 for ( ; j > start; j--)
474 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
475 "Trying to access element outside of the matrix. "
476 <<
"height = " <<
height <<
", "
477 <<
"width = " <<
width <<
", "
478 <<
"i = " << i <<
", "
481 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
483 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
491 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
497 static const double zero = 0.0;
499 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
500 "Trying to access element outside of the matrix. "
501 <<
"height = " <<
height <<
", "
502 <<
"width = " <<
width <<
", "
503 <<
"i = " << i <<
", "
508 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
518 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
520 if (node_p->Column == j)
522 return node_p->Value;
532 MFEM_VERIFY(
height ==
width,
"Matrix must be square, not height = "
534 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
545 const int begin =
I[i];
546 const int end =
I[i+1];
548 for (j = begin; j < end; j++)
566 int num_rows = this->
Height();
567 int num_cols = this->
Width();
582 for (
int r=0; r<
height; r++)
587 for (
int cj=0; cj<this->
RowSize(r); cj++)
589 B(r, col[cj]) = val[cj];
603 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
604 <<
") must match matrix width (" <<
width <<
")");
605 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
606 <<
") must match matrix height (" <<
height <<
")");
614 for (
int i = 0; i <
height; i++)
616 RowNode *row =
Rows[i];
618 for ( ; row != NULL; row = row->Prev)
620 b += row->Value * xp[row->Column];
628 #ifndef MFEM_USE_LEGACY_OPENMP
631 auto d_I =
Read(
I, height+1);
632 auto d_J =
Read(
J, nnz);
633 auto d_A =
Read(
A, nnz);
638 if (nnz == 0) {
return;}
643 const double beta = 1.0;
650 const_cast<int *
>(d_I),
651 const_cast<int *>(d_J),
const_cast<double *
>(d_A), CUSPARSE_INDEX_32I,
652 CUSPARSE_INDEX_32I, CUSPARSE_INDEX_BASE_ZERO, CUDA_R_64F);
655 cusparseCreateDnVec(&
vecX_descr, x.
Size(),
const_cast<double *
>(d_x),
663 size_t newBufferSize = 0;
664 cusparseSpMV_bufferSize(
handle, CUSPARSE_OPERATION_NON_TRANSPOSE, &alpha,
667 CUSPARSE_CSRMV_ALG1, &newBufferSize);
678 cusparseDnVecSetValues(
vecX_descr, const_cast<double *>(d_x));
689 MFEM_FORALL(i, height,
692 const int end = d_I[i+1];
693 for (
int j = d_I[i]; j < end; j++)
695 d += d_A[j] * d_x[d_J[j]];
703 const double *Ap =
A, *xp = x.
GetData();
705 const int *Jp =
J, *Ip =
I;
707 #pragma omp parallel for
708 for (
int i = 0; i <
height; i++)
711 const int end = Ip[i+1];
712 for (
int j = Ip[i]; j < end; j++)
714 d += Ap[j] * xp[Jp[j]];
729 const double a)
const
732 <<
") must match matrix height (" <<
height <<
")");
733 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
734 <<
") must match matrix width (" <<
width <<
")");
740 for (
int i = 0; i <
height; i++)
742 RowNode *row =
Rows[i];
744 for ( ; row != NULL; row = row->Prev)
746 yp[row->Column] += row->Value *
b;
759 "enabled; see BuildTranspose() for details.");
760 for (
int i = 0; i <
height; i++)
762 const double xi = a * x[i];
763 const int end =
I[i+1];
764 for (
int j =
I[i]; j < end; j++)
790 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
792 const int n = rows.
Size();
794 auto d_rows = rows.
Read();
796 auto d_J =
Read(
J, nnz);
797 auto d_A =
Read(
A, nnz);
799 auto d_y = y.
Write();
802 const int r = d_rows[i];
803 const int end = d_I[r + 1];
805 for (
int j = d_I[r]; j < end; j++)
807 a += d_A[j] * d_x[d_J[j]];
816 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
818 for (
int i = 0; i < rows.
Size(); i++)
823 for (
int j =
I[r]; j < end; j++)
825 val +=
A[j] * x(
J[j]);
833 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
834 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
835 <<
") must match matrix width (" <<
Width() <<
")");
841 auto d_I =
Read(
I, height+1);
842 auto d_J =
Read(
J, nnz);
845 MFEM_FORALL(i, height,
848 const int end = d_I[i+1];
849 for (
int j = d_I[i]; j < end; j++)
864 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
865 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
866 <<
") must match matrix height (" <<
Height() <<
")");
871 for (
int i = 0; i <
Height(); i++)
876 for (
int j =
I[i]; j < end; j++)
886 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
887 <<
") must match matrix width (" <<
width <<
")");
888 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
889 <<
") must match matrix height (" <<
height <<
")");
900 for (
int i = 0; i <
height; i++)
902 RowNode *row =
Rows[i];
904 for ( ; row != NULL; row = row->Prev)
906 b += std::abs(row->Value) * xp[row->Column];
916 auto d_I =
Read(
I, height+1);
917 auto d_J =
Read(
J, nnz);
918 auto d_A =
Read(
A, nnz);
921 MFEM_FORALL(i, height,
924 const int end = d_I[i+1];
925 for (
int j = d_I[i]; j < end; j++)
927 d += std::abs(d_A[j]) * d_x[d_J[j]];
936 <<
") must match matrix height (" <<
height <<
")");
937 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
938 <<
") must match matrix width (" <<
width <<
")");
946 for (
int i = 0; i <
height; i++)
948 RowNode *row =
Rows[i];
950 for ( ; row != NULL; row = row->Prev)
952 yp[row->Column] += fabs(row->Value) *
b;
965 "enabled; see BuildTranspose() for details.");
966 for (
int i = 0; i <
height; i++)
968 const double xi = x[i];
969 const int end =
I[i+1];
970 for (
int j =
I[i]; j < end; j++)
973 y[Jj] += std::abs(
A[j]) * xi;
982 <<
" must be equal to Width() = " <<
Width());
984 <<
" must be equal to Height() = " <<
Height());
997 for (
int i = 0; i <
height; i++)
1002 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
1004 a +=
A[j] * x(
J[j]);
1009 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
1011 a += np->Value * x(np->Column);
1022 for (
int i = 0; i <
height; i++)
1027 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
1034 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
1045 MFEM_VERIFY(irow <
height,
1046 "row " << irow <<
" not in matrix with height " <<
height);
1051 for (
int j =
I[irow], end =
I[irow+1]; j < end; j++)
1058 for (RowNode *np =
Rows[irow]; np != NULL; np = np->Prev)
1060 a += fabs(np->Value);
1069 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
1071 atol = std::abs(tol);
1073 fix_empty_rows =
height ==
width ? fix_empty_rows :
false;
1081 for (i = 0, nz = 0; i <
height; i++)
1084 for (j =
I[i]; j <
I[i+1]; j++)
1085 if (std::abs(
A[j]) > atol)
1090 if (fix_empty_rows && !found) { nz++; }
1098 for (i = 0, nz = 0; i <
height; i++)
1102 for (j =
I[i]; j <
I[i+1]; j++)
1103 if (std::abs(
A[j]) > atol)
1108 if ( lastCol > newJ[nz] )
1115 if (fix_empty_rows && !found)
1123 I.
Wrap(newI, height+1,
true);
1124 J.
Wrap(newJ,
I[height],
true);
1125 A.
Wrap(newA,
I[height],
true);
1143 for (i = 1; i <=
height; i++)
1146 for (aux =
Rows[i-1]; aux != NULL; aux = aux->Prev)
1148 if (!skip_zeros || aux->Value != 0.0) { nr++; }
1150 if (fix_empty_rows && !nr) { nr = 1; }
1159 for (j = i = 0; i <
height; i++)
1163 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1165 if (!skip_zeros || aux->Value != 0.0)
1170 if ( lastCol >
J[j] )
1180 if (fix_empty_rows && !nr)
1188 #ifdef MFEM_USE_MEMALLOC
1192 for (i = 0; i <
height; i++)
1194 RowNode *node_p =
Rows[i];
1195 while (node_p != NULL)
1198 node_p = node_p->Prev;
1211 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
1213 for (
int j = 0; j < bc; j++)
1215 for (
int i = 0; i < br; i++)
1218 for (
int k = 0; k <= nr; k++)
1222 blocks(i,j) =
new SparseMatrix(bI, NULL, NULL, nr, nc);
1226 for (
int gr = 0; gr <
height; gr++)
1228 int bi = gr/nr, i = gr%nr + 1;
1231 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1235 blocks(bi,
J[j]/nc)->I[i]++;
1241 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1243 if (n_p->Value != 0.0)
1245 blocks(bi, n_p->Column/nc)->I[i]++;
1251 for (
int j = 0; j < bc; j++)
1253 for (
int i = 0; i < br; i++)
1257 for (
int k = 1; k <= nr; k++)
1259 rs = b.
I[k], b.
I[k] = nnz, nnz += rs;
1266 for (
int gr = 0; gr <
height; gr++)
1268 int bi = gr/nr, i = gr%nr + 1;
1271 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1276 b.
J[b.
I[i]] =
J[j] % nc;
1284 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1286 if (n_p->Value != 0.0)
1289 b.
J[b.
I[i]] = n_p->Column % nc;
1290 b.
A[b.
I[i]] = n_p->Value;
1312 for (
int i = 1; i <
height; i++)
1314 for (
int j =
I[i]; j <
I[i+1]; j++)
1318 symm = std::max(symm, std::abs(
A[j]-(*
this)(
J[j],i)));
1325 for (
int i = 0; i <
height; i++)
1327 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1329 int col = node_p->Column;
1332 symm = std::max(symm, std::abs(node_p->Value-(*
this)(col,i)));
1342 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1345 for (i = 1; i <
height; i++)
1347 for (j =
I[i]; j <
I[i+1]; j++)
1351 A[j] += (*this)(
J[j],i);
1353 (*this)(J[j],i) = A[j];
1369 for (
int i = 0; i <
height; i++)
1371 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1388 for (
int j = 0; j < nnz; j++)
1390 m = std::max(m, std::abs(
A[j]));
1395 for (
int i = 0; i <
height; i++)
1397 for (RowNode *n_p =
Rows[i]; n_p != NULL; n_p = n_p->Prev)
1399 m = std::max(m, std::abs(n_p->Value));
1413 const double *Ap =
A;
1415 for (
int i = 0; i < nz; i++)
1417 counter += (std::abs(Ap[i]) <= tol);
1422 for (
int i = 0; i <
height; i++)
1424 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1426 counter += (std::abs(aux->Value) <= tol);
1447 for (
int i = 0; i <
height; i++)
1449 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1467 MFEM_ASSERT(row < height && row >= 0,
1468 "Row " << row <<
" not in matrix of height " <<
height);
1470 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1472 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1474 rhs(aux->Column) -= sol * aux->Value;
1483 MFEM_ASSERT(row < height && row >= 0,
1484 "Row " << row <<
" not in matrix of height " <<
height);
1485 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1487 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1492 for (
int i=
I[row]; i <
I[row+1]; ++i)
1499 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1513 MFEM_ASSERT(col < width && col >= 0,
1514 "Col " << col <<
" not in matrix of width " <<
width);
1515 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1517 "if dpolicy == DIAG_ONE, matrix must be square, not height = "
1523 for (
int jpos = 0; jpos != nnz; ++jpos)
1533 for (
int i = 0; i <
height; i++)
1535 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1537 if (aux->Column == col)
1556 for (
int i = 0; i <
height; i++)
1558 for (
int jpos =
I[i]; jpos !=
I[i+1]; ++jpos)
1564 (*b)(i) -=
A[jpos] * (*x)(
J[jpos] );
1573 for (
int i = 0; i <
height; i++)
1575 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1577 if (cols[aux -> Column])
1581 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1595 for (
int row = 0; row <
height; row++)
1597 for (nd =
Rows[row]; nd != NULL; nd = nd->Prev)
1599 if (col_marker[nd->Column])
1601 Ae.
Add(row, nd->Column, nd->Value);
1609 for (
int row = 0; row <
height; row++)
1611 for (
int j =
I[row]; j <
I[row+1]; j++)
1613 if (col_marker[
J[j]])
1615 Ae.
Add(row,
J[j],
A[j]);
1627 MFEM_ASSERT(rc < height && rc >= 0,
1628 "Row " << rc <<
" not in matrix of height " <<
height);
1632 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1634 const int col =
J[j];
1640 rhs(rc) =
A[j] * sol;
1651 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1658 for (
int k = I[col]; 1; k++)
1662 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1664 else if (
J[k] == rc)
1666 rhs(col) -= sol *
A[k];
1676 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1678 const int col = aux->Column;
1684 rhs(rc) = aux->Value * sol;
1695 mfem_error(
"SparseMatrix::EliminateRowCol () #4");
1702 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1706 mfem_error(
"SparseMatrix::EliminateRowCol () #5");
1708 else if (node->Column == rc)
1710 rhs(col) -= sol * node->Value;
1724 MFEM_ASSERT(rc < height && rc >= 0,
1725 "Row " << rc <<
" not in matrix of height " <<
height);
1726 MFEM_ASSERT(sol.
Size() == rhs.
Width(),
"solution size (" << sol.
Size()
1727 <<
") must match rhs width (" << rhs.
Width() <<
")");
1729 const int num_rhs = rhs.
Width();
1732 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1734 const int col =
J[j];
1740 for (
int r = 0; r < num_rhs; r++)
1742 rhs(rc,r) =
A[j] * sol(r);
1747 for (
int r = 0; r < num_rhs; r++)
1754 for (
int r = 0; r < num_rhs; r++)
1760 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
1767 for (
int k = I[col]; 1; k++)
1771 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
1773 else if (
J[k] == rc)
1775 for (
int r = 0; r < num_rhs; r++)
1777 rhs(col,r) -= sol(r) *
A[k];
1788 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1790 const int col = aux->Column;
1796 for (
int r = 0; r < num_rhs; r++)
1798 rhs(rc,r) = aux->Value * sol(r);
1803 for (
int r = 0; r < num_rhs; r++)
1810 for (
int r = 0; r < num_rhs; r++)
1816 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #5");
1823 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1827 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #6");
1829 else if (node->Column == rc)
1831 for (
int r = 0; r < num_rhs; r++)
1833 rhs(col,r) -= sol(r) * node->Value;
1846 MFEM_ASSERT(rc < height && rc >= 0,
1847 "Row " << rc <<
" not in matrix of height " <<
height);
1851 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1853 const int col =
J[j];
1868 for (
int k = I[col]; 1; k++)
1872 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1874 else if (
J[k] == rc)
1885 RowNode *aux, *node;
1887 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1889 const int col = aux->Column;
1904 for (node =
Rows[col]; 1; node = node->Prev)
1908 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1910 else if (node->Column == rc)
1925 MFEM_ASSERT(rc < height && rc >= 0,
1926 "Row " << rc <<
" not in matrix of height " <<
height);
1930 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1932 const int col =
J[j];
1940 for (
int k = I[col]; 1; k++)
1944 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
1946 else if (
J[k] == rc)
1957 RowNode *aux, *node;
1959 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1961 const int col = aux->Column;
1969 for (node =
Rows[col]; 1; node = node->Prev)
1973 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
1975 else if (node->Column == rc)
1992 for (nd =
Rows[rc]; nd != NULL; nd = nd->Prev)
1994 const int col = nd->Column;
2000 Ae.
Add(rc, rc, nd->Value - 1.0);
2004 Ae.
Add(rc, rc, nd->Value);
2010 mfem_error(
"SparseMatrix::EliminateRowCol #1");
2016 Ae.
Add(rc, col, nd->Value);
2018 for (nd2 =
Rows[col]; 1; nd2 = nd2->Prev)
2022 mfem_error(
"SparseMatrix::EliminateRowCol #2");
2024 else if (nd2->Column == rc)
2026 Ae.
Add(col, rc, nd2->Value);
2036 for (
int j =
I[rc]; j <
I[rc+1]; j++)
2038 const int col =
J[j];
2044 Ae.
Add(rc, rc,
A[j] - 1.0);
2048 Ae.
Add(rc, rc,
A[j]);
2054 mfem_error(
"SparseMatrix::EliminateRowCol #3");
2060 Ae.
Add(rc, col,
A[j]);
2062 for (
int k = I[col];
true; k++)
2066 mfem_error(
"SparseMatrix::EliminateRowCol #4");
2068 else if (
J[k] == rc)
2070 Ae.
Add(col, rc,
A[k]);
2082 for (
int i = 0; i <
height; i++)
2084 if (
I[i+1] ==
I[i]+1 && fabs(
A[
I[i]]) < 1e-16)
2093 for (
int i = 0; i <
height; i++)
2096 for (
int j =
I[i]; j <
I[i+1]; j++)
2100 if (zero <= threshold)
2102 for (
int j = I[i]; j < I[i+1]; j++)
2104 A[j] = (
J[j] == i) ? 1.0 : 0.0;
2115 const double *xp = x.
GetData();
2116 RowNode *diag_p, *n_p, **R =
Rows;
2119 for (
int i = 0; i < s; i++)
2123 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
2125 const int c = n_p->Column;
2132 sum += n_p->Value * yp[c];
2136 if (diag_p != NULL && diag_p->Value != 0.0)
2138 yp[i] = (xp[i] - sum) / diag_p->Value;
2140 else if (xp[i] == sum)
2146 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
2160 for (
int i = 0, j = Ip[0]; i < s; i++)
2162 const int end = Ip[i+1];
2165 for ( ; j < end; j++)
2167 const int c = Jp[j];
2174 sum += Ap[j] * yp[c];
2178 if (d >= 0 && Ap[d] != 0.0)
2180 yp[i] = (xp[i] - sum) / Ap[d];
2182 else if (xp[i] == sum)
2188 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
2199 const double *xp = x.
GetData();
2200 RowNode *diag_p, *n_p, **R =
Rows;
2202 for (
int i =
height-1; i >= 0; i--)
2206 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
2208 const int c = n_p->Column;
2215 sum += n_p->Value * yp[c];
2219 if (diag_p != NULL && diag_p->Value != 0.0)
2221 yp[i] = (xp[i] - sum) / diag_p->Value;
2223 else if (xp[i] == sum)
2229 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
2243 for (
int i = s-1, j = Ip[s]-1; i >= 0; i--)
2245 const int beg = Ip[i];
2248 for ( ; j >= beg; j--)
2250 const int c = Jp[j];
2257 sum += Ap[j] * yp[c];
2261 if (d >= 0 && Ap[d] != 0.0)
2263 yp[i] = (xp[i] - sum) / Ap[d];
2265 else if (xp[i] == sum)
2271 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
2279 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2282 for (
int i = 0; i <
height; i++)
2286 for (
int j =
I[i]; j <
I[i+1]; j++)
2294 if (d >= 0 &&
A[d] != 0.0)
2296 double a = 1.8 * fabs(
A[d]) / norm;
2304 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
2313 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2315 for (
int i = 0; i <
height; i++)
2319 for (
int j =
I[i]; j <
I[i+1]; j++)
2327 sum -=
A[j] * x0(
J[j]);
2330 if (d >= 0 &&
A[d] != 0.0)
2332 x1(i) = sc * (sum /
A[d]) + (1.0 - sc) * x0(i);
2343 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2349 auto bp = b.
Read(use_dev);
2350 auto xp = x.
Write(use_dev);
2352 auto Ap =
Read(
A, nnz);
2354 auto Jp =
Read(
J, nnz);
2356 bool scale = (sc != 1.0);
2360 for (
int j = Ip[i];
true; j++)
2364 MFEM_ABORT_KERNEL(
"Diagonal not found in SparseMatrix::DiagScale");
2368 if (!(std::abs(Ap[j]) > 0.0))
2370 MFEM_ABORT_KERNEL(
"Zero diagonal in SparseMatrix::DiagScale");
2375 xp[i] = sc * bp[i] / Ap[j];
2379 xp[i] = bp[i] / Ap[j];
2391 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2393 for (
int i = 0; i <
height; i++)
2395 double resi =
b(i), norm = 0.0;
2396 for (
int j =
I[i]; j <
I[i+1]; j++)
2398 resi -=
A[j] * x0(
J[j]);
2403 x1(i) = x0(i) + sc * resi / norm;
2407 MFEM_ABORT(
"L1 norm of row " << i <<
" is zero.");
2415 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2417 for (
int i = 0; i <
height; i++)
2419 double resi =
b(i), sum = 0.0;
2420 for (
int j =
I[i]; j <
I[i+1]; j++)
2422 resi -=
A[j] * x0(
J[j]);
2427 x1(i) = x0(i) + sc * resi / sum;
2431 MFEM_ABORT(
"sum of row " << i <<
" is zero.");
2439 int i, j, gi, gj, s, t;
2442 for (i = 0; i < rows.
Size(); i++)
2444 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2447 "Trying to insert a row " << gi <<
" outside the matrix height "
2450 for (j = 0; j < cols.
Size(); j++)
2452 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2454 MFEM_ASSERT(gj <
width,
2455 "Trying to insert a column " << gj <<
" outside the matrix width "
2458 if (skip_zeros && a == 0.0)
2462 if (&rows != &cols || subm(j, i) == 0.0)
2467 if (t < 0) { a = -
a; }
2479 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2482 "Trying to set a row " << gi <<
" outside the matrix height "
2484 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2486 MFEM_ASSERT(gj <
width,
2487 "Trying to set a column " << gj <<
" outside the matrix width "
2489 if (t < 0) { a = -
a; }
2498 if ((gi=i) < 0) { gi = -1-gi, s = -1; }
2501 "Trying to insert a row " << gi <<
" outside the matrix height "
2503 if ((gj=j) < 0) { gj = -1-gj, t = -s; }
2505 MFEM_ASSERT(gj <
width,
2506 "Trying to insert a column " << gj <<
" outside the matrix width "
2508 if (t < 0) { a = -
a; }
2515 int i, j, gi, gj, s, t;
2518 for (i = 0; i < rows.
Size(); i++)
2520 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2523 "Trying to set a row " << gi <<
" outside the matrix height "
2526 for (j = 0; j < cols.
Size(); j++)
2529 if (skip_zeros && a == 0.0)
2533 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2535 MFEM_ASSERT(gj <
width,
2536 "Trying to set a column " << gj <<
" outside the matrix width "
2538 if (t < 0) { a = -
a; }
2550 int i, j, gi, gj, s, t;
2553 for (i = 0; i < rows.
Size(); i++)
2555 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2558 "Trying to set a row " << gi <<
" outside the matrix height "
2561 for (j = 0; j < cols.
Size(); j++)
2564 if (skip_zeros && a == 0.0)
2568 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2570 MFEM_ASSERT(gj <
width,
2571 "Trying to set a column " << gj <<
" outside the matrix width "
2573 if (t < 0) { a = -
a; }
2583 int i, j, gi, gj, s, t;
2586 for (i = 0; i < rows.
Size(); i++)
2588 if ((gi=rows[i]) < 0) { gi = -1-gi, s = -1; }
2591 "Trying to read a row " << gi <<
" outside the matrix height "
2594 for (j = 0; j < cols.
Size(); j++)
2596 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2598 MFEM_ASSERT(gj <
width,
2599 "Trying to read a column " << gj <<
" outside the matrix width "
2602 subm(i, j) = (t < 0) ? (-a) : (
a);
2617 "Trying to query a row " << gi <<
" outside the matrix height "
2621 return (
Rows[gi] == NULL);
2625 return (
I[gi] ==
I[gi+1]);
2634 if ((gi=row) < 0) { gi = -1-gi; }
2636 "Trying to read a row " << gi <<
" outside the matrix height "
2640 for (n =
Rows[gi], j = 0; n; n = n->Prev)
2646 for (n =
Rows[gi], j = 0; n; n = n->Prev, j++)
2648 cols[j] = n->Column;
2661 cols.
MakeRef(const_cast<int*>((
const int*)
J) + j,
I[gi+1]-j);
2663 const_cast<double*>((
const double*)
A) + j, cols.
Size());
2664 MFEM_ASSERT(row >= 0,
"Row not valid: " << row <<
", height: " <<
height);
2675 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2678 "Trying to set a row " << gi <<
" outside the matrix height "
2684 for (
int j = 0; j < cols.
Size(); j++)
2686 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2688 MFEM_ASSERT(gj <
width,
2689 "Trying to set a column " << gj <<
" outside the matrix"
2690 " width " <<
width);
2692 if (t < 0) { a = -
a; }
2700 MFEM_ASSERT(cols.
Size() == srow.
Size(),
"");
2702 for (
int i =
I[gi], j = 0; j < cols.
Size(); j++, i++)
2704 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2706 MFEM_ASSERT(gj <
width,
2707 "Trying to set a column " << gj <<
" outside the matrix"
2708 " width " <<
width);
2719 int j, gi, gj, s, t;
2722 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
2724 if ((gi=row) < 0) { gi = -1-gi, s = -1; }
2727 "Trying to insert a row " << gi <<
" outside the matrix height "
2730 for (j = 0; j < cols.
Size(); j++)
2732 if ((gj=cols[j]) < 0) { gj = -1-gj, t = -s; }
2734 MFEM_ASSERT(gj <
width,
2735 "Trying to insert a column " << gj <<
" outside the matrix width "
2742 if (t < 0) { a = -
a; }
2760 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2762 aux -> Value *= scale;
2767 int j, end =
I[i+1];
2769 for (j =
I[i]; j < end; j++)
2782 for (
int i=0; i <
height; ++i)
2785 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2787 aux -> Value *= scale;
2795 for (
int i=0; i <
height; ++i)
2799 for (j =
I[i]; j < end; j++)
2812 for (
int i=0; i <
height; ++i)
2814 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
2816 aux -> Value *= sr(aux->Column);
2824 for (
int i=0; i <
height; ++i)
2827 for (j =
I[i]; j < end; j++)
2838 "Mismatch of this matrix size and rhs. This height = "
2839 <<
height <<
", width = " <<
width <<
", B.height = "
2842 for (
int i = 0; i <
height; i++)
2847 for (RowNode *aux = B.
Rows[i]; aux != NULL; aux = aux->Prev)
2849 _Add_(aux->Column, aux->Value);
2854 for (
int j = B.
I[i]; j < B.
I[i+1]; j++)
2867 for (
int i = 0; i <
height; i++)
2872 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
2874 np->Value += a * B.
_Get_(np->Column);
2879 for (
int j =
I[i]; j <
I[i+1]; j++)
2894 for (
int i = 0; i < nnz; i++)
2901 for (
int i = 0; i <
height; i++)
2903 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2904 node_p = node_p -> Prev)
2906 node_p -> Value =
a;
2918 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
2925 for (
int i = 0; i <
height; i++)
2927 for (RowNode *node_p =
Rows[i]; node_p != NULL;
2928 node_p = node_p -> Prev)
2930 node_p -> Value *=
a;
2945 for (i = 0; i <
height; i++)
2947 out <<
"[row " << i <<
"]\n";
2948 for (nd =
Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
2950 out <<
" (" << nd->Column <<
"," << nd->Value <<
")";
2951 if ( !((j+1) % _width) )
2968 for (i = 0; i <
height; i++)
2970 out <<
"[row " << i <<
"]\n";
2971 for (j =
I[i]; j <
I[i+1]; j++)
2973 out <<
" (" <<
J[j] <<
"," <<
A[j] <<
")";
2974 if ( !((j+1-I[i]) % _width) )
2979 if ((j-I[i]) % _width)
2988 out <<
"% size " <<
height <<
" " <<
width <<
"\n";
2991 ios::fmtflags old_fmt = out.flags();
2992 out.setf(ios::scientific);
2993 std::streamsize old_prec = out.precision(14);
2995 for (i = 0; i <
height; i++)
2997 for (j =
I[i]; j <
I[i+1]; j++)
2999 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
3002 out.precision(old_prec);
3009 ios::fmtflags old_fmt = out.flags();
3010 out.setf(ios::scientific);
3011 std::streamsize old_prec = out.precision(14);
3013 out <<
"%%MatrixMarket matrix coordinate real general" <<
'\n'
3014 <<
"% Generated by MFEM" <<
'\n';
3017 for (i = 0; i <
height; i++)
3019 for (j =
I[i]; j <
I[i+1]; j++)
3021 out << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
3024 out.precision(old_prec);
3030 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
3036 for (i = 0; i <=
height; i++)
3038 out <<
I[i]+1 <<
'\n';
3041 for (i = 0; i <
I[
height]; i++)
3043 out <<
J[i]+1 <<
'\n';
3046 for (i = 0; i < I[
height]; i++)
3048 out <<
A[i] <<
'\n';
3054 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
3059 out <<
width <<
'\n';
3061 for (i = 0; i <=
height; i++)
3063 out <<
I[i] <<
'\n';
3066 for (i = 0; i <
I[
height]; i++)
3068 out <<
J[i] <<
'\n';
3071 for (i = 0; i < I[
height]; i++)
3073 out <<
A[i] <<
'\n';
3079 const double MiB = 1024.*1024;
3081 double pz = 100./nnz;
3091 "SparseMatrix statistics:\n"
3094 " Dimensions : " <<
height <<
" x " <<
width <<
"\n"
3095 " Number of entries (total) : " << nnz <<
"\n"
3096 " Number of entries (per row) : " << 1.*nnz/
Height() <<
"\n"
3097 " Number of stored zeros : " << nz*pz <<
"% (" << nz <<
")\n"
3098 " Number of Inf/Nan entries : " << nnf*pz <<
"% ("<< nnf <<
")\n"
3099 " Norm, max |a_ij| : " << max_norm <<
"\n"
3100 " Symmetry, max |a_ij-a_ji| : " << symm <<
"\n"
3101 " Number of small entries:\n"
3102 " |a_ij| <= 1e-12*Norm : " << ns12*pz <<
"% (" << ns12 <<
")\n"
3103 " |a_ij| <= 1e-15*Norm : " << ns15*pz <<
"% (" << ns15 <<
")\n"
3104 " |a_ij| <= 1e-18*Norm : " << ns18*pz <<
"% (" << ns18 <<
")\n";
3107 out <<
" Memory used by CSR : " <<
3108 (
sizeof(int)*(
height+1+nnz)+
sizeof(double)*nnz)/MiB <<
" MiB\n";
3112 size_t used_mem =
sizeof(RowNode*)*
height;
3113 #ifdef MFEM_USE_MEMALLOC
3116 for (
int i = 0; i <
height; i++)
3118 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
3120 used_mem +=
sizeof(RowNode);
3124 out <<
" Memory used by LIL : " << used_mem/MiB <<
" MiB\n";
3136 #if !defined(MFEM_USE_MEMALLOC)
3137 for (
int i = 0; i <
height; i++)
3139 RowNode *aux, *node_p =
Rows[i];
3140 while (node_p != NULL)
3143 node_p = node_p->Prev;
3153 #ifdef MFEM_USE_MEMALLOC
3158 #ifdef MFEM_USE_CUDA
3174 const int *start_j =
J;
3176 for (
const int *jptr = start_j; jptr != end_j; ++jptr)
3178 awidth = std::max(awidth, *jptr + 1);
3184 for (
int i = 0; i <
height; i++)
3186 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
3188 awidth = std::max(awidth, aux->Column + 1);
3200 for (
int i = 0; i < n; i++)
3210 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
3213 const int *A_i, *A_j;
3214 int m, n, nnz, *At_i, *At_j;
3215 const double *A_data;
3229 for (i = 0; i <= n; i++)
3233 for (i = 0; i < nnz; i++)
3237 for (i = 1; i < n; i++)
3239 At_i[i+1] += At_i[i];
3242 for (i = j = 0; i < m; i++)
3245 for ( ; j < end; j++)
3247 At_j[At_i[A_j[j]]] = i;
3248 At_data[At_i[A_j[j]]] = A_data[j];
3253 for (i = n; i > 0; i--)
3255 At_i[i] = At_i[i-1];
3266 int m, n, nnz, *At_i, *At_j;
3276 for (i = 0; i < m; i++)
3278 A.
GetRow(i, Acols, Avals);
3300 for (i = 0; i <= n; i++)
3305 for (i = 0; i < m; i++)
3307 A.
GetRow(i, Acols, Avals);
3308 for (j = 0; j<Acols.
Size(); ++j)
3313 for (i = 1; i < n; i++)
3315 At_i[i+1] += At_i[i];
3318 for (i = 0; i < m; i++)
3320 A.
GetRow(i, Acols, Avals);
3321 for (j = 0; j<Acols.
Size(); ++j)
3323 At_j[At_i[Acols[j]]] = i;
3324 At_data[At_i[Acols[j]]] = Avals[j];
3329 for (i = n; i > 0; i--)
3331 At_i[i] = At_i[i-1];
3342 int nrowsA, ncolsA, nrowsB, ncolsB;
3343 const int *A_i, *A_j, *B_i, *B_j;
3344 int *C_i, *C_j, *B_marker;
3345 const double *A_data, *B_data;
3347 int ia, ib, ic, ja, jb, num_nonzeros;
3348 int row_start, counter;
3349 double a_entry, b_entry;
3357 MFEM_VERIFY(ncolsA == nrowsB,
3358 "number of columns of A (" << ncolsA
3359 <<
") must equal number of rows of B (" << nrowsB <<
")");
3368 B_marker =
new int[ncolsB];
3370 for (ib = 0; ib < ncolsB; ib++)
3379 C_i[0] = num_nonzeros = 0;
3380 for (ic = 0; ic < nrowsA; ic++)
3382 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3385 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3388 if (B_marker[jb] != ic)
3395 C_i[ic+1] = num_nonzeros;
3401 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3403 for (ib = 0; ib < ncolsB; ib++)
3412 MFEM_VERIFY(nrowsA == C -> Height() && ncolsB == C -> Width(),
3413 "Input matrix sizes do not match output sizes"
3414 <<
" nrowsA = " << nrowsA
3415 <<
", C->Height() = " << C->
Height()
3416 <<
" ncolsB = " << ncolsB
3417 <<
", C->Width() = " << C->
Width());
3421 C_data = C -> GetData();
3425 for (ic = 0; ic < nrowsA; ic++)
3428 row_start = counter;
3429 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3432 a_entry = A_data[ia];
3433 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3436 b_entry = B_data[ib];
3437 if (B_marker[jb] < row_start)
3439 B_marker[jb] = counter;
3444 C_data[counter] = a_entry*b_entry;
3449 C_data[B_marker[jb]] += a_entry*b_entry;
3457 "With pre-allocated output matrix, number of non-zeros ("
3459 <<
") did not match number of entries changed from matrix-matrix multiply, "
3478 int nrowsA, ncolsA, nrowsB, ncolsB;
3479 int *C_i, *C_j, *B_marker;
3481 int ia, ib, ic, ja, jb, num_nonzeros;
3482 int row_start, counter;
3483 double a_entry, b_entry;
3491 MFEM_VERIFY(ncolsA == nrowsB,
3492 "number of columns of A (" << ncolsA
3493 <<
") must equal number of rows of B (" << nrowsB <<
")");
3495 B_marker =
new int[ncolsB];
3497 for (ib = 0; ib < ncolsB; ib++)
3504 C_i[0] = num_nonzeros = 0;
3508 for (ic = 0; ic < nrowsA; ic++)
3510 A.
GetRow(ic, colsA, dataA);
3511 for (ia = 0; ia < colsA.
Size(); ia++)
3514 B.
GetRow(ja, colsB, dataB);
3515 for (ib = 0; ib < colsB.
Size(); ib++)
3518 if (B_marker[jb] != ic)
3525 C_i[ic+1] = num_nonzeros;
3531 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3533 for (ib = 0; ib < ncolsB; ib++)
3539 for (ic = 0; ic < nrowsA; ic++)
3541 row_start = counter;
3542 A.
GetRow(ic, colsA, dataA);
3543 for (ia = 0; ia < colsA.
Size(); ia++)
3546 a_entry = dataA[ia];
3547 B.
GetRow(ja, colsB, dataB);
3548 for (ib = 0; ib < colsB.
Size(); ib++)
3551 b_entry = dataB[ib];
3552 if (B_marker[jb] < row_start)
3554 B_marker[jb] = counter;
3556 C_data[counter] = a_entry*b_entry;
3561 C_data[B_marker[jb]] += a_entry*b_entry;
3576 for (
int j = 0; j < B.
Width(); ++j)
3580 A.
Mult(columnB, columnC);
3590 Mult (R, *AP, *_RAP);
3633 int i, At_nnz, *At_j;
3637 At_nnz = At -> NumNonZeroElems();
3638 At_j = At -> GetJ();
3639 At_data = At -> GetData();
3640 for (i = 0; i < At_nnz; i++)
3642 At_data[i] *= D(At_j[i]);
3653 int ncols = A.
Width();
3659 const int *A_i = A.
GetI();
3660 const int *A_j = A.
GetJ();
3661 const double *A_data = A.
GetData();
3663 const int *B_i = B.
GetI();
3664 const int *B_j = B.
GetJ();
3665 const double *B_data = B.
GetData();
3667 int * marker =
new int[ncols];
3668 std::fill(marker, marker+ncols, -1);
3670 int num_nonzeros = 0, jcol;
3672 for (
int ic = 0; ic < nrows; ic++)
3674 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3680 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3683 if (marker[jcol] != ic)
3689 C_i[ic+1] = num_nonzeros;
3695 for (
int ia = 0; ia < ncols; ia++)
3701 for (
int ic = 0; ic < nrows; ic++)
3703 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3707 C_data[pos] = a*A_data[ia];
3711 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3714 if (marker[jcol] < C_i[ic])
3717 C_data[pos] = b*B_data[ib];
3723 C_data[marker[jcol]] += b*B_data[ib];
3729 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
3734 return Add(1.,A,1.,B);
3739 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
3744 for (
int i=1; i < Ai.
Size(); ++i)
3746 result =
Add(*accumulate, *Ai[i]);
3752 accumulate = result;
3762 for (
int r = 0; r < B.
Height(); r++)
3766 for (
int i=0; i<A.
RowSize(r); i++)
3768 B(r, colA[i]) += alpha * valA[i];
3781 for (
int i=0; i<mA; i++)
3783 for (
int j=0; j<nA; j++)
3785 C->
AddMatrix(A(i,j), B, i * mB, j * nB);
3799 for (
int i=0; i<mA; i++)
3801 for (
int j=0; j<nA; j++)
3803 for (
int r=0; r<mB; r++)
3808 for (
int cj=0; cj<B.
RowSize(r); cj++)
3810 C->
Set(i * mB + r, j * nB + colB[cj], A(i,j) * valB[cj]);
3828 for (
int r=0; r<mA; r++)
3833 for (
int aj=0; aj<A.
RowSize(r); aj++)
3835 for (
int i=0; i<mB; i++)
3837 for (
int j=0; j<nB; j++)
3839 C->
Set(r * mB + i, colA[aj] * nB + j, valA[aj] * B(i, j));
3857 for (
int ar=0; ar<mA; ar++)
3862 for (
int aj=0; aj<A.
RowSize(ar); aj++)
3864 for (
int br=0; br<mB; br++)
3869 for (
int bj=0; bj<B.
RowSize(br); bj++)
3871 C->
Set(ar * mB + br, colA[aj] * nB + colB[bj],
3872 valA[aj] * valB[bj]);
3895 #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
Return the 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 * CuMemFree(void *dptr)
Frees device memory and returns destination ptr.
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.
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().
const double * ReadData(bool on_dev=true) const
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.
cusparseDnVecDescr_t vecY_descr
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
const int * ReadJ(bool on_dev=true) 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.
const double * HostReadData() const
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.
const int * HostReadJ() const
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
static int SparseMatrixCount
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;
static cusparseHandle_t handle
DenseMatrix * OuterProduct(const DenseMatrix &A, const DenseMatrix &B)
Produces a block matrix with blocks A_{ij}*B.
void Sort()
Sorts the array in ascending order. 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.
Set the diagonal value to one.
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.
Biwise-OR of all CUDA backends.
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
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 the 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
const int * ReadI(bool on_dev=true) const
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
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.
void AbsMultTranspose(const Vector &x, Vector &y) const
y = |At| * x, using entry-wise absolute values of the transpose of matrix A
DiagonalPolicy
Defines operator diagonal policy upon elimination of rows and/or columns.
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)
cusparseSpMatDescr_t matA_descr
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.
const int * HostReadI() const
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
cusparseDnVecDescr_t vecX_descr
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.
void AbsMult(const Vector &x, Vector &y) const
y = |A| * x, using entry-wise absolute values of matrix A
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.
void * CuMemAlloc(void **dptr, size_t bytes)
Allocates device memory and returns destination ptr.
Set the diagonal value to zero.
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 .
double f(const Vector &p)
void Neg()
(*this) = -(*this)