Actual source code: normmh.c


  2: #include <petsc/private/matimpl.h>

  4: typedef struct {
  5:   Mat         A;
  6:   Vec         w,left,right,leftwork,rightwork;
  7:   PetscScalar scale;
  8: } Mat_Normal;

 10: PetscErrorCode MatScaleHermitian_Normal(Mat inA,PetscScalar scale)
 11: {
 12:   Mat_Normal *a = (Mat_Normal*)inA->data;

 14:   a->scale *= scale;
 15:   return 0;
 16: }

 18: PetscErrorCode MatDiagonalScaleHermitian_Normal(Mat inA,Vec left,Vec right)
 19: {
 20:   Mat_Normal     *a = (Mat_Normal*)inA->data;

 22:   if (left) {
 23:     if (!a->left) {
 24:       VecDuplicate(left,&a->left);
 25:       VecCopy(left,a->left);
 26:     } else {
 27:       VecPointwiseMult(a->left,left,a->left);
 28:     }
 29:   }
 30:   if (right) {
 31:     if (!a->right) {
 32:       VecDuplicate(right,&a->right);
 33:       VecCopy(right,a->right);
 34:     } else {
 35:       VecPointwiseMult(a->right,right,a->right);
 36:     }
 37:   }
 38:   return 0;
 39: }

 41: PetscErrorCode MatMultHermitian_Normal(Mat N,Vec x,Vec y)
 42: {
 43:   Mat_Normal     *Na = (Mat_Normal*)N->data;
 44:   Vec            in;

 46:   in = x;
 47:   if (Na->right) {
 48:     if (!Na->rightwork) {
 49:       VecDuplicate(Na->right,&Na->rightwork);
 50:     }
 51:     VecPointwiseMult(Na->rightwork,Na->right,in);
 52:     in   = Na->rightwork;
 53:   }
 54:   MatMult(Na->A,in,Na->w);
 55:   MatMultHermitianTranspose(Na->A,Na->w,y);
 56:   if (Na->left) {
 57:     VecPointwiseMult(y,Na->left,y);
 58:   }
 59:   VecScale(y,Na->scale);
 60:   return 0;
 61: }

 63: PetscErrorCode MatMultHermitianAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
 64: {
 65:   Mat_Normal     *Na = (Mat_Normal*)N->data;
 66:   Vec            in;

 68:   in = v1;
 69:   if (Na->right) {
 70:     if (!Na->rightwork) {
 71:       VecDuplicate(Na->right,&Na->rightwork);
 72:     }
 73:     VecPointwiseMult(Na->rightwork,Na->right,in);
 74:     in   = Na->rightwork;
 75:   }
 76:   MatMult(Na->A,in,Na->w);
 77:   VecScale(Na->w,Na->scale);
 78:   if (Na->left) {
 79:     MatMultHermitianTranspose(Na->A,Na->w,v3);
 80:     VecPointwiseMult(v3,Na->left,v3);
 81:     VecAXPY(v3,1.0,v2);
 82:   } else {
 83:     MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);
 84:   }
 85:   return 0;
 86: }

 88: PetscErrorCode MatMultHermitianTranspose_Normal(Mat N,Vec x,Vec y)
 89: {
 90:   Mat_Normal     *Na = (Mat_Normal*)N->data;
 91:   Vec            in;

 93:   in = x;
 94:   if (Na->left) {
 95:     if (!Na->leftwork) {
 96:       VecDuplicate(Na->left,&Na->leftwork);
 97:     }
 98:     VecPointwiseMult(Na->leftwork,Na->left,in);
 99:     in   = Na->leftwork;
100:   }
101:   MatMult(Na->A,in,Na->w);
102:   MatMultHermitianTranspose(Na->A,Na->w,y);
103:   if (Na->right) {
104:     VecPointwiseMult(y,Na->right,y);
105:   }
106:   VecScale(y,Na->scale);
107:   return 0;
108: }

110: PetscErrorCode MatMultHermitianTransposeAdd_Normal(Mat N,Vec v1,Vec v2,Vec v3)
111: {
112:   Mat_Normal     *Na = (Mat_Normal*)N->data;
113:   Vec            in;

115:   in = v1;
116:   if (Na->left) {
117:     if (!Na->leftwork) {
118:       VecDuplicate(Na->left,&Na->leftwork);
119:     }
120:     VecPointwiseMult(Na->leftwork,Na->left,in);
121:     in   = Na->leftwork;
122:   }
123:   MatMult(Na->A,in,Na->w);
124:   VecScale(Na->w,Na->scale);
125:   if (Na->right) {
126:     MatMultHermitianTranspose(Na->A,Na->w,v3);
127:     VecPointwiseMult(v3,Na->right,v3);
128:     VecAXPY(v3,1.0,v2);
129:   } else {
130:     MatMultHermitianTransposeAdd(Na->A,Na->w,v2,v3);
131:   }
132:   return 0;
133: }

135: PetscErrorCode MatDestroyHermitian_Normal(Mat N)
136: {
137:   Mat_Normal     *Na = (Mat_Normal*)N->data;

139:   MatDestroy(&Na->A);
140:   VecDestroy(&Na->w);
141:   VecDestroy(&Na->left);
142:   VecDestroy(&Na->right);
143:   VecDestroy(&Na->leftwork);
144:   VecDestroy(&Na->rightwork);
145:   PetscFree(N->data);
146:   PetscObjectComposeFunction((PetscObject)N,"MatNormalGetMatHermitian_C",NULL);
147:   return 0;
148: }

