Actual source code: matadic.c

  1: /*$Id: matadic.c,v 1.13 2001/08/07 03:03:06 balay Exp $*/
  2: /*
  3:     ADIC matrix-free matrix implementation
  4: */

 6:  #include src/mat/matimpl.h
 7:  #include petscda.h
 8:  #include petscsnes.h
 9:  #include petscsys.h
 10: EXTERN_C_BEGIN
 11: #include "adic/ad_utils.h"
 12: EXTERN_C_END

 14: typedef struct {
 15:   DA         da;
 16:   Vec        localu;         /* point at which Jacobian is evaluated */
 17:   void       *ctx;
 18:   SNES       snes;
 19:   Vec        diagonal;       /* current matrix diagonal */
 20:   PetscTruth diagonalvalid;  /* indicates if diagonal matches current base vector */
 21: } Mat_DAAD;

 25: int MatAssemblyEnd_DAAD(Mat A,MatAssemblyType atype)
 26: {
 27:   Mat_DAAD *a = (Mat_DAAD*)A->data;
 28:   int      ierr;
 29:   Vec      u;

 32:   a->diagonalvalid = PETSC_FALSE;
 33:   if (a->snes) {
 34:     SNESGetSolution(a->snes,&u);
 35:     DAGlobalToLocalBegin(a->da,u,INSERT_VALUES,a->localu);
 36:     DAGlobalToLocalEnd(a->da,u,INSERT_VALUES,a->localu);
 37:   }
 38:   return(0);
 39: }

 43: int MatMult_DAAD(Mat A,Vec xx,Vec yy)
 44: {
 45:   Mat_DAAD *a = (Mat_DAAD*)A->data;
 46:   Vec      localxx;
 47:   int      ierr;

 50:   DAGetLocalVector(a->da,&localxx);
 51:   DAGlobalToLocalBegin(a->da,xx,INSERT_VALUES,localxx);
 52:   DAGlobalToLocalEnd(a->da,xx,INSERT_VALUES,localxx);
 53:   DAMultiplyByJacobian1WithAD(a->da,a->localu,localxx,yy,a->ctx);
 54:   DARestoreLocalVector(a->da,&localxx);
 55:   return(0);
 56: }

 58:  #include src/dm/da/daimpl.h

 62: int MatGetDiagonal_DAAD(Mat A,Vec dd)
 63: {
 64:   Mat_DAAD      *a = (Mat_DAAD*)A->data;
 65:   int           ierr,j,nI,gI,gtdof;
 66:   PetscScalar   *avu,*ad_vustart,ad_f[2],*d;
 67:   DALocalInfo   info;
 68:   MatStencil    stencil;
 69:   void*         *ad_vu;


 73:   /* get space for derivative object.  */
 74:   DAGetAdicMFArray(a->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);

 76:   /* copy input vector into derivative object */
 77:   VecGetArray(a->localu,&avu);
 78:   for (j=0; j<gtdof; j++) {
 79:     ad_vustart[2*j]   = avu[j];
 80:     ad_vustart[2*j+1] = 0.0;
 81:   }
 82:   VecRestoreArray(a->localu,&avu);

 84:   PetscADResetIndep();
 85:   PetscADIncrementTotalGradSize(1);
 86:   PetscADSetIndepDone();

 88:   VecGetArray(dd,&d);

 90:   DAGetLocalInfo(a->da,&info);
 91:   nI = 0;
 92:   for (stencil.k = info.zs; stencil.k<info.zs+info.zm; stencil.k++) {
 93:     for (stencil.j = info.ys; stencil.j<info.ys+info.ym; stencil.j++) {
 94:       for (stencil.i = info.xs; stencil.i<info.xs+info.xm; stencil.i++) {
 95:         for (stencil.c = 0; stencil.c<info.dof; stencil.c++) {
 96:           gI   = stencil.c + (stencil.i - info.gxs)*info.dof + (stencil.j - info.gys)*info.dof*info.gxm + (stencil.k - info.gzs)*info.dof*info.gxm*info.gym;
 97:           ad_vustart[1+2*gI] = 1.0;
 98:           (*a->da->adicmf_lfi)(&info,&stencil,ad_vu,ad_f,a->ctx);
 99:           d[nI] = ad_f[1];
100:           ad_vustart[1+2*gI] = 0.0;
101:           nI++;
102:         }
103:       }
104:     }
105:   }

107:   VecRestoreArray(dd,&d);
108:   DARestoreAdicMFArray(a->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);
109:   return(0);
110: }


