xref: /petsc/src/mat/utils/axpy.c (revision 606d414c6e034e02e67059b83ebaefc3ebe99698)
1 #ifdef PETSC_RCS_HEADER
2 static char vcid[] = "$Id: axpy.c,v 1.39 1999/05/04 20:33:40 balay Exp balay $";
3 #endif
4 
5 #include "src/mat/matimpl.h"  /*I   "mat.h"  I*/
6 
7 #undef __FUNC__
8 #define __FUNC__ "MatAXPY"
9 /*@
10    MatAXPY - Computes Y = a*X + Y.
11 
12    Collective on Mat
13 
14    Input Parameters:
15 +  X, Y - the matrices
16 -  a - the scalar multiplier
17 
18    Contributed by: Matthew Knepley
19 
20    Notes:
21    Since the current implementation of MatAXPY() uses MatGetRow() to access
22    matrix data, efficiency is somewhat limited.
23 
24    Level: intermediate
25 
26 .keywords: matrix, add
27 
28 .seealso: MatAYPX()
29  @*/
30 int MatAXPY(Scalar *a,Mat X,Mat Y)
31 {
32   int    m1,m2,n1,n2,i,*row,start,end,j,ncols,ierr;
33   Scalar *val,*vals;
34 
35   PetscFunctionBegin;
36   PetscValidHeaderSpecific(X,MAT_COOKIE);
37   PetscValidHeaderSpecific(Y,MAT_COOKIE);
38   PetscValidScalarPointer(a);
39 
40   MatGetSize(X,&m1,&n1);  MatGetSize(Y,&m2,&n2);
41   if (m1 != m2 || n1 != n2) SETERRQ4(PETSC_ERR_ARG_SIZ,0,"Non conforming matrix add: %d %d %d %d",m1,m2,n1,n2);
42 
43   if (X->ops->axpy) {
44     ierr = (*X->ops->axpy)(a,X,Y);CHKERRQ(ierr);
45   } else {
46     ierr = MatGetOwnershipRange(X,&start,&end);CHKERRQ(ierr);
47     if (*a == 1.0) {
48       for (i = start; i < end; i++) {
49         ierr = MatGetRow(X, i, &ncols, &row, &vals);CHKERRQ(ierr);
50         ierr = MatSetValues(Y, 1, &i, ncols, row, vals, ADD_VALUES);CHKERRQ(ierr);
51         ierr = MatRestoreRow(X, i, &ncols, &row, &vals);CHKERRQ(ierr);
52       }
53     } else {
54       vals = (Scalar *) PetscMalloc( (n1+1)*sizeof(Scalar) );CHKPTRQ(vals);
55       for ( i=start; i<end; i++ ) {
56         ierr = MatGetRow(X,i,&ncols,&row,&val);CHKERRQ(ierr);
57         for ( j=0; j<ncols; j++ ) {
58           vals[j] = (*a)*val[j];
59         }
60         ierr = MatSetValues(Y,1,&i,ncols,row,vals,ADD_VALUES);CHKERRQ(ierr);
61         ierr = MatRestoreRow(X,i,&ncols,&row,&val);CHKERRQ(ierr);
62       }
63       ierr = PetscFree(vals);CHKERRQ(ierr);
64     }
65     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
66     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
67   }
68   PetscFunctionReturn(0);
69 }
70 
71 #undef __FUNC__
72 #define __FUNC__ "MatShift"
73 /*@
74    MatShift - Computes Y =  Y + a I, where a is a scalar and I is the identity matrix.
75 
76    Collective on Mat
77 
78    Input Parameters:
79 +  Y - the matrices
80 -  a - the scalar
81 
82    Level: intermediate
83 
84 .keywords: matrix, add, shift
85 
86 .seealso: MatDiagonalShift()
87  @*/
88 int MatShift(Scalar *a,Mat Y)
89 {
90   int    i,start,end,ierr;
91 
92   PetscFunctionBegin;
93   PetscValidHeaderSpecific(Y,MAT_COOKIE);
94   PetscValidScalarPointer(a);
95   if (Y->ops->shift) {
96     ierr = (*Y->ops->shift)(a,Y);CHKERRQ(ierr);
97   } else {
98     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
99     for ( i=start; i<end; i++ ) {
100       ierr = MatSetValues(Y,1,&i,1,&i,a,ADD_VALUES);CHKERRQ(ierr);
101     }
102     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
103     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
104   }
105   PetscFunctionReturn(0);
106 }
107 
108 #undef __FUNC__
109 #define __FUNC__ "MatDiagonalShift"
110 /*@
111    MatDiagonalShift - Computes Y = Y + D, where D is a diagonal matrix
112    that is represented as a vector.
113 
114    Input Parameters:
115 +  Y - the input matrix
116 -  D - the diagonal matrix, represented as a vector
117 
118    Input Parameters:
119 .  Y - the shifted ouput matrix
120 
121    Collective on Mat and Vec
122 
123    Level: intermediate
124 
125 .keywords: matrix, add, shift, diagonal
126 
127 .seealso: MatShift()
128 @*/
129 int MatDiagonalShift(Mat Y,Vec D)
130 {
131   int    i,start,end,ierr;
132 
133   PetscFunctionBegin;
134   PetscValidHeaderSpecific(Y,MAT_COOKIE);
135   PetscValidHeaderSpecific(D,VEC_COOKIE);
136   if (Y->ops->shift) {
137     ierr = (*Y->ops->diagonalshift)(D,Y);CHKERRQ(ierr);
138   } else {
139     int    vstart,vend;
140     Scalar *v;
141     ierr = VecGetOwnershipRange(D,&vstart,&vend);CHKERRQ(ierr);
142     ierr = MatGetOwnershipRange(Y,&start,&end);CHKERRQ(ierr);
143     if (vstart != start || vend != end) {
144       SETERRQ4(PETSC_ERR_ARG_SIZ,0,"Vector ownership range not compatible with matrix: %d %d vec %d %d mat",vstart,vend,start,end);
145     }
146 
147     ierr = VecGetArray(D,&v);CHKERRQ(ierr);
148     for ( i=start; i<end; i++ ) {
149       ierr = MatSetValues(Y,1,&i,1,&i,v+i-start,ADD_VALUES);CHKERRQ(ierr);
150     }
151     ierr = VecRestoreArray(D,&v);CHKERRQ(ierr);
152     ierr = MatAssemblyBegin(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
153     ierr = MatAssemblyEnd(Y,MAT_FINAL_ASSEMBLY);CHKERRQ(ierr);
154   }
155   PetscFunctionReturn(0);
156 }
157 
158 #undef __FUNC__
159 #define __FUNC__ "MatAYPX"
160 /*@
161    MatAYPX - Computes Y = X + a*Y.
162 
163    Collective on Mat
164 
165    Input Parameters:
166 +  X,Y - the matrices
167 -  a - the scalar multiplier
168 
169    Contributed by: Matthew Knepley
170 
171    Notes:
172    This routine currently uses the MatAXPY() implementation.
173 
174    Level: intermediate
175 
176 .keywords: matrix, add
177 
178 .seealso: MatAXPY()
179  @*/
180 int MatAYPX(Scalar *a,Mat X,Mat Y)
181 {
182   Scalar one = 1.0;
183   int    mX, mY,nX, nY,ierr;
184 
185   PetscFunctionBegin;
186   PetscValidHeaderSpecific(X, MAT_COOKIE);
187   PetscValidHeaderSpecific(Y, MAT_COOKIE);
188   PetscValidScalarPointer(a);
189 
190   MatGetSize(X, &mX, &nX);
191   MatGetSize(X, &mY, &nY);
192   if (mX != mY || nX != nY) SETERRQ4(PETSC_ERR_ARG_SIZ,0,"Non conforming matrices: %d %d first %d %d second",mX,mY,nX,nY);
193 
194   ierr = MatScale(a, Y);CHKERRQ(ierr);
195   ierr = MatAXPY(&one, X, Y);CHKERRQ(ierr);
196   PetscFunctionReturn(0);
197 }
198