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,>dof);
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,>dof);
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,>dof);
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,>dof);
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: }