1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/petscfeimpl.h> /* For PetscFEInterpolate_Static() */ 3 4 #include <petscdmplextransform.h> 5 #include <petscsf.h> 6 7 /*@ 8 DMPlexCreateProcessSF - Create an `PetscSF` which just has process connectivity 9 10 Collective 11 12 Input Parameters: 13 + dm - The `DM` 14 - sfPoint - The `PetscSF` which encodes point connectivity 15 16 Output Parameters: 17 + processRanks - A list of process neighbors, or `NULL` 18 - sfProcess - An `PetscSF` encoding the process connectivity, or `NULL` 19 20 Level: developer 21 22 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `PetscSF`, `PetscSFCreate()`, `DMPlexCreateTwoSidedProcessSF()` 23 @*/ 24 PetscErrorCode DMPlexCreateProcessSF(DM dm, PetscSF sfPoint, IS *processRanks, PetscSF *sfProcess) 25 { 26 PetscInt numRoots, numLeaves, l; 27 const PetscInt *localPoints; 28 const PetscSFNode *remotePoints; 29 PetscInt *localPointsNew; 30 PetscSFNode *remotePointsNew; 31 PetscInt *ranks, *ranksNew; 32 PetscMPIInt size; 33 34 PetscFunctionBegin; 35 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 36 PetscValidHeaderSpecific(sfPoint, PETSCSF_CLASSID, 2); 37 if (processRanks) PetscAssertPointer(processRanks, 3); 38 if (sfProcess) PetscAssertPointer(sfProcess, 4); 39 PetscCallMPI(MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size)); 40 PetscCall(PetscSFGetGraph(sfPoint, &numRoots, &numLeaves, &localPoints, &remotePoints)); 41 PetscCall(PetscMalloc1(numLeaves, &ranks)); 42 for (l = 0; l < numLeaves; ++l) ranks[l] = remotePoints[l].rank; 43 PetscCall(PetscSortRemoveDupsInt(&numLeaves, ranks)); 44 PetscCall(PetscMalloc1(numLeaves, &ranksNew)); 45 PetscCall(PetscMalloc1(numLeaves, &localPointsNew)); 46 PetscCall(PetscMalloc1(numLeaves, &remotePointsNew)); 47 for (l = 0; l < numLeaves; ++l) { 48 ranksNew[l] = ranks[l]; 49 localPointsNew[l] = l; 50 remotePointsNew[l].index = 0; 51 remotePointsNew[l].rank = ranksNew[l]; 52 } 53 PetscCall(PetscFree(ranks)); 54 if (processRanks) PetscCall(ISCreateGeneral(PetscObjectComm((PetscObject)dm), numLeaves, ranksNew, PETSC_OWN_POINTER, processRanks)); 55 else PetscCall(PetscFree(ranksNew)); 56 if (sfProcess) { 57 PetscCall(PetscSFCreate(PetscObjectComm((PetscObject)dm), sfProcess)); 58 PetscCall(PetscObjectSetName((PetscObject)*sfProcess, "Process SF")); 59 PetscCall(PetscSFSetFromOptions(*sfProcess)); 60 PetscCall(PetscSFSetGraph(*sfProcess, size, numLeaves, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 61 } 62 PetscFunctionReturn(PETSC_SUCCESS); 63 } 64 65 /*@ 66 DMPlexCreateCoarsePointIS - Creates an `IS` covering the coarse `DM` chart with the fine points as data 67 68 Collective 69 70 Input Parameter: 71 . dm - The coarse `DM` 72 73 Output Parameter: 74 . fpointIS - The `IS` of all the fine points which exist in the original coarse mesh 75 76 Level: developer 77 78 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `IS`, `DMRefine()`, `DMPlexSetRefinementUniform()`, `DMPlexGetSubpointIS()` 79 @*/ 80 PetscErrorCode DMPlexCreateCoarsePointIS(DM dm, IS *fpointIS) 81 { 82 DMPlexTransform tr; 83 PetscInt *fpoints; 84 PetscInt pStart, pEnd, p, vStart, vEnd, v; 85 86 PetscFunctionBegin; 87 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 88 PetscCall(DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd)); 89 PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 90 PetscCall(DMPlexTransformSetUp(tr)); 91 PetscCall(PetscMalloc1(pEnd - pStart, &fpoints)); 92 for (p = 0; p < pEnd - pStart; ++p) fpoints[p] = -1; 93 for (v = vStart; v < vEnd; ++v) { 94 PetscInt vNew = -1; /* quiet overzealous may be used uninitialized check */ 95 96 PetscCall(DMPlexTransformGetTargetPoint(tr, DM_POLYTOPE_POINT, DM_POLYTOPE_POINT, p, 0, &vNew)); 97 fpoints[v - pStart] = vNew; 98 } 99 PetscCall(DMPlexTransformDestroy(&tr)); 100 PetscCall(ISCreateGeneral(PETSC_COMM_SELF, pEnd - pStart, fpoints, PETSC_OWN_POINTER, fpointIS)); 101 PetscFunctionReturn(PETSC_SUCCESS); 102 } 103 104 /*@C 105 DMPlexSetTransformType - Set the transform type for uniform refinement 106 107 Input Parameters: 108 + dm - The `DM` 109 - type - The transform type for uniform refinement 110 111 Level: developer 112 113 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTransformType`, `DMRefine()`, `DMPlexGetTransformType()`, `DMPlexSetRefinementUniform()` 114 @*/ 115 PetscErrorCode DMPlexSetTransformType(DM dm, DMPlexTransformType type) 116 { 117 DM_Plex *mesh = (DM_Plex *)dm->data; 118 119 PetscFunctionBegin; 120 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 121 if (type) PetscAssertPointer(type, 2); 122 PetscCall(PetscFree(mesh->transformType)); 123 PetscCall(PetscStrallocpy(type, &mesh->transformType)); 124 PetscFunctionReturn(PETSC_SUCCESS); 125 } 126 127 /*@C 128 DMPlexGetTransformType - Retrieve the transform type for uniform refinement 129 130 Input Parameter: 131 . dm - The `DM` 132 133 Output Parameter: 134 . type - The transform type for uniform refinement 135 136 Level: developer 137 138 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMPlexTransformType`, `DMRefine()`, `DMPlexSetTransformType()`, `DMPlexGetRefinementUniform()` 139 @*/ 140 PetscErrorCode DMPlexGetTransformType(DM dm, DMPlexTransformType *type) 141 { 142 DM_Plex *mesh = (DM_Plex *)dm->data; 143 144 PetscFunctionBegin; 145 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 146 PetscAssertPointer(type, 2); 147 *type = mesh->transformType; 148 PetscFunctionReturn(PETSC_SUCCESS); 149 } 150 151 /*@ 152 DMPlexSetRefinementUniform - Set the flag for uniform refinement 153 154 Input Parameters: 155 + dm - The `DM` 156 - refinementUniform - The flag for uniform refinement 157 158 Level: developer 159 160 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexGetRefinementUniform()`, `DMPlexGetRefinementLimit()`, `DMPlexSetRefinementLimit()` 161 @*/ 162 PetscErrorCode DMPlexSetRefinementUniform(DM dm, PetscBool refinementUniform) 163 { 164 DM_Plex *mesh = (DM_Plex *)dm->data; 165 166 PetscFunctionBegin; 167 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 168 mesh->refinementUniform = refinementUniform; 169 PetscFunctionReturn(PETSC_SUCCESS); 170 } 171 172 /*@ 173 DMPlexGetRefinementUniform - Retrieve the flag for uniform refinement 174 175 Input Parameter: 176 . dm - The `DM` 177 178 Output Parameter: 179 . refinementUniform - The flag for uniform refinement 180 181 Level: developer 182 183 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexSetRefinementUniform()`, `DMPlexGetRefinementLimit()`, `DMPlexSetRefinementLimit()` 184 @*/ 185 PetscErrorCode DMPlexGetRefinementUniform(DM dm, PetscBool *refinementUniform) 186 { 187 DM_Plex *mesh = (DM_Plex *)dm->data; 188 189 PetscFunctionBegin; 190 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMPLEX); 191 PetscAssertPointer(refinementUniform, 2); 192 *refinementUniform = mesh->refinementUniform; 193 PetscFunctionReturn(PETSC_SUCCESS); 194 } 195 196 /*@ 197 DMPlexSetRefinementLimit - Set the maximum cell volume for refinement 198 199 Input Parameters: 200 + dm - The `DM` 201 - refinementLimit - The maximum cell volume in the refined mesh 202 203 Level: developer 204 205 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexGetRefinementLimit()`, `DMPlexGetRefinementUniform()`, `DMPlexSetRefinementUniform()` 206 @*/ 207 PetscErrorCode DMPlexSetRefinementLimit(DM dm, PetscReal refinementLimit) 208 { 209 DM_Plex *mesh = (DM_Plex *)dm->data; 210 211 PetscFunctionBegin; 212 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 213 mesh->refinementLimit = refinementLimit; 214 PetscFunctionReturn(PETSC_SUCCESS); 215 } 216 217 /*@ 218 DMPlexGetRefinementLimit - Retrieve the maximum cell volume for refinement 219 220 Input Parameter: 221 . dm - The `DM` 222 223 Output Parameter: 224 . refinementLimit - The maximum cell volume in the refined mesh 225 226 Level: developer 227 228 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexSetRefinementLimit()`, `DMPlexGetRefinementUniform()`, `DMPlexSetRefinementUniform()` 229 @*/ 230 PetscErrorCode DMPlexGetRefinementLimit(DM dm, PetscReal *refinementLimit) 231 { 232 DM_Plex *mesh = (DM_Plex *)dm->data; 233 234 PetscFunctionBegin; 235 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 236 PetscAssertPointer(refinementLimit, 2); 237 /* if (mesh->refinementLimit < 0) = getMaxVolume()/2.0; */ 238 *refinementLimit = mesh->refinementLimit; 239 PetscFunctionReturn(PETSC_SUCCESS); 240 } 241 242 /*@C 243 DMPlexSetRefinementFunction - Set the function giving the maximum cell volume for refinement 244 245 Input Parameters: 246 + dm - The `DM` 247 - refinementFunc - Function giving the maximum cell volume in the refined mesh 248 249 Calling Sequence of `refinementFunc`: 250 + coords - Coordinates of the current point, usually a cell centroid 251 - limit - The maximum cell volume for a cell containing this point 252 253 Level: developer 254 255 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexGetRefinementFunction()`, `DMPlexGetRefinementUniform()`, `DMPlexSetRefinementUniform()`, `DMPlexGetRefinementLimit()`, `DMPlexSetRefinementLimit()` 256 @*/ 257 PetscErrorCode DMPlexSetRefinementFunction(DM dm, PetscErrorCode (*refinementFunc)(const PetscReal coords[], PetscReal *limit)) 258 { 259 DM_Plex *mesh = (DM_Plex *)dm->data; 260 261 PetscFunctionBegin; 262 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 263 mesh->refinementFunc = refinementFunc; 264 PetscFunctionReturn(PETSC_SUCCESS); 265 } 266 267 /*@C 268 DMPlexGetRefinementFunction - Get the function giving the maximum cell volume for refinement 269 270 Input Parameter: 271 . dm - The `DM` 272 273 Output Parameter: 274 . refinementFunc - Function giving the maximum cell volume in the refined mesh 275 276 Calling Sequence of `refinementFunc`: 277 + coords - Coordinates of the current point, usually a cell centroid 278 - limit - The maximum cell volume for a cell containing this point 279 280 Level: developer 281 282 .seealso: [](ch_unstructured), `DM`, `DMPLEX`, `DMRefine()`, `DMPlexSetRefinementFunction()`, `DMPlexGetRefinementUniform()`, `DMPlexSetRefinementUniform()`, `DMPlexGetRefinementLimit()`, `DMPlexSetRefinementLimit()` 283 @*/ 284 PetscErrorCode DMPlexGetRefinementFunction(DM dm, PetscErrorCode (**refinementFunc)(const PetscReal coords[], PetscReal *limit)) 285 { 286 DM_Plex *mesh = (DM_Plex *)dm->data; 287 288 PetscFunctionBegin; 289 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 290 PetscAssertPointer(refinementFunc, 2); 291 *refinementFunc = mesh->refinementFunc; 292 PetscFunctionReturn(PETSC_SUCCESS); 293 } 294 295 PetscErrorCode DMRefine_Plex(DM dm, MPI_Comm comm, DM *rdm) 296 { 297 PetscBool isUniform; 298 299 PetscFunctionBegin; 300 PetscCall(DMPlexGetRefinementUniform(dm, &isUniform)); 301 PetscCall(DMViewFromOptions(dm, NULL, "-initref_dm_view")); 302 if (isUniform) { 303 DMPlexTransform tr; 304 DM cdm, rcdm; 305 DMPlexTransformType trType; 306 const char *prefix; 307 PetscOptions options; 308 309 PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)dm), &tr)); 310 PetscCall(DMPlexTransformSetDM(tr, dm)); 311 PetscCall(DMPlexGetTransformType(dm, &trType)); 312 if (trType) PetscCall(DMPlexTransformSetType(tr, trType)); 313 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)dm, &prefix)); 314 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 315 PetscCall(PetscObjectGetOptions((PetscObject)dm, &options)); 316 PetscCall(PetscObjectSetOptions((PetscObject)tr, options)); 317 PetscCall(DMPlexTransformSetFromOptions(tr)); 318 PetscCall(PetscObjectSetOptions((PetscObject)tr, NULL)); 319 PetscCall(DMPlexTransformSetUp(tr)); 320 PetscCall(PetscObjectViewFromOptions((PetscObject)tr, NULL, "-dm_plex_transform_view")); 321 PetscCall(DMPlexTransformApply(tr, dm, rdm)); 322 PetscCall(DMPlexSetRegularRefinement(*rdm, PETSC_TRUE)); 323 PetscCall(DMSetMatType((*rdm), dm->mattype)); 324 PetscCall(DMCopyDisc(dm, *rdm)); 325 PetscCall(DMGetCoordinateDM(dm, &cdm)); 326 PetscCall(DMGetCoordinateDM(*rdm, &rcdm)); 327 PetscCall(DMCopyDisc(cdm, rcdm)); 328 PetscCall(DMPlexTransformCreateDiscLabels(tr, *rdm)); 329 PetscCall(DMPlexTransformDestroy(&tr)); 330 } else { 331 PetscCall(DMPlexRefine_Internal(dm, NULL, NULL, NULL, rdm)); 332 } 333 if (*rdm) { 334 ((DM_Plex *)(*rdm)->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 335 ((DM_Plex *)(*rdm)->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 336 } 337 PetscCall(DMViewFromOptions(dm, NULL, "-postref_dm_view")); 338 PetscFunctionReturn(PETSC_SUCCESS); 339 } 340 341 PetscErrorCode DMRefineHierarchy_Plex(DM dm, PetscInt nlevels, DM rdm[]) 342 { 343 DM cdm = dm; 344 PetscInt r; 345 PetscBool isUniform, localized; 346 347 PetscFunctionBegin; 348 PetscCall(DMPlexGetRefinementUniform(dm, &isUniform)); 349 PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 350 if (isUniform) { 351 for (r = 0; r < nlevels; ++r) { 352 DMPlexTransform tr; 353 DM codm, rcodm; 354 const char *prefix; 355 356 PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject)cdm), &tr)); 357 PetscCall(PetscObjectGetOptionsPrefix((PetscObject)cdm, &prefix)); 358 PetscCall(PetscObjectSetOptionsPrefix((PetscObject)tr, prefix)); 359 PetscCall(DMPlexTransformSetDM(tr, cdm)); 360 PetscCall(DMPlexTransformSetFromOptions(tr)); 361 PetscCall(DMPlexTransformSetUp(tr)); 362 PetscCall(DMPlexTransformApply(tr, cdm, &rdm[r])); 363 PetscCall(DMSetCoarsenLevel(rdm[r], cdm->leveldown)); 364 PetscCall(DMSetRefineLevel(rdm[r], cdm->levelup + 1)); 365 PetscCall(DMSetMatType(rdm[r], dm->mattype)); 366 PetscCall(DMCopyDisc(cdm, rdm[r])); 367 PetscCall(DMGetCoordinateDM(dm, &codm)); 368 PetscCall(DMGetCoordinateDM(rdm[r], &rcodm)); 369 PetscCall(DMCopyDisc(codm, rcodm)); 370 PetscCall(DMPlexTransformCreateDiscLabels(tr, rdm[r])); 371 PetscCall(DMSetCoarseDM(rdm[r], cdm)); 372 PetscCall(DMPlexSetRegularRefinement(rdm[r], PETSC_TRUE)); 373 if (rdm[r]) { 374 ((DM_Plex *)(rdm[r])->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 375 ((DM_Plex *)(rdm[r])->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 376 } 377 cdm = rdm[r]; 378 PetscCall(DMPlexTransformDestroy(&tr)); 379 } 380 } else { 381 for (r = 0; r < nlevels; ++r) { 382 PetscCall(DMRefine(cdm, PetscObjectComm((PetscObject)dm), &rdm[r])); 383 PetscCall(DMCopyDisc(cdm, rdm[r])); 384 if (localized) PetscCall(DMLocalizeCoordinates(rdm[r])); 385 PetscCall(DMSetCoarseDM(rdm[r], cdm)); 386 if (rdm[r]) { 387 ((DM_Plex *)(rdm[r])->data)->printFEM = ((DM_Plex *)dm->data)->printFEM; 388 ((DM_Plex *)(rdm[r])->data)->printL2 = ((DM_Plex *)dm->data)->printL2; 389 } 390 cdm = rdm[r]; 391 } 392 } 393 PetscFunctionReturn(PETSC_SUCCESS); 394 } 395