151a454edSToby Isaac #include <petsc/private/dmfieldimpl.h> /*I "petscdmfield.h" I*/ 251a454edSToby Isaac #include <petsc/private/dmimpl.h> /*I "petscdm.h" I*/ 351a454edSToby Isaac #include <petscdmda.h> 451a454edSToby Isaac 59371c9d4SSatish Balay typedef struct _n_DMField_DA { 651a454edSToby Isaac PetscScalar *cornerVals; 751a454edSToby Isaac PetscScalar *cornerCoeffs; 851a454edSToby Isaac PetscScalar *work; 951a454edSToby Isaac PetscReal coordRange[3][2]; 109371c9d4SSatish Balay } DMField_DA; 1151a454edSToby Isaac 12d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldDestroy_DA(DMField field) 13d71ae5a4SJacob Faibussowitsch { 1451a454edSToby Isaac DMField_DA *dafield; 1551a454edSToby Isaac 1651a454edSToby Isaac PetscFunctionBegin; 1751a454edSToby Isaac dafield = (DMField_DA *)field->data; 189566063dSJacob Faibussowitsch PetscCall(PetscFree3(dafield->cornerVals, dafield->cornerCoeffs, dafield->work)); 199566063dSJacob Faibussowitsch PetscCall(PetscFree(dafield)); 203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2151a454edSToby Isaac } 2251a454edSToby Isaac 23d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldView_DA(DMField field, PetscViewer viewer) 24d71ae5a4SJacob Faibussowitsch { 2551a454edSToby Isaac DMField_DA *dafield = (DMField_DA *)field->data; 269f196a02SMartin Diehl PetscBool isascii; 2751a454edSToby Isaac 2851a454edSToby Isaac PetscFunctionBegin; 299f196a02SMartin Diehl PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii)); 309f196a02SMartin Diehl if (isascii) { 31*e60de12fSPierre Jolivet PetscInt i, dim; 3251a454edSToby Isaac PetscInt nc; 3351a454edSToby Isaac DM dm = field->dm; 3451a454edSToby Isaac 359566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "Field corner values:\n")); 369566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPushTab(viewer)); 379566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 3851a454edSToby Isaac nc = field->numComponents; 39*e60de12fSPierre Jolivet for (i = 0; i < (1 << dim); i++) { 4051a454edSToby Isaac PetscInt j; 4151a454edSToby Isaac 42*e60de12fSPierre Jolivet for (j = 0; j < nc; j++) { 4351a454edSToby Isaac PetscScalar val = dafield->cornerVals[nc * i + j]; 4451a454edSToby Isaac 4551a454edSToby Isaac #if !defined(PETSC_USE_COMPLEX) 469566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g ", (double)val)); 4751a454edSToby Isaac #else 489566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "%g+i%g ", (double)PetscRealPart(val), (double)PetscImaginaryPart(val))); 4951a454edSToby Isaac #endif 5051a454edSToby Isaac } 519566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "\n")); 5251a454edSToby Isaac } 539566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPopTab(viewer)); 5451a454edSToby Isaac } 553ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5651a454edSToby Isaac } 5751a454edSToby Isaac 5851a454edSToby Isaac #define MEdot(y, A, x, m, c, cast) \ 5951a454edSToby Isaac do { \ 6051a454edSToby Isaac PetscInt _k, _l; \ 6151a454edSToby Isaac for (_k = 0; _k < (c); _k++) (y)[_k] = 0.; \ 6251a454edSToby Isaac for (_l = 0; _l < (m); _l++) { \ 63ad540459SPierre Jolivet for (_k = 0; _k < (c); _k++) (y)[_k] += cast((A)[(c) * _l + _k]) * (x)[_l]; \ 6451a454edSToby Isaac } \ 6551a454edSToby Isaac } while (0) 6651a454edSToby Isaac 6751a454edSToby Isaac #define MEHess(out, cf, etaB, etaD, dim, nc, cast) \ 6851a454edSToby Isaac do { \ 6951a454edSToby Isaac PetscInt _m, _j, _k; \ 7051a454edSToby Isaac for (_m = 0; _m < (nc) * (dim) * (dim); _m++) (out)[_m] = 0.; \ 7151a454edSToby Isaac for (_j = 0; _j < (dim); _j++) { \ 7251a454edSToby Isaac for (_k = _j + 1; _k < (dim); _k++) { \ 7351a454edSToby Isaac PetscInt _ind = (1 << _j) + (1 << _k); \ 7451a454edSToby Isaac for (_m = 0; _m < (nc); _m++) { \ 7551a454edSToby Isaac PetscScalar c = (cf)[_m] * (etaB)[_ind] * (etaD)[_ind]; \ 7651a454edSToby Isaac (out)[(_m * (dim) + _k) * (dim) + _j] += cast(c); \ 7751a454edSToby Isaac (out)[(_m * (dim) + _j) * (dim) + _k] += cast(c); \ 7851a454edSToby Isaac } \ 7951a454edSToby Isaac } \ 8051a454edSToby Isaac } \ 8151a454edSToby Isaac } while (0) 8251a454edSToby Isaac 83d71ae5a4SJacob Faibussowitsch 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) 84d71ae5a4SJacob Faibussowitsch { 8551a454edSToby Isaac PetscInt i, j, k, l, m; 8651a454edSToby Isaac PetscInt whol = 1 << dim; 8751a454edSToby Isaac PetscInt half = whol >> 1; 8851a454edSToby Isaac 8951a454edSToby Isaac PetscFunctionBeginHot; 9051a454edSToby Isaac if (!B && !D && !H) PetscFunctionReturnVoid(); 9151a454edSToby Isaac for (i = 0; i < nPoints; i++) { 9251a454edSToby Isaac const PetscScalar *point = &points[dim * i]; 9351a454edSToby Isaac PetscReal deta[3] = {0.}; 9451a454edSToby Isaac PetscReal etaB[8] = {1., 1., 1., 1., 1., 1., 1., 1.}; 9551a454edSToby Isaac PetscReal etaD[8] = {1., 1., 1., 1., 1., 1., 1., 1.}; 9651a454edSToby Isaac PetscReal work[8]; 9751a454edSToby Isaac 9851a454edSToby Isaac for (j = 0; j < dim; j++) { 9951a454edSToby Isaac PetscReal e, d; 10051a454edSToby Isaac 10151a454edSToby Isaac e = (PetscRealPart(point[j]) - coordRange[j][0]) / coordRange[j][1]; 10251a454edSToby Isaac deta[j] = d = 1. / coordRange[j][1]; 103ad540459SPierre Jolivet for (k = 0; k < whol; k++) work[k] = etaB[k]; 10451a454edSToby Isaac for (k = 0; k < half; k++) { 10551a454edSToby Isaac etaB[k] = work[2 * k] * e; 10651a454edSToby Isaac etaB[k + half] = work[2 * k + 1]; 10751a454edSToby Isaac } 10851a454edSToby Isaac if (H) { 109ad540459SPierre Jolivet for (k = 0; k < whol; k++) work[k] = etaD[k]; 11051a454edSToby Isaac for (k = 0; k < half; k++) { 11151a454edSToby Isaac etaD[k + half] = work[2 * k]; 11251a454edSToby Isaac etaD[k] = work[2 * k + 1] * d; 11351a454edSToby Isaac } 11451a454edSToby Isaac } 11551a454edSToby Isaac } 11651a454edSToby Isaac if (B) { 11751a454edSToby Isaac if (datatype == PETSC_SCALAR) { 11851a454edSToby Isaac PetscScalar *out = &((PetscScalar *)B)[nc * i]; 11951a454edSToby Isaac 12051a454edSToby Isaac MEdot(out, cf, etaB, (1 << dim), nc, (PetscScalar)); 12151a454edSToby Isaac } else { 12251a454edSToby Isaac PetscReal *out = &((PetscReal *)B)[nc * i]; 12351a454edSToby Isaac 12451a454edSToby Isaac MEdot(out, cf, etaB, (1 << dim), nc, PetscRealPart); 12551a454edSToby Isaac } 12651a454edSToby Isaac } 12751a454edSToby Isaac if (D) { 12851a454edSToby Isaac if (datatype == PETSC_SCALAR) { 12951a454edSToby Isaac PetscScalar *out = &((PetscScalar *)D)[nc * dim * i]; 13051a454edSToby Isaac 13151a454edSToby Isaac for (m = 0; m < nc * dim; m++) out[m] = 0.; 13251a454edSToby Isaac } else { 13351a454edSToby Isaac PetscReal *out = &((PetscReal *)D)[nc * dim * i]; 13451a454edSToby Isaac 13551a454edSToby Isaac for (m = 0; m < nc * dim; m++) out[m] = 0.; 13651a454edSToby Isaac } 13751a454edSToby Isaac for (j = 0; j < dim; j++) { 13851a454edSToby Isaac PetscReal d = deta[j]; 13951a454edSToby Isaac 140ad540459SPierre Jolivet for (k = 0; k < whol * nc; k++) cfWork[k] = cf[k]; 141ad540459SPierre Jolivet for (k = 0; k < whol; k++) work[k] = etaB[k]; 14251a454edSToby Isaac for (k = 0; k < half; k++) { 14351a454edSToby Isaac PetscReal e; 14451a454edSToby Isaac 14551a454edSToby Isaac etaB[k] = work[2 * k]; 14651a454edSToby Isaac etaB[k + half] = e = work[2 * k + 1]; 14751a454edSToby Isaac 14851a454edSToby Isaac for (l = 0; l < nc; l++) { 14951a454edSToby Isaac cf[k * nc + l] = cfWork[2 * k * nc + l]; 15051a454edSToby Isaac cf[(k + half) * nc + l] = cfWork[(2 * k + 1) * nc + l]; 15151a454edSToby Isaac } 15251a454edSToby Isaac if (datatype == PETSC_SCALAR) { 15351a454edSToby Isaac PetscScalar *out = &((PetscScalar *)D)[nc * dim * i]; 15451a454edSToby Isaac 155ad540459SPierre Jolivet for (l = 0; l < nc; l++) out[l * dim + j] += d * e * cf[k * nc + l]; 15651a454edSToby Isaac } else { 15751a454edSToby Isaac PetscReal *out = &((PetscReal *)D)[nc * dim * i]; 15851a454edSToby Isaac 159ad540459SPierre Jolivet for (l = 0; l < nc; l++) out[l * dim + j] += d * e * PetscRealPart(cf[k * nc + l]); 16051a454edSToby Isaac } 16151a454edSToby Isaac } 16251a454edSToby Isaac } 16351a454edSToby Isaac } 16451a454edSToby Isaac if (H) { 16551a454edSToby Isaac if (datatype == PETSC_SCALAR) { 16651a454edSToby Isaac PetscScalar *out = &((PetscScalar *)H)[nc * dim * dim * i]; 16751a454edSToby Isaac 16851a454edSToby Isaac MEHess(out, cf, etaB, etaD, dim, nc, (PetscScalar)); 16951a454edSToby Isaac } else { 17051a454edSToby Isaac PetscReal *out = &((PetscReal *)H)[nc * dim * dim * i]; 17151a454edSToby Isaac 17251a454edSToby Isaac MEHess(out, cf, etaB, etaD, dim, nc, PetscRealPart); 17351a454edSToby Isaac } 17451a454edSToby Isaac } 17551a454edSToby Isaac } 17651a454edSToby Isaac PetscFunctionReturnVoid(); 17751a454edSToby Isaac } 17851a454edSToby Isaac 179d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEvaluate_DA(DMField field, Vec points, PetscDataType datatype, void *B, void *D, void *H) 180d71ae5a4SJacob Faibussowitsch { 18151a454edSToby Isaac DM dm; 18251a454edSToby Isaac DMField_DA *dafield; 18351a454edSToby Isaac PetscInt dim; 18451a454edSToby Isaac PetscInt N, n, nc; 18551a454edSToby Isaac const PetscScalar *array; 18651a454edSToby Isaac PetscReal (*coordRange)[2]; 18751a454edSToby Isaac 18851a454edSToby Isaac PetscFunctionBegin; 18951a454edSToby Isaac dm = field->dm; 19051a454edSToby Isaac nc = field->numComponents; 19151a454edSToby Isaac dafield = (DMField_DA *)field->data; 1929566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 1939566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(points, &N)); 19463a3b9bcSJacob Faibussowitsch PetscCheck(N % dim == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_INCOMP, "Point vector size %" PetscInt_FMT " not divisible by coordinate dimension %" PetscInt_FMT, N, dim); 19551a454edSToby Isaac n = N / dim; 196f4f49eeaSPierre Jolivet coordRange = &dafield->coordRange[0]; 1979566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(points, &array)); 19851a454edSToby Isaac MultilinearEvaluate(dim, coordRange, nc, dafield->cornerCoeffs, dafield->work, n, array, datatype, B, D, H); 1999566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(points, &array)); 2003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 20151a454edSToby Isaac } 20251a454edSToby Isaac 203d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEvaluateFE_DA(DMField field, IS cellIS, PetscQuadrature points, PetscDataType datatype, void *B, void *D, void *H) 204d71ae5a4SJacob Faibussowitsch { 20551a454edSToby Isaac PetscInt c, i, j, k, dim, cellsPer[3] = {0}, first[3] = {0}, whol, half; 20651a454edSToby Isaac PetscReal stepPer[3] = {0.}; 2079371c9d4SSatish Balay PetscReal cellCoordRange[3][2] = { 2089371c9d4SSatish Balay {0., 1.}, 2099371c9d4SSatish Balay {0., 1.}, 2109371c9d4SSatish Balay {0., 1.} 2119371c9d4SSatish Balay }; 21251a454edSToby Isaac PetscScalar *cellCoeffs, *work; 21351a454edSToby Isaac DM dm; 21451a454edSToby Isaac DMDALocalInfo info; 21551a454edSToby Isaac PetscInt cStart, cEnd; 21651a454edSToby Isaac PetscInt nq, nc; 21751a454edSToby Isaac const PetscReal *q; 21851a454edSToby Isaac #if defined(PETSC_USE_COMPLEX) 21951a454edSToby Isaac PetscScalar *qs; 22051a454edSToby Isaac #else 22151a454edSToby Isaac const PetscScalar *qs; 22251a454edSToby Isaac #endif 22351a454edSToby Isaac DMField_DA *dafield; 22451a454edSToby Isaac PetscBool isStride; 22551a454edSToby Isaac const PetscInt *cells = NULL; 22651a454edSToby Isaac PetscInt sfirst = -1, stride = -1, nCells; 22751a454edSToby Isaac 22851a454edSToby Isaac PetscFunctionBegin; 22951a454edSToby Isaac dafield = (DMField_DA *)field->data; 23051a454edSToby Isaac dm = field->dm; 23151a454edSToby Isaac nc = field->numComponents; 2329566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 23351a454edSToby Isaac dim = info.dim; 23451a454edSToby Isaac work = dafield->work; 23551a454edSToby Isaac stepPer[0] = 1. / info.mx; 23651a454edSToby Isaac stepPer[1] = 1. / info.my; 23751a454edSToby Isaac stepPer[2] = 1. / info.mz; 23851a454edSToby Isaac first[0] = info.gxs; 23951a454edSToby Isaac first[1] = info.gys; 24051a454edSToby Isaac first[2] = info.gzs; 24151a454edSToby Isaac cellsPer[0] = info.gxm; 24251a454edSToby Isaac cellsPer[1] = info.gym; 24351a454edSToby Isaac cellsPer[2] = info.gzm; 24451a454edSToby Isaac /* TODO: probably take components into account */ 2459566063dSJacob Faibussowitsch PetscCall(PetscQuadratureGetData(points, NULL, NULL, &nq, &q, NULL)); 24651a454edSToby Isaac #if defined(PETSC_USE_COMPLEX) 2479566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, nq * dim, MPIU_SCALAR, &qs)); 24851a454edSToby Isaac for (i = 0; i < nq * dim; i++) qs[i] = q[i]; 24951a454edSToby Isaac #else 25051a454edSToby Isaac qs = q; 25151a454edSToby Isaac #endif 2529566063dSJacob Faibussowitsch PetscCall(DMDAGetHeightStratum(dm, 0, &cStart, &cEnd)); 2539566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, (1 << dim) * nc, MPIU_SCALAR, &cellCoeffs)); 25451a454edSToby Isaac whol = (1 << dim); 25551a454edSToby Isaac half = whol >> 1; 2569566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cellIS, &nCells)); 2579566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)cellIS, ISSTRIDE, &isStride)); 258ac530a7eSPierre Jolivet if (isStride) PetscCall(ISStrideGetInfo(cellIS, &sfirst, &stride)); 259ac530a7eSPierre Jolivet else PetscCall(ISGetIndices(cellIS, &cells)); 26051a454edSToby Isaac for (c = 0; c < nCells; c++) { 26151a454edSToby Isaac PetscInt cell = isStride ? (sfirst + c * stride) : cells[c]; 26251a454edSToby Isaac PetscInt rem = cell; 26351a454edSToby Isaac PetscInt ijk[3] = {0}; 26451a454edSToby Isaac void *cB, *cD, *cH; 26551a454edSToby Isaac 26651a454edSToby Isaac if (datatype == PETSC_SCALAR) { 2678e3a54c0SPierre Jolivet cB = PetscSafePointerPlusOffset((PetscScalar *)B, nc * nq * c); 2688e3a54c0SPierre Jolivet cD = PetscSafePointerPlusOffset((PetscScalar *)D, nc * nq * dim * c); 2698e3a54c0SPierre Jolivet cH = PetscSafePointerPlusOffset((PetscScalar *)H, nc * nq * dim * dim * c); 27051a454edSToby Isaac } else { 27157508eceSPierre Jolivet cB = PetscSafePointerPlusOffset((PetscReal *)B, nc * nq * c); 27257508eceSPierre Jolivet cD = PetscSafePointerPlusOffset((PetscReal *)D, nc * nq * dim * c); 27357508eceSPierre Jolivet cH = PetscSafePointerPlusOffset((PetscReal *)H, nc * nq * dim * dim * c); 27451a454edSToby Isaac } 2751dca8a05SBarry Smith PetscCheck(cell >= cStart && cell < cEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " not a cell [%" PetscInt_FMT ",%" PetscInt_FMT "), not implemented yet", cell, cStart, cEnd); 276ad540459SPierre Jolivet for (i = 0; i < nc * whol; i++) work[i] = dafield->cornerCoeffs[i]; 27751a454edSToby Isaac for (j = 0; j < dim; j++) { 27851a454edSToby Isaac PetscReal e, d; 27951a454edSToby Isaac ijk[j] = (rem % cellsPer[j]); 28051a454edSToby Isaac rem /= cellsPer[j]; 28151a454edSToby Isaac 28251a454edSToby Isaac e = 2. * (ijk[j] + first[j] + 0.5) * stepPer[j] - 1.; 28351a454edSToby Isaac d = stepPer[j]; 28451a454edSToby Isaac for (i = 0; i < half; i++) { 28551a454edSToby Isaac for (k = 0; k < nc; k++) { 28651a454edSToby Isaac cellCoeffs[i * nc + k] = work[2 * i * nc + k] * d; 28751a454edSToby Isaac cellCoeffs[(i + half) * nc + k] = work[2 * i * nc + k] * e + work[(2 * i + 1) * nc + k]; 28851a454edSToby Isaac } 28951a454edSToby Isaac } 290ad540459SPierre Jolivet for (i = 0; i < whol * nc; i++) work[i] = cellCoeffs[i]; 29151a454edSToby Isaac } 29251a454edSToby Isaac MultilinearEvaluate(dim, cellCoordRange, nc, cellCoeffs, dafield->work, nq, qs, datatype, cB, cD, cH); 29351a454edSToby Isaac } 29448a46eb9SPierre Jolivet if (!isStride) PetscCall(ISRestoreIndices(cellIS, &cells)); 2959566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, (1 << dim) * nc, MPIU_SCALAR, &cellCoeffs)); 29651a454edSToby Isaac #if defined(PETSC_USE_COMPLEX) 2979566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, nq * dim, MPIU_SCALAR, &qs)); 29851a454edSToby Isaac #endif 2993ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 30051a454edSToby Isaac } 30151a454edSToby Isaac 302d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldEvaluateFV_DA(DMField field, IS cellIS, PetscDataType datatype, void *B, void *D, void *H) 303d71ae5a4SJacob Faibussowitsch { 30451a454edSToby Isaac PetscInt c, i, dim, cellsPer[3] = {0}, first[3] = {0}; 30551a454edSToby Isaac PetscReal stepPer[3] = {0.}; 30651a454edSToby Isaac DM dm; 30751a454edSToby Isaac DMDALocalInfo info; 30851a454edSToby Isaac PetscInt cStart, cEnd, numCells; 30951a454edSToby Isaac PetscInt nc; 3104d1a973fSToby Isaac PetscScalar *points; 31151a454edSToby Isaac DMField_DA *dafield; 31251a454edSToby Isaac PetscBool isStride; 31351a454edSToby Isaac const PetscInt *cells = NULL; 31451a454edSToby Isaac PetscInt sfirst = -1, stride = -1; 31551a454edSToby Isaac 31651a454edSToby Isaac PetscFunctionBegin; 31751a454edSToby Isaac dafield = (DMField_DA *)field->data; 31851a454edSToby Isaac dm = field->dm; 31951a454edSToby Isaac nc = field->numComponents; 3209566063dSJacob Faibussowitsch PetscCall(DMDAGetLocalInfo(dm, &info)); 32151a454edSToby Isaac dim = info.dim; 32251a454edSToby Isaac stepPer[0] = 1. / info.mx; 32351a454edSToby Isaac stepPer[1] = 1. / info.my; 32451a454edSToby Isaac stepPer[2] = 1. / info.mz; 32551a454edSToby Isaac first[0] = info.gxs; 32651a454edSToby Isaac first[1] = info.gys; 32751a454edSToby Isaac first[2] = info.gzs; 32851a454edSToby Isaac cellsPer[0] = info.gxm; 32951a454edSToby Isaac cellsPer[1] = info.gym; 33051a454edSToby Isaac cellsPer[2] = info.gzm; 3319566063dSJacob Faibussowitsch PetscCall(DMDAGetHeightStratum(dm, 0, &cStart, &cEnd)); 3329566063dSJacob Faibussowitsch PetscCall(ISGetLocalSize(cellIS, &numCells)); 3339566063dSJacob Faibussowitsch PetscCall(DMGetWorkArray(dm, dim * numCells, MPIU_SCALAR, &points)); 3349566063dSJacob Faibussowitsch PetscCall(PetscObjectTypeCompare((PetscObject)cellIS, ISSTRIDE, &isStride)); 335ac530a7eSPierre Jolivet if (isStride) PetscCall(ISStrideGetInfo(cellIS, &sfirst, &stride)); 336ac530a7eSPierre Jolivet else PetscCall(ISGetIndices(cellIS, &cells)); 33751a454edSToby Isaac for (c = 0; c < numCells; c++) { 33851a454edSToby Isaac PetscInt cell = isStride ? (sfirst + c * stride) : cells[c]; 33951a454edSToby Isaac PetscInt rem = cell; 34051a454edSToby Isaac PetscInt ijk[3] = {0}; 34151a454edSToby Isaac 3421dca8a05SBarry Smith PetscCheck(cell >= cStart && cell < cEnd, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " not a cell [%" PetscInt_FMT ",%" PetscInt_FMT "), not implemented yet", cell, cStart, cEnd); 34351a454edSToby Isaac for (i = 0; i < dim; i++) { 34451a454edSToby Isaac ijk[i] = (rem % cellsPer[i]); 34551a454edSToby Isaac rem /= cellsPer[i]; 34651a454edSToby Isaac points[dim * c + i] = (ijk[i] + first[i] + 0.5) * stepPer[i]; 34751a454edSToby Isaac } 34851a454edSToby Isaac } 34948a46eb9SPierre Jolivet if (!isStride) PetscCall(ISRestoreIndices(cellIS, &cells)); 35051a454edSToby Isaac MultilinearEvaluate(dim, dafield->coordRange, nc, dafield->cornerCoeffs, dafield->work, numCells, points, datatype, B, D, H); 3519566063dSJacob Faibussowitsch PetscCall(DMRestoreWorkArray(dm, dim * numCells, MPIU_SCALAR, &points)); 3523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 35351a454edSToby Isaac } 35451a454edSToby Isaac 355d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldGetDegree_DA(DMField field, IS pointIS, PetscInt *minDegree, PetscInt *maxDegree) 356d71ae5a4SJacob Faibussowitsch { 35751a454edSToby Isaac DM dm; 35851a454edSToby Isaac PetscInt dim, h, imin; 35951a454edSToby Isaac 36051a454edSToby Isaac PetscFunctionBegin; 36151a454edSToby Isaac dm = field->dm; 3629566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(pointIS, &imin, NULL)); 3639566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 36451a454edSToby Isaac for (h = 0; h <= dim; h++) { 36551a454edSToby Isaac PetscInt hEnd; 36651a454edSToby Isaac 3679566063dSJacob Faibussowitsch PetscCall(DMDAGetHeightStratum(dm, h, NULL, &hEnd)); 36851a454edSToby Isaac if (imin < hEnd) break; 36951a454edSToby Isaac } 37051a454edSToby Isaac dim -= h; 371b7260050SToby Isaac if (minDegree) *minDegree = 1; 372b7260050SToby Isaac if (maxDegree) *maxDegree = dim; 3733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 37451a454edSToby Isaac } 37551a454edSToby Isaac 376d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldCreateDefaultQuadrature_DA(DMField field, IS cellIS, PetscQuadrature *quad) 377d71ae5a4SJacob Faibussowitsch { 37851a454edSToby Isaac PetscInt h, dim, imax, imin; 37951a454edSToby Isaac DM dm; 38051a454edSToby Isaac 38151a454edSToby Isaac PetscFunctionBegin; 38251a454edSToby Isaac dm = field->dm; 3839566063dSJacob Faibussowitsch PetscCall(ISGetMinMax(cellIS, &imin, &imax)); 3849566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 38551a454edSToby Isaac *quad = NULL; 38651a454edSToby Isaac for (h = 0; h <= dim; h++) { 38751a454edSToby Isaac PetscInt hStart, hEnd; 38851a454edSToby Isaac 3899566063dSJacob Faibussowitsch PetscCall(DMDAGetHeightStratum(dm, h, &hStart, &hEnd)); 39051a454edSToby Isaac if (imin >= hStart && imax < hEnd) break; 39151a454edSToby Isaac } 39251a454edSToby Isaac dim -= h; 39348a46eb9SPierre Jolivet if (dim > 0) PetscCall(PetscDTGaussTensorQuadrature(dim, 1, 1, -1.0, 1.0, quad)); 3943ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 39551a454edSToby Isaac } 39651a454edSToby Isaac 397d71ae5a4SJacob Faibussowitsch static PetscErrorCode DMFieldInitialize_DA(DMField field) 398d71ae5a4SJacob Faibussowitsch { 39951a454edSToby Isaac DM dm; 40051a454edSToby Isaac Vec coords = NULL; 40151a454edSToby Isaac PetscInt dim, i, j, k; 4024d1a973fSToby Isaac DMField_DA *dafield = (DMField_DA *)field->data; 40351a454edSToby Isaac 40451a454edSToby Isaac PetscFunctionBegin; 40551a454edSToby Isaac field->ops->destroy = DMFieldDestroy_DA; 40651a454edSToby Isaac field->ops->evaluate = DMFieldEvaluate_DA; 40751a454edSToby Isaac field->ops->evaluateFE = DMFieldEvaluateFE_DA; 40851a454edSToby Isaac field->ops->evaluateFV = DMFieldEvaluateFV_DA; 409b7260050SToby Isaac field->ops->getDegree = DMFieldGetDegree_DA; 41051a454edSToby Isaac field->ops->createDefaultQuadrature = DMFieldCreateDefaultQuadrature_DA; 41151a454edSToby Isaac field->ops->view = DMFieldView_DA; 41251a454edSToby Isaac dm = field->dm; 4139566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 4146858538eSMatthew G. Knepley PetscCall(DMGetCoordinates(dm, &coords)); 41551a454edSToby Isaac if (coords) { 41651a454edSToby Isaac PetscInt n; 41751a454edSToby Isaac const PetscScalar *array; 4189371c9d4SSatish Balay PetscReal mins[3][2] = { 4199371c9d4SSatish Balay {PETSC_MAX_REAL, PETSC_MAX_REAL}, 4209371c9d4SSatish Balay {PETSC_MAX_REAL, PETSC_MAX_REAL}, 4219371c9d4SSatish Balay {PETSC_MAX_REAL, PETSC_MAX_REAL} 4229371c9d4SSatish Balay }; 42351a454edSToby Isaac 4249566063dSJacob Faibussowitsch PetscCall(VecGetLocalSize(coords, &n)); 42551a454edSToby Isaac n /= dim; 4269566063dSJacob Faibussowitsch PetscCall(VecGetArrayRead(coords, &array)); 42751a454edSToby Isaac for (i = 0, k = 0; i < n; i++) { 42851a454edSToby Isaac for (j = 0; j < dim; j++, k++) { 42951a454edSToby Isaac PetscReal val = PetscRealPart(array[k]); 43051a454edSToby Isaac 43151a454edSToby Isaac mins[j][0] = PetscMin(mins[j][0], val); 43251a454edSToby Isaac mins[j][1] = PetscMin(mins[j][1], -val); 43351a454edSToby Isaac } 43451a454edSToby Isaac } 4359566063dSJacob Faibussowitsch PetscCall(VecRestoreArrayRead(coords, &array)); 436e91c04dfSPierre Jolivet PetscCallMPI(MPIU_Allreduce(mins, &dafield->coordRange[0][0], 2 * dim, MPIU_REAL, MPI_MIN, PetscObjectComm((PetscObject)dm))); 437ad540459SPierre Jolivet for (j = 0; j < dim; j++) dafield->coordRange[j][1] = -dafield->coordRange[j][1]; 43851a454edSToby Isaac } else { 43951a454edSToby Isaac for (j = 0; j < dim; j++) { 44051a454edSToby Isaac dafield->coordRange[j][0] = 0.; 44151a454edSToby Isaac dafield->coordRange[j][1] = 1.; 44251a454edSToby Isaac } 44351a454edSToby Isaac } 44451a454edSToby Isaac for (j = 0; j < dim; j++) { 4454d1a973fSToby Isaac PetscReal avg = 0.5 * (dafield->coordRange[j][1] + dafield->coordRange[j][0]); 4464d1a973fSToby Isaac PetscReal dif = 0.5 * (dafield->coordRange[j][1] - dafield->coordRange[j][0]); 44751a454edSToby Isaac 44851a454edSToby Isaac dafield->coordRange[j][0] = avg; 44951a454edSToby Isaac dafield->coordRange[j][1] = dif; 45051a454edSToby Isaac } 4513ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 45251a454edSToby Isaac } 45351a454edSToby Isaac 454d71ae5a4SJacob Faibussowitsch PETSC_INTERN PetscErrorCode DMFieldCreate_DA(DMField field) 455d71ae5a4SJacob Faibussowitsch { 45651a454edSToby Isaac DMField_DA *dafield; 45751a454edSToby Isaac 45851a454edSToby Isaac PetscFunctionBegin; 4594dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&dafield)); 46051a454edSToby Isaac field->data = dafield; 4619566063dSJacob Faibussowitsch PetscCall(DMFieldInitialize_DA(field)); 4623ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 46351a454edSToby Isaac } 46451a454edSToby Isaac 465d71ae5a4SJacob Faibussowitsch PetscErrorCode DMFieldCreateDA(DM dm, PetscInt nc, const PetscScalar *cornerValues, DMField *field) 466d71ae5a4SJacob Faibussowitsch { 46751a454edSToby Isaac DMField b; 46851a454edSToby Isaac DMField_DA *dafield; 46951a454edSToby Isaac PetscInt dim, nv, i, j, k; 47051a454edSToby Isaac PetscInt half; 47151a454edSToby Isaac PetscScalar *cv, *cf, *work; 47251a454edSToby Isaac 47351a454edSToby Isaac PetscFunctionBegin; 4749566063dSJacob Faibussowitsch PetscCall(DMFieldCreate(dm, nc, DMFIELD_VERTEX, &b)); 4759566063dSJacob Faibussowitsch PetscCall(DMFieldSetType(b, DMFIELDDA)); 47651a454edSToby Isaac dafield = (DMField_DA *)b->data; 4779566063dSJacob Faibussowitsch PetscCall(DMGetDimension(dm, &dim)); 47851a454edSToby Isaac nv = (1 << dim) * nc; 4799566063dSJacob Faibussowitsch PetscCall(PetscMalloc3(nv, &cv, nv, &cf, nv, &work)); 48051a454edSToby Isaac for (i = 0; i < nv; i++) cv[i] = cornerValues[i]; 48151a454edSToby Isaac for (i = 0; i < nv; i++) cf[i] = cv[i]; 48251a454edSToby Isaac dafield->cornerVals = cv; 48351a454edSToby Isaac dafield->cornerCoeffs = cf; 48451a454edSToby Isaac dafield->work = work; 48551a454edSToby Isaac half = (1 << (dim - 1)); 48651a454edSToby Isaac for (i = 0; i < dim; i++) { 48751a454edSToby Isaac PetscScalar *w; 48851a454edSToby Isaac 48951a454edSToby Isaac w = work; 49051a454edSToby Isaac for (j = 0; j < half; j++) { 491ad540459SPierre Jolivet for (k = 0; k < nc; k++) w[j * nc + k] = 0.5 * (cf[(2 * j + 1) * nc + k] - cf[(2 * j) * nc + k]); 49251a454edSToby Isaac } 49351a454edSToby Isaac w = &work[j * nc]; 49451a454edSToby Isaac for (j = 0; j < half; j++) { 495ad540459SPierre Jolivet for (k = 0; k < nc; k++) w[j * nc + k] = 0.5 * (cf[(2 * j) * nc + k] + cf[(2 * j + 1) * nc + k]); 49651a454edSToby Isaac } 497ad540459SPierre Jolivet for (j = 0; j < nv; j++) cf[j] = work[j]; 49851a454edSToby Isaac } 49951a454edSToby Isaac *field = b; 5003ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 50151a454edSToby Isaac } 502