1 static char help[] = "Tests for parallel mesh loading and parallel topological interpolation\n\n"; 2 3 #include <petsc/private/dmpleximpl.h> 4 /* List of test meshes 5 6 Network 7 ------- 8 Test 0 (2 ranks): 9 10 network=0: 11 --------- 12 cell 0 cell 1 cell 2 nCells-1 (edge) 13 0 ------ 1 ------ 2 ------ 3 -- -- v -- -- nCells (vertex) 14 15 vertex distribution: 16 rank 0: 0 1 17 rank 1: 2 3 ... nCells 18 cell(edge) distribution: 19 rank 0: 0 1 20 rank 1: 2 ... nCells-1 21 22 network=1: 23 --------- 24 v2 25 ^ 26 | 27 cell 2 28 | 29 v0 --cell 0--> v3--cell 1--> v1 30 31 vertex distribution: 32 rank 0: 0 1 3 33 rank 1: 2 34 cell(edge) distribution: 35 rank 0: 0 1 36 rank 1: 2 37 38 example: 39 mpiexec -n 2 ./ex18 -distribute 1 -dim 1 -orig_dm_view -dist_dm_view -dist_dm_view -petscpartitioner_type parmetis -ncells 50 40 41 Triangle 42 -------- 43 Test 0 (2 ranks): 44 Two triangles sharing a face 45 46 2 47 / | \ 48 / | \ 49 / | \ 50 0 0 | 1 3 51 \ | / 52 \ | / 53 \ | / 54 1 55 56 vertex distribution: 57 rank 0: 0 1 58 rank 1: 2 3 59 cell distribution: 60 rank 0: 0 61 rank 1: 1 62 63 Test 1 (3 ranks): 64 Four triangles partitioned across 3 ranks 65 66 0 _______ 3 67 | \ / | 68 | \ 1 / | 69 | \ / | 70 | 0 2 2 | 71 | / \ | 72 | / 3 \ | 73 | / \ | 74 1 ------- 4 75 76 vertex distribution: 77 rank 0: 0 1 78 rank 1: 2 3 79 rank 2: 4 80 cell distribution: 81 rank 0: 0 82 rank 1: 1 83 rank 2: 2 3 84 85 Test 2 (3 ranks): 86 Four triangles partitioned across 3 ranks 87 88 1 _______ 3 89 | \ / | 90 | \ 1 / | 91 | \ / | 92 | 0 0 2 | 93 | / \ | 94 | / 3 \ | 95 | / \ | 96 2 ------- 4 97 98 vertex distribution: 99 rank 0: 0 1 100 rank 1: 2 3 101 rank 2: 4 102 cell distribution: 103 rank 0: 0 104 rank 1: 1 105 rank 2: 2 3 106 107 Tetrahedron 108 ----------- 109 Test 0: 110 Two tets sharing a face 111 112 cell 3 _______ cell 113 0 / | \ \ 1 114 / | \ \ 115 / | \ \ 116 0----|----4-----2 117 \ | / / 118 \ | / / 119 \ | / / 120 1------- 121 y 122 | x 123 |/ 124 *----z 125 126 vertex distribution: 127 rank 0: 0 1 128 rank 1: 2 3 4 129 cell distribution: 130 rank 0: 0 131 rank 1: 1 132 133 Quadrilateral 134 ------------- 135 Test 0 (2 ranks): 136 Two quads sharing a face 137 138 3-------2-------5 139 | | | 140 | 0 | 1 | 141 | | | 142 0-------1-------4 143 144 vertex distribution: 145 rank 0: 0 1 2 146 rank 1: 3 4 5 147 cell distribution: 148 rank 0: 0 149 rank 1: 1 150 151 TODO Test 1: 152 A quad and a triangle sharing a face 153 154 5-------4 155 | | \ 156 | 0 | \ 157 | | 1 \ 158 2-------3----6 159 160 Hexahedron 161 ---------- 162 Test 0 (2 ranks): 163 Two hexes sharing a face 164 165 cell 7-------------6-------------11 cell 166 0 /| /| /| 1 167 / | F1 / | F7 / | 168 / | / | / | 169 4-------------5-------------10 | 170 | | F4 | | F10 | | 171 | | | | | | 172 |F5 | |F3 | |F9 | 173 | | F2 | | F8 | | 174 | 3---------|---2---------|---9 175 | / | / | / 176 | / F0 | / F6 | / 177 |/ |/ |/ 178 0-------------1-------------8 179 180 vertex distribution: 181 rank 0: 0 1 2 3 4 5 182 rank 1: 6 7 8 9 10 11 183 cell distribution: 184 rank 0: 0 185 rank 1: 1 186 187 */ 188 189 typedef enum {NONE, CREATE, AFTER_CREATE, AFTER_DISTRIBUTE} InterpType; 190 191 typedef struct { 192 PetscInt debug; /* The debugging level */ 193 PetscInt testNum; /* Indicates the mesh to create */ 194 PetscInt dim; /* The topological mesh dimension */ 195 PetscBool cellSimplex; /* Use simplices or hexes */ 196 PetscBool distribute; /* Distribute the mesh */ 197 InterpType interpolate; /* Interpolate the mesh before or after DMPlexDistribute() */ 198 PetscBool useGenerator; /* Construct mesh with a mesh generator */ 199 PetscBool testOrientIF; /* Test for different original interface orientations */ 200 PetscBool testHeavy; /* Run the heavy PointSF test */ 201 PetscBool customView; /* Show results of DMPlexIsInterpolated() etc. */ 202 PetscInt ornt[2]; /* Orientation of interface on rank 0 and rank 1 */ 203 PetscInt faces[3]; /* Number of faces per dimension for generator */ 204 PetscScalar coords[128]; 205 PetscReal coordsTol; 206 PetscInt ncoords; 207 PetscInt pointsToExpand[128]; 208 PetscInt nPointsToExpand; 209 PetscBool testExpandPointsEmpty; 210 char filename[PETSC_MAX_PATH_LEN]; /* Import mesh from file */ 211 } AppCtx; 212 213 struct _n_PortableBoundary { 214 Vec coordinates; 215 PetscInt depth; 216 PetscSection *sections; 217 }; 218 typedef struct _n_PortableBoundary * PortableBoundary; 219 220 #if defined(PETSC_USE_LOG) 221 static PetscLogStage stage[3]; 222 #endif 223 224 static PetscErrorCode DMPlexCheckPointSFHeavy(DM, PortableBoundary); 225 static PetscErrorCode DMPlexSetOrientInterface_Private(DM,PetscBool); 226 static PetscErrorCode DMPlexGetExpandedBoundary_Private(DM, PortableBoundary *); 227 static PetscErrorCode DMPlexExpandedConesToFaces_Private(DM, IS, PetscSection, IS *); 228 229 static PetscErrorCode PortableBoundaryDestroy(PortableBoundary *bnd) 230 { 231 PetscInt d; 232 PetscErrorCode ierr; 233 234 PetscFunctionBegin; 235 if (!*bnd) PetscFunctionReturn(0); 236 ierr = VecDestroy(&(*bnd)->coordinates);CHKERRQ(ierr); 237 for (d=0; d < (*bnd)->depth; d++) { 238 ierr = PetscSectionDestroy(&(*bnd)->sections[d]);CHKERRQ(ierr); 239 } 240 ierr = PetscFree((*bnd)->sections);CHKERRQ(ierr); 241 ierr = PetscFree(*bnd);CHKERRQ(ierr); 242 PetscFunctionReturn(0); 243 } 244 245 static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 246 { 247 const char *interpTypes[4] = {"none", "create", "after_create", "after_distribute"}; 248 PetscInt interp=NONE, dim; 249 PetscBool flg1, flg2; 250 PetscErrorCode ierr; 251 252 PetscFunctionBegin; 253 options->debug = 0; 254 options->testNum = 0; 255 options->dim = 2; 256 options->cellSimplex = PETSC_TRUE; 257 options->distribute = PETSC_FALSE; 258 options->interpolate = NONE; 259 options->useGenerator = PETSC_FALSE; 260 options->testOrientIF = PETSC_FALSE; 261 options->testHeavy = PETSC_TRUE; 262 options->customView = PETSC_FALSE; 263 options->testExpandPointsEmpty = PETSC_FALSE; 264 options->ornt[0] = 0; 265 options->ornt[1] = 0; 266 options->faces[0] = 2; 267 options->faces[1] = 2; 268 options->faces[2] = 2; 269 options->filename[0] = '\0'; 270 options->coordsTol = PETSC_DEFAULT; 271 272 ierr = PetscOptionsBegin(comm, "", "Meshing Interpolation Test Options", "DMPLEX");CHKERRQ(ierr); 273 ierr = PetscOptionsBoundedInt("-debug", "The debugging level", "ex18.c", options->debug, &options->debug, NULL,0);CHKERRQ(ierr); 274 ierr = PetscOptionsBoundedInt("-testnum", "The mesh to create", "ex18.c", options->testNum, &options->testNum, NULL,0);CHKERRQ(ierr); 275 ierr = PetscOptionsBool("-cell_simplex", "Generate simplices if true, otherwise hexes", "ex18.c", options->cellSimplex, &options->cellSimplex, NULL);CHKERRQ(ierr); 276 ierr = PetscOptionsBool("-distribute", "Distribute the mesh", "ex18.c", options->distribute, &options->distribute, NULL);CHKERRQ(ierr); 277 ierr = PetscOptionsEList("-interpolate", "Type of mesh interpolation (none, create, after_create, after_distribute)", "ex18.c", interpTypes, 4, interpTypes[options->interpolate], &interp, NULL);CHKERRQ(ierr); 278 options->interpolate = (InterpType) interp; 279 if (!options->distribute && options->interpolate == AFTER_DISTRIBUTE) SETERRQ(comm, PETSC_ERR_SUP, "-interpolate after_distribute needs -distribute 1"); 280 ierr = PetscOptionsBool("-use_generator", "Use a mesh generator to build the mesh", "ex18.c", options->useGenerator, &options->useGenerator, NULL);CHKERRQ(ierr); 281 options->ncoords = 128; 282 ierr = PetscOptionsScalarArray("-view_vertices_from_coords", "Print DAG points corresponding to vertices with given coordinates", "ex18.c", options->coords, &options->ncoords, NULL);CHKERRQ(ierr); 283 ierr = PetscOptionsReal("-view_vertices_from_coords_tol", "Tolerance for -view_vertices_from_coords", "ex18.c", options->coordsTol, &options->coordsTol, NULL);CHKERRQ(ierr); 284 options->nPointsToExpand = 128; 285 ierr = PetscOptionsIntArray("-test_expand_points", "Expand given array of DAG point using DMPlexGetConeRecursive() and print results", "ex18.c", options->pointsToExpand, &options->nPointsToExpand, NULL);CHKERRQ(ierr); 286 if (options->nPointsToExpand) { 287 ierr = PetscOptionsBool("-test_expand_points_empty", "For -test_expand_points, rank 0 will have empty input array", "ex18.c", options->testExpandPointsEmpty, &options->testExpandPointsEmpty, NULL);CHKERRQ(ierr); 288 } 289 ierr = PetscOptionsBool("-test_heavy", "Run the heavy PointSF test", "ex18.c", options->testHeavy, &options->testHeavy, NULL);CHKERRQ(ierr); 290 ierr = PetscOptionsBool("-custom_view", "Custom DMPlex view", "ex18.c", options->customView, &options->customView, NULL);CHKERRQ(ierr); 291 ierr = PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex18.c", options->dim, &options->dim, &flg1,1,3);CHKERRQ(ierr); 292 dim = 3; 293 ierr = PetscOptionsIntArray("-faces", "Number of faces per dimension", "ex18.c", options->faces, &dim, &flg2);CHKERRQ(ierr); 294 if (flg2) { 295 if (flg1 && dim != options->dim) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "specified -dim %D is not equal to length %D of -faces (note that -dim can be omitted)", options->dim, dim); 296 options->dim = dim; 297 } 298 ierr = PetscOptionsString("-filename", "The mesh file", "ex18.c", options->filename, options->filename, sizeof(options->filename), NULL);CHKERRQ(ierr); 299 ierr = PetscOptionsBoundedInt("-rotate_interface_0", "Rotation (relative orientation) of interface on rank 0; implies -interpolate create -distribute 0", "ex18.c", options->ornt[0], &options->ornt[0], &options->testOrientIF,0);CHKERRQ(ierr); 300 ierr = PetscOptionsBoundedInt("-rotate_interface_1", "Rotation (relative orientation) of interface on rank 1; implies -interpolate create -distribute 0", "ex18.c", options->ornt[1], &options->ornt[1], &flg2,0);CHKERRQ(ierr); 301 if (flg2 != options->testOrientIF) SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "neither or both -rotate_interface_0 -rotate_interface_1 must be set"); 302 if (options->testOrientIF) { 303 PetscInt i; 304 for (i=0; i<2; i++) { 305 if (options->ornt[i] >= 10) options->ornt[i] = -(options->ornt[i]-10); /* 11 12 13 become -1 -2 -3 */ 306 } 307 options->filename[0] = 0; 308 options->useGenerator = PETSC_FALSE; 309 options->dim = 3; 310 options->cellSimplex = PETSC_TRUE; 311 options->interpolate = CREATE; 312 options->distribute = PETSC_FALSE; 313 } 314 ierr = PetscOptionsEnd();CHKERRQ(ierr); 315 PetscFunctionReturn(0); 316 } 317 318 static PetscErrorCode CreateMesh_1D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) 319 { 320 PetscInt testNum = user->testNum; 321 PetscMPIInt rank,size; 322 PetscErrorCode ierr; 323 PetscInt numCorners=2,i; 324 PetscInt numCells,numVertices,network; 325 PetscInt *cells; 326 PetscReal *coords; 327 328 PetscFunctionBegin; 329 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 330 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 331 if (size > 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for <=2 processes",testNum); 332 333 numCells = 3; 334 ierr = PetscOptionsGetInt(NULL, NULL, "-ncells", &numCells, NULL);CHKERRQ(ierr); 335 if (numCells < 3) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test ncells must >=3",numCells); 336 337 if (size == 1) { 338 numVertices = numCells + 1; 339 ierr = PetscMalloc2(2*numCells,&cells,2*numVertices,&coords);CHKERRQ(ierr); 340 for (i=0; i<numCells; i++) { 341 cells[2*i] = i; cells[2*i+1] = i + 1; 342 coords[2*i] = i; coords[2*i+1] = i + 1; 343 } 344 345 ierr = DMPlexCreateFromCellListPetsc(comm, user->dim, numCells, numVertices, numCorners, PETSC_FALSE, cells, user->dim, coords, dm);CHKERRQ(ierr); 346 ierr = PetscFree2(cells,coords);CHKERRQ(ierr); 347 PetscFunctionReturn(0); 348 } 349 350 network = 0; 351 ierr = PetscOptionsGetInt(NULL, NULL, "-network_case", &network, NULL);CHKERRQ(ierr); 352 if (network == 0) { 353 switch (rank) { 354 case 0: 355 { 356 numCells = 2; 357 numVertices = numCells; 358 ierr = PetscMalloc2(2*numCells,&cells,2*numCells,&coords);CHKERRQ(ierr); 359 cells[0] = 0; cells[1] = 1; 360 cells[2] = 1; cells[3] = 2; 361 coords[0] = 0.; coords[1] = 1.; 362 coords[2] = 1.; coords[3] = 2.; 363 } 364 break; 365 case 1: 366 { 367 numCells -= 2; 368 numVertices = numCells + 1; 369 ierr = PetscMalloc2(2*numCells,&cells,2*numCells,&coords);CHKERRQ(ierr); 370 for (i=0; i<numCells; i++) { 371 cells[2*i] = 2+i; cells[2*i+1] = 2 + i + 1; 372 coords[2*i] = 2+i; coords[2*i+1] = 2 + i + 1; 373 } 374 } 375 break; 376 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 377 } 378 } else { /* network_case = 1 */ 379 /* ----------------------- */ 380 switch (rank) { 381 case 0: 382 { 383 numCells = 2; 384 numVertices = 3; 385 ierr = PetscMalloc2(2*numCells,&cells,2*numCells,&coords);CHKERRQ(ierr); 386 cells[0] = 0; cells[1] = 3; 387 cells[2] = 3; cells[3] = 1; 388 } 389 break; 390 case 1: 391 { 392 numCells = 1; 393 numVertices = 1; 394 ierr = PetscMalloc2(2*numCells,&cells,2*numCells,&coords);CHKERRQ(ierr); 395 cells[0] = 3; cells[1] = 2; 396 } 397 break; 398 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 399 } 400 } 401 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, PETSC_FALSE, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 402 ierr = PetscFree2(cells,coords);CHKERRQ(ierr); 403 PetscFunctionReturn(0); 404 } 405 406 static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) 407 { 408 PetscInt testNum = user->testNum, p; 409 PetscMPIInt rank, size; 410 PetscErrorCode ierr; 411 412 PetscFunctionBegin; 413 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 414 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 415 switch (testNum) { 416 case 0: 417 if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 2 processes", testNum); 418 switch (rank) { 419 case 0: 420 { 421 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 422 const PetscInt cells[3] = {0, 1, 2}; 423 PetscReal coords[4] = {-0.5, 0.5, 0.0, 0.0}; 424 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 425 426 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 427 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 428 } 429 break; 430 case 1: 431 { 432 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 433 const PetscInt cells[3] = {1, 3, 2}; 434 PetscReal coords[4] = {0.0, 1.0, 0.5, 0.5}; 435 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 436 437 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 438 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 439 } 440 break; 441 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 442 } 443 break; 444 case 1: 445 if (size != 3) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 3 processes", testNum); 446 switch (rank) { 447 case 0: 448 { 449 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 450 const PetscInt cells[3] = {0, 1, 2}; 451 PetscReal coords[4] = {0.0, 1.0, 0.0, 0.0}; 452 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 453 454 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 455 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 456 } 457 break; 458 case 1: 459 { 460 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 461 const PetscInt cells[3] = {0, 2, 3}; 462 PetscReal coords[4] = {0.5, 0.5, 1.0, 1.0}; 463 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 464 465 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 466 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 467 } 468 break; 469 case 2: 470 { 471 const PetscInt numCells = 2, numVertices = 1, numCorners = 3; 472 const PetscInt cells[6] = {2, 4, 3, 2, 1, 4}; 473 PetscReal coords[2] = {1.0, 0.0}; 474 PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1}; 475 476 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 477 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 478 } 479 break; 480 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 481 } 482 break; 483 case 2: 484 if (size != 3) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 3 processes", testNum); 485 switch (rank) { 486 case 0: 487 { 488 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 489 const PetscInt cells[3] = {1, 2, 0}; 490 PetscReal coords[4] = {0.5, 0.5, 0.0, 1.0}; 491 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 492 493 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 494 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 495 } 496 break; 497 case 1: 498 { 499 const PetscInt numCells = 1, numVertices = 2, numCorners = 3; 500 const PetscInt cells[3] = {1, 0, 3}; 501 PetscReal coords[4] = {0.0, 0.0, 1.0, 1.0}; 502 PetscInt markerPoints[6] = {1, 1, 2, 1, 3, 1}; 503 504 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 505 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 506 } 507 break; 508 case 2: 509 { 510 const PetscInt numCells = 2, numVertices = 1, numCorners = 3; 511 const PetscInt cells[6] = {0, 4, 3, 0, 2, 4}; 512 PetscReal coords[2] = {1.0, 0.0}; 513 PetscInt markerPoints[10] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1}; 514 515 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 516 for (p = 0; p < 3; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 517 } 518 break; 519 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 520 } 521 break; 522 default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %D", testNum); 523 } 524 PetscFunctionReturn(0); 525 } 526 527 static PetscErrorCode CreateSimplex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) 528 { 529 PetscInt testNum = user->testNum, p; 530 PetscMPIInt rank, size; 531 PetscErrorCode ierr; 532 533 PetscFunctionBegin; 534 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 535 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 536 switch (testNum) { 537 case 0: 538 if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 2 processes", testNum); 539 switch (rank) { 540 case 0: 541 { 542 const PetscInt numCells = 1, numVertices = 2, numCorners = 4; 543 const PetscInt cells[4] = {0, 2, 1, 3}; 544 PetscReal coords[6] = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0}; 545 PetscInt markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1}; 546 547 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 548 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 549 } 550 break; 551 case 1: 552 { 553 const PetscInt numCells = 1, numVertices = 3, numCorners = 4; 554 const PetscInt cells[4] = {1, 2, 4, 3}; 555 PetscReal coords[9] = {1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}; 556 PetscInt markerPoints[8] = {1, 1, 2, 1, 3, 1, 4, 1}; 557 558 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 559 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 560 } 561 break; 562 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 563 } 564 break; 565 default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %D", testNum); 566 } 567 if (user->testOrientIF) { 568 PetscInt ifp[] = {8, 6}; 569 570 ierr = PetscObjectSetName((PetscObject) *dm, "Mesh before orientation");CHKERRQ(ierr); 571 ierr = DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view");CHKERRQ(ierr); 572 /* rotate interface face ifp[rank] by given orientation ornt[rank] */ 573 ierr = DMPlexOrientPoint(*dm, ifp[rank], user->ornt[rank]);CHKERRQ(ierr); 574 ierr = DMViewFromOptions(*dm, NULL, "-before_orientation_dm_view");CHKERRQ(ierr); 575 ierr = DMPlexCheckFaces(*dm, 0);CHKERRQ(ierr); 576 ierr = DMPlexOrientInterface_Internal(*dm);CHKERRQ(ierr); 577 ierr = PetscPrintf(comm, "Orientation test PASSED\n");CHKERRQ(ierr); 578 } 579 PetscFunctionReturn(0); 580 } 581 582 static PetscErrorCode CreateQuad_2D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) 583 { 584 PetscInt testNum = user->testNum, p; 585 PetscMPIInt rank, size; 586 PetscErrorCode ierr; 587 588 PetscFunctionBegin; 589 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 590 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 591 switch (testNum) { 592 case 0: 593 if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 2 processes", testNum); 594 switch (rank) { 595 case 0: 596 { 597 const PetscInt numCells = 1, numVertices = 3, numCorners = 4; 598 const PetscInt cells[4] = {0, 1, 2, 3}; 599 PetscReal coords[6] = {-0.5, 0.0, 0.0, 0.0, 0.0, 1.0}; 600 PetscInt markerPoints[4*2] = {1, 1, 2, 1, 3, 1, 4, 1}; 601 602 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 603 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 604 } 605 break; 606 case 1: 607 { 608 const PetscInt numCells = 1, numVertices = 3, numCorners = 4; 609 const PetscInt cells[4] = {1, 4, 5, 2}; 610 PetscReal coords[6] = {-0.5, 1.0, 0.5, 0.0, 0.5, 1.0}; 611 PetscInt markerPoints[4*2] = {1, 1, 2, 1, 3, 1, 4, 1}; 612 613 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 614 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 615 } 616 break; 617 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 618 } 619 break; 620 default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %D", testNum); 621 } 622 PetscFunctionReturn(0); 623 } 624 625 static PetscErrorCode CreateHex_3D(MPI_Comm comm, PetscBool interpolate, AppCtx *user, DM *dm) 626 { 627 PetscInt testNum = user->testNum, p; 628 PetscMPIInt rank, size; 629 PetscErrorCode ierr; 630 631 PetscFunctionBegin; 632 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 633 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 634 switch (testNum) { 635 case 0: 636 if (size != 2) SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Test mesh %d only for 2 processes", testNum); 637 switch (rank) { 638 case 0: 639 { 640 const PetscInt numCells = 1, numVertices = 6, numCorners = 8; 641 const PetscInt cells[8] = {0, 3, 2, 1, 4, 5, 6, 7}; 642 PetscReal coords[6*3] = {-0.5,0.0,0.0, 0.0,0.0,0.0, 0.0,1.0,0.0, -0.5,1.0,0.0, -0.5,0.0,1.0, 0.0,0.0,1.0}; 643 PetscInt markerPoints[8*2] = {2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1}; 644 645 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 646 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 647 } 648 break; 649 case 1: 650 { 651 const PetscInt numCells = 1, numVertices = 6, numCorners = 8; 652 const PetscInt cells[8] = {1, 2, 9, 8, 5, 10, 11, 6}; 653 PetscReal coords[6*3] = {0.0,1.0,1.0, -0.5,1.0,1.0, 0.5,0.0,0.0, 0.5,1.0,0.0, 0.5,0.0,1.0, 0.5,1.0,1.0}; 654 PetscInt markerPoints[8*2] = {2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1}; 655 656 ierr = DMPlexCreateFromCellListParallelPetsc(comm, user->dim, numCells, numVertices, PETSC_DECIDE, numCorners, interpolate, cells, user->dim, coords, NULL, NULL, dm);CHKERRQ(ierr); 657 for (p = 0; p < 4; ++p) {ierr = DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1]);CHKERRQ(ierr);} 658 } 659 break; 660 default: SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh for rank %d", rank); 661 } 662 break; 663 default: SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %D", testNum); 664 } 665 PetscFunctionReturn(0); 666 } 667 668 static PetscErrorCode CustomView(DM dm, PetscViewer v) 669 { 670 DMPlexInterpolatedFlag interpolated; 671 PetscBool distributed; 672 PetscErrorCode ierr; 673 674 PetscFunctionBegin; 675 ierr = DMPlexIsDistributed(dm, &distributed);CHKERRQ(ierr); 676 ierr = DMPlexIsInterpolatedCollective(dm, &interpolated);CHKERRQ(ierr); 677 ierr = PetscViewerASCIIPrintf(v, "DMPlexIsDistributed: %s\n", PetscBools[distributed]);CHKERRQ(ierr); 678 ierr = PetscViewerASCIIPrintf(v, "DMPlexIsInterpolatedCollective: %s\n", DMPlexInterpolatedFlags[interpolated]);CHKERRQ(ierr); 679 PetscFunctionReturn(0); 680 } 681 682 static PetscErrorCode CreateMeshFromFile(MPI_Comm comm, AppCtx *user, DM *dm, DM *serialDM) 683 { 684 const char *filename = user->filename; 685 PetscBool testHeavy = user->testHeavy; 686 PetscBool interpCreate = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE; 687 PetscBool distributed = PETSC_FALSE; 688 PetscErrorCode ierr; 689 690 PetscFunctionBegin; 691 *serialDM = NULL; 692 if (testHeavy && interpCreate) {ierr = DMPlexSetOrientInterface_Private(NULL, PETSC_FALSE);CHKERRQ(ierr);} 693 ierr = PetscLogStagePush(stage[0]);CHKERRQ(ierr); 694 ierr = DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, dm);CHKERRQ(ierr); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */ 695 ierr = PetscLogStagePop();CHKERRQ(ierr); 696 if (testHeavy && interpCreate) {ierr = DMPlexSetOrientInterface_Private(NULL, PETSC_TRUE);CHKERRQ(ierr);} 697 ierr = DMPlexIsDistributed(*dm, &distributed);CHKERRQ(ierr); 698 ierr = PetscPrintf(comm, "DMPlexCreateFromFile produced %s mesh.\n", distributed ? "distributed" : "serial");CHKERRQ(ierr); 699 if (testHeavy && distributed) { 700 ierr = PetscOptionsSetValue(NULL, "-dm_plex_hdf5_force_sequential", NULL);CHKERRQ(ierr); 701 ierr = DMPlexCreateFromFile(comm, filename, "ex18_plex", interpCreate, serialDM);CHKERRQ(ierr); 702 ierr = DMPlexIsDistributed(*serialDM, &distributed);CHKERRQ(ierr); 703 if (distributed) SETERRQ(comm, PETSC_ERR_PLIB, "unable to create a serial DM from file"); 704 } 705 ierr = DMGetDimension(*dm, &user->dim);CHKERRQ(ierr); 706 PetscFunctionReturn(0); 707 } 708 709 static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 710 { 711 PetscPartitioner part; 712 PortableBoundary boundary = NULL; 713 DM serialDM = NULL; 714 PetscBool cellSimplex = user->cellSimplex; 715 PetscBool useGenerator = user->useGenerator; 716 PetscBool interpCreate = user->interpolate == CREATE ? PETSC_TRUE : PETSC_FALSE; 717 PetscBool interpSerial = user->interpolate == AFTER_CREATE ? PETSC_TRUE : PETSC_FALSE; 718 PetscBool interpParallel = user->interpolate == AFTER_DISTRIBUTE ? PETSC_TRUE : PETSC_FALSE; 719 PetscBool testHeavy = user->testHeavy; 720 PetscMPIInt rank; 721 PetscErrorCode ierr; 722 723 PetscFunctionBegin; 724 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 725 if (user->filename[0]) { 726 ierr = CreateMeshFromFile(comm, user, dm, &serialDM);CHKERRQ(ierr); 727 } else if (useGenerator) { 728 ierr = PetscLogStagePush(stage[0]);CHKERRQ(ierr); 729 ierr = DMPlexCreateBoxMesh(comm, user->dim, cellSimplex, user->faces, NULL, NULL, NULL, interpCreate, dm);CHKERRQ(ierr); 730 ierr = PetscLogStagePop();CHKERRQ(ierr); 731 } else { 732 ierr = PetscLogStagePush(stage[0]);CHKERRQ(ierr); 733 switch (user->dim) { 734 case 1: 735 ierr = CreateMesh_1D(comm, interpCreate, user, dm);CHKERRQ(ierr); 736 break; 737 case 2: 738 if (cellSimplex) { 739 ierr = CreateSimplex_2D(comm, interpCreate, user, dm);CHKERRQ(ierr); 740 } else { 741 ierr = CreateQuad_2D(comm, interpCreate, user, dm);CHKERRQ(ierr); 742 } 743 break; 744 case 3: 745 if (cellSimplex) { 746 ierr = CreateSimplex_3D(comm, interpCreate, user, dm);CHKERRQ(ierr); 747 } else { 748 ierr = CreateHex_3D(comm, interpCreate, user, dm);CHKERRQ(ierr); 749 } 750 break; 751 default: 752 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make meshes for dimension %D", user->dim); 753 } 754 ierr = PetscLogStagePop();CHKERRQ(ierr); 755 } 756 if (user->ncoords % user->dim) SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "length of coordinates array %D must be divisable by spatial dimension %D", user->ncoords, user->dim); 757 ierr = PetscObjectSetName((PetscObject) *dm, "Original Mesh");CHKERRQ(ierr); 758 ierr = DMViewFromOptions(*dm, NULL, "-orig_dm_view");CHKERRQ(ierr); 759 760 if (interpSerial) { 761 DM idm; 762 763 if (testHeavy) {ierr = DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE);CHKERRQ(ierr);} 764 ierr = PetscLogStagePush(stage[2]);CHKERRQ(ierr); 765 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */ 766 ierr = PetscLogStagePop();CHKERRQ(ierr); 767 if (testHeavy) {ierr = DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE);CHKERRQ(ierr);} 768 ierr = DMDestroy(dm);CHKERRQ(ierr); 769 *dm = idm; 770 ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Mesh");CHKERRQ(ierr); 771 ierr = DMViewFromOptions(*dm, NULL, "-intp_dm_view");CHKERRQ(ierr); 772 } 773 774 /* Set partitioner options */ 775 ierr = DMPlexGetPartitioner(*dm, &part);CHKERRQ(ierr); 776 if (part) { 777 ierr = PetscPartitionerSetType(part, PETSCPARTITIONERSIMPLE);CHKERRQ(ierr); 778 ierr = PetscPartitionerSetFromOptions(part);CHKERRQ(ierr); 779 } 780 781 if (user->customView) {ierr = CustomView(*dm, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 782 if (testHeavy) { 783 PetscBool distributed; 784 785 ierr = DMPlexIsDistributed(*dm, &distributed);CHKERRQ(ierr); 786 if (!serialDM && !distributed) { 787 serialDM = *dm; 788 ierr = PetscObjectReference((PetscObject)*dm);CHKERRQ(ierr); 789 } 790 if (serialDM) { 791 ierr = DMPlexGetExpandedBoundary_Private(serialDM, &boundary);CHKERRQ(ierr); 792 } 793 if (boundary) { 794 /* check DM which has been created in parallel and already interpolated */ 795 ierr = DMPlexCheckPointSFHeavy(*dm, boundary);CHKERRQ(ierr); 796 } 797 /* Orient interface because it could be deliberately skipped above. It is idempotent. */ 798 ierr = DMPlexOrientInterface_Internal(*dm);CHKERRQ(ierr); 799 } 800 if (user->distribute) { 801 DM pdm = NULL; 802 803 /* Redistribute mesh over processes using that partitioner */ 804 ierr = PetscLogStagePush(stage[1]);CHKERRQ(ierr); 805 ierr = DMPlexDistribute(*dm, 0, NULL, &pdm);CHKERRQ(ierr); 806 ierr = PetscLogStagePop();CHKERRQ(ierr); 807 if (pdm) { 808 ierr = DMDestroy(dm);CHKERRQ(ierr); 809 *dm = pdm; 810 ierr = PetscObjectSetName((PetscObject) *dm, "Redistributed Mesh");CHKERRQ(ierr); 811 ierr = DMViewFromOptions(*dm, NULL, "-dist_dm_view");CHKERRQ(ierr); 812 } 813 814 if (interpParallel) { 815 DM idm; 816 817 if (testHeavy) {ierr = DMPlexSetOrientInterface_Private(*dm, PETSC_FALSE);CHKERRQ(ierr);} 818 ierr = PetscLogStagePush(stage[2]);CHKERRQ(ierr); 819 ierr = DMPlexInterpolate(*dm, &idm);CHKERRQ(ierr); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexCheckPointSFHeavy() */ 820 ierr = PetscLogStagePop();CHKERRQ(ierr); 821 if (testHeavy) {ierr = DMPlexSetOrientInterface_Private(*dm, PETSC_TRUE);CHKERRQ(ierr);} 822 ierr = DMDestroy(dm);CHKERRQ(ierr); 823 *dm = idm; 824 ierr = PetscObjectSetName((PetscObject) *dm, "Interpolated Redistributed Mesh");CHKERRQ(ierr); 825 ierr = DMViewFromOptions(*dm, NULL, "-intp_dm_view");CHKERRQ(ierr); 826 } 827 } 828 if (testHeavy) { 829 if (boundary) { 830 ierr = DMPlexCheckPointSFHeavy(*dm, boundary);CHKERRQ(ierr); 831 } 832 /* Orient interface because it could be deliberately skipped above. It is idempotent. */ 833 ierr = DMPlexOrientInterface_Internal(*dm);CHKERRQ(ierr); 834 } 835 836 ierr = PetscObjectSetName((PetscObject) *dm, "Parallel Mesh");CHKERRQ(ierr); 837 ierr = DMSetFromOptions(*dm);CHKERRQ(ierr); 838 ierr = DMViewFromOptions(*dm, NULL, "-dm_view");CHKERRQ(ierr); 839 840 if (user->customView) {ierr = CustomView(*dm, PETSC_VIEWER_STDOUT_(comm));CHKERRQ(ierr);} 841 ierr = DMDestroy(&serialDM);CHKERRQ(ierr); 842 ierr = PortableBoundaryDestroy(&boundary);CHKERRQ(ierr); 843 PetscFunctionReturn(0); 844 } 845 846 #define ps2d(number) ((double) PetscRealPart(number)) 847 PETSC_STATIC_INLINE PetscErrorCode coord2str(char buf[], size_t len, PetscInt dim, const PetscScalar coords[], PetscReal tol) 848 { 849 PetscErrorCode ierr; 850 851 PetscFunctionBegin; 852 if (dim > 3) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "dim must be less than or equal 3"); 853 if (tol >= 1e-3) { 854 switch (dim) { 855 case 1: ierr = PetscSNPrintf(buf,len,"(%12.3f)",ps2d(coords[0]));CHKERRQ(ierr); 856 case 2: ierr = PetscSNPrintf(buf,len,"(%12.3f, %12.3f)",ps2d(coords[0]),ps2d(coords[1]));CHKERRQ(ierr); 857 case 3: ierr = PetscSNPrintf(buf,len,"(%12.3f, %12.3f, %12.3f)",ps2d(coords[0]),ps2d(coords[1]),ps2d(coords[2]));CHKERRQ(ierr); 858 } 859 } else { 860 switch (dim) { 861 case 1: ierr = PetscSNPrintf(buf,len,"(%12.6f)",ps2d(coords[0]));CHKERRQ(ierr); 862 case 2: ierr = PetscSNPrintf(buf,len,"(%12.6f, %12.6f)",ps2d(coords[0]),ps2d(coords[1]));CHKERRQ(ierr); 863 case 3: ierr = PetscSNPrintf(buf,len,"(%12.6f, %12.6f, %12.6f)",ps2d(coords[0]),ps2d(coords[1]),ps2d(coords[2]));CHKERRQ(ierr); 864 } 865 } 866 PetscFunctionReturn(0); 867 } 868 869 static PetscErrorCode ViewVerticesFromCoords(DM dm, Vec coordsVec, PetscReal tol, PetscViewer viewer) 870 { 871 PetscInt dim, i, npoints; 872 IS pointsIS; 873 const PetscInt *points; 874 const PetscScalar *coords; 875 char coordstr[128]; 876 MPI_Comm comm; 877 PetscMPIInt rank; 878 PetscErrorCode ierr; 879 880 PetscFunctionBegin; 881 ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 882 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 883 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 884 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 885 ierr = DMPlexFindVertices(dm, coordsVec, tol, &pointsIS);CHKERRQ(ierr); 886 ierr = ISGetIndices(pointsIS, &points);CHKERRQ(ierr); 887 ierr = ISGetLocalSize(pointsIS, &npoints);CHKERRQ(ierr); 888 ierr = VecGetArrayRead(coordsVec, &coords);CHKERRQ(ierr); 889 for (i=0; i < npoints; i++) { 890 ierr = coord2str(coordstr, sizeof(coordstr), dim, &coords[i*dim], tol);CHKERRQ(ierr); 891 if (rank == 0 && i) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, "-----\n");CHKERRQ(ierr);} 892 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] %s --> points[%D] = %D\n", rank, coordstr, i, points[i]);CHKERRQ(ierr); 893 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 894 } 895 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 896 ierr = VecRestoreArrayRead(coordsVec, &coords);CHKERRQ(ierr); 897 ierr = ISRestoreIndices(pointsIS, &points);CHKERRQ(ierr); 898 ierr = ISDestroy(&pointsIS);CHKERRQ(ierr); 899 PetscFunctionReturn(0); 900 } 901 902 static PetscErrorCode TestExpandPoints(DM dm, AppCtx *user) 903 { 904 IS is; 905 PetscSection *sects; 906 IS *iss; 907 PetscInt d,depth; 908 PetscMPIInt rank; 909 PetscErrorCode ierr; 910 PetscViewer viewer=PETSC_VIEWER_STDOUT_WORLD, sviewer; 911 912 PetscFunctionBegin; 913 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm),&rank);CHKERRMPI(ierr); 914 if (user->testExpandPointsEmpty && rank == 0) { 915 ierr = ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &is);CHKERRQ(ierr); 916 } else { 917 ierr = ISCreateGeneral(PETSC_COMM_SELF, user->nPointsToExpand, user->pointsToExpand, PETSC_USE_POINTER, &is);CHKERRQ(ierr); 918 } 919 ierr = DMPlexGetConeRecursive(dm, is, &depth, &iss, §s);CHKERRQ(ierr); 920 ierr = PetscViewerGetSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 921 ierr = PetscViewerASCIIPrintf(sviewer, "[%d] ==========================\n",rank);CHKERRQ(ierr); 922 for (d=depth-1; d>=0; d--) { 923 IS checkIS; 924 PetscBool flg; 925 926 ierr = PetscViewerASCIIPrintf(sviewer, "depth %D ---------------\n",d);CHKERRQ(ierr); 927 ierr = PetscSectionView(sects[d], sviewer);CHKERRQ(ierr); 928 ierr = ISView(iss[d], sviewer);CHKERRQ(ierr); 929 /* check reverse operation */ 930 if (d < depth-1) { 931 ierr = DMPlexExpandedConesToFaces_Private(dm, iss[d], sects[d], &checkIS);CHKERRQ(ierr); 932 ierr = ISEqualUnsorted(checkIS, iss[d+1], &flg);CHKERRQ(ierr); 933 if (!flg) SETERRQ(PetscObjectComm((PetscObject) checkIS), PETSC_ERR_PLIB, "DMPlexExpandedConesToFaces_Private produced wrong IS"); 934 ierr = ISDestroy(&checkIS);CHKERRQ(ierr); 935 } 936 } 937 ierr = PetscViewerRestoreSubViewer(viewer,PETSC_COMM_SELF,&sviewer);CHKERRQ(ierr); 938 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 939 ierr = DMPlexRestoreConeRecursive(dm, is, &depth, &iss, §s);CHKERRQ(ierr); 940 ierr = ISDestroy(&is);CHKERRQ(ierr); 941 PetscFunctionReturn(0); 942 } 943 944 static PetscErrorCode DMPlexExpandedConesToFaces_Private(DM dm, IS is, PetscSection section, IS *newis) 945 { 946 PetscInt n,n1,ncone,numCoveredPoints,o,p,q,start,end; 947 const PetscInt *coveredPoints; 948 const PetscInt *arr, *cone; 949 PetscInt *newarr; 950 PetscErrorCode ierr; 951 952 PetscFunctionBegin; 953 ierr = ISGetLocalSize(is, &n);CHKERRQ(ierr); 954 ierr = PetscSectionGetStorageSize(section, &n1);CHKERRQ(ierr); 955 ierr = PetscSectionGetChart(section, &start, &end);CHKERRQ(ierr); 956 if (n != n1) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "IS size = %D != %D = section storage size", n, n1); 957 ierr = ISGetIndices(is, &arr);CHKERRQ(ierr); 958 ierr = PetscMalloc1(end-start, &newarr);CHKERRQ(ierr); 959 for (q=start; q<end; q++) { 960 ierr = PetscSectionGetDof(section, q, &ncone);CHKERRQ(ierr); 961 ierr = PetscSectionGetOffset(section, q, &o);CHKERRQ(ierr); 962 cone = &arr[o]; 963 if (ncone == 1) { 964 numCoveredPoints = 1; 965 p = cone[0]; 966 } else { 967 PetscInt i; 968 p = PETSC_MAX_INT; 969 for (i=0; i<ncone; i++) if (cone[i] < 0) {p = -1; break;} 970 if (p >= 0) { 971 ierr = DMPlexGetJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 972 if (numCoveredPoints > 1) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_PLIB, "more than one covered points for section point %D",q); 973 if (numCoveredPoints) p = coveredPoints[0]; 974 else p = -2; 975 ierr = DMPlexRestoreJoin(dm, ncone, cone, &numCoveredPoints, &coveredPoints);CHKERRQ(ierr); 976 } 977 } 978 newarr[q-start] = p; 979 } 980 ierr = ISRestoreIndices(is, &arr);CHKERRQ(ierr); 981 ierr = ISCreateGeneral(PETSC_COMM_SELF, end-start, newarr, PETSC_OWN_POINTER, newis);CHKERRQ(ierr); 982 PetscFunctionReturn(0); 983 } 984 985 static PetscErrorCode DMPlexExpandedVerticesToFaces_Private(DM dm, IS boundary_expanded_is, PetscInt depth, PetscSection sections[], IS *boundary_is) 986 { 987 PetscInt d; 988 IS is,newis; 989 PetscErrorCode ierr; 990 991 PetscFunctionBegin; 992 is = boundary_expanded_is; 993 ierr = PetscObjectReference((PetscObject)is);CHKERRQ(ierr); 994 for (d = 0; d < depth-1; ++d) { 995 ierr = DMPlexExpandedConesToFaces_Private(dm, is, sections[d], &newis);CHKERRQ(ierr); 996 ierr = ISDestroy(&is);CHKERRQ(ierr); 997 is = newis; 998 } 999 *boundary_is = is; 1000 PetscFunctionReturn(0); 1001 } 1002 1003 #define CHKERRQI(incall,ierr) if (ierr) {incall = PETSC_FALSE; } 1004 1005 static PetscErrorCode DMLabelViewFromOptionsOnComm_Private(DMLabel label, const char optionname[], MPI_Comm comm) 1006 { 1007 PetscErrorCode ierr; 1008 PetscViewer viewer; 1009 PetscBool flg; 1010 static PetscBool incall = PETSC_FALSE; 1011 PetscViewerFormat format; 1012 1013 PetscFunctionBegin; 1014 if (incall) PetscFunctionReturn(0); 1015 incall = PETSC_TRUE; 1016 ierr = PetscOptionsGetViewer(comm,((PetscObject)label)->options,((PetscObject)label)->prefix,optionname,&viewer,&format,&flg);CHKERRQI(incall,ierr); 1017 if (flg) { 1018 ierr = PetscViewerPushFormat(viewer,format);CHKERRQI(incall,ierr); 1019 ierr = DMLabelView(label, viewer);CHKERRQI(incall,ierr); 1020 ierr = PetscViewerPopFormat(viewer);CHKERRQI(incall,ierr); 1021 ierr = PetscViewerDestroy(&viewer);CHKERRQI(incall,ierr); 1022 } 1023 incall = PETSC_FALSE; 1024 PetscFunctionReturn(0); 1025 } 1026 1027 /* TODO: this is hotfixing DMLabelGetStratumIS() - it should be fixed systematically instead */ 1028 PETSC_STATIC_INLINE PetscErrorCode DMLabelGetStratumISOnComm_Private(DMLabel label, PetscInt value, MPI_Comm comm, IS *is) 1029 { 1030 IS tmpis; 1031 PetscErrorCode ierr; 1032 1033 PetscFunctionBegin; 1034 ierr = DMLabelGetStratumIS(label, value, &tmpis);CHKERRQ(ierr); 1035 if (!tmpis) {ierr = ISCreateGeneral(PETSC_COMM_SELF, 0, NULL, PETSC_USE_POINTER, &tmpis);CHKERRQ(ierr);} 1036 ierr = ISOnComm(tmpis, comm, PETSC_COPY_VALUES, is);CHKERRQ(ierr); 1037 ierr = ISDestroy(&tmpis);CHKERRQ(ierr); 1038 PetscFunctionReturn(0); 1039 } 1040 1041 /* currently only for simple PetscSection without fields or constraints */ 1042 static PetscErrorCode PetscSectionReplicate_Private(MPI_Comm comm, PetscMPIInt rootrank, PetscSection sec0, PetscSection *secout) 1043 { 1044 PetscSection sec; 1045 PetscInt chart[2], p; 1046 PetscInt *dofarr; 1047 PetscMPIInt rank; 1048 PetscErrorCode ierr; 1049 1050 PetscFunctionBegin; 1051 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1052 if (rank == rootrank) { 1053 ierr = PetscSectionGetChart(sec0, &chart[0], &chart[1]);CHKERRQ(ierr); 1054 } 1055 ierr = MPI_Bcast(chart, 2, MPIU_INT, rootrank, comm);CHKERRMPI(ierr); 1056 ierr = PetscMalloc1(chart[1]-chart[0], &dofarr);CHKERRQ(ierr); 1057 if (rank == rootrank) { 1058 for (p = chart[0]; p < chart[1]; p++) { 1059 ierr = PetscSectionGetDof(sec0, p, &dofarr[p-chart[0]]);CHKERRQ(ierr); 1060 } 1061 } 1062 ierr = MPI_Bcast(dofarr, chart[1]-chart[0], MPIU_INT, rootrank, comm);CHKERRMPI(ierr); 1063 ierr = PetscSectionCreate(comm, &sec);CHKERRQ(ierr); 1064 ierr = PetscSectionSetChart(sec, chart[0], chart[1]);CHKERRQ(ierr); 1065 for (p = chart[0]; p < chart[1]; p++) { 1066 ierr = PetscSectionSetDof(sec, p, dofarr[p-chart[0]]);CHKERRQ(ierr); 1067 } 1068 ierr = PetscSectionSetUp(sec);CHKERRQ(ierr); 1069 ierr = PetscFree(dofarr);CHKERRQ(ierr); 1070 *secout = sec; 1071 PetscFunctionReturn(0); 1072 } 1073 1074 static PetscErrorCode DMPlexExpandedVerticesCoordinatesToFaces_Private(DM ipdm, PortableBoundary bnd, IS *face_is) 1075 { 1076 IS faces_expanded_is; 1077 PetscErrorCode ierr; 1078 1079 PetscFunctionBegin; 1080 ierr = DMPlexFindVertices(ipdm, bnd->coordinates, 0.0, &faces_expanded_is);CHKERRQ(ierr); 1081 ierr = DMPlexExpandedVerticesToFaces_Private(ipdm, faces_expanded_is, bnd->depth, bnd->sections, face_is);CHKERRQ(ierr); 1082 ierr = ISDestroy(&faces_expanded_is);CHKERRQ(ierr); 1083 PetscFunctionReturn(0); 1084 } 1085 1086 /* hack disabling DMPlexOrientInterface() call in DMPlexInterpolate() via -dm_plex_interpolate_orient_interfaces option */ 1087 static PetscErrorCode DMPlexSetOrientInterface_Private(DM dm, PetscBool enable) 1088 { 1089 PetscOptions options = NULL; 1090 const char *prefix = NULL; 1091 const char opt[] = "-dm_plex_interpolate_orient_interfaces"; 1092 char prefix_opt[512]; 1093 PetscBool flg, set; 1094 static PetscBool wasSetTrue = PETSC_FALSE; 1095 PetscErrorCode ierr; 1096 1097 PetscFunctionBegin; 1098 if (dm) { 1099 ierr = PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix);CHKERRQ(ierr); 1100 options = ((PetscObject)dm)->options; 1101 } 1102 ierr = PetscStrcpy(prefix_opt, "-");CHKERRQ(ierr); 1103 ierr = PetscStrlcat(prefix_opt, prefix, sizeof(prefix_opt));CHKERRQ(ierr); 1104 ierr = PetscStrlcat(prefix_opt, &opt[1], sizeof(prefix_opt));CHKERRQ(ierr); 1105 ierr = PetscOptionsGetBool(options, prefix, opt, &flg, &set);CHKERRQ(ierr); 1106 if (!enable) { 1107 if (set && flg) wasSetTrue = PETSC_TRUE; 1108 ierr = PetscOptionsSetValue(options, prefix_opt, "0");CHKERRQ(ierr); 1109 } else if (set && !flg) { 1110 if (wasSetTrue) { 1111 ierr = PetscOptionsSetValue(options, prefix_opt, "1");CHKERRQ(ierr); 1112 } else { 1113 /* default is PETSC_TRUE */ 1114 ierr = PetscOptionsClearValue(options, prefix_opt);CHKERRQ(ierr); 1115 } 1116 wasSetTrue = PETSC_FALSE; 1117 } 1118 if (PetscDefined(USE_DEBUG)) { 1119 ierr = PetscOptionsGetBool(options, prefix, opt, &flg, &set);CHKERRQ(ierr); 1120 if (PetscUnlikely(set && flg != enable)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "PetscOptionsSetValue did not have the desired effect"); 1121 } 1122 PetscFunctionReturn(0); 1123 } 1124 1125 /* get coordinate description of the whole-domain boundary */ 1126 static PetscErrorCode DMPlexGetExpandedBoundary_Private(DM dm, PortableBoundary *boundary) 1127 { 1128 PortableBoundary bnd0, bnd; 1129 MPI_Comm comm; 1130 DM idm; 1131 DMLabel label; 1132 PetscInt d; 1133 const char boundaryName[] = "DMPlexDistributeInterpolateMarkInterface_boundary"; 1134 IS boundary_is; 1135 IS *boundary_expanded_iss; 1136 PetscMPIInt rootrank = 0; 1137 PetscMPIInt rank, size; 1138 PetscInt value = 1; 1139 DMPlexInterpolatedFlag intp; 1140 PetscBool flg; 1141 PetscErrorCode ierr; 1142 1143 PetscFunctionBegin; 1144 ierr = PetscNew(&bnd);CHKERRQ(ierr); 1145 ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1146 ierr = MPI_Comm_rank(comm, &rank);CHKERRMPI(ierr); 1147 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1148 ierr = DMPlexIsDistributed(dm, &flg);CHKERRQ(ierr); 1149 if (flg) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "serial DM (all points on one rank) needed"); 1150 1151 /* interpolate serial DM if not yet interpolated */ 1152 ierr = DMPlexIsInterpolatedCollective(dm, &intp);CHKERRQ(ierr); 1153 if (intp == DMPLEX_INTERPOLATED_FULL) { 1154 idm = dm; 1155 ierr = PetscObjectReference((PetscObject)dm);CHKERRQ(ierr); 1156 } else { 1157 ierr = DMPlexInterpolate(dm, &idm);CHKERRQ(ierr); 1158 ierr = DMViewFromOptions(idm, NULL, "-idm_view");CHKERRQ(ierr); 1159 } 1160 1161 /* mark whole-domain boundary of the serial DM */ 1162 ierr = DMLabelCreate(PETSC_COMM_SELF, boundaryName, &label);CHKERRQ(ierr); 1163 ierr = DMAddLabel(idm, label);CHKERRQ(ierr); 1164 ierr = DMPlexMarkBoundaryFaces(idm, value, label);CHKERRQ(ierr); 1165 ierr = DMLabelViewFromOptionsOnComm_Private(label, "-idm_boundary_view", comm);CHKERRQ(ierr); 1166 ierr = DMLabelGetStratumIS(label, value, &boundary_is);CHKERRQ(ierr); 1167 1168 /* translate to coordinates */ 1169 ierr = PetscNew(&bnd0);CHKERRQ(ierr); 1170 ierr = DMGetCoordinatesLocalSetUp(idm);CHKERRQ(ierr); 1171 if (rank == rootrank) { 1172 ierr = DMPlexGetConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections);CHKERRQ(ierr); 1173 ierr = DMGetCoordinatesLocalTuple(dm, boundary_expanded_iss[0], NULL, &bnd0->coordinates);CHKERRQ(ierr); 1174 /* self-check */ 1175 { 1176 IS is0; 1177 ierr = DMPlexExpandedVerticesCoordinatesToFaces_Private(idm, bnd0, &is0);CHKERRQ(ierr); 1178 ierr = ISEqual(is0, boundary_is, &flg);CHKERRQ(ierr); 1179 if (!flg) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "DMPlexExpandedVerticesCoordinatesToFaces_Private produced a wrong IS"); 1180 ierr = ISDestroy(&is0);CHKERRQ(ierr); 1181 } 1182 } else { 1183 ierr = VecCreateSeq(PETSC_COMM_SELF, 0, &bnd0->coordinates);CHKERRQ(ierr); 1184 } 1185 1186 { 1187 Vec tmp; 1188 VecScatter sc; 1189 IS xis; 1190 PetscInt n; 1191 1192 /* just convert seq vectors to mpi vector */ 1193 ierr = VecGetLocalSize(bnd0->coordinates, &n);CHKERRQ(ierr); 1194 ierr = MPI_Bcast(&n, 1, MPIU_INT, rootrank, comm);CHKERRMPI(ierr); 1195 if (rank == rootrank) { 1196 ierr = VecCreateMPI(comm, n, n, &tmp);CHKERRQ(ierr); 1197 } else { 1198 ierr = VecCreateMPI(comm, 0, n, &tmp);CHKERRQ(ierr); 1199 } 1200 ierr = VecCopy(bnd0->coordinates, tmp);CHKERRQ(ierr); 1201 ierr = VecDestroy(&bnd0->coordinates);CHKERRQ(ierr); 1202 bnd0->coordinates = tmp; 1203 1204 /* replicate coordinates from root rank to all ranks */ 1205 ierr = VecCreateMPI(comm, n, n*size, &bnd->coordinates);CHKERRQ(ierr); 1206 ierr = ISCreateStride(comm, n, 0, 1, &xis);CHKERRQ(ierr); 1207 ierr = VecScatterCreate(bnd0->coordinates, xis, bnd->coordinates, NULL, &sc);CHKERRQ(ierr); 1208 ierr = VecScatterBegin(sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 1209 ierr = VecScatterEnd( sc, bnd0->coordinates, bnd->coordinates, INSERT_VALUES, SCATTER_FORWARD);CHKERRQ(ierr); 1210 ierr = VecScatterDestroy(&sc);CHKERRQ(ierr); 1211 ierr = ISDestroy(&xis);CHKERRQ(ierr); 1212 } 1213 bnd->depth = bnd0->depth; 1214 ierr = MPI_Bcast(&bnd->depth, 1, MPIU_INT, rootrank, comm);CHKERRMPI(ierr); 1215 ierr = PetscMalloc1(bnd->depth, &bnd->sections);CHKERRQ(ierr); 1216 for (d=0; d<bnd->depth; d++) { 1217 ierr = PetscSectionReplicate_Private(comm, rootrank, (rank == rootrank) ? bnd0->sections[d] : NULL, &bnd->sections[d]);CHKERRQ(ierr); 1218 } 1219 1220 if (rank == rootrank) { 1221 ierr = DMPlexRestoreConeRecursive(idm, boundary_is, &bnd0->depth, &boundary_expanded_iss, &bnd0->sections);CHKERRQ(ierr); 1222 } 1223 ierr = PortableBoundaryDestroy(&bnd0);CHKERRQ(ierr); 1224 ierr = DMRemoveLabelBySelf(idm, &label, PETSC_TRUE);CHKERRQ(ierr); 1225 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 1226 ierr = ISDestroy(&boundary_is);CHKERRQ(ierr); 1227 ierr = DMDestroy(&idm);CHKERRQ(ierr); 1228 *boundary = bnd; 1229 PetscFunctionReturn(0); 1230 } 1231 1232 /* get faces of inter-partition interface */ 1233 static PetscErrorCode DMPlexGetInterfaceFaces_Private(DM ipdm, IS boundary_faces_is, IS *interface_faces_is) 1234 { 1235 MPI_Comm comm; 1236 DMLabel label; 1237 IS part_boundary_faces_is; 1238 const char partBoundaryName[] = "DMPlexDistributeInterpolateMarkInterface_partBoundary"; 1239 PetscInt value = 1; 1240 DMPlexInterpolatedFlag intp; 1241 PetscErrorCode ierr; 1242 1243 PetscFunctionBegin; 1244 ierr = PetscObjectGetComm((PetscObject)ipdm, &comm);CHKERRQ(ierr); 1245 ierr = DMPlexIsInterpolatedCollective(ipdm, &intp);CHKERRQ(ierr); 1246 if (intp != DMPLEX_INTERPOLATED_FULL) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex"); 1247 1248 /* get ipdm partition boundary (partBoundary) */ 1249 ierr = DMLabelCreate(PETSC_COMM_SELF, partBoundaryName, &label);CHKERRQ(ierr); 1250 ierr = DMAddLabel(ipdm, label);CHKERRQ(ierr); 1251 ierr = DMPlexMarkBoundaryFaces(ipdm, value, label);CHKERRQ(ierr); 1252 ierr = DMLabelViewFromOptionsOnComm_Private(label, "-ipdm_part_boundary_view", comm);CHKERRQ(ierr); 1253 ierr = DMLabelGetStratumISOnComm_Private(label, value, comm, &part_boundary_faces_is);CHKERRQ(ierr); 1254 ierr = DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE);CHKERRQ(ierr); 1255 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 1256 1257 /* remove ipdm whole-domain boundary (boundary_faces_is) from ipdm partition boundary (part_boundary_faces_is), resulting just in inter-partition interface */ 1258 ierr = ISDifference(part_boundary_faces_is,boundary_faces_is,interface_faces_is);CHKERRQ(ierr); 1259 ierr = ISDestroy(&part_boundary_faces_is);CHKERRQ(ierr); 1260 PetscFunctionReturn(0); 1261 } 1262 1263 /* compute inter-partition interface including edges and vertices */ 1264 static PetscErrorCode DMPlexComputeCompleteInterface_Private(DM ipdm, IS interface_faces_is, IS *interface_is) 1265 { 1266 DMLabel label; 1267 PetscInt value = 1; 1268 const char interfaceName[] = "DMPlexDistributeInterpolateMarkInterface_interface"; 1269 DMPlexInterpolatedFlag intp; 1270 MPI_Comm comm; 1271 PetscErrorCode ierr; 1272 1273 PetscFunctionBegin; 1274 ierr = PetscObjectGetComm((PetscObject)ipdm, &comm);CHKERRQ(ierr); 1275 ierr = DMPlexIsInterpolatedCollective(ipdm, &intp);CHKERRQ(ierr); 1276 if (intp != DMPLEX_INTERPOLATED_FULL) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "only for fully interpolated DMPlex"); 1277 1278 ierr = DMLabelCreate(PETSC_COMM_SELF, interfaceName, &label);CHKERRQ(ierr); 1279 ierr = DMAddLabel(ipdm, label);CHKERRQ(ierr); 1280 ierr = DMLabelSetStratumIS(label, value, interface_faces_is);CHKERRQ(ierr); 1281 ierr = DMLabelViewFromOptionsOnComm_Private(label, "-interface_faces_view", comm);CHKERRQ(ierr); 1282 ierr = DMPlexLabelComplete(ipdm, label);CHKERRQ(ierr); 1283 ierr = DMLabelViewFromOptionsOnComm_Private(label, "-interface_view", comm);CHKERRQ(ierr); 1284 ierr = DMLabelGetStratumISOnComm_Private(label, value, comm, interface_is);CHKERRQ(ierr); 1285 ierr = PetscObjectSetName((PetscObject)*interface_is, "interface_is");CHKERRQ(ierr); 1286 ierr = ISViewFromOptions(*interface_is, NULL, "-interface_is_view");CHKERRQ(ierr); 1287 ierr = DMRemoveLabelBySelf(ipdm, &label, PETSC_TRUE);CHKERRQ(ierr); 1288 ierr = DMLabelDestroy(&label);CHKERRQ(ierr); 1289 PetscFunctionReturn(0); 1290 } 1291 1292 static PetscErrorCode PointSFGetOutwardInterfacePoints(PetscSF sf, IS *is) 1293 { 1294 PetscInt n; 1295 const PetscInt *arr; 1296 PetscErrorCode ierr; 1297 1298 PetscFunctionBegin; 1299 ierr = PetscSFGetGraph(sf, NULL, &n, &arr, NULL);CHKERRQ(ierr); 1300 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_USE_POINTER, is);CHKERRQ(ierr); 1301 PetscFunctionReturn(0); 1302 } 1303 1304 static PetscErrorCode PointSFGetInwardInterfacePoints(PetscSF sf, IS *is) 1305 { 1306 PetscInt n; 1307 const PetscInt *rootdegree; 1308 PetscInt *arr; 1309 PetscErrorCode ierr; 1310 1311 PetscFunctionBegin; 1312 ierr = PetscSFSetUp(sf);CHKERRQ(ierr); 1313 ierr = PetscSFComputeDegreeBegin(sf, &rootdegree);CHKERRQ(ierr); 1314 ierr = PetscSFComputeDegreeEnd(sf, &rootdegree);CHKERRQ(ierr); 1315 ierr = PetscSFComputeMultiRootOriginalNumbering(sf, rootdegree, &n, &arr);CHKERRQ(ierr); 1316 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)sf), n, arr, PETSC_OWN_POINTER, is);CHKERRQ(ierr); 1317 PetscFunctionReturn(0); 1318 } 1319 1320 static PetscErrorCode PointSFGetInterfacePoints_Private(PetscSF pointSF, IS *is) 1321 { 1322 IS pointSF_out_is, pointSF_in_is; 1323 PetscErrorCode ierr; 1324 1325 PetscFunctionBegin; 1326 ierr = PointSFGetOutwardInterfacePoints(pointSF, &pointSF_out_is);CHKERRQ(ierr); 1327 ierr = PointSFGetInwardInterfacePoints(pointSF, &pointSF_in_is);CHKERRQ(ierr); 1328 ierr = ISExpand(pointSF_out_is, pointSF_in_is, is);CHKERRQ(ierr); 1329 ierr = ISDestroy(&pointSF_out_is);CHKERRQ(ierr); 1330 ierr = ISDestroy(&pointSF_in_is);CHKERRQ(ierr); 1331 PetscFunctionReturn(0); 1332 } 1333 1334 #define CHKERRMY(ierr) do {if (PetscUnlikely(ierr)) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_PLIB, "PointSF is wrong. Unable to show details!");} while (0) 1335 1336 static PetscErrorCode ViewPointsWithType_Internal(DM dm, IS pointsIS, PetscViewer v) 1337 { 1338 DMLabel label; 1339 PetscSection coordsSection; 1340 Vec coordsVec; 1341 PetscScalar *coordsScalar; 1342 PetscInt coneSize, depth, dim, i, p, npoints; 1343 const PetscInt *points; 1344 PetscErrorCode ierr; 1345 1346 PetscFunctionBegin; 1347 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 1348 ierr = DMGetCoordinateSection(dm, &coordsSection);CHKERRQ(ierr); 1349 ierr = DMGetCoordinatesLocal(dm, &coordsVec);CHKERRQ(ierr); 1350 ierr = VecGetArray(coordsVec, &coordsScalar);CHKERRQ(ierr); 1351 ierr = ISGetLocalSize(pointsIS, &npoints);CHKERRQ(ierr); 1352 ierr = ISGetIndices(pointsIS, &points);CHKERRQ(ierr); 1353 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 1354 ierr = PetscViewerASCIIPushTab(v);CHKERRQ(ierr); 1355 for (i=0; i<npoints; i++) { 1356 p = points[i]; 1357 ierr = DMLabelGetValue(label, p, &depth);CHKERRQ(ierr); 1358 if (!depth) { 1359 PetscInt n, o; 1360 char coordstr[128]; 1361 1362 ierr = PetscSectionGetDof(coordsSection, p, &n);CHKERRQ(ierr); 1363 ierr = PetscSectionGetOffset(coordsSection, p, &o);CHKERRQ(ierr); 1364 ierr = coord2str(coordstr, sizeof(coordstr), n, &coordsScalar[o], 1.0);CHKERRQ(ierr); 1365 ierr = PetscViewerASCIISynchronizedPrintf(v, "vertex %D w/ coordinates %s\n", p, coordstr);CHKERRQ(ierr); 1366 } else { 1367 char entityType[16]; 1368 1369 switch (depth) { 1370 case 1: ierr = PetscStrcpy(entityType, "edge");CHKERRQ(ierr); break; 1371 case 2: ierr = PetscStrcpy(entityType, "face");CHKERRQ(ierr); break; 1372 case 3: ierr = PetscStrcpy(entityType, "cell");CHKERRQ(ierr); break; 1373 default: SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for depth <= 3"); 1374 } 1375 if (depth == dim && dim < 3) { 1376 ierr = PetscStrlcat(entityType, " (cell)", sizeof(entityType));CHKERRQ(ierr); 1377 } 1378 ierr = PetscViewerASCIISynchronizedPrintf(v, "%s %D\n", entityType, p);CHKERRQ(ierr); 1379 } 1380 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1381 if (coneSize) { 1382 const PetscInt *cone; 1383 IS coneIS; 1384 1385 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 1386 ierr = ISCreateGeneral(PETSC_COMM_SELF, coneSize, cone, PETSC_USE_POINTER, &coneIS);CHKERRQ(ierr); 1387 ierr = ViewPointsWithType_Internal(dm, coneIS, v);CHKERRQ(ierr); 1388 ierr = ISDestroy(&coneIS);CHKERRQ(ierr); 1389 } 1390 } 1391 ierr = PetscViewerASCIIPopTab(v);CHKERRQ(ierr); 1392 ierr = VecRestoreArray(coordsVec, &coordsScalar);CHKERRQ(ierr); 1393 ierr = ISRestoreIndices(pointsIS, &points);CHKERRQ(ierr); 1394 PetscFunctionReturn(0); 1395 } 1396 1397 static PetscErrorCode ViewPointsWithType(DM dm, IS points, PetscViewer v) 1398 { 1399 PetscBool flg; 1400 PetscInt npoints; 1401 PetscMPIInt rank; 1402 PetscErrorCode ierr; 1403 1404 PetscFunctionBegin; 1405 ierr = PetscObjectTypeCompare((PetscObject)v, PETSCVIEWERASCII, &flg);CHKERRQ(ierr); 1406 if (!flg) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_SUP, "Only for ASCII viewer"); 1407 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank);CHKERRMPI(ierr); 1408 ierr = PetscViewerASCIIPushSynchronized(v);CHKERRQ(ierr); 1409 ierr = ISGetLocalSize(points, &npoints);CHKERRQ(ierr); 1410 if (npoints) { 1411 ierr = PetscViewerASCIISynchronizedPrintf(v, "[%d] --------\n", rank);CHKERRQ(ierr); 1412 ierr = ViewPointsWithType_Internal(dm, points, v);CHKERRQ(ierr); 1413 } 1414 ierr = PetscViewerFlush(v);CHKERRQ(ierr); 1415 ierr = PetscViewerASCIIPopSynchronized(v);CHKERRQ(ierr); 1416 PetscFunctionReturn(0); 1417 } 1418 1419 static PetscErrorCode DMPlexComparePointSFWithInterface_Private(DM ipdm, IS interface_is) 1420 { 1421 PetscSF pointsf; 1422 IS pointsf_is; 1423 PetscBool flg; 1424 MPI_Comm comm; 1425 PetscMPIInt size; 1426 PetscErrorCode ierr; 1427 1428 PetscFunctionBegin; 1429 ierr = PetscObjectGetComm((PetscObject)ipdm, &comm);CHKERRQ(ierr); 1430 ierr = MPI_Comm_size(comm, &size);CHKERRMPI(ierr); 1431 ierr = DMGetPointSF(ipdm, &pointsf);CHKERRQ(ierr); 1432 if (pointsf) { 1433 PetscInt nroots; 1434 ierr = PetscSFGetGraph(pointsf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 1435 if (nroots < 0) pointsf = NULL; /* uninitialized SF */ 1436 } 1437 if (!pointsf) { 1438 PetscInt N=0; 1439 if (interface_is) {ierr = ISGetSize(interface_is, &N);CHKERRQ(ierr);} 1440 if (N) SETERRQ(comm, PETSC_ERR_PLIB, "interface_is should be NULL or empty for PointSF being NULL"); 1441 PetscFunctionReturn(0); 1442 } 1443 1444 /* get PointSF points as IS pointsf_is */ 1445 ierr = PointSFGetInterfacePoints_Private(pointsf, &pointsf_is);CHKERRQ(ierr); 1446 1447 /* compare pointsf_is with interface_is */ 1448 ierr = ISEqual(interface_is, pointsf_is, &flg);CHKERRQ(ierr); 1449 ierr = MPI_Allreduce(MPI_IN_PLACE,&flg,1,MPIU_BOOL,MPI_LAND,comm);CHKERRMPI(ierr); 1450 if (!flg) { 1451 IS pointsf_extra_is, pointsf_missing_is; 1452 PetscViewer errv = PETSC_VIEWER_STDERR_(comm); 1453 ierr = ISDifference(interface_is, pointsf_is, &pointsf_missing_is);CHKERRMY(ierr); 1454 ierr = ISDifference(pointsf_is, interface_is, &pointsf_extra_is);CHKERRMY(ierr); 1455 ierr = PetscViewerASCIIPrintf(errv, "Points missing in PointSF:\n");CHKERRMY(ierr); 1456 ierr = ViewPointsWithType(ipdm, pointsf_missing_is, errv);CHKERRMY(ierr); 1457 ierr = PetscViewerASCIIPrintf(errv, "Extra points in PointSF:\n");CHKERRMY(ierr); 1458 ierr = ViewPointsWithType(ipdm, pointsf_extra_is, errv);CHKERRMY(ierr); 1459 ierr = ISDestroy(&pointsf_extra_is);CHKERRMY(ierr); 1460 ierr = ISDestroy(&pointsf_missing_is);CHKERRMY(ierr); 1461 SETERRQ(comm, PETSC_ERR_PLIB, "PointSF is wrong! See details above."); 1462 } 1463 ierr = ISDestroy(&pointsf_is);CHKERRQ(ierr); 1464 PetscFunctionReturn(0); 1465 } 1466 1467 /* remove faces & edges from label, leave just vertices */ 1468 static PetscErrorCode DMPlexISFilterVertices_Private(DM dm, IS points) 1469 { 1470 PetscInt vStart, vEnd; 1471 MPI_Comm comm; 1472 PetscErrorCode ierr; 1473 1474 PetscFunctionBegin; 1475 ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1476 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 1477 ierr = ISGeneralFilter(points, vStart, vEnd);CHKERRQ(ierr); 1478 PetscFunctionReturn(0); 1479 } 1480 1481 /* 1482 DMPlexCheckPointSFHeavy - Thoroughly test that the PointSF after parallel DMPlexInterpolate() includes exactly all interface points. 1483 1484 Collective 1485 1486 Input Parameters: 1487 . dm - The DMPlex object 1488 1489 Notes: 1490 The input DMPlex must be serial (one partition has all points, the other partitions have no points). 1491 This is a heavy test which involves DMPlexInterpolate() if the input DM is not interpolated yet, and depends on having a representation of the whole-domain boundary (PortableBoundary), which can be obtained only by DMPlexGetExpandedBoundary_Private() (which involves DMPlexInterpolate() of a sequential DM). 1492 This is mainly intended for debugging/testing purposes. 1493 1494 Algorithm: 1495 1. boundary faces of the serial version of the whole mesh are found using DMPlexMarkBoundaryFaces() 1496 2. boundary faces are translated into vertices using DMPlexGetConeRecursive() and these are translated into coordinates - this description (aka PortableBoundary) is completely independent of partitioning and point numbering 1497 3. the mesh is distributed or loaded in parallel 1498 4. boundary faces of the distributed mesh are reconstructed from PortableBoundary using DMPlexFindVertices() 1499 5. partition boundary faces of the parallel mesh are found using DMPlexMarkBoundaryFaces() 1500 6. partition interfaces are computed as set difference of partition boundary faces minus the reconstructed boundary 1501 7. check that interface covered by PointSF (union of inward and outward points) is equal to the partition interface for each rank, otherwise print the difference and throw an error 1502 1503 Level: developer 1504 1505 .seealso: DMGetPointSF(), DMPlexCheckSymmetry(), DMPlexCheckSkeleton(), DMPlexCheckFaces() 1506 */ 1507 static PetscErrorCode DMPlexCheckPointSFHeavy(DM dm, PortableBoundary bnd) 1508 { 1509 DM ipdm=NULL; 1510 IS boundary_faces_is, interface_faces_is, interface_is; 1511 DMPlexInterpolatedFlag intp; 1512 MPI_Comm comm; 1513 PetscErrorCode ierr; 1514 1515 PetscFunctionBegin; 1516 ierr = PetscObjectGetComm((PetscObject)dm, &comm);CHKERRQ(ierr); 1517 1518 ierr = DMPlexIsInterpolatedCollective(dm, &intp);CHKERRQ(ierr); 1519 if (intp == DMPLEX_INTERPOLATED_FULL) { 1520 ipdm = dm; 1521 } else { 1522 /* create temporary interpolated DM if input DM is not interpolated */ 1523 ierr = DMPlexSetOrientInterface_Private(dm, PETSC_FALSE);CHKERRQ(ierr); 1524 ierr = DMPlexInterpolate(dm, &ipdm);CHKERRQ(ierr); /* with DMPlexOrientInterface_Internal() call skipped so that PointSF issues are left to DMPlexComparePointSFWithInterface_Private() below */ 1525 ierr = DMPlexSetOrientInterface_Private(dm, PETSC_TRUE);CHKERRQ(ierr); 1526 } 1527 ierr = DMViewFromOptions(ipdm, NULL, "-ipdm_view");CHKERRQ(ierr); 1528 1529 /* recover ipdm whole-domain boundary faces from the expanded vertices coordinates */ 1530 ierr = DMPlexExpandedVerticesCoordinatesToFaces_Private(ipdm, bnd, &boundary_faces_is);CHKERRQ(ierr); 1531 /* get inter-partition interface faces (interface_faces_is)*/ 1532 ierr = DMPlexGetInterfaceFaces_Private(ipdm, boundary_faces_is, &interface_faces_is);CHKERRQ(ierr); 1533 /* compute inter-partition interface including edges and vertices (interface_is) */ 1534 ierr = DMPlexComputeCompleteInterface_Private(ipdm, interface_faces_is, &interface_is);CHKERRQ(ierr); 1535 /* destroy immediate ISs */ 1536 ierr = ISDestroy(&boundary_faces_is);CHKERRQ(ierr); 1537 ierr = ISDestroy(&interface_faces_is);CHKERRQ(ierr); 1538 1539 /* for uninterpolated case, keep just vertices in interface */ 1540 if (!intp) { 1541 ierr = DMPlexISFilterVertices_Private(ipdm, interface_is);CHKERRQ(ierr); 1542 ierr = DMDestroy(&ipdm);CHKERRQ(ierr); 1543 } 1544 1545 /* compare PointSF with the boundary reconstructed from coordinates */ 1546 ierr = DMPlexComparePointSFWithInterface_Private(dm, interface_is);CHKERRQ(ierr); 1547 ierr = PetscPrintf(comm, "DMPlexCheckPointSFHeavy PASSED\n");CHKERRQ(ierr); 1548 ierr = ISDestroy(&interface_is);CHKERRQ(ierr); 1549 PetscFunctionReturn(0); 1550 } 1551 1552 int main(int argc, char **argv) 1553 { 1554 DM dm; 1555 AppCtx user; 1556 PetscErrorCode ierr; 1557 1558 ierr = PetscInitialize(&argc, &argv, NULL, help);if (ierr) return ierr; 1559 ierr = PetscLogStageRegister("create",&stage[0]);CHKERRQ(ierr); 1560 ierr = PetscLogStageRegister("distribute",&stage[1]);CHKERRQ(ierr); 1561 ierr = PetscLogStageRegister("interpolate",&stage[2]);CHKERRQ(ierr); 1562 ierr = ProcessOptions(PETSC_COMM_WORLD, &user);CHKERRQ(ierr); 1563 ierr = CreateMesh(PETSC_COMM_WORLD, &user, &dm);CHKERRQ(ierr); 1564 if (user.nPointsToExpand) { 1565 ierr = TestExpandPoints(dm, &user);CHKERRQ(ierr); 1566 } 1567 if (user.ncoords) { 1568 Vec coords; 1569 1570 ierr = VecCreateSeqWithArray(PETSC_COMM_SELF, user.ncoords, user.ncoords, user.coords, &coords);CHKERRQ(ierr); 1571 ierr = ViewVerticesFromCoords(dm, coords, user.coordsTol, PETSC_VIEWER_STDOUT_WORLD);CHKERRQ(ierr); 1572 ierr = VecDestroy(&coords);CHKERRQ(ierr); 1573 } 1574 ierr = DMDestroy(&dm);CHKERRQ(ierr); 1575 ierr = PetscFinalize(); 1576 return ierr; 1577 } 1578 1579 /*TEST 1580 1581 testset: 1582 nsize: 2 1583 args: -dm_view ascii::ascii_info_detail 1584 args: -dm_plex_check_all 1585 test: 1586 suffix: 1_tri_dist0 1587 args: -distribute 0 -interpolate {{none create}separate output} 1588 test: 1589 suffix: 1_tri_dist1 1590 args: -distribute 1 -interpolate {{none create after_distribute}separate output} 1591 test: 1592 suffix: 1_quad_dist0 1593 args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output} 1594 test: 1595 suffix: 1_quad_dist1 1596 args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output} 1597 test: 1598 suffix: 1_1d_dist1 1599 args: -dim 1 -distribute 1 1600 1601 testset: 1602 nsize: 3 1603 args: -testnum 1 -interpolate create 1604 args: -dm_plex_check_all 1605 test: 1606 suffix: 2 1607 args: -dm_view ascii::ascii_info_detail 1608 test: 1609 suffix: 2a 1610 args: -dm_plex_check_cones_conform_on_interfaces_verbose 1611 test: 1612 suffix: 2b 1613 args: -test_expand_points 0,1,2,5,6 1614 test: 1615 suffix: 2c 1616 args: -test_expand_points 0,1,2,5,6 -test_expand_points_empty 1617 1618 testset: 1619 # the same as 1% for 3D 1620 nsize: 2 1621 args: -dim 3 -dm_view ascii::ascii_info_detail 1622 args: -dm_plex_check_all 1623 test: 1624 suffix: 4_tet_dist0 1625 args: -distribute 0 -interpolate {{none create}separate output} 1626 test: 1627 suffix: 4_tet_dist1 1628 args: -distribute 1 -interpolate {{none create after_distribute}separate output} 1629 test: 1630 suffix: 4_hex_dist0 1631 args: -cell_simplex 0 -distribute 0 -interpolate {{none create}separate output} 1632 test: 1633 suffix: 4_hex_dist1 1634 args: -cell_simplex 0 -distribute 1 -interpolate {{none create after_distribute}separate output} 1635 1636 test: 1637 # the same as 4_tet_dist0 but test different initial orientations 1638 suffix: 4_tet_test_orient 1639 nsize: 2 1640 args: -dim 3 -distribute 0 1641 args: -dm_plex_check_all 1642 args: -rotate_interface_0 {{0 1 2 11 12 13}} 1643 args: -rotate_interface_1 {{0 1 2 11 12 13}} 1644 1645 testset: 1646 requires: exodusii 1647 args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/TwoQuads.exo 1648 args: -dm_view ascii::ascii_info_detail 1649 args: -dm_plex_check_all 1650 args: -custom_view 1651 test: 1652 suffix: 5_seq 1653 nsize: 1 1654 args: -distribute 0 -interpolate {{none create}separate output} 1655 test: 1656 # Detail viewing in a non-distributed mesh is broken because the DMLabelView() is collective, but the label is not shared 1657 suffix: 5_dist0 1658 nsize: 2 1659 args: -distribute 0 -interpolate {{none create}separate output} -dm_view 1660 test: 1661 suffix: 5_dist1 1662 nsize: 2 1663 args: -distribute 1 -interpolate {{none create after_distribute}separate output} 1664 1665 testset: 1666 nsize: {{1 2 4}} 1667 args: -use_generator 1668 args: -dm_plex_check_all 1669 args: -distribute -interpolate none 1670 test: 1671 suffix: 6_tri 1672 requires: triangle 1673 args: -faces {{2,2 1,3 7,4}} -cell_simplex 1 -dm_generator triangle 1674 test: 1675 suffix: 6_quad 1676 args: -faces {{2,2 1,3 7,4}} -cell_simplex 0 1677 test: 1678 suffix: 6_tet 1679 requires: ctetgen 1680 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 1 -dm_generator ctetgen 1681 test: 1682 suffix: 6_hex 1683 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 0 1684 testset: 1685 nsize: {{1 2 4}} 1686 args: -use_generator 1687 args: -dm_plex_check_all 1688 args: -distribute -interpolate create 1689 test: 1690 suffix: 6_int_tri 1691 requires: triangle 1692 args: -faces {{2,2 1,3 7,4}} -cell_simplex 1 -dm_generator triangle 1693 test: 1694 suffix: 6_int_quad 1695 args: -faces {{2,2 1,3 7,4}} -cell_simplex 0 1696 test: 1697 suffix: 6_int_tet 1698 requires: ctetgen 1699 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 1 -dm_generator ctetgen 1700 test: 1701 suffix: 6_int_hex 1702 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 0 1703 testset: 1704 nsize: {{2 4}} 1705 args: -use_generator 1706 args: -dm_plex_check_all 1707 args: -distribute -interpolate after_distribute 1708 test: 1709 suffix: 6_parint_tri 1710 requires: triangle 1711 args: -faces {{2,2 1,3 7,4}} -cell_simplex 1 -dm_generator triangle 1712 test: 1713 suffix: 6_parint_quad 1714 args: -faces {{2,2 1,3 7,4}} -cell_simplex 0 1715 test: 1716 suffix: 6_parint_tet 1717 requires: ctetgen 1718 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 1 -dm_generator ctetgen 1719 test: 1720 suffix: 6_parint_hex 1721 args: -faces {{2,2,2 1,3,5 3,4,7}} -cell_simplex 0 1722 1723 testset: # 7 EXODUS 1724 requires: exodusii 1725 args: -dm_plex_check_all 1726 args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.exo 1727 args: -distribute 1728 test: # seq load, simple partitioner 1729 suffix: 7_exo 1730 nsize: {{1 2 4 5}} 1731 args: -interpolate none 1732 test: # seq load, seq interpolation, simple partitioner 1733 suffix: 7_exo_int_simple 1734 nsize: {{1 2 4 5}} 1735 args: -interpolate create 1736 test: # seq load, seq interpolation, metis partitioner 1737 suffix: 7_exo_int_metis 1738 requires: parmetis 1739 nsize: {{2 4 5}} 1740 args: -interpolate create 1741 args: -petscpartitioner_type parmetis 1742 test: # seq load, simple partitioner, par interpolation 1743 suffix: 7_exo_simple_int 1744 nsize: {{2 4 5}} 1745 args: -interpolate after_distribute 1746 test: # seq load, metis partitioner, par interpolation 1747 suffix: 7_exo_metis_int 1748 requires: parmetis 1749 nsize: {{2 4 5}} 1750 args: -interpolate after_distribute 1751 args: -petscpartitioner_type parmetis 1752 1753 testset: # 7 HDF5 SEQUANTIAL LOAD 1754 requires: hdf5 !complex 1755 args: -dm_plex_check_all 1756 args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf 1757 args: -dm_plex_hdf5_force_sequential 1758 args: -distribute 1759 test: # seq load, simple partitioner 1760 suffix: 7_seq_hdf5_simple 1761 nsize: {{1 2 4 5}} 1762 args: -interpolate none 1763 test: # seq load, seq interpolation, simple partitioner 1764 suffix: 7_seq_hdf5_int_simple 1765 nsize: {{1 2 4 5}} 1766 args: -interpolate after_create 1767 test: # seq load, seq interpolation, metis partitioner 1768 nsize: {{2 4 5}} 1769 suffix: 7_seq_hdf5_int_metis 1770 requires: parmetis 1771 args: -interpolate after_create 1772 args: -petscpartitioner_type parmetis 1773 test: # seq load, simple partitioner, par interpolation 1774 suffix: 7_seq_hdf5_simple_int 1775 nsize: {{2 4 5}} 1776 args: -interpolate after_distribute 1777 test: # seq load, metis partitioner, par interpolation 1778 nsize: {{2 4 5}} 1779 suffix: 7_seq_hdf5_metis_int 1780 requires: parmetis 1781 args: -interpolate after_distribute 1782 args: -petscpartitioner_type parmetis 1783 1784 testset: # 7 HDF5 PARALLEL LOAD 1785 requires: hdf5 !complex 1786 nsize: {{2 4 5}} 1787 args: -dm_plex_check_all 1788 args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf 1789 test: # par load 1790 suffix: 7_par_hdf5 1791 args: -interpolate none 1792 test: # par load, par interpolation 1793 suffix: 7_par_hdf5_int 1794 args: -interpolate after_create 1795 test: # par load, parmetis repartitioner 1796 TODO: Parallel partitioning of uninterpolated meshes not supported 1797 suffix: 7_par_hdf5_parmetis 1798 requires: parmetis 1799 args: -distribute -petscpartitioner_type parmetis 1800 args: -interpolate none 1801 test: # par load, par interpolation, parmetis repartitioner 1802 suffix: 7_par_hdf5_int_parmetis 1803 requires: parmetis 1804 args: -distribute -petscpartitioner_type parmetis 1805 args: -interpolate after_create 1806 test: # par load, parmetis partitioner, par interpolation 1807 TODO: Parallel partitioning of uninterpolated meshes not supported 1808 suffix: 7_par_hdf5_parmetis_int 1809 requires: parmetis 1810 args: -distribute -petscpartitioner_type parmetis 1811 args: -interpolate after_distribute 1812 1813 test: 1814 suffix: 7_hdf5_hierarch 1815 requires: hdf5 ptscotch !complex 1816 nsize: {{2 3 4}separate output} 1817 args: -distribute 1818 args: -interpolate after_create 1819 args: -petscpartitioner_type matpartitioning -petscpartitioner_view ::ascii_info 1820 args: -mat_partitioning_type hierarch -mat_partitioning_hierarchical_nfineparts 2 1821 args: -mat_partitioning_hierarchical_coarseparttype ptscotch -mat_partitioning_hierarchical_fineparttype ptscotch 1822 1823 test: 1824 suffix: 8 1825 requires: hdf5 !complex 1826 nsize: 4 1827 args: -filename ${wPETSC_DIR}/share/petsc/datafiles/meshes/blockcylinder-50.h5 -dm_plex_create_from_hdf5_xdmf 1828 args: -distribute 0 -interpolate after_create 1829 args: -view_vertices_from_coords 0.,1.,0.,-0.5,1.,0.,0.583,-0.644,0.,-2.,-2.,-2. -view_vertices_from_coords_tol 1e-3 1830 args: -dm_plex_check_all 1831 args: -custom_view 1832 1833 testset: # 9 HDF5 SEQUANTIAL LOAD 1834 requires: hdf5 !complex datafilespath 1835 args: -dm_plex_check_all 1836 args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /cells -dm_plex_hdf5_geometry_path /coordinates 1837 args: -dm_plex_hdf5_force_sequential 1838 args: -distribute 1839 test: # seq load, simple partitioner 1840 suffix: 9_seq_hdf5_simple 1841 nsize: {{1 2 4 5}} 1842 args: -interpolate none 1843 test: # seq load, seq interpolation, simple partitioner 1844 suffix: 9_seq_hdf5_int_simple 1845 nsize: {{1 2 4 5}} 1846 args: -interpolate after_create 1847 test: # seq load, seq interpolation, metis partitioner 1848 nsize: {{2 4 5}} 1849 suffix: 9_seq_hdf5_int_metis 1850 requires: parmetis 1851 args: -interpolate after_create 1852 args: -petscpartitioner_type parmetis 1853 test: # seq load, simple partitioner, par interpolation 1854 suffix: 9_seq_hdf5_simple_int 1855 nsize: {{2 4 5}} 1856 args: -interpolate after_distribute 1857 test: # seq load, simple partitioner, par interpolation 1858 # This is like 9_seq_hdf5_simple_int but testing error output of DMPlexCheckPointSFHeavy(). 1859 # Once 9_seq_hdf5_simple_int gets fixed, this one gets broken. 1860 # We can then provide an intentionally broken mesh instead. 1861 TODO: This test is broken because PointSF is fixed. 1862 suffix: 9_seq_hdf5_simple_int_err 1863 nsize: 4 1864 args: -interpolate after_distribute 1865 filter: sed -e "/PETSC ERROR/,$$d" 1866 test: # seq load, metis partitioner, par interpolation 1867 nsize: {{2 4 5}} 1868 suffix: 9_seq_hdf5_metis_int 1869 requires: parmetis 1870 args: -interpolate after_distribute 1871 args: -petscpartitioner_type parmetis 1872 1873 testset: # 9 HDF5 PARALLEL LOAD 1874 requires: hdf5 !complex datafilespath 1875 nsize: {{2 4 5}} 1876 args: -dm_plex_check_all 1877 args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /cells -dm_plex_hdf5_geometry_path /coordinates 1878 test: # par load 1879 suffix: 9_par_hdf5 1880 args: -interpolate none 1881 test: # par load, par interpolation 1882 suffix: 9_par_hdf5_int 1883 args: -interpolate after_create 1884 test: # par load, parmetis repartitioner 1885 TODO: Parallel partitioning of uninterpolated meshes not supported 1886 suffix: 9_par_hdf5_parmetis 1887 requires: parmetis 1888 args: -distribute -petscpartitioner_type parmetis 1889 args: -interpolate none 1890 test: # par load, par interpolation, parmetis repartitioner 1891 suffix: 9_par_hdf5_int_parmetis 1892 requires: parmetis 1893 args: -distribute -petscpartitioner_type parmetis 1894 args: -interpolate after_create 1895 test: # par load, parmetis partitioner, par interpolation 1896 TODO: Parallel partitioning of uninterpolated meshes not supported 1897 suffix: 9_par_hdf5_parmetis_int 1898 requires: parmetis 1899 args: -distribute -petscpartitioner_type parmetis 1900 args: -interpolate after_distribute 1901 1902 testset: # 10 HDF5 PARALLEL LOAD 1903 requires: hdf5 !complex datafilespath 1904 nsize: {{2 4 7}} 1905 args: -dm_plex_check_all 1906 args: -filename ${DATAFILESPATH}/meshes/cube-hexahedra-refined2.h5 -dm_plex_create_from_hdf5_xdmf -dm_plex_hdf5_topology_path /topo -dm_plex_hdf5_geometry_path /geom 1907 test: # par load, par interpolation 1908 suffix: 10_par_hdf5_int 1909 args: -interpolate after_create 1910 TEST*/ 1911