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