1 static char help[] = "Tests for submesh creation\n\n"; 2 3 #include <petscdmplex.h> 4 #include <petscsf.h> 5 6 /* Submesh of a 2 x 2 mesh using 3 processes. 7 8 Local numbering on each rank: 9 10 (6)(16)-(7)(17)-(8) 5--14---6--15---7 (10)(20)(11)(21)(12) 11 | | | | | | | | | 12 (18) (1)(19) (2)(20) 16 0 17 1 18 (22) (2)(23) (3)(24) 13 | | | | | | | | | 14 (5)(15)(11)(22)(12) 4--13-(11)(22)(12) (9)(19)--6--14---7 15 | | | | | | | | | 16 14 0 (23) (3)(24) (20) (2)(23) (3)(24) (18) (1) 15 0 16 17 | | | | | | | | | 18 4--13--(9)(21)(10) (8)(19)-(9)(21)(10) (8)(17)--4--13---5 19 20 mesh_0 mesh_1 mesh_2 21 22 where () represents ghost points. We extract the left 2 cells. 23 With sanitize_submesh = PETSC_FALSE, we get: 24 25 (4)(11)-(5) 3---9---4 26 | | | | 27 (12) (1)(13) 10 0 11 28 | | | | 29 (3)(10) (7) 2---8---7 30 | | | | 31 9 0 (14) (13) (1) 14 32 | | | | 33 2---8--(6) (5)(12)--6 34 35 On the other hand, with sanitize_submesh = PETSC_TRUE, we get: 36 37 (4)(11)-(5) 3---9---4 38 | | | | 39 (12) (1)(13) 10 0 11 40 | | | | 41 (3)(10) (7) 2---8---7 42 | | | | 43 9 0 14 (13) (1)(14) 44 | | | | 45 2---8---6 (5)(12)-(6) 46 47 submesh_0 submesh_1 submesh_2 48 49 as points 15 and 4 of mesh_2 are in the closure of a submesh cell owned by rank 0 (point 0 of submesh_0), 50 and not in the closure of any submesh cell owned by rank 1. 51 52 */ 53 54 typedef struct { 55 PetscBool ignoreLabelHalo; /* Ignore filter values in the halo. */ 56 PetscBool sanitizeSubmesh; /* Sanitize submesh. */ 57 } AppCtx; 58 59 PetscErrorCode ProcessOptions(AppCtx *options) 60 { 61 PetscFunctionBegin; 62 options->ignoreLabelHalo = PETSC_FALSE; 63 options->sanitizeSubmesh = PETSC_FALSE; 64 65 PetscOptionsBegin(PETSC_COMM_SELF, "", "Filtering Problem Options", "DMPLEX"); 66 PetscCall(PetscOptionsBool("-ignore_label_halo", "Ignore filter values in the halo", "ex80.c", options->ignoreLabelHalo, &options->ignoreLabelHalo, NULL)); 67 PetscCall(PetscOptionsBool("-sanitize_submesh", "Sanitize submesh", "ex80.c", options->sanitizeSubmesh, &options->sanitizeSubmesh, NULL)); 68 PetscOptionsEnd(); 69 PetscFunctionReturn(PETSC_SUCCESS); 70 } 71 int main(int argc, char **argv) 72 { 73 DM dm, subdm; 74 PetscSF ownershipTransferSF; 75 DMLabel filter; 76 const PetscInt filterValue = 1; 77 MPI_Comm comm; 78 PetscMPIInt size, rank; 79 AppCtx user; 80 81 PetscFunctionBeginUser; 82 PetscCall(PetscInitialize(&argc, &argv, NULL, help)); 83 PetscCall(ProcessOptions(&user)); 84 comm = PETSC_COMM_WORLD; 85 PetscCallMPI(MPI_Comm_size(comm, &size)); 86 if (size != 3) { 87 PetscCall(PetscPrintf(comm, "This example is specifically designed for comm size == 3.\n")); 88 PetscCall(PetscFinalize()); 89 return 0; 90 } 91 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 92 { 93 DM pdm; 94 const PetscInt faces[2] = {2, 2}; 95 PetscInt overlap = 1; 96 97 PetscCall(DMPlexCreateBoxMesh(comm, 2, PETSC_FALSE, faces, NULL, NULL, NULL, PETSC_TRUE, 0, PETSC_TRUE, &dm)); 98 { 99 PetscPartitioner part; 100 PetscInt *sizes = NULL; 101 PetscInt *points = NULL; 102 103 if (rank == 0) { 104 PetscInt sizes1[3] = {1, 2, 1}; 105 PetscInt points1[4] = {0, 2, 3, 1}; 106 107 PetscCall(PetscMalloc2(3, &sizes, 4, &points)); 108 PetscCall(PetscArraycpy(sizes, sizes1, 3)); 109 PetscCall(PetscArraycpy(points, points1, 4)); 110 } 111 PetscCall(DMPlexGetPartitioner(dm, &part)); 112 PetscCall(PetscPartitionerSetType(part, PETSCPARTITIONERSHELL)); 113 PetscCall(PetscPartitionerShellSetPartition(part, size, sizes, points)); 114 PetscCall(PetscFree2(sizes, points)); 115 } 116 PetscCall(DMSetAdjacency(dm, -1, PETSC_FALSE, PETSC_TRUE)); 117 PetscCall(DMPlexDistribute(dm, overlap, NULL, &pdm)); 118 if (pdm) { 119 PetscCall(DMDestroy(&dm)); 120 dm = pdm; 121 } 122 } 123 PetscCall(DMLabelCreate(PETSC_COMM_SELF, "filter", &filter)); 124 switch (rank) { 125 case 0: 126 PetscCall(DMLabelSetValue(filter, 0, filterValue)); 127 PetscCall(DMLabelSetValue(filter, 1, filterValue)); 128 break; 129 case 1: 130 PetscCall(DMLabelSetValue(filter, 0, filterValue)); 131 PetscCall(DMLabelSetValue(filter, 2, filterValue)); 132 break; 133 case 2: 134 break; 135 } 136 PetscCall(PetscObjectSetName((PetscObject)dm, "Example_DM")); 137 PetscCall(DMViewFromOptions(dm, NULL, "-dm_view")); 138 PetscCall(DMPlexFilter(dm, filter, filterValue, user.ignoreLabelHalo, user.sanitizeSubmesh, PetscObjectComm((PetscObject)dm), &ownershipTransferSF, &subdm)); 139 PetscCall(DMLabelDestroy(&filter)); 140 PetscCall(DMDestroy(&dm)); 141 PetscCall(PetscObjectSetName((PetscObject)subdm, "Example_SubDM")); 142 PetscCall(DMViewFromOptions(subdm, NULL, "-dm_view")); 143 PetscCall(DMDestroy(&subdm)); 144 PetscCall(PetscObjectSetName((PetscObject)ownershipTransferSF, "Example_Ownership_Transfer_SF")); 145 PetscCall(PetscSFView(ownershipTransferSF, PETSC_VIEWER_STDOUT_WORLD)); 146 PetscCall(PetscSFDestroy(&ownershipTransferSF)); 147 PetscCall(PetscFinalize()); 148 return 0; 149 } 150 151 /*TEST 152 153 testset: 154 nsize: 3 155 args: -dm_view ascii::ascii_info_detail 156 157 test: 158 suffix: 0 159 args: 160 161 test: 162 suffix: 1 163 args: -sanitize_submesh 164 165 test: 166 suffix: 2 167 args: -ignore_label_halo 168 169 TEST*/ 170