/* FormFunctionLocal - Form the local residual F from the local input X Input Parameters: + dm - The mesh . X - Local input vector - user - The user context Output Parameter: . F - Local output vector Note: We form the residual one batch of elements at a time. This allows us to offload work onto an accelerator, like a GPU, or vectorize on a multicore machine. .seealso: FormJacobianLocal() */ PetscErrorCode FormFunctionLocal(DM dm, Vec X, Vec F, AppCtx *user) { const PetscInt debug = user->debug; const PetscInt dim = user->dim; PetscReal *coords, *v0, *J, *invJ, *detJ; PetscScalar *elemVec, *u; const PetscInt numCells = cEnd - cStart; PetscInt cellDof = 0; PetscInt maxQuad = 0; PetscInt jacSize = 1; PetscInt cStart, cEnd, c, field; PetscErrorCode ierr; PetscFunctionBegin; ierr = PetscLogEventBegin(user->residualEvent,0,0,0,0);CHKERRQ(ierr); ierr = VecSet(F, 0.0);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); for(field = 0; field < numFields; ++field) { PetscInt dof = 1; for(d = 0; d < dim; ++d) {dof *= user->q[field].numBasisFuncs*user->q[field].numComponents;} cellDof += dof; maxQuad = PetscMax(maxQuad, user->q[field].numQuadPoints); } for(d = 0; d < dim; ++d) {jacSize *= maxQuad;} ierr = PetscMalloc3(dim,PetscReal,&coords,dim,PetscReal,&v0,jacSize,PetscReal,&J);CHKERRQ(ierr); ierr = PetscMalloc4(numCells*cellDof,PetscScalar,&u,numCells*jacSize,PetscReal,&invJ,numCells,PetscReal,&detJ,numCells*cellDof,PetscScalar,&elemVec);CHKERRQ(ierr); for(c = cStart; c < cEnd; ++c) { const PetscScalar *x; PetscInt i; ierr = DMDAComputeCellGeometry(dm, c, v0, J, &invJ[c*jacSize], &detJ[c]);CHKERRQ(ierr); if (detJ[c] <= 0.0) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Invalid determinant %g for element %d", detJ[c], c); ierr = DMDAVecGetClosure(dm, PETSC_NULL, X, c, &x);CHKERRQ(ierr); for(i = 0; i < cellDof; ++i) { u[c*cellDof+i] = x[i]; } } for(field = 0; field < numFields; ++field) { const PetscInt numQuadPoints = user->q[field].numQuadPoints; const PetscInt numBasisFuncs = user->q[field].numBasisFuncs; void (*f0)(PetscScalar u[], const PetscScalar gradU[], PetscScalar f0[]) = user->f0Funcs[field]; void (*f1)(PetscScalar u[], const PetscScalar gradU[], PetscScalar f1[]) = user->f1Funcs[field]; /* Conforming batches */ PetscInt blockSize = numBasisFuncs*numQuadPoints; PetscInt numBlocks = 1; PetscInt batchSize = numBlocks * blockSize; PetscInt numBatches = user->numBatches; PetscInt numChunks = numCells / (numBatches*batchSize); ierr = IntegrateResidualBatchCPU(numChunks*numBatches*batchSize, numFields, field, u, invJ, detJ, user->q, f0, f1, elemVec, user);CHKERRQ(ierr); /* Remainder */ PetscInt numRemainder = numCells % (numBatches * batchSize); PetscInt offset = numCells - numRemainder; ierr = IntegrateResidualBatchCPU(numRemainder, numFields, field, &u[offset*cellDof], &invJ[offset*dim*dim], &detJ[offset], user->q, f0, f1, &elemVec[offset*cellDof], user);CHKERRQ(ierr); } for(c = cStart; c < cEnd; ++c) { if (debug) {ierr = DMPrintCellVector(c, "Residual", cellDof, &elemVec[c*cellDof]);CHKERRQ(ierr);} ierr = DMComplexVecSetClosure(dm, PETSC_NULL, F, c, &elemVec[c*cellDof], ADD_VALUES);CHKERRQ(ierr); } ierr = PetscFree4(u,invJ,detJ,elemVec);CHKERRQ(ierr); ierr = PetscFree3(coords,v0,J);CHKERRQ(ierr); if (user->showResidual) { PetscInt p; ierr = PetscPrintf(PETSC_COMM_WORLD, "Residual:\n");CHKERRQ(ierr); for(p = 0; p < user->numProcs; ++p) { if (p == user->rank) { Vec f; ierr = VecDuplicate(F, &f);CHKERRQ(ierr); ierr = VecCopy(F, f);CHKERRQ(ierr); ierr = VecChop(f, 1.0e-10);CHKERRQ(ierr); ierr = VecView(f, PETSC_VIEWER_STDOUT_SELF);CHKERRQ(ierr); ierr = VecDestroy(&f);CHKERRQ(ierr); } ierr = PetscBarrier((PetscObject) dm);CHKERRQ(ierr); } } ierr = PetscLogEventEnd(user->residualEvent,0,0,0,0);CHKERRQ(ierr); PetscFunctionReturn(0); }
/*@ DMDASetUniformCoordinates - Sets a DMDA coordinates to be a uniform grid Collective on DMDA Input Parameters: + da - the distributed array object . xmin,xmax - extremes in the x direction . ymin,ymax - extremes in the y direction (use NULL for 1 dimensional problems) - zmin,zmax - extremes in the z direction (use NULL for 1 or 2 dimensional problems) Level: beginner .seealso: DMSetCoordinates(), DMGetCoordinates(), DMDACreate1d(), DMDACreate2d(), DMDACreate3d() @*/ PetscErrorCode DMDASetUniformCoordinates(DM da,PetscReal xmin,PetscReal xmax,PetscReal ymin,PetscReal ymax,PetscReal zmin,PetscReal zmax) { MPI_Comm comm; PetscSection section; DM cda; DMBoundaryType bx,by,bz; Vec xcoor; PetscScalar *coors; PetscReal hx,hy,hz_; PetscInt i,j,k,M,N,P,istart,isize,jstart,jsize,kstart,ksize,dim,cnt; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(da,DM_CLASSID,1); ierr = DMDAGetInfo(da,&dim,&M,&N,&P,0,0,0,0,0,&bx,&by,&bz,0);CHKERRQ(ierr); if (xmax <= xmin) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"xmax must be larger than xmin %g %g",(double)xmin,(double)xmax); if ((ymax <= ymin) && (dim > 1)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"ymax must be larger than ymin %g %g",(double)ymin,(double)ymax); if ((zmax <= zmin) && (dim > 2)) SETERRQ2(PetscObjectComm((PetscObject)da),PETSC_ERR_ARG_INCOMP,"zmax must be larger than zmin %g %g",(double)zmin,(double)zmax); ierr = PetscObjectGetComm((PetscObject)da,&comm);CHKERRQ(ierr); ierr = DMGetDefaultSection(da,§ion);CHKERRQ(ierr); ierr = DMDAGetCorners(da,&istart,&jstart,&kstart,&isize,&jsize,&ksize);CHKERRQ(ierr); ierr = DMGetCoordinateDM(da, &cda);CHKERRQ(ierr); if (section) { /* This would be better as a vector, but this is compatible */ PetscInt numComp[3] = {1, 1, 1}; PetscInt numVertexDof[3] = {1, 1, 1}; ierr = DMDASetFieldName(cda, 0, "x");CHKERRQ(ierr); if (dim > 1) {ierr = DMDASetFieldName(cda, 1, "y");CHKERRQ(ierr);} if (dim > 2) {ierr = DMDASetFieldName(cda, 2, "z");CHKERRQ(ierr);} ierr = DMDACreateSection(cda, numComp, numVertexDof, NULL, NULL);CHKERRQ(ierr); } ierr = DMCreateGlobalVector(cda, &xcoor);CHKERRQ(ierr); if (section) { PetscSection csection; PetscInt vStart, vEnd; ierr = DMGetDefaultGlobalSection(cda,&csection);CHKERRQ(ierr); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(da, dim, &vStart, &vEnd);CHKERRQ(ierr); if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M+1); else hx = (xmax-xmin)/(M ? M : 1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N+1); else hy = (ymax-ymin)/(N ? N : 1); if (bz == DM_BOUNDARY_PERIODIC) hz_ = (zmax-zmin)/(P+1); else hz_ = (zmax-zmin)/(P ? P : 1); switch (dim) { case 1: for (i = 0; i < isize+1; ++i) { PetscInt v = i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off] = xmin + hx*(i+istart); } } break; case 2: for (j = 0; j < jsize+1; ++j) { for (i = 0; i < isize+1; ++i) { PetscInt v = j*(isize+1)+i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off+0] = xmin + hx*(i+istart); coors[off+1] = ymin + hy*(j+jstart); } } } break; case 3: for (k = 0; k < ksize+1; ++k) { for (j = 0; j < jsize+1; ++j) { for (i = 0; i < isize+1; ++i) { PetscInt v = (k*(jsize+1)+j)*(isize+1)+i+vStart, dof, off; ierr = PetscSectionGetDof(csection, v, &dof);CHKERRQ(ierr); ierr = PetscSectionGetOffset(csection, v, &off);CHKERRQ(ierr); if (off >= 0) { coors[off+0] = xmin + hx*(i+istart); coors[off+1] = ymin + hy*(j+jstart); coors[off+2] = zmin + hz_*(k+kstart); } } } } break; default: SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot create uniform coordinates for this dimension %D\n",dim); } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); ierr = DMSetCoordinates(da,xcoor);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)xcoor);CHKERRQ(ierr); ierr = VecDestroy(&xcoor);CHKERRQ(ierr); PetscFunctionReturn(0); } if (dim == 1) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/M; else hx = (xmax-xmin)/(M-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); for (i=0; i<isize; i++) { coors[i] = xmin + hx*(i+istart); } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else if (dim == 2) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M); else hx = (xmax-xmin)/(M-1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N); else hy = (ymax-ymin)/(N-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); cnt = 0; for (j=0; j<jsize; j++) { for (i=0; i<isize; i++) { coors[cnt++] = xmin + hx*(i+istart); coors[cnt++] = ymin + hy*(j+jstart); } } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else if (dim == 3) { if (bx == DM_BOUNDARY_PERIODIC) hx = (xmax-xmin)/(M); else hx = (xmax-xmin)/(M-1); if (by == DM_BOUNDARY_PERIODIC) hy = (ymax-ymin)/(N); else hy = (ymax-ymin)/(N-1); if (bz == DM_BOUNDARY_PERIODIC) hz_ = (zmax-zmin)/(P); else hz_ = (zmax-zmin)/(P-1); ierr = VecGetArray(xcoor,&coors);CHKERRQ(ierr); cnt = 0; for (k=0; k<ksize; k++) { for (j=0; j<jsize; j++) { for (i=0; i<isize; i++) { coors[cnt++] = xmin + hx*(i+istart); coors[cnt++] = ymin + hy*(j+jstart); coors[cnt++] = zmin + hz_*(k+kstart); } } } ierr = VecRestoreArray(xcoor,&coors);CHKERRQ(ierr); } else SETERRQ1(PetscObjectComm((PetscObject)da),PETSC_ERR_SUP,"Cannot create uniform coordinates for this dimension %D\n",dim); ierr = DMSetCoordinates(da,xcoor);CHKERRQ(ierr); ierr = PetscLogObjectParent((PetscObject)da,(PetscObject)xcoor);CHKERRQ(ierr); ierr = VecDestroy(&xcoor);CHKERRQ(ierr); PetscFunctionReturn(0); }
PetscErrorCode DMDASetClosureScalar(DM dm, PetscSection section, PetscInt p,PetscScalar *vArray, const PetscScalar *values, InsertMode mode) { PetscInt dim = dm->dim; PetscInt nVx, nVy, nxF, nXF, nyF, nYF, nzF, nZF, nCx, nCy; PetscInt pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart, yfEnd, zfStart; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); PetscValidScalarPointer(values, 4); PetscValidPointer(values, 5); if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This DM has not default PetscSection"); ierr = DMDAGetHeightStratum(dm, -1, &pStart, &pEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMDAGetNumCells(dm, &nCx, &nCy, NULL, NULL);CHKERRQ(ierr); ierr = DMDAGetNumVertices(dm, &nVx, &nVy, NULL, NULL);CHKERRQ(ierr); ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr); xfStart = fStart; xfEnd = xfStart+nXF; yfStart = xfEnd; yfEnd = yfStart+nYF; zfStart = yfEnd; if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd); if ((p >= cStart) || (p < cEnd)) { /* Cell */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); else if (dim == 2) { /* 4 faces, 4 vertices Bottom-left vertex follows same order as cells Bottom y-face same order as cells Left x-face follows same order as cells We number the quad: 8--3--7 | | 4 0 2 | | 5--1--6 */ PetscInt c = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1); PetscInt v = cy*nVx + cx + vStart; PetscInt xf = cx*nxF + cy + xfStart; PetscInt yf = c + yfStart; PetscInt points[9]; points[0] = p; points[1] = yf; points[2] = xf+nxF; points[3] = yf+nyF; points[4] = xf; points[5] = v+0; points[6] = v+1; points[7] = v+nVx+1; points[8] = v+nVx+0; ierr = FillClosureVec_Private(dm, section, 9, points, vArray, values, mode);CHKERRQ(ierr); } else { /* 6 faces, 8 vertices Bottom-left-back vertex follows same order as cells Back z-face follows same order as cells Bottom y-face follows same order as cells Left x-face follows same order as cells 14-----13 /| /| / | 2 / | / 5| / | 10-----9 4| | 11-|---12 |6 / | / | /1 3| / |/ |/ 7-----8 */ PetscInt c = p - cStart; PetscInt points[15]; points[0] = p; points[1] = c+zfStart; points[2] = c+zfStart+nzF; points[3] = c+yfStart; points[4] = c+xfStart+nxF; points[5] = c+yfStart+nyF; points[6] = c+xfStart; points[7] = c+vStart+0; points[8] = c+vStart+1; points[9] = c+vStart+nVx+1; points[10] = c+vStart+nVx+0; points[11] = c+vStart+nVx*nVy+0; points[12] = c+vStart+nVx*nVy+1; points[13] = c+vStart+nVx*nVy+nVx+1; points[14] = c+vStart+nVx*nVy+nVx+0; ierr = FillClosureVec_Private(dm, section, 15, points, vArray, values, mode);CHKERRQ(ierr); } } else if ((p >= vStart) || (p < vEnd)) { /* Vertex */ ierr = FillClosureVec_Private(dm, section, 1, &p, vArray, values, mode);CHKERRQ(ierr); } else if ((p >= fStart) || (p < fStart + nXF)) { /* X Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The bottom vertex has the same numbering as the face */ PetscInt f = p - xfStart; PetscInt points[3]; points[0] = p; points[1] = f; points[2] = f+nVx; ierr = FillClosureVec_Private(dm, section, 3, points, vArray, values, mode);CHKERRQ(ierr); } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) { /* Y Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The left vertex has the same numbering as the face */ PetscInt f = p - yfStart; PetscInt points[3]; points[0] = p; points[1] = f; points[2] = f+1; ierr = FillClosureVec_Private(dm, section, 3, points, vArray, values, mode);CHKERRQ(ierr); } else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } else { /* Z Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D"); else if (dim == 3) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } PetscFunctionReturn(0); }
PetscErrorCode DMDAGetTransitiveClosure(DM dm, PetscInt p, PetscBool useClosure, PetscInt *closureSize, PetscInt **closure) { PetscInt dim = dm->dim; PetscInt nVx, nVy, nVz, nxF, nXF, nyF, nYF, nzF, nZF; PetscInt pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart; PetscErrorCode ierr; PetscFunctionBegin; if (!useClosure) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Star operation is not yet supported"); PetscValidHeaderSpecific(dm, DM_CLASSID, 1); ierr = DMDAGetHeightStratum(dm, -1, &pStart, &pEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMDAGetNumVertices(dm, &nVx, &nVy, &nVz, NULL);CHKERRQ(ierr); ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr); xfStart = fStart; xfEnd = xfStart+nXF; yfStart = xfEnd; if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd); if ((p >= cStart) || (p < cEnd)) { /* Cell */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); else if (dim == 2) { /* 4 faces, 4 vertices Bottom-left vertex follows same order as cells Bottom y-face same order as cells Left x-face follows same order as cells We number the quad: 8--3--7 | | 4 0 2 | | 5--1--6 */ PetscInt c = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1); PetscInt v = cy*nVx + cx + vStart; PetscInt xf = cy*nxF + cx + xfStart; PetscInt yf = c + yfStart; if (closureSize) {PetscValidPointer(closureSize, 4); *closureSize = 9;} if (!(*closure)) {ierr = DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);CHKERRQ(ierr);} (*closure)[0] = p; (*closure)[1] = yf; (*closure)[2] = xf+1; (*closure)[3] = yf+nyF; (*closure)[4] = xf+0; (*closure)[5] = v+0; (*closure)[6]= v+1; (*closure)[7] = v+nVx+1; (*closure)[8] = v+nVx+0; } else { /* 6 faces, 12 edges, 8 vertices Bottom-left vertex follows same order as cells Bottom y-face same order as cells Left x-face follows same order as cells We number the quad: 8--3--7 | | 4 0 2 | | 5--1--6 */ #if 0 PetscInt c = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1), cz = c / ((nVx-1)*(nVy-1)); PetscInt v = cy*nVx + cx + vStart; PetscInt xf = cy*nxF + cx + xfStart; PetscInt yf = c + yfStart; if (closureSize) {PetscValidPointer(closureSize, 4); *closureSize = 26;} if (!(*closure)) {ierr = DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);CHKERRQ(ierr);} #endif SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } else if ((p >= vStart) || (p < vEnd)) { /* Vertex */ if (closureSize) {PetscValidPointer(closureSize, 4); *closureSize = 1;} if (!(*closure)) {ierr = DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);CHKERRQ(ierr);} (*closure)[0] = p; } else if ((p >= fStart) || (p < fStart + nXF)) { /* X Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The bottom vertex has the same numbering as the face */ PetscInt f = p - xfStart; if (closureSize) {PetscValidPointer(closureSize, 4); *closureSize = 3;} if (!(*closure)) {ierr = DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);CHKERRQ(ierr);} (*closure)[0] = p; (*closure)[1] = f; (*closure)[2] = f+nVx; } else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) { /* Y Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The left vertex has the same numbering as the face */ PetscInt f = p - yfStart; if (closureSize) {PetscValidPointer(closureSize, 4); *closureSize = 3;} if (!(*closure)) {ierr = DMGetWorkArray(dm, *closureSize, PETSC_INT, closure);CHKERRQ(ierr);} (*closure)[0] = p; (*closure)[1] = f; (*closure)[2]= f+1; } else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } else { /* Z Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D"); else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } PetscFunctionReturn(0); }
PetscErrorCode DMDAGetClosure(DM dm, PetscSection section, PetscInt p,PetscInt *n,const PetscInt **closure) { PetscInt dim = dm->dim; PetscInt nVx, nVy, nxF, nXF, nyF, nYF, nzF, nZF; PetscInt pStart, pEnd, cStart, cEnd, vStart, vEnd, fStart, fEnd, xfStart, xfEnd, yfStart; PetscErrorCode ierr; PetscFunctionBegin; PetscValidHeaderSpecific(dm, DM_CLASSID, 1); if (n) PetscValidIntPointer(n,4); if (closure) PetscValidPointer(closure, 5); if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} if (!section) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "This DM has not default PetscSection"); ierr = DMDAGetHeightStratum(dm, -1, &pStart, &pEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, 1, &fStart, &fEnd);CHKERRQ(ierr); ierr = DMDAGetHeightStratum(dm, dim, &vStart, &vEnd);CHKERRQ(ierr); ierr = DMDAGetNumVertices(dm, &nVx, &nVy, NULL, NULL);CHKERRQ(ierr); ierr = DMDAGetNumFaces(dm, &nxF, &nXF, &nyF, &nYF, &nzF, &nZF);CHKERRQ(ierr); xfStart = fStart; xfEnd = xfStart+nXF; yfStart = xfEnd; if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid point %d should be in [%d, %d)", p, pStart, pEnd); if ((p >= cStart) || (p < cEnd)) { /* Cell */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); else if (dim == 2) { /* 4 faces, 4 vertices Bottom-left vertex follows same order as cells Bottom y-face same order as cells Left x-face follows same order as cells We number the quad: 8--3--7 | | 4 0 2 | | 5--1--6 */ PetscInt c = p - cStart, cx = c % (nVx-1), cy = c / (nVx-1); PetscInt v = cy*nVx + cx + vStart; PetscInt xf = cy*nxF + cx + xfStart; PetscInt yf = c + yfStart; PetscInt points[9]; /* Note: initializer list is not computable at compile time, hence we fill the array manually */ points[0] = p; points[1] = yf; points[2] = xf+1; points[3] = yf+nyF; points[4] = xf+0; points[5] = v+0; points[6]= v+1; points[7] = v+nVx+1; points[8] = v+nVx+0; ierr = GetPointArray_Private(dm,9,points,n,closure);CHKERRQ(ierr); } else SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } else if ((p >= vStart) || (p < vEnd)) { /* Vertex */ ierr = GetPointArray_Private(dm,1,&p,n,closure);CHKERRQ(ierr); } else if ((p >= fStart) || (p < fStart + nXF)) { /* X Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The bottom vertex has the same numbering as the face */ PetscInt f = p - xfStart; PetscInt points[3]; points[0] = p; points[1] = f; points[2] = f+nVx; SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken"); ierr = GetPointArray_Private(dm,3,points,n,closure);CHKERRQ(ierr); } else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } else if ((p >= fStart + nXF) || (p < fStart + nXF + nYF)) { /* Y Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) { /* 2 vertices: The left vertex has the same numbering as the face */ PetscInt f = p - yfStart; PetscInt points[3]; points[0] = p; points[1] = f; points[2]= f+1; SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Broken"); ierr = GetPointArray_Private(dm, 3, points, n, closure);CHKERRQ(ierr); } else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } else { /* Z Face */ if (dim == 1) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no faces in 1D"); else if (dim == 2) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "There are no z-faces in 2D"); else if (dim == 3) { /* 4 vertices */ SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Not implemented"); } } PetscFunctionReturn(0); }