Actual source code: normalmat.c

  1: #include "normalmat.h"                /*I  "mat.h"  I*/

  5: /*@C
  6:    MatCreateADA - Creates a matrix M=A^T D1 A + D2.

  8:    Collective on matrix

 10:    Input Parameters:
 11: +  mat - matrix of arbitrary type
 12: .  D1 - A vector
 13: -  D2 - A vector

 15:    Output Parameters:
 16: .  J - New matrix whose operations are defined in terms of mat, D1, and D2.

 18:    Notes: 
 19:    The user provides the input data and is responsible for destroying
 20:    this data after matrix J has been destroyed.  
 21:    The operation MatMult(A,D2,D1) must be well defined.
 22:    Before calling the operation MatGetDiagonal(), the function 
 23:    MatADAComputeDiagonal() must be called.  The matrices A and D1 must
 24:    be the same during calls to MatADAComputeDiagonal() and
 25:    MatGetDiagonal().

 27:    Level: developer

 29: .seealso: MatCreate()
 30: @*/
 31: int MatCreateADA(Mat mat,Vec D1, Vec D2, Mat *J)
 32: {
 33:   MPI_Comm     comm=mat->comm;
 34:   TaoMatADACtx ctx;
 35:   int          info,nloc,n;

 38:   /*
 39:   info=MatCheckVecs(mat,D1,D2,&flg);CHKERRQ(info);
 40:   if (flg==PETSC_FALSE){
 41:     SETERRQ(PETSC_ERR_SUP,"InCompatible matrix and vector for ADA^T matrix");
 42:   }
 43:   */
 44:   info = PetscNew(_p_TaoMatADACtx,&ctx);CHKERRQ(info);

 46:   ctx->A=mat;
 47:   ctx->D1=D1;
 48:   ctx->D2=D2;
 49:   if (D1){
 50:     info = VecDuplicate(D1,&ctx->W);CHKERRQ(info);
 51:     info =  PetscObjectReference((PetscObject)D1);CHKERRQ(info);
 52:   } else {
 53:     ctx->W=0;
 54:   }
 55:   if (D2){
 56:     info = VecDuplicate(D2,&ctx->W2);CHKERRQ(info);
 57:     info = VecDuplicate(D2,&ctx->ADADiag);CHKERRQ(info);
 58:     info =  PetscObjectReference((PetscObject)D2);CHKERRQ(info);
 59:   } else {
 60:     ctx->W2=0;
 61:     ctx->ADADiag=0;
 62:   }

 64:   ctx->GotDiag=0;
 65:   info =  PetscObjectReference((PetscObject)mat);CHKERRQ(info);

 67:   info=VecGetLocalSize(D2,&nloc);CHKERRQ(info);
 68:   info=VecGetSize(D2,&n);CHKERRQ(info);

 70:   info = MatCreateShell(comm,nloc,nloc,n,n,ctx,J);CHKERRQ(info);

 72:   info = MatShellSetOperation(*J,MATOP_MULT,(void(*)())MatMult_ADA);CHKERRQ(info);
 73:   info = MatShellSetOperation(*J,MATOP_DESTROY,(void(*)())MatDestroy_ADA);CHKERRQ(info);
 74:   info = MatShellSetOperation(*J,MATOP_VIEW,(void(*)())MatView_ADA);CHKERRQ(info);
 75:   info = MatShellSetOperation(*J,MATOP_MULT_TRANSPOSE,(void(*)())MatMultTranspose_ADA);CHKERRQ(info);
 76:   info = MatShellSetOperation(*J,MATOP_DIAGONAL_SHIFT,(void(*)())MatDiagonalShift_ADA);CHKERRQ(info);
 77:   info = MatShellSetOperation(*J,MATOP_SHIFT,(void(*)())MatShift_ADA);CHKERRQ(info);
 78:   info = MatShellSetOperation(*J,MATOP_EQUAL,(void(*)())MatEqual_ADA);CHKERRQ(info);
 79:   info = MatShellSetOperation(*J,MATOP_SCALE,(void(*)())MatScale_ADA);CHKERRQ(info);
 80:   info = MatShellSetOperation(*J,MATOP_TRANSPOSE,(void(*)())MatTranspose_ADA);CHKERRQ(info);
 81:   info = MatShellSetOperation(*J,MATOP_GET_DIAGONAL,(void(*)())MatGetDiagonal_ADA);CHKERRQ(info);
 82:   info = MatShellSetOperation(*J,MATOP_GET_SUBMATRICES,(void(*)())MatGetSubMatrices_ADA);CHKERRQ(info);
 83:   info = MatShellSetOperation(*J,MATOP_NORM,(void(*)())MatNorm_ADA);CHKERRQ(info);
 84:   info = MatShellSetOperation(*J,MATOP_DUPLICATE,(void(*)())MatDuplicate_ADA);CHKERRQ(info);
 85:   info = MatShellSetOperation(*J,MATOP_GET_SUBMATRIX,(void(*)())MatGetSubMatrix_ADA);CHKERRQ(info);

 87:   info = PetscLogObjectParent(*J,ctx->W); CHKERRQ(info);
 88:   info = PetscLogObjectParent(mat,*J); CHKERRQ(info);

 90:   info = MatSetOption(*J,MAT_SYMMETRIC);CHKERRQ(info);
 91:   return(0);  
 92: }

 96: int MatMult_ADA(Mat mat,Vec a,Vec y)
 97: {
 98:   TaoMatADACtx ctx;
 99:   PetscScalar        one = 1.0;
100:   int           info;

103:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);

