1 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <../src/sys/utils/hash.h> 3 #include <petsc-private/isimpl.h> 4 #include <petscsf.h> 5 6 /** hierarchy routines */ 7 8 #undef __FUNCT__ 9 #define __FUNCT__ "DMPlexSetReferenceTree" 10 /*@ 11 DMPlexSetReferenceTree - set the reference tree for hierarchically non-conforming meshes. 12 13 Not collective 14 15 Input Parameters: 16 + dm - The DMPlex object 17 - ref - The reference tree DMPlex object 18 19 Level: intermediate 20 21 .seealso: DMPlexGetReferenceTree(), DMPlexCreateDefaultReferenceTree() 22 @*/ 23 PetscErrorCode DMPlexSetReferenceTree(DM dm, DM ref) 24 { 25 DM_Plex *mesh = (DM_Plex *)dm->data; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 30 PetscValidHeaderSpecific(ref, DM_CLASSID, 2); 31 ierr = PetscObjectReference((PetscObject)ref);CHKERRQ(ierr); 32 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 33 mesh->referenceTree = ref; 34 PetscFunctionReturn(0); 35 } 36 37 #undef __FUNCT__ 38 #define __FUNCT__ "DMPlexGetReferenceTree" 39 /*@ 40 DMPlexGetReferenceTree - get the reference tree for hierarchically non-conforming meshes. 41 42 Not collective 43 44 Input Parameters: 45 . dm - The DMPlex object 46 47 Output Parameters 48 . ref - The reference tree DMPlex object 49 50 Level: intermediate 51 52 .seealso: DMPlexSetReferenceTree(), DMPlexCreateDefaultReferenceTree() 53 @*/ 54 PetscErrorCode DMPlexGetReferenceTree(DM dm, DM *ref) 55 { 56 DM_Plex *mesh = (DM_Plex *)dm->data; 57 58 PetscFunctionBegin; 59 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 60 PetscValidPointer(ref,2); 61 *ref = mesh->referenceTree; 62 PetscFunctionReturn(0); 63 } 64 65 #undef __FUNCT__ 66 #define __FUNCT__ "DMPlexCreateDefaultReferenceTree" 67 /*@ 68 DMPlexCreateDefaultReferenceTree - create a reference tree for isotropic hierarchical mesh refinement. 69 70 Collective on comm 71 72 Input Parameters: 73 + comm - the MPI communicator 74 . dim - the spatial dimension 75 - simplex - Flag for simplex, otherwise use a tensor-product cell 76 77 Output Parameters: 78 . ref - the reference tree DMPlex object 79 80 Level: intermediate 81 82 .keywords: reference cell 83 .seealso: DMPlexSetReferenceTree(), DMPlexGetReferenceTree() 84 @*/ 85 PetscErrorCode DMPlexCreateDefaultReferenceTree(MPI_Comm comm, PetscInt dim, PetscBool simplex, DM *ref) 86 { 87 DM K, Kref; 88 PetscInt p, pStart, pEnd, pRefStart, pRefEnd, d, offset, parentSize, *parents, *childIDs; 89 PetscInt *permvals, *unionCones, *coneSizes, *unionOrientations, numUnionPoints, *numDimPoints, numCones, numVerts; 90 DMLabel identity, identityRef; 91 PetscSection unionSection, unionConeSection, parentSection; 92 PetscScalar *unionCoords; 93 IS perm; 94 PetscErrorCode ierr; 95 96 PetscFunctionBegin; 97 /* create a reference element */ 98 ierr = DMPlexCreateReferenceCell(comm, dim, simplex, &K);CHKERRQ(ierr); 99 ierr = DMPlexCreateLabel(K, "identity");CHKERRQ(ierr); 100 ierr = DMPlexGetLabel(K, "identity", &identity);CHKERRQ(ierr); 101 ierr = DMPlexGetChart(K, &pStart, &pEnd);CHKERRQ(ierr); 102 for (p = pStart; p < pEnd; p++) { 103 ierr = DMLabelSetValue(identity, p, p);CHKERRQ(ierr); 104 } 105 /* refine it */ 106 ierr = DMRefine(K,comm,&Kref);CHKERRQ(ierr); 107 108 /* the reference tree is the union of these two, without duplicating 109 * points that appear in both */ 110 ierr = DMPlexGetLabel(Kref, "identity", &identityRef);CHKERRQ(ierr); 111 ierr = DMPlexGetChart(Kref, &pRefStart, &pRefEnd);CHKERRQ(ierr); 112 ierr = PetscSectionCreate(comm, &unionSection);CHKERRQ(ierr); 113 ierr = PetscSectionSetChart(unionSection, 0, (pEnd - pStart) + (pRefEnd - pRefStart));CHKERRQ(ierr); 114 /* count points that will go in the union */ 115 for (p = pStart; p < pEnd; p++) { 116 ierr = PetscSectionSetDof(unionSection, p - pStart, 1);CHKERRQ(ierr); 117 } 118 for (p = pRefStart; p < pRefEnd; p++) { 119 PetscInt q, qSize; 120 ierr = DMLabelGetValue(identityRef, p, &q);CHKERRQ(ierr); 121 ierr = DMLabelGetStratumSize(identityRef, q, &qSize);CHKERRQ(ierr); 122 if (qSize > 1) { 123 ierr = PetscSectionSetDof(unionSection, p - pRefStart + (pEnd - pStart), 1);CHKERRQ(ierr); 124 } 125 } 126 ierr = PetscMalloc1((pEnd - pStart) + (pRefEnd - pRefStart),&permvals);CHKERRQ(ierr); 127 offset = 0; 128 /* stratify points in the union by topological dimension */ 129 for (d = 0; d <= dim; d++) { 130 PetscInt cStart, cEnd, c; 131 132 ierr = DMPlexGetHeightStratum(K, d, &cStart, &cEnd);CHKERRQ(ierr); 133 for (c = cStart; c < cEnd; c++) { 134 permvals[offset++] = c; 135 } 136 137 ierr = DMPlexGetHeightStratum(Kref, d, &cStart, &cEnd);CHKERRQ(ierr); 138 for (c = cStart; c < cEnd; c++) { 139 permvals[offset++] = c + (pEnd - pStart); 140 } 141 } 142 ierr = ISCreateGeneral(comm, (pEnd - pStart) + (pRefEnd - pRefStart), permvals, PETSC_OWN_POINTER, &perm);CHKERRQ(ierr); 143 ierr = PetscSectionSetPermutation(unionSection,perm);CHKERRQ(ierr); 144 ierr = PetscSectionSetUp(unionSection);CHKERRQ(ierr); 145 ierr = PetscSectionGetStorageSize(unionSection,&numUnionPoints);CHKERRQ(ierr); 146 ierr = PetscMalloc2(numUnionPoints,&coneSizes,dim+1,&numDimPoints);CHKERRQ(ierr); 147 /* count dimension points */ 148 for (d = 0; d <= dim; d++) { 149 PetscInt cStart, cOff, cOff2; 150 ierr = DMPlexGetHeightStratum(K,d,&cStart,NULL);CHKERRQ(ierr); 151 ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff);CHKERRQ(ierr); 152 if (d < dim) { 153 ierr = DMPlexGetHeightStratum(K,d+1,&cStart,NULL);CHKERRQ(ierr); 154 ierr = PetscSectionGetOffset(unionSection,cStart-pStart,&cOff2);CHKERRQ(ierr); 155 } 156 else { 157 cOff2 = numUnionPoints; 158 } 159 numDimPoints[dim - d] = cOff2 - cOff; 160 } 161 ierr = PetscSectionCreate(comm, &unionConeSection);CHKERRQ(ierr); 162 ierr = PetscSectionSetChart(unionConeSection, 0, numUnionPoints);CHKERRQ(ierr); 163 /* count the cones in the union */ 164 for (p = pStart; p < pEnd; p++) { 165 PetscInt dof, uOff; 166 167 ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 168 ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 169 ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 170 coneSizes[uOff] = dof; 171 } 172 for (p = pRefStart; p < pRefEnd; p++) { 173 PetscInt dof, uDof, uOff; 174 175 ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 176 ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 177 ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 178 if (uDof) { 179 ierr = PetscSectionSetDof(unionConeSection, uOff, dof);CHKERRQ(ierr); 180 coneSizes[uOff] = dof; 181 } 182 } 183 ierr = PetscSectionSetUp(unionConeSection);CHKERRQ(ierr); 184 ierr = PetscSectionGetStorageSize(unionConeSection,&numCones);CHKERRQ(ierr); 185 ierr = PetscMalloc2(numCones,&unionCones,numCones,&unionOrientations);CHKERRQ(ierr); 186 /* write the cones in the union */ 187 for (p = pStart; p < pEnd; p++) { 188 PetscInt dof, uOff, c, cOff; 189 const PetscInt *cone, *orientation; 190 191 ierr = DMPlexGetConeSize(K, p, &dof);CHKERRQ(ierr); 192 ierr = DMPlexGetCone(K, p, &cone);CHKERRQ(ierr); 193 ierr = DMPlexGetConeOrientation(K, p, &orientation);CHKERRQ(ierr); 194 ierr = PetscSectionGetOffset(unionSection, p - pStart,&uOff);CHKERRQ(ierr); 195 ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 196 for (c = 0; c < dof; c++) { 197 PetscInt e, eOff; 198 e = cone[c]; 199 ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 200 unionCones[cOff + c] = eOff; 201 unionOrientations[cOff + c] = orientation[c]; 202 } 203 } 204 for (p = pRefStart; p < pRefEnd; p++) { 205 PetscInt dof, uDof, uOff, c, cOff; 206 const PetscInt *cone, *orientation; 207 208 ierr = DMPlexGetConeSize(Kref, p, &dof);CHKERRQ(ierr); 209 ierr = DMPlexGetCone(Kref, p, &cone);CHKERRQ(ierr); 210 ierr = DMPlexGetConeOrientation(Kref, p, &orientation);CHKERRQ(ierr); 211 ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 212 ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 213 if (uDof) { 214 ierr = PetscSectionGetOffset(unionConeSection,uOff,&cOff);CHKERRQ(ierr); 215 for (c = 0; c < dof; c++) { 216 PetscInt e, eOff, eDof; 217 218 e = cone[c]; 219 ierr = PetscSectionGetDof(unionSection, e - pRefStart + (pEnd - pStart),&eDof);CHKERRQ(ierr); 220 if (eDof) { 221 ierr = PetscSectionGetOffset(unionSection, e - pRefStart + (pEnd - pStart), &eOff);CHKERRQ(ierr); 222 } 223 else { 224 ierr = DMLabelGetValue(identityRef, e, &e);CHKERRQ(ierr); 225 ierr = PetscSectionGetOffset(unionSection, e - pStart, &eOff);CHKERRQ(ierr); 226 } 227 unionCones[cOff + c] = eOff; 228 unionOrientations[cOff + c] = orientation[c]; 229 } 230 } 231 } 232 /* get the coordinates */ 233 { 234 PetscInt vStart, vEnd, vRefStart, vRefEnd, v, vDof, vOff; 235 PetscSection KcoordsSec, KrefCoordsSec; 236 Vec KcoordsVec, KrefCoordsVec; 237 PetscScalar *Kcoords; 238 239 DMGetCoordinateSection(K, &KcoordsSec);CHKERRQ(ierr); 240 DMGetCoordinatesLocal(K, &KcoordsVec);CHKERRQ(ierr); 241 DMGetCoordinateSection(Kref, &KrefCoordsSec);CHKERRQ(ierr); 242 DMGetCoordinatesLocal(Kref, &KrefCoordsVec);CHKERRQ(ierr); 243 244 numVerts = numDimPoints[0]; 245 ierr = PetscMalloc1(numVerts * dim,&unionCoords);CHKERRQ(ierr); 246 ierr = DMPlexGetDepthStratum(K,0,&vStart,&vEnd);CHKERRQ(ierr); 247 248 offset = 0; 249 for (v = vStart; v < vEnd; v++) { 250 ierr = PetscSectionGetOffset(unionSection,v - pStart,&vOff);CHKERRQ(ierr); 251 ierr = VecGetValuesSection(KcoordsVec, KcoordsSec, v, &Kcoords);CHKERRQ(ierr); 252 for (d = 0; d < dim; d++) { 253 unionCoords[offset * dim + d] = Kcoords[d]; 254 } 255 offset++; 256 } 257 ierr = DMPlexGetDepthStratum(Kref,0,&vRefStart,&vRefEnd);CHKERRQ(ierr); 258 for (v = vRefStart; v < vRefEnd; v++) { 259 ierr = PetscSectionGetDof(unionSection,v - pRefStart + (pEnd - pStart),&vDof);CHKERRQ(ierr); 260 ierr = PetscSectionGetOffset(unionSection,v - pRefStart + (pEnd - pStart),&vOff);CHKERRQ(ierr); 261 ierr = VecGetValuesSection(KrefCoordsVec, KrefCoordsSec, v, &Kcoords);CHKERRQ(ierr); 262 if (vDof) { 263 for (d = 0; d < dim; d++) { 264 unionCoords[offset * dim + d] = Kcoords[d]; 265 } 266 offset++; 267 } 268 } 269 } 270 ierr = DMCreate(comm,ref);CHKERRQ(ierr); 271 ierr = DMSetType(*ref,DMPLEX);CHKERRQ(ierr); 272 ierr = DMPlexSetDimension(*ref,dim);CHKERRQ(ierr); 273 ierr = DMPlexCreateFromDAG(*ref,dim,numDimPoints,coneSizes,unionCones,unionOrientations,unionCoords);CHKERRQ(ierr); 274 /* set the tree */ 275 ierr = PetscSectionCreate(comm,&parentSection);CHKERRQ(ierr); 276 ierr = PetscSectionSetChart(parentSection,0,numUnionPoints);CHKERRQ(ierr); 277 for (p = pRefStart; p < pRefEnd; p++) { 278 PetscInt uDof, uOff; 279 280 ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 281 ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 282 if (uDof) { 283 PetscSectionSetDof(parentSection,uOff,1);CHKERRQ(ierr); 284 } 285 } 286 ierr = PetscSectionSetUp(parentSection);CHKERRQ(ierr); 287 ierr = PetscSectionGetStorageSize(parentSection,&parentSize);CHKERRQ(ierr); 288 ierr = PetscMalloc2(parentSize,&parents,parentSize,&childIDs);CHKERRQ(ierr); 289 for (p = pRefStart; p < pRefEnd; p++) { 290 PetscInt uDof, uOff; 291 292 ierr = PetscSectionGetDof(unionSection, p - pRefStart + (pEnd - pStart),&uDof);CHKERRQ(ierr); 293 ierr = PetscSectionGetOffset(unionSection, p - pRefStart + (pEnd - pStart),&uOff);CHKERRQ(ierr); 294 if (uDof) { 295 PetscInt pOff, parent, parentU; 296 PetscSectionGetOffset(parentSection,uOff,&pOff);CHKERRQ(ierr); 297 DMLabelGetValue(identityRef,p,&parent);CHKERRQ(ierr); 298 ierr = PetscSectionGetOffset(unionSection, parent - pStart,&parentU);CHKERRQ(ierr); 299 parents[pOff] = parentU; 300 childIDs[pOff] = uOff; 301 } 302 } 303 ierr = DMPlexSetTree(*ref,parentSection,parents,childIDs);CHKERRQ(ierr); 304 ierr = PetscSectionDestroy(&parentSection);CHKERRQ(ierr); 305 ierr = PetscFree2(parents,childIDs);CHKERRQ(ierr); 306 307 /* clean up */ 308 ierr = PetscSectionDestroy(&unionSection);CHKERRQ(ierr); 309 ierr = PetscSectionDestroy(&unionConeSection);CHKERRQ(ierr); 310 ierr = ISDestroy(&perm);CHKERRQ(ierr); 311 ierr = PetscFree(unionCoords);CHKERRQ(ierr); 312 ierr = PetscFree2(unionCones,unionOrientations);CHKERRQ(ierr); 313 ierr = PetscFree2(coneSizes,numDimPoints);CHKERRQ(ierr); 314 ierr = DMDestroy(&K);CHKERRQ(ierr); 315 ierr = DMDestroy(&Kref);CHKERRQ(ierr); 316 PetscFunctionReturn(0); 317 } 318 319 #undef __FUNCT__ 320 #define __FUNCT__ "DMPlexTreeSymmetrize" 321 static PetscErrorCode DMPlexTreeSymmetrize(DM dm) 322 { 323 DM_Plex *mesh = (DM_Plex *)dm->data; 324 PetscSection childSec, pSec; 325 PetscInt p, pSize, cSize, parMax = PETSC_MIN_INT, parMin = PETSC_MAX_INT; 326 PetscInt *offsets, *children, pStart, pEnd; 327 PetscErrorCode ierr; 328 329 PetscFunctionBegin; 330 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 331 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 332 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 333 pSec = mesh->parentSection; 334 if (!pSec) PetscFunctionReturn(0); 335 ierr = PetscSectionGetStorageSize(pSec,&pSize);CHKERRQ(ierr); 336 for (p = 0; p < pSize; p++) { 337 PetscInt par = mesh->parents[p]; 338 339 parMax = PetscMax(parMax,par+1); 340 parMin = PetscMin(parMin,par); 341 } 342 if (parMin > parMax) { 343 parMin = -1; 344 parMax = -1; 345 } 346 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)pSec),&childSec);CHKERRQ(ierr); 347 ierr = PetscSectionSetChart(childSec,parMin,parMax);CHKERRQ(ierr); 348 for (p = 0; p < pSize; p++) { 349 PetscInt par = mesh->parents[p]; 350 351 ierr = PetscSectionAddDof(childSec,par,1);CHKERRQ(ierr); 352 } 353 ierr = PetscSectionSetUp(childSec);CHKERRQ(ierr); 354 ierr = PetscSectionGetStorageSize(childSec,&cSize);CHKERRQ(ierr); 355 ierr = PetscMalloc1(cSize,&children);CHKERRQ(ierr); 356 ierr = PetscCalloc1(parMax-parMin,&offsets);CHKERRQ(ierr); 357 ierr = PetscSectionGetChart(pSec,&pStart,&pEnd);CHKERRQ(ierr); 358 for (p = pStart; p < pEnd; p++) { 359 PetscInt dof, off, i; 360 361 ierr = PetscSectionGetDof(pSec,p,&dof);CHKERRQ(ierr); 362 ierr = PetscSectionGetOffset(pSec,p,&off);CHKERRQ(ierr); 363 for (i = 0; i < dof; i++) { 364 PetscInt par = mesh->parents[off + i], cOff; 365 366 ierr = PetscSectionGetOffset(childSec,par,&cOff);CHKERRQ(ierr); 367 children[cOff + offsets[par-parMin]++] = p; 368 } 369 } 370 mesh->childSection = childSec; 371 mesh->children = children; 372 ierr = PetscFree(offsets);CHKERRQ(ierr); 373 PetscFunctionReturn(0); 374 } 375 376 #undef __FUNCT__ 377 #define __FUNCT__ "DMPlexComputeConstraints_Tree" 378 static PetscErrorCode DMPlexComputeConstraints_Tree(DM dm) 379 { 380 PetscInt p, pStart, pEnd, *anchors, size; 381 PetscInt aMin = PETSC_MAX_INT, aMax = PETSC_MIN_INT; 382 PetscSection aSec; 383 IS aIS; 384 PetscErrorCode ierr; 385 386 PetscFunctionBegin; 387 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 388 ierr = DMPlexGetChart(dm,&pStart,&pEnd);CHKERRQ(ierr); 389 for (p = pStart; p < pEnd; p++) { 390 PetscInt parent; 391 392 ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 393 if (parent != p) { 394 aMin = PetscMin(aMin,p); 395 aMax = PetscMax(aMax,p+1); 396 } 397 } 398 if (aMin > aMax) { 399 aMin = -1; 400 aMax = -1; 401 } 402 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm),&aSec);CHKERRQ(ierr); 403 ierr = PetscSectionSetChart(aSec,aMin,aMax);CHKERRQ(ierr); 404 for (p = aMin; p < aMax; p++) { 405 PetscInt parent, ancestor = p; 406 407 ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 408 while (parent != ancestor) { 409 ancestor = parent; 410 ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 411 } 412 if (ancestor != p) { 413 PetscInt closureSize, *closure = NULL; 414 415 ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 416 ierr = PetscSectionSetDof(aSec,p,closureSize);CHKERRQ(ierr); 417 ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 418 } 419 } 420 ierr = PetscSectionSetUp(aSec);CHKERRQ(ierr); 421 ierr = PetscSectionGetStorageSize(aSec,&size);CHKERRQ(ierr); 422 ierr = PetscMalloc1(size,&anchors);CHKERRQ(ierr); 423 for (p = aMin; p < aMax; p++) { 424 PetscInt parent, ancestor = p; 425 426 ierr = DMPlexGetTreeParent(dm,p,&parent,NULL);CHKERRQ(ierr); 427 while (parent != ancestor) { 428 ancestor = parent; 429 ierr = DMPlexGetTreeParent(dm,ancestor,&parent,NULL);CHKERRQ(ierr); 430 } 431 if (ancestor != p) { 432 PetscInt j, closureSize, *closure = NULL, aOff; 433 434 ierr = PetscSectionGetOffset(aSec,p,&aOff);CHKERRQ(ierr); 435 436 ierr = DMPlexGetTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 437 for (j = 0; j < closureSize; j++) { 438 anchors[aOff + j] = closure[2*j]; 439 } 440 ierr = DMPlexRestoreTransitiveClosure(dm,ancestor,PETSC_TRUE,&closureSize,&closure);CHKERRQ(ierr); 441 } 442 } 443 ierr = ISCreateGeneral(PetscObjectComm((PetscObject)dm),size,anchors,PETSC_OWN_POINTER,&aIS);CHKERRQ(ierr); 444 ierr = DMPlexSetConstraints(dm,aSec,aIS);CHKERRQ(ierr); 445 ierr = PetscSectionDestroy(&aSec);CHKERRQ(ierr); 446 ierr = ISDestroy(&aIS);CHKERRQ(ierr); 447 PetscFunctionReturn(0); 448 } 449 450 #undef __FUNCT__ 451 #define __FUNCT__ "DMPlexSetTree" 452 /*@ 453 DMPlexSetTree - set the tree that describes the hierarchy of non-conforming mesh points. This routine also creates 454 the point-to-point constraints determined by the tree: a point is constained to the points in the closure of its 455 tree root. 456 457 Collective on dm 458 459 Input Parameters: 460 + dm - the DMPlex object 461 . parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 462 offset indexes the parent and childID list; the reference count of parentSection is incremented 463 . parents - a list of the point parents; copied, can be destroyed 464 - childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 465 the child corresponds to the point in the reference tree with index childIDs; copied, can be destroyed 466 467 Level: intermediate 468 469 .seealso: DMPlexGetTree(), DMPlexSetReferenceTree(), DMPlexSetConstraints(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 470 @*/ 471 PetscErrorCode DMPlexSetTree(DM dm, PetscSection parentSection, PetscInt parents[], PetscInt childIDs[]) 472 { 473 DM_Plex *mesh = (DM_Plex *)dm->data; 474 PetscInt size; 475 PetscErrorCode ierr; 476 477 PetscFunctionBegin; 478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 479 PetscValidHeaderSpecific(parentSection, PETSC_SECTION_CLASSID, 2); 480 ierr = PetscObjectReference((PetscObject)parentSection);CHKERRQ(ierr); 481 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 482 mesh->parentSection = parentSection; 483 ierr = PetscSectionGetStorageSize(parentSection,&size);CHKERRQ(ierr); 484 if (parents != mesh->parents) { 485 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 486 ierr = PetscMalloc1(size,&mesh->parents);CHKERRQ(ierr); 487 ierr = PetscMemcpy(mesh->parents, parents, size * sizeof(*parents));CHKERRQ(ierr); 488 } 489 if (childIDs != mesh->childIDs) { 490 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 491 ierr = PetscMalloc1(size,&mesh->childIDs);CHKERRQ(ierr); 492 ierr = PetscMemcpy(mesh->childIDs, childIDs, size * sizeof(*childIDs));CHKERRQ(ierr); 493 } 494 ierr = DMPlexTreeSymmetrize(dm);CHKERRQ(ierr); 495 ierr = DMPlexComputeConstraints_Tree(dm);CHKERRQ(ierr); 496 PetscFunctionReturn(0); 497 } 498 499 #undef __FUNCT__ 500 #define __FUNCT__ "DMPlexGetTree" 501 /*@ 502 DMPlexGetTree - get the tree that describes the hierarchy of non-conforming mesh points. 503 Collective on dm 504 505 Input Parameters: 506 . dm - the DMPlex object 507 508 Output Parameters: 509 + parentSection - a section describing the tree: a point has a parent if it has 1 dof in the section; the section 510 offset indexes the parent and childID list 511 . parents - a list of the point parents 512 . childIDs - identifies the relationship of the child point to the parent point; if there is a reference tree, then 513 the child corresponds to the point in the reference tree with index childID 514 . childSection - the inverse of the parent section 515 - children - a list of the point children 516 517 Level: intermediate 518 519 .seealso: DMPlexSetTree(), DMPlexSetReferenceTree(), DMPlexSetConstraints(), DMPlexGetTreeParent(), DMPlexGetTreeChildren() 520 @*/ 521 PetscErrorCode DMPlexGetTree(DM dm, PetscSection *parentSection, PetscInt *parents[], PetscInt *childIDs[], PetscSection *childSection, PetscInt *children[]) 522 { 523 DM_Plex *mesh = (DM_Plex *)dm->data; 524 525 PetscFunctionBegin; 526 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 527 if (parentSection) *parentSection = mesh->parentSection; 528 if (parents) *parents = mesh->parents; 529 if (childIDs) *childIDs = mesh->childIDs; 530 if (childSection) *childSection = mesh->childSection; 531 if (children) *children = mesh->children; 532 PetscFunctionReturn(0); 533 } 534 535 #undef __FUNCT__ 536 #define __FUNCT__ "DMPlexGetTreeParent" 537 /*@ 538 DMPlexGetTreeParent - get the parent of a point in the tree describing the point hierarchy (not the Sieve DAG) 539 540 Input Parameters: 541 + dm - the DMPlex object 542 - point - the query point 543 544 Output Parameters: 545 + parent - if not NULL, set to the parent of the point, or the point itself if the point does not have a parent 546 - childID - if not NULL, set to the child ID of the point with respect to its parent, or 0 if the point 547 does not have a parent 548 549 Level: intermediate 550 551 .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeChildren() 552 @*/ 553 PetscErrorCode DMPlexGetTreeParent(DM dm, PetscInt point, PetscInt *parent, PetscInt *childID) 554 { 555 DM_Plex *mesh = (DM_Plex *)dm->data; 556 PetscSection pSec; 557 PetscErrorCode ierr; 558 559 PetscFunctionBegin; 560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 561 pSec = mesh->parentSection; 562 if (pSec && point >= pSec->pStart && point < pSec->pEnd) { 563 PetscInt dof; 564 565 ierr = PetscSectionGetDof (pSec, point, &dof);CHKERRQ(ierr); 566 if (dof) { 567 PetscInt off; 568 569 ierr = PetscSectionGetOffset (pSec, point, &off);CHKERRQ(ierr); 570 if (parent) *parent = mesh->parents[off]; 571 if (childID) *childID = mesh->childIDs[off]; 572 PetscFunctionReturn(0); 573 } 574 } 575 if (parent) { 576 *parent = point; 577 } 578 if (childID) { 579 *childID = 0; 580 } 581 PetscFunctionReturn(0); 582 } 583 584 #undef __FUNCT__ 585 #define __FUNCT__ "DMPlexGetTreeChildren" 586 /*@C 587 DMPlexGetTreeChildren - get the children of a point in the tree describing the point hierarchy (not the Sieve DAG) 588 589 Input Parameters: 590 + dm - the DMPlex object 591 - point - the query point 592 593 Output Parameters: 594 + numChildren - if not NULL, set to the number of children 595 - children - if not NULL, set to a list children, or set to NULL if the point has no children 596 597 Level: intermediate 598 599 Fortran Notes: 600 Since it returns an array, this routine is only available in Fortran 90, and you must 601 include petsc.h90 in your code. 602 603 .seealso: DMPlexSetTree(), DMPlexGetTree(), DMPlexGetTreeParent() 604 @*/ 605 PetscErrorCode DMPlexGetTreeChildren(DM dm, PetscInt point, PetscInt *numChildren, const PetscInt *children[]) 606 { 607 DM_Plex *mesh = (DM_Plex *)dm->data; 608 PetscSection childSec; 609 PetscInt dof = 0; 610 PetscErrorCode ierr; 611 612 PetscFunctionBegin; 613 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 614 childSec = mesh->childSection; 615 if (childSec && point >= childSec->pStart && point < childSec->pEnd) { 616 ierr = PetscSectionGetDof (childSec, point, &dof);CHKERRQ(ierr); 617 } 618 if (numChildren) *numChildren = dof; 619 if (children) { 620 if (dof) { 621 PetscInt off; 622 623 ierr = PetscSectionGetOffset (childSec, point, &off);CHKERRQ(ierr); 624 *children = &mesh->children[off]; 625 } 626 else { 627 *children = NULL; 628 } 629 } 630 PetscFunctionReturn(0); 631 } 632