16f79c3a4SBarry Smith 2af0996ceSBarry Smith #include <petsc/private/matimpl.h> /*I "petscmat.h" I*/ 36f79c3a4SBarry Smith 4d54c938cSPierre Jolivet static PetscErrorCode MatTransposeAXPY_Private(Mat Y,PetscScalar a,Mat X,MatStructure str,Mat T) 5d54c938cSPierre Jolivet { 6d54c938cSPierre Jolivet Mat A,F; 7*5f80ce2aSJacob Faibussowitsch PetscErrorCode (*f)(Mat,Mat*); 8d54c938cSPierre Jolivet 9d54c938cSPierre Jolivet PetscFunctionBegin; 10*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQueryFunction((PetscObject)T,"MatTransposeGetMat_C",&f)); 11d54c938cSPierre Jolivet if (f) { 12*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeGetMat(T,&A)); 13d54c938cSPierre Jolivet if (T == X) { 14*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Explicitly transposing X of type MATTRANSPOSEMAT to perform MatAXPY()\n")); 15*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(A,MAT_INITIAL_MATRIX,&F)); 16d54c938cSPierre Jolivet A = Y; 17d54c938cSPierre Jolivet } else { 18*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Transposing X because Y of type MATTRANSPOSEMAT to perform MatAXPY()\n")); 19*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTranspose(X,MAT_INITIAL_MATRIX,&F)); 20d54c938cSPierre Jolivet } 21d54c938cSPierre Jolivet } else { 22*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatHermitianTransposeGetMat(T,&A)); 23d54c938cSPierre Jolivet if (T == X) { 24*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Explicitly Hermitian transposing X of type MATTRANSPOSEMAT to perform MatAXPY()\n")); 25*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatHermitianTranspose(A,MAT_INITIAL_MATRIX,&F)); 26d54c938cSPierre Jolivet A = Y; 27d54c938cSPierre Jolivet } else { 28*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscInfo(NULL,"Hermitian transposing X because Y of type MATTRANSPOSEMAT to perform MatAXPY()\n")); 29*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatHermitianTranspose(X,MAT_INITIAL_MATRIX,&F)); 30d54c938cSPierre Jolivet } 31d54c938cSPierre Jolivet } 32*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(A,a,F,str)); 33*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&F)); 34d54c938cSPierre Jolivet PetscFunctionReturn(0); 35d54c938cSPierre Jolivet } 36d54c938cSPierre Jolivet 3706be10caSBarry Smith /*@ 3821c89e3eSBarry Smith MatAXPY - Computes Y = a*X + Y. 396f79c3a4SBarry Smith 403f9fe445SBarry Smith Logically Collective on Mat 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 48edf9a46cSStefano Zampini Notes: No operation is performed when a is zero. 49edf9a46cSStefano Zampini 502860a424SLois Curfman McInnes Level: intermediate 512860a424SLois Curfman McInnes 522860a424SLois Curfman McInnes .seealso: MatAYPX() 5306be10caSBarry Smith @*/ 547087cfbeSBarry Smith PetscErrorCode MatAXPY(Mat Y,PetscScalar a,Mat X,MatStructure str) 556f79c3a4SBarry Smith { 56646531bbSStefano Zampini PetscInt M1,M2,N1,N2; 57c1ac3661SBarry Smith PetscInt m1,m2,n1,n2; 58a683ea4aSPierre Jolivet MatType t1,t2; 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); 66*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(X,&M1,&N1)); 67*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Y,&M2,&N2)); 68*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(X,&m1,&n1)); 69*5f80ce2aSJacob Faibussowitsch CHKERRQ(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) { 76*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Y,1.0 + a)); 77edf9a46cSStefano Zampini PetscFunctionReturn(0); 78edf9a46cSStefano Zampini } 79*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetType(X,&t1)); 80*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetType(Y,&t2)); 81*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(t1,t2,&sametype)); 82*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventBegin(MAT_AXPY,Y,0,0,0)); 8393c87e65SStefano Zampini if (Y->ops->axpy && (sametype || X->ops->axpy == Y->ops->axpy)) { 84*5f80ce2aSJacob Faibussowitsch CHKERRQ((*Y->ops->axpy)(Y,a,X,str)); 85d4bb536fSBarry Smith } else { 86*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(t1,MATTRANSPOSEMAT,&transpose)); 87a683ea4aSPierre Jolivet if (transpose) { 88*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeAXPY_Private(Y,a,X,str,X)); 89a683ea4aSPierre Jolivet } else { 90*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscStrcmp(t2,MATTRANSPOSEMAT,&transpose)); 91a683ea4aSPierre Jolivet if (transpose) { 92*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatTransposeAXPY_Private(Y,a,X,str,Y)); 93a683ea4aSPierre Jolivet } else { 94*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY_Basic(Y,a,X,str)); 95607cd303SBarry Smith } 96a683ea4aSPierre Jolivet } 97a683ea4aSPierre Jolivet } 98*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscLogEventEnd(MAT_AXPY,Y,0,0,0)); 99607cd303SBarry Smith PetscFunctionReturn(0); 100607cd303SBarry Smith } 101607cd303SBarry Smith 102646531bbSStefano Zampini PetscErrorCode MatAXPY_Basic_Preallocate(Mat Y, Mat X, Mat *B) 103646531bbSStefano Zampini { 10427afe9e8SStefano Zampini PetscErrorCode (*preall)(Mat,Mat,Mat*) = NULL; 105646531bbSStefano Zampini 106646531bbSStefano Zampini PetscFunctionBegin; 107646531bbSStefano Zampini /* look for any available faster alternative to the general preallocator */ 108*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectQueryFunction((PetscObject)Y,"MatAXPYGetPreallocation_C",&preall)); 109646531bbSStefano Zampini if (preall) { 110*5f80ce2aSJacob Faibussowitsch CHKERRQ((*preall)(Y,X,B)); 111646531bbSStefano Zampini } else { /* Use MatPrellocator, assumes same row-col distribution */ 112646531bbSStefano Zampini Mat preallocator; 113646531bbSStefano Zampini PetscInt r,rstart,rend; 114646531bbSStefano Zampini PetscInt m,n,M,N; 115646531bbSStefano Zampini 116*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(Y)); 117*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(X)); 118*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(Y,&M,&N)); 119*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(Y,&m,&n)); 120*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)Y),&preallocator)); 121*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(preallocator,MATPREALLOCATOR)); 122*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLayouts(preallocator,Y->rmap,Y->cmap)); 123*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetUp(preallocator)); 124*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(preallocator,&rstart,&rend)); 125646531bbSStefano Zampini for (r = rstart; r < rend; ++r) { 126646531bbSStefano Zampini PetscInt ncols; 127646531bbSStefano Zampini const PetscInt *row; 128646531bbSStefano Zampini const PetscScalar *vals; 129646531bbSStefano Zampini 130*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(Y,r,&ncols,&row,&vals)); 131*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(preallocator,1,&r,ncols,row,vals,INSERT_VALUES)); 132*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(Y,r,&ncols,&row,&vals)); 133*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(X,r,&ncols,&row,&vals)); 134*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(preallocator,1,&r,ncols,row,vals,INSERT_VALUES)); 135*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(X,r,&ncols,&row,&vals)); 136646531bbSStefano Zampini } 137*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(preallocator,MAT_NO_OFF_PROC_ENTRIES,PETSC_TRUE)); 138*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(preallocator,MAT_FINAL_ASSEMBLY)); 139*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(preallocator,MAT_FINAL_ASSEMBLY)); 140*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(Y)); 141*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(X)); 142646531bbSStefano Zampini 143*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreate(PetscObjectComm((PetscObject)Y),B)); 144*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetType(*B,((PetscObject)Y)->type_name)); 145*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetLayouts(*B,Y->rmap,Y->cmap)); 146*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatPreallocatorPreallocate(preallocator,PETSC_FALSE,*B)); 147*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&preallocator)); 148646531bbSStefano Zampini } 149646531bbSStefano Zampini PetscFunctionReturn(0); 150646531bbSStefano Zampini } 151646531bbSStefano Zampini 152f4df32b1SMatthew Knepley PetscErrorCode MatAXPY_Basic(Mat Y,PetscScalar a,Mat X,MatStructure str) 153607cd303SBarry Smith { 154be705e3aSPierre Jolivet PetscBool isshell,isdense,isnest; 155edf9a46cSStefano Zampini 156edf9a46cSStefano Zampini PetscFunctionBegin; 157*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatIsShell(Y,&isshell)); 158edf9a46cSStefano Zampini if (isshell) { /* MatShell has special support for AXPY */ 159edf9a46cSStefano Zampini PetscErrorCode (*f)(Mat,PetscScalar,Mat,MatStructure); 160edf9a46cSStefano Zampini 161*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOperation(Y,MATOP_AXPY,(void (**)(void))&f)); 162edf9a46cSStefano Zampini if (f) { 163*5f80ce2aSJacob Faibussowitsch CHKERRQ((*f)(Y,a,X,str)); 164edf9a46cSStefano Zampini PetscFunctionReturn(0); 165edf9a46cSStefano Zampini } 166edf9a46cSStefano Zampini } 16793c87e65SStefano Zampini /* no need to preallocate if Y is dense */ 168*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectBaseTypeCompareAny((PetscObject)Y,&isdense,MATSEQDENSE,MATMPIDENSE,"")); 169be705e3aSPierre Jolivet if (isdense) { 170*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectTypeCompare((PetscObject)X,MATNEST,&isnest)); 171be705e3aSPierre Jolivet if (isnest) { 172*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY_Dense_Nest(Y,a,X)); 173be705e3aSPierre Jolivet PetscFunctionReturn(0); 174be705e3aSPierre Jolivet } 175be705e3aSPierre Jolivet if (str == DIFFERENT_NONZERO_PATTERN || str == UNKNOWN_NONZERO_PATTERN) str = SUBSET_NONZERO_PATTERN; 176be705e3aSPierre Jolivet } 177a6ab3590SBarry Smith if (str != DIFFERENT_NONZERO_PATTERN && str != UNKNOWN_NONZERO_PATTERN) { 178edf9a46cSStefano Zampini PetscInt i,start,end,j,ncols,m,n; 17938baddfdSBarry Smith const PetscInt *row; 180b3cc6726SBarry Smith PetscScalar *val; 181b3cc6726SBarry Smith const PetscScalar *vals; 182607cd303SBarry Smith 183*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(X,&m,&n)); 184*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(X,&start,&end)); 185*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(X)); 186f4df32b1SMatthew Knepley if (a == 1.0) { 187d4bb536fSBarry Smith for (i = start; i < end; i++) { 188*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(X,i,&ncols,&row,&vals)); 189*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES)); 190*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(X,i,&ncols,&row,&vals)); 191d4bb536fSBarry Smith } 192d4bb536fSBarry Smith } else { 19321a3365eSStefano Zampini PetscInt vs = 100; 19421a3365eSStefano Zampini /* realloc if needed, as this function may be used in parallel */ 195*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(vs,&val)); 19606be10caSBarry Smith for (i=start; i<end; i++) { 197*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(X,i,&ncols,&row,&vals)); 19821a3365eSStefano Zampini if (vs < ncols) { 19921a3365eSStefano Zampini vs = PetscMin(2*ncols,n); 200*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRealloc(vs*sizeof(*val),&val)); 2016f79c3a4SBarry Smith } 20221a3365eSStefano Zampini for (j=0; j<ncols; j++) val[j] = a*vals[j]; 203*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(Y,1,&i,ncols,row,val,ADD_VALUES)); 204*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(X,i,&ncols,&row,&vals)); 2056f79c3a4SBarry Smith } 206*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(val)); 207d4bb536fSBarry Smith } 208*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(X)); 209*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY)); 210*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY)); 211edf9a46cSStefano Zampini } else { 212edf9a46cSStefano Zampini Mat B; 213edf9a46cSStefano Zampini 214*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY_Basic_Preallocate(Y,X,&B)); 215*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY_BasicWithPreallocation(B,Y,a,X,str)); 216*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatHeaderMerge(Y,&B)); 217edf9a46cSStefano Zampini } 2183a40ed3dSBarry Smith PetscFunctionReturn(0); 2196f79c3a4SBarry Smith } 220052efed2SBarry Smith 221ec7775f6SShri Abhyankar PetscErrorCode MatAXPY_BasicWithPreallocation(Mat B,Mat Y,PetscScalar a,Mat X,MatStructure str) 222ec7775f6SShri Abhyankar { 223ec7775f6SShri Abhyankar PetscInt i,start,end,j,ncols,m,n; 224ec7775f6SShri Abhyankar const PetscInt *row; 225ec7775f6SShri Abhyankar PetscScalar *val; 226ec7775f6SShri Abhyankar const PetscScalar *vals; 227ec7775f6SShri Abhyankar 228ec7775f6SShri Abhyankar PetscFunctionBegin; 229*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(X,&m,&n)); 230*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(X,&start,&end)); 231*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(Y)); 232*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(X)); 233ec7775f6SShri Abhyankar if (a == 1.0) { 234ec7775f6SShri Abhyankar for (i = start; i < end; i++) { 235*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(Y,i,&ncols,&row,&vals)); 236*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES)); 237*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(Y,i,&ncols,&row,&vals)); 238ec7775f6SShri Abhyankar 239*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(X,i,&ncols,&row,&vals)); 240*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES)); 241*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(X,i,&ncols,&row,&vals)); 242ec7775f6SShri Abhyankar } 243ec7775f6SShri Abhyankar } else { 24421a3365eSStefano Zampini PetscInt vs = 100; 24521a3365eSStefano Zampini /* realloc if needed, as this function may be used in parallel */ 246*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc1(vs,&val)); 247ec7775f6SShri Abhyankar for (i=start; i<end; i++) { 248*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(Y,i,&ncols,&row,&vals)); 249*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&i,ncols,row,vals,ADD_VALUES)); 250*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(Y,i,&ncols,&row,&vals)); 251ec7775f6SShri Abhyankar 252*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(X,i,&ncols,&row,&vals)); 25321a3365eSStefano Zampini if (vs < ncols) { 25421a3365eSStefano Zampini vs = PetscMin(2*ncols,n); 255*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscRealloc(vs*sizeof(*val),&val)); 256ec7775f6SShri Abhyankar } 25721a3365eSStefano Zampini for (j=0; j<ncols; j++) val[j] = a*vals[j]; 258*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(B,1,&i,ncols,row,val,ADD_VALUES)); 259*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(X,i,&ncols,&row,&vals)); 260ec7775f6SShri Abhyankar } 261*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree(val)); 262ec7775f6SShri Abhyankar } 263*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(Y)); 264*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(X)); 265*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(B,MAT_FINAL_ASSEMBLY)); 266*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(B,MAT_FINAL_ASSEMBLY)); 267ec7775f6SShri Abhyankar PetscFunctionReturn(0); 268ec7775f6SShri Abhyankar } 269ec7775f6SShri Abhyankar 270052efed2SBarry Smith /*@ 27187828ca2SBarry Smith MatShift - Computes Y = Y + a I, where a is a PetscScalar and I is the identity matrix. 272052efed2SBarry Smith 2733f9fe445SBarry Smith Neighbor-wise Collective on Mat 274fee21e36SBarry Smith 27598a79cdbSBarry Smith Input Parameters: 27698a79cdbSBarry Smith + Y - the matrices 27787828ca2SBarry Smith - a - the PetscScalar 27898a79cdbSBarry Smith 2792860a424SLois Curfman McInnes Level: intermediate 2802860a424SLois Curfman McInnes 28195452b02SPatrick Sanan Notes: 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 2880c0fd78eSBarry Smith .seealso: MatDiagonalSet(), MatScale(), MatDiagonalScale() 289052efed2SBarry Smith @*/ 2907087cfbeSBarry Smith PetscErrorCode MatShift(Mat Y,PetscScalar a) 291052efed2SBarry Smith { 2923a40ed3dSBarry Smith PetscFunctionBegin; 2930700a824SBarry Smith PetscValidHeaderSpecific(Y,MAT_CLASSID,1); 294*5f80ce2aSJacob Faibussowitsch PetscCheck(Y->assembled,PetscObjectComm((PetscObject)Y),PETSC_ERR_ARG_WRONGSTATE,"Not for unassembled matrix"); 295*5f80ce2aSJacob 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 299*5f80ce2aSJacob Faibussowitsch if (Y->ops->shift) CHKERRQ((*Y->ops->shift)(Y,a)); 300*5f80ce2aSJacob Faibussowitsch else CHKERRQ(MatShift_Basic(Y,a)); 3017d68702bSBarry Smith 302*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateIncrease((PetscObject)Y)); 3033a40ed3dSBarry Smith PetscFunctionReturn(0); 304052efed2SBarry Smith } 3056d84be18SBarry Smith 3067087cfbeSBarry Smith PetscErrorCode MatDiagonalSet_Default(Mat Y,Vec D,InsertMode is) 30709f38230SBarry Smith { 30867576b8bSBarry Smith PetscInt i,start,end; 309fa2e578bSStefano Zampini const PetscScalar *v; 31009f38230SBarry Smith 31109f38230SBarry Smith PetscFunctionBegin; 312*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(Y,&start,&end)); 313*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetArrayRead(D,&v)); 31409f38230SBarry Smith for (i=start; i<end; i++) { 315*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(Y,1,&i,1,&i,v+i-start,is)); 31609f38230SBarry Smith } 317*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecRestoreArrayRead(D,&v)); 318*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY)); 319*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY)); 32009f38230SBarry Smith PetscFunctionReturn(0); 32109f38230SBarry Smith } 32209f38230SBarry Smith 3236d84be18SBarry Smith /*@ 324f56f2b3fSBarry Smith MatDiagonalSet - Computes Y = Y + D, where D is a diagonal matrix 325f56f2b3fSBarry Smith that is represented as a vector. Or Y[i,i] = D[i] if InsertMode is 326f56f2b3fSBarry Smith INSERT_VALUES. 3276d84be18SBarry Smith 32848e586daSJose E. Roman Neighbor-wise Collective on Mat 32948e586daSJose E. Roman 3306d84be18SBarry Smith Input Parameters: 33198a79cdbSBarry Smith + Y - the input matrix 332f56f2b3fSBarry Smith . D - the diagonal matrix, represented as a vector 333f56f2b3fSBarry Smith - i - INSERT_VALUES or ADD_VALUES 3346d84be18SBarry Smith 33595452b02SPatrick Sanan Notes: 33695452b02SPatrick Sanan If the matrix Y is missing some diagonal entries this routine can be very slow. To make it fast one should initially 3376f33a894SBarry 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 3386f33a894SBarry Smith entry). 3396f33a894SBarry Smith 3402860a424SLois Curfman McInnes Level: intermediate 3412860a424SLois Curfman McInnes 3420c0fd78eSBarry Smith .seealso: MatShift(), MatScale(), MatDiagonalScale() 3436d84be18SBarry Smith @*/ 3447087cfbeSBarry Smith PetscErrorCode MatDiagonalSet(Mat Y,Vec D,InsertMode is) 3456d84be18SBarry Smith { 34667576b8bSBarry Smith PetscInt matlocal,veclocal; 3476d84be18SBarry Smith 3483a40ed3dSBarry Smith PetscFunctionBegin; 3490700a824SBarry Smith PetscValidHeaderSpecific(Y,MAT_CLASSID,1); 3500700a824SBarry Smith PetscValidHeaderSpecific(D,VEC_CLASSID,2); 351*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetLocalSize(Y,&matlocal,NULL)); 352*5f80ce2aSJacob Faibussowitsch CHKERRQ(VecGetLocalSize(D,&veclocal)); 353*5f80ce2aSJacob 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); 354f56f2b3fSBarry Smith if (Y->ops->diagonalset) { 355*5f80ce2aSJacob Faibussowitsch CHKERRQ((*Y->ops->diagonalset)(Y,D,is)); 35694d884c6SBarry Smith } else { 357*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDiagonalSet_Default(Y,D,is)); 3586d84be18SBarry Smith } 359*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectStateIncrease((PetscObject)Y)); 3603a40ed3dSBarry Smith PetscFunctionReturn(0); 3616d84be18SBarry Smith } 362d4bb536fSBarry Smith 363d4bb536fSBarry Smith /*@ 36404aac2b0SHong Zhang MatAYPX - Computes Y = a*Y + X. 365d4bb536fSBarry Smith 3663f9fe445SBarry Smith Logically on Mat 367fee21e36SBarry Smith 36898a79cdbSBarry Smith Input Parameters: 36904aac2b0SHong Zhang + a - the PetscScalar multiplier 37004aac2b0SHong Zhang . Y - the first matrix 37104aac2b0SHong Zhang . X - the second matrix 372531d0c6aSBarry 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) 373d4bb536fSBarry Smith 3742860a424SLois Curfman McInnes Level: intermediate 3752860a424SLois Curfman McInnes 3762860a424SLois Curfman McInnes .seealso: MatAXPY() 377d4bb536fSBarry Smith @*/ 3787087cfbeSBarry Smith PetscErrorCode MatAYPX(Mat Y,PetscScalar a,Mat X,MatStructure str) 379d4bb536fSBarry Smith { 3803a40ed3dSBarry Smith PetscFunctionBegin; 381*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatScale(Y,a)); 382*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAXPY(Y,1.0,X,str)); 3833a40ed3dSBarry Smith PetscFunctionReturn(0); 384d4bb536fSBarry Smith } 385b0a32e0cSBarry Smith 386b0a32e0cSBarry Smith /*@ 3870bacdadaSStefano Zampini MatComputeOperator - Computes the explicit matrix 388b0a32e0cSBarry Smith 389b0a32e0cSBarry Smith Collective on Mat 390b0a32e0cSBarry Smith 391d8d19677SJose E. Roman Input Parameters: 392186a3e20SStefano Zampini + inmat - the matrix 393186a3e20SStefano Zampini - mattype - the matrix type for the explicit operator 394b0a32e0cSBarry Smith 395b0a32e0cSBarry Smith Output Parameter: 396a5b23f4aSJose E. Roman . mat - the explicit operator 397b0a32e0cSBarry Smith 398b0a32e0cSBarry Smith Notes: 399186a3e20SStefano Zampini This computation is done by applying the operators to columns of the identity matrix. 400186a3e20SStefano Zampini This routine is costly in general, and is recommended for use only with relatively small systems. 401186a3e20SStefano Zampini Currently, this routine uses a dense matrix format if mattype == NULL. 402b0a32e0cSBarry Smith 403b0a32e0cSBarry Smith Level: advanced 404b0a32e0cSBarry Smith 405b0a32e0cSBarry Smith @*/ 4060bacdadaSStefano Zampini PetscErrorCode MatComputeOperator(Mat inmat,MatType mattype,Mat *mat) 407b0a32e0cSBarry Smith { 408b0a32e0cSBarry Smith PetscFunctionBegin; 4090700a824SBarry Smith PetscValidHeaderSpecific(inmat,MAT_CLASSID,1); 410186a3e20SStefano Zampini PetscValidPointer(mat,3); 411*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert_Shell(inmat,mattype ? mattype : MATDENSE,MAT_INITIAL_MATRIX,mat)); 41224f910e3SHong Zhang PetscFunctionReturn(0); 41324f910e3SHong Zhang } 4144325cce7SMatthew G Knepley 4154325cce7SMatthew G Knepley /*@ 4160bacdadaSStefano Zampini MatComputeOperatorTranspose - Computes the explicit matrix representation of 417f3b1f45cSBarry Smith a give matrix that can apply MatMultTranspose() 418f3b1f45cSBarry Smith 419f3b1f45cSBarry Smith Collective on Mat 420f3b1f45cSBarry Smith 4216b867d5aSJose E. Roman Input Parameters: 4226b867d5aSJose E. Roman + inmat - the matrix 4236b867d5aSJose E. Roman - mattype - the matrix type for the explicit operator 424f3b1f45cSBarry Smith 425f3b1f45cSBarry Smith Output Parameter: 426a5b23f4aSJose E. Roman . mat - the explicit operator transposed 427f3b1f45cSBarry Smith 428f3b1f45cSBarry Smith Notes: 429186a3e20SStefano Zampini This computation is done by applying the transpose of the operator to columns of the identity matrix. 430186a3e20SStefano Zampini This routine is costly in general, and is recommended for use only with relatively small systems. 431186a3e20SStefano Zampini Currently, this routine uses a dense matrix format if mattype == NULL. 432f3b1f45cSBarry Smith 433f3b1f45cSBarry Smith Level: advanced 434f3b1f45cSBarry Smith 435f3b1f45cSBarry Smith @*/ 4360bacdadaSStefano Zampini PetscErrorCode MatComputeOperatorTranspose(Mat inmat,MatType mattype,Mat *mat) 437f3b1f45cSBarry Smith { 438186a3e20SStefano Zampini Mat A; 439f3b1f45cSBarry Smith 440f3b1f45cSBarry Smith PetscFunctionBegin; 441f3b1f45cSBarry Smith PetscValidHeaderSpecific(inmat,MAT_CLASSID,1); 442186a3e20SStefano Zampini PetscValidPointer(mat,3); 443*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatCreateTranspose(inmat,&A)); 444*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatConvert_Shell(A,mattype ? mattype : MATDENSE,MAT_INITIAL_MATRIX,mat)); 445*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDestroy(&A)); 446f3b1f45cSBarry Smith PetscFunctionReturn(0); 447f3b1f45cSBarry Smith } 448f3b1f45cSBarry Smith 449f3b1f45cSBarry Smith /*@ 4504325cce7SMatthew G Knepley MatChop - Set all values in the matrix less than the tolerance to zero 4514325cce7SMatthew G Knepley 4524325cce7SMatthew G Knepley Input Parameters: 4534325cce7SMatthew G Knepley + A - The matrix 4544325cce7SMatthew G Knepley - tol - The zero tolerance 4554325cce7SMatthew G Knepley 4564325cce7SMatthew G Knepley Output Parameters: 4574325cce7SMatthew G Knepley . A - The chopped matrix 4584325cce7SMatthew G Knepley 4594325cce7SMatthew G Knepley Level: intermediate 4604325cce7SMatthew G Knepley 4614325cce7SMatthew G Knepley .seealso: MatCreate(), MatZeroEntries() 4623fc99919SSatish Balay @*/ 4634325cce7SMatthew G Knepley PetscErrorCode MatChop(Mat A, PetscReal tol) 4644325cce7SMatthew G Knepley { 465038df967SPierre Jolivet Mat a; 4664325cce7SMatthew G Knepley PetscScalar *newVals; 467cf5d3338SPierre Jolivet PetscInt *newCols, rStart, rEnd, numRows, maxRows, r, colMax = 0; 468038df967SPierre Jolivet PetscBool flg; 4694325cce7SMatthew G Knepley 4704325cce7SMatthew G Knepley PetscFunctionBegin; 471*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscObjectBaseTypeCompareAny((PetscObject)A, &flg, MATSEQDENSE, MATMPIDENSE, "")); 472038df967SPierre Jolivet if (flg) { 473*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetLocalMatrix(A, &a)); 474*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetLDA(a, &r)); 475*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetSize(a, &rStart, &rEnd)); 476*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseGetArray(a, &newVals)); 477038df967SPierre Jolivet for (; colMax < rEnd; ++colMax) { 478038df967SPierre Jolivet for (maxRows = 0; maxRows < rStart; ++maxRows) { 479038df967SPierre Jolivet newVals[maxRows + colMax * r] = PetscAbsScalar(newVals[maxRows + colMax * r]) < tol ? 0.0 : newVals[maxRows + colMax * r]; 480038df967SPierre Jolivet } 481038df967SPierre Jolivet } 482*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatDenseRestoreArray(a, &newVals)); 483038df967SPierre Jolivet } else { 484*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOwnershipRange(A, &rStart, &rEnd)); 485*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRowUpperTriangular(A)); 4864325cce7SMatthew G Knepley for (r = rStart; r < rEnd; ++r) { 4874325cce7SMatthew G Knepley PetscInt ncols; 4884325cce7SMatthew G Knepley 489*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A, r, &ncols, NULL, NULL)); 490*5f80ce2aSJacob Faibussowitsch colMax = PetscMax(colMax, ncols); 491*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A, r, &ncols, NULL, NULL)); 4924325cce7SMatthew G Knepley } 4934325cce7SMatthew G Knepley numRows = rEnd - rStart; 494*5f80ce2aSJacob Faibussowitsch CHKERRMPI(MPIU_Allreduce(&numRows, &maxRows, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)A))); 495*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscMalloc2(colMax, &newCols, colMax, &newVals)); 496*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetOption(A, MAT_NO_OFF_PROC_ENTRIES, &flg)); /* cache user-defined value */ 497*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, PETSC_TRUE)); 498cf5d3338SPierre Jolivet /* short-circuit code in MatAssemblyBegin() and MatAssemblyEnd() */ 499cf5d3338SPierre Jolivet /* that are potentially called many times depending on the distribution of A */ 5004325cce7SMatthew G Knepley for (r = rStart; r < rStart+maxRows; ++r) { 5014325cce7SMatthew G Knepley const PetscScalar *vals; 5024325cce7SMatthew G Knepley const PetscInt *cols; 503fad45679SMatthew G. Knepley PetscInt ncols, newcols, c; 5044325cce7SMatthew G Knepley 5054325cce7SMatthew G Knepley if (r < rEnd) { 506*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatGetRow(A, r, &ncols, &cols, &vals)); 5074325cce7SMatthew G Knepley for (c = 0; c < ncols; ++c) { 5084325cce7SMatthew G Knepley newCols[c] = cols[c]; 5094325cce7SMatthew G Knepley newVals[c] = PetscAbsScalar(vals[c]) < tol ? 0.0 : vals[c]; 5104325cce7SMatthew G Knepley } 511fad45679SMatthew G. Knepley newcols = ncols; 512*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRow(A, r, &ncols, &cols, &vals)); 513*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetValues(A, 1, &r, newcols, newCols, newVals, INSERT_VALUES)); 5144325cce7SMatthew G Knepley } 515*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyBegin(A, MAT_FINAL_ASSEMBLY)); 516*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatAssemblyEnd(A, MAT_FINAL_ASSEMBLY)); 5174325cce7SMatthew G Knepley } 518*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatRestoreRowUpperTriangular(A)); 519*5f80ce2aSJacob Faibussowitsch CHKERRQ(PetscFree2(newCols, newVals)); 520*5f80ce2aSJacob Faibussowitsch CHKERRQ(MatSetOption(A, MAT_NO_OFF_PROC_ENTRIES, flg)); /* reset option to its user-defined value */ 521038df967SPierre Jolivet } 5224325cce7SMatthew G Knepley PetscFunctionReturn(0); 5234325cce7SMatthew G Knepley } 524