105:   info = MatMult(ctx->A,a,ctx->W);CHKERRQ(info);
106:   if (ctx->D1){
107:     info = VecPointwiseMult(ctx->W,ctx->D1,ctx->W);CHKERRQ(info);
108:   }
109:   info = MatMultTranspose(ctx->A,ctx->W,y);CHKERRQ(info);
110:   if (ctx->D2){
111:     info = VecPointwiseMult(ctx->W2, ctx->D2, a);CHKERRQ(info);
112:     info = VecAXPY(y, one, ctx->W2);CHKERRQ(info);
113:   }
114:   return(0);
115: } 

119: int MatMultTranspose_ADA(Mat mat,Vec a,Vec y)
120: {
121:   int info;

124:   info = MatMult_ADA(mat,a,y);CHKERRQ(info);
125:   return(0);
126: } 

130: int MatDiagonalShift_ADA(Vec D, Mat M)
131: {
132:   TaoMatADACtx ctx;
133:   PetscScalar        zero=0.0,one = 1.0;
134:   int           info;

137:   info = MatShellGetContext(M,(void **)&ctx);CHKERRQ(info);

139:   if (ctx->D2==PETSC_NULL){
140:     info = VecDuplicate(D,&ctx->D2);CHKERRQ(info);
141:     info = VecSet(ctx->D2, zero);CHKERRQ(info);
142:   }
143:   info = VecAXPY(ctx->D2, one, D);CHKERRQ(info);

145:   return(0);
146: } 

150: int MatDestroy_ADA(Mat mat)
151: {
152:   int          info;
153:   TaoMatADACtx ctx;

156:   info=MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
157:   info=VecDestroy(ctx->W);CHKERRQ(info);
158:   info=VecDestroy(ctx->W2);CHKERRQ(info);
159:   info=VecDestroy(ctx->ADADiag);CHKERRQ(info);
160:   info=MatDestroy(ctx->A);CHKERRQ(info);
161:   info=VecDestroy(ctx->D1);CHKERRQ(info);
162:   info=VecDestroy(ctx->D2);CHKERRQ(info);
163:   info = PetscFree(ctx); CHKERRQ(info);
164:   return(0);
165: }

169: int MatView_ADA(Mat mat,PetscViewer viewer)
170: {

173:   /*
174:   info = ViewerGetFormat(viewer,&format);CHKERRQ(info);
175:   if (format == PETSC_VIEWER_ASCII_INFO || format == PETSC_VIEWER_ASCII_INFO_LONG) {
176:     return(0);  / * do nothing for now * /
177:   }
178:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
179:   info = MatView(ctx->A,viewer);CHKERRQ(info);
180:   if (ctx->D1){
181:     info = VecView(ctx->D1,viewer);CHKERRQ(info);
182:   }
183:   if (ctx->D2){
184:     info = VecView(ctx->D2,viewer);CHKERRQ(info);
185:   }
186:   */
187:   return(0);
188: }

192: int MatShift_ADA(Mat Y, PetscScalar a)
193: {
194:   int          info;
195:   TaoMatADACtx ctx;

198:   info = MatShellGetContext(Y,(void **)&ctx);CHKERRQ(info);
199:   info = VecShift(ctx->D2,a);CHKERRQ(info);
200:   return(0);
201: }

