Actual source code: matadic.c

  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
 11: #include "adic/ad_utils.h"

 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: PetscErrorCode MatAssemblyEnd_DAAD(Mat A,MatAssemblyType atype)
 26: {
 27:   Mat_DAAD *a = (Mat_DAAD*)A->data;
 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: PetscErrorCode MatMult_DAAD(Mat A,Vec xx,Vec yy)
 44: {
 45:   Mat_DAAD *a = (Mat_DAAD*)A->data;
 46:   Vec      localxx;

 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: PetscErrorCode MatGetDiagonal_DAAD(Mat A,Vec dd)
 63: {
 64:   Mat_DAAD      *a = (Mat_DAAD*)A->data;
 66:   int j,nI,gI,gtdof;
 67:   PetscScalar   *avu,*ad_vustart,ad_f[2],*d;
 68:   DALocalInfo   info;
 69:   MatStencil    stencil;
 70:   void*         *ad_vu;


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

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

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

 89:   VecGetArray(dd,&d);

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

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


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

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

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


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

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

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

163:   PetscADResetIndep();
164:   PetscADIncrementTotalGradSize(1);
165:   PetscADSetIndepDone();

167:   VecGetArray(dd,&d);
168:   VecGetArray(bb,&b);

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

204:   VecRestoreArray(dd,&d);
205:   VecRestoreArray(bb,&b);

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

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



223: PetscErrorCode MatDestroy_DAAD(Mat A)
224: {
225:   Mat_DAAD *a = (Mat_DAAD*)A->data;

229:   DADestroy(a->da);
230:   VecDestroy(a->localu);
231:   if (a->diagonal) {VecDestroy(a->diagonal);}
232:   PetscFree(a);
233:   PetscObjectComposeFunction((PetscObject)A,"MatSNESMFSetBase_C","",PETSC_NULL);
234:   PetscObjectComposeFunction((PetscObject)A,"MatDAADSetDA_C","",PETSC_NULL);
235:   PetscObjectComposeFunction((PetscObject)A,"MatDAADSetSNES_C","",PETSC_NULL);
236:   PetscObjectComposeFunction((PetscObject)A,"MatDAADSetCtx_C","",PETSC_NULL);
237:   return(0);
238: }

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

341: /* --------------------------------------------------------------------------------*/

346: PetscErrorCode MatSNESMFSetBase_AD(Mat J,Vec U)
347: {
349:   Mat_DAAD *a = (Mat_DAAD*)J->data;

352:   a->diagonalvalid = PETSC_FALSE;
353:   DAGlobalToLocalBegin(a->da,U,INSERT_VALUES,a->localu);
354:   DAGlobalToLocalEnd(a->da,U,INSERT_VALUES,a->localu);
355:   return(0);
356: }

362: PetscErrorCode MatDAADSetDA_AD(Mat A,DA da)
363: {
364:   Mat_DAAD *a = (Mat_DAAD*)A->data;
366:   int nc,nx,ny,nz,Nx,Ny,Nz;

369:   a->da = da;
370:   PetscObjectReference((PetscObject)da);
371:   DAGetInfo(da,0,&Nx,&Ny,&Nz,0,0,0,&nc,0,0,0);
372:   DAGetCorners(da,0,0,0,&nx,&ny,&nz);
373:   A->m  = A->n = nc*nx*ny*nz;
374:   A->M  = A->N = nc*Nx*Ny*Nz;
375:   DACreateLocalVector(da,&a->localu);
376:   return(0);
377: }

383: PetscErrorCode MatDAADSetSNES_AD(Mat A,SNES snes)
384: {
385:   Mat_DAAD *a = (Mat_DAAD*)A->data;

388:   a->snes = snes;
389:   return(0);
390: }

396: PetscErrorCode MatDAADSetCtx_AD(Mat A,void *ctx)
397: {
398:   Mat_DAAD *a = (Mat_DAAD*)A->data;

401:   a->ctx = ctx;
402:   return(0);
403: }

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

410:   Level: intermediate

412: .seealso: MatCreateDAAD
413: M*/

418: PetscErrorCode MatCreate_DAAD(Mat B)
419: {
420:   Mat_DAAD *b;

424:   PetscNew(Mat_DAAD,&b);
425:   B->data = (void*)b;
426:   PetscMemzero(b,sizeof(Mat_DAAD));
427:   PetscMemcpy(B->ops,&MatOps_Values,sizeof(struct _MatOps));
428: 
429:   PetscMapCreateMPI(B->comm,B->m,B->m,&B->rmap);
430:   PetscMapCreateMPI(B->comm,B->n,B->n,&B->cmap);

432:   PetscObjectChangeTypeName((PetscObject)B,MATDAAD);
433:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatSNESMFSetBase_C","MatSNESMFSetBase_AD",MatSNESMFSetBase_AD);
434:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetDA_C","MatDAADSetDA_AD",MatDAADSetDA_AD);
435:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetSNES_C","MatDAADSetSNES_AD",MatDAADSetSNES_AD);
436:   PetscObjectComposeFunctionDynamic((PetscObject)B,"MatDAADSetCtx_C","MatDAADSetCtx_AD",MatDAADSetCtx_AD);
437:   return(0);
438: }


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

447:    Collective on Mat and DA

449:    Input Parameters:
450: +  mat - the matrix
451: -  da - the DA

453:    Level: intermediate

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

457: @*/
458: PetscErrorCode MatDAADSetDA(Mat A,DA da)
459: {
460:   PetscErrorCode ierr,(*f)(Mat,void*);

465:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetDA_C",(void (**)(void))&f);
466:   if (f) {
467:     (*f)(A,da);
468:   }
469:   return(0);
470: }

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

477:    Collective on Mat and SNES

479:    Input Parameters:
480: +  mat - the matrix
481: -  snes - the SNES

483:    Level: intermediate

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

487: @*/
488: PetscErrorCode MatDAADSetSNES(Mat A,SNES snes)
489: {
490:   PetscErrorCode ierr,(*f)(Mat,void*);

495:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetSNES_C",(void (**)(void))&f);
496:   if (f) {
497:     (*f)(A,snes);
498:   }
499:   return(0);
500: }

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

507:    Collective on Mat

509:    Input Parameters:
510: +  mat - the matrix
511: -  ctx - the context

513:    Level: intermediate

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

517: @*/
518: PetscErrorCode MatDAADSetCtx(Mat A,void *ctx)
519: {
520:   PetscErrorCode ierr,(*f)(Mat,void*);

524:   PetscObjectQueryFunction((PetscObject)A,"MatDAADSetCtx_C",(void (**)(void))&f);
525:   if (f) {
526:     (*f)(A,ctx);
527:   }
528:   return(0);
529: }

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

537:    Collective on DA

539:    Input Parameters:
540: .  da - the DA that defines the distribution of the vectors

542:    Output Parameter:
543: .  A - the matrix 

545:    Level: intermediate

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

549: @*/
550: PetscErrorCode MatCreateDAAD(DA da,Mat *A)
551: {
553:   MPI_Comm comm;

556:   PetscObjectGetComm((PetscObject)da,&comm);
557:   MatCreate(comm,0,0,0,0,A);
558:   MatSetType(*A,MATDAAD);
559:   MatDAADSetDA(*A,da);
560:   return(0);
561: }

565: PetscErrorCode MatRegisterDAAD(void)
566: {
569:   MatRegisterDynamic(MATDAAD,PETSC_NULL,"MatCreate_DAAD",MatCreate_DAAD);
570:   return(0);
571: }