1 static char help[] = "Tests for creation of hybrid meshes\n\n"; 2 3 /* TODO 4 - Propagate hybridSize with distribution 5 - Test with multiple fault segments 6 - Test with embedded fault 7 - Test with multiple faults 8 - Move over all PyLith tests? 9 */ 10 11 #include <petscdmplex.h> 12 #include <petscds.h> 13 #include <petsc/private/dmpleximpl.h> 14 /* List of test meshes 15 16 Triangle 17 -------- 18 Test 0: 19 Two triangles sharing a face 20 21 4 22 / | \ 23 8 | 9 24 / | \ 25 2 0 7 1 5 26 \ | / 27 6 | 10 28 \ | / 29 3 30 31 should become two triangles separated by a zero-volume cell with 4 vertices 32 33 5--16--8 4--12--6 3 34 / | | \ / | | | \ 35 11 | | 12 9 | | | 4 36 / | | \ / | | | \ 37 3 0 10 2 14 1 6 2 0 8 1 10 6 0 1 38 \ | | / \ | | | / 39 9 | | 13 7 | | | 5 40 \ | | / \ | | | / 41 4--15--7 3--11--5 2 42 43 Test 1: 44 Four triangles sharing two faces which are oriented against each other 45 46 9 47 / \ 48 / \ 49 17 2 16 50 / \ 51 / \ 52 8-----15----5 53 \ /|\ 54 \ / | \ 55 18 3 12 | 14 56 \ / | \ 57 \ / | \ 58 4 0 11 1 7 59 \ | / 60 \ | / 61 10 | 13 62 \ | / 63 \|/ 64 6 65 66 Fault mesh 67 68 0 --> 0 69 1 --> 1 70 2 --> 2 71 3 --> 3 72 4 --> 5 73 5 --> 6 74 6 --> 8 75 7 --> 11 76 8 --> 15 77 78 2 79 | 80 6----8----4 81 | | 82 3 | 83 0-7-1 84 | 85 | 86 5 87 88 should become four triangles separated by two zero-volume cells with 4 vertices 89 90 11 91 / \ 92 / \ 93 / \ 94 22 2 21 95 / \ 96 / \ 97 10-----20------7 98 28 | 5 26/ \ 99 14----25----12 \ 100 \ /| |\ 101 \ / | | \ 102 23 3 17 | | 19 103 \ / | | \ 104 \ / | | \ 105 6 0 24 4 16 1 9 106 \ | | / 107 \ | | / 108 15 | | 18 109 \ | | / 110 \| |/ 111 13---8 112 27 113 114 Tetrahedron 115 ----------- 116 Test 0: 117 Two tets sharing a face 118 119 cell 5 _______ cell 120 0 / | \ \ 1 121 16 | 18 22 122 /8 19 10\ \ 123 2-15-|----4--21--6 124 \ 9| 7 / / 125 14 | 17 20 126 \ | / / 127 3------- 128 129 should become two tetrahedrons separated by a zero-volume cell with 3 faces/3 edges/6 vertices 130 131 cell 6 ___36___10______ cell 132 0 / | \ |\ \ 1 133 24 | 26 | 32 30 134 /12 27 14\ 33 \ \ 135 3-23-|----5--35-|---9--29--7 136 \ 13| 11/ |18 / / 137 22 | 25 | 31 28 138 \ | / |/ / 139 4----34----8------ 140 cell 2 141 142 In parallel, 143 144 cell 5 ___28____8 4______ cell 145 0 / | \ |\ |\ \ 0 146 19 | 21 | 24 | 13 6 11 147 /10 22 12\ 25 \ |8 \ \ 148 2-18-|----4--27-|---7 14 3--10--1 149 \ 11| 9 / |13 / | / / 150 17 | 20 | 23 | 12 5 9 151 \ | / |/ |/ / 152 3----26----6 2------ 153 cell 1 154 155 Test 1: 156 Four tets sharing two faces 157 158 Cells: 0-3,4-5 159 Vertices: 6-15 160 Faces: 16-29,30-34 161 Edges: 35-52,53-56 162 163 Quadrilateral 164 ------------- 165 Test 0: 166 Two quads sharing a face 167 168 5--10---4--14---7 169 | | | 170 11 0 9 1 13 171 | | | 172 2---8---3--12---6 173 174 should become two quads separated by a zero-volume cell with 4 vertices 175 176 6--13---5-20-10--17---8 5--10---4-14--7 4---7---2 177 | | | | | | | | | 178 14 0 12 2 18 1 16 11 0 9 1 12 8 0 6 179 | | | | | | | | | 180 3--11---4-19--9--15---7 2---8---3-13--6 3---5---1 181 182 Test 1: 183 184 Original mesh with 9 cells, 185 186 9 ----10 ----11 ----12 187 | | | | 188 | | | | 189 | | | | 190 | | | | 191 13 ----14 ----15 ----16 192 | | | | 193 | | | | 194 | | | | 195 | | | | 196 17 ----18 ----19 ----20 197 | | | | 198 | | | | 199 | | | | 200 | | | | 201 21 ----22 ----23 ----24 202 203 After first fault, 204 205 12 ----13 ----14-28 ----15 206 | | | | | 207 | 0 | 1 | 9| 2 | 208 | | | | | 209 | | | | | 210 16 ----17 ----18-29 ----19 211 | | | | | 212 | 3 | 4 |10| 5 | 213 | | | | | 214 | | | | | 215 20 ----21-----22-30 ----23 216 | | | \--11- | 217 | 6 | 7 | 8 | 218 | | | | 219 | | | | 220 24 ----25 ----26--------27 221 222 After second fault, 223 224 14 ----15 ----16-30 ----17 225 | | | | | 226 | 0 | 1 | 9| 2 | 227 | | | | | 228 | | | | | 229 18 ----19 ----20-31 ----21 230 | | | | | 231 | 3 | 4 |10| 5 | 232 | | | | | 233 | | | | | 234 33 ----34-----24-32 ----25 235 | 12 | 13 / | \-11-- | 236 22 ----23---/ | | 237 | | 7 | 8 | 238 | 6 | | | 239 | | | | 240 | | | | 241 26 ----27 ----28--------29 242 243 Hexahedron 244 ---------- 245 Test 0: 246 Two hexes sharing a face 247 248 cell 9-----31------8-----42------13 cell 249 0 /| /| /| 1 250 32 | 15 30| 21 41| 251 / | / | / | 252 6-----29------7-----40------12 | 253 | | 18 | | 24 | | 254 | 36 | 35 | 44 255 |19 | |17 | |23 | 256 33 | 16 34 | 22 43 | 257 | 5-----27--|---4-----39--|---11 258 | / | / | / 259 | 28 14 | 26 20 | 38 260 |/ |/ |/ 261 2-----25------3-----37------10 262 263 should become two hexes separated by a zero-volume cell with 8 vertices 264 265 cell 2 266 cell 10-----41------9-----62------18----52------14 cell 267 0 /| /| /| /| 1 268 42 | 20 40| 32 56| 26 51| 269 / | / | / | / | 270 7-----39------8-----61------17--|-50------13 | 271 | | 23 | | | | 29 | | 272 | 46 | 45 | 58 | 54 273 |24 | |22 | |30 | |28 | 274 43 | 21 44 | 57 | 27 53 | 275 | 6-----37--|---5-----60--|---16----49--|---12 276 | / | / | / | / 277 | 38 19 | 36 31 | 55 25 | 48 278 |/ |/ |/ |/ 279 3-----35------4-----59------15----47------11 280 281 In parallel, 282 283 cell 2 284 cell 9-----31------8-----44------13 8----20------4 cell 285 0 /| /| /| /| /| 1 286 32 | 15 30| 22 38| 24 | 10 19| 287 / | / | / | / | / | 288 6-----29------7-----43------12 | 7----18------3 | 289 | | 18 | | | | | | 13 | | 290 | 36 | 35 | 40 | 26 | 22 291 |19 | |17 | |20 | |14 | |12 | 292 33 | 16 34 | 39 | 25 | 11 21 | 293 | 5-----27--|---4-----42--|---11 | 6----17--|---2 294 | / | / | / | / | / 295 | 28 14 | 26 21 | 37 |23 9 | 16 296 |/ |/ |/ |/ |/ 297 2-----25------3-----41------10 5----15------1 298 299 Test 1: 300 301 */ 302 303 typedef struct { 304 PetscInt debug; /* The debugging level */ 305 PetscInt dim; /* The topological mesh dimension */ 306 PetscBool cellSimplex; /* Use simplices or hexes */ 307 PetscBool testPartition; /* Use a fixed partitioning for testing */ 308 PetscInt testNum; /* The particular mesh to test */ 309 PetscInt cohesiveFields; /* The number of cohesive fields */ 310 } AppCtx; 311 312 static PetscErrorCode ProcessOptions(MPI_Comm comm, AppCtx *options) 313 { 314 PetscErrorCode ierr; 315 316 PetscFunctionBegin; 317 options->debug = 0; 318 options->dim = 2; 319 options->cellSimplex = PETSC_TRUE; 320 options->testPartition = PETSC_TRUE; 321 options->testNum = 0; 322 options->cohesiveFields = 1; 323 324 ierr = PetscOptionsBegin(comm, "", "Meshing Problem Options", "DMPLEX");CHKERRQ(ierr); 325 CHKERRQ(PetscOptionsBoundedInt("-debug", "The debugging level", "ex5.c", options->debug, &options->debug, NULL,0)); 326 CHKERRQ(PetscOptionsRangeInt("-dim", "The topological mesh dimension", "ex5.c", options->dim, &options->dim, NULL,1,3)); 327 CHKERRQ(PetscOptionsBool("-cell_simplex", "Use simplices if true, otherwise hexes", "ex5.c", options->cellSimplex, &options->cellSimplex, NULL)); 328 CHKERRQ(PetscOptionsBool("-test_partition", "Use a fixed partition for testing", "ex5.c", options->testPartition, &options->testPartition, NULL)); 329 CHKERRQ(PetscOptionsBoundedInt("-test_num", "The particular mesh to test", "ex5.c", options->testNum, &options->testNum, NULL,0)); 330 CHKERRQ(PetscOptionsBoundedInt("-cohesive_fields", "The number of cohesive fields", "ex5.c", options->cohesiveFields, &options->cohesiveFields, NULL, 0)); 331 ierr = PetscOptionsEnd();CHKERRQ(ierr); 332 PetscFunctionReturn(0); 333 } 334 335 static PetscErrorCode CreateSimplex_2D(MPI_Comm comm, PetscInt testNum, DM *dm) 336 { 337 DM idm; 338 PetscInt p; 339 PetscMPIInt rank; 340 341 PetscFunctionBegin; 342 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 343 if (rank == 0) { 344 switch (testNum) { 345 case 0: 346 { 347 PetscInt numPoints[2] = {4, 2}; 348 PetscInt coneSize[6] = {3, 3, 0, 0, 0, 0}; 349 PetscInt cones[6] = {2, 3, 4, 5, 4, 3}; 350 PetscInt coneOrientations[6] = {0, 0, 0, 0, 0, 0}; 351 PetscScalar vertexCoords[8] = {-0.5, 0.5, 0.0, 0.0, 0.0, 1.0, 0.5, 0.5}; 352 PetscInt markerPoints[8] = {2, 1, 3, 1, 4, 1, 5, 1}; 353 PetscInt faultPoints[2] = {3, 4}; 354 355 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 356 for (p = 0; p < 4; ++p) CHKERRQ(DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 357 for (p = 0; p < 2; ++p) CHKERRQ(DMSetLabelValue(*dm, "fault", faultPoints[p], 1)); 358 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 359 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 2)); 360 } 361 break; 362 case 1: 363 { 364 PetscInt numPoints[2] = {6, 4}; 365 PetscInt coneSize[10] = {3, 3, 3, 3, 0, 0, 0, 0, 0, 0}; 366 PetscInt cones[12] = {4, 6, 5, 5, 6, 7, 8, 5, 9, 8, 4, 5}; 367 PetscInt coneOrientations[12] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 368 PetscScalar vertexCoords[12] = {-1.0, 0.0, 0.0, 1.0, 0.0, -1.0, 1.0, 0.0, -2.0, 1.0, -1.0, 2.0}; 369 PetscInt markerPoints[6] = {4, 1, 6, 1, 8, 1}; 370 PetscInt faultPoints[3] = {5, 6, 8}; 371 372 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 373 for (p = 0; p < 3; ++p) CHKERRQ(DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 374 for (p = 0; p < 3; ++p) CHKERRQ(DMSetLabelValue(*dm, "fault", faultPoints[p], 1)); 375 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1));CHKERRQ(DMSetLabelValue(*dm, "material", 3, 1)); 376 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 2));CHKERRQ(DMSetLabelValue(*dm, "material", 2, 2)); 377 } 378 break; 379 default: 380 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); 381 } 382 } else { 383 PetscInt numPoints[3] = {0, 0, 0}; 384 385 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL)); 386 CHKERRQ(DMCreateLabel(*dm, "fault")); 387 } 388 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 389 CHKERRQ(DMViewFromOptions(idm, NULL, "-in_dm_view")); 390 CHKERRQ(DMDestroy(dm)); 391 *dm = idm; 392 PetscFunctionReturn(0); 393 } 394 395 static PetscErrorCode CreateSimplex_3D(MPI_Comm comm, AppCtx *user, DM dm) 396 { 397 PetscInt depth = 3, testNum = user->testNum, p; 398 PetscMPIInt rank; 399 400 PetscFunctionBegin; 401 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 402 if (rank == 0) { 403 switch (testNum) { 404 case 0: 405 { 406 PetscInt numPoints[4] = {5, 7, 9, 2}; 407 PetscInt coneSize[23] = {4, 4, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2}; 408 PetscInt cones[47] = {7, 8, 9, 10, 11, 10, 13, 12, 15, 17, 14, 16, 18, 15, 14, 19, 16, 17, 18, 19, 17, 21, 20, 18, 22, 21, 22, 19, 20, 2, 3, 2, 4, 2, 5, 3, 4, 4, 5, 5, 3, 3, 6, 4, 6, 5, 6}; 409 PetscInt coneOrientations[47] = {0, 0, 0, 0, 0, -2, 2, 2, 0, -1, -1, 0, -1, -1, 0, -1, -1, 0, 0, 0, 0, 0, -1, 0, 0, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 410 PetscScalar vertexCoords[15] = {0.0, 0.0, -0.5, 0.0, -0.5, 0.0, 1.0, 0.0, 0.0, 0.0, 0.5, 0.0, 0.0, 0.0, 0.5}; 411 PetscInt markerPoints[20] = {2, 1, 3, 1, 4, 1, 5, 1, 14, 1, 15, 1, 16, 1, 17, 1, 18, 1, 19, 1}; 412 PetscInt faultPoints[3] = {3, 4, 5}; 413 414 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 415 for (p = 0; p < 10; ++p) { 416 CHKERRQ(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 417 } 418 for (p = 0; p < 3; ++p) { 419 CHKERRQ(DMSetLabelValue(dm, "fault", faultPoints[p], 1)); 420 } 421 CHKERRQ(DMSetLabelValue(dm, "material", 0, 1)); 422 CHKERRQ(DMSetLabelValue(dm, "material", 1, 2)); 423 } 424 break; 425 case 1: 426 { 427 PetscInt numPoints[4] = {6, 13, 12, 4}; 428 PetscInt coneSize[35] = {4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2}; 429 PetscInt cones[78] = {10, 11, 12, 13, 10, 15, 16, 14, 17, 18, 14, 19, 20, 13, 19, 21, 22, 23, 24, 25, 26, 22, 24, 27, 25, 23, 26, 27, 28, 29, 23, 24, 30, 28, 22, 29, 30, 31, 32, 28, 29, 33, 31, 32, 33, 23, 26, 34, 33, 34, 27, 32, 6, 5, 5, 7, 7, 6, 6, 4, 4, 5, 7, 4, 7, 9, 9, 5, 6, 9, 9, 8, 8, 7, 5, 8, 4, 8}; 430 PetscInt coneOrientations[78] = { 0, 0, 0, 0, -2, 1, 0, 2, 0, 0, -3, 0, 0, -3, -1, 0, 0, 0, 0, 0, 0, -1, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, -1, 0, -1, -1, 0, 0, 0, 0, 0, -1, -1, -1, 0, -1, 0, -1, -1, -1, -1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 431 PetscScalar vertexCoords[18] = {-1.0, 0.0, 0.0, 0.0, -1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 1.0, 0.0, 0.0, 0.0, -1.0, 1.0, 0.0, 0.0}; 432 PetscInt markerPoints[14] = {5, 1, 6, 1, 7, 1, 10, 1, 22, 1, 23, 1, 24, 1}; 433 PetscInt faultPoints[4] = {5, 6, 7, 8}; 434 435 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 436 for (p = 0; p < 7; ++p) { 437 CHKERRQ(DMSetLabelValue(dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 438 } 439 for (p = 0; p < 4; ++p) { 440 CHKERRQ(DMSetLabelValue(dm, "fault", faultPoints[p], 1)); 441 } 442 CHKERRQ(DMSetLabelValue(dm, "material", 0, 1)); 443 CHKERRQ(DMSetLabelValue(dm, "material", 1, 2)); 444 } 445 break; 446 default: 447 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); 448 } 449 } else { 450 PetscInt numPoints[4] = {0, 0, 0, 0}; 451 452 CHKERRQ(DMPlexCreateFromDAG(dm, depth, numPoints, NULL, NULL, NULL, NULL)); 453 CHKERRQ(DMCreateLabel(dm, "fault")); 454 } 455 PetscFunctionReturn(0); 456 } 457 458 static PetscErrorCode CreateQuad_2D(MPI_Comm comm, PetscInt testNum, DM *dm) 459 { 460 DM idm; 461 PetscInt p; 462 PetscMPIInt rank; 463 464 PetscFunctionBegin; 465 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 466 if (rank == 0) { 467 switch (testNum) { 468 case 0: 469 case 2: 470 { 471 PetscInt numPoints[2] = {6, 2}; 472 PetscInt coneSize[8] = {4, 4, 0, 0, 0, 0, 0, 0}; 473 PetscInt cones[8] = {2, 3, 4, 5, 3, 6, 7, 4}; 474 PetscInt coneOrientations[8] = {0, 0, 0, 0, 0, 0, 0, 0}; 475 PetscScalar vertexCoords[12] = {-0.5, 0.0, 0.0, 0.0, 0.0, 1.0, -0.5, 1.0, 0.5, 0.0, 0.5, 1.0}; 476 PetscInt markerPoints[12] = {2, 1, 3, 1, 4, 1, 5, 1, 6, 1, 7, 1}; 477 PetscInt faultPoints[2] = {3, 4}; 478 479 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 480 for (p = 0; p < 6; ++p) CHKERRQ(DMSetLabelValue(*dm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 481 if (testNum == 0) for (p = 0; p < 2; ++p) CHKERRQ(DMSetLabelValue(*dm, "fault", faultPoints[p], 1)); 482 if (testNum == 2) for (p = 0; p < 2; ++p) CHKERRQ(DMSetLabelValue(*dm, "pfault", faultPoints[p], 1)); 483 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 484 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 2)); 485 } 486 break; 487 case 1: 488 { 489 PetscInt numPoints[2] = {16, 9}; 490 PetscInt coneSize[25] = {4, 4, 4, 4, 4, 4, 4, 4, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; 491 PetscInt cones[36] = {9, 13, 14, 10, 492 10, 14, 15, 11, 493 11, 15, 16, 12, 494 13, 17, 18, 14, 495 14, 18, 19, 15, 496 15, 19, 20, 16, 497 17, 21, 22, 18, 498 18, 22, 23, 19, 499 19, 23, 24, 20}; 500 PetscInt coneOrientations[36] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 501 PetscScalar vertexCoords[32] = {-3.0, 3.0, -1.0, 3.0, 1.0, 3.0, 3.0, 3.0, -3.0, 1.0, -1.0, 1.0, 1.0, 1.0, 3.0, 1.0, 502 -3.0, -1.0, -1.0, -1.0, 1.0, -1.0, 3.0, -1.0, -3.0, -3.0, -1.0, -3.0, 1.0, -3.0, 3.0, -3.0}; 503 PetscInt faultPoints[3] = {11, 15, 19}; 504 PetscInt fault2Points[2] = {17, 18}; 505 506 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 507 for (p = 0; p < 3; ++p) CHKERRQ(DMSetLabelValue(*dm, "fault", faultPoints[p], 1)); 508 for (p = 0; p < 2; ++p) CHKERRQ(DMSetLabelValue(*dm, "fault2", fault2Points[p], 1)); 509 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 510 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 1)); 511 CHKERRQ(DMSetLabelValue(*dm, "material", 2, 1)); 512 CHKERRQ(DMSetLabelValue(*dm, "material", 3, 1)); 513 CHKERRQ(DMSetLabelValue(*dm, "material", 4, 1)); 514 CHKERRQ(DMSetLabelValue(*dm, "material", 5, 2)); 515 CHKERRQ(DMSetLabelValue(*dm, "material", 6, 2)); 516 CHKERRQ(DMSetLabelValue(*dm, "material", 7, 2)); 517 CHKERRQ(DMSetLabelValue(*dm, "material", 8, 2)); 518 } 519 break; 520 default: 521 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); 522 } 523 } else { 524 PetscInt numPoints[3] = {0, 0, 0}; 525 526 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, NULL, NULL, NULL, NULL)); 527 if (testNum == 2) CHKERRQ(DMCreateLabel(*dm, "pfault")); 528 else CHKERRQ(DMCreateLabel(*dm, "fault")); 529 } 530 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 531 CHKERRQ(DMViewFromOptions(idm, NULL, "-in_dm_view")); 532 CHKERRQ(DMDestroy(dm)); 533 *dm = idm; 534 PetscFunctionReturn(0); 535 } 536 537 static PetscErrorCode CreateHex_3D(MPI_Comm comm, PetscInt testNum, DM *dm) 538 { 539 DM idm; 540 PetscInt depth = 3, p; 541 PetscMPIInt rank; 542 543 PetscFunctionBegin; 544 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 545 if (rank == 0) { 546 switch (testNum) { 547 case 0: 548 { 549 PetscInt numPoints[2] = {12, 2}; 550 PetscInt coneSize[14] = {8,8, 0,0,0,0,0,0,0,0,0,0,0,0}; 551 PetscInt cones[16] = {2,5,4,3,6,7,8,9, 3,4,11,10,7,12,13,8}; 552 PetscInt coneOrientations[16] = {0,0,0,0,0,0,0,0, 0,0, 0,0 ,0, 0, 0,0}; 553 PetscScalar vertexCoords[36] = {-0.5,0.0,0.0, 0.0,0.0,0.0, 0.0,1.0,0.0, -0.5,1.0,0.0, 554 -0.5,0.0,1.0, 0.0,0.0,1.0, 0.0,1.0,1.0, -0.5,1.0,1.0, 555 0.5,0.0,0.0, 0.5,1.0,0.0, 0.5,0.0,1.0, 0.5,1.0,1.0}; 556 PetscInt markerPoints[52] = {2,1,3,1,4,1,5,1,6,1,7,1,8,1,9,1}; 557 PetscInt faultPoints[4] = {3, 4, 7, 8}; 558 559 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 560 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 561 for (p = 0; p < 8; ++p) CHKERRQ(DMSetLabelValue(idm, "marker", markerPoints[p*2], markerPoints[p*2+1])); 562 for (p = 0; p < 4; ++p) CHKERRQ(DMSetLabelValue(idm, "fault", faultPoints[p], 1)); 563 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 564 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 2)); 565 } 566 break; 567 case 1: 568 { 569 /* Cell Adjacency Graph: 570 0 -- { 8, 13, 21, 24} --> 1 571 0 -- {20, 21, 23, 24} --> 5 F 572 1 -- {10, 15, 21, 24} --> 2 573 1 -- {13, 14, 15, 24} --> 6 574 2 -- {21, 22, 24, 25} --> 4 F 575 3 -- {21, 24, 30, 35} --> 4 576 3 -- {21, 24, 28, 33} --> 5 577 */ 578 PetscInt numPoints[2] = {30, 7}; 579 PetscInt coneSize[37] = {8,8,8,8,8,8,8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 580 PetscInt cones[56] = { 8, 21, 20, 7, 13, 12, 23, 24, 581 14, 15, 10, 9, 13, 8, 21, 24, 582 15, 16, 11, 10, 24, 21, 22, 25, 583 30, 29, 28, 21, 35, 24, 33, 34, 584 24, 21, 30, 35, 25, 36, 31, 22, 585 27, 20, 21, 28, 32, 33, 24, 23, 586 15, 24, 13, 14, 19, 18, 17, 26}; 587 PetscInt coneOrientations[56] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 588 PetscScalar vertexCoords[90] = {-2.0, -2.0, -2.0, -2.0, -1.0, -2.0, -3.0, 0.0, -2.0, -2.0, 1.0, -2.0, -2.0, 2.0, -2.0, -2.0, -2.0, 0.0, 589 -2.0, -1.0, 0.0, -3.0, 0.0, 0.0, -2.0, 1.0, 0.0, -2.0, 2.0, 0.0, -2.0, -1.0, 2.0, -3.0, 0.0, 2.0, 590 -2.0, 1.0, 2.0, 0.0, -2.0, -2.0, 0.0, 0.0, -2.0, 0.0, 2.0, -2.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 591 0.0, 2.0, 0.0, 0.0, 0.0, 2.0, 2.0, -2.0, -2.0, 2.0, -1.0, -2.0, 3.0, 0.0, -2.0, 2.0, 1.0, -2.0, 592 2.0, 2.0, -2.0, 2.0, -2.0, 0.0, 2.0, -1.0, 0.0, 3.0, 0.0, 0.0, 2.0, 1.0, 0.0, 2.0, 2.0, 0.0}; 593 PetscInt faultPoints[6] = {20, 21, 22, 23, 24, 25}; 594 595 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 596 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 597 for (p = 0; p < 6; ++p) CHKERRQ(DMSetLabelValue(idm, "fault", faultPoints[p], 1)); 598 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 599 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 1)); 600 CHKERRQ(DMSetLabelValue(*dm, "material", 2, 1)); 601 CHKERRQ(DMSetLabelValue(*dm, "material", 3, 2)); 602 CHKERRQ(DMSetLabelValue(*dm, "material", 4, 2)); 603 CHKERRQ(DMSetLabelValue(*dm, "material", 5, 2)); 604 CHKERRQ(DMSetLabelValue(*dm, "material", 6, 2)); 605 } 606 break; 607 case 2: 608 { 609 /* Buried fault edge */ 610 PetscInt numPoints[2] = {18, 4}; 611 PetscInt coneSize[22] = {8,8,8,8, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 612 PetscInt cones[32] = { 4, 5, 8, 7, 13, 16, 17, 14, 613 5, 6, 9, 8, 14, 17, 18, 15, 614 7, 8, 11, 10, 16, 19, 20, 17, 615 8, 9, 12, 11, 17, 20, 21, 18}; 616 PetscInt coneOrientations[32] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; 617 PetscScalar vertexCoords[54] = {-2.0, -2.0, 0.0, -2.0, 0.0, 0.0, -2.0, 2.0, 0.0, 0.0, -2.0, 0.0, 0.0, 0.0, 0.0, 0.0, 2.0, 0.0, 618 2.0, -2.0, 0.0, 2.0, 0.0, 0.0, 2.0, 2.0, 0.0, -2.0, -2.0, 2.0, -2.0, 0.0, 2.0, -2.0, 2.0, 2.0, 619 0.0, -2.0, 2.0, 0.0, 0.0, 2.0, 0.0, 2.0, 2.0, 2.0, -2.0, 2.0, 2.0, 0.0, 2.0, 2.0, 2.0, 2.0}; 620 PetscInt faultPoints[4] = {7, 8, 16, 17}; 621 622 CHKERRQ(DMPlexCreateFromDAG(*dm, 1, numPoints, coneSize, cones, coneOrientations, vertexCoords)); 623 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 624 for (p = 0; p < 4; ++p) CHKERRQ(DMSetLabelValue(idm, "fault", faultPoints[p], 1)); 625 CHKERRQ(DMSetLabelValue(*dm, "material", 0, 1)); 626 CHKERRQ(DMSetLabelValue(*dm, "material", 1, 1)); 627 CHKERRQ(DMSetLabelValue(*dm, "material", 2, 2)); 628 CHKERRQ(DMSetLabelValue(*dm, "material", 3, 2)); 629 } 630 break; 631 default: SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "No test mesh %d", testNum); 632 } 633 } else { 634 PetscInt numPoints[4] = {0, 0, 0, 0}; 635 636 CHKERRQ(DMPlexCreateFromDAG(*dm, depth, numPoints, NULL, NULL, NULL, NULL)); 637 CHKERRQ(DMPlexInterpolate(*dm, &idm)); 638 CHKERRQ(DMCreateLabel(idm, "fault")); 639 } 640 CHKERRQ(DMViewFromOptions(idm, NULL, "-in_dm_view")); 641 CHKERRQ(DMDestroy(dm)); 642 *dm = idm; 643 PetscFunctionReturn(0); 644 } 645 646 static PetscErrorCode CreateFaultLabel(DM dm) 647 { 648 DMLabel label; 649 PetscInt dim, h, pStart, pEnd, pMax, p; 650 651 PetscFunctionBegin; 652 CHKERRQ(DMGetDimension(dm, &dim)); 653 CHKERRQ(DMCreateLabel(dm, "cohesive")); 654 CHKERRQ(DMGetLabel(dm, "cohesive", &label)); 655 for (h = 0; h <= dim; ++h) { 656 CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, h, NULL, &pMax)); 657 CHKERRQ(DMPlexGetHeightStratum(dm, h, &pStart, &pEnd)); 658 for (p = pMax; p < pEnd; ++p) CHKERRQ(DMLabelSetValue(label, p, 1)); 659 } 660 PetscFunctionReturn(0); 661 } 662 663 static PetscErrorCode CreateDiscretization(DM dm, AppCtx *user) 664 { 665 PetscFE fe; 666 DMLabel fault; 667 PetscInt dim, Ncf = user->cohesiveFields, f; 668 669 PetscFunctionBegin; 670 CHKERRQ(DMGetDimension(dm, &dim)); 671 CHKERRQ(DMGetLabel(dm, "cohesive", &fault)); 672 CHKERRQ(DMLabelView(fault, PETSC_VIEWER_STDOUT_WORLD)); 673 674 CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim, dim, user->cellSimplex, "displacement_", PETSC_DETERMINE, &fe)); 675 CHKERRQ(PetscFESetName(fe, "displacement")); 676 CHKERRQ(DMAddField(dm, NULL, (PetscObject) fe)); 677 CHKERRQ(PetscFEDestroy(&fe)); 678 679 if (Ncf > 0) { 680 CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim-1, dim, user->cellSimplex, "faulttraction_", PETSC_DETERMINE, &fe)); 681 CHKERRQ(PetscFESetName(fe, "fault traction")); 682 CHKERRQ(DMAddField(dm, fault, (PetscObject) fe)); 683 CHKERRQ(PetscFEDestroy(&fe)); 684 } 685 for (f = 1; f < Ncf; ++f) { 686 char name[256], opt[256]; 687 688 CHKERRQ(PetscSNPrintf(name, 256, "fault field %D", f)); 689 CHKERRQ(PetscSNPrintf(opt, 256, "faultfield_%D_", f)); 690 CHKERRQ(PetscFECreateDefault(PETSC_COMM_SELF, dim-1, dim, user->cellSimplex, opt, PETSC_DETERMINE, &fe)); 691 CHKERRQ(PetscFESetName(fe, name)); 692 CHKERRQ(DMAddField(dm, fault, (PetscObject) fe)); 693 CHKERRQ(PetscFEDestroy(&fe)); 694 } 695 696 CHKERRQ(DMCreateDS(dm)); 697 PetscFunctionReturn(0); 698 } 699 700 static PetscErrorCode CreateMesh(MPI_Comm comm, AppCtx *user, DM *dm) 701 { 702 PetscInt dim = user->dim; 703 PetscBool cellSimplex = user->cellSimplex, hasFault, hasFault2, hasParallelFault; 704 PetscMPIInt rank, size; 705 DMLabel matLabel; 706 707 PetscFunctionBegin; 708 CHKERRMPI(MPI_Comm_rank(comm, &rank)); 709 CHKERRMPI(MPI_Comm_size(comm, &size)); 710 CHKERRQ(DMCreate(comm, dm)); 711 CHKERRQ(DMSetType(*dm, DMPLEX)); 712 CHKERRQ(DMSetDimension(*dm, dim)); 713 switch (dim) { 714 case 2: 715 if (cellSimplex) { 716 CHKERRQ(CreateSimplex_2D(comm, user->testNum, dm)); 717 } else { 718 CHKERRQ(CreateQuad_2D(comm, user->testNum, dm)); 719 } 720 break; 721 case 3: 722 if (cellSimplex) { 723 CHKERRQ(CreateSimplex_3D(comm, user, *dm)); 724 } else { 725 CHKERRQ(CreateHex_3D(comm, user->testNum, dm)); 726 } 727 break; 728 default: 729 SETERRQ(comm, PETSC_ERR_ARG_OUTOFRANGE, "Cannot make hybrid meshes for dimension %d", dim); 730 } 731 CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *dm, "orig_")); 732 CHKERRQ(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 733 CHKERRQ(DMSetFromOptions(*dm)); 734 CHKERRQ(DMGetLabel(*dm, "material", &matLabel)); 735 if (matLabel) { 736 CHKERRQ(DMPlexLabelComplete(*dm, matLabel)); 737 } 738 CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view")); 739 CHKERRQ(DMHasLabel(*dm, "fault", &hasFault)); 740 if (hasFault) { 741 DM dmHybrid = NULL, dmInterface = NULL; 742 DMLabel faultLabel, faultBdLabel, hybridLabel, splitLabel; 743 744 CHKERRQ(DMGetLabel(*dm, "fault", &faultLabel)); 745 CHKERRQ(DMGetLabel(*dm, "faultBd", &faultBdLabel)); 746 CHKERRQ(DMPlexCreateHybridMesh(*dm, faultLabel, faultBdLabel, &hybridLabel, &splitLabel, &dmInterface, &dmHybrid)); 747 CHKERRQ(DMLabelView(hybridLabel, PETSC_VIEWER_STDOUT_WORLD)); 748 CHKERRQ(DMLabelDestroy(&hybridLabel)); 749 CHKERRQ(DMLabelView(splitLabel, PETSC_VIEWER_STDOUT_WORLD)); 750 CHKERRQ(DMLabelDestroy(&splitLabel)); 751 CHKERRQ(DMViewFromOptions(dmInterface, NULL, "-dm_interface_view")); 752 CHKERRQ(DMDestroy(&dmInterface)); 753 CHKERRQ(DMDestroy(dm)); 754 *dm = dmHybrid; 755 } 756 CHKERRQ(DMHasLabel(*dm, "fault2", &hasFault2)); 757 if (hasFault2) { 758 DM dmHybrid = NULL; 759 DMLabel faultLabel, faultBdLabel, hybridLabel; 760 761 CHKERRQ(PetscObjectSetOptionsPrefix((PetscObject) *dm, "faulted_")); 762 CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view_pre")); 763 CHKERRQ(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 764 CHKERRQ(DMSetFromOptions(*dm)); 765 CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view")); 766 CHKERRQ(DMGetLabel(*dm, "fault2", &faultLabel)); 767 CHKERRQ(DMGetLabel(*dm, "fault2Bd", &faultBdLabel)); 768 CHKERRQ(DMPlexCreateHybridMesh(*dm, faultLabel, faultBdLabel, &hybridLabel, NULL, NULL, &dmHybrid)); 769 CHKERRQ(DMLabelView(hybridLabel, PETSC_VIEWER_STDOUT_WORLD)); 770 CHKERRQ(DMLabelDestroy(&hybridLabel)); 771 CHKERRQ(DMDestroy(dm)); 772 *dm = dmHybrid; 773 } 774 if (user->testPartition && size > 1) { 775 PetscPartitioner part; 776 PetscInt *sizes = NULL; 777 PetscInt *points = NULL; 778 779 if (rank == 0) { 780 if (dim == 2 && cellSimplex && size == 2) { 781 switch (user->testNum) { 782 case 0: { 783 PetscInt triSizes_p2[2] = {1, 2}; 784 PetscInt triPoints_p2[3] = {0, 1, 2}; 785 786 CHKERRQ(PetscMalloc2(2, &sizes, 3, &points)); 787 CHKERRQ(PetscArraycpy(sizes, triSizes_p2, 2)); 788 CHKERRQ(PetscArraycpy(points, triPoints_p2, 3));break;} 789 default: 790 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); 791 } 792 } else if (dim == 2 && !cellSimplex && size == 2) { 793 switch (user->testNum) { 794 case 0: { 795 PetscInt quadSizes_p2[2] = {1, 2}; 796 PetscInt quadPoints_p2[3] = {0, 1, 2}; 797 798 CHKERRQ(PetscMalloc2(2, &sizes, 3, &points)); 799 CHKERRQ(PetscArraycpy(sizes, quadSizes_p2, 2)); 800 CHKERRQ(PetscArraycpy(points, quadPoints_p2, 3));break;} 801 case 2: { 802 PetscInt quadSizes_p2[2] = {1, 1}; 803 PetscInt quadPoints_p2[2] = {0, 1}; 804 805 CHKERRQ(PetscMalloc2(2, &sizes, 2, &points)); 806 CHKERRQ(PetscArraycpy(sizes, quadSizes_p2, 2)); 807 CHKERRQ(PetscArraycpy(points, quadPoints_p2, 2));break;} 808 default: 809 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for quadrilateral mesh on 2 procs", user->testNum); 810 } 811 } else if (dim == 3 && cellSimplex && size == 2) { 812 switch (user->testNum) { 813 case 0: { 814 PetscInt tetSizes_p2[2] = {1, 2}; 815 PetscInt tetPoints_p2[3] = {0, 1, 2}; 816 817 CHKERRQ(PetscMalloc2(2, &sizes, 3, &points)); 818 CHKERRQ(PetscArraycpy(sizes, tetSizes_p2, 2)); 819 CHKERRQ(PetscArraycpy(points, tetPoints_p2, 3));break;} 820 default: 821 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); 822 } 823 } else if (dim == 3 && !cellSimplex && size == 2) { 824 switch (user->testNum) { 825 case 0: { 826 PetscInt hexSizes_p2[2] = {1, 2}; 827 PetscInt hexPoints_p2[3] = {0, 1, 2}; 828 829 CHKERRQ(PetscMalloc2(2, &sizes, 3, &points)); 830 CHKERRQ(PetscArraycpy(sizes, hexSizes_p2, 2)); 831 CHKERRQ(PetscArraycpy(points, hexPoints_p2, 3));break;} 832 default: 833 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test number %d for triangular mesh on 2 procs", user->testNum); 834 } 835 } else SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG, "Could not find matching test partition"); 836 } 837 CHKERRQ(DMPlexGetPartitioner(*dm, &part)); 838 CHKERRQ(PetscPartitionerSetType(part, PETSCPARTITIONERSHELL)); 839 CHKERRQ(PetscPartitionerShellSetPartition(part, size, sizes, points)); 840 CHKERRQ(PetscFree2(sizes, points)); 841 } 842 { 843 DM pdm = NULL; 844 845 /* Distribute mesh over processes */ 846 CHKERRQ(DMPlexDistribute(*dm, 0, NULL, &pdm)); 847 if (pdm) { 848 CHKERRQ(DMViewFromOptions(pdm, NULL, "-dm_view")); 849 CHKERRQ(DMDestroy(dm)); 850 *dm = pdm; 851 } 852 } 853 CHKERRQ(DMHasLabel(*dm, "pfault", &hasParallelFault)); 854 if (hasParallelFault) { 855 DM dmHybrid = NULL; 856 DMLabel faultLabel, faultBdLabel, hybridLabel; 857 858 CHKERRQ(DMGetLabel(*dm, "pfault", &faultLabel)); 859 CHKERRQ(DMGetLabel(*dm, "pfaultBd", &faultBdLabel)); 860 CHKERRQ(DMPlexCreateHybridMesh(*dm, faultLabel, faultBdLabel, &hybridLabel, NULL, NULL, &dmHybrid)); 861 CHKERRQ(DMLabelView(hybridLabel, PETSC_VIEWER_STDOUT_WORLD)); 862 CHKERRQ(DMLabelDestroy(&hybridLabel)); 863 CHKERRQ(DMDestroy(dm)); 864 *dm = dmHybrid; 865 } 866 CHKERRQ(PetscObjectSetName((PetscObject) *dm, "Hybrid Mesh")); 867 CHKERRQ(CreateFaultLabel(*dm)); 868 CHKERRQ(CreateDiscretization(*dm, user)); 869 CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view_pre")); 870 CHKERRQ(DMPlexDistributeSetDefault(*dm, PETSC_FALSE)); 871 CHKERRQ(DMSetFromOptions(*dm)); 872 CHKERRQ(DMViewFromOptions(*dm, NULL, "-dm_view")); 873 PetscFunctionReturn(0); 874 } 875 876 static PetscErrorCode TestMesh(DM dm, AppCtx *user) 877 { 878 PetscFunctionBegin; 879 CHKERRQ(DMPlexCheckSymmetry(dm)); 880 CHKERRQ(DMPlexCheckSkeleton(dm, 0)); 881 CHKERRQ(DMPlexCheckFaces(dm, 0)); 882 PetscFunctionReturn(0); 883 } 884 885 static PetscErrorCode TestDiscretization(DM dm, AppCtx *user) 886 { 887 PetscSection s; 888 889 PetscFunctionBegin; 890 CHKERRQ(DMGetSection(dm, &s)); 891 CHKERRQ(PetscObjectViewFromOptions((PetscObject) s, NULL, "-local_section_view")); 892 PetscFunctionReturn(0); 893 } 894 895 static PetscErrorCode r(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 896 { 897 PetscInt d; 898 for (d = 0; d < dim; ++d) u[d] = x[d]; 899 return 0; 900 } 901 902 static PetscErrorCode rp1(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 903 { 904 PetscInt d; 905 for (d = 0; d < dim; ++d) u[d] = x[d] + (d > 0 ? 1.0 : 0.0); 906 return 0; 907 } 908 909 static PetscErrorCode phi(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar *u, void *ctx) 910 { 911 PetscInt d; 912 u[0] = -x[1]; 913 u[1] = x[0]; 914 for (d = 2; d < dim; ++d) u[d] = x[d]; 915 return 0; 916 } 917 918 /* \lambda \cdot (\psi_u^- - \psi_u^+) */ 919 static void f0_bd_u(PetscInt dim, PetscInt Nf, PetscInt NfAux, 920 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 921 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 922 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 923 { 924 const PetscInt Nc = uOff[1]-uOff[0]; 925 PetscInt c; 926 for (c = 0; c < Nc; ++c) { 927 f0[c] = u[Nc*2+c] + x[Nc-c-1]; 928 f0[Nc+c] = -(u[Nc*2+c] + x[Nc-c-1]); 929 } 930 } 931 932 /* (d - u^+ + u^-) \cdot \psi_\lambda */ 933 static void f0_bd_l(PetscInt dim, PetscInt Nf, PetscInt NfAux, 934 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 935 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 936 PetscReal t, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar f0[]) 937 { 938 const PetscInt Nc = uOff[2]-uOff[1]; 939 PetscInt c; 940 941 for (c = 0; c < Nc; ++c) f0[c] = (c > 0 ? 1.0 : 0.0) + u[c] - u[Nc+c]; 942 } 943 944 /* \psi_lambda \cdot (\psi_u^- - \psi_u^+) */ 945 static void g0_bd_ul(PetscInt dim, PetscInt Nf, PetscInt NfAux, 946 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 947 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 948 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 949 { 950 const PetscInt Nc = uOff[1]-uOff[0]; 951 PetscInt c; 952 953 for (c = 0; c < Nc; ++c) { 954 g0[(0 +c)*Nc+c] = 1.0; 955 g0[(Nc+c)*Nc+c] = -1.0; 956 } 957 } 958 959 /* (-\psi_u^+ + \psi_u^-) \cdot \psi_\lambda */ 960 static void g0_bd_lu(PetscInt dim, PetscInt Nf, PetscInt NfAux, 961 const PetscInt uOff[], const PetscInt uOff_x[], const PetscScalar u[], const PetscScalar u_t[], const PetscScalar u_x[], 962 const PetscInt aOff[], const PetscInt aOff_x[], const PetscScalar a[], const PetscScalar a_t[], const PetscScalar a_x[], 963 PetscReal t, PetscReal u_tShift, const PetscReal x[], const PetscReal n[], PetscInt numConstants, const PetscScalar constants[], PetscScalar g0[]) 964 { 965 const PetscInt Nc = uOff[2]-uOff[1]; 966 PetscInt c; 967 968 for (c = 0; c < Nc; ++c) { 969 g0[c*Nc*2+c] = 1.0; 970 g0[c*Nc*2+Nc+c] = -1.0; 971 } 972 } 973 974 static PetscErrorCode TestAssembly(DM dm, AppCtx *user) 975 { 976 Mat J; 977 Vec locX, locF; 978 PetscDS probh; 979 DMLabel fault, material; 980 IS cohesiveCells; 981 PetscWeakForm wf; 982 PetscFormKey keys[3]; 983 PetscErrorCode (*initialGuess[2])(PetscInt dim, PetscReal time, const PetscReal x[], PetscInt Nc, PetscScalar u[], void *ctx); 984 PetscInt dim, Nf, cMax, cEnd, id; 985 PetscMPIInt rank; 986 987 PetscFunctionBegin; 988 CHKERRMPI(MPI_Comm_rank(PetscObjectComm((PetscObject) dm), &rank)); 989 CHKERRQ(DMGetDimension(dm, &dim)); 990 CHKERRQ(DMPlexGetSimplexOrBoxCells(dm, 0, NULL, &cMax)); 991 CHKERRQ(DMPlexGetHeightStratum(dm, 0, NULL, &cEnd)); 992 CHKERRQ(ISCreateStride(PETSC_COMM_SELF, cEnd - cMax, cMax, 1, &cohesiveCells)); 993 CHKERRQ(DMGetLabel(dm, "cohesive", &fault)); 994 CHKERRQ(DMGetLocalVector(dm, &locX)); 995 CHKERRQ(PetscObjectSetName((PetscObject) locX, "Local Solution")); 996 CHKERRQ(DMGetLocalVector(dm, &locF)); 997 CHKERRQ(PetscObjectSetName((PetscObject) locF, "Local Residual")); 998 CHKERRQ(DMCreateMatrix(dm, &J)); 999 CHKERRQ(PetscObjectSetName((PetscObject) J, "Jacobian")); 1000 1001 /* The initial guess has displacement shifted by one unit in each fault parallel direction across the fault */ 1002 CHKERRQ(DMGetLabel(dm, "material", &material)); 1003 id = 1; 1004 initialGuess[0] = r; 1005 initialGuess[1] = NULL; 1006 CHKERRQ(DMProjectFunctionLabelLocal(dm, 0.0, material, 1, &id, PETSC_DETERMINE, NULL, initialGuess, NULL, INSERT_VALUES, locX)); 1007 id = 2; 1008 initialGuess[0] = rp1; 1009 initialGuess[1] = NULL; 1010 CHKERRQ(DMProjectFunctionLabelLocal(dm, 0.0, material, 1, &id, PETSC_DETERMINE, NULL, initialGuess, NULL, INSERT_VALUES, locX)); 1011 id = 1; 1012 initialGuess[0] = NULL; 1013 initialGuess[1] = phi; 1014 CHKERRQ(DMProjectFunctionLabelLocal(dm, 0.0, fault, 1, &id, PETSC_DETERMINE, NULL, initialGuess, NULL, INSERT_VALUES, locX)); 1015 CHKERRQ(VecViewFromOptions(locX, NULL, "-local_solution_view")); 1016 1017 CHKERRQ(DMGetCellDS(dm, cMax, &probh)); 1018 CHKERRQ(PetscDSGetWeakForm(probh, &wf)); 1019 CHKERRQ(PetscDSGetNumFields(probh, &Nf)); 1020 CHKERRQ(PetscWeakFormSetIndexBdResidual(wf, material, 1, 0, 0, 0, f0_bd_u, 0, NULL)); 1021 CHKERRQ(PetscWeakFormSetIndexBdResidual(wf, material, 2, 0, 0, 0, f0_bd_u, 0, NULL)); 1022 CHKERRQ(PetscWeakFormSetIndexBdJacobian(wf, material, 1, 0, 1, 0, 0, g0_bd_ul, 0, NULL, 0, NULL, 0, NULL)); 1023 CHKERRQ(PetscWeakFormSetIndexBdJacobian(wf, material, 2, 0, 1, 0, 0, g0_bd_ul, 0, NULL, 0, NULL, 0, NULL)); 1024 if (Nf > 1) { 1025 CHKERRQ(PetscWeakFormSetIndexBdResidual(wf, fault, 1, 1, 0, 0, f0_bd_l, 0, NULL)); 1026 CHKERRQ(PetscWeakFormSetIndexBdJacobian(wf, fault, 1, 1, 0, 0, 0, g0_bd_lu, 0, NULL, 0, NULL, 0, NULL)); 1027 } 1028 if (!rank) CHKERRQ(PetscDSView(probh, NULL)); 1029 1030 keys[0].label = NULL; 1031 keys[0].value = 0; 1032 keys[0].field = 0; 1033 keys[0].part = 0; 1034 keys[1].label = material; 1035 keys[1].value = 2; 1036 keys[1].field = 0; 1037 keys[1].part = 0; 1038 keys[2].label = fault; 1039 keys[2].value = 1; 1040 keys[2].field = 1; 1041 keys[2].part = 0; 1042 CHKERRQ(VecSet(locF, 0.)); 1043 CHKERRQ(DMPlexComputeResidual_Hybrid_Internal(dm, keys, cohesiveCells, 0.0, locX, NULL, 0.0, locF, user)); 1044 CHKERRQ(VecViewFromOptions(locF, NULL, "-local_residual_view")); 1045 CHKERRQ(MatZeroEntries(J)); 1046 CHKERRQ(DMPlexComputeJacobian_Hybrid_Internal(dm, keys, cohesiveCells, 0.0, 0.0, locX, NULL, J, J, user)); 1047 CHKERRQ(MatViewFromOptions(J, NULL, "-local_jacobian_view")); 1048 1049 CHKERRQ(DMRestoreLocalVector(dm, &locX)); 1050 CHKERRQ(DMRestoreLocalVector(dm, &locF)); 1051 CHKERRQ(MatDestroy(&J)); 1052 CHKERRQ(ISDestroy(&cohesiveCells)); 1053 PetscFunctionReturn(0); 1054 } 1055 1056 int main(int argc, char **argv) 1057 { 1058 DM dm; 1059 AppCtx user; /* user-defined work context */ 1060 PetscErrorCode ierr; 1061 1062 ierr = PetscInitialize(&argc, &argv, NULL,help);if (ierr) return ierr; 1063 CHKERRQ(ProcessOptions(PETSC_COMM_WORLD, &user)); 1064 CHKERRQ(CreateMesh(PETSC_COMM_WORLD, &user, &dm)); 1065 CHKERRQ(TestMesh(dm, &user)); 1066 CHKERRQ(TestDiscretization(dm, &user)); 1067 CHKERRQ(TestAssembly(dm, &user)); 1068 CHKERRQ(DMDestroy(&dm)); 1069 ierr = PetscFinalize(); 1070 return ierr; 1071 } 1072 1073 /*TEST 1074 testset: 1075 args: -orig_dm_plex_check_all -dm_plex_check_all \ 1076 -displacement_petscspace_degree 1 -faulttraction_petscspace_degree 1 -local_section_view \ 1077 -local_solution_view -local_residual_view -local_jacobian_view 1078 test: 1079 suffix: tri_0 1080 args: -dim 2 1081 test: 1082 suffix: tri_t1_0 1083 args: -dim 2 -test_num 1 1084 test: 1085 suffix: tet_0 1086 args: -dim 3 1087 test: 1088 suffix: tet_t1_0 1089 args: -dim 3 -test_num 1 1090 1091 testset: 1092 args: -orig_dm_plex_check_all -dm_plex_check_all \ 1093 -displacement_petscspace_degree 1 -faulttraction_petscspace_degree 1 1094 test: 1095 suffix: tet_1 1096 nsize: 2 1097 args: -dim 3 1098 test: 1099 suffix: tri_1 1100 nsize: 2 1101 args: -dim 2 1102 1103 testset: 1104 args: -orig_dm_plex_check_all -dm_plex_check_all \ 1105 -displacement_petscspace_degree 1 -faulttraction_petscspace_degree 1 1106 # 2D Quads 1107 test: 1108 suffix: quad_0 1109 args: -dim 2 -cell_simplex 0 1110 test: 1111 suffix: quad_1 1112 nsize: 2 1113 args: -dim 2 -cell_simplex 0 1114 test: 1115 suffix: quad_t1_0 1116 args: -dim 2 -cell_simplex 0 -test_num 1 -faulted_dm_plex_check_all 1117 # 3D Hex 1118 test: 1119 suffix: hex_0 1120 args: -dim 3 -cell_simplex 0 1121 test: 1122 suffix: hex_1 1123 nsize: 2 1124 args: -dim 3 -cell_simplex 0 1125 test: 1126 suffix: hex_t1_0 1127 args: -dim 3 -cell_simplex 0 -test_num 1 1128 test: 1129 suffix: hex_t2_0 1130 args: -dim 3 -cell_simplex 0 -test_num 2 1131 1132 TEST*/ 1133