115: int MatRelax_DAAD(Mat A,Vec bb,PetscReal omega,MatSORType flag,PetscReal fshift,int its,int lits,Vec xx)
116: {
117:   Mat_DAAD      *a = (Mat_DAAD*)A->data;
118:   int           ierr,j,gtdof,nI,gI;
119:   PetscScalar   *avu,*av,*ad_vustart,ad_f[2],zero = 0.0,*d,*b;
120:   Vec           localxx,dd;
121:   DALocalInfo   info;
122:   MatStencil    stencil;
123:   void*         *ad_vu;

126:   if (omega != 1.0) SETERRQ(PETSC_ERR_ARG_WRONG,"Currently only support omega of 1.0");
127:   if (fshift)       SETERRQ(PETSC_ERR_ARG_WRONG,"Currently do not support fshift");
128:   if (its <= 0 || lits <= 0) SETERRQ2(PETSC_ERR_ARG_WRONG,"Relaxation requires global its %d and local its %d both positive",its,lits);

130:   if (!a->diagonal) {
131:     DACreateGlobalVector(a->da,&a->diagonal);
132:   }
133:   if (!a->diagonalvalid) {
134:     MatGetDiagonal(A,a->diagonal);
135:     a->diagonalvalid = PETSC_TRUE;
136:   }
137:   dd   = a->diagonal;


140:   DAGetLocalVector(a->da,&localxx);
141:   if (flag & SOR_ZERO_INITIAL_GUESS) {
142:     VecSet(&zero,localxx);
143:   } else {
144:     DAGlobalToLocalBegin(a->da,xx,INSERT_VALUES,localxx);
145:     DAGlobalToLocalEnd(a->da,xx,INSERT_VALUES,localxx);
146:   }

148:   /* get space for derivative object.  */
149:   DAGetAdicMFArray(a->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);

151:   /* copy input vector into derivative object */
152:   VecGetArray(a->localu,&avu);
153:   VecGetArray(localxx,&av);
154:   for (j=0; j<gtdof; j++) {
155:     ad_vustart[2*j]   = avu[j];
156:     ad_vustart[2*j+1] = av[j];
157:   }
158:   VecRestoreArray(a->localu,&avu);
159:   VecRestoreArray(localxx,&av);

161:   PetscADResetIndep();
162:   PetscADIncrementTotalGradSize(1);
163:   PetscADSetIndepDone();

165:   VecGetArray(dd,&d);
166:   VecGetArray(bb,&b);

168:   DAGetLocalInfo(a->da,&info);
169:   while (its--) {
170:     if (flag & SOR_FORWARD_SWEEP || flag & SOR_LOCAL_FORWARD_SWEEP){
171:       nI = 0;
172:       for (stencil.k = info.zs; stencil.k<info.zs+info.zm; stencil.k++) {
173:         for (stencil.j = info.ys; stencil.j<info.ys+info.ym; stencil.j++) {
174:           for (stencil.i = info.xs; stencil.i<info.xs+info.xm; stencil.i++) {
175:             for (stencil.c = 0; stencil.c<info.dof; stencil.c++) {
176:               (*a->da->adicmf_lfi)(&info,&stencil,ad_vu,ad_f,a->ctx);
177:               gI   = stencil.c + (stencil.i - info.gxs)*info.dof + (stencil.j - info.gys)*info.dof*info.gxm + (stencil.k - info.gzs)*info.dof*info.gxm*info.gym;
178:               ad_vustart[1+2*gI] += (b[nI] - ad_f[1])/d[nI];
179:               nI++;
180:             }
181:           }
182:         }
183:       }
184:     }
185:     if (flag & SOR_BACKWARD_SWEEP || flag & SOR_LOCAL_BACKWARD_SWEEP){
186:       nI = info.dof*info.xm*info.ym*info.zm - 1;
187:       for (stencil.k = info.zs+info.zm-1; stencil.k>=info.zs; stencil.k--) {
188:         for (stencil.j = info.ys+info.ym-1; stencil.j>=info.ys; stencil.j--) {
189:           for (stencil.i = info.xs+info.xm-1; stencil.i>=info.xs; stencil.i--) {
190:             for (stencil.c = info.dof-1; stencil.c>=0; stencil.c--) {
191:               (*a->da->adicmf_lfi)(&info,&stencil,ad_vu,ad_f,a->ctx);
192:               gI   = stencil.c + (stencil.i - info.gxs)*info.dof + (stencil.j - info.gys)*info.dof*info.gxm + (stencil.k - info.gzs)*info.dof*info.gxm*info.gym;
193:               ad_vustart[1+2*gI] += (b[nI] - ad_f[1])/d[nI];
194:               nI--;
195:             }
196:           }
197:         }
198:       }
199:     }
200:   }

202:   VecRestoreArray(dd,&d);
203:   VecRestoreArray(bb,&b);

205:   VecGetArray(localxx,&av);
206:   for (j=0; j<gtdof; j++) {
207:     av[j] = ad_vustart[2*j+1];
208:   }
209:   VecRestoreArray(localxx,&av);
210:   DALocalToGlobal(a->da,localxx,INSERT_VALUES,xx);

212:   DARestoreLocalVector(a->da,&localxx);
213:   DARestoreAdicMFArray(a->da,PETSC_TRUE,(void **)&ad_vu,(void**)&ad_vustart,&gtdof);
214:   return(0);
215: }



