1 #include <petsc/private/dmplextransformimpl.h> /*I "petscdmplextransform.h" I*/ 2 3 #include <petsc/private/petscfeimpl.h> /* For PetscFEInterpolate_Static() */ 4 5 PetscClassId DMPLEXTRANSFORM_CLASSID; 6 7 PetscFunctionList DMPlexTransformList = NULL; 8 PetscBool DMPlexTransformRegisterAllCalled = PETSC_FALSE; 9 10 /* Construct cell type order since we must loop over cell types in depth order */ 11 static PetscErrorCode DMPlexCreateCellTypeOrder_Internal(PetscInt dim, PetscInt *ctOrder[], PetscInt *ctOrderInv[]) 12 { 13 PetscInt *ctO, *ctOInv; 14 PetscInt c, d, off = 0; 15 16 PetscFunctionBegin; 17 PetscCall(PetscCalloc2(DM_NUM_POLYTOPES+1, &ctO, DM_NUM_POLYTOPES+1, &ctOInv)); 18 for (d = 3; d >= dim; --d) { 19 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 20 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue; 21 ctO[off++] = c; 22 } 23 } 24 if (dim != 0) { 25 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 26 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != 0) continue; 27 ctO[off++] = c; 28 } 29 } 30 for (d = dim-1; d > 0; --d) { 31 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 32 if (DMPolytopeTypeGetDim((DMPolytopeType) c) != d) continue; 33 ctO[off++] = c; 34 } 35 } 36 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 37 if (DMPolytopeTypeGetDim((DMPolytopeType) c) >= 0) continue; 38 ctO[off++] = c; 39 } 40 PetscCheck(off == DM_NUM_POLYTOPES+1,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid offset %" PetscInt_FMT " for cell type order", off); 41 for (c = 0; c <= DM_NUM_POLYTOPES; ++c) { 42 ctOInv[ctO[c]] = c; 43 } 44 *ctOrder = ctO; 45 *ctOrderInv = ctOInv; 46 PetscFunctionReturn(0); 47 } 48 49 /*@C 50 DMPlexTransformRegister - Adds a new transform component implementation 51 52 Not Collective 53 54 Input Parameters: 55 + name - The name of a new user-defined creation routine 56 - create_func - The creation routine itself 57 58 Notes: 59 DMPlexTransformRegister() may be called multiple times to add several user-defined transforms 60 61 Sample usage: 62 .vb 63 DMPlexTransformRegister("my_transform", MyTransformCreate); 64 .ve 65 66 Then, your transform type can be chosen with the procedural interface via 67 .vb 68 DMPlexTransformCreate(MPI_Comm, DMPlexTransform *); 69 DMPlexTransformSetType(DMPlexTransform, "my_transform"); 70 .ve 71 or at runtime via the option 72 .vb 73 -dm_plex_transform_type my_transform 74 .ve 75 76 Level: advanced 77 78 .seealso: DMPlexTransformRegisterAll(), DMPlexTransformRegisterDestroy() 79 @*/ 80 PetscErrorCode DMPlexTransformRegister(const char name[], PetscErrorCode (*create_func)(DMPlexTransform)) 81 { 82 PetscFunctionBegin; 83 PetscCall(DMInitializePackage()); 84 PetscCall(PetscFunctionListAdd(&DMPlexTransformList, name, create_func)); 85 PetscFunctionReturn(0); 86 } 87 88 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Filter(DMPlexTransform); 89 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Regular(DMPlexTransform); 90 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_ToBox(DMPlexTransform); 91 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Alfeld(DMPlexTransform); 92 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_SBR(DMPlexTransform); 93 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_BL(DMPlexTransform); 94 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_1D(DMPlexTransform); 95 PETSC_EXTERN PetscErrorCode DMPlexTransformCreate_Extrude(DMPlexTransform); 96 97 /*@C 98 DMPlexTransformRegisterAll - Registers all of the transform components in the DM package. 99 100 Not Collective 101 102 Level: advanced 103 104 .seealso: DMRegisterAll(), DMPlexTransformRegisterDestroy() 105 @*/ 106 PetscErrorCode DMPlexTransformRegisterAll(void) 107 { 108 PetscFunctionBegin; 109 if (DMPlexTransformRegisterAllCalled) PetscFunctionReturn(0); 110 DMPlexTransformRegisterAllCalled = PETSC_TRUE; 111 112 PetscCall(DMPlexTransformRegister(DMPLEXTRANSFORMFILTER, DMPlexTransformCreate_Filter)); 113 PetscCall(DMPlexTransformRegister(DMPLEXREFINEREGULAR, DMPlexTransformCreate_Regular)); 114 PetscCall(DMPlexTransformRegister(DMPLEXREFINETOBOX, DMPlexTransformCreate_ToBox)); 115 PetscCall(DMPlexTransformRegister(DMPLEXREFINEALFELD, DMPlexTransformCreate_Alfeld)); 116 PetscCall(DMPlexTransformRegister(DMPLEXREFINEBOUNDARYLAYER, DMPlexTransformCreate_BL)); 117 PetscCall(DMPlexTransformRegister(DMPLEXREFINESBR, DMPlexTransformCreate_SBR)); 118 PetscCall(DMPlexTransformRegister(DMPLEXREFINE1D, DMPlexTransformCreate_1D)); 119 PetscCall(DMPlexTransformRegister(DMPLEXEXTRUDE, DMPlexTransformCreate_Extrude)); 120 PetscFunctionReturn(0); 121 } 122 123 /*@C 124 DMPlexTransformRegisterDestroy - This function destroys the . It is called from PetscFinalize(). 125 126 Level: developer 127 128 .seealso: PetscInitialize() 129 @*/ 130 PetscErrorCode DMPlexTransformRegisterDestroy(void) 131 { 132 PetscFunctionBegin; 133 PetscCall(PetscFunctionListDestroy(&DMPlexTransformList)); 134 DMPlexTransformRegisterAllCalled = PETSC_FALSE; 135 PetscFunctionReturn(0); 136 } 137 138 /*@ 139 DMPlexTransformCreate - Creates an empty transform object. The type can then be set with DMPlexTransformSetType(). 140 141 Collective 142 143 Input Parameter: 144 . comm - The communicator for the transform object 145 146 Output Parameter: 147 . dm - The transform object 148 149 Level: beginner 150 151 .seealso: DMPlexTransformSetType(), DMPLEXREFINEREGULAR, DMPLEXTRANSFORMFILTER 152 @*/ 153 PetscErrorCode DMPlexTransformCreate(MPI_Comm comm, DMPlexTransform *tr) 154 { 155 DMPlexTransform t; 156 157 PetscFunctionBegin; 158 PetscValidPointer(tr, 2); 159 *tr = NULL; 160 PetscCall(DMInitializePackage()); 161 162 PetscCall(PetscHeaderCreate(t, DMPLEXTRANSFORM_CLASSID, "DMPlexTransform", "Mesh Transform", "DMPlexTransform", comm, DMPlexTransformDestroy, DMPlexTransformView)); 163 t->setupcalled = PETSC_FALSE; 164 PetscCall(PetscCalloc2(DM_NUM_POLYTOPES, &t->coordFE, DM_NUM_POLYTOPES, &t->refGeom)); 165 *tr = t; 166 PetscFunctionReturn(0); 167 } 168 169 /*@C 170 DMSetType - Sets the particular implementation for a transform. 171 172 Collective on tr 173 174 Input Parameters: 175 + tr - The transform 176 - method - The name of the transform type 177 178 Options Database Key: 179 . -dm_plex_transform_type <type> - Sets the transform type; use -help for a list of available types 180 181 Notes: 182 See "petsc/include/petscdmplextransform.h" for available transform types 183 184 Level: intermediate 185 186 .seealso: DMPlexTransformGetType(), DMPlexTransformCreate() 187 @*/ 188 PetscErrorCode DMPlexTransformSetType(DMPlexTransform tr, DMPlexTransformType method) 189 { 190 PetscErrorCode (*r)(DMPlexTransform); 191 PetscBool match; 192 193 PetscFunctionBegin; 194 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 195 PetscCall(PetscObjectTypeCompare((PetscObject) tr, method, &match)); 196 if (match) PetscFunctionReturn(0); 197 198 PetscCall(DMPlexTransformRegisterAll()); 199 PetscCall(PetscFunctionListFind(DMPlexTransformList, method, &r)); 200 PetscCheck(r,PetscObjectComm((PetscObject) tr), PETSC_ERR_ARG_UNKNOWN_TYPE, "Unknown DMPlexTransform type: %s", method); 201 202 if (tr->ops->destroy) PetscCall((*tr->ops->destroy)(tr)); 203 PetscCall(PetscMemzero(tr->ops, sizeof(*tr->ops))); 204 PetscCall(PetscObjectChangeTypeName((PetscObject) tr, method)); 205 PetscCall((*r)(tr)); 206 PetscFunctionReturn(0); 207 } 208 209 /*@C 210 DMPlexTransformGetType - Gets the type name (as a string) from the transform. 211 212 Not Collective 213 214 Input Parameter: 215 . tr - The DMPlexTransform 216 217 Output Parameter: 218 . type - The DMPlexTransform type name 219 220 Level: intermediate 221 222 .seealso: DMPlexTransformSetType(), DMPlexTransformCreate() 223 @*/ 224 PetscErrorCode DMPlexTransformGetType(DMPlexTransform tr, DMPlexTransformType *type) 225 { 226 PetscFunctionBegin; 227 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 228 PetscValidPointer(type, 2); 229 PetscCall(DMPlexTransformRegisterAll()); 230 *type = ((PetscObject) tr)->type_name; 231 PetscFunctionReturn(0); 232 } 233 234 static PetscErrorCode DMPlexTransformView_Ascii(DMPlexTransform tr, PetscViewer v) 235 { 236 PetscViewerFormat format; 237 238 PetscFunctionBegin; 239 PetscCall(PetscViewerGetFormat(v, &format)); 240 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 241 const PetscInt *trTypes = NULL; 242 IS trIS; 243 PetscInt cols = 8; 244 PetscInt Nrt = 8, f, g; 245 246 PetscCall(PetscViewerASCIIPrintf(v, "Source Starts\n")); 247 for (g = 0; g <= cols; ++g) PetscCall(PetscViewerASCIIPrintf(v, " %14s", DMPolytopeTypes[g])); 248 PetscCall(PetscViewerASCIIPrintf(v, "\n")); 249 for (f = 0; f <= cols; ++f) PetscCall(PetscViewerASCIIPrintf(v, " %14" PetscInt_FMT, tr->ctStart[f])); 250 PetscCall(PetscViewerASCIIPrintf(v, "\n")); 251 PetscCall(PetscViewerASCIIPrintf(v, "Target Starts\n")); 252 for (g = 0; g <= cols; ++g) PetscCall(PetscViewerASCIIPrintf(v, " %14s", DMPolytopeTypes[g])); 253 PetscCall(PetscViewerASCIIPrintf(v, "\n")); 254 for (f = 0; f <= cols; ++f) PetscCall(PetscViewerASCIIPrintf(v, " %14" PetscInt_FMT, tr->ctStartNew[f])); 255 PetscCall(PetscViewerASCIIPrintf(v, "\n")); 256 257 if (tr->trType) { 258 PetscCall(DMLabelGetNumValues(tr->trType, &Nrt)); 259 PetscCall(DMLabelGetValueIS(tr->trType, &trIS)); 260 PetscCall(ISGetIndices(trIS, &trTypes)); 261 } 262 PetscCall(PetscViewerASCIIPrintf(v, "Offsets\n")); 263 PetscCall(PetscViewerASCIIPrintf(v, " ")); 264 for (g = 0; g < cols; ++g) { 265 PetscCall(PetscViewerASCIIPrintf(v, " %14s", DMPolytopeTypes[g])); 266 } 267 PetscCall(PetscViewerASCIIPrintf(v, "\n")); 268 for (f = 0; f < Nrt; ++f) { 269 PetscCall(PetscViewerASCIIPrintf(v, "%2" PetscInt_FMT " |", trTypes ? trTypes[f] : f)); 270 for (g = 0; g < cols; ++g) { 271 PetscCall(PetscViewerASCIIPrintf(v, " %14" PetscInt_FMT, tr->offset[f*DM_NUM_POLYTOPES+g])); 272 } 273 PetscCall(PetscViewerASCIIPrintf(v, " |\n")); 274 } 275 if (trTypes) { 276 PetscCall(ISGetIndices(trIS, &trTypes)); 277 PetscCall(ISDestroy(&trIS)); 278 } 279 } 280 PetscFunctionReturn(0); 281 } 282 283 /*@C 284 DMPlexTransformView - Views a DMPlexTransform 285 286 Collective on tr 287 288 Input Parameters: 289 + tr - the DMPlexTransform object to view 290 - v - the viewer 291 292 Level: beginner 293 294 .seealso DMPlexTransformDestroy(), DMPlexTransformCreate() 295 @*/ 296 PetscErrorCode DMPlexTransformView(DMPlexTransform tr, PetscViewer v) 297 { 298 PetscBool isascii; 299 300 PetscFunctionBegin; 301 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID ,1); 302 if (!v) PetscCall(PetscViewerASCIIGetStdout(PetscObjectComm((PetscObject) tr), &v)); 303 PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 2); 304 PetscCheckSameComm(tr, 1, v, 2); 305 PetscCall(PetscViewerCheckWritable(v)); 306 PetscCall(PetscObjectPrintClassNamePrefixType((PetscObject) tr, v)); 307 PetscCall(PetscObjectTypeCompare((PetscObject) v, PETSCVIEWERASCII, &isascii)); 308 if (isascii) PetscCall(DMPlexTransformView_Ascii(tr, v)); 309 if (tr->ops->view) PetscCall((*tr->ops->view)(tr, v)); 310 PetscFunctionReturn(0); 311 } 312 313 /*@ 314 DMPlexTransformSetFromOptions - Sets parameters in a transform from the options database 315 316 Collective on tr 317 318 Input Parameter: 319 . tr - the DMPlexTransform object to set options for 320 321 Options Database: 322 . -dm_plex_transform_type - Set the transform type, e.g. refine_regular 323 324 Level: intermediate 325 326 .seealso DMPlexTransformView(), DMPlexTransformCreate() 327 @*/ 328 PetscErrorCode DMPlexTransformSetFromOptions(DMPlexTransform tr) 329 { 330 char typeName[1024]; 331 const char *defName = DMPLEXREFINEREGULAR; 332 PetscBool flg; 333 334 PetscFunctionBegin; 335 PetscValidHeaderSpecific(tr,DMPLEXTRANSFORM_CLASSID,1); 336 PetscObjectOptionsBegin((PetscObject)tr); 337 PetscCall(PetscOptionsFList("-dm_plex_transform_type", "DMPlexTransform", "DMPlexTransformSetType", DMPlexTransformList, defName, typeName, 1024, &flg)); 338 if (flg) PetscCall(DMPlexTransformSetType(tr, typeName)); 339 else if (!((PetscObject) tr)->type_name) PetscCall(DMPlexTransformSetType(tr, defName)); 340 if (tr->ops->setfromoptions) PetscCall((*tr->ops->setfromoptions)(PetscOptionsObject,tr)); 341 /* process any options handlers added with PetscObjectAddOptionsHandler() */ 342 PetscCall(PetscObjectProcessOptionsHandlers(PetscOptionsObject,(PetscObject) tr)); 343 PetscOptionsEnd(); 344 PetscFunctionReturn(0); 345 } 346 347 /*@C 348 DMPlexTransformDestroy - Destroys a transform. 349 350 Collective on tr 351 352 Input Parameter: 353 . tr - the transform object to destroy 354 355 Level: beginner 356 357 .seealso DMPlexTransformView(), DMPlexTransformCreate() 358 @*/ 359 PetscErrorCode DMPlexTransformDestroy(DMPlexTransform *tr) 360 { 361 PetscInt c; 362 363 PetscFunctionBegin; 364 if (!*tr) PetscFunctionReturn(0); 365 PetscValidHeaderSpecific((*tr), DMPLEXTRANSFORM_CLASSID, 1); 366 if (--((PetscObject) (*tr))->refct > 0) {*tr = NULL; PetscFunctionReturn(0);} 367 368 if ((*tr)->ops->destroy) { 369 PetscCall((*(*tr)->ops->destroy)(*tr)); 370 } 371 PetscCall(DMDestroy(&(*tr)->dm)); 372 PetscCall(DMLabelDestroy(&(*tr)->active)); 373 PetscCall(DMLabelDestroy(&(*tr)->trType)); 374 PetscCall(PetscFree2((*tr)->ctOrderOld, (*tr)->ctOrderInvOld)); 375 PetscCall(PetscFree2((*tr)->ctOrderNew, (*tr)->ctOrderInvNew)); 376 PetscCall(PetscFree2((*tr)->ctStart, (*tr)->ctStartNew)); 377 PetscCall(PetscFree((*tr)->offset)); 378 for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 379 PetscCall(PetscFEDestroy(&(*tr)->coordFE[c])); 380 PetscCall(PetscFEGeomDestroy(&(*tr)->refGeom[c])); 381 } 382 if ((*tr)->trVerts) { 383 for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 384 DMPolytopeType *rct; 385 PetscInt *rsize, *rcone, *rornt, Nct, n, r; 386 387 if (DMPolytopeTypeGetDim((DMPolytopeType) c) > 0) { 388 PetscCall(DMPlexTransformCellTransform((*tr), (DMPolytopeType) c, 0, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 389 for (n = 0; n < Nct; ++n) { 390 391 if (rct[n] == DM_POLYTOPE_POINT) continue; 392 for (r = 0; r < rsize[n]; ++r) PetscCall(PetscFree((*tr)->trSubVerts[c][rct[n]][r])); 393 PetscCall(PetscFree((*tr)->trSubVerts[c][rct[n]])); 394 } 395 } 396 PetscCall(PetscFree((*tr)->trSubVerts[c])); 397 PetscCall(PetscFree((*tr)->trVerts[c])); 398 } 399 } 400 PetscCall(PetscFree3((*tr)->trNv, (*tr)->trVerts, (*tr)->trSubVerts)); 401 PetscCall(PetscFree2((*tr)->coordFE, (*tr)->refGeom)); 402 /* We do not destroy (*dm)->data here so that we can reference count backend objects */ 403 PetscCall(PetscHeaderDestroy(tr)); 404 PetscFunctionReturn(0); 405 } 406 407 static PetscErrorCode DMPlexTransformCreateOffset_Internal(DMPlexTransform tr, PetscInt ctOrderOld[], PetscInt ctStart[], PetscInt **offset) 408 { 409 DMLabel trType = tr->trType; 410 PetscInt c, cN, *off; 411 412 PetscFunctionBegin; 413 if (trType) { 414 DM dm; 415 IS rtIS; 416 const PetscInt *reftypes; 417 PetscInt Nrt, r; 418 419 PetscCall(DMPlexTransformGetDM(tr, &dm)); 420 PetscCall(DMLabelGetNumValues(trType, &Nrt)); 421 PetscCall(DMLabelGetValueIS(trType, &rtIS)); 422 PetscCall(ISGetIndices(rtIS, &reftypes)); 423 PetscCall(PetscCalloc1(Nrt*DM_NUM_POLYTOPES, &off)); 424 for (r = 0; r < Nrt; ++r) { 425 const PetscInt rt = reftypes[r]; 426 IS rtIS; 427 const PetscInt *points; 428 DMPolytopeType ct; 429 PetscInt p; 430 431 PetscCall(DMLabelGetStratumIS(trType, rt, &rtIS)); 432 PetscCall(ISGetIndices(rtIS, &points)); 433 p = points[0]; 434 PetscCall(ISRestoreIndices(rtIS, &points)); 435 PetscCall(ISDestroy(&rtIS)); 436 PetscCall(DMPlexGetCellType(dm, p, &ct)); 437 for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) { 438 const DMPolytopeType ctNew = (DMPolytopeType) cN; 439 DMPolytopeType *rct; 440 PetscInt *rsize, *cone, *ornt; 441 PetscInt Nct, n, s; 442 443 if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[r*DM_NUM_POLYTOPES+ctNew] = -1; break;} 444 off[r*DM_NUM_POLYTOPES+ctNew] = 0; 445 for (s = 0; s <= r; ++s) { 446 const PetscInt st = reftypes[s]; 447 DMPolytopeType sct; 448 PetscInt q, qrt; 449 450 PetscCall(DMLabelGetStratumIS(trType, st, &rtIS)); 451 PetscCall(ISGetIndices(rtIS, &points)); 452 q = points[0]; 453 PetscCall(ISRestoreIndices(rtIS, &points)); 454 PetscCall(ISDestroy(&rtIS)); 455 PetscCall(DMPlexGetCellType(dm, q, &sct)); 456 PetscCall(DMPlexTransformCellTransform(tr, sct, q, &qrt, &Nct, &rct, &rsize, &cone, &ornt)); 457 PetscCheck(st == qrt,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Refine type %" PetscInt_FMT " of point %" PetscInt_FMT " does not match predicted type %" PetscInt_FMT, qrt, q, st); 458 if (st == rt) { 459 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break; 460 if (n == Nct) off[r*DM_NUM_POLYTOPES+ctNew] = -1; 461 break; 462 } 463 for (n = 0; n < Nct; ++n) { 464 if (rct[n] == ctNew) { 465 PetscInt sn; 466 467 PetscCall(DMLabelGetStratumSize(trType, st, &sn)); 468 off[r*DM_NUM_POLYTOPES+ctNew] += sn * rsize[n]; 469 } 470 } 471 } 472 } 473 } 474 PetscCall(ISRestoreIndices(rtIS, &reftypes)); 475 PetscCall(ISDestroy(&rtIS)); 476 } else { 477 PetscCall(PetscCalloc1(DM_NUM_POLYTOPES*DM_NUM_POLYTOPES, &off)); 478 for (c = DM_POLYTOPE_POINT; c < DM_NUM_POLYTOPES; ++c) { 479 const DMPolytopeType ct = (DMPolytopeType) c; 480 for (cN = DM_POLYTOPE_POINT; cN < DM_NUM_POLYTOPES; ++cN) { 481 const DMPolytopeType ctNew = (DMPolytopeType) cN; 482 DMPolytopeType *rct; 483 PetscInt *rsize, *cone, *ornt; 484 PetscInt Nct, n, i; 485 486 if (DMPolytopeTypeGetDim(ct) < 0 || DMPolytopeTypeGetDim(ctNew) < 0) {off[ct*DM_NUM_POLYTOPES+ctNew] = -1; continue;} 487 off[ct*DM_NUM_POLYTOPES+ctNew] = 0; 488 for (i = DM_POLYTOPE_POINT; i < DM_NUM_POLYTOPES; ++i) { 489 const DMPolytopeType ict = (DMPolytopeType) ctOrderOld[i]; 490 const DMPolytopeType ictn = (DMPolytopeType) ctOrderOld[i+1]; 491 492 PetscCall(DMPlexTransformCellTransform(tr, ict, PETSC_DETERMINE, NULL, &Nct, &rct, &rsize, &cone, &ornt)); 493 if (ict == ct) { 494 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) break; 495 if (n == Nct) off[ct*DM_NUM_POLYTOPES+ctNew] = -1; 496 break; 497 } 498 for (n = 0; n < Nct; ++n) if (rct[n] == ctNew) off[ct*DM_NUM_POLYTOPES+ctNew] += (ctStart[ictn]-ctStart[ict]) * rsize[n]; 499 } 500 } 501 } 502 } 503 *offset = off; 504 PetscFunctionReturn(0); 505 } 506 507 PetscErrorCode DMPlexTransformSetUp(DMPlexTransform tr) 508 { 509 DM dm; 510 DMPolytopeType ctCell; 511 PetscInt pStart, pEnd, p, c, celldim = 0; 512 513 PetscFunctionBegin; 514 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 515 if (tr->setupcalled) PetscFunctionReturn(0); 516 if (tr->ops->setup) PetscCall((*tr->ops->setup)(tr)); 517 PetscCall(DMPlexTransformGetDM(tr, &dm)); 518 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 519 if (pEnd > pStart) { 520 PetscCall(DMPlexGetCellType(dm, 0, &ctCell)); 521 } else { 522 PetscInt dim; 523 524 PetscCall(DMGetDimension(dm, &dim)); 525 switch (dim) { 526 case 0: ctCell = DM_POLYTOPE_POINT;break; 527 case 1: ctCell = DM_POLYTOPE_SEGMENT;break; 528 case 2: ctCell = DM_POLYTOPE_TRIANGLE;break; 529 case 3: ctCell = DM_POLYTOPE_TETRAHEDRON;break; 530 default: ctCell = DM_POLYTOPE_UNKNOWN; 531 } 532 } 533 PetscCall(DMPlexCreateCellTypeOrder_Internal(DMPolytopeTypeGetDim(ctCell), &tr->ctOrderOld, &tr->ctOrderInvOld)); 534 for (p = pStart; p < pEnd; ++p) { 535 DMPolytopeType ct; 536 DMPolytopeType *rct; 537 PetscInt *rsize, *cone, *ornt; 538 PetscInt Nct, n; 539 540 PetscCall(DMPlexGetCellType(dm, p, &ct)); 541 PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %" PetscInt_FMT, p); 542 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &cone, &ornt)); 543 for (n = 0; n < Nct; ++n) celldim = PetscMax(celldim, DMPolytopeTypeGetDim(rct[n])); 544 } 545 PetscCall(DMPlexCreateCellTypeOrder_Internal(celldim, &tr->ctOrderNew, &tr->ctOrderInvNew)); 546 /* Construct sizes and offsets for each cell type */ 547 if (!tr->ctStart) { 548 PetscInt *ctS, *ctSN, *ctC, *ctCN; 549 550 PetscCall(PetscCalloc2(DM_NUM_POLYTOPES+1, &ctS, DM_NUM_POLYTOPES+1, &ctSN)); 551 PetscCall(PetscCalloc2(DM_NUM_POLYTOPES+1, &ctC, DM_NUM_POLYTOPES+1, &ctCN)); 552 for (p = pStart; p < pEnd; ++p) { 553 DMPolytopeType ct; 554 DMPolytopeType *rct; 555 PetscInt *rsize, *cone, *ornt; 556 PetscInt Nct, n; 557 558 PetscCall(DMPlexGetCellType(dm, p, &ct)); 559 PetscCheck(ct != DM_POLYTOPE_UNKNOWN,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No cell type for point %" PetscInt_FMT, p); 560 ++ctC[ct]; 561 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &cone, &ornt)); 562 for (n = 0; n < Nct; ++n) ctCN[rct[n]] += rsize[n]; 563 } 564 for (c = 0; c < DM_NUM_POLYTOPES; ++c) { 565 const PetscInt cto = tr->ctOrderOld[c]; 566 const PetscInt cton = tr->ctOrderOld[c+1]; 567 const PetscInt ctn = tr->ctOrderNew[c]; 568 const PetscInt ctnn = tr->ctOrderNew[c+1]; 569 570 ctS[cton] = ctS[cto] + ctC[cto]; 571 ctSN[ctnn] = ctSN[ctn] + ctCN[ctn]; 572 } 573 PetscCall(PetscFree2(ctC, ctCN)); 574 tr->ctStart = ctS; 575 tr->ctStartNew = ctSN; 576 } 577 PetscCall(DMPlexTransformCreateOffset_Internal(tr, tr->ctOrderOld, tr->ctStart, &tr->offset)); 578 tr->setupcalled = PETSC_TRUE; 579 PetscFunctionReturn(0); 580 } 581 582 PetscErrorCode DMPlexTransformGetDM(DMPlexTransform tr, DM *dm) 583 { 584 PetscFunctionBegin; 585 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 586 PetscValidPointer(dm, 2); 587 *dm = tr->dm; 588 PetscFunctionReturn(0); 589 } 590 591 PetscErrorCode DMPlexTransformSetDM(DMPlexTransform tr, DM dm) 592 { 593 PetscFunctionBegin; 594 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 595 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 596 PetscCall(PetscObjectReference((PetscObject) dm)); 597 PetscCall(DMDestroy(&tr->dm)); 598 tr->dm = dm; 599 PetscFunctionReturn(0); 600 } 601 602 PetscErrorCode DMPlexTransformGetActive(DMPlexTransform tr, DMLabel *active) 603 { 604 PetscFunctionBegin; 605 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 606 PetscValidPointer(active, 2); 607 *active = tr->active; 608 PetscFunctionReturn(0); 609 } 610 611 PetscErrorCode DMPlexTransformSetActive(DMPlexTransform tr, DMLabel active) 612 { 613 PetscFunctionBegin; 614 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 615 PetscValidHeaderSpecific(active, DMLABEL_CLASSID, 2); 616 PetscCall(PetscObjectReference((PetscObject) active)); 617 PetscCall(DMLabelDestroy(&tr->active)); 618 tr->active = active; 619 PetscFunctionReturn(0); 620 } 621 622 static PetscErrorCode DMPlexTransformGetCoordinateFE(DMPlexTransform tr, DMPolytopeType ct, PetscFE *fe) 623 { 624 PetscFunctionBegin; 625 if (!tr->coordFE[ct]) { 626 PetscInt dim, cdim; 627 628 dim = DMPolytopeTypeGetDim(ct); 629 PetscCall(DMGetCoordinateDim(tr->dm, &cdim)); 630 PetscCall(PetscFECreateLagrangeByCell(PETSC_COMM_SELF, dim, cdim, ct, 1, PETSC_DETERMINE, &tr->coordFE[ct])); 631 { 632 PetscDualSpace dsp; 633 PetscQuadrature quad; 634 DM K; 635 PetscFEGeom *cg; 636 PetscScalar *Xq; 637 PetscReal *xq, *wq; 638 PetscInt Nq, q; 639 640 PetscCall(DMPlexTransformGetCellVertices(tr, ct, &Nq, &Xq)); 641 PetscCall(PetscMalloc1(Nq*cdim, &xq)); 642 for (q = 0; q < Nq*cdim; ++q) xq[q] = PetscRealPart(Xq[q]); 643 PetscCall(PetscMalloc1(Nq, &wq)); 644 for (q = 0; q < Nq; ++q) wq[q] = 1.0; 645 PetscCall(PetscQuadratureCreate(PETSC_COMM_SELF, &quad)); 646 PetscCall(PetscQuadratureSetData(quad, dim, 1, Nq, xq, wq)); 647 PetscCall(PetscFESetQuadrature(tr->coordFE[ct], quad)); 648 649 PetscCall(PetscFEGetDualSpace(tr->coordFE[ct], &dsp)); 650 PetscCall(PetscDualSpaceGetDM(dsp, &K)); 651 PetscCall(PetscFEGeomCreate(quad, 1, cdim, PETSC_FALSE, &tr->refGeom[ct])); 652 cg = tr->refGeom[ct]; 653 PetscCall(DMPlexComputeCellGeometryFEM(K, 0, NULL, cg->v, cg->J, cg->invJ, cg->detJ)); 654 PetscCall(PetscQuadratureDestroy(&quad)); 655 } 656 } 657 *fe = tr->coordFE[ct]; 658 PetscFunctionReturn(0); 659 } 660 661 /*@ 662 DMPlexTransformSetDimensions - Set the dimensions for the transformed DM 663 664 Input Parameters: 665 + tr - The DMPlexTransform object 666 - dm - The original DM 667 668 Output Parameter: 669 . tdm - The transformed DM 670 671 Level: advanced 672 673 .seealso: DMPlexTransformApply(), DMPlexTransformCreate() 674 @*/ 675 PetscErrorCode DMPlexTransformSetDimensions(DMPlexTransform tr, DM dm, DM tdm) 676 { 677 PetscFunctionBegin; 678 if (tr->ops->setdimensions) { 679 PetscCall((*tr->ops->setdimensions)(tr, dm, tdm)); 680 } else { 681 PetscInt dim, cdim; 682 683 PetscCall(DMGetDimension(dm, &dim)); 684 PetscCall(DMSetDimension(tdm, dim)); 685 PetscCall(DMGetCoordinateDim(dm, &cdim)); 686 PetscCall(DMSetCoordinateDim(tdm, cdim)); 687 } 688 PetscFunctionReturn(0); 689 } 690 691 /*@ 692 DMPlexTransformGetTargetPoint - Get the number of a point in the transformed mesh based on information from the original mesh. 693 694 Not collective 695 696 Input Parameters: 697 + tr - The DMPlexTransform 698 . ct - The type of the original point which produces the new point 699 . ctNew - The type of the new point 700 . p - The original point which produces the new point 701 - r - The replica number of the new point, meaning it is the rth point of type ctNew produced from p 702 703 Output Parameters: 704 . pNew - The new point number 705 706 Level: developer 707 708 .seealso: DMPlexTransformGetSourcePoint(), DMPlexTransformCellTransform() 709 @*/ 710 PetscErrorCode DMPlexTransformGetTargetPoint(DMPlexTransform tr, DMPolytopeType ct, DMPolytopeType ctNew, PetscInt p, PetscInt r, PetscInt *pNew) 711 { 712 DMPolytopeType *rct; 713 PetscInt *rsize, *cone, *ornt; 714 PetscInt rt, Nct, n, off, rp; 715 DMLabel trType = tr->trType; 716 PetscInt ctS = tr->ctStart[ct], ctE = tr->ctStart[tr->ctOrderOld[tr->ctOrderInvOld[ct]+1]]; 717 PetscInt ctSN = tr->ctStartNew[ctNew], ctEN = tr->ctStartNew[tr->ctOrderNew[tr->ctOrderInvNew[ctNew]+1]]; 718 PetscInt newp = ctSN, cind; 719 720 PetscFunctionBeginHot; 721 PetscCheck(!(p < ctS) && !(p >= ctE),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %" PetscInt_FMT " is not a %s [%" PetscInt_FMT ", %" PetscInt_FMT ")", p, DMPolytopeTypes[ct], ctS, ctE); 722 PetscCall(DMPlexTransformCellTransform(tr, ct, p, &rt, &Nct, &rct, &rsize, &cone, &ornt)); 723 if (trType) { 724 PetscCall(DMLabelGetValueIndex(trType, rt, &cind)); 725 PetscCall(DMLabelGetStratumPointIndex(trType, rt, p, &rp)); 726 PetscCheck(rp >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s point %" PetscInt_FMT " does not have refine type %" PetscInt_FMT, DMPolytopeTypes[ct], p, rt); 727 } else { 728 cind = ct; 729 rp = p - ctS; 730 } 731 off = tr->offset[cind*DM_NUM_POLYTOPES + ctNew]; 732 PetscCheck(off >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell type %s (%" PetscInt_FMT ") of point %" PetscInt_FMT " does not produce type %s for transform %s", DMPolytopeTypes[ct], rt, p, DMPolytopeTypes[ctNew], tr->hdr.type_name); 733 newp += off; 734 for (n = 0; n < Nct; ++n) { 735 if (rct[n] == ctNew) { 736 if (rsize[n] && r >= rsize[n]) 737 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Replica number %" PetscInt_FMT " should be in [0, %" PetscInt_FMT ") for subcell type %s in cell type %s", r, rsize[n], DMPolytopeTypes[rct[n]], DMPolytopeTypes[ct]); 738 newp += rp * rsize[n] + r; 739 break; 740 } 741 } 742 743 PetscCheck(!(newp < ctSN) && !(newp >= ctEN),PETSC_COMM_SELF, PETSC_ERR_PLIB, "New point %" PetscInt_FMT " is not a %s [%" PetscInt_FMT ", %" PetscInt_FMT ")", newp, DMPolytopeTypes[ctNew], ctSN, ctEN); 744 *pNew = newp; 745 PetscFunctionReturn(0); 746 } 747 748 /*@ 749 DMPlexTransformGetSourcePoint - Get the number of a point in the original mesh based on information from the transformed mesh. 750 751 Not collective 752 753 Input Parameters: 754 + tr - The DMPlexTransform 755 - pNew - The new point number 756 757 Output Parameters: 758 + ct - The type of the original point which produces the new point 759 . ctNew - The type of the new point 760 . p - The original point which produces the new point 761 - r - The replica number of the new point, meaning it is the rth point of type ctNew produced from p 762 763 Level: developer 764 765 .seealso: DMPlexTransformGetTargetPoint(), DMPlexTransformCellTransform() 766 @*/ 767 PetscErrorCode DMPlexTransformGetSourcePoint(DMPlexTransform tr, PetscInt pNew, DMPolytopeType *ct, DMPolytopeType *ctNew, PetscInt *p, PetscInt *r) 768 { 769 DMLabel trType = tr->trType; 770 DMPolytopeType *rct; 771 PetscInt *rsize, *cone, *ornt; 772 PetscInt rt, Nct, n, rp = 0, rO = 0, pO; 773 PetscInt offset = -1, ctS, ctE, ctO = 0, ctN, ctTmp; 774 775 PetscFunctionBegin; 776 for (ctN = 0; ctN < DM_NUM_POLYTOPES; ++ctN) { 777 PetscInt ctSN = tr->ctStartNew[ctN], ctEN = tr->ctStartNew[tr->ctOrderNew[tr->ctOrderInvNew[ctN]+1]]; 778 779 if ((pNew >= ctSN) && (pNew < ctEN)) break; 780 } 781 PetscCheck(ctN != DM_NUM_POLYTOPES,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Cell type for target point %" PetscInt_FMT " could be not found", pNew); 782 if (trType) { 783 DM dm; 784 IS rtIS; 785 const PetscInt *reftypes; 786 PetscInt Nrt, r, rtStart; 787 788 PetscCall(DMPlexTransformGetDM(tr, &dm)); 789 PetscCall(DMLabelGetNumValues(trType, &Nrt)); 790 PetscCall(DMLabelGetValueIS(trType, &rtIS)); 791 PetscCall(ISGetIndices(rtIS, &reftypes)); 792 for (r = 0; r < Nrt; ++r) { 793 const PetscInt off = tr->offset[r*DM_NUM_POLYTOPES + ctN]; 794 795 if (tr->ctStartNew[ctN] + off > pNew) continue; 796 /* Check that any of this refinement type exist */ 797 /* TODO Actually keep track of the number produced here instead */ 798 if (off > offset) {rt = reftypes[r]; offset = off;} 799 } 800 PetscCall(ISRestoreIndices(rtIS, &reftypes)); 801 PetscCall(ISDestroy(&rtIS)); 802 PetscCheck(offset >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Source cell type for target point %" PetscInt_FMT " could be not found", pNew); 803 /* TODO Map refinement types to cell types */ 804 PetscCall(DMLabelGetStratumBounds(trType, rt, &rtStart, NULL)); 805 PetscCheck(rtStart >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Refinement type %" PetscInt_FMT " has no source points", rt); 806 for (ctO = 0; ctO < DM_NUM_POLYTOPES; ++ctO) { 807 PetscInt ctS = tr->ctStart[ctO], ctE = tr->ctStart[tr->ctOrderOld[tr->ctOrderInvOld[ctO]+1]]; 808 809 if ((rtStart >= ctS) && (rtStart < ctE)) break; 810 } 811 PetscCheck(ctO != DM_NUM_POLYTOPES,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Could not determine a cell type for refinement type %" PetscInt_FMT, rt); 812 } else { 813 for (ctTmp = 0; ctTmp < DM_NUM_POLYTOPES; ++ctTmp) { 814 const PetscInt off = tr->offset[ctTmp*DM_NUM_POLYTOPES + ctN]; 815 816 if (tr->ctStartNew[ctN] + off > pNew) continue; 817 if (tr->ctStart[tr->ctOrderOld[tr->ctOrderInvOld[ctTmp]+1]] <= tr->ctStart[ctTmp]) continue; 818 /* TODO Actually keep track of the number produced here instead */ 819 if (off > offset) {ctO = ctTmp; offset = off;} 820 } 821 PetscCheck(offset >= 0,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Source cell type for target point %" PetscInt_FMT " could be not found", pNew); 822 } 823 ctS = tr->ctStart[ctO]; 824 ctE = tr->ctStart[tr->ctOrderOld[tr->ctOrderInvOld[ctO]+1]]; 825 PetscCall(DMPlexTransformCellTransform(tr, (DMPolytopeType) ctO, ctS, &rt, &Nct, &rct, &rsize, &cone, &ornt)); 826 for (n = 0; n < Nct; ++n) { 827 if ((PetscInt) rct[n] == ctN) { 828 PetscInt tmp = pNew - tr->ctStartNew[ctN] - offset; 829 830 rp = tmp / rsize[n]; 831 rO = tmp % rsize[n]; 832 break; 833 } 834 } 835 PetscCheck(n != Nct,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Replica number for target point %" PetscInt_FMT " could be not found", pNew); 836 pO = rp + ctS; 837 PetscCheck(!(pO < ctS) && !(pO >= ctE),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Source point %" PetscInt_FMT " is not a %s [%" PetscInt_FMT ", %" PetscInt_FMT ")", pO, DMPolytopeTypes[ctO], ctS, ctE); 838 if (ct) *ct = (DMPolytopeType) ctO; 839 if (ctNew) *ctNew = (DMPolytopeType) ctN; 840 if (p) *p = pO; 841 if (r) *r = rO; 842 PetscFunctionReturn(0); 843 } 844 845 /*@ 846 DMPlexTransformCellTransform - Describes the transform of a given source cell into a set of other target cells. These produced cells become the new mesh. 847 848 Input Parameters: 849 + tr - The DMPlexTransform object 850 . source - The source cell type 851 - p - The source point, which can also determine the refine type 852 853 Output Parameters: 854 + rt - The refine type for this point 855 . Nt - The number of types produced by this point 856 . target - An array of length Nt giving the types produced 857 . size - An array of length Nt giving the number of cells of each type produced 858 . cone - An array of length Nt*size[t]*coneSize[t] giving the cell type for each point in the cone of each produced point 859 - ornt - An array of length Nt*size[t]*coneSize[t] giving the orientation for each point in the cone of each produced point 860 861 Note: The cone array gives the cone of each subcell listed by the first three outputs. For each cone point, we 862 need the cell type, point identifier, and orientation within the subcell. The orientation is with respect to the canonical 863 division (described in these outputs) of the cell in the original mesh. The point identifier is given by 864 $ the number of cones to be taken, or 0 for the current cell 865 $ the cell cone point number at each level from which it is subdivided 866 $ the replica number r of the subdivision. 867 The orientation is with respect to the canonical cone orientation. For example, the prescription for edge division is 868 $ Nt = 2 869 $ target = {DM_POLYTOPE_POINT, DM_POLYTOPE_SEGMENT} 870 $ size = {1, 2} 871 $ cone = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0} 872 $ ornt = { 0, 0, 0, 0} 873 874 Level: advanced 875 876 .seealso: DMPlexTransformApply(), DMPlexTransformCreate() 877 @*/ 878 PetscErrorCode DMPlexTransformCellTransform(DMPlexTransform tr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 879 { 880 PetscFunctionBegin; 881 PetscCall((*tr->ops->celltransform)(tr, source, p, rt, Nt, target, size, cone, ornt)); 882 PetscFunctionReturn(0); 883 } 884 885 PetscErrorCode DMPlexTransformGetSubcellOrientationIdentity(DMPlexTransform tr, DMPolytopeType sct, PetscInt sp, PetscInt so, DMPolytopeType tct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 886 { 887 PetscFunctionBegin; 888 *rnew = r; 889 *onew = DMPolytopeTypeComposeOrientation(tct, o, so); 890 PetscFunctionReturn(0); 891 } 892 893 /* Returns the same thing */ 894 PetscErrorCode DMPlexTransformCellTransformIdentity(DMPlexTransform tr, DMPolytopeType source, PetscInt p, PetscInt *rt, PetscInt *Nt, DMPolytopeType *target[], PetscInt *size[], PetscInt *cone[], PetscInt *ornt[]) 895 { 896 static DMPolytopeType vertexT[] = {DM_POLYTOPE_POINT}; 897 static PetscInt vertexS[] = {1}; 898 static PetscInt vertexC[] = {0}; 899 static PetscInt vertexO[] = {0}; 900 static DMPolytopeType edgeT[] = {DM_POLYTOPE_SEGMENT}; 901 static PetscInt edgeS[] = {1}; 902 static PetscInt edgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 903 static PetscInt edgeO[] = {0, 0}; 904 static DMPolytopeType tedgeT[] = {DM_POLYTOPE_POINT_PRISM_TENSOR}; 905 static PetscInt tedgeS[] = {1}; 906 static PetscInt tedgeC[] = {DM_POLYTOPE_POINT, 1, 0, 0, DM_POLYTOPE_POINT, 1, 1, 0}; 907 static PetscInt tedgeO[] = {0, 0}; 908 static DMPolytopeType triT[] = {DM_POLYTOPE_TRIANGLE}; 909 static PetscInt triS[] = {1}; 910 static PetscInt triC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0}; 911 static PetscInt triO[] = {0, 0, 0}; 912 static DMPolytopeType quadT[] = {DM_POLYTOPE_QUADRILATERAL}; 913 static PetscInt quadS[] = {1}; 914 static PetscInt quadC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_SEGMENT, 1, 2, 0, DM_POLYTOPE_SEGMENT, 1, 3, 0}; 915 static PetscInt quadO[] = {0, 0, 0, 0}; 916 static DMPolytopeType tquadT[] = {DM_POLYTOPE_SEG_PRISM_TENSOR}; 917 static PetscInt tquadS[] = {1}; 918 static PetscInt tquadC[] = {DM_POLYTOPE_SEGMENT, 1, 0, 0, DM_POLYTOPE_SEGMENT, 1, 1, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_POINT_PRISM_TENSOR, 1, 3, 0}; 919 static PetscInt tquadO[] = {0, 0, 0, 0}; 920 static DMPolytopeType tetT[] = {DM_POLYTOPE_TETRAHEDRON}; 921 static PetscInt tetS[] = {1}; 922 static PetscInt tetC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0}; 923 static PetscInt tetO[] = {0, 0, 0, 0}; 924 static DMPolytopeType hexT[] = {DM_POLYTOPE_HEXAHEDRON}; 925 static PetscInt hexS[] = {1}; 926 static PetscInt hexC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, 927 DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0, DM_POLYTOPE_QUADRILATERAL, 1, 5, 0}; 928 static PetscInt hexO[] = {0, 0, 0, 0, 0, 0}; 929 static DMPolytopeType tripT[] = {DM_POLYTOPE_TRI_PRISM}; 930 static PetscInt tripS[] = {1}; 931 static PetscInt tripC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 932 DM_POLYTOPE_QUADRILATERAL, 1, 2, 0, DM_POLYTOPE_QUADRILATERAL, 1, 3, 0, DM_POLYTOPE_QUADRILATERAL, 1, 4, 0}; 933 static PetscInt tripO[] = {0, 0, 0, 0, 0}; 934 static DMPolytopeType ttripT[] = {DM_POLYTOPE_TRI_PRISM_TENSOR}; 935 static PetscInt ttripS[] = {1}; 936 static PetscInt ttripC[] = {DM_POLYTOPE_TRIANGLE, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 937 DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0}; 938 static PetscInt ttripO[] = {0, 0, 0, 0, 0}; 939 static DMPolytopeType tquadpT[] = {DM_POLYTOPE_QUAD_PRISM_TENSOR}; 940 static PetscInt tquadpS[] = {1}; 941 static PetscInt tquadpC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_QUADRILATERAL, 1, 1, 0, 942 DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 2, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 3, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 4, 0, DM_POLYTOPE_SEG_PRISM_TENSOR, 1, 5, 0}; 943 static PetscInt tquadpO[] = {0, 0, 0, 0, 0, 0}; 944 static DMPolytopeType pyrT[] = {DM_POLYTOPE_PYRAMID}; 945 static PetscInt pyrS[] = {1}; 946 static PetscInt pyrC[] = {DM_POLYTOPE_QUADRILATERAL, 1, 0, 0, DM_POLYTOPE_TRIANGLE, 1, 1, 0, 947 DM_POLYTOPE_TRIANGLE, 1, 2, 0, DM_POLYTOPE_TRIANGLE, 1, 3, 0, DM_POLYTOPE_TRIANGLE, 1, 4, 0}; 948 static PetscInt pyrO[] = {0, 0, 0, 0, 0}; 949 950 PetscFunctionBegin; 951 if (rt) *rt = 0; 952 switch (source) { 953 case DM_POLYTOPE_POINT: *Nt = 1; *target = vertexT; *size = vertexS; *cone = vertexC; *ornt = vertexO; break; 954 case DM_POLYTOPE_SEGMENT: *Nt = 1; *target = edgeT; *size = edgeS; *cone = edgeC; *ornt = edgeO; break; 955 case DM_POLYTOPE_POINT_PRISM_TENSOR: *Nt = 1; *target = tedgeT; *size = tedgeS; *cone = tedgeC; *ornt = tedgeO; break; 956 case DM_POLYTOPE_TRIANGLE: *Nt = 1; *target = triT; *size = triS; *cone = triC; *ornt = triO; break; 957 case DM_POLYTOPE_QUADRILATERAL: *Nt = 1; *target = quadT; *size = quadS; *cone = quadC; *ornt = quadO; break; 958 case DM_POLYTOPE_SEG_PRISM_TENSOR: *Nt = 1; *target = tquadT; *size = tquadS; *cone = tquadC; *ornt = tquadO; break; 959 case DM_POLYTOPE_TETRAHEDRON: *Nt = 1; *target = tetT; *size = tetS; *cone = tetC; *ornt = tetO; break; 960 case DM_POLYTOPE_HEXAHEDRON: *Nt = 1; *target = hexT; *size = hexS; *cone = hexC; *ornt = hexO; break; 961 case DM_POLYTOPE_TRI_PRISM: *Nt = 1; *target = tripT; *size = tripS; *cone = tripC; *ornt = tripO; break; 962 case DM_POLYTOPE_TRI_PRISM_TENSOR: *Nt = 1; *target = ttripT; *size = ttripS; *cone = ttripC; *ornt = ttripO; break; 963 case DM_POLYTOPE_QUAD_PRISM_TENSOR: *Nt = 1; *target = tquadpT; *size = tquadpS; *cone = tquadpC; *ornt = tquadpO; break; 964 case DM_POLYTOPE_PYRAMID: *Nt = 1; *target = pyrT; *size = pyrS; *cone = pyrC; *ornt = pyrO; break; 965 default: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "No refinement strategy for %s", DMPolytopeTypes[source]); 966 } 967 PetscFunctionReturn(0); 968 } 969 970 /*@ 971 DMPlexTransformGetSubcellOrientation - Transform the replica number and orientation for a target point according to the group action for the source point 972 973 Not collective 974 975 Input Parameters: 976 + tr - The DMPlexTransform 977 . sct - The source point cell type, from whom the new cell is being produced 978 . sp - The source point 979 . so - The orientation of the source point in its enclosing parent 980 . tct - The target point cell type 981 . r - The replica number requested for the produced cell type 982 - o - The orientation of the replica 983 984 Output Parameters: 985 + rnew - The replica number, given the orientation of the parent 986 - onew - The replica orientation, given the orientation of the parent 987 988 Level: advanced 989 990 .seealso: DMPlexTransformCellTransform(), DMPlexTransformApply() 991 @*/ 992 PetscErrorCode DMPlexTransformGetSubcellOrientation(DMPlexTransform tr, DMPolytopeType sct, PetscInt sp, PetscInt so, DMPolytopeType tct, PetscInt r, PetscInt o, PetscInt *rnew, PetscInt *onew) 993 { 994 PetscFunctionBeginHot; 995 PetscCall((*tr->ops->getsubcellorientation)(tr, sct, sp, so, tct, r, o, rnew, onew)); 996 PetscFunctionReturn(0); 997 } 998 999 static PetscErrorCode DMPlexTransformSetConeSizes(DMPlexTransform tr, DM rdm) 1000 { 1001 DM dm; 1002 PetscInt pStart, pEnd, p, pNew; 1003 1004 PetscFunctionBegin; 1005 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1006 /* Must create the celltype label here so that we do not automatically try to compute the types */ 1007 PetscCall(DMCreateLabel(rdm, "celltype")); 1008 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1009 for (p = pStart; p < pEnd; ++p) { 1010 DMPolytopeType ct; 1011 DMPolytopeType *rct; 1012 PetscInt *rsize, *rcone, *rornt; 1013 PetscInt Nct, n, r; 1014 1015 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1016 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1017 for (n = 0; n < Nct; ++n) { 1018 for (r = 0; r < rsize[n]; ++r) { 1019 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &pNew)); 1020 PetscCall(DMPlexSetConeSize(rdm, pNew, DMPolytopeTypeGetConeSize(rct[n]))); 1021 PetscCall(DMPlexSetCellType(rdm, pNew, rct[n])); 1022 } 1023 } 1024 } 1025 /* Let the DM know we have set all the cell types */ 1026 { 1027 DMLabel ctLabel; 1028 DM_Plex *plex = (DM_Plex *) rdm->data; 1029 1030 PetscCall(DMPlexGetCellTypeLabel(rdm, &ctLabel)); 1031 PetscCall(PetscObjectStateGet((PetscObject) ctLabel, &plex->celltypeState)); 1032 } 1033 PetscFunctionReturn(0); 1034 } 1035 1036 #if 0 1037 static PetscErrorCode DMPlexTransformGetConeSize(DMPlexTransform tr, PetscInt q, PetscInt *coneSize) 1038 { 1039 PetscInt ctNew; 1040 1041 PetscFunctionBegin; 1042 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 1043 PetscValidPointer(coneSize, 3); 1044 /* TODO Can do bisection since everything is sorted */ 1045 for (ctNew = DM_POLYTOPE_POINT; ctNew < DM_NUM_POLYTOPES; ++ctNew) { 1046 PetscInt ctSN = tr->ctStartNew[ctNew], ctEN = tr->ctStartNew[tr->ctOrderNew[tr->ctOrderInvNew[ctNew]+1]]; 1047 1048 if (q >= ctSN && q < ctEN) break; 1049 } 1050 PetscCheck(ctNew < DM_NUM_POLYTOPES,PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Point %" PetscInt_FMT " cannot be located in the transformed mesh", q); 1051 *coneSize = DMPolytopeTypeGetConeSize((DMPolytopeType) ctNew); 1052 PetscFunctionReturn(0); 1053 } 1054 #endif 1055 1056 /* The orientation o is for the interior of the cell p */ 1057 static PetscErrorCode DMPlexTransformGetCone_Internal(DMPlexTransform tr, PetscInt p, PetscInt o, DMPolytopeType ct, DMPolytopeType ctNew, 1058 const PetscInt rcone[], PetscInt *coneoff, const PetscInt rornt[], PetscInt *orntoff, 1059 PetscInt coneNew[], PetscInt orntNew[]) 1060 { 1061 DM dm; 1062 const PetscInt csizeNew = DMPolytopeTypeGetConeSize(ctNew); 1063 const PetscInt *cone; 1064 PetscInt c, coff = *coneoff, ooff = *orntoff; 1065 1066 PetscFunctionBegin; 1067 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1068 PetscCall(DMPlexGetCone(dm, p, &cone)); 1069 for (c = 0; c < csizeNew; ++c) { 1070 PetscInt ppp = -1; /* Parent Parent point: Parent of point pp */ 1071 PetscInt pp = p; /* Parent point: Point in the original mesh producing new cone point */ 1072 PetscInt po = 0; /* Orientation of parent point pp in parent parent point ppp */ 1073 DMPolytopeType pct = ct; /* Parent type: Cell type for parent of new cone point */ 1074 const PetscInt *pcone = cone; /* Parent cone: Cone of parent point pp */ 1075 PetscInt pr = -1; /* Replica number of pp that produces new cone point */ 1076 const DMPolytopeType ft = (DMPolytopeType) rcone[coff++]; /* Cell type for new cone point of pNew */ 1077 const PetscInt fn = rcone[coff++]; /* Number of cones of p that need to be taken when producing new cone point */ 1078 PetscInt fo = rornt[ooff++]; /* Orientation of new cone point in pNew */ 1079 PetscInt lc; 1080 1081 /* Get the type (pct) and point number (pp) of the parent point in the original mesh which produces this cone point */ 1082 for (lc = 0; lc < fn; ++lc) { 1083 const PetscInt *parr = DMPolytopeTypeGetArrangment(pct, po); 1084 const PetscInt acp = rcone[coff++]; 1085 const PetscInt pcp = parr[acp*2]; 1086 const PetscInt pco = parr[acp*2+1]; 1087 const PetscInt *ppornt; 1088 1089 ppp = pp; 1090 pp = pcone[pcp]; 1091 PetscCall(DMPlexGetCellType(dm, pp, &pct)); 1092 PetscCall(DMPlexGetCone(dm, pp, &pcone)); 1093 PetscCall(DMPlexGetConeOrientation(dm, ppp, &ppornt)); 1094 po = DMPolytopeTypeComposeOrientation(pct, ppornt[pcp], pco); 1095 } 1096 pr = rcone[coff++]; 1097 /* Orientation po of pp maps (pr, fo) -> (pr', fo') */ 1098 PetscCall(DMPlexTransformGetSubcellOrientation(tr, pct, pp, fn ? po : o, ft, pr, fo, &pr, &fo)); 1099 PetscCall(DMPlexTransformGetTargetPoint(tr, pct, ft, pp, pr, &coneNew[c])); 1100 orntNew[c] = fo; 1101 } 1102 *coneoff = coff; 1103 *orntoff = ooff; 1104 PetscFunctionReturn(0); 1105 } 1106 1107 static PetscErrorCode DMPlexTransformSetCones(DMPlexTransform tr, DM rdm) 1108 { 1109 DM dm; 1110 DMPolytopeType ct; 1111 PetscInt *coneNew, *orntNew; 1112 PetscInt maxConeSize = 0, pStart, pEnd, p, pNew; 1113 1114 PetscFunctionBegin; 1115 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1116 for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p)); 1117 PetscCall(DMGetWorkArray(rdm, maxConeSize, MPIU_INT, &coneNew)); 1118 PetscCall(DMGetWorkArray(rdm, maxConeSize, MPIU_INT, &orntNew)); 1119 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1120 for (p = pStart; p < pEnd; ++p) { 1121 const PetscInt *cone, *ornt; 1122 PetscInt coff, ooff; 1123 DMPolytopeType *rct; 1124 PetscInt *rsize, *rcone, *rornt; 1125 PetscInt Nct, n, r; 1126 1127 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1128 PetscCall(DMPlexGetCone(dm, p, &cone)); 1129 PetscCall(DMPlexGetConeOrientation(dm, p, &ornt)); 1130 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1131 for (n = 0, coff = 0, ooff = 0; n < Nct; ++n) { 1132 const DMPolytopeType ctNew = rct[n]; 1133 1134 for (r = 0; r < rsize[n]; ++r) { 1135 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &pNew)); 1136 PetscCall(DMPlexTransformGetCone_Internal(tr, p, 0, ct, ctNew, rcone, &coff, rornt, &ooff, coneNew, orntNew)); 1137 PetscCall(DMPlexSetCone(rdm, pNew, coneNew)); 1138 PetscCall(DMPlexSetConeOrientation(rdm, pNew, orntNew)); 1139 } 1140 } 1141 } 1142 PetscCall(DMRestoreWorkArray(rdm, maxConeSize, MPIU_INT, &coneNew)); 1143 PetscCall(DMRestoreWorkArray(rdm, maxConeSize, MPIU_INT, &orntNew)); 1144 PetscCall(DMViewFromOptions(rdm, NULL, "-rdm_view")); 1145 PetscCall(DMPlexSymmetrize(rdm)); 1146 PetscCall(DMPlexStratify(rdm)); 1147 PetscFunctionReturn(0); 1148 } 1149 1150 PetscErrorCode DMPlexTransformGetConeOriented(DMPlexTransform tr, PetscInt q, PetscInt po, const PetscInt *cone[], const PetscInt *ornt[]) 1151 { 1152 DM dm; 1153 DMPolytopeType ct, qct; 1154 DMPolytopeType *rct; 1155 PetscInt *rsize, *rcone, *rornt, *qcone, *qornt; 1156 PetscInt maxConeSize = 0, Nct, p, r, n, nr, coff = 0, ooff = 0; 1157 1158 PetscFunctionBegin; 1159 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 1160 PetscValidPointer(cone, 4); 1161 PetscValidPointer(ornt, 5); 1162 for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p)); 1163 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1164 PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &qcone)); 1165 PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &qornt)); 1166 PetscCall(DMPlexTransformGetSourcePoint(tr, q, &ct, &qct, &p, &r)); 1167 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1168 for (n = 0; n < Nct; ++n) { 1169 const DMPolytopeType ctNew = rct[n]; 1170 const PetscInt csizeNew = DMPolytopeTypeGetConeSize(ctNew); 1171 PetscInt Nr = rsize[n], fn, c; 1172 1173 if (ctNew == qct) Nr = r; 1174 for (nr = 0; nr < Nr; ++nr) { 1175 for (c = 0; c < csizeNew; ++c) { 1176 ++coff; /* Cell type of new cone point */ 1177 fn = rcone[coff++]; /* Number of cones of p that need to be taken when producing new cone point */ 1178 coff += fn; 1179 ++coff; /* Replica number of new cone point */ 1180 ++ooff; /* Orientation of new cone point */ 1181 } 1182 } 1183 if (ctNew == qct) break; 1184 } 1185 PetscCall(DMPlexTransformGetCone_Internal(tr, p, po, ct, qct, rcone, &coff, rornt, &ooff, qcone, qornt)); 1186 *cone = qcone; 1187 *ornt = qornt; 1188 PetscFunctionReturn(0); 1189 } 1190 1191 PetscErrorCode DMPlexTransformGetCone(DMPlexTransform tr, PetscInt q, const PetscInt *cone[], const PetscInt *ornt[]) 1192 { 1193 DM dm; 1194 DMPolytopeType ct, qct; 1195 DMPolytopeType *rct; 1196 PetscInt *rsize, *rcone, *rornt, *qcone, *qornt; 1197 PetscInt maxConeSize = 0, Nct, p, r, n, nr, coff = 0, ooff = 0; 1198 1199 PetscFunctionBegin; 1200 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 1201 PetscValidPointer(cone, 3); 1202 for (p = 0; p < DM_NUM_POLYTOPES; ++p) maxConeSize = PetscMax(maxConeSize, DMPolytopeTypeGetConeSize((DMPolytopeType) p)); 1203 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1204 PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &qcone)); 1205 PetscCall(DMGetWorkArray(dm, maxConeSize, MPIU_INT, &qornt)); 1206 PetscCall(DMPlexTransformGetSourcePoint(tr, q, &ct, &qct, &p, &r)); 1207 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1208 for (n = 0; n < Nct; ++n) { 1209 const DMPolytopeType ctNew = rct[n]; 1210 const PetscInt csizeNew = DMPolytopeTypeGetConeSize(ctNew); 1211 PetscInt Nr = rsize[n], fn, c; 1212 1213 if (ctNew == qct) Nr = r; 1214 for (nr = 0; nr < Nr; ++nr) { 1215 for (c = 0; c < csizeNew; ++c) { 1216 ++coff; /* Cell type of new cone point */ 1217 fn = rcone[coff++]; /* Number of cones of p that need to be taken when producing new cone point */ 1218 coff += fn; 1219 ++coff; /* Replica number of new cone point */ 1220 ++ooff; /* Orientation of new cone point */ 1221 } 1222 } 1223 if (ctNew == qct) break; 1224 } 1225 PetscCall(DMPlexTransformGetCone_Internal(tr, p, 0, ct, qct, rcone, &coff, rornt, &ooff, qcone, qornt)); 1226 *cone = qcone; 1227 *ornt = qornt; 1228 PetscFunctionReturn(0); 1229 } 1230 1231 PetscErrorCode DMPlexTransformRestoreCone(DMPlexTransform tr, PetscInt q, const PetscInt *cone[], const PetscInt *ornt[]) 1232 { 1233 DM dm; 1234 1235 PetscFunctionBegin; 1236 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 1237 PetscValidPointer(cone, 3); 1238 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1239 PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, cone)); 1240 PetscCall(DMRestoreWorkArray(dm, 0, MPIU_INT, ornt)); 1241 PetscFunctionReturn(0); 1242 } 1243 1244 static PetscErrorCode DMPlexTransformCreateCellVertices_Internal(DMPlexTransform tr) 1245 { 1246 PetscInt ict; 1247 1248 PetscFunctionBegin; 1249 PetscCall(PetscCalloc3(DM_NUM_POLYTOPES, &tr->trNv, DM_NUM_POLYTOPES, &tr->trVerts, DM_NUM_POLYTOPES, &tr->trSubVerts)); 1250 for (ict = DM_POLYTOPE_POINT; ict < DM_NUM_POLYTOPES; ++ict) { 1251 const DMPolytopeType ct = (DMPolytopeType) ict; 1252 DMPlexTransform reftr; 1253 DM refdm, trdm; 1254 Vec coordinates; 1255 const PetscScalar *coords; 1256 DMPolytopeType *rct; 1257 PetscInt *rsize, *rcone, *rornt; 1258 PetscInt Nct, n, r, pNew; 1259 PetscInt vStart, vEnd, Nc; 1260 const PetscInt debug = 0; 1261 const char *typeName; 1262 1263 /* Since points are 0-dimensional, coordinates make no sense */ 1264 if (DMPolytopeTypeGetDim(ct) <= 0) continue; 1265 PetscCall(DMPlexCreateReferenceCell(PETSC_COMM_SELF, ct, &refdm)); 1266 PetscCall(DMPlexTransformCreate(PETSC_COMM_SELF, &reftr)); 1267 PetscCall(DMPlexTransformSetDM(reftr, refdm)); 1268 PetscCall(DMPlexTransformGetType(tr, &typeName)); 1269 PetscCall(DMPlexTransformSetType(reftr, typeName)); 1270 PetscCall(DMPlexTransformSetUp(reftr)); 1271 PetscCall(DMPlexTransformApply(reftr, refdm, &trdm)); 1272 1273 PetscCall(DMPlexGetDepthStratum(trdm, 0, &vStart, &vEnd)); 1274 tr->trNv[ct] = vEnd - vStart; 1275 PetscCall(DMGetCoordinatesLocal(trdm, &coordinates)); 1276 PetscCall(VecGetLocalSize(coordinates, &Nc)); 1277 PetscCheckFalse(tr->trNv[ct] * DMPolytopeTypeGetDim(ct) != Nc,PETSC_COMM_SELF, PETSC_ERR_PLIB, "Cell type %s, transformed coordinate size %" PetscInt_FMT " != %" PetscInt_FMT " size of coordinate storage", DMPolytopeTypes[ct], tr->trNv[ct] * DMPolytopeTypeGetDim(ct), Nc); 1278 PetscCall(PetscCalloc1(Nc, &tr->trVerts[ct])); 1279 PetscCall(VecGetArrayRead(coordinates, &coords)); 1280 PetscCall(PetscArraycpy(tr->trVerts[ct], coords, Nc)); 1281 PetscCall(VecRestoreArrayRead(coordinates, &coords)); 1282 1283 PetscCall(PetscCalloc1(DM_NUM_POLYTOPES, &tr->trSubVerts[ct])); 1284 PetscCall(DMPlexTransformCellTransform(reftr, ct, 0, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1285 for (n = 0; n < Nct; ++n) { 1286 1287 /* Since points are 0-dimensional, coordinates make no sense */ 1288 if (rct[n] == DM_POLYTOPE_POINT) continue; 1289 PetscCall(PetscCalloc1(rsize[n], &tr->trSubVerts[ct][rct[n]])); 1290 for (r = 0; r < rsize[n]; ++r) { 1291 PetscInt *closure = NULL; 1292 PetscInt clSize, cl, Nv = 0; 1293 1294 PetscCall(PetscCalloc1(DMPolytopeTypeGetNumVertices(rct[n]), &tr->trSubVerts[ct][rct[n]][r])); 1295 PetscCall(DMPlexTransformGetTargetPoint(reftr, ct, rct[n], 0, r, &pNew)); 1296 PetscCall(DMPlexGetTransitiveClosure(trdm, pNew, PETSC_TRUE, &clSize, &closure)); 1297 for (cl = 0; cl < clSize*2; cl += 2) { 1298 const PetscInt sv = closure[cl]; 1299 1300 if ((sv >= vStart) && (sv < vEnd)) tr->trSubVerts[ct][rct[n]][r][Nv++] = sv - vStart; 1301 } 1302 PetscCall(DMPlexRestoreTransitiveClosure(trdm, pNew, PETSC_TRUE, &clSize, &closure)); 1303 PetscCheck(Nv == DMPolytopeTypeGetNumVertices(rct[n]),PETSC_COMM_SELF, PETSC_ERR_PLIB, "Number of vertices %" PetscInt_FMT " != %" PetscInt_FMT " for %s subcell %" PetscInt_FMT " from cell %s", Nv, DMPolytopeTypeGetNumVertices(rct[n]), DMPolytopeTypes[rct[n]], r, DMPolytopeTypes[ct]); 1304 } 1305 } 1306 if (debug) { 1307 DMPolytopeType *rct; 1308 PetscInt *rsize, *rcone, *rornt; 1309 PetscInt v, dE = DMPolytopeTypeGetDim(ct), d, off = 0; 1310 1311 PetscCall(PetscPrintf(PETSC_COMM_SELF, "%s: %" PetscInt_FMT " vertices\n", DMPolytopeTypes[ct], tr->trNv[ct])); 1312 for (v = 0; v < tr->trNv[ct]; ++v) { 1313 PetscCall(PetscPrintf(PETSC_COMM_SELF, " ")); 1314 for (d = 0; d < dE; ++d) PetscCall(PetscPrintf(PETSC_COMM_SELF, "%g ", (double)PetscRealPart(tr->trVerts[ct][off++]))); 1315 PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 1316 } 1317 1318 PetscCall(DMPlexTransformCellTransform(reftr, ct, 0, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1319 for (n = 0; n < Nct; ++n) { 1320 if (rct[n] == DM_POLYTOPE_POINT) continue; 1321 PetscCall(PetscPrintf(PETSC_COMM_SELF, "%s: %s subvertices %" PetscInt_FMT "\n", DMPolytopeTypes[ct], DMPolytopeTypes[rct[n]], tr->trNv[ct])); 1322 for (r = 0; r < rsize[n]; ++r) { 1323 PetscCall(PetscPrintf(PETSC_COMM_SELF, " ")); 1324 for (v = 0; v < DMPolytopeTypeGetNumVertices(rct[n]); ++v) { 1325 PetscCall(PetscPrintf(PETSC_COMM_SELF, "%" PetscInt_FMT " ", tr->trSubVerts[ct][rct[n]][r][v])); 1326 } 1327 PetscCall(PetscPrintf(PETSC_COMM_SELF, "\n")); 1328 } 1329 } 1330 } 1331 PetscCall(DMDestroy(&refdm)); 1332 PetscCall(DMDestroy(&trdm)); 1333 PetscCall(DMPlexTransformDestroy(&reftr)); 1334 } 1335 PetscFunctionReturn(0); 1336 } 1337 1338 /* 1339 DMPlexTransformGetCellVertices - Get the set of transformed vertices lying in the closure of a reference cell of given type 1340 1341 Input Parameters: 1342 + tr - The DMPlexTransform object 1343 - ct - The cell type 1344 1345 Output Parameters: 1346 + Nv - The number of transformed vertices in the closure of the reference cell of given type 1347 - trVerts - The coordinates of these vertices in the reference cell 1348 1349 Level: developer 1350 1351 .seealso: DMPlexTransformGetSubcellVertices() 1352 */ 1353 PetscErrorCode DMPlexTransformGetCellVertices(DMPlexTransform tr, DMPolytopeType ct, PetscInt *Nv, PetscScalar *trVerts[]) 1354 { 1355 PetscFunctionBegin; 1356 if (!tr->trNv) PetscCall(DMPlexTransformCreateCellVertices_Internal(tr)); 1357 if (Nv) *Nv = tr->trNv[ct]; 1358 if (trVerts) *trVerts = tr->trVerts[ct]; 1359 PetscFunctionReturn(0); 1360 } 1361 1362 /* 1363 DMPlexTransformGetSubcellVertices - Get the set of transformed vertices defining a subcell in the reference cell of given type 1364 1365 Input Parameters: 1366 + tr - The DMPlexTransform object 1367 . ct - The cell type 1368 . rct - The subcell type 1369 - r - The subcell index 1370 1371 Output Parameter: 1372 . subVerts - The indices of these vertices in the set of vertices returned by DMPlexTransformGetCellVertices() 1373 1374 Level: developer 1375 1376 .seealso: DMPlexTransformGetCellVertices() 1377 */ 1378 PetscErrorCode DMPlexTransformGetSubcellVertices(DMPlexTransform tr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, PetscInt *subVerts[]) 1379 { 1380 PetscFunctionBegin; 1381 if (!tr->trNv) PetscCall(DMPlexTransformCreateCellVertices_Internal(tr)); 1382 PetscCheck(tr->trSubVerts[ct][rct],PetscObjectComm((PetscObject) tr), PETSC_ERR_ARG_WRONG, "Cell type %s does not produce %s", DMPolytopeTypes[ct], DMPolytopeTypes[rct]); 1383 if (subVerts) *subVerts = tr->trSubVerts[ct][rct][r]; 1384 PetscFunctionReturn(0); 1385 } 1386 1387 /* Computes new vertex as the barycenter, or centroid */ 1388 PetscErrorCode DMPlexTransformMapCoordinatesBarycenter_Internal(DMPlexTransform tr, DMPolytopeType pct, DMPolytopeType ct, PetscInt p, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[]) 1389 { 1390 PetscInt v,d; 1391 1392 PetscFunctionBeginHot; 1393 PetscCheck(ct == DM_POLYTOPE_POINT,PETSC_COMM_SELF,PETSC_ERR_SUP,"Not for refined point type %s",DMPolytopeTypes[ct]); 1394 for (d = 0; d < dE; ++d) out[d] = 0.0; 1395 for (v = 0; v < Nv; ++v) for (d = 0; d < dE; ++d) out[d] += in[v*dE+d]; 1396 for (d = 0; d < dE; ++d) out[d] /= Nv; 1397 PetscFunctionReturn(0); 1398 } 1399 1400 /*@ 1401 DMPlexTransformMapCoordinates - Calculate new coordinates for produced points 1402 1403 Not collective 1404 1405 Input Parameters: 1406 + cr - The DMPlexCellRefiner 1407 . pct - The cell type of the parent, from whom the new cell is being produced 1408 . ct - The type being produced 1409 . p - The original point 1410 . r - The replica number requested for the produced cell type 1411 . Nv - Number of vertices in the closure of the parent cell 1412 . dE - Spatial dimension 1413 - in - array of size Nv*dE, holding coordinates of the vertices in the closure of the parent cell 1414 1415 Output Parameter: 1416 . out - The coordinates of the new vertices 1417 1418 Level: intermediate 1419 1420 .seealso: DMPlexTransformApply() 1421 @*/ 1422 PetscErrorCode DMPlexTransformMapCoordinates(DMPlexTransform tr, DMPolytopeType pct, DMPolytopeType ct, PetscInt p, PetscInt r, PetscInt Nv, PetscInt dE, const PetscScalar in[], PetscScalar out[]) 1423 { 1424 PetscFunctionBeginHot; 1425 PetscCall((*tr->ops->mapcoordinates)(tr, pct, ct, p, r, Nv, dE, in, out)); 1426 PetscFunctionReturn(0); 1427 } 1428 1429 static PetscErrorCode RefineLabel_Internal(DMPlexTransform tr, DMLabel label, DMLabel labelNew) 1430 { 1431 DM dm; 1432 IS valueIS; 1433 const PetscInt *values; 1434 PetscInt defVal, Nv, val; 1435 1436 PetscFunctionBegin; 1437 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1438 PetscCall(DMLabelGetDefaultValue(label, &defVal)); 1439 PetscCall(DMLabelSetDefaultValue(labelNew, defVal)); 1440 PetscCall(DMLabelGetValueIS(label, &valueIS)); 1441 PetscCall(ISGetLocalSize(valueIS, &Nv)); 1442 PetscCall(ISGetIndices(valueIS, &values)); 1443 for (val = 0; val < Nv; ++val) { 1444 IS pointIS; 1445 const PetscInt *points; 1446 PetscInt numPoints, p; 1447 1448 /* Ensure refined label is created with same number of strata as 1449 * original (even if no entries here). */ 1450 PetscCall(DMLabelAddStratum(labelNew, values[val])); 1451 PetscCall(DMLabelGetStratumIS(label, values[val], &pointIS)); 1452 PetscCall(ISGetLocalSize(pointIS, &numPoints)); 1453 PetscCall(ISGetIndices(pointIS, &points)); 1454 for (p = 0; p < numPoints; ++p) { 1455 const PetscInt point = points[p]; 1456 DMPolytopeType ct; 1457 DMPolytopeType *rct; 1458 PetscInt *rsize, *rcone, *rornt; 1459 PetscInt Nct, n, r, pNew=0; 1460 1461 PetscCall(DMPlexGetCellType(dm, point, &ct)); 1462 PetscCall(DMPlexTransformCellTransform(tr, ct, point, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1463 for (n = 0; n < Nct; ++n) { 1464 for (r = 0; r < rsize[n]; ++r) { 1465 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], point, r, &pNew)); 1466 PetscCall(DMLabelSetValue(labelNew, pNew, values[val])); 1467 } 1468 } 1469 } 1470 PetscCall(ISRestoreIndices(pointIS, &points)); 1471 PetscCall(ISDestroy(&pointIS)); 1472 } 1473 PetscCall(ISRestoreIndices(valueIS, &values)); 1474 PetscCall(ISDestroy(&valueIS)); 1475 PetscFunctionReturn(0); 1476 } 1477 1478 static PetscErrorCode DMPlexTransformCreateLabels(DMPlexTransform tr, DM rdm) 1479 { 1480 DM dm; 1481 PetscInt numLabels, l; 1482 1483 PetscFunctionBegin; 1484 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1485 PetscCall(DMGetNumLabels(dm, &numLabels)); 1486 for (l = 0; l < numLabels; ++l) { 1487 DMLabel label, labelNew; 1488 const char *lname; 1489 PetscBool isDepth, isCellType; 1490 1491 PetscCall(DMGetLabelName(dm, l, &lname)); 1492 PetscCall(PetscStrcmp(lname, "depth", &isDepth)); 1493 if (isDepth) continue; 1494 PetscCall(PetscStrcmp(lname, "celltype", &isCellType)); 1495 if (isCellType) continue; 1496 PetscCall(DMCreateLabel(rdm, lname)); 1497 PetscCall(DMGetLabel(dm, lname, &label)); 1498 PetscCall(DMGetLabel(rdm, lname, &labelNew)); 1499 PetscCall(RefineLabel_Internal(tr, label, labelNew)); 1500 } 1501 PetscFunctionReturn(0); 1502 } 1503 1504 /* This refines the labels which define regions for fields and DSes since they are not in the list of labels for the DM */ 1505 PetscErrorCode DMPlexTransformCreateDiscLabels(DMPlexTransform tr, DM rdm) 1506 { 1507 DM dm; 1508 PetscInt Nf, f, Nds, s; 1509 1510 PetscFunctionBegin; 1511 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1512 PetscCall(DMGetNumFields(dm, &Nf)); 1513 for (f = 0; f < Nf; ++f) { 1514 DMLabel label, labelNew; 1515 PetscObject obj; 1516 const char *lname; 1517 1518 PetscCall(DMGetField(rdm, f, &label, &obj)); 1519 if (!label) continue; 1520 PetscCall(PetscObjectGetName((PetscObject) label, &lname)); 1521 PetscCall(DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew)); 1522 PetscCall(RefineLabel_Internal(tr, label, labelNew)); 1523 PetscCall(DMSetField_Internal(rdm, f, labelNew, obj)); 1524 PetscCall(DMLabelDestroy(&labelNew)); 1525 } 1526 PetscCall(DMGetNumDS(dm, &Nds)); 1527 for (s = 0; s < Nds; ++s) { 1528 DMLabel label, labelNew; 1529 const char *lname; 1530 1531 PetscCall(DMGetRegionNumDS(rdm, s, &label, NULL, NULL)); 1532 if (!label) continue; 1533 PetscCall(PetscObjectGetName((PetscObject) label, &lname)); 1534 PetscCall(DMLabelCreate(PETSC_COMM_SELF, lname, &labelNew)); 1535 PetscCall(RefineLabel_Internal(tr, label, labelNew)); 1536 PetscCall(DMSetRegionNumDS(rdm, s, labelNew, NULL, NULL)); 1537 PetscCall(DMLabelDestroy(&labelNew)); 1538 } 1539 PetscFunctionReturn(0); 1540 } 1541 1542 static PetscErrorCode DMPlexTransformCreateSF(DMPlexTransform tr, DM rdm) 1543 { 1544 DM dm; 1545 PetscSF sf, sfNew; 1546 PetscInt numRoots, numLeaves, numLeavesNew = 0, l, m; 1547 const PetscInt *localPoints; 1548 const PetscSFNode *remotePoints; 1549 PetscInt *localPointsNew; 1550 PetscSFNode *remotePointsNew; 1551 PetscInt pStartNew, pEndNew, pNew; 1552 /* Brute force algorithm */ 1553 PetscSF rsf; 1554 PetscSection s; 1555 const PetscInt *rootdegree; 1556 PetscInt *rootPointsNew, *remoteOffsets; 1557 PetscInt numPointsNew, pStart, pEnd, p; 1558 1559 PetscFunctionBegin; 1560 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1561 PetscCall(DMPlexGetChart(rdm, &pStartNew, &pEndNew)); 1562 PetscCall(DMGetPointSF(dm, &sf)); 1563 PetscCall(DMGetPointSF(rdm, &sfNew)); 1564 /* Calculate size of new SF */ 1565 PetscCall(PetscSFGetGraph(sf, &numRoots, &numLeaves, &localPoints, &remotePoints)); 1566 if (numRoots < 0) PetscFunctionReturn(0); 1567 for (l = 0; l < numLeaves; ++l) { 1568 const PetscInt p = localPoints[l]; 1569 DMPolytopeType ct; 1570 DMPolytopeType *rct; 1571 PetscInt *rsize, *rcone, *rornt; 1572 PetscInt Nct, n; 1573 1574 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1575 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1576 for (n = 0; n < Nct; ++n) { 1577 numLeavesNew += rsize[n]; 1578 } 1579 } 1580 /* Send new root point numbers 1581 It is possible to optimize for regular transforms by sending only the cell type offsets, but it seems a needless complication 1582 */ 1583 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1584 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) dm), &s)); 1585 PetscCall(PetscSectionSetChart(s, pStart, pEnd)); 1586 for (p = pStart; p < pEnd; ++p) { 1587 DMPolytopeType ct; 1588 DMPolytopeType *rct; 1589 PetscInt *rsize, *rcone, *rornt; 1590 PetscInt Nct, n; 1591 1592 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1593 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1594 for (n = 0; n < Nct; ++n) { 1595 PetscCall(PetscSectionAddDof(s, p, rsize[n])); 1596 } 1597 } 1598 PetscCall(PetscSectionSetUp(s)); 1599 PetscCall(PetscSectionGetStorageSize(s, &numPointsNew)); 1600 PetscCall(PetscSFCreateRemoteOffsets(sf, s, s, &remoteOffsets)); 1601 PetscCall(PetscSFCreateSectionSF(sf, s, remoteOffsets, s, &rsf)); 1602 PetscCall(PetscFree(remoteOffsets)); 1603 PetscCall(PetscSFComputeDegreeBegin(sf, &rootdegree)); 1604 PetscCall(PetscSFComputeDegreeEnd(sf, &rootdegree)); 1605 PetscCall(PetscMalloc1(numPointsNew, &rootPointsNew)); 1606 for (p = 0; p < numPointsNew; ++p) rootPointsNew[p] = -1; 1607 for (p = pStart; p < pEnd; ++p) { 1608 DMPolytopeType ct; 1609 DMPolytopeType *rct; 1610 PetscInt *rsize, *rcone, *rornt; 1611 PetscInt Nct, n, r, off; 1612 1613 if (!rootdegree[p-pStart]) continue; 1614 PetscCall(PetscSectionGetOffset(s, p, &off)); 1615 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1616 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1617 for (n = 0, m = 0; n < Nct; ++n) { 1618 for (r = 0; r < rsize[n]; ++r, ++m) { 1619 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &pNew)); 1620 rootPointsNew[off+m] = pNew; 1621 } 1622 } 1623 } 1624 PetscCall(PetscSFBcastBegin(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE)); 1625 PetscCall(PetscSFBcastEnd(rsf, MPIU_INT, rootPointsNew, rootPointsNew,MPI_REPLACE)); 1626 PetscCall(PetscSFDestroy(&rsf)); 1627 PetscCall(PetscMalloc1(numLeavesNew, &localPointsNew)); 1628 PetscCall(PetscMalloc1(numLeavesNew, &remotePointsNew)); 1629 for (l = 0, m = 0; l < numLeaves; ++l) { 1630 const PetscInt p = localPoints[l]; 1631 DMPolytopeType ct; 1632 DMPolytopeType *rct; 1633 PetscInt *rsize, *rcone, *rornt; 1634 PetscInt Nct, n, r, q, off; 1635 1636 PetscCall(PetscSectionGetOffset(s, p, &off)); 1637 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1638 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1639 for (n = 0, q = 0; n < Nct; ++n) { 1640 for (r = 0; r < rsize[n]; ++r, ++m, ++q) { 1641 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &pNew)); 1642 localPointsNew[m] = pNew; 1643 remotePointsNew[m].index = rootPointsNew[off+q]; 1644 remotePointsNew[m].rank = remotePoints[l].rank; 1645 } 1646 } 1647 } 1648 PetscCall(PetscSectionDestroy(&s)); 1649 PetscCall(PetscFree(rootPointsNew)); 1650 /* SF needs sorted leaves to correctly calculate Gather */ 1651 { 1652 PetscSFNode *rp, *rtmp; 1653 PetscInt *lp, *idx, *ltmp, i; 1654 1655 PetscCall(PetscMalloc1(numLeavesNew, &idx)); 1656 PetscCall(PetscMalloc1(numLeavesNew, &lp)); 1657 PetscCall(PetscMalloc1(numLeavesNew, &rp)); 1658 for (i = 0; i < numLeavesNew; ++i) { 1659 PetscCheck(!(localPointsNew[i] < pStartNew) && !(localPointsNew[i] >= pEndNew),PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Local SF point %" PetscInt_FMT " (%" PetscInt_FMT ") not in [%" PetscInt_FMT ", %" PetscInt_FMT ")", localPointsNew[i], i, pStartNew, pEndNew); 1660 idx[i] = i; 1661 } 1662 PetscCall(PetscSortIntWithPermutation(numLeavesNew, localPointsNew, idx)); 1663 for (i = 0; i < numLeavesNew; ++i) { 1664 lp[i] = localPointsNew[idx[i]]; 1665 rp[i] = remotePointsNew[idx[i]]; 1666 } 1667 ltmp = localPointsNew; 1668 localPointsNew = lp; 1669 rtmp = remotePointsNew; 1670 remotePointsNew = rp; 1671 PetscCall(PetscFree(idx)); 1672 PetscCall(PetscFree(ltmp)); 1673 PetscCall(PetscFree(rtmp)); 1674 } 1675 PetscCall(PetscSFSetGraph(sfNew, pEndNew-pStartNew, numLeavesNew, localPointsNew, PETSC_OWN_POINTER, remotePointsNew, PETSC_OWN_POINTER)); 1676 PetscFunctionReturn(0); 1677 } 1678 1679 /* 1680 DMPlexCellRefinerMapLocalizedCoordinates - Given a cell of type ct with localized coordinates x, we generate localized coordinates xr for subcell r of type rct. 1681 1682 Not collective 1683 1684 Input Parameters: 1685 + cr - The DMPlexCellRefiner 1686 . ct - The type of the parent cell 1687 . rct - The type of the produced cell 1688 . r - The index of the produced cell 1689 - x - The localized coordinates for the parent cell 1690 1691 Output Parameter: 1692 . xr - The localized coordinates for the produced cell 1693 1694 Level: developer 1695 1696 .seealso: DMPlexCellRefinerSetCoordinates() 1697 */ 1698 static PetscErrorCode DMPlexTransformMapLocalizedCoordinates(DMPlexTransform tr, DMPolytopeType ct, DMPolytopeType rct, PetscInt r, const PetscScalar x[], PetscScalar xr[]) 1699 { 1700 PetscFE fe = NULL; 1701 PetscInt cdim, v, *subcellV; 1702 1703 PetscFunctionBegin; 1704 PetscCall(DMPlexTransformGetCoordinateFE(tr, ct, &fe)); 1705 PetscCall(DMPlexTransformGetSubcellVertices(tr, ct, rct, r, &subcellV)); 1706 PetscCall(PetscFEGetNumComponents(fe, &cdim)); 1707 for (v = 0; v < DMPolytopeTypeGetNumVertices(rct); ++v) { 1708 PetscCall(PetscFEInterpolate_Static(fe, x, tr->refGeom[ct], subcellV[v], &xr[v*cdim])); 1709 } 1710 PetscFunctionReturn(0); 1711 } 1712 1713 static PetscErrorCode DMPlexTransformSetCoordinates(DMPlexTransform tr, DM rdm) 1714 { 1715 DM dm, cdm; 1716 PetscSection coordSection, coordSectionNew; 1717 Vec coordsLocal, coordsLocalNew; 1718 const PetscScalar *coords; 1719 PetscScalar *coordsNew; 1720 const DMBoundaryType *bd; 1721 const PetscReal *maxCell, *L; 1722 PetscBool isperiodic, localizeVertices = PETSC_FALSE, localizeCells = PETSC_FALSE; 1723 PetscInt dE, dEo, d, cStart, cEnd, c, vStartNew, vEndNew, v, pStart, pEnd, p, ocStart, ocEnd; 1724 1725 PetscFunctionBegin; 1726 PetscCall(DMPlexTransformGetDM(tr, &dm)); 1727 PetscCall(DMGetCoordinateDM(dm, &cdm)); 1728 PetscCall(DMGetPeriodicity(dm, &isperiodic, &maxCell, &L, &bd)); 1729 /* Determine if we need to localize coordinates when generating them */ 1730 if (isperiodic) { 1731 localizeVertices = PETSC_TRUE; 1732 if (!maxCell) { 1733 PetscBool localized; 1734 PetscCall(DMGetCoordinatesLocalized(dm, &localized)); 1735 PetscCheck(localized,PetscObjectComm((PetscObject) dm), PETSC_ERR_USER, "Cannot refine a periodic mesh if coordinates have not been localized"); 1736 localizeCells = PETSC_TRUE; 1737 } 1738 } 1739 1740 PetscCall(DMGetCoordinateSection(dm, &coordSection)); 1741 PetscCall(PetscSectionGetFieldComponents(coordSection, 0, &dEo)); 1742 if (maxCell) { 1743 PetscReal maxCellNew[3]; 1744 1745 for (d = 0; d < dEo; ++d) maxCellNew[d] = maxCell[d]/2.0; 1746 PetscCall(DMSetPeriodicity(rdm, isperiodic, maxCellNew, L, bd)); 1747 } else { 1748 PetscCall(DMSetPeriodicity(rdm, isperiodic, maxCell, L, bd)); 1749 } 1750 PetscCall(DMGetCoordinateDim(rdm, &dE)); 1751 PetscCall(PetscSectionCreate(PetscObjectComm((PetscObject) rdm), &coordSectionNew)); 1752 PetscCall(PetscSectionSetNumFields(coordSectionNew, 1)); 1753 PetscCall(PetscSectionSetFieldComponents(coordSectionNew, 0, dE)); 1754 PetscCall(DMPlexGetDepthStratum(rdm, 0, &vStartNew, &vEndNew)); 1755 if (localizeCells) PetscCall(PetscSectionSetChart(coordSectionNew, 0, vEndNew)); 1756 else PetscCall(PetscSectionSetChart(coordSectionNew, vStartNew, vEndNew)); 1757 1758 /* Localization should be inherited */ 1759 /* Stefano calculates parent cells for each new cell for localization */ 1760 /* Localized cells need coordinates of closure */ 1761 for (v = vStartNew; v < vEndNew; ++v) { 1762 PetscCall(PetscSectionSetDof(coordSectionNew, v, dE)); 1763 PetscCall(PetscSectionSetFieldDof(coordSectionNew, v, 0, dE)); 1764 } 1765 if (localizeCells) { 1766 PetscCall(DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd)); 1767 for (c = cStart; c < cEnd; ++c) { 1768 PetscInt dof; 1769 1770 PetscCall(PetscSectionGetDof(coordSection, c, &dof)); 1771 if (dof) { 1772 DMPolytopeType ct; 1773 DMPolytopeType *rct; 1774 PetscInt *rsize, *rcone, *rornt; 1775 PetscInt dim, cNew, Nct, n, r; 1776 1777 PetscCall(DMPlexGetCellType(dm, c, &ct)); 1778 dim = DMPolytopeTypeGetDim(ct); 1779 PetscCall(DMPlexTransformCellTransform(tr, ct, c, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1780 /* This allows for different cell types */ 1781 for (n = 0; n < Nct; ++n) { 1782 if (dim != DMPolytopeTypeGetDim(rct[n])) continue; 1783 for (r = 0; r < rsize[n]; ++r) { 1784 PetscInt *closure = NULL; 1785 PetscInt clSize, cl, Nv = 0; 1786 1787 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], c, r, &cNew)); 1788 PetscCall(DMPlexGetTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure)); 1789 for (cl = 0; cl < clSize*2; cl += 2) {if ((closure[cl] >= vStartNew) && (closure[cl] < vEndNew)) ++Nv;} 1790 PetscCall(DMPlexRestoreTransitiveClosure(rdm, cNew, PETSC_TRUE, &clSize, &closure)); 1791 PetscCall(PetscSectionSetDof(coordSectionNew, cNew, Nv * dE)); 1792 PetscCall(PetscSectionSetFieldDof(coordSectionNew, cNew, 0, Nv * dE)); 1793 } 1794 } 1795 } 1796 } 1797 } 1798 PetscCall(PetscSectionSetUp(coordSectionNew)); 1799 PetscCall(DMViewFromOptions(dm, NULL, "-coarse_dm_view")); 1800 PetscCall(DMSetCoordinateSection(rdm, PETSC_DETERMINE, coordSectionNew)); 1801 { 1802 VecType vtype; 1803 PetscInt coordSizeNew, bs; 1804 const char *name; 1805 1806 PetscCall(DMGetCoordinatesLocal(dm, &coordsLocal)); 1807 PetscCall(VecCreate(PETSC_COMM_SELF, &coordsLocalNew)); 1808 PetscCall(PetscSectionGetStorageSize(coordSectionNew, &coordSizeNew)); 1809 PetscCall(VecSetSizes(coordsLocalNew, coordSizeNew, PETSC_DETERMINE)); 1810 PetscCall(PetscObjectGetName((PetscObject) coordsLocal, &name)); 1811 PetscCall(PetscObjectSetName((PetscObject) coordsLocalNew, name)); 1812 PetscCall(VecGetBlockSize(coordsLocal, &bs)); 1813 PetscCall(VecSetBlockSize(coordsLocalNew, dEo == dE ? bs : dE)); 1814 PetscCall(VecGetType(coordsLocal, &vtype)); 1815 PetscCall(VecSetType(coordsLocalNew, vtype)); 1816 } 1817 PetscCall(VecGetArrayRead(coordsLocal, &coords)); 1818 PetscCall(VecGetArray(coordsLocalNew, &coordsNew)); 1819 PetscCall(PetscSectionGetChart(coordSection, &ocStart, &ocEnd)); 1820 PetscCall(DMPlexGetChart(dm, &pStart, &pEnd)); 1821 /* First set coordinates for vertices*/ 1822 for (p = pStart; p < pEnd; ++p) { 1823 DMPolytopeType ct; 1824 DMPolytopeType *rct; 1825 PetscInt *rsize, *rcone, *rornt; 1826 PetscInt Nct, n, r; 1827 PetscBool hasVertex = PETSC_FALSE, isLocalized = PETSC_FALSE; 1828 1829 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1830 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1831 for (n = 0; n < Nct; ++n) { 1832 if (rct[n] == DM_POLYTOPE_POINT) {hasVertex = PETSC_TRUE; break;} 1833 } 1834 if (localizeVertices && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) { 1835 PetscInt dof; 1836 PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 1837 if (dof) isLocalized = PETSC_TRUE; 1838 } 1839 if (hasVertex) { 1840 const PetscScalar *icoords = NULL; 1841 PetscScalar *pcoords = NULL; 1842 PetscInt Nc, Nv, v, d; 1843 1844 PetscCall(DMPlexVecGetClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords)); 1845 1846 icoords = pcoords; 1847 Nv = Nc/dEo; 1848 if (ct != DM_POLYTOPE_POINT) { 1849 if (localizeVertices) { 1850 PetscScalar anchor[3]; 1851 1852 for (d = 0; d < dEo; ++d) anchor[d] = pcoords[d]; 1853 if (!isLocalized) { 1854 for (v = 0; v < Nv; ++v) PetscCall(DMLocalizeCoordinate_Internal(dm, dEo, anchor, &pcoords[v*dEo], &pcoords[v*dEo])); 1855 } else { 1856 Nv = Nc/(2*dEo); 1857 for (v = Nv; v < Nv*2; ++v) PetscCall(DMLocalizeCoordinate_Internal(dm, dEo, anchor, &pcoords[v*dEo], &pcoords[v*dEo])); 1858 } 1859 } 1860 } 1861 for (n = 0; n < Nct; ++n) { 1862 if (rct[n] != DM_POLYTOPE_POINT) continue; 1863 for (r = 0; r < rsize[n]; ++r) { 1864 PetscScalar vcoords[3]; 1865 PetscInt vNew, off; 1866 1867 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &vNew)); 1868 PetscCall(PetscSectionGetOffset(coordSectionNew, vNew, &off)); 1869 PetscCall(DMPlexTransformMapCoordinates(tr, ct, rct[n], p, r, Nv, dEo, icoords, vcoords)); 1870 PetscCall(DMPlexSnapToGeomModel(dm, p, dE, vcoords, &coordsNew[off])); 1871 } 1872 } 1873 PetscCall(DMPlexVecRestoreClosure(dm, coordSection, coordsLocal, p, &Nc, &pcoords)); 1874 } 1875 } 1876 /* Then set coordinates for cells by localizing */ 1877 for (p = pStart; p < pEnd; ++p) { 1878 DMPolytopeType ct; 1879 DMPolytopeType *rct; 1880 PetscInt *rsize, *rcone, *rornt; 1881 PetscInt Nct, n, r; 1882 PetscBool isLocalized = PETSC_FALSE; 1883 1884 PetscCall(DMPlexGetCellType(dm, p, &ct)); 1885 PetscCall(DMPlexTransformCellTransform(tr, ct, p, NULL, &Nct, &rct, &rsize, &rcone, &rornt)); 1886 if (localizeCells && ct != DM_POLYTOPE_POINT && (p >= ocStart) && (p < ocEnd)) { 1887 PetscInt dof; 1888 PetscCall(PetscSectionGetDof(coordSection, p, &dof)); 1889 if (dof) isLocalized = PETSC_TRUE; 1890 } 1891 if (isLocalized) { 1892 const PetscScalar *pcoords; 1893 1894 PetscCall(DMPlexPointLocalRead(cdm, p, coords, &pcoords)); 1895 for (n = 0; n < Nct; ++n) { 1896 const PetscInt Nr = rsize[n]; 1897 1898 if (DMPolytopeTypeGetDim(ct) != DMPolytopeTypeGetDim(rct[n])) continue; 1899 for (r = 0; r < Nr; ++r) { 1900 PetscInt pNew, offNew; 1901 1902 /* It looks like Stefano and Lisandro are allowing localized coordinates without defining the periodic boundary, which means that 1903 DMLocalizeCoordinate_Internal() will not work. Localized coordinates will have to have obtained by the affine map of the larger 1904 cell to the ones it produces. */ 1905 PetscCall(DMPlexTransformGetTargetPoint(tr, ct, rct[n], p, r, &pNew)); 1906 PetscCall(PetscSectionGetOffset(coordSectionNew, pNew, &offNew)); 1907 PetscCall(DMPlexTransformMapLocalizedCoordinates(tr, ct, rct[n], r, pcoords, &coordsNew[offNew])); 1908 } 1909 } 1910 } 1911 } 1912 PetscCall(VecRestoreArrayRead(coordsLocal, &coords)); 1913 PetscCall(VecRestoreArray(coordsLocalNew, &coordsNew)); 1914 PetscCall(DMSetCoordinatesLocal(rdm, coordsLocalNew)); 1915 /* TODO Stefano has a final reduction if some hybrid coordinates cannot be found. (needcoords) Should not be needed. */ 1916 PetscCall(VecDestroy(&coordsLocalNew)); 1917 PetscCall(PetscSectionDestroy(&coordSectionNew)); 1918 if (!localizeCells) PetscCall(DMLocalizeCoordinates(rdm)); 1919 PetscFunctionReturn(0); 1920 } 1921 1922 PetscErrorCode DMPlexTransformApply(DMPlexTransform tr, DM dm, DM *tdm) 1923 { 1924 DM rdm; 1925 DMPlexInterpolatedFlag interp; 1926 1927 PetscFunctionBegin; 1928 PetscValidHeaderSpecific(tr, DMPLEXTRANSFORM_CLASSID, 1); 1929 PetscValidHeaderSpecific(dm, DM_CLASSID, 2); 1930 PetscValidPointer(tdm, 3); 1931 PetscCall(DMPlexTransformSetDM(tr, dm)); 1932 1933 PetscCall(DMCreate(PetscObjectComm((PetscObject)dm), &rdm)); 1934 PetscCall(DMSetType(rdm, DMPLEX)); 1935 PetscCall(DMPlexTransformSetDimensions(tr, dm, rdm)); 1936 /* Calculate number of new points of each depth */ 1937 PetscCall(DMPlexIsInterpolated(dm, &interp)); 1938 PetscCheck(interp == DMPLEX_INTERPOLATED_FULL,PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Mesh must be fully interpolated for regular refinement"); 1939 /* Step 1: Set chart */ 1940 PetscCall(DMPlexSetChart(rdm, 0, tr->ctStartNew[tr->ctOrderNew[DM_NUM_POLYTOPES]])); 1941 /* Step 2: Set cone/support sizes (automatically stratifies) */ 1942 PetscCall(DMPlexTransformSetConeSizes(tr, rdm)); 1943 /* Step 3: Setup refined DM */ 1944 PetscCall(DMSetUp(rdm)); 1945 /* Step 4: Set cones and supports (automatically symmetrizes) */ 1946 PetscCall(DMPlexTransformSetCones(tr, rdm)); 1947 /* Step 5: Create pointSF */ 1948 PetscCall(DMPlexTransformCreateSF(tr, rdm)); 1949 /* Step 6: Create labels */ 1950 PetscCall(DMPlexTransformCreateLabels(tr, rdm)); 1951 /* Step 7: Set coordinates */ 1952 PetscCall(DMPlexTransformSetCoordinates(tr, rdm)); 1953 PetscCall(DMPlexCopy_Internal(dm, PETSC_TRUE, rdm)); 1954 *tdm = rdm; 1955 PetscFunctionReturn(0); 1956 } 1957 1958 PetscErrorCode DMPlexTransformAdaptLabel(DM dm, PETSC_UNUSED Vec metric, DMLabel adaptLabel, PETSC_UNUSED DMLabel rgLabel, DM *rdm) 1959 { 1960 DMPlexTransform tr; 1961 DM cdm, rcdm; 1962 const char *prefix; 1963 1964 PetscFunctionBegin; 1965 PetscCall(DMPlexTransformCreate(PetscObjectComm((PetscObject) dm), &tr)); 1966 PetscCall(PetscObjectGetOptionsPrefix((PetscObject) dm, &prefix)); 1967 PetscCall(PetscObjectSetOptionsPrefix((PetscObject) tr, prefix)); 1968 PetscCall(DMPlexTransformSetDM(tr, dm)); 1969 PetscCall(DMPlexTransformSetFromOptions(tr)); 1970 PetscCall(DMPlexTransformSetActive(tr, adaptLabel)); 1971 PetscCall(DMPlexTransformSetUp(tr)); 1972 PetscCall(PetscObjectViewFromOptions((PetscObject) tr, NULL, "-dm_plex_transform_view")); 1973 PetscCall(DMPlexTransformApply(tr, dm, rdm)); 1974 PetscCall(DMCopyDisc(dm, *rdm)); 1975 PetscCall(DMGetCoordinateDM(dm, &cdm)); 1976 PetscCall(DMGetCoordinateDM(*rdm, &rcdm)); 1977 PetscCall(DMCopyDisc(cdm, rcdm)); 1978 PetscCall(DMPlexTransformCreateDiscLabels(tr, *rdm)); 1979 PetscCall(DMCopyDisc(dm, *rdm)); 1980 PetscCall(DMPlexTransformDestroy(&tr)); 1981 ((DM_Plex *) (*rdm)->data)->useHashLocation = ((DM_Plex *) dm->data)->useHashLocation; 1982 PetscFunctionReturn(0); 1983 } 1984