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: /*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: }