xref: /petsc/src/mat/utils/axpy.c (revision 5f80ce2ab25dff0f4601e710601cbbcecf323266)
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