16f79c3a4SBarry Smith 2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 36f79c3a4SBarry Smith 4d71ae5a4SJacob Faibussowitsch static PetscErrorCode MatTransposeAXPY_Private(Mat Y, PetscScalar a, Mat X, MatStructure str, Mat T) 5d71ae5a4SJacob Faibussowitsch { 6d54c938cSPierre Jolivet Mat A, F; 75f80ce2aSJacob Faibussowitsch PetscErrorCode (*f)(Mat, Mat *); 8d54c938cSPierre Jolivet 9d54c938cSPierre Jolivet PetscFunctionBegin; 109566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)T, "MatTransposeGetMat_C", &f)); 11d54c938cSPierre Jolivet if (f) { 129566063dSJacob Faibussowitsch PetscCall(MatTransposeGetMat(T, &A)); 13d54c938cSPierre Jolivet if (T == X) { 14013e2dc7SBarry Smith PetscCall(PetscInfo(NULL, "Explicitly transposing X of type MATTRANSPOSEVIRTUAL to perform MatAXPY()\n")); 159566063dSJacob Faibussowitsch PetscCall(MatTranspose(A, MAT_INITIAL_MATRIX, &F)); 16d54c938cSPierre Jolivet A = Y; 17d54c938cSPierre Jolivet } else { 18013e2dc7SBarry Smith PetscCall(PetscInfo(NULL, "Transposing X because Y of type MATTRANSPOSEVIRTUAL to perform MatAXPY()\n")); 199566063dSJacob Faibussowitsch PetscCall(MatTranspose(X, MAT_INITIAL_MATRIX, &F)); 20d54c938cSPierre Jolivet } 21d54c938cSPierre Jolivet } else { 229566063dSJacob Faibussowitsch PetscCall(MatHermitianTransposeGetMat(T, &A)); 23d54c938cSPierre Jolivet if (T == X) { 24013e2dc7SBarry Smith PetscCall(PetscInfo(NULL, "Explicitly Hermitian transposing X of type MATHERITIANTRANSPOSEVIRTUAL to perform MatAXPY()\n")); 259566063dSJacob Faibussowitsch PetscCall(MatHermitianTranspose(A, MAT_INITIAL_MATRIX, &F)); 26d54c938cSPierre Jolivet A = Y; 27d54c938cSPierre Jolivet } else { 28013e2dc7SBarry Smith PetscCall(PetscInfo(NULL, "Hermitian transposing X because Y of type MATHERITIANTRANSPOSEVIRTUAL to perform MatAXPY()\n")); 299566063dSJacob Faibussowitsch PetscCall(MatHermitianTranspose(X, MAT_INITIAL_MATRIX, &F)); 30d54c938cSPierre Jolivet } 31d54c938cSPierre Jolivet } 329566063dSJacob Faibussowitsch PetscCall(MatAXPY(A, a, F, str)); 339566063dSJacob Faibussowitsch PetscCall(MatDestroy(&F)); 34d54c938cSPierre Jolivet PetscFunctionReturn(0); 35d54c938cSPierre Jolivet } 36d54c938cSPierre Jolivet 3706be10caSBarry Smith /*@ 3821c89e3eSBarry Smith MatAXPY - Computes Y = a*X + Y. 396f79c3a4SBarry Smith 40*c3339decSBarry Smith Logically Collective 41fee21e36SBarry Smith 4298a79cdbSBarry Smith Input Parameters: 43607cd303SBarry Smith + a - the scalar multiplier 44607cd303SBarry Smith . X - the first matrix 45607cd303SBarry Smith . Y - the second matrix 46531d0c6aSBarry Smith - str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN, UNKNOWN_NONZERO_PATTERN, or SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's) 4798a79cdbSBarry Smith 4811a5261eSBarry Smith Note: 4911a5261eSBarry Smith No operation is performed when a is zero. 50edf9a46cSStefano Zampini 512860a424SLois Curfman McInnes Level: intermediate 522860a424SLois Curfman McInnes 53db781477SPatrick Sanan .seealso: `MatAYPX()` 5406be10caSBarry Smith @*/ 55d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY(Mat Y, PetscScalar a, Mat X, MatStructure str) 56d71ae5a4SJacob Faibussowitsch { 57646531bbSStefano Zampini PetscInt M1, M2, N1, N2; 58c1ac3661SBarry Smith PetscInt m1, m2, n1, n2; 59a683ea4aSPierre Jolivet PetscBool sametype, transpose; 606f79c3a4SBarry Smith 613a40ed3dSBarry Smith PetscFunctionBegin; 620700a824SBarry Smith PetscValidHeaderSpecific(Y, MAT_CLASSID, 1); 63c5eb9154SBarry Smith PetscValidLogicalCollectiveScalar(Y, a, 2); 64646531bbSStefano Zampini PetscValidHeaderSpecific(X, MAT_CLASSID, 3); 65646531bbSStefano Zampini PetscCheckSameComm(Y, 1, X, 3); 669566063dSJacob Faibussowitsch PetscCall(MatGetSize(X, &M1, &N1)); 679566063dSJacob Faibussowitsch PetscCall(MatGetSize(Y, &M2, &N2)); 689566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(X, &m1, &n1)); 699566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Y, &m2, &n2)); 702c71b3e2SJacob Faibussowitsch PetscCheck(M1 == M2 && N1 == N2, PetscObjectComm((PetscObject)Y), PETSC_ERR_ARG_SIZ, "Non conforming matrix add: global sizes X %" PetscInt_FMT " x %" PetscInt_FMT ", Y %" PetscInt_FMT " x %" PetscInt_FMT, M1, N1, M2, N2); 712c71b3e2SJacob Faibussowitsch PetscCheck(m1 == m2 && n1 == n2, PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Non conforming matrix add: local sizes X %" PetscInt_FMT " x %" PetscInt_FMT ", Y %" PetscInt_FMT " x %" PetscInt_FMT, m1, n1, m2, n2); 722c71b3e2SJacob Faibussowitsch PetscCheck(Y->assembled, PetscObjectComm((PetscObject)Y), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix (Y)"); 732c71b3e2SJacob Faibussowitsch PetscCheck(X->assembled, PetscObjectComm((PetscObject)X), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix (X)"); 74edf9a46cSStefano Zampini if (a == (PetscScalar)0.0) PetscFunctionReturn(0); 75edf9a46cSStefano Zampini if (Y == X) { 769566063dSJacob Faibussowitsch PetscCall(MatScale(Y, 1.0 + a)); 77edf9a46cSStefano Zampini PetscFunctionReturn(0); 78edf9a46cSStefano Zampini } 79013e2dc7SBarry Smith PetscCall(PetscObjectObjectTypeCompare((PetscObject)X, (PetscObject)Y, &sametype)); 809566063dSJacob Faibussowitsch PetscCall(PetscLogEventBegin(MAT_AXPY, Y, 0, 0, 0)); 8193c87e65SStefano Zampini if (Y->ops->axpy && (sametype || X->ops->axpy == Y->ops->axpy)) { 82dbbe0bcdSBarry Smith PetscUseTypeMethod(Y, axpy, a, X, str); 83d4bb536fSBarry Smith } else { 84013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompareAny((PetscObject)X, &transpose, MATTRANSPOSEVIRTUAL, MATHERMITIANTRANSPOSEVIRTUAL, "")); 85a683ea4aSPierre Jolivet if (transpose) { 869566063dSJacob Faibussowitsch PetscCall(MatTransposeAXPY_Private(Y, a, X, str, X)); 87a683ea4aSPierre Jolivet } else { 88013e2dc7SBarry Smith PetscCall(PetscObjectTypeCompareAny((PetscObject)Y, &transpose, MATTRANSPOSEVIRTUAL, MATHERMITIANTRANSPOSEVIRTUAL, "")); 89a683ea4aSPierre Jolivet if (transpose) { 909566063dSJacob Faibussowitsch PetscCall(MatTransposeAXPY_Private(Y, a, X, str, Y)); 91a683ea4aSPierre Jolivet } else { 929566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic(Y, a, X, str)); 93607cd303SBarry Smith } 94a683ea4aSPierre Jolivet } 95a683ea4aSPierre Jolivet } 969566063dSJacob Faibussowitsch PetscCall(PetscLogEventEnd(MAT_AXPY, Y, 0, 0, 0)); 97607cd303SBarry Smith PetscFunctionReturn(0); 98607cd303SBarry Smith } 99607cd303SBarry Smith 100d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_Basic_Preallocate(Mat Y, Mat X, Mat *B) 101d71ae5a4SJacob Faibussowitsch { 10227afe9e8SStefano Zampini PetscErrorCode (*preall)(Mat, Mat, Mat *) = NULL; 103646531bbSStefano Zampini 104646531bbSStefano Zampini PetscFunctionBegin; 105646531bbSStefano Zampini /* look for any available faster alternative to the general preallocator */ 1069566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction((PetscObject)Y, "MatAXPYGetPreallocation_C", &preall)); 107646531bbSStefano Zampini if (preall) { 1089566063dSJacob Faibussowitsch PetscCall((*preall)(Y, X, B)); 109646531bbSStefano Zampini } else { /* Use MatPrellocator, assumes same row-col distribution */ 110646531bbSStefano Zampini Mat preallocator; 111646531bbSStefano Zampini PetscInt r, rstart, rend; 112646531bbSStefano Zampini PetscInt m, n, M, N; 113646531bbSStefano Zampini 1149566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(Y)); 1159566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 1169566063dSJacob Faibussowitsch PetscCall(MatGetSize(Y, &M, &N)); 1179566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Y, &m, &n)); 1189566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), &preallocator)); 1199566063dSJacob Faibussowitsch PetscCall(MatSetType(preallocator, MATPREALLOCATOR)); 1209566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(preallocator, Y->rmap, Y->cmap)); 1219566063dSJacob Faibussowitsch PetscCall(MatSetUp(preallocator)); 1229566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(preallocator, &rstart, &rend)); 123646531bbSStefano Zampini for (r = rstart; r < rend; ++r) { 124646531bbSStefano Zampini PetscInt ncols; 125646531bbSStefano Zampini const PetscInt *row; 126646531bbSStefano Zampini const PetscScalar *vals; 127646531bbSStefano Zampini 1289566063dSJacob Faibussowitsch PetscCall(MatGetRow(Y, r, &ncols, &row, &vals)); 1299566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, 1, &r, ncols, row, vals, INSERT_VALUES)); 1309566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Y, r, &ncols, &row, &vals)); 1319566063dSJacob Faibussowitsch PetscCall(MatGetRow(X, r, &ncols, &row, &vals)); 1329566063dSJacob Faibussowitsch PetscCall(MatSetValues(preallocator, 1, &r, ncols, row, vals, INSERT_VALUES)); 1339566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(X, r, &ncols, &row, &vals)); 134646531bbSStefano Zampini } 1359566063dSJacob Faibussowitsch PetscCall(MatSetOption(preallocator, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 1369566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(preallocator, MAT_FINAL_ASSEMBLY)); 1379566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(preallocator, MAT_FINAL_ASSEMBLY)); 1389566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(Y)); 1399566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 140646531bbSStefano Zampini 1419566063dSJacob Faibussowitsch PetscCall(MatCreate(PetscObjectComm((PetscObject)Y), B)); 1429566063dSJacob Faibussowitsch PetscCall(MatSetType(*B, ((PetscObject)Y)->type_name)); 1439566063dSJacob Faibussowitsch PetscCall(MatSetLayouts(*B, Y->rmap, Y->cmap)); 1449566063dSJacob Faibussowitsch PetscCall(MatPreallocatorPreallocate(preallocator, PETSC_FALSE, *B)); 1459566063dSJacob Faibussowitsch PetscCall(MatDestroy(&preallocator)); 146646531bbSStefano Zampini } 147646531bbSStefano Zampini PetscFunctionReturn(0); 148646531bbSStefano Zampini } 149646531bbSStefano Zampini 150d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_Basic(Mat Y, PetscScalar a, Mat X, MatStructure str) 151d71ae5a4SJacob Faibussowitsch { 152be705e3aSPierre Jolivet PetscBool isshell, isdense, isnest; 153edf9a46cSStefano Zampini 154edf9a46cSStefano Zampini PetscFunctionBegin; 1559566063dSJacob Faibussowitsch PetscCall(MatIsShell(Y, &isshell)); 156edf9a46cSStefano Zampini if (isshell) { /* MatShell has special support for AXPY */ 157edf9a46cSStefano Zampini PetscErrorCode (*f)(Mat, PetscScalar, Mat, MatStructure); 158edf9a46cSStefano Zampini 1599566063dSJacob Faibussowitsch PetscCall(MatGetOperation(Y, MATOP_AXPY, (void (**)(void)) & f)); 160edf9a46cSStefano Zampini if (f) { 1619566063dSJacob Faibussowitsch PetscCall((*f)(Y, a, X, str)); 162edf9a46cSStefano Zampini PetscFunctionReturn(0); 163edf9a46cSStefano Zampini } 164edf9a46cSStefano Zampini } 16593c87e65SStefano Zampini /* no need to preallocate if Y is dense */ 1669566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)Y, &isdense, MATSEQDENSE, MATMPIDENSE, "")); 167be705e3aSPierre Jolivet if (isdense) { 1689566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)X, MATNEST, &isnest)); 169be705e3aSPierre Jolivet if (isnest) { 1709566063dSJacob Faibussowitsch PetscCall(MatAXPY_Dense_Nest(Y, a, X)); 171be705e3aSPierre Jolivet PetscFunctionReturn(0); 172be705e3aSPierre Jolivet } 173be705e3aSPierre Jolivet if (str == DIFFERENT_NONZERO_PATTERN || str == UNKNOWN_NONZERO_PATTERN) str = SUBSET_NONZERO_PATTERN; 174be705e3aSPierre Jolivet } 175a6ab3590SBarry Smith if (str != DIFFERENT_NONZERO_PATTERN && str != UNKNOWN_NONZERO_PATTERN) { 176edf9a46cSStefano Zampini PetscInt i, start, end, j, ncols, m, n; 17738baddfdSBarry Smith const PetscInt *row; 178b3cc6726SBarry Smith PetscScalar *val; 179b3cc6726SBarry Smith const PetscScalar *vals; 180607cd303SBarry Smith 1819566063dSJacob Faibussowitsch PetscCall(MatGetSize(X, &m, &n)); 1829566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(X, &start, &end)); 1839566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 184f4df32b1SMatthew Knepley if (a == 1.0) { 185d4bb536fSBarry Smith for (i = start; i < end; i++) { 1869566063dSJacob Faibussowitsch PetscCall(MatGetRow(X, i, &ncols, &row, &vals)); 1879566063dSJacob Faibussowitsch PetscCall(MatSetValues(Y, 1, &i, ncols, row, vals, ADD_VALUES)); 1889566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(X, i, &ncols, &row, &vals)); 189d4bb536fSBarry Smith } 190d4bb536fSBarry Smith } else { 19121a3365eSStefano Zampini PetscInt vs = 100; 19221a3365eSStefano Zampini /* realloc if needed, as this function may be used in parallel */ 1939566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vs, &val)); 19406be10caSBarry Smith for (i = start; i < end; i++) { 1959566063dSJacob Faibussowitsch PetscCall(MatGetRow(X, i, &ncols, &row, &vals)); 19621a3365eSStefano Zampini if (vs < ncols) { 19721a3365eSStefano Zampini vs = PetscMin(2 * ncols, n); 1989566063dSJacob Faibussowitsch PetscCall(PetscRealloc(vs * sizeof(*val), &val)); 1996f79c3a4SBarry Smith } 20021a3365eSStefano Zampini for (j = 0; j < ncols; j++) val[j] = a * vals[j]; 2019566063dSJacob Faibussowitsch PetscCall(MatSetValues(Y, 1, &i, ncols, row, val, ADD_VALUES)); 2029566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(X, i, &ncols, &row, &vals)); 2036f79c3a4SBarry Smith } 2049566063dSJacob Faibussowitsch PetscCall(PetscFree(val)); 205d4bb536fSBarry Smith } 2069566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 2079566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Y, MAT_FINAL_ASSEMBLY)); 2089566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Y, MAT_FINAL_ASSEMBLY)); 209edf9a46cSStefano Zampini } else { 210edf9a46cSStefano Zampini Mat B; 211edf9a46cSStefano Zampini 2129566063dSJacob Faibussowitsch PetscCall(MatAXPY_Basic_Preallocate(Y, X, &B)); 2139566063dSJacob Faibussowitsch PetscCall(MatAXPY_BasicWithPreallocation(B, Y, a, X, str)); 2149566063dSJacob Faibussowitsch PetscCall(MatHeaderMerge(Y, &B)); 215edf9a46cSStefano Zampini } 2163a40ed3dSBarry Smith PetscFunctionReturn(0); 2176f79c3a4SBarry Smith } 218052efed2SBarry Smith 219d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAXPY_BasicWithPreallocation(Mat B, Mat Y, PetscScalar a, Mat X, MatStructure str) 220d71ae5a4SJacob Faibussowitsch { 221ec7775f6SShri Abhyankar PetscInt i, start, end, j, ncols, m, n; 222ec7775f6SShri Abhyankar const PetscInt *row; 223ec7775f6SShri Abhyankar PetscScalar *val; 224ec7775f6SShri Abhyankar const PetscScalar *vals; 225ec7775f6SShri Abhyankar 226ec7775f6SShri Abhyankar PetscFunctionBegin; 2279566063dSJacob Faibussowitsch PetscCall(MatGetSize(X, &m, &n)); 2289566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(X, &start, &end)); 2299566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(Y)); 2309566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(X)); 231ec7775f6SShri Abhyankar if (a == 1.0) { 232ec7775f6SShri Abhyankar for (i = start; i < end; i++) { 2339566063dSJacob Faibussowitsch PetscCall(MatGetRow(Y, i, &ncols, &row, &vals)); 2349566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, ncols, row, vals, ADD_VALUES)); 2359566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Y, i, &ncols, &row, &vals)); 236ec7775f6SShri Abhyankar 2379566063dSJacob Faibussowitsch PetscCall(MatGetRow(X, i, &ncols, &row, &vals)); 2389566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, ncols, row, vals, ADD_VALUES)); 2399566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(X, i, &ncols, &row, &vals)); 240ec7775f6SShri Abhyankar } 241ec7775f6SShri Abhyankar } else { 24221a3365eSStefano Zampini PetscInt vs = 100; 24321a3365eSStefano Zampini /* realloc if needed, as this function may be used in parallel */ 2449566063dSJacob Faibussowitsch PetscCall(PetscMalloc1(vs, &val)); 245ec7775f6SShri Abhyankar for (i = start; i < end; i++) { 2469566063dSJacob Faibussowitsch PetscCall(MatGetRow(Y, i, &ncols, &row, &vals)); 2479566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, ncols, row, vals, ADD_VALUES)); 2489566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(Y, i, &ncols, &row, &vals)); 249ec7775f6SShri Abhyankar 2509566063dSJacob Faibussowitsch PetscCall(MatGetRow(X, i, &ncols, &row, &vals)); 25121a3365eSStefano Zampini if (vs < ncols) { 25221a3365eSStefano Zampini vs = PetscMin(2 * ncols, n); 2539566063dSJacob Faibussowitsch PetscCall(PetscRealloc(vs * sizeof(*val), &val)); 254ec7775f6SShri Abhyankar } 25521a3365eSStefano Zampini for (j = 0; j < ncols; j++) val[j] = a * vals[j]; 2569566063dSJacob Faibussowitsch PetscCall(MatSetValues(B, 1, &i, ncols, row, val, ADD_VALUES)); 2579566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(X, i, &ncols, &row, &vals)); 258ec7775f6SShri Abhyankar } 2599566063dSJacob Faibussowitsch PetscCall(PetscFree(val)); 260ec7775f6SShri Abhyankar } 2619566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(Y)); 2629566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(X)); 2639566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(B, MAT_FINAL_ASSEMBLY)); 2649566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(B, MAT_FINAL_ASSEMBLY)); 265ec7775f6SShri Abhyankar PetscFunctionReturn(0); 266ec7775f6SShri Abhyankar } 267ec7775f6SShri Abhyankar 268052efed2SBarry Smith /*@ 26987828ca2SBarry Smith MatShift - Computes Y = Y + a I, where a is a PetscScalar and I is the identity matrix. 270052efed2SBarry Smith 271*c3339decSBarry Smith Neighbor-wise Collective 272fee21e36SBarry Smith 27398a79cdbSBarry Smith Input Parameters: 27498a79cdbSBarry Smith + Y - the matrices 27587828ca2SBarry Smith - a - the PetscScalar 27698a79cdbSBarry Smith 2772860a424SLois Curfman McInnes Level: intermediate 2782860a424SLois Curfman McInnes 27995452b02SPatrick Sanan Notes: 28084e19e3eSJunchao Zhang If Y is a rectangular matrix, the shift is done on the main diagonal Y_{ii} of the matrix (https://en.wikipedia.org/wiki/Main_diagonal) 28184e19e3eSJunchao Zhang 28295452b02SPatrick Sanan If the matrix Y is missing some diagonal entries this routine can be very slow. To make it fast one should initially 2836f33a894SBarry Smith fill the matrix so that all diagonal entries have a value (with a value of zero for those locations that would not have an 284edf9a46cSStefano Zampini entry). No operation is performed when a is zero. 2856f33a894SBarry Smith 2860c0fd78eSBarry Smith To form Y = Y + diag(V) use MatDiagonalSet() 2870c0fd78eSBarry Smith 288db781477SPatrick Sanan .seealso: `MatDiagonalSet()`, `MatScale()`, `MatDiagonalScale()` 289052efed2SBarry Smith @*/ 290d71ae5a4SJacob Faibussowitsch PetscErrorCode MatShift(Mat Y, PetscScalar a) 291d71ae5a4SJacob Faibussowitsch { 2923a40ed3dSBarry Smith PetscFunctionBegin; 2930700a824SBarry Smith PetscValidHeaderSpecific(Y, MAT_CLASSID, 1); 2945f80ce2aSJacob Faibussowitsch PetscCheck(Y->assembled, PetscObjectComm((PetscObject)Y), PETSC_ERR_ARG_WRONGSTATE, "Not for unassembled matrix"); 2955f80ce2aSJacob Faibussowitsch PetscCheck(!Y->factortype, PetscObjectComm((PetscObject)Y), PETSC_ERR_ARG_WRONGSTATE, "Not for factored matrix"); 2964994cf47SJed Brown MatCheckPreallocated(Y, 1); 2971b71c1a7SBarry Smith if (a == 0.0) PetscFunctionReturn(0); 298b50b34bdSBarry Smith 299dbbe0bcdSBarry Smith if (Y->ops->shift) PetscUseTypeMethod(Y, shift, a); 3009566063dSJacob Faibussowitsch else PetscCall(MatShift_Basic(Y, a)); 3017d68702bSBarry Smith 3029566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 3033a40ed3dSBarry Smith PetscFunctionReturn(0); 304052efed2SBarry Smith } 3056d84be18SBarry Smith 306d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet_Default(Mat Y, Vec D, InsertMode is) 307d71ae5a4SJacob Faibussowitsch { 30867576b8bSBarry Smith PetscInt i, start, end; 309fa2e578bSStefano Zampini const PetscScalar *v; 31009f38230SBarry Smith 31109f38230SBarry Smith PetscFunctionBegin; 3129566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(Y, &start, &end)); 3139566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(D, &v)); 31448a46eb9SPierre Jolivet for (i = start; i < end; i++) PetscCall(MatSetValues(Y, 1, &i, 1, &i, v + i - start, is)); 3159566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(D, &v)); 3169566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(Y, MAT_FINAL_ASSEMBLY)); 3179566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(Y, MAT_FINAL_ASSEMBLY)); 31809f38230SBarry Smith PetscFunctionReturn(0); 31909f38230SBarry Smith } 32009f38230SBarry Smith 3216d84be18SBarry Smith /*@ 322f56f2b3fSBarry Smith MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix 323f56f2b3fSBarry Smith that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is 324f56f2b3fSBarry Smith INSERT_VALUES. 3256d84be18SBarry Smith 326*c3339decSBarry Smith Neighbor-wise Collective 32748e586daSJose E. Roman 3286d84be18SBarry Smith Input Parameters: 32998a79cdbSBarry Smith + Y - the input matrix 330f56f2b3fSBarry Smith . D - the diagonal matrix, represented as a vector 331f56f2b3fSBarry Smith - i - INSERT_VALUES or ADD_VALUES 3326d84be18SBarry Smith 33311a5261eSBarry Smith Note: 33495452b02SPatrick Sanan If the matrix Y is missing some diagonal entries this routine can be very slow. To make it fast one should initially 3356f33a894SBarry Smith fill the matrix so that all diagonal entries have a value (with a value of zero for those locations that would not have an 3366f33a894SBarry Smith entry). 3376f33a894SBarry Smith 3382860a424SLois Curfman McInnes Level: intermediate 3392860a424SLois Curfman McInnes 340db781477SPatrick Sanan .seealso: `MatShift()`, `MatScale()`, `MatDiagonalScale()` 3416d84be18SBarry Smith @*/ 342d71ae5a4SJacob Faibussowitsch PetscErrorCode MatDiagonalSet(Mat Y, Vec D, InsertMode is) 343d71ae5a4SJacob Faibussowitsch { 34467576b8bSBarry Smith PetscInt matlocal, veclocal; 3456d84be18SBarry Smith 3463a40ed3dSBarry Smith PetscFunctionBegin; 3470700a824SBarry Smith PetscValidHeaderSpecific(Y, MAT_CLASSID, 1); 3480700a824SBarry Smith PetscValidHeaderSpecific(D, VEC_CLASSID, 2); 3499566063dSJacob Faibussowitsch PetscCall(MatGetLocalSize(Y, &matlocal, NULL)); 3509566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(D, &veclocal)); 3515f80ce2aSJacob Faibussowitsch PetscCheck(matlocal == veclocal, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Number local rows of matrix %" PetscInt_FMT " does not match that of vector for diagonal %" PetscInt_FMT, matlocal, veclocal); 352dbbe0bcdSBarry Smith if (Y->ops->diagonalset) PetscUseTypeMethod(Y, diagonalset, D, is); 353dbbe0bcdSBarry Smith else PetscCall(MatDiagonalSet_Default(Y, D, is)); 3549566063dSJacob Faibussowitsch PetscCall(PetscObjectStateIncrease((PetscObject)Y)); 3553a40ed3dSBarry Smith PetscFunctionReturn(0); 3566d84be18SBarry Smith } 357d4bb536fSBarry Smith 358d4bb536fSBarry Smith /*@ 35904aac2b0SHong Zhang MatAYPX - Computes Y = a*Y + X. 360d4bb536fSBarry Smith 3613f9fe445SBarry Smith Logically on Mat 362fee21e36SBarry Smith 36398a79cdbSBarry Smith Input Parameters: 36404aac2b0SHong Zhang + a - the PetscScalar multiplier 36504aac2b0SHong Zhang . Y - the first matrix 36604aac2b0SHong Zhang . X - the second matrix 367531d0c6aSBarry Smith - str - either SAME_NONZERO_PATTERN, DIFFERENT_NONZERO_PATTERN, UNKNOWN_NONZERO_PATTERN, or SUBSET_NONZERO_PATTERN (nonzeros of X is a subset of Y's) 368d4bb536fSBarry Smith 3692860a424SLois Curfman McInnes Level: intermediate 3702860a424SLois Curfman McInnes 371db781477SPatrick Sanan .seealso: `MatAXPY()` 372d4bb536fSBarry Smith @*/ 373d71ae5a4SJacob Faibussowitsch PetscErrorCode MatAYPX(Mat Y, PetscScalar a, Mat X, MatStructure str) 374d71ae5a4SJacob Faibussowitsch { 3753a40ed3dSBarry Smith PetscFunctionBegin; 3769566063dSJacob Faibussowitsch PetscCall(MatScale(Y, a)); 3779566063dSJacob Faibussowitsch PetscCall(MatAXPY(Y, 1.0, X, str)); 3783a40ed3dSBarry Smith PetscFunctionReturn(0); 379d4bb536fSBarry Smith } 380b0a32e0cSBarry Smith 381b0a32e0cSBarry Smith /*@ 3820bacdadaSStefano Zampini MatComputeOperator - Computes the explicit matrix 383b0a32e0cSBarry Smith 384*c3339decSBarry Smith Collective 385b0a32e0cSBarry Smith 386d8d19677SJose E. Roman Input Parameters: 387186a3e20SStefano Zampini + inmat - the matrix 388186a3e20SStefano Zampini - mattype - the matrix type for the explicit operator 389b0a32e0cSBarry Smith 390b0a32e0cSBarry Smith Output Parameter: 391a5b23f4aSJose E. Roman . mat - the explicit operator 392b0a32e0cSBarry Smith 39311a5261eSBarry Smith Note: 394186a3e20SStefano Zampini This computation is done by applying the operators to columns of the identity matrix. 395186a3e20SStefano Zampini This routine is costly in general, and is recommended for use only with relatively small systems. 396186a3e20SStefano Zampini Currently, this routine uses a dense matrix format if mattype == NULL. 397b0a32e0cSBarry Smith 398b0a32e0cSBarry Smith Level: advanced 399b0a32e0cSBarry Smith 400b0a32e0cSBarry Smith @*/ 401d71ae5a4SJacob Faibussowitsch PetscErrorCode MatComputeOperator(Mat inmat, MatType mattype, Mat *mat) 402d71ae5a4SJacob Faibussowitsch { 403b0a32e0cSBarry Smith PetscFunctionBegin; 4040700a824SBarry Smith PetscValidHeaderSpecific(inmat, MAT_CLASSID, 1); 405186a3e20SStefano Zampini PetscValidPointer(mat, 3); 4069566063dSJacob Faibussowitsch PetscCall(MatConvert_Shell(inmat, mattype ? mattype : MATDENSE, MAT_INITIAL_MATRIX, mat)); 40724f910e3SHong Zhang PetscFunctionReturn(0); 40824f910e3SHong Zhang } 4094325cce7SMatthew G Knepley 4104325cce7SMatthew G Knepley /*@ 4110bacdadaSStefano Zampini MatComputeOperatorTranspose - Computes the explicit matrix representation of 412f3b1f45cSBarry Smith a give matrix that can apply MatMultTranspose() 413f3b1f45cSBarry Smith 414*c3339decSBarry Smith Collective 415f3b1f45cSBarry Smith 4166b867d5aSJose E. Roman Input Parameters: 4176b867d5aSJose E. Roman + inmat - the matrix 4186b867d5aSJose E. Roman - mattype - the matrix type for the explicit operator 419f3b1f45cSBarry Smith 420f3b1f45cSBarry Smith Output Parameter: 421a5b23f4aSJose E. Roman . mat - the explicit operator transposed 422f3b1f45cSBarry Smith 42311a5261eSBarry Smith Note: 424186a3e20SStefano Zampini This computation is done by applying the transpose of the operator to columns of the identity matrix. 425186a3e20SStefano Zampini This routine is costly in general, and is recommended for use only with relatively small systems. 426186a3e20SStefano Zampini Currently, this routine uses a dense matrix format if mattype == NULL. 427f3b1f45cSBarry Smith 428f3b1f45cSBarry Smith Level: advanced 429f3b1f45cSBarry Smith 430f3b1f45cSBarry Smith @*/ 431d71ae5a4SJacob Faibussowitsch PetscErrorCode MatComputeOperatorTranspose(Mat inmat, MatType mattype, Mat *mat) 432d71ae5a4SJacob Faibussowitsch { 433186a3e20SStefano Zampini Mat A; 434f3b1f45cSBarry Smith 435f3b1f45cSBarry Smith PetscFunctionBegin; 436f3b1f45cSBarry Smith PetscValidHeaderSpecific(inmat, MAT_CLASSID, 1); 437186a3e20SStefano Zampini PetscValidPointer(mat, 3); 4389566063dSJacob Faibussowitsch PetscCall(MatCreateTranspose(inmat, &A)); 4399566063dSJacob Faibussowitsch PetscCall(MatConvert_Shell(A, mattype ? mattype : MATDENSE, MAT_INITIAL_MATRIX, mat)); 4409566063dSJacob Faibussowitsch PetscCall(MatDestroy(&A)); 441f3b1f45cSBarry Smith PetscFunctionReturn(0); 442f3b1f45cSBarry Smith } 443f3b1f45cSBarry Smith 444f3b1f45cSBarry Smith /*@ 4454325cce7SMatthew G Knepley MatChop - Set all values in the matrix less than the tolerance to zero 4464325cce7SMatthew G Knepley 4474325cce7SMatthew G Knepley Input Parameters: 4484325cce7SMatthew G Knepley + A - The matrix 4494325cce7SMatthew G Knepley - tol - The zero tolerance 4504325cce7SMatthew G Knepley 4514325cce7SMatthew G Knepley Output Parameters: 4524325cce7SMatthew G Knepley . A - The chopped matrix 4534325cce7SMatthew G Knepley 4544325cce7SMatthew G Knepley Level: intermediate 4554325cce7SMatthew G Knepley 456db781477SPatrick Sanan .seealso: `MatCreate()`, `MatZeroEntries()` 4573fc99919SSatish Balay @*/ 458d71ae5a4SJacob Faibussowitsch PetscErrorCode MatChop(Mat A, PetscReal tol) 459d71ae5a4SJacob Faibussowitsch { 460038df967SPierre Jolivet Mat a; 4614325cce7SMatthew G Knepley PetscScalar *newVals; 462cf5d3338SPierre Jolivet PetscInt *newCols, rStart, rEnd, numRows, maxRows, r, colMax = 0; 463038df967SPierre Jolivet PetscBool flg; 4644325cce7SMatthew G Knepley 4654325cce7SMatthew G Knepley PetscFunctionBegin; 4669566063dSJacob Faibussowitsch PetscCall(PetscObjectBaseTypeCompareAny((PetscObject)A, &flg, MATSEQDENSE, MATMPIDENSE, "")); 467038df967SPierre Jolivet if (flg) { 4689566063dSJacob Faibussowitsch PetscCall(MatDenseGetLocalMatrix(A, &a)); 4699566063dSJacob Faibussowitsch PetscCall(MatDenseGetLDA(a, &r)); 4709566063dSJacob Faibussowitsch PetscCall(MatGetSize(a, &rStart, &rEnd)); 4719566063dSJacob Faibussowitsch PetscCall(MatDenseGetArray(a, &newVals)); 472038df967SPierre Jolivet for (; colMax < rEnd; ++colMax) { 473ad540459SPierre Jolivet for (maxRows = 0; maxRows < rStart; ++maxRows) newVals[maxRows + colMax * r] = PetscAbsScalar(newVals[maxRows + colMax * r]) < tol ? 0.0 : newVals[maxRows + colMax * r]; 474038df967SPierre Jolivet } 4759566063dSJacob Faibussowitsch PetscCall(MatDenseRestoreArray(a, &newVals)); 476038df967SPierre Jolivet } else { 4779566063dSJacob Faibussowitsch PetscCall(MatGetOwnershipRange(A, &rStart, &rEnd)); 4789566063dSJacob Faibussowitsch PetscCall(MatGetRowUpperTriangular(A)); 4794325cce7SMatthew G Knepley for (r = rStart; r < rEnd; ++r) { 4804325cce7SMatthew G Knepley PetscInt ncols; 4814325cce7SMatthew G Knepley 4829566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, r, &ncols, NULL, NULL)); 4835f80ce2aSJacob Faibussowitsch colMax = PetscMax(colMax, ncols); 4849566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, r, &ncols, NULL, NULL)); 4854325cce7SMatthew G Knepley } 4864325cce7SMatthew G Knepley numRows = rEnd - rStart; 4871c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&numRows, &maxRows, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)A))); 4889566063dSJacob Faibussowitsch PetscCall(PetscMalloc2(colMax, &newCols, colMax, &newVals)); 4899566063dSJacob Faibussowitsch PetscCall(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &flg)); /* cache user-defined value */ 4909566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 491cf5d3338SPierre Jolivet /* short-circuit code in MatAssemblyBegin() and MatAssemblyEnd() */ 492cf5d3338SPierre Jolivet /* that are potentially called many times depending on the distribution of A */ 4934325cce7SMatthew G Knepley for (r = rStart; r < rStart + maxRows; ++r) { 4944325cce7SMatthew G Knepley const PetscScalar *vals; 4954325cce7SMatthew G Knepley const PetscInt *cols; 496fad45679SMatthew G. Knepley PetscInt ncols, newcols, c; 4974325cce7SMatthew G Knepley 4984325cce7SMatthew G Knepley if (r < rEnd) { 4999566063dSJacob Faibussowitsch PetscCall(MatGetRow(A, r, &ncols, &cols, &vals)); 5004325cce7SMatthew G Knepley for (c = 0; c < ncols; ++c) { 5014325cce7SMatthew G Knepley newCols[c] = cols[c]; 5024325cce7SMatthew G Knepley newVals[c] = PetscAbsScalar(vals[c]) < tol ? 0.0 : vals[c]; 5034325cce7SMatthew G Knepley } 504fad45679SMatthew G. Knepley newcols = ncols; 5059566063dSJacob Faibussowitsch PetscCall(MatRestoreRow(A, r, &ncols, &cols, &vals)); 5069566063dSJacob Faibussowitsch PetscCall(MatSetValues(A, 1, &r, newcols, newCols, newVals, INSERT_VALUES)); 5074325cce7SMatthew G Knepley } 5089566063dSJacob Faibussowitsch PetscCall(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 5099566063dSJacob Faibussowitsch PetscCall(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 5104325cce7SMatthew G Knepley } 5119566063dSJacob Faibussowitsch PetscCall(MatRestoreRowUpperTriangular(A)); 5129566063dSJacob Faibussowitsch PetscCall(PetscFree2(newCols, newVals)); 5139566063dSJacob Faibussowitsch PetscCall(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, flg)); /* reset option to its user-defined value */ 514038df967SPierre Jolivet } 5154325cce7SMatthew G Knepley PetscFunctionReturn(0); 5164325cce7SMatthew G Knepley } 517