205: int MatDuplicate_ADA(Mat mat,MatDuplicateOption op,Mat *M)
206: {
207:   int          info;
208:   TaoMatADACtx ctx;
209:   Mat          A2;
210:   Vec          D1b=NULL,D2b;

213:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
214:   info = MatDuplicate(ctx->A,op,&A2);CHKERRQ(info);
215:   if (ctx->D1){
216:     info = VecDuplicate(ctx->D1,&D1b);CHKERRQ(info);
217:     info = VecCopy(ctx->D1,D1b);CHKERRQ(info);
218:   }
219:   info = VecDuplicate(ctx->D2,&D2b);CHKERRQ(info);
220:   info = VecCopy(ctx->D2,D2b);CHKERRQ(info);
221:   info = MatCreateADA(A2,D1b,D2b,M);CHKERRQ(info);
222:   if (ctx->D1){
223:   info = PetscObjectDereference((PetscObject)D1b);CHKERRQ(info);
224:   }
225:   info = PetscObjectDereference((PetscObject)D2b);CHKERRQ(info);
226:   info = PetscObjectDereference((PetscObject)A2);CHKERRQ(info);

228:   return(0);
229: }

233: int MatEqual_ADA(Mat A,Mat B,PetscTruth *flg)
234: {
235:   int          info;
236:   TaoMatADACtx  ctx1,ctx2;

239:   info = MatShellGetContext(A,(void **)&ctx1);CHKERRQ(info);
240:   info = MatShellGetContext(B,(void **)&ctx2);CHKERRQ(info);
241:   info = VecEqual(ctx1->D2,ctx2->D2,flg);CHKERRQ(info);
242:   if (*flg==PETSC_TRUE){
243:     info = VecEqual(ctx1->D1,ctx2->D1,flg);CHKERRQ(info);
244:   }
245:   if (*flg==PETSC_TRUE){
246:     info = MatEqual(ctx1->A,ctx2->A,flg);CHKERRQ(info);
247:   }
248:   return(0);
249: }

253: int MatScale_ADA(Mat mat, PetscScalar a)
254: {
255:   int          info;
256:   TaoMatADACtx ctx;

259:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
260:   info = VecScale(ctx->D1,a);CHKERRQ(info);
261:   if (ctx->D2){
262:     info = VecScale(ctx->D2,a);CHKERRQ(info);
263:   }
264:   return(0);
265: }

269: int MatTranspose_ADA(Mat mat,Mat *B)
270: {
271:   int          info;
272:   TaoMatADACtx ctx;

275:   if (*B){
276:     info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
277:     info = MatDuplicate(mat,MAT_COPY_VALUES,B);CHKERRQ(info);
278:   }
279:   return(0);
280: }

284: int MatADAComputeDiagonal(Mat mat)
285: {
286:   int          i,m,n,low,high,info;
287:   PetscScalar       *dtemp,*dptr;
288:   TaoMatADACtx ctx;

291:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);

293:   info = MatGetOwnershipRange(mat, &low, &high);CHKERRQ(info);
294:   info = MatGetSize(mat,&m,&n);CHKERRQ(info);
295:   
296:   info = PetscMalloc( n*sizeof(PetscScalar),&dtemp ); CHKERRQ(info);

298:   for (i=0; i<n; i++){
299:     info = MatGetColumnVector(ctx->A, ctx->W, i);CHKERRQ(info);
300:     info = VecPointwiseMult(ctx->W,ctx->W,ctx->W);CHKERRQ(info);
301:     info = VecDotBegin(ctx->D1, ctx->W,dtemp+i);CHKERRQ(info);
302:   }
303:   for (i=0; i<n; i++){
304:     info = VecDotEnd(ctx->D1, ctx->W,dtemp+i);CHKERRQ(info);
305:   } 

307:   info = VecGetArray(ctx->ADADiag,&dptr);CHKERRQ(info);
308:   for (i=low; i<high; i++){
309:     dptr[i-low]= dtemp[i];
310:   }
311:   info = VecRestoreArray(ctx->ADADiag,&dptr);CHKERRQ(info);
312:   if (dtemp) {
313:     info = PetscFree(dtemp); CHKERRQ(info);
314:   }
315:   return(0);
316: }

320: int MatGetDiagonal_ADA(Mat mat,Vec v)
321: {
322:   int          info;
323:   PetscScalar       one=1.0;
324:   TaoMatADACtx ctx;

327:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
328:   info = MatADAComputeDiagonal(mat);
329:   info=VecCopy(ctx->ADADiag,v);CHKERRQ(info);
330:   if (ctx->D2){
331:     info=VecAXPY(v, one, ctx->D2);CHKERRQ(info);
332:   }

334:   return(0);
335: }

339: int MatGetSubMatrices_ADA(Mat A,int n, IS *irow,IS *icol,MatReuse scall,Mat **B)
340: {
341:   int info,i;

344:   if (scall == MAT_INITIAL_MATRIX) {
345:     info = PetscMalloc( (n+1)*sizeof(Mat),B );CHKERRQ(info);
346:   }

348:   for ( i=0; i<n; i++ ) {
349:     info = MatGetSubMatrix_ADA(A,irow[i],icol[i],PETSC_DECIDE,scall,&(*B)[i]);CHKERRQ(info);
350:   }
351:   return(0);
352: }

