xref: /petsc/src/dm/impls/da/dalocal.c (revision 8b8307b2cbff7ae63ec0459e534a4a6ccda2943f)
1 #define PETSCDM_DLL
2 
3 /*
4   Code for manipulating distributed regular arrays in parallel.
5 */
6 
7 #include "private/daimpl.h"    /*I   "petscdm.h"   I*/
8 
9 /*
10    This allows the DMDA vectors to properly tell Matlab their dimensions
11 */
12 #if defined(PETSC_HAVE_MATLAB_ENGINE)
13 #include "engine.h"   /* Matlab include file */
14 #include "mex.h"      /* Matlab include file */
15 EXTERN_C_BEGIN
16 #undef __FUNCT__
17 #define __FUNCT__ "VecMatlabEnginePut_DA2d"
18 PetscErrorCode PETSCDM_DLLEXPORT VecMatlabEnginePut_DA2d(PetscObject obj,void *mengine)
19 {
20   PetscErrorCode ierr;
21   PetscInt       n,m;
22   Vec            vec = (Vec)obj;
23   PetscScalar    *array;
24   mxArray        *mat;
25   DM             da;
26 
27   PetscFunctionBegin;
28   ierr = PetscObjectQuery((PetscObject)vec,"DMDA",(PetscObject*)&da);CHKERRQ(ierr);
29   if (!da) SETERRQ(((PetscObject)vec)->comm,PETSC_ERR_ARG_WRONGSTATE,"Vector not associated with a DMDA");
30   ierr = DMDAGetGhostCorners(da,0,0,0,&m,&n,0);CHKERRQ(ierr);
31 
32   ierr = VecGetArray(vec,&array);CHKERRQ(ierr);
33 #if !defined(PETSC_USE_COMPLEX)
34   mat  = mxCreateDoubleMatrix(m,n,mxREAL);
35 #else
36   mat  = mxCreateDoubleMatrix(m,n,mxCOMPLEX);
37 #endif
38   ierr = PetscMemcpy(mxGetPr(mat),array,n*m*sizeof(PetscScalar));CHKERRQ(ierr);
39   ierr = PetscObjectName(obj);CHKERRQ(ierr);
40   engPutVariable((Engine *)mengine,obj->name,mat);
41 
42   ierr = VecRestoreArray(vec,&array);CHKERRQ(ierr);
43   PetscFunctionReturn(0);
44 }
45 EXTERN_C_END
46 #endif
47 
48 
49 #undef __FUNCT__
50 #define __FUNCT__ "DMCreateLocalVector_DA"
51 PetscErrorCode PETSCDM_DLLEXPORT DMCreateLocalVector_DA(DM da,Vec* g)
52 {
53   PetscErrorCode ierr;
54   DM_DA          *dd = (DM_DA*)da->data;
55 
56   PetscFunctionBegin;
57   PetscValidHeaderSpecific(da,DM_CLASSID,1);
58   PetscValidPointer(g,2);
59   ierr = VecCreate(PETSC_COMM_SELF,g);CHKERRQ(ierr);
60   ierr = VecSetSizes(*g,dd->nlocal,PETSC_DETERMINE);CHKERRQ(ierr);
61   ierr = VecSetType(*g,da->vectype);CHKERRQ(ierr);
62   ierr = VecSetBlockSize(*g,dd->w);CHKERRQ(ierr);
63   ierr = PetscObjectCompose((PetscObject)*g,"DMDA",(PetscObject)da);CHKERRQ(ierr);
64 #if defined(PETSC_HAVE_MATLAB_ENGINE)
65   if (dd->w == 1  && dd->dim == 2) {
66     ierr = PetscObjectComposeFunctionDynamic((PetscObject)*g,"PetscMatlabEnginePut_C","VecMatlabEnginePut_DA2d",VecMatlabEnginePut_DA2d);CHKERRQ(ierr);
67   }
68 #endif
69   PetscFunctionReturn(0);
70 }
71 
72 #undef __FUNCT__
73 #define __FUNCT__ "DMGetLocalVector"
74 /*@
75    DMGetLocalVector - Gets a Seq PETSc vector that
76    may be used with the DMXXX routines. This vector has spaces for the ghost values.
77 
78    Not Collective
79 
80    Input Parameter:
81 .  dm - the distributed array
82 
83    Output Parameter:
84 .  g - the local vector
85 
86    Level: beginner
87 
88    Note:
89    The vector values are NOT initialized and may have garbage in them, so you may need
90    to zero them.
91 
92    The output parameter, g, is a regular PETSc vector that should be returned with
93    DMRestoreLocalVector() DO NOT call VecDestroy() on it.
94 
95    VecStride*() operations can be useful when using DM with dof > 1
96 
97 .keywords: distributed array, create, local, vector
98 
99 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
100           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
101           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMRestoreLocalVector(),
102           VecStrideMax(), VecStrideMin(), VecStrideNorm()
103 @*/
104 PetscErrorCode PETSCDM_DLLEXPORT DMGetLocalVector(DM dm,Vec* g)
105 {
106   PetscErrorCode ierr,i;
107 
108   PetscFunctionBegin;
109   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
110   PetscValidPointer(g,2);
111   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
112     if (dm->localin[i]) {
113       *g             = dm->localin[i];
114       dm->localin[i] = PETSC_NULL;
115       goto alldone;
116     }
117   }
118   ierr = DMCreateLocalVector(dm,g);CHKERRQ(ierr);
119 
120   alldone:
121   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
122     if (!dm->localout[i]) {
123       dm->localout[i] = *g;
124       break;
125     }
126   }
127   PetscFunctionReturn(0);
128 }
129 
130 #undef __FUNCT__
131 #define __FUNCT__ "DMRestoreLocalVector"
132 /*@
133    DMRestoreLocalVector - Returns a Seq PETSc vector that
134      obtained from DMGetLocalVector(). Do not use with vector obtained via
135      DMCreateLocalVector().
136 
137    Not Collective
138 
139    Input Parameter:
140 +  dm - the distributed array
141 -  g - the local vector
142 
143    Level: beginner
144 
145 .keywords: distributed array, create, local, vector
146 
147 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
148           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
149           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMGetLocalVector()
150 @*/
151 PetscErrorCode PETSCDM_DLLEXPORT DMRestoreLocalVector(DM dm,Vec* g)
152 {
153   PetscErrorCode ierr;
154   PetscInt       i,j;
155 
156   PetscFunctionBegin;
157   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
158   PetscValidPointer(g,2);
159   for (j=0; j<DM_MAX_WORK_VECTORS; j++) {
160     if (*g == dm->localout[j]) {
161       dm->localout[j] = PETSC_NULL;
162       for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
163         if (!dm->localin[i]) {
164           dm->localin[i] = *g;
165           goto alldone;
166         }
167       }
168     }
169   }
170   ierr = VecDestroy(*g);CHKERRQ(ierr);
171   alldone:
172   PetscFunctionReturn(0);
173 }
174 
175 #undef __FUNCT__
176 #define __FUNCT__ "DMGetGlobalVector"
177 /*@
178    DMGetGlobalVector - Gets a MPI PETSc vector that
179    may be used with the DMXXX routines.
180 
181    Collective on DM
182 
183    Input Parameter:
184 .  dm - the distributed array
185 
186    Output Parameter:
187 .  g - the global vector
188 
189    Level: beginner
190 
191    Note:
192    The vector values are NOT initialized and may have garbage in them, so you may need
193    to zero them.
194 
195    The output parameter, g, is a regular PETSc vector that should be returned with
196    DMRestoreGlobalVector() DO NOT call VecDestroy() on it.
197 
198    VecStride*() operations can be useful when using DM with dof > 1
199 
200 .keywords: distributed array, create, Global, vector
201 
202 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
203           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToLocalBegin(),
204           DMGlobalToLocalEnd(), DMLocalToGlobalBegin(), DMCreateLocalVector(), DMRestoreLocalVector()
205           VecStrideMax(), VecStrideMin(), VecStrideNorm()
206 
207 @*/
208 PetscErrorCode PETSCDM_DLLEXPORT DMGetGlobalVector(DM dm,Vec* g)
209 {
210   PetscErrorCode ierr;
211   PetscInt       i;
212 
213   PetscFunctionBegin;
214   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
215   PetscValidPointer(g,2);
216   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
217     if (dm->globalin[i]) {
218       *g             = dm->globalin[i];
219       dm->globalin[i] = PETSC_NULL;
220       goto alldone;
221     }
222   }
223   ierr = DMCreateGlobalVector(dm,g);CHKERRQ(ierr);
224 
225   alldone:
226   for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
227     if (!dm->globalout[i]) {
228       dm->globalout[i] = *g;
229       break;
230     }
231   }
232   PetscFunctionReturn(0);
233 }
234 
235 #undef __FUNCT__
236 #define __FUNCT__ "DMRestoreGlobalVector"
237 /*@
238    DMRestoreGlobalVector - Returns a Seq PETSc vector that
239      obtained from DMGetGlobalVector(). Do not use with vector obtained via
240      DMCreateGlobalVector().
241 
242    Not Collective
243 
244    Input Parameter:
245 +  dm - the distributed array
246 -  g - the global vector
247 
248    Level: beginner
249 
250 .keywords: distributed array, create, global, vector
251 
252 .seealso: DMCreateGlobalVector(), VecDuplicate(), VecDuplicateVecs(),
253           DMDACreate1d(), DMDACreate2d(), DMDACreate3d(), DMGlobalToGlobalBegin(),
254           DMGlobalToGlobalEnd(), DMGlobalToGlobal(), DMCreateLocalVector(), DMGetGlobalVector()
255 @*/
256 PetscErrorCode PETSCDM_DLLEXPORT DMRestoreGlobalVector(DM dm,Vec* g)
257 {
258   PetscErrorCode ierr;
259   PetscInt       i,j;
260 
261   PetscFunctionBegin;
262   PetscValidHeaderSpecific(dm,DM_CLASSID,1);
263   PetscValidPointer(g,2);
264   for (j=0; j<DM_MAX_WORK_VECTORS; j++) {
265     if (*g == dm->globalout[j]) {
266       dm->globalout[j] = PETSC_NULL;
267       for (i=0; i<DM_MAX_WORK_VECTORS; i++) {
268         if (!dm->globalin[i]) {
269           dm->globalin[i] = *g;
270           goto alldone;
271         }
272       }
273     }
274   }
275   ierr = VecDestroy(*g);CHKERRQ(ierr);
276   alldone:
277   PetscFunctionReturn(0);
278 }
279 
280 /* ------------------------------------------------------------------- */
281 #if defined(PETSC_HAVE_ADIC)
282 
283 EXTERN_C_BEGIN
284 #include "adic/ad_utils.h"
285 EXTERN_C_END
286 
287 #undef __FUNCT__
288 #define __FUNCT__ "DMDAGetAdicArray"
289 /*@C
290      DMDAGetAdicArray - Gets an array of derivative types for a DMDA
291 
292     Input Parameter:
293 +    da - information about my local patch
294 -    ghosted - do you want arrays for the ghosted or nonghosted patch
295 
296     Output Parameters:
297 +    vptr - array data structured to be passed to ad_FormFunctionLocal()
298 .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
299 -    tdof - total number of degrees of freedom represented in array_start (may be null)
300 
301      Notes:
302        The vector values are NOT initialized and may have garbage in them, so you may need
303        to zero them.
304 
305        Returns the same type of object as the DMDAVecGetArray() except its elements are
306            derivative types instead of PetscScalars
307 
308      Level: advanced
309 
310 .seealso: DMDARestoreAdicArray()
311 
312 @*/
313 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetAdicArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
314 {
315   PetscErrorCode ierr;
316   PetscInt       j,i,deriv_type_size,xs,ys,xm,ym,zs,zm,itdof;
317   char           *iarray_start;
318   void           **iptr = (void**)vptr;
319   DM_DA          *dd = (DM_DA*)da->data;
320 
321   PetscFunctionBegin;
322   PetscValidHeaderSpecific(da,DM_CLASSID,1);
323   if (ghosted) {
324     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
325       if (dd->adarrayghostedin[i]) {
326         *iptr                   = dd->adarrayghostedin[i];
327         iarray_start            = (char*)dd->adstartghostedin[i];
328         itdof                   = dd->ghostedtdof;
329         dd->adarrayghostedin[i] = PETSC_NULL;
330         dd->adstartghostedin[i] = PETSC_NULL;
331 
332         goto done;
333       }
334     }
335     xs = dd->Xs;
336     ys = dd->Ys;
337     zs = dd->Zs;
338     xm = dd->Xe-dd->Xs;
339     ym = dd->Ye-dd->Ys;
340     zm = dd->Ze-dd->Zs;
341   } else {
342     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
343       if (dd->adarrayin[i]) {
344         *iptr            = dd->adarrayin[i];
345         iarray_start     = (char*)dd->adstartin[i];
346         itdof            = dd->tdof;
347         dd->adarrayin[i] = PETSC_NULL;
348         dd->adstartin[i] = PETSC_NULL;
349 
350         goto done;
351       }
352     }
353     xs = dd->xs;
354     ys = dd->ys;
355     zs = dd->zs;
356     xm = dd->xe-dd->xs;
357     ym = dd->ye-dd->ys;
358     zm = dd->ze-dd->zs;
359   }
360   deriv_type_size = PetscADGetDerivTypeSize();
361 
362   switch (dd->dim) {
363     case 1: {
364       void *ptr;
365       itdof = xm;
366 
367       ierr  = PetscMalloc(xm*deriv_type_size,&iarray_start);CHKERRQ(ierr);
368 
369       ptr   = (void*)(iarray_start - xs*deriv_type_size);
370       *iptr = (void*)ptr;
371       break;}
372     case 2: {
373       void **ptr;
374       itdof = xm*ym;
375 
376       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*deriv_type_size,&iarray_start);CHKERRQ(ierr);
377 
378       ptr  = (void**)(iarray_start + xm*ym*deriv_type_size - ys*sizeof(void*));
379       for(j=ys;j<ys+ym;j++) {
380         ptr[j] = iarray_start + deriv_type_size*(xm*(j-ys) - xs);
381       }
382       *iptr = (void*)ptr;
383       break;}
384     case 3: {
385       void ***ptr,**bptr;
386       itdof = xm*ym*zm;
387 
388       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*deriv_type_size,&iarray_start);CHKERRQ(ierr);
389 
390       ptr  = (void***)(iarray_start + xm*ym*zm*deriv_type_size - zs*sizeof(void*));
391       bptr = (void**)(iarray_start + xm*ym*zm*deriv_type_size + zm*sizeof(void**));
392 
393       for(i=zs;i<zs+zm;i++) {
394         ptr[i] = bptr + ((i-zs)*ym - ys);
395       }
396       for (i=zs; i<zs+zm; i++) {
397         for (j=ys; j<ys+ym; j++) {
398           ptr[i][j] = iarray_start + deriv_type_size*(xm*ym*(i-zs) + xm*(j-ys) - xs);
399         }
400       }
401 
402       *iptr = (void*)ptr;
403       break;}
404     default:
405       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
406   }
407 
408   done:
409   /* add arrays to the checked out list */
410   if (ghosted) {
411     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
412       if (!dd->adarrayghostedout[i]) {
413         dd->adarrayghostedout[i] = *iptr ;
414         dd->adstartghostedout[i] = iarray_start;
415         dd->ghostedtdof          = itdof;
416         break;
417       }
418     }
419   } else {
420     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
421       if (!dd->adarrayout[i]) {
422         dd->adarrayout[i] = *iptr ;
423         dd->adstartout[i] = iarray_start;
424         dd->tdof          = itdof;
425         break;
426       }
427     }
428   }
429   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"Too many DMDA ADIC arrays obtained");
430   if (tdof)        *tdof = itdof;
431   if (array_start) *(void**)array_start = iarray_start;
432   PetscFunctionReturn(0);
433 }
434 
435 #undef __FUNCT__
436 #define __FUNCT__ "DMDARestoreAdicArray"
437 /*@C
438      DMDARestoreAdicArray - Restores an array of derivative types for a DMDA
439 
440     Input Parameter:
441 +    da - information about my local patch
442 -    ghosted - do you want arrays for the ghosted or nonghosted patch
443 
444     Output Parameters:
445 +    ptr - array data structured to be passed to ad_FormFunctionLocal()
446 .    array_start - actual start of 1d array of all values that adiC can access directly
447 -    tdof - total number of degrees of freedom represented in array_start
448 
449      Level: advanced
450 
451 .seealso: DMDAGetAdicArray()
452 
453 @*/
454 PetscErrorCode PETSCDM_DLLEXPORT DMDARestoreAdicArray(DM da,PetscBool  ghosted,void *ptr,void *array_start,PetscInt *tdof)
455 {
456   PetscInt  i;
457   void      **iptr = (void**)ptr,iarray_start = 0;
458 
459   PetscFunctionBegin;
460   PetscValidHeaderSpecific(da,DM_CLASSID,1);
461   if (ghosted) {
462     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
463       if (dd->adarrayghostedout[i] == *iptr) {
464         iarray_start             = dd->adstartghostedout[i];
465         dd->adarrayghostedout[i] = PETSC_NULL;
466         dd->adstartghostedout[i] = PETSC_NULL;
467         break;
468       }
469     }
470     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
471     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
472       if (!dd->adarrayghostedin[i]){
473         dd->adarrayghostedin[i] = *iptr;
474         dd->adstartghostedin[i] = iarray_start;
475         break;
476       }
477     }
478   } else {
479     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
480       if (dd->adarrayout[i] == *iptr) {
481         iarray_start      = dd->adstartout[i];
482         dd->adarrayout[i] = PETSC_NULL;
483         dd->adstartout[i] = PETSC_NULL;
484         break;
485       }
486     }
487     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
488     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
489       if (!dd->adarrayin[i]){
490         dd->adarrayin[i]   = *iptr;
491         dd->adstartin[i]   = iarray_start;
492         break;
493       }
494     }
495   }
496   PetscFunctionReturn(0);
497 }
498 
499 #undef __FUNCT__
500 #define __FUNCT__ "ad_DAGetArray"
501 PetscErrorCode PETSCDM_DLLEXPORT ad_DAGetArray(DM da,PetscBool  ghosted,void *iptr)
502 {
503   PetscErrorCode ierr;
504   PetscFunctionBegin;
505   ierr = DMDAGetAdicArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
506   PetscFunctionReturn(0);
507 }
508 
509 #undef __FUNCT__
510 #define __FUNCT__ "ad_DARestoreArray"
511 PetscErrorCode PETSCDM_DLLEXPORT ad_DARestoreArray(DM da,PetscBool  ghosted,void *iptr)
512 {
513   PetscErrorCode ierr;
514   PetscFunctionBegin;
515   ierr = DMDARestoreAdicArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
516   PetscFunctionReturn(0);
517 }
518 
519 #endif
520 
521 #undef __FUNCT__
522 #define __FUNCT__ "DMDAGetArray"
523 /*@C
524      DMDAGetArray - Gets a work array for a DMDA
525 
526     Input Parameter:
527 +    da - information about my local patch
528 -    ghosted - do you want arrays for the ghosted or nonghosted patch
529 
530     Output Parameters:
531 .    vptr - array data structured
532 
533     Note:  The vector values are NOT initialized and may have garbage in them, so you may need
534            to zero them.
535 
536   Level: advanced
537 
538 .seealso: DMDARestoreArray(), DMDAGetAdicArray()
539 
540 @*/
541 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetArray(DM da,PetscBool  ghosted,void *vptr)
542 {
543   PetscErrorCode ierr;
544   PetscInt       j,i,xs,ys,xm,ym,zs,zm;
545   char           *iarray_start;
546   void           **iptr = (void**)vptr;
547   DM_DA          *dd = (DM_DA*)da->data;
548 
549   PetscFunctionBegin;
550   PetscValidHeaderSpecific(da,DM_CLASSID,1);
551   if (ghosted) {
552     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
553       if (dd->arrayghostedin[i]) {
554         *iptr                 = dd->arrayghostedin[i];
555         iarray_start          = (char*)dd->startghostedin[i];
556         dd->arrayghostedin[i] = PETSC_NULL;
557         dd->startghostedin[i] = PETSC_NULL;
558 
559         goto done;
560       }
561     }
562     xs = dd->Xs;
563     ys = dd->Ys;
564     zs = dd->Zs;
565     xm = dd->Xe-dd->Xs;
566     ym = dd->Ye-dd->Ys;
567     zm = dd->Ze-dd->Zs;
568   } else {
569     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
570       if (dd->arrayin[i]) {
571         *iptr          = dd->arrayin[i];
572         iarray_start   = (char*)dd->startin[i];
573         dd->arrayin[i] = PETSC_NULL;
574         dd->startin[i] = PETSC_NULL;
575 
576         goto done;
577       }
578     }
579     xs = dd->xs;
580     ys = dd->ys;
581     zs = dd->zs;
582     xm = dd->xe-dd->xs;
583     ym = dd->ye-dd->ys;
584     zm = dd->ze-dd->zs;
585   }
586 
587   switch (dd->dim) {
588     case 1: {
589       void *ptr;
590 
591       ierr  = PetscMalloc(xm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
592 
593       ptr   = (void*)(iarray_start - xs*sizeof(PetscScalar));
594       *iptr = (void*)ptr;
595       break;}
596     case 2: {
597       void **ptr;
598 
599       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
600 
601       ptr  = (void**)(iarray_start + xm*ym*sizeof(PetscScalar) - ys*sizeof(void*));
602       for(j=ys;j<ys+ym;j++) {
603         ptr[j] = iarray_start + sizeof(PetscScalar)*(xm*(j-ys) - xs);
604       }
605       *iptr = (void*)ptr;
606       break;}
607     case 3: {
608       void ***ptr,**bptr;
609 
610       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
611 
612       ptr  = (void***)(iarray_start + xm*ym*zm*sizeof(PetscScalar) - zs*sizeof(void*));
613       bptr = (void**)(iarray_start + xm*ym*zm*sizeof(PetscScalar) + zm*sizeof(void**));
614       for(i=zs;i<zs+zm;i++) {
615         ptr[i] = bptr + ((i-zs)*ym - ys);
616       }
617       for (i=zs; i<zs+zm; i++) {
618         for (j=ys; j<ys+ym; j++) {
619           ptr[i][j] = iarray_start + sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
620         }
621       }
622 
623       *iptr = (void*)ptr;
624       break;}
625     default:
626       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
627   }
628 
629   done:
630   /* add arrays to the checked out list */
631   if (ghosted) {
632     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
633       if (!dd->arrayghostedout[i]) {
634         dd->arrayghostedout[i] = *iptr ;
635         dd->startghostedout[i] = iarray_start;
636         break;
637       }
638     }
639   } else {
640     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
641       if (!dd->arrayout[i]) {
642         dd->arrayout[i] = *iptr ;
643         dd->startout[i] = iarray_start;
644         break;
645       }
646     }
647   }
648   PetscFunctionReturn(0);
649 }
650 
651 #undef __FUNCT__
652 #define __FUNCT__ "DMDARestoreArray"
653 /*@C
654      DMDARestoreArray - Restores an array of derivative types for a DMDA
655 
656     Input Parameter:
657 +    da - information about my local patch
658 .    ghosted - do you want arrays for the ghosted or nonghosted patch
659 -    vptr - array data structured to be passed to ad_FormFunctionLocal()
660 
661      Level: advanced
662 
663 .seealso: DMDAGetArray(), DMDAGetAdicArray()
664 
665 @*/
666 PetscErrorCode PETSCDM_DLLEXPORT DMDARestoreArray(DM da,PetscBool  ghosted,void *vptr)
667 {
668   PetscInt  i;
669   void      **iptr = (void**)vptr,*iarray_start = 0;
670   DM_DA     *dd = (DM_DA*)da->data;
671 
672   PetscFunctionBegin;
673   PetscValidHeaderSpecific(da,DM_CLASSID,1);
674   if (ghosted) {
675     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
676       if (dd->arrayghostedout[i] == *iptr) {
677         iarray_start           = dd->startghostedout[i];
678         dd->arrayghostedout[i] = PETSC_NULL;
679         dd->startghostedout[i] = PETSC_NULL;
680         break;
681       }
682     }
683     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
684       if (!dd->arrayghostedin[i]){
685         dd->arrayghostedin[i] = *iptr;
686         dd->startghostedin[i] = iarray_start;
687         break;
688       }
689     }
690   } else {
691     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
692       if (dd->arrayout[i] == *iptr) {
693         iarray_start    = dd->startout[i];
694         dd->arrayout[i] = PETSC_NULL;
695         dd->startout[i] = PETSC_NULL;
696         break;
697       }
698     }
699     for (i=0; i<DMDA_MAX_WORK_ARRAYS; i++) {
700       if (!dd->arrayin[i]){
701         dd->arrayin[i]  = *iptr;
702         dd->startin[i]  = iarray_start;
703         break;
704       }
705     }
706   }
707   PetscFunctionReturn(0);
708 }
709 
710 #undef __FUNCT__
711 #define __FUNCT__ "DMDAGetAdicMFArray"
712 /*@C
713      DMDAGetAdicMFArray - Gets an array of derivative types for a DMDA for matrix-free ADIC.
714 
715      Input Parameter:
716 +    da - information about my local patch
717 -    ghosted - do you want arrays for the ghosted or nonghosted patch?
718 
719      Output Parameters:
720 +    vptr - array data structured to be passed to ad_FormFunctionLocal()
721 .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
722 -    tdof - total number of degrees of freedom represented in array_start (may be null)
723 
724      Notes:
725      The vector values are NOT initialized and may have garbage in them, so you may need
726      to zero them.
727 
728      This routine returns the same type of object as the DMDAVecGetArray(), except its
729      elements are derivative types instead of PetscScalars.
730 
731      Level: advanced
732 
733 .seealso: DMDARestoreAdicMFArray(), DMDAGetArray(), DMDAGetAdicArray()
734 
735 @*/
736 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetAdicMFArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
737 {
738   PetscErrorCode ierr;
739   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
740   char           *iarray_start;
741   void           **iptr = (void**)vptr;
742   DM_DA          *dd = (DM_DA*)da->data;
743 
744   PetscFunctionBegin;
745   PetscValidHeaderSpecific(da,DM_CLASSID,1);
746   if (ghosted) {
747     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
748       if (dd->admfarrayghostedin[i]) {
749         *iptr                     = dd->admfarrayghostedin[i];
750         iarray_start              = (char*)dd->admfstartghostedin[i];
751         itdof                     = dd->ghostedtdof;
752         dd->admfarrayghostedin[i] = PETSC_NULL;
753         dd->admfstartghostedin[i] = PETSC_NULL;
754 
755         goto done;
756       }
757     }
758     xs = dd->Xs;
759     ys = dd->Ys;
760     zs = dd->Zs;
761     xm = dd->Xe-dd->Xs;
762     ym = dd->Ye-dd->Ys;
763     zm = dd->Ze-dd->Zs;
764   } else {
765     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
766       if (dd->admfarrayin[i]) {
767         *iptr              = dd->admfarrayin[i];
768         iarray_start       = (char*)dd->admfstartin[i];
769         itdof              = dd->tdof;
770         dd->admfarrayin[i] = PETSC_NULL;
771         dd->admfstartin[i] = PETSC_NULL;
772 
773         goto done;
774       }
775     }
776     xs = dd->xs;
777     ys = dd->ys;
778     zs = dd->zs;
779     xm = dd->xe-dd->xs;
780     ym = dd->ye-dd->ys;
781     zm = dd->ze-dd->zs;
782   }
783 
784   switch (dd->dim) {
785     case 1: {
786       void *ptr;
787       itdof = xm;
788 
789       ierr  = PetscMalloc(xm*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
790 
791       ptr   = (void*)(iarray_start - xs*2*sizeof(PetscScalar));
792       *iptr = (void*)ptr;
793       break;}
794     case 2: {
795       void **ptr;
796       itdof = xm*ym;
797 
798       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
799 
800       ptr  = (void**)(iarray_start + xm*ym*2*sizeof(PetscScalar) - ys*sizeof(void*));
801       for(j=ys;j<ys+ym;j++) {
802         ptr[j] = iarray_start + 2*sizeof(PetscScalar)*(xm*(j-ys) - xs);
803       }
804       *iptr = (void*)ptr;
805       break;}
806     case 3: {
807       void ***ptr,**bptr;
808       itdof = xm*ym*zm;
809 
810       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*2*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
811 
812       ptr  = (void***)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) - zs*sizeof(void*));
813       bptr = (void**)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) + zm*sizeof(void**));
814       for(i=zs;i<zs+zm;i++) {
815         ptr[i] = bptr + ((i-zs)*ym* - ys)*sizeof(void*);
816       }
817       for (i=zs; i<zs+zm; i++) {
818         for (j=ys; j<ys+ym; j++) {
819           ptr[i][j] = iarray_start + 2*sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
820         }
821       }
822 
823       *iptr = (void*)ptr;
824       break;}
825     default:
826       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
827   }
828 
829   done:
830   /* add arrays to the checked out list */
831   if (ghosted) {
832     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
833       if (!dd->admfarrayghostedout[i]) {
834         dd->admfarrayghostedout[i] = *iptr ;
835         dd->admfstartghostedout[i] = iarray_start;
836         dd->ghostedtdof            = itdof;
837         break;
838       }
839     }
840   } else {
841     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
842       if (!dd->admfarrayout[i]) {
843         dd->admfarrayout[i] = *iptr ;
844         dd->admfstartout[i] = iarray_start;
845         dd->tdof            = itdof;
846         break;
847       }
848     }
849   }
850   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(((PetscObject)da)->comm,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
851   if (tdof)        *tdof = itdof;
852   if (array_start) *(void**)array_start = iarray_start;
853   PetscFunctionReturn(0);
854 }
855 
856 #undef __FUNCT__
857 #define __FUNCT__ "DMDAGetAdicMFArray4"
858 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetAdicMFArray4(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
859 {
860   PetscErrorCode ierr;
861   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
862   char           *iarray_start;
863   void           **iptr = (void**)vptr;
864   DM_DA          *dd = (DM_DA*)da->data;
865 
866   PetscFunctionBegin;
867   PetscValidHeaderSpecific(da,DM_CLASSID,1);
868   if (ghosted) {
869     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
870       if (dd->admfarrayghostedin[i]) {
871         *iptr                     = dd->admfarrayghostedin[i];
872         iarray_start              = (char*)dd->admfstartghostedin[i];
873         itdof                     = dd->ghostedtdof;
874         dd->admfarrayghostedin[i] = PETSC_NULL;
875         dd->admfstartghostedin[i] = PETSC_NULL;
876 
877         goto done;
878       }
879     }
880     xs = dd->Xs;
881     ys = dd->Ys;
882     zs = dd->Zs;
883     xm = dd->Xe-dd->Xs;
884     ym = dd->Ye-dd->Ys;
885     zm = dd->Ze-dd->Zs;
886   } else {
887     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
888       if (dd->admfarrayin[i]) {
889         *iptr              = dd->admfarrayin[i];
890         iarray_start       = (char*)dd->admfstartin[i];
891         itdof              = dd->tdof;
892         dd->admfarrayin[i] = PETSC_NULL;
893         dd->admfstartin[i] = PETSC_NULL;
894 
895         goto done;
896       }
897     }
898     xs = dd->xs;
899     ys = dd->ys;
900     zs = dd->zs;
901     xm = dd->xe-dd->xs;
902     ym = dd->ye-dd->ys;
903     zm = dd->ze-dd->zs;
904   }
905 
906   switch (dd->dim) {
907     case 2: {
908       void **ptr;
909       itdof = xm*ym;
910 
911       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*5*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
912 
913       ptr  = (void**)(iarray_start + xm*ym*5*sizeof(PetscScalar) - ys*sizeof(void*));
914       for(j=ys;j<ys+ym;j++) {
915         ptr[j] = iarray_start + 5*sizeof(PetscScalar)*(xm*(j-ys) - xs);
916       }
917       *iptr = (void*)ptr;
918       break;}
919     default:
920       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
921   }
922 
923   done:
924   /* add arrays to the checked out list */
925   if (ghosted) {
926     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
927       if (!dd->admfarrayghostedout[i]) {
928         dd->admfarrayghostedout[i] = *iptr ;
929         dd->admfstartghostedout[i] = iarray_start;
930         dd->ghostedtdof            = itdof;
931         break;
932       }
933     }
934   } else {
935     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
936       if (!dd->admfarrayout[i]) {
937         dd->admfarrayout[i] = *iptr ;
938         dd->admfstartout[i] = iarray_start;
939         dd->tdof            = itdof;
940         break;
941       }
942     }
943   }
944   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
945   if (tdof)        *tdof = itdof;
946   if (array_start) *(void**)array_start = iarray_start;
947   PetscFunctionReturn(0);
948 }
949 
950 #undef __FUNCT__
951 #define __FUNCT__ "DMDAGetAdicMFArray9"
952 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetAdicMFArray9(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
953 {
954   PetscErrorCode ierr;
955   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
956   char           *iarray_start;
957   void           **iptr = (void**)vptr;
958   DM_DA          *dd = (DM_DA*)da->data;
959 
960   PetscFunctionBegin;
961   PetscValidHeaderSpecific(da,DM_CLASSID,1);
962   if (ghosted) {
963     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
964       if (dd->admfarrayghostedin[i]) {
965         *iptr                     = dd->admfarrayghostedin[i];
966         iarray_start              = (char*)dd->admfstartghostedin[i];
967         itdof                     = dd->ghostedtdof;
968         dd->admfarrayghostedin[i] = PETSC_NULL;
969         dd->admfstartghostedin[i] = PETSC_NULL;
970 
971         goto done;
972       }
973     }
974     xs = dd->Xs;
975     ys = dd->Ys;
976     zs = dd->Zs;
977     xm = dd->Xe-dd->Xs;
978     ym = dd->Ye-dd->Ys;
979     zm = dd->Ze-dd->Zs;
980   } else {
981     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
982       if (dd->admfarrayin[i]) {
983         *iptr              = dd->admfarrayin[i];
984         iarray_start       = (char*)dd->admfstartin[i];
985         itdof              = dd->tdof;
986         dd->admfarrayin[i] = PETSC_NULL;
987         dd->admfstartin[i] = PETSC_NULL;
988 
989         goto done;
990       }
991     }
992     xs = dd->xs;
993     ys = dd->ys;
994     zs = dd->zs;
995     xm = dd->xe-dd->xs;
996     ym = dd->ye-dd->ys;
997     zm = dd->ze-dd->zs;
998   }
999 
1000   switch (dd->dim) {
1001     case 2: {
1002       void **ptr;
1003       itdof = xm*ym;
1004 
1005       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*10*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
1006 
1007       ptr  = (void**)(iarray_start + xm*ym*10*sizeof(PetscScalar) - ys*sizeof(void*));
1008       for(j=ys;j<ys+ym;j++) {
1009         ptr[j] = iarray_start + 10*sizeof(PetscScalar)*(xm*(j-ys) - xs);
1010       }
1011       *iptr = (void*)ptr;
1012       break;}
1013     default:
1014       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
1015   }
1016 
1017   done:
1018   /* add arrays to the checked out list */
1019   if (ghosted) {
1020     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1021       if (!dd->admfarrayghostedout[i]) {
1022         dd->admfarrayghostedout[i] = *iptr ;
1023         dd->admfstartghostedout[i] = iarray_start;
1024         dd->ghostedtdof            = itdof;
1025         break;
1026       }
1027     }
1028   } else {
1029     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1030       if (!dd->admfarrayout[i]) {
1031         dd->admfarrayout[i] = *iptr ;
1032         dd->admfstartout[i] = iarray_start;
1033         dd->tdof            = itdof;
1034         break;
1035       }
1036     }
1037   }
1038   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
1039   if (tdof)        *tdof = itdof;
1040   if (array_start) *(void**)array_start = iarray_start;
1041   PetscFunctionReturn(0);
1042 }
1043 
1044 #undef __FUNCT__
1045 #define __FUNCT__ "DMDAGetAdicMFArrayb"
1046 /*@C
1047      DMDAGetAdicMFArrayb - Gets an array of derivative types for a DMDA for matrix-free ADIC.
1048 
1049      Input Parameter:
1050 +    da - information about my local patch
1051 -    ghosted - do you want arrays for the ghosted or nonghosted patch?
1052 
1053      Output Parameters:
1054 +    vptr - array data structured to be passed to ad_FormFunctionLocal()
1055 .    array_start - actual start of 1d array of all values that adiC can access directly (may be null)
1056 -    tdof - total number of degrees of freedom represented in array_start (may be null)
1057 
1058      Notes:
1059      The vector values are NOT initialized and may have garbage in them, so you may need
1060      to zero them.
1061 
1062      This routine returns the same type of object as the DMDAVecGetArray(), except its
1063      elements are derivative types instead of PetscScalars.
1064 
1065      Level: advanced
1066 
1067 .seealso: DMDARestoreAdicMFArray(), DMDAGetArray(), DMDAGetAdicArray()
1068 
1069 @*/
1070 PetscErrorCode PETSCDM_DLLEXPORT DMDAGetAdicMFArrayb(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
1071 {
1072   PetscErrorCode ierr;
1073   PetscInt       j,i,xs,ys,xm,ym,zs,zm,itdof = 0;
1074   char           *iarray_start;
1075   void           **iptr = (void**)vptr;
1076   DM_DA          *dd = (DM_DA*)da->data;
1077   PetscInt       bs = dd->w,bs1 = bs+1;
1078 
1079   PetscFunctionBegin;
1080   PetscValidHeaderSpecific(da,DM_CLASSID,1);
1081   if (ghosted) {
1082     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1083       if (dd->admfarrayghostedin[i]) {
1084         *iptr                     = dd->admfarrayghostedin[i];
1085         iarray_start              = (char*)dd->admfstartghostedin[i];
1086         itdof                     = dd->ghostedtdof;
1087         dd->admfarrayghostedin[i] = PETSC_NULL;
1088         dd->admfstartghostedin[i] = PETSC_NULL;
1089 
1090         goto done;
1091       }
1092     }
1093     xs = dd->Xs;
1094     ys = dd->Ys;
1095     zs = dd->Zs;
1096     xm = dd->Xe-dd->Xs;
1097     ym = dd->Ye-dd->Ys;
1098     zm = dd->Ze-dd->Zs;
1099   } else {
1100     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1101       if (dd->admfarrayin[i]) {
1102         *iptr              = dd->admfarrayin[i];
1103         iarray_start       = (char*)dd->admfstartin[i];
1104         itdof              = dd->tdof;
1105         dd->admfarrayin[i] = PETSC_NULL;
1106         dd->admfstartin[i] = PETSC_NULL;
1107 
1108         goto done;
1109       }
1110     }
1111     xs = dd->xs;
1112     ys = dd->ys;
1113     zs = dd->zs;
1114     xm = dd->xe-dd->xs;
1115     ym = dd->ye-dd->ys;
1116     zm = dd->ze-dd->zs;
1117   }
1118 
1119   switch (dd->dim) {
1120     case 1: {
1121       void *ptr;
1122       itdof = xm;
1123 
1124       ierr  = PetscMalloc(xm*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
1125 
1126       ptr   = (void*)(iarray_start - xs*bs1*sizeof(PetscScalar));
1127       *iptr = (void*)ptr;
1128       break;}
1129     case 2: {
1130       void **ptr;
1131       itdof = xm*ym;
1132 
1133       ierr  = PetscMalloc((ym+1)*sizeof(void*)+xm*ym*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
1134 
1135       ptr  = (void**)(iarray_start + xm*ym*bs1*sizeof(PetscScalar) - ys*sizeof(void*));
1136       for(j=ys;j<ys+ym;j++) {
1137         ptr[j] = iarray_start + bs1*sizeof(PetscScalar)*(xm*(j-ys) - xs);
1138       }
1139       *iptr = (void*)ptr;
1140       break;}
1141     case 3: {
1142       void ***ptr,**bptr;
1143       itdof = xm*ym*zm;
1144 
1145       ierr  = PetscMalloc((zm+1)*sizeof(void **)+(ym*zm+1)*sizeof(void*)+xm*ym*zm*bs1*sizeof(PetscScalar),&iarray_start);CHKERRQ(ierr);
1146 
1147       ptr  = (void***)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) - zs*sizeof(void*));
1148       bptr = (void**)(iarray_start + xm*ym*zm*2*sizeof(PetscScalar) + zm*sizeof(void**));
1149       for(i=zs;i<zs+zm;i++) {
1150         ptr[i] = bptr + ((i-zs)*ym* - ys)*sizeof(void*);
1151       }
1152       for (i=zs; i<zs+zm; i++) {
1153         for (j=ys; j<ys+ym; j++) {
1154           ptr[i][j] = iarray_start + bs1*sizeof(PetscScalar)*(xm*ym*(i-zs) + xm*(j-ys) - xs);
1155         }
1156       }
1157 
1158       *iptr = (void*)ptr;
1159       break;}
1160     default:
1161       SETERRQ1(((PetscObject)da)->comm,PETSC_ERR_SUP,"Dimension %D not supported",dd->dim);
1162   }
1163 
1164   done:
1165   /* add arrays to the checked out list */
1166   if (ghosted) {
1167     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1168       if (!dd->admfarrayghostedout[i]) {
1169         dd->admfarrayghostedout[i] = *iptr ;
1170         dd->admfstartghostedout[i] = iarray_start;
1171         dd->ghostedtdof            = itdof;
1172         break;
1173       }
1174     }
1175   } else {
1176     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1177       if (!dd->admfarrayout[i]) {
1178         dd->admfarrayout[i] = *iptr ;
1179         dd->admfstartout[i] = iarray_start;
1180         dd->tdof            = itdof;
1181         break;
1182       }
1183     }
1184   }
1185   if (i == DMDA_MAX_AD_ARRAYS+1) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Too many DMDA ADIC arrays obtained");
1186   if (tdof)        *tdof = itdof;
1187   if (array_start) *(void**)array_start = iarray_start;
1188   PetscFunctionReturn(0);
1189 }
1190 
1191 #undef __FUNCT__
1192 #define __FUNCT__ "DMDARestoreAdicMFArray"
1193 /*@C
1194      DMDARestoreAdicMFArray - Restores an array of derivative types for a DMDA.
1195 
1196      Input Parameter:
1197 +    da - information about my local patch
1198 -    ghosted - do you want arrays for the ghosted or nonghosted patch?
1199 
1200      Output Parameters:
1201 +    ptr - array data structure to be passed to ad_FormFunctionLocal()
1202 .    array_start - actual start of 1d array of all values that adiC can access directly
1203 -    tdof - total number of degrees of freedom represented in array_start
1204 
1205      Level: advanced
1206 
1207 .seealso: DMDAGetAdicArray()
1208 
1209 @*/
1210 PetscErrorCode PETSCDM_DLLEXPORT DMDARestoreAdicMFArray(DM da,PetscBool  ghosted,void *vptr,void *array_start,PetscInt *tdof)
1211 {
1212   PetscInt  i;
1213   void      **iptr = (void**)vptr,*iarray_start = 0;
1214   DM_DA     *dd = (DM_DA*)da->data;
1215 
1216   PetscFunctionBegin;
1217   PetscValidHeaderSpecific(da,DM_CLASSID,1);
1218   if (ghosted) {
1219     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1220       if (dd->admfarrayghostedout[i] == *iptr) {
1221         iarray_start               = dd->admfstartghostedout[i];
1222         dd->admfarrayghostedout[i] = PETSC_NULL;
1223         dd->admfstartghostedout[i] = PETSC_NULL;
1224         break;
1225       }
1226     }
1227     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
1228     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1229       if (!dd->admfarrayghostedin[i]){
1230         dd->admfarrayghostedin[i] = *iptr;
1231         dd->admfstartghostedin[i] = iarray_start;
1232         break;
1233       }
1234     }
1235   } else {
1236     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1237       if (dd->admfarrayout[i] == *iptr) {
1238         iarray_start        = dd->admfstartout[i];
1239         dd->admfarrayout[i] = PETSC_NULL;
1240         dd->admfstartout[i] = PETSC_NULL;
1241         break;
1242       }
1243     }
1244     if (!iarray_start) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG,"Could not find array in checkout list");
1245     for (i=0; i<DMDA_MAX_AD_ARRAYS; i++) {
1246       if (!dd->admfarrayin[i]){
1247         dd->admfarrayin[i] = *iptr;
1248         dd->admfstartin[i] = iarray_start;
1249         break;
1250       }
1251     }
1252   }
1253   PetscFunctionReturn(0);
1254 }
1255 
1256 #undef __FUNCT__
1257 #define __FUNCT__ "admf_DAGetArray"
1258 PetscErrorCode PETSCDM_DLLEXPORT admf_DAGetArray(DM da,PetscBool  ghosted,void *iptr)
1259 {
1260   PetscErrorCode ierr;
1261   PetscFunctionBegin;
1262   ierr = DMDAGetAdicMFArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
1263   PetscFunctionReturn(0);
1264 }
1265 
1266 #undef __FUNCT__
1267 #define __FUNCT__ "admf_DARestoreArray"
1268 PetscErrorCode PETSCDM_DLLEXPORT admf_DARestoreArray(DM da,PetscBool  ghosted,void *iptr)
1269 {
1270   PetscErrorCode ierr;
1271   PetscFunctionBegin;
1272   ierr = DMDARestoreAdicMFArray(da,ghosted,iptr,0,0);CHKERRQ(ierr);
1273   PetscFunctionReturn(0);
1274 }
1275 
1276