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