221: int MatDestroy_DAAD(Mat A)
222: {
223:   Mat_DAAD *a = (Mat_DAAD*)A->data;
224:   int      ierr;

227:   DADestroy(a->da);
228:   VecDestroy(a->localu);
229:   if (a->diagonal) {VecDestroy(a->diagonal);}
230:   PetscFree(a);
231:   return(0);
232: }

234: /* -------------------------------------------------------------------*/
235: static struct _MatOps MatOps_Values = {0,
236:        0,
237:        0,
238:        MatMult_DAAD,
239: /* 4*/ 0,
240:        0,
241:        0,
242:        0,
243:        0,
244:        0,
245: /*10*/ 0,
246:        0,
247:        0,
248:        MatRelax_DAAD,
249:        0,
250: /*15*/ 0,
251:        0,
252:        MatGetDiagonal_DAAD,
253:        0,
254:        0,
255: /*20*/ 0,
256:        MatAssemblyEnd_DAAD,
257:        0,
258:        0,
259:        0,
260: /*25*/ 0,
261:        0,
262:        0,
263:        0,
264:        0,
265: /*30*/ 0,
266:        0,
267:        0,
268:        0,
269:        0,
270: /*35*/ 0,
271:        0,
272:        0,
273:        0,
274:        0,
275: /*40*/ 0,
276:        0,
277:        0,
278:        0,
279:        0,
280: /*45*/ 0,
281:        0,
282:        0,
283:        0,
284:        0,
285: /*50*/ 0,
286:        0,
287:        0,
288:        0,
289:        0,
290: /*55*/ 0,
291:        0,
292:        0,
293:        0,
294:        0,
295: /*60*/ 0,
296:        MatDestroy_DAAD,
297:        0,
298:        0,
299:        0,
300: /*65*/ 0,
301:        0,
302:        0,
303:        0,
304:        0,
305: /*70*/ 0,
306:        0,
307:        0,
308:        0,
309:        0,
310: /*75*/ 0,
311:        0,
312:        0,
313:        0,
314:        0,
315: /*80*/ 0,
316:        0,
317:        0,
318:        0,
319: /*85*/ 0
320: };

322: /* --------------------------------------------------------------------------------*/

324: EXTERN_C_BEGIN
327: int MatSNESMFSetBase_AD(Mat J,Vec U)
328: {
329:   int      ierr;
330:   Mat_DAAD *a = (Mat_DAAD*)J->data;

333:   a->diagonalvalid = PETSC_FALSE;
334:   DAGlobalToLocalBegin(a->da,U,INSERT_VALUES,a->localu);
335:   DAGlobalToLocalEnd(a->da,U,INSERT_VALUES,a->localu);
336:   return(0);
337: }
338: EXTERN_C_END

340: EXTERN_C_BEGIN
343: int MatDAADSetDA_AD(Mat A,DA da)
344: {
345:   Mat_DAAD *a = (Mat_DAAD*)A->data;
346:   int      ierr,nc,nx,ny,nz,Nx,Ny,Nz;

349:   a->da = da;
350:   PetscObjectReference((PetscObject)da);
351:   DAGetInfo(da,0,&Nx,&Ny,&Nz,0,0,0,&nc,0,0,0);
352:   DAGetCorners(da,0,0,0,&nx,&ny,&nz);
353:   A->m  = A->n = nc*nx*ny*nz;
354:   A->M  = A->N = nc*Nx*Ny*Nz;
355:   DACreateLocalVector(da,&a->localu);
356:   return(0);
357: }
358: EXTERN_C_END

360: EXTERN_C_BEGIN
363: int MatDAADSetSNES_AD(Mat A,SNES snes)
364: {
365:   Mat_DAAD *a = (Mat_DAAD*)A->data;

368:   a->snes = snes;
369:   return(0);
370: }
371: EXTERN_C_END