356: int MatGetSubMatrix_ADA(Mat mat,IS isrow,IS iscol,int csize,MatReuse cll,
357:                         Mat *newmat)
358: {
359:   int          info,low,high;
360:   int          n,nlocal,i;
361:   int          *iptr;
362:   PetscScalar       *dptr,*ddptr,zero=0.0;
363:   VecType type_name;
364:   IS           ISrow;
365:   Vec          D1,D2;
366:   Mat          Atemp;
367:   TaoMatADACtx ctx;


371:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);

373:   info = MatGetOwnershipRange(ctx->A,&low,&high);CHKERRQ(info);
374:   info = ISCreateStride(mat->comm,high-low,low,1,&ISrow);CHKERRQ(info);
375:   info = MatGetSubMatrix(ctx->A,ISrow,iscol,csize,cll,&Atemp);CHKERRQ(info);
376:   info = ISDestroy(ISrow);CHKERRQ(info);

378:   if (ctx->D1){
379:     info=VecDuplicate(ctx->D1,&D1);CHKERRQ(info);
380:     info=VecCopy(ctx->D1,D1);CHKERRQ(info);
381:   } else {
382:     D1=PETSC_NULL;
383:   }

385:   if (ctx->D2){
386:     info=ISGetSize(isrow,&n);CHKERRQ(info);
387:     info=ISGetLocalSize(isrow,&nlocal);CHKERRQ(info);
388:     info=VecCreate(ctx->D2->comm,&D2);CHKERRQ(info);
389:     info=VecGetType(ctx->D2,&type_name);CHKERRQ(info);
390:     info=VecSetSizes(D2,nlocal,n);CHKERRQ(info);
391:     info=VecSetType(D2,type_name);CHKERRQ(info);
392:     info=VecSet(D2, zero);CHKERRQ(info);
393:     info=VecGetArray(ctx->D2, &dptr); CHKERRQ(info);
394:     info=VecGetArray(D2, &ddptr); CHKERRQ(info);
395:     info=ISGetIndices(isrow,&iptr); CHKERRQ(info);
396:     for (i=0;i<nlocal;i++){
397:       ddptr[i] = dptr[iptr[i]-low];
398:     }
399:     info=ISRestoreIndices(isrow,&iptr); CHKERRQ(info);
400:     info=VecRestoreArray(D2, &ddptr); CHKERRQ(info);
401:     info=VecRestoreArray(ctx->D2, &dptr); CHKERRQ(info);
402:    
403:   } else {
404:     D2=PETSC_NULL;
405:   }

407:   info = MatCreateADA(Atemp,D1,D2,newmat);CHKERRQ(info);
408:   info = MatShellGetContext(*newmat,(void **)&ctx);CHKERRQ(info);
409:   info = PetscObjectDereference((PetscObject)Atemp);CHKERRQ(info);
410:   if (ctx->D1){
411:     info = PetscObjectDereference((PetscObject)D1);CHKERRQ(info);
412:   }
413:   if (ctx->D2){
414:     info = PetscObjectDereference((PetscObject)D2);CHKERRQ(info);
415:   }
416:   return(0);
417: }

421: int MatGetRowADA(Mat mat,int row,int *ncols,int **cols,PetscScalar **vals)
422: {
423:   int info,m,n;

426:   info = MatGetSize(mat,&m,&n);CHKERRQ(info);

428:   if (*ncols>0){
429:     info = PetscMalloc( (*ncols)*sizeof(int),cols );CHKERRQ(info);
430:     info = PetscMalloc( (*ncols)*sizeof(PetscScalar),vals );CHKERRQ(info);
431:   } else {
432:     *cols=PETSC_NULL;
433:     *vals=PETSC_NULL;
434:   }
435:   
436:   return(0);
437: }

441: int MatRestoreRowADA(Mat mat,int row,int *ncols,int **cols,PetscScalar **vals)
442: {
443:   int info;
445:   if (*ncols>0){
446:     info = PetscFree(*cols);  CHKERRQ(info);
447:     info = PetscFree(*vals);  CHKERRQ(info);
448:   }
449:   *cols=PETSC_NULL;
450:   *vals=PETSC_NULL;
451:   return(0);
452: }

