xref: /petsc/src/dm/field/impls/da/dmfieldda.c (revision 51a454ed6e58ee190520820375fdcc42fc4a0793)
1*51a454edSToby Isaac #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/
2*51a454edSToby Isaac #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/
3*51a454edSToby Isaac #include <petscdmda.h>
4*51a454edSToby Isaac 
5*51a454edSToby Isaac typedef struct _n_DMField_DA
6*51a454edSToby Isaac {
7*51a454edSToby Isaac   PetscScalar     *cornerVals;
8*51a454edSToby Isaac   PetscScalar     *cornerCoeffs;
9*51a454edSToby Isaac   PetscScalar     *work;
10*51a454edSToby Isaac   PetscReal       coordRange[3][2];
11*51a454edSToby Isaac }
12*51a454edSToby Isaac DMField_DA;
13*51a454edSToby Isaac 
14*51a454edSToby Isaac static PetscErrorCode DMFieldDestroy_DA(DMField field)
15*51a454edSToby Isaac {
16*51a454edSToby Isaac   DMField_DA     *dafield;
17*51a454edSToby Isaac   PetscErrorCode ierr;
18*51a454edSToby Isaac 
19*51a454edSToby Isaac   PetscFunctionBegin;
20*51a454edSToby Isaac   dafield = (DMField_DA *) field->data;
21*51a454edSToby Isaac   ierr = PetscFree3(dafield->cornerVals,dafield->cornerCoeffs,dafield->work);CHKERRQ(ierr);
22*51a454edSToby Isaac   ierr = PetscFree(dafield);CHKERRQ(ierr);
23*51a454edSToby Isaac   PetscFunctionReturn(0);
24*51a454edSToby Isaac }
25*51a454edSToby Isaac 
26*51a454edSToby Isaac static PetscErrorCode DMFieldView_DA(DMField field,PetscViewer viewer)
27*51a454edSToby Isaac {
28*51a454edSToby Isaac   DMField_DA     *dafield = (DMField_DA *) field->data;
29*51a454edSToby Isaac   PetscBool      iascii;
30*51a454edSToby Isaac   PetscErrorCode ierr;
31*51a454edSToby Isaac 
32*51a454edSToby Isaac   PetscFunctionBegin;
33*51a454edSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject)viewer,PETSCVIEWERASCII,&iascii);CHKERRQ(ierr);
34*51a454edSToby Isaac   if (iascii) {
35*51a454edSToby Isaac     PetscInt i, c, dim;
36*51a454edSToby Isaac     PetscInt nc;
37*51a454edSToby Isaac     DM       dm = field->dm;
38*51a454edSToby Isaac 
39*51a454edSToby Isaac     PetscViewerASCIIPrintf(viewer, "Field corner values:\n");CHKERRQ(ierr);
40*51a454edSToby Isaac     ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr);
41*51a454edSToby Isaac     ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
42*51a454edSToby Isaac     nc = field->numComponents;
43*51a454edSToby Isaac     for (i = 0, c = 0; i < (1 << dim); i++) {
44*51a454edSToby Isaac       PetscInt j;
45*51a454edSToby Isaac 
46*51a454edSToby Isaac       for (j = 0; j < nc; j++, c++) {
47*51a454edSToby Isaac         PetscScalar val = dafield->cornerVals[nc * i + j];
48*51a454edSToby Isaac 
49*51a454edSToby Isaac #if !defined(PETSC_USE_COMPLEX)
50*51a454edSToby Isaac         ierr = PetscViewerASCIIPrintf(viewer,"%g ",(double) val);CHKERRQ(ierr);
51*51a454edSToby Isaac #else
52*51a454edSToby Isaac         ierr = PetscViewerASCIIPrintf(viewer,"%g+i%g ",(double) PetscRealPart(val),(double) PetscImaginaryPart(val));CHKERRQ(ierr);
53*51a454edSToby Isaac #endif
54*51a454edSToby Isaac       }
55*51a454edSToby Isaac       ierr = PetscViewerASCIIPrintf(viewer,"\n");CHKERRQ(ierr);
56*51a454edSToby Isaac     }
57*51a454edSToby Isaac     ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr);
58*51a454edSToby Isaac   }
59*51a454edSToby Isaac   PetscFunctionReturn(0);
60*51a454edSToby Isaac }
61*51a454edSToby Isaac 
62*51a454edSToby Isaac #define MEdot(y,A,x,m,c,cast)                          \
63*51a454edSToby Isaac   do {                                                 \
64*51a454edSToby Isaac     PetscInt _k, _l;                                   \
65*51a454edSToby Isaac     for (_k = 0; _k < (c); _k++) (y)[_k] = 0.;         \
66*51a454edSToby Isaac     for (_l = 0; _l < (m); _l++) {                     \
67*51a454edSToby Isaac       for (_k = 0; _k < (c); _k++) {                   \
68*51a454edSToby Isaac         (y)[_k] += cast((A)[(c) * _l + _k]) * (x)[_l]; \
69*51a454edSToby Isaac       }                                                \
70*51a454edSToby Isaac     }                                                  \
71*51a454edSToby Isaac   } while (0)
72*51a454edSToby Isaac 
73*51a454edSToby Isaac #define MEHess(out,cf,etaB,etaD,dim,nc,cast)                      \
74*51a454edSToby Isaac   do {                                                            \
75*51a454edSToby Isaac     PetscInt _m, _j, _k;                                          \
76*51a454edSToby Isaac     for (_m = 0; _m < (nc) * (dim) * (dim); _m++) (out)[_m] = 0.; \
77*51a454edSToby Isaac     for (_j = 0; _j < (dim); _j++) {                              \
78*51a454edSToby Isaac       for (_k = _j + 1; _k < (dim); _k++) {                       \
79*51a454edSToby Isaac         PetscInt _ind = (1 << _j) + (1 << _k);                    \
80*51a454edSToby Isaac         for (_m = 0; _m < (nc); _m++) {                           \
81*51a454edSToby Isaac           PetscScalar c = (cf)[_m] * (etaB)[_ind] * (etaD)[_ind];   \
82*51a454edSToby Isaac           (out)[(_m * (dim) + _k) * (dim) + _j] += cast(c);       \
83*51a454edSToby Isaac           (out)[(_m * (dim) + _j) * (dim) + _k] += cast(c);       \
84*51a454edSToby Isaac         }                                                         \
85*51a454edSToby Isaac       }                                                           \
86*51a454edSToby Isaac     }                                                             \
87*51a454edSToby Isaac   } while (0)
88*51a454edSToby Isaac 
89*51a454edSToby Isaac static void MultilinearEvaluate(PetscInt dim, PetscReal (*coordRange)[2], PetscInt nc, PetscScalar *cf, PetscScalar *cfWork, PetscInt nPoints, const PetscScalar *points, PetscDataType datatype, void *B, void *D, void *H)
90*51a454edSToby Isaac {
91*51a454edSToby Isaac   PetscInt i, j, k, l, m;
92*51a454edSToby Isaac   PetscInt  whol = 1 << dim;
93*51a454edSToby Isaac   PetscInt  half = whol >> 1;
94*51a454edSToby Isaac 
95*51a454edSToby Isaac   PetscFunctionBeginHot;
96*51a454edSToby Isaac   if (!B && !D && !H) PetscFunctionReturnVoid();
97*51a454edSToby Isaac   for (i = 0; i < nPoints; i++) {
98*51a454edSToby Isaac     const PetscScalar *point = &points[dim * i];
99*51a454edSToby Isaac     PetscReal deta[3] = {0.};
100*51a454edSToby Isaac     PetscReal etaB[8] = {1.,1.,1.,1.,1.,1.,1.,1.};
101*51a454edSToby Isaac     PetscReal etaD[8] = {1.,1.,1.,1.,1.,1.,1.,1.};
102*51a454edSToby Isaac     PetscReal work[8];
103*51a454edSToby Isaac 
104*51a454edSToby Isaac     for (j = 0; j < dim; j++) {
105*51a454edSToby Isaac       PetscReal e, d;
106*51a454edSToby Isaac 
107*51a454edSToby Isaac       e = (PetscRealPart(point[j]) - coordRange[j][0]) / coordRange[j][1];
108*51a454edSToby Isaac       deta[j] = d = 1. / coordRange[j][1];
109*51a454edSToby Isaac       for (k = 0; k < whol; k++) {work[k] = etaB[k];}
110*51a454edSToby Isaac       for (k = 0; k < half; k++) {
111*51a454edSToby Isaac         etaB[k]        = work[2 * k] * e;
112*51a454edSToby Isaac         etaB[k + half] = work[2 * k + 1];
113*51a454edSToby Isaac       }
114*51a454edSToby Isaac       if (H) {
115*51a454edSToby Isaac         for (k = 0; k < whol; k++) {work[k] = etaD[k];}
116*51a454edSToby Isaac         for (k = 0; k < half; k++) {
117*51a454edSToby Isaac           etaD[k + half] = work[2 * k];
118*51a454edSToby Isaac           etaD[k       ] = work[2 * k + 1] * d;
119*51a454edSToby Isaac         }
120*51a454edSToby Isaac       }
121*51a454edSToby Isaac     }
122*51a454edSToby Isaac     if (B) {
123*51a454edSToby Isaac       if (datatype == PETSC_SCALAR) {
124*51a454edSToby Isaac         PetscScalar *out = &((PetscScalar *)B)[nc * i];
125*51a454edSToby Isaac 
126*51a454edSToby Isaac         MEdot(out,cf,etaB,(1 << dim),nc,(PetscScalar));
127*51a454edSToby Isaac       } else {
128*51a454edSToby Isaac         PetscReal *out = &((PetscReal *)B)[nc * i];
129*51a454edSToby Isaac 
130*51a454edSToby Isaac         MEdot(out,cf,etaB,(1 << dim),nc,PetscRealPart);
131*51a454edSToby Isaac       }
132*51a454edSToby Isaac     }
133*51a454edSToby Isaac     if (D) {
134*51a454edSToby Isaac       if (datatype == PETSC_SCALAR) {
135*51a454edSToby Isaac         PetscScalar *out = &((PetscScalar *)D)[nc * dim * i];
136*51a454edSToby Isaac 
137*51a454edSToby Isaac         for (m = 0; m < nc * dim; m++) out[m] = 0.;
138*51a454edSToby Isaac       } else {
139*51a454edSToby Isaac         PetscReal *out = &((PetscReal *)D)[nc * dim * i];
140*51a454edSToby Isaac 
141*51a454edSToby Isaac         for (m = 0; m < nc * dim; m++) out[m] = 0.;
142*51a454edSToby Isaac       }
143*51a454edSToby Isaac       for (j = 0; j < dim; j++) {
144*51a454edSToby Isaac         PetscReal d = deta[j];
145*51a454edSToby Isaac 
146*51a454edSToby Isaac         for (k = 0; k < whol * nc; k++) {cfWork[k] = cf[k];}
147*51a454edSToby Isaac         for (k = 0; k < whol; k++) {work[k] = etaB[k];}
148*51a454edSToby Isaac         for (k = 0; k < half; k++) {
149*51a454edSToby Isaac           PetscReal e;
150*51a454edSToby Isaac 
151*51a454edSToby Isaac           etaB[k]        =     work[2 * k];
152*51a454edSToby Isaac           etaB[k + half] = e = work[2 * k + 1];
153*51a454edSToby Isaac 
154*51a454edSToby Isaac           for (l = 0; l < nc; l++) {
155*51a454edSToby Isaac             cf[ k         * nc + l] = cfWork[ 2 * k      * nc + l];
156*51a454edSToby Isaac             cf[(k + half) * nc + l] = cfWork[(2 * k + 1) * nc + l];
157*51a454edSToby Isaac           }
158*51a454edSToby Isaac           if (datatype == PETSC_SCALAR) {
159*51a454edSToby Isaac             PetscScalar *out = &((PetscScalar *)D)[nc * dim * i];
160*51a454edSToby Isaac 
161*51a454edSToby Isaac             for (l = 0; l < nc; l++) {
162*51a454edSToby Isaac               out[l * dim + j] += d * e * cf[k * nc + l];
163*51a454edSToby Isaac             }
164*51a454edSToby Isaac           } else {
165*51a454edSToby Isaac             PetscReal *out = &((PetscReal *)D)[nc * dim * i];
166*51a454edSToby Isaac 
167*51a454edSToby Isaac             for (l = 0; l < nc; l++) {
168*51a454edSToby Isaac               out[l * dim + j] += d * e * PetscRealPart(cf[k * nc + l]);
169*51a454edSToby Isaac             }
170*51a454edSToby Isaac           }
171*51a454edSToby Isaac         }
172*51a454edSToby Isaac       }
173*51a454edSToby Isaac     }
174*51a454edSToby Isaac     if (H) {
175*51a454edSToby Isaac       if (datatype == PETSC_SCALAR) {
176*51a454edSToby Isaac         PetscScalar *out = &((PetscScalar *)H)[nc * dim * dim * i];
177*51a454edSToby Isaac 
178*51a454edSToby Isaac         MEHess(out,cf,etaB,etaD,dim,nc,(PetscScalar));
179*51a454edSToby Isaac       } else {
180*51a454edSToby Isaac         PetscReal *out = &((PetscReal *)H)[nc * dim * dim * i];
181*51a454edSToby Isaac 
182*51a454edSToby Isaac         MEHess(out,cf,etaB,etaD,dim,nc,PetscRealPart);
183*51a454edSToby Isaac       }
184*51a454edSToby Isaac     }
185*51a454edSToby Isaac   }
186*51a454edSToby Isaac   PetscFunctionReturnVoid();
187*51a454edSToby Isaac }
188*51a454edSToby Isaac 
189*51a454edSToby Isaac static PetscErrorCode DMFieldEvaluate_DA(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H)
190*51a454edSToby Isaac {
191*51a454edSToby Isaac   DM             dm;
192*51a454edSToby Isaac   DMField_DA     *dafield;
193*51a454edSToby Isaac   PetscInt       dim;
194*51a454edSToby Isaac   PetscInt       N, n, nc;
195*51a454edSToby Isaac   const PetscScalar *array;
196*51a454edSToby Isaac   PetscReal (*coordRange)[2];
197*51a454edSToby Isaac   PetscErrorCode ierr;
198*51a454edSToby Isaac 
199*51a454edSToby Isaac   PetscFunctionBegin;
200*51a454edSToby Isaac   dm      = field->dm;
201*51a454edSToby Isaac   nc      = field->numComponents;
202*51a454edSToby Isaac   dafield = (DMField_DA *) field->data;
203*51a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
204*51a454edSToby Isaac   ierr = VecGetLocalSize(points,&N);CHKERRQ(ierr);
205*51a454edSToby Isaac   if (N % dim) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point vector size %D not divisible by coordinate dimension %D\n",N,dim);
206*51a454edSToby Isaac   n = N / dim;
207*51a454edSToby Isaac   coordRange = &(dafield->coordRange[0]);
208*51a454edSToby Isaac   ierr = VecGetArrayRead(points,&array);CHKERRQ(ierr);
209*51a454edSToby Isaac   MultilinearEvaluate(dim,coordRange,nc,dafield->cornerCoeffs,dafield->work,n,array,datatype,B,D,H);
210*51a454edSToby Isaac   ierr = VecRestoreArrayRead(points,&array);CHKERRQ(ierr);
211*51a454edSToby Isaac   PetscFunctionReturn(0);
212*51a454edSToby Isaac }
213*51a454edSToby Isaac 
214*51a454edSToby Isaac static PetscErrorCode DMFieldEvaluateFE_DA(DMField field, IS cellIS, PetscQuadrature points, PetscDataType datatype, void *B, void *D, void *H)
215*51a454edSToby Isaac {
216*51a454edSToby Isaac   PetscInt       c, i, j, k, dim, cellsPer[3] = {0}, first[3] = {0}, whol, half;
217*51a454edSToby Isaac   PetscReal      stepPer[3] = {0.};
218*51a454edSToby Isaac   PetscReal      cellCoordRange[3][2] = {{0.,1.},{0.,1.},{0.,1.}};
219*51a454edSToby Isaac   PetscScalar    *cellCoeffs, *work;
220*51a454edSToby Isaac   DM             dm;
221*51a454edSToby Isaac   DMDALocalInfo  info;
222*51a454edSToby Isaac   PetscInt       cStart, cEnd;
223*51a454edSToby Isaac   PetscInt       nq, nc;
224*51a454edSToby Isaac   const PetscReal *q;
225*51a454edSToby Isaac #if defined(PETSC_USE_COMPLEX)
226*51a454edSToby Isaac   PetscScalar    *qs;
227*51a454edSToby Isaac #else
228*51a454edSToby Isaac   const PetscScalar *qs;
229*51a454edSToby Isaac #endif
230*51a454edSToby Isaac   DMField_DA     *dafield;
231*51a454edSToby Isaac   PetscBool      isStride;
232*51a454edSToby Isaac   const PetscInt *cells = NULL;
233*51a454edSToby Isaac   PetscInt       sfirst = -1, stride = -1, nCells;
234*51a454edSToby Isaac   PetscErrorCode ierr;
235*51a454edSToby Isaac 
236*51a454edSToby Isaac   PetscFunctionBegin;
237*51a454edSToby Isaac   dafield = (DMField_DA *) field->data;
238*51a454edSToby Isaac   dm = field->dm;
239*51a454edSToby Isaac   nc = field->numComponents;
240*51a454edSToby Isaac   ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
241*51a454edSToby Isaac   dim = info.dim;
242*51a454edSToby Isaac   work = dafield->work;
243*51a454edSToby Isaac   stepPer[0] = 1./ info.mx;
244*51a454edSToby Isaac   stepPer[1] = 1./ info.my;
245*51a454edSToby Isaac   stepPer[2] = 1./ info.mz;
246*51a454edSToby Isaac   first[0] = info.gxs;
247*51a454edSToby Isaac   first[1] = info.gys;
248*51a454edSToby Isaac   first[2] = info.gzs;
249*51a454edSToby Isaac   cellsPer[0] = info.gxm;
250*51a454edSToby Isaac   cellsPer[1] = info.gym;
251*51a454edSToby Isaac   cellsPer[2] = info.gzm;
252*51a454edSToby Isaac   /* TODO: probably take components into account */
253*51a454edSToby Isaac   ierr = PetscQuadratureGetData(points, NULL, NULL, &nq, &q, NULL);CHKERRQ(ierr);
254*51a454edSToby Isaac #if defined(PETSC_USE_COMPLEX)
255*51a454edSToby Isaac   ierr = DMGetWorkArray(dm,nq * dim,PETSC_SCALAR,&qs);CHKERRQ(ierr);
256*51a454edSToby Isaac   for (i = 0; i < nq * dim; i++) qs[i] = q[i];
257*51a454edSToby Isaac #else
258*51a454edSToby Isaac   qs = q;
259*51a454edSToby Isaac #endif
260*51a454edSToby Isaac   ierr = DMDAGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
261*51a454edSToby Isaac   ierr = DMGetWorkArray(dm,(1 << dim) * nc,PETSC_SCALAR,&cellCoeffs);CHKERRQ(ierr);
262*51a454edSToby Isaac   whol = (1 << dim);
263*51a454edSToby Isaac   half = whol >> 1;
264*51a454edSToby Isaac   ierr = ISGetLocalSize(cellIS,&nCells);CHKERRQ(ierr);
265*51a454edSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject)cellIS,ISSTRIDE,&isStride);CHKERRQ(ierr);
266*51a454edSToby Isaac   if (isStride) {
267*51a454edSToby Isaac     ierr = ISStrideGetInfo(cellIS,&sfirst,&stride);CHKERRQ(ierr);
268*51a454edSToby Isaac   } else {
269*51a454edSToby Isaac     ierr = ISGetIndices(cellIS,&cells);CHKERRQ(ierr);
270*51a454edSToby Isaac   }
271*51a454edSToby Isaac   for (c = 0; c < nCells; c++) {
272*51a454edSToby Isaac     PetscInt  cell = isStride ? (sfirst + c * stride) : cells[c];
273*51a454edSToby Isaac     PetscInt  rem  = cell;
274*51a454edSToby Isaac     PetscInt  ijk[3] = {0};
275*51a454edSToby Isaac     void *cB, *cD, *cH;
276*51a454edSToby Isaac 
277*51a454edSToby Isaac     if (datatype == PETSC_SCALAR) {
278*51a454edSToby Isaac       cB = B ? &((PetscScalar *)B)[nc * nq * c] : NULL;
279*51a454edSToby Isaac       cD = D ? &((PetscScalar *)D)[nc * nq * dim * c] : NULL;
280*51a454edSToby Isaac       cH = H ? &((PetscScalar *)H)[nc * nq * dim * dim * c] : NULL;
281*51a454edSToby Isaac     } else {
282*51a454edSToby Isaac       cB = B ? &((PetscReal *)B)[nc * nq * c] : NULL;
283*51a454edSToby Isaac       cD = D ? &((PetscReal *)D)[nc * nq * dim * c] : NULL;
284*51a454edSToby Isaac       cH = H ? &((PetscReal *)H)[nc * nq * dim * dim * c] : NULL;
285*51a454edSToby Isaac     }
286*51a454edSToby Isaac     if (cell < cStart || cell >= cEnd) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Point %D not a cell [%D,%D), not implemented yet",cell,cStart,cEnd);
287*51a454edSToby Isaac     for (i = 0; i < nc * whol; i++) {work[i] = dafield->cornerCoeffs[i];}
288*51a454edSToby Isaac     for (j = 0; j < dim; j++) {
289*51a454edSToby Isaac       PetscReal e, d;
290*51a454edSToby Isaac       ijk[j] = (rem % cellsPer[j]);
291*51a454edSToby Isaac       rem /= cellsPer[j];
292*51a454edSToby Isaac 
293*51a454edSToby Isaac       e = 2. * (ijk[j] + first[j] + 0.5) * stepPer[j] - 1.;
294*51a454edSToby Isaac       d = stepPer[j];
295*51a454edSToby Isaac       for (i = 0; i < half; i++) {
296*51a454edSToby Isaac         for (k = 0; k < nc; k++) {
297*51a454edSToby Isaac           cellCoeffs[ i         * nc + k] = work[ 2 * i * nc + k] * d;
298*51a454edSToby Isaac           cellCoeffs[(i + half) * nc + k] = work[ 2 * i * nc + k] * e + work[(2 * i + 1) * nc + k];
299*51a454edSToby Isaac         }
300*51a454edSToby Isaac       }
301*51a454edSToby Isaac       for (i = 0; i < whol * nc; i++) {work[i] = cellCoeffs[i];}
302*51a454edSToby Isaac     }
303*51a454edSToby Isaac     MultilinearEvaluate(dim,cellCoordRange,nc,cellCoeffs,dafield->work,nq,qs,datatype,cB,cD,cH);
304*51a454edSToby Isaac   }
305*51a454edSToby Isaac   if (!isStride) {
306*51a454edSToby Isaac     ierr = ISRestoreIndices(cellIS,&cells);CHKERRQ(ierr);
307*51a454edSToby Isaac   }
308*51a454edSToby Isaac   ierr = DMRestoreWorkArray(dm,(1 << dim) * nc,PETSC_SCALAR,&cellCoeffs);CHKERRQ(ierr);
309*51a454edSToby Isaac #if defined(PETSC_USE_COMPLEX)
310*51a454edSToby Isaac   ierr = DMRestoreWorkArray(dm,nq * dim,PETSC_SCALAR,&qs);CHKERRQ(ierr);
311*51a454edSToby Isaac #endif
312*51a454edSToby Isaac   PetscFunctionReturn(0);
313*51a454edSToby Isaac }
314*51a454edSToby Isaac 
315*51a454edSToby Isaac static PetscErrorCode DMFieldEvaluateFV_DA(DMField field, IS cellIS, PetscDataType datatype, void *B, void *D, void *H)
316*51a454edSToby Isaac {
317*51a454edSToby Isaac   PetscInt       c, i, dim, cellsPer[3] = {0}, first[3] = {0};
318*51a454edSToby Isaac   PetscReal      stepPer[3] = {0.};
319*51a454edSToby Isaac   DM             dm;
320*51a454edSToby Isaac   DMDALocalInfo  info;
321*51a454edSToby Isaac   PetscInt       cStart, cEnd, numCells;
322*51a454edSToby Isaac   PetscInt       nc;
323*51a454edSToby Isaac   PetscReal      *points;
324*51a454edSToby Isaac   DMField_DA     *dafield;
325*51a454edSToby Isaac   PetscBool      isStride;
326*51a454edSToby Isaac   const PetscInt *cells = NULL;
327*51a454edSToby Isaac   PetscInt       sfirst = -1, stride = -1;
328*51a454edSToby Isaac   PetscErrorCode ierr;
329*51a454edSToby Isaac 
330*51a454edSToby Isaac   PetscFunctionBegin;
331*51a454edSToby Isaac   dafield = (DMField_DA *) field->data;
332*51a454edSToby Isaac   dm = field->dm;
333*51a454edSToby Isaac   nc = field->numComponents;
334*51a454edSToby Isaac   ierr = DMDAGetLocalInfo(dm,&info);CHKERRQ(ierr);
335*51a454edSToby Isaac   dim = info.dim;
336*51a454edSToby Isaac   stepPer[0] = 1./ info.mx;
337*51a454edSToby Isaac   stepPer[1] = 1./ info.my;
338*51a454edSToby Isaac   stepPer[2] = 1./ info.mz;
339*51a454edSToby Isaac   first[0] = info.gxs;
340*51a454edSToby Isaac   first[1] = info.gys;
341*51a454edSToby Isaac   first[2] = info.gzs;
342*51a454edSToby Isaac   cellsPer[0] = info.gxm;
343*51a454edSToby Isaac   cellsPer[1] = info.gym;
344*51a454edSToby Isaac   cellsPer[2] = info.gzm;
345*51a454edSToby Isaac   ierr = DMDAGetHeightStratum(dm,0,&cStart,&cEnd);CHKERRQ(ierr);
346*51a454edSToby Isaac   ierr = ISGetLocalSize(cellIS,&numCells);CHKERRQ(ierr);
347*51a454edSToby Isaac   ierr = DMGetWorkArray(dm,dim * numCells,PETSC_SCALAR,&points);CHKERRQ(ierr);
348*51a454edSToby Isaac   ierr = PetscObjectTypeCompare((PetscObject)cellIS,ISSTRIDE,&isStride);CHKERRQ(ierr);
349*51a454edSToby Isaac   if (isStride) {
350*51a454edSToby Isaac     ierr = ISStrideGetInfo(cellIS,&sfirst,&stride);CHKERRQ(ierr);
351*51a454edSToby Isaac   } else {
352*51a454edSToby Isaac     ierr = ISGetIndices(cellIS,&cells);CHKERRQ(ierr);
353*51a454edSToby Isaac   }
354*51a454edSToby Isaac   for (c = 0; c < numCells; c++) {
355*51a454edSToby Isaac     PetscInt  cell = isStride ? (sfirst + c * stride) : cells[c];
356*51a454edSToby Isaac     PetscInt  rem  = cell;
357*51a454edSToby Isaac     PetscInt  ijk[3] = {0};
358*51a454edSToby Isaac 
359*51a454edSToby Isaac     if (cell < cStart || cell >= cEnd) SETERRQ3(PETSC_COMM_SELF,PETSC_ERR_ARG_OUTOFRANGE,"Point %D not a cell [%D,%D), not implemented yet",cell,cStart,cEnd);
360*51a454edSToby Isaac     for (i = 0; i < dim; i++) {
361*51a454edSToby Isaac       ijk[i] = (rem % cellsPer[i]);
362*51a454edSToby Isaac       rem /= cellsPer[i];
363*51a454edSToby Isaac       points[dim * c + i] = (ijk[i] + first[i] + 0.5) * stepPer[i];
364*51a454edSToby Isaac     }
365*51a454edSToby Isaac   }
366*51a454edSToby Isaac   if (!isStride) {
367*51a454edSToby Isaac     ierr = ISRestoreIndices(cellIS,&cells);CHKERRQ(ierr);
368*51a454edSToby Isaac   }
369*51a454edSToby Isaac   MultilinearEvaluate(dim,dafield->coordRange,nc,dafield->cornerCoeffs,dafield->work,numCells,points,datatype,B,D,H);
370*51a454edSToby Isaac   ierr = DMRestoreWorkArray(dm,dim * numCells,PETSC_SCALAR,&points);CHKERRQ(ierr);
371*51a454edSToby Isaac   PetscFunctionReturn(0);
372*51a454edSToby Isaac }
373*51a454edSToby Isaac 
374*51a454edSToby Isaac static PetscErrorCode DMFieldGetFEInvariance_DA(DMField field, IS pointIS, PetscBool *isConstant, PetscBool *isAffine, PetscBool *isQuadratic)
375*51a454edSToby Isaac {
376*51a454edSToby Isaac   DM             dm;
377*51a454edSToby Isaac   PetscInt       dim, h, imin;
378*51a454edSToby Isaac   PetscErrorCode ierr;
379*51a454edSToby Isaac 
380*51a454edSToby Isaac   PetscFunctionBegin;
381*51a454edSToby Isaac   dm = field->dm;
382*51a454edSToby Isaac   ierr = ISGetMinMax(pointIS,&imin,NULL);CHKERRQ(ierr);
383*51a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
384*51a454edSToby Isaac   for (h = 0; h <= dim; h++) {
385*51a454edSToby Isaac     PetscInt hEnd;
386*51a454edSToby Isaac 
387*51a454edSToby Isaac     ierr = DMDAGetHeightStratum(dm,h,NULL,&hEnd);CHKERRQ(ierr);
388*51a454edSToby Isaac     if (imin < hEnd) break;
389*51a454edSToby Isaac   }
390*51a454edSToby Isaac   dim -= h;
391*51a454edSToby Isaac   if (isConstant)  *isConstant  = (dim < 1) ? PETSC_TRUE : PETSC_FALSE;
392*51a454edSToby Isaac   if (isAffine)    *isAffine    = (dim < 2) ? PETSC_TRUE : PETSC_FALSE;
393*51a454edSToby Isaac   if (isQuadratic) *isQuadratic = (dim < 3) ? PETSC_TRUE : PETSC_FALSE;
394*51a454edSToby Isaac   PetscFunctionReturn(0);
395*51a454edSToby Isaac }
396*51a454edSToby Isaac 
397*51a454edSToby Isaac static PetscErrorCode DMFieldCreateDefaultQuadrature_DA(DMField field, IS cellIS, PetscQuadrature *quad)
398*51a454edSToby Isaac {
399*51a454edSToby Isaac   PetscInt       h, dim, imax, imin;
400*51a454edSToby Isaac   DM             dm;
401*51a454edSToby Isaac   PetscErrorCode ierr;
402*51a454edSToby Isaac 
403*51a454edSToby Isaac   PetscFunctionBegin;
404*51a454edSToby Isaac   dm = field->dm;
405*51a454edSToby Isaac   ierr = ISGetMinMax(cellIS,&imax,&imin);CHKERRQ(ierr);
406*51a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
407*51a454edSToby Isaac   *quad = NULL;
408*51a454edSToby Isaac   for (h = 0; h <= dim; h++) {
409*51a454edSToby Isaac     PetscInt hStart, hEnd;
410*51a454edSToby Isaac 
411*51a454edSToby Isaac     ierr = DMDAGetHeightStratum(dm,h,&hStart,&hEnd);CHKERRQ(ierr);
412*51a454edSToby Isaac     if (imin >= hStart && imax < hEnd) break;
413*51a454edSToby Isaac   }
414*51a454edSToby Isaac   dim -= h;
415*51a454edSToby Isaac   if (dim > 0) {
416*51a454edSToby Isaac     ierr = PetscDTGaussTensorQuadrature(dim, 1, 1, -1.0, 1.0, quad);CHKERRQ(ierr);
417*51a454edSToby Isaac   }
418*51a454edSToby Isaac 
419*51a454edSToby Isaac   PetscFunctionReturn(0);
420*51a454edSToby Isaac }
421*51a454edSToby Isaac 
422*51a454edSToby Isaac static PetscErrorCode DMFieldInitialize_DA(DMField field)
423*51a454edSToby Isaac {
424*51a454edSToby Isaac   DM             dm;
425*51a454edSToby Isaac   Vec            coords = NULL;
426*51a454edSToby Isaac   PetscInt       dim, i, j, k;
427*51a454edSToby Isaac   DMField_DA     *dafield = field->data;
428*51a454edSToby Isaac   PetscErrorCode ierr;
429*51a454edSToby Isaac 
430*51a454edSToby Isaac   PetscFunctionBegin;
431*51a454edSToby Isaac   field->ops->destroy                 = DMFieldDestroy_DA;
432*51a454edSToby Isaac   field->ops->evaluate                = DMFieldEvaluate_DA;
433*51a454edSToby Isaac   field->ops->evaluateFE              = DMFieldEvaluateFE_DA;
434*51a454edSToby Isaac   field->ops->evaluateFV              = DMFieldEvaluateFV_DA;
435*51a454edSToby Isaac   field->ops->getFEInvariance         = DMFieldGetFEInvariance_DA;
436*51a454edSToby Isaac   field->ops->createDefaultQuadrature = DMFieldCreateDefaultQuadrature_DA;
437*51a454edSToby Isaac   field->ops->view                    = DMFieldView_DA;
438*51a454edSToby Isaac   dm = field->dm;
439*51a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
440*51a454edSToby Isaac   if (dm->coordinates) coords = dm->coordinates;
441*51a454edSToby Isaac   else if (dm->coordinatesLocal) coords = dm->coordinatesLocal;
442*51a454edSToby Isaac   if (coords) {
443*51a454edSToby Isaac     PetscInt          n;
444*51a454edSToby Isaac     const PetscScalar *array;
445*51a454edSToby Isaac     PetscReal         mins[3][2] = {{PETSC_MAX_REAL,PETSC_MAX_REAL},{PETSC_MAX_REAL,PETSC_MAX_REAL},{PETSC_MAX_REAL,PETSC_MAX_REAL}};
446*51a454edSToby Isaac 
447*51a454edSToby Isaac     ierr = VecGetLocalSize(coords,&n);CHKERRQ(ierr);
448*51a454edSToby Isaac     n /= dim;
449*51a454edSToby Isaac     ierr = VecGetArrayRead(coords,&array);CHKERRQ(ierr);
450*51a454edSToby Isaac     for (i = 0, k = 0; i < n; i++) {
451*51a454edSToby Isaac       for (j = 0; j < dim; j++, k++) {
452*51a454edSToby Isaac         PetscReal val = PetscRealPart(array[k]);
453*51a454edSToby Isaac 
454*51a454edSToby Isaac         mins[j][0] = PetscMin(mins[j][0],val);
455*51a454edSToby Isaac         mins[j][1] = PetscMin(mins[j][1],-val);
456*51a454edSToby Isaac       }
457*51a454edSToby Isaac     }
458*51a454edSToby Isaac     ierr = VecRestoreArrayRead(coords,&array);CHKERRQ(ierr);
459*51a454edSToby Isaac     ierr = MPIU_Allreduce(mins,&(dafield->coordRange[0][0]),2*dim,MPIU_REAL,MPI_MIN,PetscObjectComm((PetscObject)dm));CHKERRQ(ierr);
460*51a454edSToby Isaac     for (j = 0; j < dim; j++) {
461*51a454edSToby Isaac       dafield->coordRange[j][1] = -dafield->coordRange[j][1];
462*51a454edSToby Isaac     }
463*51a454edSToby Isaac   } else {
464*51a454edSToby Isaac     for (j = 0; j < dim; j++) {
465*51a454edSToby Isaac       dafield->coordRange[j][0] = 0.;
466*51a454edSToby Isaac       dafield->coordRange[j][1] = 1.;
467*51a454edSToby Isaac     }
468*51a454edSToby Isaac   }
469*51a454edSToby Isaac   for (j = 0; j < dim; j++) {
470*51a454edSToby Isaac     PetscScalar avg = 0.5 * (dafield->coordRange[j][1] + dafield->coordRange[j][0]);
471*51a454edSToby Isaac     PetscScalar dif = 0.5 * (dafield->coordRange[j][1] - dafield->coordRange[j][0]);
472*51a454edSToby Isaac 
473*51a454edSToby Isaac     dafield->coordRange[j][0] = avg;
474*51a454edSToby Isaac     dafield->coordRange[j][1] = dif;
475*51a454edSToby Isaac   }
476*51a454edSToby Isaac   PetscFunctionReturn(0);
477*51a454edSToby Isaac }
478*51a454edSToby Isaac 
479*51a454edSToby Isaac PETSC_INTERN PetscErrorCode DMFieldCreate_DA(DMField field)
480*51a454edSToby Isaac {
481*51a454edSToby Isaac   DMField_DA     *dafield;
482*51a454edSToby Isaac   PetscErrorCode ierr;
483*51a454edSToby Isaac 
484*51a454edSToby Isaac   PetscFunctionBegin;
485*51a454edSToby Isaac   ierr = PetscNewLog(field,&dafield);CHKERRQ(ierr);
486*51a454edSToby Isaac   field->data = dafield;
487*51a454edSToby Isaac   ierr = DMFieldInitialize_DA(field);CHKERRQ(ierr);
488*51a454edSToby Isaac   PetscFunctionReturn(0);
489*51a454edSToby Isaac }
490*51a454edSToby Isaac 
491*51a454edSToby Isaac PetscErrorCode DMFieldCreateDA(DM dm, PetscInt nc, const PetscScalar *cornerValues,DMField *field)
492*51a454edSToby Isaac {
493*51a454edSToby Isaac   DMField        b;
494*51a454edSToby Isaac   DMField_DA     *dafield;
495*51a454edSToby Isaac   PetscInt       dim, nv, i, j, k;
496*51a454edSToby Isaac   PetscInt       half;
497*51a454edSToby Isaac   PetscScalar    *cv, *cf, *work;
498*51a454edSToby Isaac   PetscErrorCode ierr;
499*51a454edSToby Isaac 
500*51a454edSToby Isaac   PetscFunctionBegin;
501*51a454edSToby Isaac   ierr = DMFieldCreate(dm,nc,DMFIELD_VERTEX,&b);CHKERRQ(ierr);
502*51a454edSToby Isaac   ierr = DMFieldSetType(b,DMFIELDDA);CHKERRQ(ierr);
503*51a454edSToby Isaac   dafield = (DMField_DA *) b->data;
504*51a454edSToby Isaac   ierr = DMGetDimension(dm,&dim);CHKERRQ(ierr);
505*51a454edSToby Isaac   nv = (1 << dim) * nc;
506*51a454edSToby Isaac   ierr = PetscMalloc3(nv,&cv,nv,&cf,nv,&work);CHKERRQ(ierr);
507*51a454edSToby Isaac   for (i = 0; i < nv; i++) cv[i] = cornerValues[i];
508*51a454edSToby Isaac   for (i = 0; i < nv; i++) cf[i] = cv[i];
509*51a454edSToby Isaac   dafield->cornerVals = cv;
510*51a454edSToby Isaac   dafield->cornerCoeffs = cf;
511*51a454edSToby Isaac   dafield->work = work;
512*51a454edSToby Isaac   half = (1 << (dim - 1));
513*51a454edSToby Isaac   for (i = 0; i < dim; i++) {
514*51a454edSToby Isaac     PetscScalar *w;
515*51a454edSToby Isaac 
516*51a454edSToby Isaac     w = work;
517*51a454edSToby Isaac     for (j = 0; j < half; j++) {
518*51a454edSToby Isaac       for (k = 0; k < nc; k++) {
519*51a454edSToby Isaac         w[j * nc + k] = 0.5 * (cf[(2 * j + 1) * nc + k] - cf[(2 * j) * nc + k]);
520*51a454edSToby Isaac       }
521*51a454edSToby Isaac     }
522*51a454edSToby Isaac     w = &work[j * nc];
523*51a454edSToby Isaac     for (j = 0; j < half; j++) {
524*51a454edSToby Isaac       for (k = 0; k < nc; k++) {
525*51a454edSToby Isaac         w[j * nc + k] = 0.5 * (cf[(2 * j) * nc + k] + cf[(2 * j + 1) * nc + k]);
526*51a454edSToby Isaac       }
527*51a454edSToby Isaac     }
528*51a454edSToby Isaac     for (j = 0; j < nv; j++) {cf[j] = work[j];}
529*51a454edSToby Isaac   }
530*51a454edSToby Isaac   *field = b;
531*51a454edSToby Isaac   PetscFunctionReturn(0);
532*51a454edSToby Isaac }
533