Actual source code: ex17.c

  1: static char help[] = "Tests for point location\n\n";

  3: #include <petscsf.h>
  4: #include <petscdmplex.h>

  6: /* To inspect the location process, use

  8:     -dm_plex_print_locate 5 -info :dm
  9: */

 11: typedef struct {
 12:   PetscBool centroids;
 13:   PetscBool custom;
 14: } AppCtx;

 16: static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options)
 17: {
 18:   PetscFunctionBeginUser;
 19:   options->centroids = PETSC_TRUE;
 20:   options->custom    = PETSC_FALSE;

 22:   PetscOptionsBegin(comm, "", "Point Location Options", "DMPLEX");
 23:   PetscCall(PetscOptionsBool("-centroids", "Locate cell centroids", "ex17.c", options->centroids, &options->centroids, NULL));
 24:   PetscCall(PetscOptionsBool("-custom", "Locate user-defined points", "ex17.c", options->custom, &options->custom, NULL));
 25:   PetscOptionsEnd();
 26:   PetscFunctionReturn(PETSC_SUCCESS);
 27: }

 29: static PetscErrorCode CreateMesh(MPI_Comm comm, DM *dm)
 30: {
 31:   PetscFunctionBeginUser;
 32:   PetscCall(DMCreate(comm, dm));
 33:   PetscCall(DMSetType(*dm, DMPLEX));
 34:   PetscCall(DMSetFromOptions(*dm));
 35:   PetscCall(DMViewFromOptions(*dm, NULL, "-dm_view"));
 36:   PetscFunctionReturn(PETSC_SUCCESS);
 37: }

 39: static PetscErrorCode TestCentroidLocation(DM dm, AppCtx *user)
 40: {
 41:   Vec                points;
 42:   PetscSF            cellSF = NULL;
 43:   const PetscSFNode *cells;
 44:   PetscScalar       *a;
 45:   PetscInt           cdim, n;
 46:   PetscInt           cStart, cEnd, c;

 48:   PetscFunctionBeginUser;
 49:   if (!user->centroids) PetscFunctionReturn(PETSC_SUCCESS);
 50:   PetscCall(DMGetCoordinateDim(dm, &cdim));
 51:   PetscCall(DMGetCoordinatesLocalSetUp(dm));
 52:   PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd));
 53:   /* Locate all centroids */
 54:   PetscCall(VecCreateSeq(PETSC_COMM_SELF, (cEnd - cStart) * cdim, &points));
 55:   PetscCall(VecSetBlockSize(points, cdim));
 56:   PetscCall(VecGetArray(points, &a));
 57:   for (c = cStart; c < cEnd; ++c) {
 58:     PetscReal centroid[3];
 59:     PetscInt  off = (c - cStart) * cdim, d;

 61:     PetscCall(DMPlexComputeCellGeometryFVM(dm, c, NULL, centroid, NULL));
 62:     for (d = 0; d < cdim; ++d) a[off + d] = centroid[d];
 63:   }
 64:   PetscCall(VecRestoreArray(points, &a));
 65:   PetscCall(DMLocatePoints(dm, points, DM_POINTLOCATION_NONE, &cellSF));
 66:   PetscCall(VecDestroy(&points));
 67:   PetscCall(PetscSFGetGraph(cellSF, NULL, &n, NULL, &cells));
 68:   if (n != (cEnd - cStart)) {
 69:     for (c = 0; c < n; ++c) {
 70:       if (cells[c].index != c + cStart) PetscCall(PetscPrintf(PETSC_COMM_SELF, "Could not locate centroid of cell %" PetscInt_FMT ", error %" PetscInt_FMT "\n", c + cStart, cells[c].index));
 71:     }
 72:     SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Located %" PetscInt_FMT " points instead of %" PetscInt_FMT, n, cEnd - cStart);
 73:   }
 74:   for (c = cStart; c < cEnd; ++c) PetscCheck(cells[c - cStart].index == c, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Could not locate centroid of cell %" PetscInt_FMT ", instead found %" PetscInt_FMT, c, cells[c - cStart].index);
 75:   PetscCall(PetscSFDestroy(&cellSF));
 76:   PetscFunctionReturn(PETSC_SUCCESS);
 77: }

 79: static PetscErrorCode TestCustomLocation(DM dm, AppCtx *user)
 80: {
 81:   PetscSF            cellSF = NULL;
 82:   const PetscSFNode *cells;
 83:   const PetscInt    *found;
 84:   Vec                points;
 85:   PetscScalar        coords[2] = {0.5, 0.5};
 86:   PetscInt           cdim, Np = 1, Nfd;
 87:   PetscMPIInt        rank;
 88:   MPI_Comm           comm;

 90:   PetscFunctionBeginUser;
 91:   if (!user->custom) PetscFunctionReturn(PETSC_SUCCESS);
 92:   PetscCall(DMGetCoordinateDim(dm, &cdim));

 94:   // Locate serially on each process
 95:   PetscCall(VecCreate(PETSC_COMM_SELF, &points));
 96:   PetscCall(VecSetBlockSize(points, cdim));
 97:   PetscCall(VecSetSizes(points, Np * cdim, PETSC_DETERMINE));
 98:   PetscCall(VecSetFromOptions(points));
 99:   for (PetscInt p = 0; p < Np; ++p) {
100:     const PetscInt idx[2] = {p * cdim, p * cdim + 1};
101:     PetscCall(VecSetValues(points, cdim, idx, coords, INSERT_VALUES));
102:   }
103:   PetscCall(VecAssemblyBegin(points));
104:   PetscCall(VecAssemblyEnd(points));

106:   PetscCall(DMLocatePoints(dm, points, DM_POINTLOCATION_NONE, &cellSF));

108:   PetscCall(PetscSFGetGraph(cellSF, NULL, &Nfd, &found, &cells));
109:   PetscCall(PetscObjectGetComm((PetscObject)dm, &comm));
110:   PetscCallMPI(MPI_Comm_rank(comm, &rank));
111:   PetscCall(PetscSynchronizedPrintf(comm, "[%d] Found %" PetscInt_FMT " particles\n", rank, Nfd));
112:   for (PetscInt p = 0; p < Nfd; ++p) {
113:     const PetscInt     point = found ? found[p] : p;
114:     const PetscScalar *array;
115:     PetscScalar       *ccoords = NULL;
116:     PetscInt           numCoords;
117:     PetscBool          isDG;

119:     // Since the v comm is SELF, rank is always 0
120:     PetscCall(PetscSynchronizedPrintf(comm, "  point %" PetscInt_FMT " cell %" PetscInt_FMT "\n", point, cells[p].index));
121:     PetscCall(DMPlexGetCellCoordinates(dm, cells[p].index, &isDG, &numCoords, &array, &ccoords));
122:     for (PetscInt c = 0; c < numCoords / cdim; ++c) {
123:       PetscCall(PetscSynchronizedPrintf(comm, "  "));
124:       for (PetscInt d = 0; d < cdim; ++d) PetscCall(PetscSynchronizedPrintf(comm, " %g", (double)PetscRealPart(ccoords[c * cdim + d])));
125:       PetscCall(PetscSynchronizedPrintf(comm, "\n"));
126:     }
127:     PetscCall(DMPlexRestoreCellCoordinates(dm, cells[p].index, &isDG, &numCoords, &array, &ccoords));
128:   }
129:   PetscCall(PetscSynchronizedFlush(comm, PETSC_STDOUT));

131:   PetscCall(PetscSFDestroy(&cellSF));
132:   PetscCall(VecDestroy(&points));
133:   PetscFunctionReturn(PETSC_SUCCESS);
134: }