150: /*
151:       Slow, nonscalable version
152: */
153: PetscErrorCode MatGetDiagonalHermitian_Normal(Mat N,Vec v)
154: {
155:   Mat_Normal        *Na = (Mat_Normal*)N->data;
156:   Mat               A   = Na->A;
157:   PetscInt          i,j,rstart,rend,nnz;
158:   const PetscInt    *cols;
159:   PetscScalar       *diag,*work,*values;
160:   const PetscScalar *mvalues;

162:   PetscMalloc2(A->cmap->N,&diag,A->cmap->N,&work);
163:   PetscArrayzero(work,A->cmap->N);
164:   MatGetOwnershipRange(A,&rstart,&rend);
165:   for (i=rstart; i<rend; i++) {
166:     MatGetRow(A,i,&nnz,&cols,&mvalues);
167:     for (j=0; j<nnz; j++) {
168:       work[cols[j]] += mvalues[j]*PetscConj(mvalues[j]);
169:     }
170:     MatRestoreRow(A,i,&nnz,&cols,&mvalues);
171:   }
172:   MPIU_Allreduce(work,diag,A->cmap->N,MPIU_SCALAR,MPIU_SUM,PetscObjectComm((PetscObject)N));
173:   rstart = N->cmap->rstart;
174:   rend   = N->cmap->rend;
175:   VecGetArray(v,&values);
176:   PetscArraycpy(values,diag+rstart,rend-rstart);
177:   VecRestoreArray(v,&values);
178:   PetscFree2(diag,work);
179:   VecScale(v,Na->scale);
180:   return 0;
181: }

183: PetscErrorCode MatNormalGetMatHermitian_Normal(Mat A,Mat *M)
184: {
185:   Mat_Normal *Aa = (Mat_Normal*)A->data;

187:   *M = Aa->A;
188:   return 0;
189: }

191: /*@
192:       MatNormalHermitianGetMat - Gets the Mat object stored inside a MATNORMALHERMITIAN

194:    Logically collective on Mat

196:    Input Parameter:
197: .   A  - the MATNORMALHERMITIAN matrix

199:    Output Parameter:
200: .   M - the matrix object stored inside A

202:    Level: intermediate

204: .seealso: MatCreateNormalHermitian()

206: @*/
207: PetscErrorCode MatNormalHermitianGetMat(Mat A,Mat *M)
208: {
212:   PetscUseMethod(A,"MatNormalGetMatHermitian_C",(Mat,Mat*),(A,M));
213:   return 0;
214: }

216: /*@
217:       MatCreateNormalHermitian - Creates a new matrix object that behaves like (A*)'*A.

219:    Collective on Mat

221:    Input Parameter:
222: .   A  - the (possibly rectangular complex) matrix

224:    Output Parameter:
225: .   N - the matrix that represents (A*)'*A

227:    Level: intermediate

229:    Notes:
230:     The product (A*)'*A is NOT actually formed! Rather the new matrix
231:           object performs the matrix-vector product by first multiplying by
232:           A and then (A*)'
233: @*/
234: PetscErrorCode  MatCreateNormalHermitian(Mat A,Mat *N)
235: {
236:   PetscInt       m,n;
237:   Mat_Normal     *Na;
238:   VecType        vtype;

240:   MatGetLocalSize(A,&m,&n);
241:   MatCreate(PetscObjectComm((PetscObject)A),N);
242:   MatSetSizes(*N,n,n,PETSC_DECIDE,PETSC_DECIDE);
243:   PetscObjectChangeTypeName((PetscObject)*N,MATNORMALHERMITIAN);
244:   PetscLayoutReference(A->cmap,&(*N)->rmap);
245:   PetscLayoutReference(A->cmap,&(*N)->cmap);

247:   PetscNewLog(*N,&Na);
248:   (*N)->data = (void*) Na;
249:   PetscObjectReference((PetscObject)A);
250:   Na->A      = A;
251:   Na->scale  = 1.0;

253:   MatCreateVecs(A,NULL,&Na->w);

255:   (*N)->ops->destroy          = MatDestroyHermitian_Normal;
256:   (*N)->ops->mult             = MatMultHermitian_Normal;
257:   (*N)->ops->multtranspose    = MatMultHermitianTranspose_Normal;
258:   (*N)->ops->multtransposeadd = MatMultHermitianTransposeAdd_Normal;
259:   (*N)->ops->multadd          = MatMultHermitianAdd_Normal;
260:   (*N)->ops->getdiagonal      = MatGetDiagonalHermitian_Normal;
261:   (*N)->ops->scale            = MatScaleHermitian_Normal;
262:   (*N)->ops->diagonalscale    = MatDiagonalScaleHermitian_Normal;
263:   (*N)->assembled             = PETSC_TRUE;
264:   (*N)->preallocated          = PETSC_TRUE;

266:   PetscObjectComposeFunction((PetscObject)(*N),"MatNormalGetMatHermitian_C",MatNormalGetMatHermitian_Normal);
267:   MatSetOption(*N,MAT_HERMITIAN,PETSC_TRUE);
268:   MatGetVecType(A,&vtype);
269:   MatSetVecType(*N,vtype);
270: #if defined(PETSC_HAVE_DEVICE)
271:   MatBindToCPU(*N,A->boundtocpu);
272: #endif
273:   return 0;
274: }