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