15 #include "../general/forall.hpp" 16 #include "../general/table.hpp" 17 #include "../general/sort_pairs.hpp" 18 #include "../general/backends.hpp" 27 #if defined(MFEM_USE_CUDA) 28 #define MFEM_cu_or_hip(stub) cu##stub 29 #define MFEM_Cu_or_Hip(stub) Cu##stub 30 #define MFEM_CU_or_HIP(stub) CU##stub 31 #define MFEM_CUDA_or_HIP(stub) CUDA##stub 33 #if CUSPARSE_VERSION >= 11400 34 #define MFEM_GPUSPARSE_ALG CUSPARSE_SPMV_CSR_ALG1 35 #else // CUSPARSE_VERSION >= 11400 36 #define MFEM_GPUSPARSE_ALG CUSPARSE_CSRMV_ALG1 37 #endif // CUSPARSE_VERSION >= 11400 39 #elif defined(MFEM_USE_HIP) 40 #define MFEM_cu_or_hip(stub) hip##stub 41 #define MFEM_Cu_or_Hip(stub) Hip##stub 42 #define MFEM_CU_or_HIP(stub) HIP##stub 43 #define MFEM_CUDA_or_HIP(stub) HIP##stub 46 #define MFEM_GPUSPARSE_ALG HIPSPARSE_CSRMV_ALG1 47 #endif // defined(MFEM_USE_CUDA) 54 #ifdef MFEM_USE_CUDA_OR_HIP 62 #endif // MFEM_USE_CUDA_OR_HIP 67 #ifdef MFEM_USE_CUDA_OR_HIP 70 if (!handle) { MFEM_cu_or_hip(sparseCreate)(&handle); }
78 #endif // MFEM_USE_CUDA_OR_HIP 83 #ifdef MFEM_USE_CUDA_OR_HIP 86 #if CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 87 MFEM_cu_or_hip(sparseDestroySpMat)(matA_descr);
88 MFEM_cu_or_hip(sparseDestroyDnVec)(vecX_descr);
89 MFEM_cu_or_hip(sparseDestroyDnVec)(vecY_descr);
91 cusparseDestroyMatDescr(matA_descr);
92 #endif // CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 95 #endif // MFEM_USE_CUDA_OR_HIP 100 Rows(new RowNode *[nrows]),
112 for (
int i = 0; i < nrows; i++)
117 #ifdef MFEM_USE_MEMALLOC 136 #ifdef MFEM_USE_MEMALLOC 144 bool ownij,
bool owna,
bool issorted)
155 #ifdef MFEM_USE_MEMALLOC 167 for (
int ii=0; ii<nnz; ++ii)
184 #ifdef MFEM_USE_MEMALLOC 188 J.
New(nrows * rowsize);
189 A.
New(nrows * rowsize);
191 for (
int i = 0; i <= nrows; i++)
225 #ifdef MFEM_USE_MEMALLOC 231 #ifdef MFEM_USE_MEMALLOC 235 for (
int i = 0; i <
height; i++)
237 RowNode **node_pp = &
Rows[i];
238 for (RowNode *node_p = mat.
Rows[i]; node_p; node_p = node_p->Prev)
240 #ifdef MFEM_USE_MEMALLOC 243 RowNode *new_node_p =
new RowNode;
245 new_node_p->Value = node_p->Value;
246 new_node_p->Column = node_p->Column;
247 *node_pp = new_node_p;
248 node_pp = &new_node_p->Prev;
276 #ifdef MFEM_USE_MEMALLOC 283 for (
int i = 0; i <=
height; i++)
288 for (
int r=0; r<
height; r++)
315 MFEM_ASSERT(master.
Finalized(),
"'master' must be finalized");
336 #ifdef MFEM_USE_MEMALLOC 354 return I[gi+1]-
I[gi];
358 RowNode *row =
Rows[gi];
359 for ( ; row != NULL; row = row->Prev)
360 if (row->Value != 0.0)
373 for (
int i=0; i <
height; ++i)
375 rowSize =
I[i+1]-
I[i];
376 max_row_size = (max_row_size > rowSize) ? max_row_size : rowSize;
381 for (
int i=0; i <
height; ++i)
384 max_row_size = (max_row_size > rowSize) ? max_row_size : rowSize;
393 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
400 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
407 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
414 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
421 if (newWidth ==
width)
426 else if (newWidth == -1)
432 else if (newWidth >
width)
443 ColPtrJ =
static_cast<int *
>(NULL);
451 "The new width needs to be bigger or equal to the actual width");
459 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
466 #ifdef MFEM_USE_CUDA_OR_HIP 469 #if defined(MFEM_USE_CUDA) 470 size_t pBufferSizeInBytes = 0;
471 void *pBuffer = NULL;
474 const int m =
Width();
477 const int * d_ia =
ReadI();
479 csru2csrInfo_t sortInfoA;
483 cusparseSetMatIndexBase(
matA_descr, CUSPARSE_INDEX_BASE_ZERO );
484 cusparseSetMatType(
matA_descr, CUSPARSE_MATRIX_TYPE_GENERAL );
486 cusparseCreateCsru2csrInfo( &sortInfoA );
488 cusparseDcsru2csr_bufferSizeExt(
handle, n, m, nnzA, d_a_sorted, d_ia,
489 d_ja_sorted, sortInfoA,
490 &pBufferSizeInBytes);
495 d_ja_sorted, sortInfoA, pBuffer);
501 cusparseDestroyCsru2csrInfo( sortInfoA );
509 #if defined(MFEM_USE_HIP) 510 size_t pBufferSizeInBytes = 0;
511 void *pBuffer = NULL;
515 const int m =
Width();
518 const int * d_ia =
ReadI();
521 hipsparseMatDescr_t descrA;
522 hipsparseCreateMatDescr( &descrA );
528 double *d_a_tmp = a_tmp.
Write();
530 hipsparseXcsrsort_bufferSizeExt(
handle, n, m, nnzA, d_ia, d_ja_sorted,
531 &pBufferSizeInBytes);
536 hipsparseCreateIdentityPermutation(
handle, nnzA, P);
537 hipsparseXcsrsort(
handle, n, m, nnzA, descrA, d_ia, d_ja_sorted, P, pBuffer);
539 hipsparseDgthr(
handle, nnzA, d_a_sorted, d_a_tmp, P,
540 HIPSPARSE_INDEX_BASE_ZERO);
543 hipsparseDestroyMatDescr( descrA );
550 #endif // MFEM_USE_CUDA_OR_HIP 557 for (
int j = 0, i = 0; i <
height; i++)
561 for (
int k = 0; k < row.
Size(); k++)
567 for (
int k = 0; k < row.
Size(); k++, j++)
579 MFEM_VERIFY(
Finalized(),
"Matrix is not Finalized!");
581 for (
int row = 0, end = 0; row <
height; row++)
585 for (j = start;
true; j++)
587 MFEM_VERIFY(j < end,
"diagonal entry not found in row = " << row);
588 if (
J[j] == row) {
break; }
590 const double diag =
A[j];
591 for ( ; j > start; j--)
613 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
614 "Trying to access element outside of the matrix. " 615 <<
"height = " <<
height <<
", " 616 <<
"width = " <<
width <<
", " 617 <<
"i = " << i <<
", " 620 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
622 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
630 MFEM_ABORT(
"Did not find i = " << i <<
", j = " << j <<
" in matrix.");
636 static const double zero = 0.0;
638 MFEM_ASSERT(i < height && i >= 0 && j < width && j >= 0,
639 "Trying to access element outside of the matrix. " 640 <<
"height = " <<
height <<
", " 641 <<
"width = " <<
width <<
", " 642 <<
"i = " << i <<
", " 647 for (
int k =
I[i], end =
I[i+1]; k < end; k++)
657 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
659 if (node_p->Column == j)
661 return node_p->Value;
671 MFEM_VERIFY(
height ==
width,
"Matrix must be square, not height = " 673 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
677 const auto II = this->
ReadI();
678 const auto JJ = this->
ReadJ();
684 const int begin = II[i];
685 const int end = II[i+1];
687 for (j = begin; j < end; j++)
705 int num_rows = this->
Height();
706 int num_cols = this->
Width();
721 for (
int r=0; r<
height; r++)
726 for (
int cj=0; cj<this->
RowSize(r); cj++)
728 B(r, col[cj]) = val[cj];
742 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
743 <<
") must match matrix width (" <<
width <<
")");
744 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
745 <<
") must match matrix height (" <<
height <<
")");
753 for (
int i = 0; i <
height; i++)
755 RowNode *row =
Rows[i];
757 for ( ; row != NULL; row = row->Prev)
759 b += row->Value * xp[row->Column];
767 #ifndef MFEM_USE_LEGACY_OPENMP 771 auto d_J =
Read(
J, nnz);
772 auto d_A =
Read(
A, nnz);
777 if (nnz == 0) {
return;}
780 #ifdef MFEM_USE_CUDA_OR_HIP 782 const double beta = 1.0;
787 #if CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 789 MFEM_cu_or_hip(sparseCreateCsr)(
793 const_cast<int *
>(d_I),
794 const_cast<int *>(d_J),
795 const_cast<double *
>(d_A),
796 MFEM_CU_or_HIP(SPARSE_INDEX_32I),
797 MFEM_CU_or_HIP(SPARSE_INDEX_32I),
798 MFEM_CU_or_HIP(SPARSE_INDEX_BASE_ZERO),
799 MFEM_CUDA_or_HIP(_R_64F));
802 MFEM_cu_or_hip(sparseCreateDnVec)(&
vecX_descr,
804 const_cast<double *
>(d_x),
805 MFEM_CUDA_or_HIP(_R_64F));
807 MFEM_CUDA_or_HIP(_R_64F));
810 cusparseSetMatIndexBase(
matA_descr, CUSPARSE_INDEX_BASE_ZERO);
811 cusparseSetMatType(
matA_descr, CUSPARSE_MATRIX_TYPE_GENERAL);
812 #endif // CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 816 size_t newBufferSize = 0;
818 MFEM_cu_or_hip(sparseSpMV_bufferSize)(
820 MFEM_CU_or_HIP(SPARSE_OPERATION_NON_TRANSPOSE),
826 MFEM_CUDA_or_HIP(_R_64F),
838 #if CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 840 MFEM_cu_or_hip(sparseDnVecSetValues)(
vecX_descr,
841 const_cast<double *
>(d_x));
842 MFEM_cu_or_hip(sparseDnVecSetValues)(
vecY_descr, d_y);
845 MFEM_cu_or_hip(sparseSpMV)(
847 MFEM_CU_or_HIP(SPARSE_OPERATION_NON_TRANSPOSE),
853 MFEM_CUDA_or_HIP(_R_64F),
858 CUSPARSE_OPERATION_NON_TRANSPOSE,
864 const_cast<double *
>(d_A),
865 const_cast<int *>(d_I),
866 const_cast<int *
>(d_J),
867 const_cast<double *>(d_x),
870 #endif // CUDA_VERSION >= 10010 || defined(MFEM_USE_HIP) 871 #endif // MFEM_USE_CUDA_OR_HIP 879 const int end = d_I[i+1];
880 for (
int j = d_I[i]; j < end; j++)
882 d += d_A[j] * d_x[d_J[j]];
889 #else // MFEM_USE_LEGACY_OPENMP 890 const double *Ap =
A, *xp = x.
GetData();
892 const int *Jp =
J, *Ip =
I;
894 #pragma omp parallel for 895 for (
int i = 0; i <
height; i++)
898 const int end = Ip[i+1];
899 for (
int j = Ip[i]; j < end; j++)
901 d += Ap[j] * xp[Jp[j]];
905 #endif // MFEM_USE_LEGACY_OPENMP 916 const double a)
const 919 <<
") must match matrix height (" <<
height <<
")");
920 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
921 <<
") must match matrix width (" <<
width <<
")");
928 for (
int i = 0; i <
height; i++)
930 RowNode *row =
Rows[i];
931 double b =
a * xp[i];
932 for ( ; row != NULL; row = row->Prev)
934 yp[row->Column] += row->Value *
b;
947 for (
int i = 0; i <
height; i++)
949 const double xi =
a * x[i];
950 const int end =
I[i+1];
951 for (
int j =
I[i]; j < end; j++)
985 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
987 const int n = rows.
Size();
989 auto d_rows = rows.
Read();
991 auto d_J =
Read(
J, nnz);
992 auto d_A =
Read(
A, nnz);
994 auto d_y = y.
Write();
997 const int r = d_rows[i];
998 const int end = d_I[r + 1];
1000 for (
int j = d_I[r]; j < end; j++)
1002 a += d_A[j] * d_x[d_J[j]];
1011 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1013 for (
int i = 0; i < rows.
Size(); i++)
1018 for (
int j =
I[r]; j < end; j++)
1020 val +=
A[j] * x(
J[j]);
1028 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
1029 MFEM_ASSERT(x.
Size() ==
Width(),
"Input vector size (" << x.
Size()
1030 <<
") must match matrix width (" <<
Width() <<
")");
1037 auto d_J =
Read(
J, nnz);
1043 const int end = d_I[i+1];
1044 for (
int j = d_I[i]; j < end; j++)
1059 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
1060 MFEM_ASSERT(x.
Size() ==
Height(),
"Input vector size (" << x.
Size()
1061 <<
") must match matrix height (" <<
Height() <<
")");
1066 for (
int i = 0; i <
Height(); i++)
1071 for (
int j =
I[i]; j < end; j++)
1081 MFEM_ASSERT(
width == x.
Size(),
"Input vector size (" << x.
Size()
1082 <<
") must match matrix width (" <<
width <<
")");
1083 MFEM_ASSERT(
height == y.
Size(),
"Output vector size (" << y.
Size()
1084 <<
") must match matrix height (" <<
height <<
")");
1095 for (
int i = 0; i <
height; i++)
1097 RowNode *row =
Rows[i];
1099 for ( ; row != NULL; row = row->Prev)
1101 b += std::abs(row->Value) * xp[row->Column];
1112 auto d_J =
Read(
J, nnz);
1113 auto d_A =
Read(
A, nnz);
1114 auto d_x = x.
Read();
1119 const int end = d_I[i+1];
1120 for (
int j = d_I[i]; j < end; j++)
1122 d += std::abs(d_A[j]) * d_x[d_J[j]];
1130 MFEM_ASSERT(
height == x.
Size(),
"Input vector size (" << x.
Size()
1131 <<
") must match matrix height (" <<
height <<
")");
1132 MFEM_ASSERT(
width == y.
Size(),
"Output vector size (" << y.
Size()
1133 <<
") must match matrix width (" <<
width <<
")");
1141 for (
int i = 0; i <
height; i++)
1143 RowNode *row =
Rows[i];
1145 for ( ; row != NULL; row = row->Prev)
1147 yp[row->Column] += fabs(row->Value) *
b;
1160 for (
int i = 0; i <
height; i++)
1162 const double xi = x[i];
1163 const int end =
I[i+1];
1164 for (
int j =
I[i]; j < end; j++)
1166 const int Jj =
J[j];
1167 y[Jj] += std::abs(
A[j]) * xi;
1176 <<
" must be equal to Width() = " <<
Width());
1178 <<
" must be equal to Height() = " <<
Height());
1191 for (
int i = 0; i <
height; i++)
1196 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
1198 a +=
A[j] * x(
J[j]);
1203 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
1205 a += np->Value * x(np->Column);
1216 for (
int i = 0; i <
height; i++)
1221 for (
int j =
I[i], end =
I[i+1]; j < end; j++)
1228 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
1239 MFEM_VERIFY(irow <
height,
1240 "row " << irow <<
" not in matrix with height " <<
height);
1245 for (
int j =
I[irow], end =
I[irow+1]; j < end; j++)
1252 for (RowNode *np =
Rows[irow]; np != NULL; np = np->Prev)
1254 a += fabs(np->Value);
1263 MFEM_ASSERT(
Finalized(),
"Matrix must be finalized.");
1265 atol = std::abs(tol);
1267 fix_empty_rows =
height ==
width ? fix_empty_rows :
false;
1275 for (i = 0, nz = 0; i <
height; i++)
1278 for (j =
I[i]; j <
I[i+1]; j++)
1279 if (std::abs(
A[j]) > atol)
1284 if (fix_empty_rows && !found) { nz++; }
1292 for (i = 0, nz = 0; i <
height; i++)
1296 for (j =
I[i]; j <
I[i+1]; j++)
1297 if (std::abs(
A[j]) > atol)
1302 if ( lastCol > newJ[nz] )
1309 if (fix_empty_rows && !found)
1337 for (i = 1; i <=
height; i++)
1340 for (aux =
Rows[i-1]; aux != NULL; aux = aux->Prev)
1342 if (skip_zeros && aux->Value == 0.0)
1344 if (skip_zeros == 2) {
continue; }
1345 if ((i-1) != aux->Column) {
continue; }
1349 for (RowNode *other =
Rows[aux->Column]; other != NULL; other = other->Prev)
1351 if (other->Column == (i-1))
1354 found_val = other->Value;
1358 if (found && found_val == 0.0) {
continue; }
1363 if (fix_empty_rows && !nr) { nr = 1; }
1372 for (j = i = 0; i <
height; i++)
1376 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1378 if (skip_zeros && aux->Value == 0.0)
1380 if (skip_zeros == 2) {
continue; }
1381 if (i != aux->Column) {
continue; }
1385 for (RowNode *other =
Rows[aux->Column]; other != NULL; other = other->Prev)
1387 if (other->Column == i)
1390 found_val = other->Value;
1394 if (found && found_val == 0.0) {
continue; }
1400 if ( lastCol >
J[j] )
1409 if (fix_empty_rows && !nr)
1417 #ifdef MFEM_USE_MEMALLOC 1421 for (i = 0; i <
height; i++)
1423 RowNode *node_p =
Rows[i];
1424 while (node_p != NULL)
1427 node_p = node_p->Prev;
1440 int nr = (
height + br - 1)/br, nc = (
width + bc - 1)/bc;
1442 for (
int j = 0; j < bc; j++)
1444 for (
int i = 0; i < br; i++)
1447 for (
int k = 0; k <= nr; k++)
1451 blocks(i,j) =
new SparseMatrix(bI, NULL, NULL, nr, nc);
1455 for (
int gr = 0; gr <
height; gr++)
1457 int bi = gr/nr, i = gr%nr + 1;
1460 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1464 blocks(bi,
J[j]/nc)->I[i]++;
1470 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1472 if (n_p->Value != 0.0)
1474 blocks(bi, n_p->Column/nc)->I[i]++;
1480 for (
int j = 0; j < bc; j++)
1482 for (
int i = 0; i < br; i++)
1486 for (
int k = 1; k <= nr; k++)
1488 rs =
b.I[k],
b.I[k] = nnz, nnz += rs;
1495 for (
int gr = 0; gr <
height; gr++)
1497 int bi = gr/nr, i = gr%nr + 1;
1500 for (
int j =
I[gr]; j <
I[gr+1]; j++)
1505 b.J[
b.I[i]] =
J[j] % nc;
1513 for (RowNode *n_p =
Rows[gr]; n_p != NULL; n_p = n_p->Prev)
1515 if (n_p->Value != 0.0)
1518 b.J[
b.I[i]] = n_p->Column % nc;
1519 b.A[
b.I[i]] = n_p->Value;
1541 for (
int i = 1; i <
height; i++)
1543 for (
int j =
I[i]; j <
I[i+1]; j++)
1547 symm = std::max(symm, std::abs(
A[j]-(*
this)(
J[j],i)));
1554 for (
int i = 0; i <
height; i++)
1556 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1558 int col = node_p->Column;
1561 symm = std::max(symm, std::abs(node_p->Value-(*
this)(col,i)));
1571 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
1574 for (i = 1; i <
height; i++)
1576 for (j =
I[i]; j <
I[i+1]; j++)
1580 A[j] += (*this)(
J[j],i);
1582 (*this)(
J[j],i) =
A[j];
1599 for (
int i = 0; i <
height; i++)
1601 for (RowNode *node_p =
Rows[i]; node_p != NULL; node_p = node_p->Prev)
1618 for (
int j = 0; j < nnz; j++)
1620 m = std::max(m, std::abs(
A[j]));
1625 for (
int i = 0; i <
height; i++)
1627 for (RowNode *n_p =
Rows[i]; n_p != NULL; n_p = n_p->Prev)
1629 m = std::max(m, std::abs(n_p->Value));
1643 const double *Ap =
A;
1645 for (
int i = 0; i < nz; i++)
1647 counter += (std::abs(Ap[i]) <= tol);
1652 for (
int i = 0; i <
height; i++)
1654 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1656 counter += (std::abs(aux->Value) <= tol);
1677 for (
int i = 0; i <
height; i++)
1679 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1697 MFEM_ASSERT(row < height && row >= 0,
1698 "Row " << row <<
" not in matrix of height " <<
height);
1700 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
1702 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1704 rhs(aux->Column) -= sol * aux->Value;
1713 MFEM_ASSERT(row < height && row >= 0,
1714 "Row " << row <<
" not in matrix of height " <<
height);
1715 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1717 "if dpolicy == DIAG_ONE, matrix must be square, not height = " 1722 for (
int i=
I[row]; i <
I[row+1]; ++i)
1729 for (aux =
Rows[row]; aux != NULL; aux = aux->Prev)
1743 MFEM_ASSERT(col < width && col >= 0,
1744 "Col " << col <<
" not in matrix of width " <<
width);
1745 MFEM_ASSERT(dpolicy !=
DIAG_KEEP,
"Diagonal policy must not be DIAG_KEEP");
1747 "if dpolicy == DIAG_ONE, matrix must be square, not height = " 1753 for (
int jpos = 0; jpos != nnz; ++jpos)
1763 for (
int i = 0; i <
height; i++)
1765 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1767 if (aux->Column == col)
1786 for (
int i = 0; i <
height; i++)
1788 for (
int jpos =
I[i]; jpos !=
I[i+1]; ++jpos)
1794 (*b)(i) -=
A[jpos] * (*x)(
J[jpos] );
1803 for (
int i = 0; i <
height; i++)
1805 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
1807 if (cols[aux -> Column])
1811 (*b)(i) -= aux -> Value * (*x)(aux -> Column);
1825 for (
int row = 0; row <
height; row++)
1827 for (nd =
Rows[row]; nd != NULL; nd = nd->Prev)
1829 if (col_marker[nd->Column])
1831 Ae.
Add(row, nd->Column, nd->Value);
1839 for (
int row = 0; row <
height; row++)
1841 for (
int j =
I[row]; j <
I[row+1]; j++)
1843 if (col_marker[
J[j]])
1845 Ae.
Add(row,
J[j],
A[j]);
1857 MFEM_ASSERT(rc < height && rc >= 0,
1858 "Row " << rc <<
" not in matrix of height " <<
height);
1865 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1867 const int col =
J[j];
1873 rhs(rc) =
A[j] * sol;
1884 mfem_error(
"SparseMatrix::EliminateRowCol () #2");
1891 for (
int k =
I[col]; 1; k++)
1895 mfem_error(
"SparseMatrix::EliminateRowCol () #3");
1897 else if (
J[k] == rc)
1899 rhs(col) -= sol *
A[k];
1909 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
1911 const int col = aux->Column;
1917 rhs(rc) = aux->Value * sol;
1928 mfem_error(
"SparseMatrix::EliminateRowCol () #4");
1935 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
1939 mfem_error(
"SparseMatrix::EliminateRowCol () #5");
1941 else if (node->Column == rc)
1943 rhs(col) -= sol * node->Value;
1957 MFEM_ASSERT(rc < height && rc >= 0,
1958 "Row " << rc <<
" not in matrix of height " <<
height);
1959 MFEM_ASSERT(sol.
Size() == rhs.
Width(),
"solution size (" << sol.
Size()
1960 <<
") must match rhs width (" << rhs.
Width() <<
")");
1962 const int num_rhs = rhs.
Width();
1965 for (
int j =
I[rc]; j <
I[rc+1]; j++)
1967 const int col =
J[j];
1973 for (
int r = 0; r < num_rhs; r++)
1975 rhs(rc,r) =
A[j] * sol(r);
1980 for (
int r = 0; r < num_rhs; r++)
1987 for (
int r = 0; r < num_rhs; r++)
1993 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #3");
2000 for (
int k =
I[col]; 1; k++)
2004 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #4");
2006 else if (
J[k] == rc)
2008 for (
int r = 0; r < num_rhs; r++)
2010 rhs(col,r) -= sol(r) *
A[k];
2021 for (RowNode *aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
2023 const int col = aux->Column;
2029 for (
int r = 0; r < num_rhs; r++)
2031 rhs(rc,r) = aux->Value * sol(r);
2036 for (
int r = 0; r < num_rhs; r++)
2043 for (
int r = 0; r < num_rhs; r++)
2049 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #5");
2056 for (RowNode *node =
Rows[col]; 1; node = node->Prev)
2060 mfem_error(
"SparseMatrix::EliminateRowColMultipleRHS() #6");
2062 else if (node->Column == rc)
2064 for (
int r = 0; r < num_rhs; r++)
2066 rhs(col,r) -= sol(r) * node->Value;
2079 MFEM_ASSERT(rc < height && rc >= 0,
2080 "Row " << rc <<
" not in matrix of height " <<
height);
2084 const auto &II = this->
I;
2085 const auto &JJ = this->
J;
2086 for (
int j = II[rc]; j < II[rc+1]; j++)
2088 const int col = JJ[j];
2103 for (
int k = II[col]; 1; k++)
2107 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
2109 else if (JJ[k] == rc)
2120 RowNode *aux, *node;
2122 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
2124 const int col = aux->Column;
2139 for (node =
Rows[col]; 1; node = node->Prev)
2143 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
2145 else if (node->Column == rc)
2160 MFEM_ASSERT(rc < height && rc >= 0,
2161 "Row " << rc <<
" not in matrix of height " <<
height);
2165 for (
int j =
I[rc]; j <
I[rc+1]; j++)
2167 const int col =
J[j];
2175 for (
int k =
I[col]; 1; k++)
2179 mfem_error(
"SparseMatrix::EliminateRowCol() #2");
2181 else if (
J[k] == rc)
2192 RowNode *aux, *node;
2194 for (aux =
Rows[rc]; aux != NULL; aux = aux->Prev)
2196 const int col = aux->Column;
2204 for (node =
Rows[col]; 1; node = node->Prev)
2208 mfem_error(
"SparseMatrix::EliminateRowCol() #3");
2210 else if (node->Column == rc)
2227 for (nd =
Rows[rc]; nd != NULL; nd = nd->Prev)
2229 const int col = nd->Column;
2235 Ae.
Add(rc, rc, nd->Value - 1.0);
2239 Ae.
Add(rc, rc, nd->Value);
2245 mfem_error(
"SparseMatrix::EliminateRowCol #1");
2251 Ae.
Add(rc, col, nd->Value);
2253 for (nd2 =
Rows[col]; 1; nd2 = nd2->Prev)
2257 mfem_error(
"SparseMatrix::EliminateRowCol #2");
2259 else if (nd2->Column == rc)
2261 Ae.
Add(col, rc, nd2->Value);
2271 for (
int j =
I[rc]; j <
I[rc+1]; j++)
2273 const int col =
J[j];
2279 Ae.
Add(rc, rc,
A[j] - 1.0);
2283 Ae.
Add(rc, rc,
A[j]);
2289 mfem_error(
"SparseMatrix::EliminateRowCol #3");
2295 Ae.
Add(rc, col,
A[j]);
2297 for (
int k =
I[col];
true; k++)
2301 mfem_error(
"SparseMatrix::EliminateRowCol #4");
2303 else if (
J[k] == rc)
2305 Ae.
Add(col, rc,
A[k]);
2318 const int n_ess_dofs = ess_dofs.
Size();
2319 const auto ess_dofs_d = ess_dofs.
Read();
2320 const auto dI =
ReadI();
2321 const auto dJ =
ReadJ();
2324 MFEM_FORALL(i, n_ess_dofs,
2326 const int idof = ess_dofs_d[i];
2327 for (
int j=dI[idof]; j<dI[idof+1]; ++j)
2329 const int jdof = dJ[j];
2333 for (
int k=dI[jdof]; k<dI[jdof+1]; ++k)
2344 if (diag_policy == DiagonalPolicy::DIAG_ONE)
2348 else if (diag_policy == DiagonalPolicy::DIAG_ZERO)
2360 for (
int i = 0; i <
height; i++)
2362 if (
I[i+1] ==
I[i]+1 && fabs(
A[
I[i]]) < 1e-16)
2371 for (
int i = 0; i <
height; i++)
2374 for (
int j =
I[i]; j <
I[i+1]; j++)
2378 if (zero <= threshold)
2380 for (
int j =
I[i]; j <
I[i+1]; j++)
2382 A[j] = (
J[j] == i) ? 1.0 : 0.0;
2393 const double *xp = x.
GetData();
2394 RowNode *diag_p, *n_p, **R =
Rows;
2397 for (
int i = 0; i <
s; i++)
2401 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
2403 const int c = n_p->Column;
2410 sum += n_p->Value * yp[c];
2414 if (diag_p != NULL && diag_p->Value != 0.0)
2416 yp[i] = (xp[i] - sum) / diag_p->Value;
2418 else if (xp[i] == sum)
2424 mfem_error(
"SparseMatrix::Gauss_Seidel_forw()");
2438 for (
int i = 0, j = Ip[0]; i <
s; i++)
2440 const int end = Ip[i+1];
2443 for ( ; j < end; j++)
2445 const int c = Jp[j];
2452 sum += Ap[j] * yp[c];
2456 if (d >= 0 && Ap[d] != 0.0)
2458 yp[i] = (xp[i] - sum) / Ap[d];
2460 else if (xp[i] == sum)
2466 mfem_error(
"SparseMatrix::Gauss_Seidel_forw(...) #2");
2477 const double *xp = x.
GetData();
2478 RowNode *diag_p, *n_p, **R =
Rows;
2480 for (
int i =
height-1; i >= 0; i--)
2484 for (n_p = R[i]; n_p != NULL; n_p = n_p->Prev)
2486 const int c = n_p->Column;
2493 sum += n_p->Value * yp[c];
2497 if (diag_p != NULL && diag_p->Value != 0.0)
2499 yp[i] = (xp[i] - sum) / diag_p->Value;
2501 else if (xp[i] == sum)
2507 mfem_error(
"SparseMatrix::Gauss_Seidel_back()");
2521 for (
int i =
s-1, j = Ip[
s]-1; i >= 0; i--)
2523 const int beg = Ip[i];
2526 for ( ; j >= beg; j--)
2528 const int c = Jp[j];
2535 sum += Ap[j] * yp[c];
2539 if (d >= 0 && Ap[d] != 0.0)
2541 yp[i] = (xp[i] - sum) / Ap[d];
2543 else if (xp[i] == sum)
2549 mfem_error(
"SparseMatrix::Gauss_Seidel_back(...) #2");
2557 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2560 for (
int i = 0; i <
height; i++)
2564 for (
int j =
I[i]; j <
I[i+1]; j++)
2572 if (d >= 0 &&
A[d] != 0.0)
2574 double a = 1.8 * fabs(
A[d]) / norm;
2582 mfem_error(
"SparseMatrix::GetJacobiScaling() #2");
2589 double sc,
bool use_abs_diag)
const 2591 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2593 for (
int i = 0; i <
height; i++)
2597 for (
int j =
I[i]; j <
I[i+1]; j++)
2605 sum -=
A[j] * x0(
J[j]);
2608 if (d >= 0 &&
A[d] != 0.0)
2610 const double diag = (use_abs_diag) ? fabs(
A[d]) :
A[d];
2611 x1(i) = sc * (sum / diag) + (1.0 - sc) * x0(i);
2621 double sc,
bool use_abs_diag)
const 2623 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2627 const bool use_dev =
b.UseDevice() || x.
UseDevice();
2629 const auto Ap =
Read(
A, nnz, use_dev);
2631 const auto Jp =
Read(
J, nnz, use_dev);
2633 const auto bp =
b.Read(use_dev);
2634 auto xp = x.
Write(use_dev);
2636 MFEM_FORALL_SWITCH(use_dev, i, H,
2638 const int end = Ip[i+1];
2639 for (
int j = Ip[i];
true; j++)
2643 MFEM_ABORT_KERNEL(
"Diagonal not found in SparseMatrix::DiagScale");
2647 const double diag = (use_abs_diag) ? fabs(Ap[j]) : Ap[j];
2650 MFEM_ABORT_KERNEL(
"Zero diagonal in SparseMatrix::DiagScale");
2652 xp[i] = sc * bp[i] / diag;
2659 template <
bool useFabs>
2667 const auto bp =
b.Read(useDevice);
2668 const auto x0p = x0.
Read(useDevice);
2669 auto x1p = x1.
Write(useDevice);
2671 const auto Ip =
Read(I, height+1, useDevice);
2675 MFEM_FORALL_SWITCH(useDevice, i, height,
2677 double resi = bp[i], norm = 0.0;
2678 for (
int j = Ip[i]; j < Ip[i+1]; j++)
2680 resi -= Ap[j] * x0p[Jp[j]];
2683 norm += fabs(Ap[j]);
2692 x1p[i] = x0p[i] + sc * resi / norm;
2698 MFEM_ABORT_KERNEL(
"L1 norm of row is zero.");
2702 MFEM_ABORT_KERNEL(
"sum of row is zero.");
2711 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2712 JacobiDispatch<true>(
b,x0,x1,
I,
J,
A,
height,sc);
2718 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
2719 JacobiDispatch<false>(
b,x0,x1,
I,
J,
A,
height,sc);
2725 int i, j, gi, gj,
s,
t;
2735 for (i = 0; i < rows.
Size(); i++)
2737 if ((gi=rows[i]) < 0) { gi = -1-gi,
s = -1; }
2740 "Trying to insert a row " << gi <<
" outside the matrix height " 2743 for (j = 0; j < cols.
Size(); j++)
2745 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
2747 MFEM_ASSERT(gj <
width,
2748 "Trying to insert a column " << gj <<
" outside the matrix width " 2751 if (skip_zeros &&
a == 0.0)
2756 if (skip_zeros == 2 || &rows != &cols || subm(j, i) == 0.0)
2761 if (
t < 0) {
a = -
a; }
2773 if ((gi=i) < 0) { gi = -1-gi,
s = -1; }
2776 "Trying to set a row " << gi <<
" outside the matrix height " 2778 if ((gj=j) < 0) { gj = -1-gj,
t = -
s; }
2780 MFEM_ASSERT(gj <
width,
2781 "Trying to set a column " << gj <<
" outside the matrix width " 2783 if (
t < 0) {
a = -
a; }
2792 if ((gi=i) < 0) { gi = -1-gi,
s = -1; }
2795 "Trying to insert a row " << gi <<
" outside the matrix height " 2797 if ((gj=j) < 0) { gj = -1-gj,
t = -
s; }
2799 MFEM_ASSERT(gj <
width,
2800 "Trying to insert a column " << gj <<
" outside the matrix width " 2802 if (
t < 0) {
a = -
a; }
2809 int i, j, gi, gj,
s,
t;
2812 for (i = 0; i < rows.
Size(); i++)
2814 if ((gi=rows[i]) < 0) { gi = -1-gi,
s = -1; }
2817 "Trying to set a row " << gi <<
" outside the matrix height " 2820 for (j = 0; j < cols.
Size(); j++)
2823 if (skip_zeros &&
a == 0.0)
2828 if (skip_zeros == 2 || &rows != &cols || subm(j, i) == 0.0)
2833 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
2835 MFEM_ASSERT(gj <
width,
2836 "Trying to set a column " << gj <<
" outside the matrix width " 2838 if (
t < 0) {
a = -
a; }
2850 int i, j, gi, gj,
s,
t;
2853 for (i = 0; i < rows.
Size(); i++)
2855 if ((gi=rows[i]) < 0) { gi = -1-gi,
s = -1; }
2858 "Trying to set a row " << gi <<
" outside the matrix height " 2861 for (j = 0; j < cols.
Size(); j++)
2864 if (skip_zeros &&
a == 0.0)
2869 if (skip_zeros == 2 || &rows != &cols || subm(j, i) == 0.0)
2874 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
2876 MFEM_ASSERT(gj <
width,
2877 "Trying to set a column " << gj <<
" outside the matrix width " 2879 if (
t < 0) {
a = -
a; }
2889 int i, j, gi, gj,
s,
t;
2892 for (i = 0; i < rows.
Size(); i++)
2894 if ((gi=rows[i]) < 0) { gi = -1-gi,
s = -1; }
2897 "Trying to read a row " << gi <<
" outside the matrix height " 2900 for (j = 0; j < cols.
Size(); j++)
2902 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
2904 MFEM_ASSERT(gj <
width,
2905 "Trying to read a column " << gj <<
" outside the matrix width " 2908 subm(i, j) = (
t < 0) ? (-
a) : (
a);
2923 "Trying to query a row " << gi <<
" outside the matrix height " 2927 return (
Rows[gi] == NULL);
2931 return (
I[gi] ==
I[gi+1]);
2940 if ((gi=row) < 0) { gi = -1-gi; }
2942 "Trying to read a row " << gi <<
" outside the matrix height " 2946 for (n =
Rows[gi], j = 0; n; n = n->Prev)
2952 for (n =
Rows[gi], j = 0; n; n = n->Prev, j++)
2954 cols[j] = n->Column;
2967 cols.
MakeRef(const_cast<int*>((
const int*)
J) + j,
I[gi+1]-j);
2969 const_cast<double*>((
const double*)
A) + j, cols.
Size());
2970 MFEM_ASSERT(row >= 0,
"Row not valid: " << row <<
", height: " <<
height);
2981 if ((gi=row) < 0) { gi = -1-gi,
s = -1; }
2984 "Trying to set a row " << gi <<
" outside the matrix height " 2990 for (
int j = 0; j < cols.
Size(); j++)
2992 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
2994 MFEM_ASSERT(gj <
width,
2995 "Trying to set a column " << gj <<
" outside the matrix" 2996 " width " <<
width);
2998 if (
t < 0) {
a = -
a; }
3006 MFEM_ASSERT(cols.
Size() == srow.
Size(),
"");
3008 for (
int i =
I[gi], j = 0; j < cols.
Size(); j++, i++)
3010 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
3012 MFEM_ASSERT(gj <
width,
3013 "Trying to set a column " << gj <<
" outside the matrix" 3014 " width " <<
width);
3025 int j, gi, gj,
s,
t;
3028 MFEM_VERIFY(!
Finalized(),
"Matrix must NOT be finalized.");
3030 if ((gi=row) < 0) { gi = -1-gi,
s = -1; }
3033 "Trying to insert a row " << gi <<
" outside the matrix height " 3036 for (j = 0; j < cols.
Size(); j++)
3038 if ((gj=cols[j]) < 0) { gj = -1-gj,
t = -
s; }
3040 MFEM_ASSERT(gj <
width,
3041 "Trying to insert a column " << gj <<
" outside the matrix width " 3048 if (
t < 0) {
a = -
a; }
3066 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
3068 aux -> Value *= scale;
3073 int j, end =
I[i+1];
3075 for (j =
I[i]; j < end; j++)
3088 for (
int i=0; i <
height; ++i)
3091 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
3093 aux -> Value *= scale;
3101 for (
int i=0; i <
height; ++i)
3105 for (j =
I[i]; j < end; j++)
3118 for (
int i=0; i <
height; ++i)
3120 for (aux =
Rows[i]; aux != NULL; aux = aux -> Prev)
3122 aux -> Value *= sr(aux->Column);
3130 for (
int i=0; i <
height; ++i)
3133 for (j =
I[i]; j < end; j++)
3144 "Mismatch of this matrix size and rhs. This height = " 3145 <<
height <<
", width = " <<
width <<
", B.height = " 3148 for (
int i = 0; i <
height; i++)
3153 for (RowNode *aux = B.
Rows[i]; aux != NULL; aux = aux->Prev)
3155 _Add_(aux->Column, aux->Value);
3160 for (
int j = B.
I[i]; j < B.
I[i+1]; j++)
3173 for (
int i = 0; i <
height; i++)
3178 for (RowNode *np =
Rows[i]; np != NULL; np = np->Prev)
3180 np->Value +=
a * B.
_Get_(np->Column);
3185 for (
int j =
I[i]; j <
I[i+1]; j++)
3200 for (
int i = 0; i < nnz; i++)
3207 for (
int i = 0; i <
height; i++)
3209 for (RowNode *node_p =
Rows[i]; node_p != NULL;
3210 node_p = node_p -> Prev)
3212 node_p -> Value =
a;
3224 for (
int i = 0, nnz =
I[
height]; i < nnz; i++)
3231 for (
int i = 0; i <
height; i++)
3233 for (RowNode *node_p =
Rows[i]; node_p != NULL;
3234 node_p = node_p -> Prev)
3236 node_p -> Value *=
a;
3251 for (i = 0; i <
height; i++)
3253 os <<
"[row " << i <<
"]\n";
3254 for (nd =
Rows[i], j = 0; nd != NULL; nd = nd->Prev, j++)
3256 os <<
" (" << nd->Column <<
"," << nd->Value <<
")";
3257 if ( !((j+1) % width_) )
3274 for (i = 0; i <
height; i++)
3276 os <<
"[row " << i <<
"]\n";
3277 for (j =
I[i]; j <
I[i+1]; j++)
3279 os <<
" (" <<
J[j] <<
"," <<
A[j] <<
")";
3280 if ( !((j+1-
I[i]) % width_) )
3285 if ((j-
I[i]) % width_)
3294 os <<
"% size " <<
height <<
" " <<
width <<
"\n";
3297 ios::fmtflags old_fmt = os.flags();
3298 os.setf(ios::scientific);
3299 std::streamsize old_prec = os.precision(14);
3301 for (i = 0; i <
height; i++)
3303 for (j =
I[i]; j <
I[i+1]; j++)
3305 os << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
3310 os.precision(old_prec);
3317 ios::fmtflags old_fmt = os.flags();
3318 os.setf(ios::scientific);
3319 std::streamsize old_prec = os.precision(14);
3321 os <<
"%%MatrixMarket matrix coordinate real general" <<
'\n' 3322 <<
"% Generated by MFEM" <<
'\n';
3325 for (i = 0; i <
height; i++)
3327 for (j =
I[i]; j <
I[i+1]; j++)
3329 os << i+1 <<
" " <<
J[j]+1 <<
" " <<
A[j] <<
'\n';
3332 os.precision(old_prec);
3338 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
3344 for (i = 0; i <=
height; i++)
3346 os <<
I[i]+1 <<
'\n';
3349 for (i = 0; i <
I[
height]; i++)
3351 os <<
J[i]+1 <<
'\n';
3354 for (i = 0; i <
I[
height]; i++)
3362 MFEM_VERIFY(
Finalized(),
"Matrix must be finalized.");
3367 os <<
width <<
'\n';
3369 for (i = 0; i <=
height; i++)
3374 for (i = 0; i <
I[
height]; i++)
3379 for (i = 0; i <
I[
height]; i++)
3387 const double MiB = 1024.*1024;
3389 double pz = 100./nnz;
3399 "SparseMatrix statistics:\n" 3402 " Dimensions : " <<
height <<
" x " <<
width <<
"\n" 3403 " Number of entries (total) : " << nnz <<
"\n" 3404 " Number of entries (per row) : " << 1.*nnz/
Height() <<
"\n" 3405 " Number of stored zeros : " << nz*pz <<
"% (" << nz <<
")\n" 3406 " Number of Inf/Nan entries : " << nnf*pz <<
"% ("<< nnf <<
")\n" 3407 " Norm, max |a_ij| : " << max_norm <<
"\n" 3408 " Symmetry, max |a_ij-a_ji| : " << symm <<
"\n" 3409 " Number of small entries:\n" 3410 " |a_ij| <= 1e-12*Norm : " << ns12*pz <<
"% (" << ns12 <<
")\n" 3411 " |a_ij| <= 1e-15*Norm : " << ns15*pz <<
"% (" << ns15 <<
")\n" 3412 " |a_ij| <= 1e-18*Norm : " << ns18*pz <<
"% (" << ns18 <<
")\n";
3415 os <<
" Memory used by CSR : " <<
3416 (
sizeof(int)*(
height+1+nnz)+
sizeof(double)*nnz)/MiB <<
" MiB\n";
3420 size_t used_mem =
sizeof(RowNode*)*
height;
3421 #ifdef MFEM_USE_MEMALLOC 3424 for (
int i = 0; i <
height; i++)
3426 for (RowNode *aux =
Rows[i]; aux != NULL; aux = aux->Prev)
3428 used_mem +=
sizeof(RowNode);
3432 os <<
" Memory used by LIL : " << used_mem/MiB <<
" MiB\n";
3444 #if !defined(MFEM_USE_MEMALLOC) 3445 for (
int i = 0; i <
height; i++)
3447 RowNode *aux, *node_p =
Rows[i];
3448 while (node_p != NULL)
3451 node_p = node_p->Prev;
3461 #ifdef MFEM_USE_MEMALLOC 3474 const int *start_j =
J;
3476 for (
const int *jptr = start_j; jptr != end_j; ++jptr)
3478 awidth = std::max(awidth, *jptr + 1);
3484 for (
int i = 0; i <
height; i++)
3486 for (aux =
Rows[i]; aux != NULL; aux = aux->Prev)
3488 awidth = std::max(awidth, aux->Column + 1);
3500 for (
int i = 0; i < n; i++)
3510 "Finalize must be called before Transpose. Use TransposeRowMatrix instead");
3513 const int *A_i, *A_j;
3514 int m, n, nnz, *At_i, *At_j;
3515 const double *A_data;
3529 for (i = 0; i <= n; i++)
3533 for (i = 0; i < nnz; i++)
3537 for (i = 1; i < n; i++)
3539 At_i[i+1] += At_i[i];
3542 for (i = j = 0; i < m; i++)
3545 for ( ; j < end; j++)
3547 At_j[At_i[A_j[j]]] = i;
3548 At_data[At_i[A_j[j]]] = A_data[j];
3553 for (i = n; i > 0; i--)
3555 At_i[i] = At_i[i-1];
3566 int m, n, nnz, *At_i, *At_j;
3576 for (i = 0; i < m; i++)
3578 A.
GetRow(i, Acols, Avals);
3600 for (i = 0; i <= n; i++)
3605 for (i = 0; i < m; i++)
3607 A.
GetRow(i, Acols, Avals);
3608 for (j = 0; j<Acols.
Size(); ++j)
3613 for (i = 1; i < n; i++)
3615 At_i[i+1] += At_i[i];
3618 for (i = 0; i < m; i++)
3620 A.
GetRow(i, Acols, Avals);
3621 for (j = 0; j<Acols.
Size(); ++j)
3623 At_j[At_i[Acols[j]]] = i;
3624 At_data[At_i[Acols[j]]] = Avals[j];
3629 for (i = n; i > 0; i--)
3631 At_i[i] = At_i[i-1];
3642 int nrowsA, ncolsA, nrowsB, ncolsB;
3643 const int *A_i, *A_j, *B_i, *B_j;
3644 int *C_i, *C_j, *B_marker;
3645 const double *A_data, *B_data;
3647 int ia, ib, ic, ja, jb, num_nonzeros;
3648 int row_start, counter;
3649 double a_entry, b_entry;
3657 MFEM_VERIFY(ncolsA == nrowsB,
3658 "number of columns of A (" << ncolsA
3659 <<
") must equal number of rows of B (" << nrowsB <<
")");
3668 B_marker =
new int[ncolsB];
3670 for (ib = 0; ib < ncolsB; ib++)
3679 C_i[0] = num_nonzeros = 0;
3680 for (ic = 0; ic < nrowsA; ic++)
3682 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3685 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3688 if (B_marker[jb] != ic)
3695 C_i[ic+1] = num_nonzeros;
3701 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3703 for (ib = 0; ib < ncolsB; ib++)
3712 MFEM_VERIFY(nrowsA == C->
Height() && ncolsB == C->
Width(),
3713 "Input matrix sizes do not match output sizes" 3714 <<
" nrowsA = " << nrowsA
3715 <<
", C->Height() = " << C->
Height()
3716 <<
" ncolsB = " << ncolsB
3717 <<
", C->Width() = " << C->
Width());
3725 for (ic = 0; ic < nrowsA; ic++)
3728 row_start = counter;
3729 for (ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3732 a_entry = A_data[ia];
3733 for (ib = B_i[ja]; ib < B_i[ja+1]; ib++)
3736 b_entry = B_data[ib];
3737 if (B_marker[jb] < row_start)
3739 B_marker[jb] = counter;
3744 C_data[counter] = a_entry*b_entry;
3749 C_data[B_marker[jb]] += a_entry*b_entry;
3757 "With pre-allocated output matrix, number of non-zeros (" 3759 <<
") did not match number of entries changed from matrix-matrix multiply, " 3778 int nrowsA, ncolsA, nrowsB, ncolsB;
3779 int *C_i, *C_j, *B_marker;
3781 int ia, ib, ic, ja, jb, num_nonzeros;
3782 int row_start, counter;
3783 double a_entry, b_entry;
3791 MFEM_VERIFY(ncolsA == nrowsB,
3792 "number of columns of A (" << ncolsA
3793 <<
") must equal number of rows of B (" << nrowsB <<
")");
3795 B_marker =
new int[ncolsB];
3797 for (ib = 0; ib < ncolsB; ib++)
3804 C_i[0] = num_nonzeros = 0;
3808 for (ic = 0; ic < nrowsA; ic++)
3810 A.
GetRow(ic, colsA, dataA);
3811 for (ia = 0; ia < colsA.
Size(); ia++)
3814 B.
GetRow(ja, colsB, dataB);
3815 for (ib = 0; ib < colsB.
Size(); ib++)
3818 if (B_marker[jb] != ic)
3825 C_i[ic+1] = num_nonzeros;
3831 C =
new SparseMatrix(C_i, C_j, C_data, nrowsA, ncolsB);
3833 for (ib = 0; ib < ncolsB; ib++)
3839 for (ic = 0; ic < nrowsA; ic++)
3841 row_start = counter;
3842 A.
GetRow(ic, colsA, dataA);
3843 for (ia = 0; ia < colsA.
Size(); ia++)
3846 a_entry = dataA[ia];
3847 B.
GetRow(ja, colsB, dataB);
3848 for (ib = 0; ib < colsB.
Size(); ib++)
3851 b_entry = dataB[ib];
3852 if (B_marker[jb] < row_start)
3854 B_marker[jb] = counter;
3856 C_data[counter] = a_entry*b_entry;
3861 C_data[B_marker[jb]] += a_entry*b_entry;
3876 for (
int j = 0; j < B.
Width(); ++j)
3880 A.
Mult(columnB, columnC);
3890 Mult (R, *AP, *RAP_);
3933 int i, At_nnz, *At_j;
3937 At_nnz = At -> NumNonZeroElems();
3938 At_j = At -> GetJ();
3939 At_data = At -> GetData();
3940 for (i = 0; i < At_nnz; i++)
3942 At_data[i] *= D(At_j[i]);
3953 int ncols = A.
Width();
3959 const int *A_i = A.
GetI();
3960 const int *A_j = A.
GetJ();
3961 const double *A_data = A.
GetData();
3963 const int *B_i = B.
GetI();
3964 const int *B_j = B.
GetJ();
3965 const double *B_data = B.
GetData();
3967 int * marker =
new int[ncols];
3968 std::fill(marker, marker+ncols, -1);
3970 int num_nonzeros = 0, jcol;
3972 for (
int ic = 0; ic < nrows; ic++)
3974 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
3980 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
3983 if (marker[jcol] != ic)
3989 C_i[ic+1] = num_nonzeros;
3995 for (
int ia = 0; ia < ncols; ia++)
4001 for (
int ic = 0; ic < nrows; ic++)
4003 for (
int ia = A_i[ic]; ia < A_i[ic+1]; ia++)
4007 C_data[pos] =
a*A_data[ia];
4011 for (
int ib = B_i[ic]; ib < B_i[ic+1]; ib++)
4014 if (marker[jcol] < C_i[ic])
4017 C_data[pos] =
b*B_data[ib];
4023 C_data[marker[jcol]] +=
b*B_data[ib];
4029 return new SparseMatrix(C_i, C_j, C_data, nrows, ncols);
4034 return Add(1.,A,1.,B);
4039 MFEM_ASSERT(Ai.
Size() > 0,
"invalid size Ai.Size() = " << Ai.
Size());
4044 for (
int i=1; i < Ai.
Size(); ++i)
4046 result =
Add(*accumulate, *Ai[i]);
4052 accumulate = result;
4062 for (
int r = 0; r < B.
Height(); r++)
4066 for (
int i=0; i<A.
RowSize(r); i++)
4068 B(r, colA[i]) +=
alpha * valA[i];
4081 for (
int i=0; i<mA; i++)
4083 for (
int j=0; j<nA; j++)
4085 C->
AddMatrix(A(i,j), B, i * mB, j * nB);
4099 for (
int i=0; i<mA; i++)
4101 for (
int j=0; j<nA; j++)
4103 for (
int r=0; r<mB; r++)
4108 for (
int cj=0; cj<B.
RowSize(r); cj++)
4110 C->
Set(i * mB + r, j * nB + colB[cj], A(i,j) * valB[cj]);
4128 for (
int r=0; r<mA; r++)
4133 for (
int aj=0; aj<A.
RowSize(r); aj++)
4135 for (
int i=0; i<mB; i++)
4137 for (
int j=0; j<nB; j++)
4139 C->
Set(r * mB + i, colA[aj] * nB + j, valA[aj] * B(i, j));
4157 for (
int ar=0; ar<mA; ar++)
4162 for (
int aj=0; aj<A.
RowSize(ar); aj++)
4164 for (
int br=0; br<mB; br++)
4169 for (
int bj=0; bj<B.
RowSize(br); bj++)
4171 C->
Set(ar * mB + br, colA[aj] * nB + colB[bj],
4172 valA[aj] * valB[bj]);
4195 #ifdef MFEM_USE_MEMALLOC 4205 #ifdef MFEM_USE_CUDA_OR_HIP 4212 MFEM_cu_or_hip(sparseDestroy)(
handle);
4217 MFEM_Cu_or_Hip(MemFree)(
dBuffer);
4224 #endif // MFEM_USE_CUDA_OR_HIP const T * Read(bool on_dev=true) const
Shortcut for mfem::Read(a.GetMemory(), a.Size(), on_dev).
Memory< int > I
Array with size (height+1) containing the row offsets.
const double * HostReadData() const
virtual void Mult(const Vector &x, Vector &y) const
Matrix vector multiplication.
SparseMatrix * TransposeAbstractSparseMatrix(const AbstractSparseMatrix &A, int useActualWidth)
Transpose of a sparse matrix. A does not need to be a CSR matrix.
int CheckFinite(const double *v, const int n)
virtual int NumNonZeroElems() const
Returns the number of the nonzero elements in the matrix.
void * CuMemFree(void *dptr)
Frees device memory and returns destination ptr.
void _Add_(const int col, const double a)
Add a value to an entry in the "current row". See SetColPtr().
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.
void GetDiag(Vector &d) const
Returns the Diagonal of A.
void PrintMM(std::ostream &out=mfem::out) const
Prints matrix in Matrix Market sparse format.
double GetRowNorml1(int irow) const
For i = irow compute .
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 and reset the Memory object.
virtual const double * HostRead() const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), false).
size_t MemoryUsage() const
int * GetRowColumns(const int row)
Return a pointer to the column indices in a row.
void PrintCSR(std::ostream &out) const
Prints matrix to stream out in hypre_CSRMatrix format.
double GetJacobiScaling() const
Determine appropriate scaling for Jacobi iteration.
int RowSize(const int i) const
Returns the number of elements in row i.
virtual void UseDevice(bool use_dev) const
Enable execution of Vector operations using the mfem::Device.
void Mult(const Table &A, const Table &B, Table &C)
C = A * B (as boolean matrices)
void SetColPtr(const int row) const
Initialize the SparseMatrix for fast access to the entries of the given row which becomes the "curren...
int * GetJ()
Return the array J.
int Width() const
Get the width (size of input) of the Operator. Synonym with NumCols().
Biwise-OR of all HIP backends.
Abstract data type for sparse matrices.
double IsSymmetric() const
Returns max_{i,j} |(i,j)-(j,i)| for a finalized matrix.
int Size() const
Returns the size of the vector.
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...
T Max() const
Find the maximal element in the array, using the comparison operator < for class T.
Data type dense matrix using column-major storage.
virtual const double * Read(bool on_dev=true) const
Shortcut for mfem::Read(vec.GetMemory(), vec.Size(), on_dev).
int * GetI()
Return the array I.
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.
virtual void AddMult(const Vector &x, Vector &y, const double a=1.0) const
y += A * x (default) or y += a * A * x
virtual int GetRow(const int row, Array< int > &cols, Vector &srow) const
Extract all column indices and values from a given row.
void ClearGPUSparse()
Clear the cuSPARSE/hipSPARSE descriptors. This must be called after releasing the device memory of A...
void CopyFrom(const Memory &src, int size)
Copy size entries from src to *this.
virtual double & Elem(int i, int j)
Returns reference to a_{ij}.
void Print(std::ostream &out=mfem::out, int width_=4) const
Prints matrix to stream out.
void GetSubMatrix(const Array< int > &rows, const Array< int > &cols, DenseMatrix &subm) const
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.
cusparseDnVecDescr_t vecY_descr
double * HostReadWriteData()
void _Set_(const int col, const double a)
Set an entry in the "current row". See SetColPtr().
SparseMatrix * Mult_AtDA(const SparseMatrix &A, const Vector &D, SparseMatrix *OAtDA)
Matrix multiplication A^t D A. All matrices must be finalized.
unsigned flags
Bit flags defined from the FlagMask enum.
void Gauss_Seidel_back(const Vector &x, Vector &y) const
void ScaleRow(const int row, const double scale)
double * GetData()
Return the element data, i.e. the array A.
virtual MatrixInverse * Inverse() const
This virtual method is not supported: it always returns NULL.
DenseMatrix * ToDenseMatrix() const
Produces a DenseMatrix from a SparseMatrix.
void Symmetrize()
(*this) = 1/2 ((*this) + (*this)^t)
bool IsFinite(const double &val)
void Jacobi3(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
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 Set(const int i, const int j, const double val)
void Wrap(T *ptr, int size, bool own)
Wrap an externally allocated host pointer, ptr with the current host memory type returned by MemoryMa...
void GetBlocks(Array2D< SparseMatrix *> &blocks) const
void ScaleColumns(const Vector &sr)
this = this * diag(sr);
void GetRowSums(Vector &x) const
For all i compute .
virtual ~SparseMatrix()
Destroys sparse matrix.
double f(const Vector &xvec)
bool Empty() const
Check if the SparseMatrix is empty.
bool isSorted
Are the columns sorted already.
void ClearColPtr() const
Reset the "current row" set by calling SetColPtr(). This method must be called between any two calls ...
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.
virtual double * Write(bool on_dev=true)
Shortcut for mfem::Write(vec.GetMemory(), vec.Size(), on_dev).
void mfem_error(const char *msg)
Function called when an error is encountered. Used by the macros MFEM_ABORT, MFEM_ASSERT, MFEM_VERIFY.
void SetWidth(int width_=-1)
Change the width of a SparseMatrix.
static MemoryType GetDeviceMemoryType()
Get the current Device MemoryType. This is the MemoryType used by most MFEM classes when allocating m...
void EnsureMultTranspose() const
Ensures that the matrix is capable of performing MultTranspose(), AddMultTranspose(), and AbsMultTranspose().
const int * HostReadJ() const
virtual void PrintMatlab(std::ostream &out=mfem::out) const
Prints matrix in matlab format.
int CountSmallElems(double tol) const
Count the number of entries with |a_ij| <= tol.
void * HipMemFree(void *dptr)
Frees device memory.
static int SparseMatrixCount
const double * ReadData(bool on_dev=true) const
double InnerProduct(const Vector &x, const Vector &y) const
Compute y^t A x.
void SetDiagIdentity()
If a row contains only one diag entry of zero, set it to 1.
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 DiagScale(const Vector &b, Vector &x, double sc=1.0, bool use_abs_diag=false) const
x = sc b / A_ii. When use_abs_diag = true, |A_ii| is used.
void Sort()
Sorts the array in ascending order. This requires operator< to be defined for T.
int Capacity() const
Return the size of the allocated memory.
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 RAP(const DenseMatrix &A, const DenseMatrix &P, DenseMatrix &RAP)
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...
bool RowIsEmpty(const int row) const
void Reset()
Reset the memory to be empty, ensuring that Delete() will be a no-op.
bool Finalized() const
Returns whether or not CSR format has been finalized.
void Jacobi2(const Vector &b, const Vector &x0, Vector &x1, double sc=1.0) const
Biwise-OR of all CUDA backends.
void AddSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void Add(const int i, const int j, const double val)
Dynamic 2D array using row-major layout.
void SetSubMatrix(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
double * GetData() const
Return a pointer to the beginning of the Vector data.
Biwise-OR of all CPU backends.
void * HipMemAlloc(void **dptr, size_t bytes)
Allocates device memory.
T * HostWrite(Memory< T > &mem, int size)
Shortcut to Write(const Memory<T> &mem, int size, false)
virtual void MultTranspose(const Vector &x, Vector &y) const
Multiply a vector with the transposed matrix. y = At * x.
void SparseMatrixFunction(SparseMatrix &S, double(*f)(double))
Applies f() to each element of the matrix (after it is finalized).
void Swap(Array< T > &, Array< T > &)
const int * ReadI(bool on_dev=true) const
double _Get_(const int col) const
Read the value of an entry in the "current row". See SetColPtr().
void EliminateRowColDiag(int rc, double value)
Perform elimination and set the diagonal entry to the given value.
MemoryType
Memory types supported by MFEM.
void SetSubMatrixTranspose(const Array< int > &rows, const Array< int > &cols, const DenseMatrix &subm, int skip_zeros=1)
void Gauss_Seidel_forw(const Vector &x, Vector &y) const
Gauss-Seidel forward and backward iterations over a vector x.
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.
int ActualWidth() const
Returns the actual Width of the matrix.
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 Transpose(const Table &A, Table &At, int ncols_A_)
Transpose a Table.
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.
int Height() const
Get the height (size of output) of the Operator. Synonym with NumRows().
static bool Allows(unsigned long b_mask)
Return true if any of the backends in the backend mask, b_mask, are allowed.
RowNode ** Rows
Array of linked lists, one for every row. This array represents the linked list (LIL) storage format...
void Jacobi(const Vector &b, const Vector &x0, Vector &x1, double sc, bool use_abs_diag=false) const
const int * HostReadI() const
void BooleanMult(const Array< int > &x, Array< int > &y) const
y = A * x, treating all entries as booleans (zero=false, nonzero=true).
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.
void BuildTranspose() const
Build and store internally the transpose of this matrix which will be used in the methods AddMultTran...
const T * HostRead(const Memory< T > &mem, int size)
Shortcut to Read(const Memory<T> &mem, int size, false)
virtual double * ReadWrite(bool on_dev=true)
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), on_dev).
MemAlloc< RowNode, 1024 > RowNodeAlloc
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 ClearOwnerFlags() const
Clear the ownership flags for the host and device pointers, as well as any internal data allocated by...
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 AbsMult(const Vector &x, Vector &y) const
y = |A| * x, using entry-wise absolute values of matrix A
void PrintInfo(std::ostream &out) const
Print various sparse matrix statistics.
void EliminateCols(const Array< int > &cols, const Vector *x=NULL, Vector *b=NULL)
Eliminate all columns i for which cols[i] != 0.
void OverrideSize(int height_, int width_)
Sets the height and width of the matrix.
const int * ReadJ(bool on_dev=true) const
SparseMatrix & operator=(const SparseMatrix &rhs)
Assignment operator: deep copy.
void AbsMultTranspose(const Vector &x, Vector &y) const
y = |At| * x, using entry-wise absolute values of the transpose of matrix A
double infinity()
Define a shortcut for std::numeric_limits<double>::infinity()
SparseMatrix & operator*=(double a)
void ResetTranspose() const
void PrintCSR2(std::ostream &out) const
Prints a sparse matrix to stream out in CSR format.
int MaxRowSize() const
Returns the maximum number of elements among all rows.
int Size() const
Return the logical size of the array.
void SetRow(const int row, const Array< int > &cols, const Vector &srow)
cusparseSpMatDescr_t matA_descr
T * Write(bool on_dev=true)
Shortcut for mfem::Write(a.GetMemory(), a.Size(), on_dev).
void MakeRef(T *, int)
Make this Array a reference to a pointer.
double * ReadWriteData(bool on_dev=true)
int * ReadWriteJ(bool on_dev=true)
void PartAddMult(const Array< int > &rows, const Vector &x, Vector &y, const double a=1.0) const
cusparseDnVecDescr_t vecX_descr
int CheckFinite() const
Count the number of entries that are NOT finite, i.e. Inf or Nan.
SparseMatrix * MultAbstractSparseMatrix(const AbstractSparseMatrix &A, const AbstractSparseMatrix &B)
Matrix product of sparse matrices. A and B do not need to be CSR matrices.
void SetSize(int s)
Change the size of the DenseMatrix to s x 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 * CuMemAlloc(void **dptr, size_t bytes)
Allocates device memory and returns destination ptr.
virtual double * HostReadWrite()
Shortcut for mfem::ReadWrite(vec.GetMemory(), vec.Size(), false).
Set the diagonal value to zero.
int width
Dimension of the input / number of columns in the matrix.
MemoryType GetMemoryType() const
Return a MemoryType that is currently valid. If both the host and the device pointers are currently v...
void EliminateBC(const Array< int > &ess_dofs, DiagonalPolicy diag_policy)
Eliminate essential (Dirichlet) boundary conditions.
virtual void AddMultTranspose(const Vector &x, Vector &y, const double a=1.0) const
y += At * x (default) or y += a * At * x
void PartMult(const Array< int > &rows, const Vector &x, Vector &y) const
void Neg()
(*this) = -(*this)
void BooleanMultTranspose(const Array< int > &x, Array< int > &y) const
y = At * x, treating all entries as booleans (zero=false, nonzero=true).