373: EXTERN_C_BEGIN
376: int MatDAADSetCtx_AD(Mat A,void *ctx)
377: {
378:   Mat_DAAD *a = (Mat_DAAD*)A->data;

381:   a->ctx = ctx;
382:   return(0);
383: }
384: EXTERN_C_END

386: /*MC
387:   MATDAAD - MATDAAD = "daad" - A matrix type that can do matrix-vector products using a local function that
388:   is differentiated with ADIFOR or ADIC. 

390:   Level: intermediate

392: .seealso: MatCreateDAAD
393: M*/

395: EXTERN_C_BEGIN
398: int MatCreate_DAAD(Mat B)
399: {
400:   Mat_DAAD *b;
401:   int      ierr;

404:   PetscNew(Mat_DAAD,&b);
405:   B->data = (void*)b;
406:   PetscMemzero(b,sizeof(Mat_DAAD));
407:   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
408: 
409:   PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);
410:   PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);

412:   PetscObjectChangeTypeName((PetscObject)B,MATDAAD);
413:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSNESMFSetBase_C","MatSNESMFSetBase_AD",MatSNESMFSetBase_AD);
414:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetDA_C","MatDAADSetDA_AD",MatDAADSetDA_AD);
415:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetSNES_C","MatDAADSetSNES_AD",MatDAADSetSNES_AD);
416:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetCtx_C","MatDAADSetCtx_AD",MatDAADSetCtx_AD);
417:   return(0);
418: }
419: EXTERN_C_END


424: /*@C
425:    MatDAADSetDA - Tells the matrix what DA it is using for layout and Jacobian.

427:    Collective on Mat and DA

429:    Input Parameters:
430: +  mat - the matrix
431: -  da - the DA

433:    Level: intermediate

435: .seealso: MatCreate(), DASetLocalAdicMFFunction(), MatCreateDAAD()

437: @*/
438: int MatDAADSetDA(Mat A,DA da)
439: {
440:   int      ierr,(*f)(Mat,void*);

445:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetDA_C",(void (**)(void))&f);
446:   if (f) {
447:     (*f)(A,da);
448:   }
449:   return(0);
450: }

454: /*@C
455:    MatDAADSetSNES - Tells the matrix what SNES it is using for the base U.

457:    Collective on Mat and SNES

459:    Input Parameters:
460: +  mat - the matrix
461: -  snes - the SNES

463:    Level: intermediate

465: .seealso: MatCreate(), DASetLocalAdicMFFunction(), MatCreateDAAD(), MatDAADSetDA()

467: @*/
468: int MatDAADSetSNES(Mat A,SNES snes)
469: {
470:   int      ierr,(*f)(Mat,void*);

475:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetSNES_C",(void (**)(void))&f);
476:   if (f) {
477:     (*f)(A,snes);
478:   }
479:   return(0);
480: }

484: /*@C
485:    MatDAADSetCtx - Sets the user context for a DAAD (ADIC matrix-free) matrix.

487:    Collective on Mat

489:    Input Parameters:
490: +  mat - the matrix
491: -  ctx - the context

493:    Level: intermediate

495: .seealso: MatCreate(), DASetLocalAdicMFFunction(), MatCreateDAAD(), MatDAADSetDA()

497: @*/
498: int MatDAADSetCtx(Mat A,void *ctx)
499: {
500:   int      ierr,(*f)(Mat,void*);

504:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetCtx_C",(void (**)(void))&f);
505:   if (f) {
506:     (*f)(A,ctx);
507:   }
508:   return(0);
509: }

513: /*@C
514:    MatCreateDAAD - Creates a matrix that can do matrix-vector products using a local 
515:    function that is differentiated with ADIFOR or ADIC.

517:    Collective on DA

519:    Input Parameters:
520: .  da - the DA that defines the distribution of the vectors

522:    Output Parameter:
523: .  A - the matrix 

525:    Level: intermediate

527: .seealso: MatCreate(), DASetLocalAdicMFFunction()

529: @*/
530: int MatCreateDAAD(DA da,Mat *A)
531: {
532:   int      ierr;
533:   MPI_Comm comm;

536:   PetscObjectGetComm((PetscObject)da,&comm);
537:   MatCreate(comm,0,0,0,0,A);
538:   MatSetType(*A,MATDAAD);
539:   MatDAADSetDA(*A,da);
540:   return(0);
541: }

545: int MatRegisterDAAD(void)
546: {
549:   MatRegisterDynamic(MATDAAD,PETSC_NULL,"MatCreate_DAAD",MatCreate_DAAD);
550:   return(0);
551: }