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:        0,
320: /*85*/ 0
321: };

323: /* --------------------------------------------------------------------------------*/

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

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

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

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

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

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

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

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

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

391:   Level: intermediate

393: .seealso: MatCreateDAAD
394: M*/

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

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

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


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

428:    Collective on Mat and DA

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

434:    Level: intermediate

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

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

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

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

458:    Collective on Mat and SNES

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

464:    Level: intermediate

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

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

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

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

488:    Collective on Mat

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

494:    Level: intermediate

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

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

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

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

518:    Collective on DA

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

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

526:    Level: intermediate

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

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

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

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