456: int MatGetColumnVector_ADA(Mat mat,Vec Y, int col)
457: {
458:   int    info,low,high;
459:   PetscScalar zero=0.0,one=1.0;

462:   info=VecSet(Y, zero);CHKERRQ(info);
463:   info=VecGetOwnershipRange(Y,&low,&high);CHKERRQ(info);
464:   if (col>=low && col<high){
465:     info=VecSetValue(Y,col,one,INSERT_VALUES);CHKERRQ(info);
466:   }
467:   info=VecAssemblyBegin(Y);CHKERRQ(info);
468:   info=VecAssemblyEnd(Y);CHKERRQ(info);
469:   info=MatMult_ADA(mat,Y,Y);CHKERRQ(info);

471:   return(0);
472: }

474: int MatConvert_ADA(Mat mat,MatType newtype,Mat *NewMat)
475: {
476:   int info,size;
477:   TaoMatADACtx  ctx;

480:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);
481:   MPI_Comm_size(mat->comm,&size);

483:   if (newtype==MATSAME){

485:     info=MatDuplicate(mat,MAT_COPY_VALUES,NewMat);CHKERRQ(info);

487:   } else if (newtype==MATMPIDENSE){

489:     int i,j,low,high,m,n,M,N;
490:     PetscScalar *dptr;
491:     Vec X;

493:     info = VecDuplicate(ctx->D2,&X);CHKERRQ(info);
494:     info=MatGetSize(mat,&M,&N);CHKERRQ(info);
495:     info=MatGetLocalSize(mat,&m,&n);CHKERRQ(info);
496:     info = MatCreateMPIDense(mat->comm,m,m,N,N,PETSC_NULL,NewMat);
497:     CHKERRQ(info);
498:     info = MatGetOwnershipRange(*NewMat,&low,&high);CHKERRQ(info);
499:     for (i=0;i<M;i++){
500:       info = MatGetColumnVector_ADA(mat,X,i);CHKERRQ(info);
501:       info = VecGetArray(X,&dptr);CHKERRQ(info);
502:       for (j=0; j<high-low; j++){
503:         info = MatSetValue(*NewMat,low+j,i,dptr[j],INSERT_VALUES);CHKERRQ(info);
504:       }
505:       info=VecRestoreArray(X,&dptr);CHKERRQ(info);
506:     }
507:     info=MatAssemblyBegin(*NewMat,MAT_FINAL_ASSEMBLY);CHKERRQ(info);
508:     info=MatAssemblyEnd(*NewMat,MAT_FINAL_ASSEMBLY);CHKERRQ(info);
509:     info = VecDestroy(X);CHKERRQ(info);

511:   } else if (newtype==MATSEQDENSE && size==1){

513:     int i,j,low,high,m,n,M,N;
514:     PetscScalar *dptr;
515:     Vec X;

517:     info = VecDuplicate(ctx->D2,&X);CHKERRQ(info);
518:     info = MatGetSize(mat,&M,&N);CHKERRQ(info);
519:     info = MatGetLocalSize(mat,&m,&n);CHKERRQ(info);
520:     info = MatCreateSeqDense(mat->comm,N,N,PETSC_NULL,NewMat);
521:     CHKERRQ(info);
522:     info = MatGetOwnershipRange(*NewMat,&low,&high);CHKERRQ(info);
523:     for (i=0;i<M;i++){
524:       info = MatGetColumnVector_ADA(mat,X,i);CHKERRQ(info);
525:       info = VecGetArray(X,&dptr);CHKERRQ(info);
526:       for (j=0; j<high-low; j++){
527:         info = MatSetValue(*NewMat,low+j,i,dptr[j],INSERT_VALUES);CHKERRQ(info);
528:       }
529:       info=VecRestoreArray(X,&dptr);CHKERRQ(info);
530:     }
531:     info=MatAssemblyBegin(*NewMat,MAT_FINAL_ASSEMBLY);CHKERRQ(info);
532:     info=MatAssemblyEnd(*NewMat,MAT_FINAL_ASSEMBLY);CHKERRQ(info);
533:     info=VecDestroy(X);CHKERRQ(info);

535:   } else {
536:     SETERRQ(1,"No support to convert objects to that type");
537:   }
538:   return(0);
539: }

543: int MatNorm_ADA(Mat mat,NormType type,PetscReal *norm)
544: {
545:   int info;
546:   TaoMatADACtx  ctx;

549:   info = MatShellGetContext(mat,(void **)&ctx);CHKERRQ(info);

551:   if (type == NORM_FROBENIUS) {
552:     *norm = 1.0;
553:   } else if (type == NORM_1 || type == NORM_INFINITY) {
554:     *norm = 1.0;
555:   } else {
556:     SETERRQ(PETSC_ERR_SUP,"No two norm");
557:   }
558:   return(0);
559: }