136: int main(int argc, char **argv)
137: {
138:   DM     dm;
139:   AppCtx user;

141:   PetscFunctionBeginUser;
142:   PetscCall(PetscInitialize(&argc, &argv, NULL, help));
143:   PetscCall(ProcessOptions(PETSC_COMM_WORLD, &user));
144:   PetscCall(CreateMesh(PETSC_COMM_WORLD, &dm));
145:   PetscCall(TestCentroidLocation(dm, &user));
146:   PetscCall(TestCustomLocation(dm, &user));
147:   PetscCall(DMDestroy(&dm));
148:   PetscCall(PetscFinalize());
149:   return 0;
150: }

152: /*TEST

154:   testset:
155:     args: -dm_plex_dim 1 -dm_plex_box_faces 10
156:     output_file: output/empty.out

158:     test:
159:       suffix: seg

161:     test:
162:       suffix: seg_hash
163:       args: -dm_refine 2 -dm_plex_hash_location

165:   testset:
166:     args: -dm_plex_box_faces 5,5
167:     output_file: output/empty.out

169:     test:
170:       suffix: tri
171:       requires: triangle

173:     test:
174:       suffix: tri_hash
175:       requires: triangle
176:       args: -dm_refine 2 -dm_plex_hash_location

178:     test:
179:       suffix: quad
180:       args: -dm_plex_simplex 0

182:     test:
183:       suffix: quad_order_2
184:       args: -dm_plex_simplex 0 -dm_coord_petscspace_degree 2

186:     test:
187:       suffix: quad_hash
188:       args: -dm_plex_simplex 0 -dm_refine 2 -dm_plex_hash_location

190:   testset:
191:     args: -dm_plex_dim 3 -dm_plex_box_faces 3,3,3
192:     output_file: output/empty.out

194:     test:
195:       suffix: tet
196:       requires: ctetgen

198:     test:
199:       suffix: tet_hash
200:       requires: ctetgen
201:       args: -dm_refine 1 -dm_plex_hash_location

203:     test:
204:       suffix: hex
205:       args: -dm_plex_simplex 0

207:     test:
208:       suffix: hex_hash
209:       args: -dm_plex_simplex 0 -dm_refine 1 -dm_plex_hash_location

211:     test:
212:       suffix: hex_order_2
213:       args: -dm_plex_simplex 0 -dm_refine 1 -dm_coord_petscspace_degree 2
214:       nsize: 2

216:     test:
217:       suffix: hex_order_3
218:       args: -dm_plex_simplex 0 -dm_coord_petscspace_degree 3

220:   testset:
221:     args: -centroids 0 -custom \
222:           -dm_plex_simplex 0 -dm_plex_box_faces 21,21 -dm_distribute_overlap 4 -petscpartitioner_type simple
223:     nsize: 2

225:     test:
226:       suffix: quad_overlap
227:       args: -dm_plex_hash_location {{0 1}}

229:   # Test location on a Monge Manifold
230:   testset:
231:     args: -dm_refine 3 -dm_coord_space 0 \
232:             -dm_plex_option_phases proj_ -cdm_proj_dm_plex_coordinate_dim 3 -proj_dm_coord_space \
233:             -proj_dm_coord_remap -proj_dm_coord_map sinusoid -proj_dm_coord_map_params 0.1,1.,1.
234:     output_file: output/empty.out

236:     test:
237:       requires: triangle
238:       suffix: tri_monge

240:     test:
241:       suffix: quad_monge
242:       args: -dm_plex_simplex 0

244: TEST*/