1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petscsf.h> 4 #include <petscds.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Interpolate, PETSCPARTITIONER_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh; 8 9 PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 PETSC_EXTERN PetscErrorCode VecLoad_Default(Vec, PetscViewer); 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "DMPlexGetFieldType_Internal" 15 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 16 { 17 PetscInt dim, pStart, pEnd, vStart, vEnd, cStart, cEnd, cEndInterior, vdof = 0, cdof = 0; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 *ft = PETSC_VTK_POINT_FIELD; 22 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 23 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 24 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 25 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 26 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 27 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 28 if (field >= 0) { 29 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vdof);CHKERRQ(ierr);} 30 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &cdof);CHKERRQ(ierr);} 31 } else { 32 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 33 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 34 } 35 if (vdof) { 36 *sStart = vStart; 37 *sEnd = vEnd; 38 if (vdof == dim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 39 else *ft = PETSC_VTK_POINT_FIELD; 40 } else if (cdof) { 41 *sStart = cStart; 42 *sEnd = cEnd; 43 if (cdof == dim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 44 else *ft = PETSC_VTK_CELL_FIELD; 45 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 46 PetscFunctionReturn(0); 47 } 48 49 #undef __FUNCT__ 50 #define __FUNCT__ "VecView_Plex_Local" 51 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 52 { 53 DM dm; 54 PetscBool isvtk, ishdf5, isseq; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 59 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 60 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 61 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 62 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 63 if (isvtk || ishdf5) { 64 PetscInt numFields; 65 PetscBool fem = PETSC_FALSE; 66 67 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 68 if (numFields) { 69 PetscObject fe; 70 71 ierr = DMGetField(dm, 0, &fe);CHKERRQ(ierr); 72 if (fe->classid == PETSCFE_CLASSID) fem = PETSC_TRUE; 73 } 74 if (fem) {ierr = DMPlexInsertBoundaryValues(dm, v, 0.0, NULL, NULL, NULL);CHKERRQ(ierr);} 75 } 76 if (isvtk) { 77 PetscSection section; 78 PetscViewerVTKFieldType ft; 79 PetscInt pStart, pEnd; 80 81 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 82 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 83 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 84 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 85 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 86 } else if (ishdf5) { 87 #if defined(PETSC_HAVE_HDF5) 88 ierr = VecView_Plex_Local_HDF5(v, viewer);CHKERRQ(ierr); 89 #else 90 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 91 #endif 92 } else { 93 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 94 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 95 } 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "VecView_Plex" 101 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 102 { 103 DM dm; 104 PetscBool isvtk, ishdf5, isseq; 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 109 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 110 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 111 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 112 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 113 if (isvtk) { 114 Vec locv; 115 const char *name; 116 117 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 118 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 119 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 120 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 121 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 122 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 123 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 124 } else if (ishdf5) { 125 #if defined(PETSC_HAVE_HDF5) 126 ierr = VecView_Plex_HDF5(v, viewer);CHKERRQ(ierr); 127 #else 128 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 129 #endif 130 } else { 131 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 132 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 133 } 134 PetscFunctionReturn(0); 135 } 136 137 #undef __FUNCT__ 138 #define __FUNCT__ "VecView_Plex_Native" 139 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 140 { 141 DM dm; 142 MPI_Comm comm; 143 PetscViewerFormat format; 144 Vec v; 145 PetscBool isvtk, ishdf5; 146 PetscErrorCode ierr; 147 148 PetscFunctionBegin; 149 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 150 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 151 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 152 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 153 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 154 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 155 if (format == PETSC_VIEWER_NATIVE) { 156 const char *vecname; 157 PetscInt n, nroots; 158 159 if (dm->sfNatural) { 160 ierr = VecGetLocalSize(originalv, &n); 161 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 162 if (n == nroots) { 163 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 164 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 165 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 166 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 167 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 168 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 169 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 170 } else { 171 /* we are viewing a natural DMPlex vec. */ 172 v = originalv; 173 } 174 if (ishdf5) { 175 #if defined(PETSC_HAVE_HDF5) 176 ierr = VecView_Plex_HDF5_Native(v, viewer);CHKERRQ(ierr); 177 #else 178 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 179 #endif 180 } else if (isvtk) { 181 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 182 } else { 183 PetscBool isseq; 184 185 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 186 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 187 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 188 } 189 if (format == PETSC_VIEWER_NATIVE) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 190 PetscFunctionReturn(0); 191 } 192 193 #undef __FUNCT__ 194 #define __FUNCT__ "VecLoad_Plex_Local" 195 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 196 { 197 DM dm; 198 PetscBool ishdf5; 199 PetscErrorCode ierr; 200 201 PetscFunctionBegin; 202 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 203 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 204 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 205 if (ishdf5) { 206 DM dmBC; 207 Vec gv; 208 const char *name; 209 210 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 211 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 212 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 213 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 214 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 215 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 216 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 217 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 218 } else { 219 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 220 } 221 PetscFunctionReturn(0); 222 } 223 224 #undef __FUNCT__ 225 #define __FUNCT__ "VecLoad_Plex" 226 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 227 { 228 DM dm; 229 PetscBool ishdf5; 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 234 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 235 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 236 if (ishdf5) { 237 #if defined(PETSC_HAVE_HDF5) 238 ierr = VecLoad_Plex_HDF5(v, viewer);CHKERRQ(ierr); 239 #else 240 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 241 #endif 242 } else { 243 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 244 } 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "VecLoad_Plex_Native" 250 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 251 { 252 DM dm; 253 PetscViewerFormat format; 254 PetscBool ishdf5; 255 PetscErrorCode ierr; 256 257 PetscFunctionBegin; 258 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 259 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 260 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 261 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 262 if (format == PETSC_VIEWER_NATIVE) { 263 if (dm->sfNatural) { 264 if (ishdf5) { 265 #if defined(PETSC_HAVE_HDF5) 266 Vec v; 267 const char *vecname; 268 269 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 270 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 271 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 272 ierr = VecLoad_Plex_HDF5_Native(v, viewer);CHKERRQ(ierr); 273 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 274 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 275 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 276 #else 277 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 278 #endif 279 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 280 } 281 } 282 PetscFunctionReturn(0); 283 } 284 285 #undef __FUNCT__ 286 #define __FUNCT__ "DMPlexView_Ascii_Geometry" 287 PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 288 { 289 PetscSection coordSection; 290 Vec coordinates; 291 DMLabel depthLabel; 292 const char *name[4]; 293 const PetscScalar *a; 294 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 295 PetscErrorCode ierr; 296 297 PetscFunctionBegin; 298 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 299 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 300 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 301 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 302 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 303 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 304 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 305 name[0] = "vertex"; 306 name[1] = "edge"; 307 name[dim-1] = "face"; 308 name[dim] = "cell"; 309 for (c = cStart; c < cEnd; ++c) { 310 PetscInt *closure = NULL; 311 PetscInt closureSize, cl; 312 313 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %d:\n", c);CHKERRQ(ierr); 314 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 315 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 316 for (cl = 0; cl < closureSize*2; cl += 2) { 317 PetscInt point = closure[cl], depth, dof, off, d, p; 318 319 if ((point < pStart) || (point >= pEnd)) continue; 320 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 321 if (!dof) continue; 322 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 323 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 324 ierr = PetscViewerASCIIPrintf(viewer, "%s %d coords:", name[depth], point);CHKERRQ(ierr); 325 for (p = 0; p < dof/dim; ++p) { 326 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 327 for (d = 0; d < dim; ++d) { 328 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 329 ierr = PetscViewerASCIIPrintf(viewer, "%g", PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 330 } 331 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 332 } 333 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 334 } 335 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 336 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 337 } 338 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 #undef __FUNCT__ 343 #define __FUNCT__ "DMPlexView_Ascii" 344 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 345 { 346 DM_Plex *mesh = (DM_Plex*) dm->data; 347 DM cdm; 348 DMLabel markers; 349 PetscSection coordSection; 350 Vec coordinates; 351 PetscViewerFormat format; 352 PetscErrorCode ierr; 353 354 PetscFunctionBegin; 355 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 356 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 357 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 358 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 359 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 360 const char *name; 361 PetscInt maxConeSize, maxSupportSize; 362 PetscInt pStart, pEnd, p; 363 PetscMPIInt rank, size; 364 365 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 366 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 367 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 368 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 369 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 370 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 371 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 372 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "Max sizes cone: %D support: %D\n", maxConeSize, maxSupportSize);CHKERRQ(ierr); 373 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 374 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 375 for (p = pStart; p < pEnd; ++p) { 376 PetscInt dof, off, s; 377 378 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 379 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 380 for (s = off; s < off+dof; ++s) { 381 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 382 } 383 } 384 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 385 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 386 for (p = pStart; p < pEnd; ++p) { 387 PetscInt dof, off, c; 388 389 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 390 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 391 for (c = off; c < off+dof; ++c) { 392 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 393 } 394 } 395 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 396 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 397 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 398 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 399 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 400 if (size > 1) { 401 PetscSF sf; 402 403 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 404 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 405 } 406 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 407 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 408 const char *name, *color; 409 const char *defcolors[3] = {"gray", "orange", "green"}; 410 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 411 PetscReal scale = 2.0; 412 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 413 double tcoords[3]; 414 PetscScalar *coords; 415 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 416 PetscMPIInt rank, size; 417 char **names, **colors, **lcolors; 418 419 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 420 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 421 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 422 numLabels = PetscMax(numLabels, 10); 423 numColors = 10; 424 numLColors = 10; 425 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 426 ierr = PetscOptionsGetReal(((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 427 ierr = PetscOptionsGetBool(((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 428 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 429 if (!useLabels) numLabels = 0; 430 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 431 if (!useColors) { 432 numColors = 3; 433 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 434 } 435 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 436 if (!useColors) { 437 numLColors = 4; 438 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 439 } 440 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 441 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 442 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 443 ierr = PetscViewerASCIISynchronizedAllow(viewer, PETSC_TRUE);CHKERRQ(ierr); 444 ierr = PetscViewerASCIIPrintf(viewer, "\ 445 \\documentclass[tikz]{standalone}\n\n\ 446 \\usepackage{pgflibraryshapes}\n\ 447 \\usetikzlibrary{backgrounds}\n\ 448 \\usetikzlibrary{arrows}\n\ 449 \\begin{document}\n");CHKERRQ(ierr); 450 if (size > 1) { 451 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 452 for (p = 0; p < size; ++p) { 453 if (p > 0 && p == size-1) { 454 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 455 } else if (p > 0) { 456 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 457 } 458 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 459 } 460 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 461 } 462 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", 1.0);CHKERRQ(ierr); 463 /* Plot vertices */ 464 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 465 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 466 for (v = vStart; v < vEnd; ++v) { 467 PetscInt off, dof, d; 468 PetscBool isLabeled = PETSC_FALSE; 469 470 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 471 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 472 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 473 for (d = 0; d < dof; ++d) { 474 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 475 tcoords[d] = PetscAbsReal(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 476 } 477 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 478 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 479 for (d = 0; d < dof; ++d) { 480 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 481 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d]);CHKERRQ(ierr); 482 } 483 color = colors[rank%numColors]; 484 for (l = 0; l < numLabels; ++l) { 485 PetscInt val; 486 ierr = DMPlexGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 487 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 488 } 489 if (useNumbers) { 490 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 491 } else { 492 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 493 } 494 } 495 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 496 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 497 /* Plot edges */ 498 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 499 if (dim < 3 && useNumbers) { 500 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 501 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 502 for (e = eStart; e < eEnd; ++e) { 503 const PetscInt *cone; 504 PetscInt coneSize, offA, offB, dof, d; 505 506 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 507 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %d cone should have two vertices, not %d", e, coneSize); 508 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 509 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 510 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 511 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 512 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 513 for (d = 0; d < dof; ++d) { 514 tcoords[d] = (double) (scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 515 tcoords[d] = PetscAbsReal(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 516 } 517 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 518 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 519 for (d = 0; d < dof; ++d) { 520 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 521 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d]);CHKERRQ(ierr); 522 } 523 color = colors[rank%numColors]; 524 for (l = 0; l < numLabels; ++l) { 525 PetscInt val; 526 ierr = DMPlexGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 527 if (val >= 0) {color = lcolors[l%numLColors]; break;} 528 } 529 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 530 } 531 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 532 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 533 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 534 } 535 /* Plot cells */ 536 if (dim == 3 || !useNumbers) { 537 for (e = eStart; e < eEnd; ++e) { 538 const PetscInt *cone; 539 540 color = colors[rank%numColors]; 541 for (l = 0; l < numLabels; ++l) { 542 PetscInt val; 543 ierr = DMPlexGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 544 if (val >= 0) {color = lcolors[l%numLColors]; break;} 545 } 546 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 547 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 548 } 549 } else { 550 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 551 for (c = cStart; c < cEnd; ++c) { 552 PetscInt *closure = NULL; 553 PetscInt closureSize, firstPoint = -1; 554 555 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 556 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 557 for (p = 0; p < closureSize*2; p += 2) { 558 const PetscInt point = closure[p]; 559 560 if ((point < vStart) || (point >= vEnd)) continue; 561 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 562 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 563 if (firstPoint < 0) firstPoint = point; 564 } 565 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 566 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 567 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 568 } 569 } 570 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 571 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 572 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 573 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 574 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 575 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 576 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 577 } else { 578 MPI_Comm comm; 579 PetscInt *sizes, *hybsizes; 580 PetscInt locDepth, depth, dim, d, pMax[4]; 581 PetscInt pStart, pEnd, p; 582 PetscInt numLabels, l; 583 const char *name; 584 PetscMPIInt size; 585 586 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 587 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 588 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 589 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 590 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dim);CHKERRQ(ierr);} 591 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr);} 592 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 593 ierr = MPI_Allreduce(&locDepth, &depth, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 594 ierr = DMPlexGetHybridBounds(dm, &pMax[depth], depth > 0 ? &pMax[depth-1] : NULL, &pMax[1], &pMax[0]);CHKERRQ(ierr); 595 ierr = PetscMalloc2(size,&sizes,size,&hybsizes);CHKERRQ(ierr); 596 if (depth == 1) { 597 ierr = DMPlexGetDepthStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 598 pEnd = pEnd - pStart; 599 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 600 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", 0);CHKERRQ(ierr); 601 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 602 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 603 ierr = DMPlexGetHeightStratum(dm, 0, &pStart, &pEnd);CHKERRQ(ierr); 604 pEnd = pEnd - pStart; 605 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 606 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", dim);CHKERRQ(ierr); 607 for (p = 0; p < size; ++p) {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 608 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 609 } else { 610 for (d = 0; d <= dim; d++) { 611 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 612 pEnd -= pStart; 613 pMax[d] -= pStart; 614 ierr = MPI_Gather(&pEnd, 1, MPIU_INT, sizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 615 ierr = MPI_Gather(&pMax[d], 1, MPIU_INT, hybsizes, 1, MPIU_INT, 0, comm);CHKERRQ(ierr); 616 ierr = PetscViewerASCIIPrintf(viewer, " %D-cells:", d);CHKERRQ(ierr); 617 for (p = 0; p < size; ++p) { 618 if (hybsizes[p] >= 0) {ierr = PetscViewerASCIIPrintf(viewer, " %D (%D)", sizes[p], sizes[p] - hybsizes[p]);CHKERRQ(ierr);} 619 else {ierr = PetscViewerASCIIPrintf(viewer, " %D", sizes[p]);CHKERRQ(ierr);} 620 } 621 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 622 } 623 } 624 ierr = PetscFree2(sizes,hybsizes);CHKERRQ(ierr); 625 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 626 if (numLabels) {ierr = PetscViewerASCIIPrintf(viewer, "Labels:\n");CHKERRQ(ierr);} 627 for (l = 0; l < numLabels; ++l) { 628 DMLabel label; 629 const char *name; 630 IS valueIS; 631 const PetscInt *values; 632 PetscInt numValues, v; 633 634 ierr = DMPlexGetLabelName(dm, l, &name);CHKERRQ(ierr); 635 ierr = DMPlexGetLabel(dm, name, &label);CHKERRQ(ierr); 636 ierr = DMLabelGetNumValues(label, &numValues);CHKERRQ(ierr); 637 ierr = PetscViewerASCIIPrintf(viewer, " %s: %d strata of sizes (", name, numValues);CHKERRQ(ierr); 638 ierr = DMLabelGetValueIS(label, &valueIS);CHKERRQ(ierr); 639 ierr = ISGetIndices(valueIS, &values);CHKERRQ(ierr); 640 for (v = 0; v < numValues; ++v) { 641 PetscInt size; 642 643 ierr = DMLabelGetStratumSize(label, values[v], &size);CHKERRQ(ierr); 644 if (v > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 645 ierr = PetscViewerASCIIPrintf(viewer, "%d", size);CHKERRQ(ierr); 646 } 647 ierr = PetscViewerASCIIPrintf(viewer, ")\n");CHKERRQ(ierr); 648 ierr = ISRestoreIndices(valueIS, &values);CHKERRQ(ierr); 649 ierr = ISDestroy(&valueIS);CHKERRQ(ierr); 650 } 651 } 652 PetscFunctionReturn(0); 653 } 654 655 #undef __FUNCT__ 656 #define __FUNCT__ "DMView_Plex" 657 PetscErrorCode DMView_Plex(DM dm, PetscViewer viewer) 658 { 659 PetscBool iascii, ishdf5, isvtk; 660 PetscErrorCode ierr; 661 662 PetscFunctionBegin; 663 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 664 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 665 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERASCII, &iascii);CHKERRQ(ierr); 666 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 667 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 668 if (iascii) { 669 ierr = DMPlexView_Ascii(dm, viewer);CHKERRQ(ierr); 670 } else if (ishdf5) { 671 #if defined(PETSC_HAVE_HDF5) 672 ierr = PetscViewerPushFormat(viewer, PETSC_VIEWER_HDF5_VIZ);CHKERRQ(ierr); 673 ierr = DMPlexView_HDF5(dm, viewer);CHKERRQ(ierr); 674 ierr = PetscViewerPopFormat(viewer);CHKERRQ(ierr); 675 #else 676 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 677 #endif 678 } 679 else if (isvtk) { 680 ierr = DMPlexVTKWriteAll((PetscObject) dm,viewer);CHKERRQ(ierr); 681 } 682 PetscFunctionReturn(0); 683 } 684 685 #undef __FUNCT__ 686 #define __FUNCT__ "DMLoad_Plex" 687 PetscErrorCode DMLoad_Plex(DM dm, PetscViewer viewer) 688 { 689 PetscBool isbinary, ishdf5; 690 PetscErrorCode ierr; 691 692 PetscFunctionBegin; 693 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 694 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 695 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERBINARY, &isbinary);CHKERRQ(ierr); 696 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 697 if (isbinary) {SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Do not yet support binary viewers");} 698 else if (ishdf5) { 699 #if defined(PETSC_HAVE_HDF5) 700 ierr = DMPlexLoad_HDF5(dm, viewer);CHKERRQ(ierr); 701 #else 702 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 703 #endif 704 } 705 PetscFunctionReturn(0); 706 } 707 708 #undef __FUNCT__ 709 #define __FUNCT__ "BoundaryDestroy" 710 static PetscErrorCode BoundaryDestroy(DMBoundary *boundary) 711 { 712 DMBoundary b, next; 713 PetscErrorCode ierr; 714 715 PetscFunctionBegin; 716 if (!boundary) PetscFunctionReturn(0); 717 b = *boundary; 718 *boundary = NULL; 719 for (; b; b = next) { 720 next = b->next; 721 ierr = PetscFree(b->comps);CHKERRQ(ierr); 722 ierr = PetscFree(b->ids);CHKERRQ(ierr); 723 ierr = PetscFree(b->name);CHKERRQ(ierr); 724 ierr = PetscFree(b->labelname);CHKERRQ(ierr); 725 ierr = PetscFree(b);CHKERRQ(ierr); 726 } 727 PetscFunctionReturn(0); 728 } 729 730 #undef __FUNCT__ 731 #define __FUNCT__ "DMDestroy_Plex" 732 PetscErrorCode DMDestroy_Plex(DM dm) 733 { 734 DM_Plex *mesh = (DM_Plex*) dm->data; 735 PlexLabel next = mesh->labels; 736 PetscErrorCode ierr; 737 738 PetscFunctionBegin; 739 if (--mesh->refct > 0) PetscFunctionReturn(0); 740 ierr = PetscSectionDestroy(&mesh->coneSection);CHKERRQ(ierr); 741 ierr = PetscFree(mesh->cones);CHKERRQ(ierr); 742 ierr = PetscFree(mesh->coneOrientations);CHKERRQ(ierr); 743 ierr = PetscSectionDestroy(&mesh->supportSection);CHKERRQ(ierr); 744 ierr = PetscFree(mesh->supports);CHKERRQ(ierr); 745 ierr = PetscFree(mesh->facesTmp);CHKERRQ(ierr); 746 ierr = PetscFree(mesh->tetgenOpts);CHKERRQ(ierr); 747 ierr = PetscFree(mesh->triangleOpts);CHKERRQ(ierr); 748 ierr = PetscPartitionerDestroy(&mesh->partitioner);CHKERRQ(ierr); 749 while (next) { 750 PlexLabel tmp = next->next; 751 752 ierr = DMLabelDestroy(&next->label);CHKERRQ(ierr); 753 ierr = PetscFree(next);CHKERRQ(ierr); 754 next = tmp; 755 } 756 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 757 ierr = DMLabelDestroy(&mesh->subpointMap);CHKERRQ(ierr); 758 ierr = ISDestroy(&mesh->globalVertexNumbers);CHKERRQ(ierr); 759 ierr = ISDestroy(&mesh->globalCellNumbers);CHKERRQ(ierr); 760 ierr = BoundaryDestroy(&mesh->boundary);CHKERRQ(ierr); 761 ierr = PetscSectionDestroy(&mesh->anchorSection);CHKERRQ(ierr); 762 ierr = ISDestroy(&mesh->anchorIS);CHKERRQ(ierr); 763 ierr = PetscSectionDestroy(&mesh->parentSection);CHKERRQ(ierr); 764 ierr = PetscFree(mesh->parents);CHKERRQ(ierr); 765 ierr = PetscFree(mesh->childIDs);CHKERRQ(ierr); 766 ierr = PetscSectionDestroy(&mesh->childSection);CHKERRQ(ierr); 767 ierr = PetscFree(mesh->children);CHKERRQ(ierr); 768 ierr = DMDestroy(&mesh->referenceTree);CHKERRQ(ierr); 769 /* This was originally freed in DMDestroy(), but that prevents reference counting of backend objects */ 770 ierr = PetscFree(mesh);CHKERRQ(ierr); 771 PetscFunctionReturn(0); 772 } 773 774 #undef __FUNCT__ 775 #define __FUNCT__ "DMCreateMatrix_Plex" 776 PetscErrorCode DMCreateMatrix_Plex(DM dm, Mat *J) 777 { 778 PetscSection sectionGlobal; 779 PetscInt bs = -1; 780 PetscInt localSize; 781 PetscBool isShell, isBlock, isSeqBlock, isMPIBlock, isSymBlock, isSymSeqBlock, isSymMPIBlock; 782 PetscErrorCode ierr; 783 MatType mtype; 784 ISLocalToGlobalMapping ltog; 785 786 PetscFunctionBegin; 787 ierr = MatInitializePackage();CHKERRQ(ierr); 788 mtype = dm->mattype; 789 ierr = DMGetDefaultGlobalSection(dm, §ionGlobal);CHKERRQ(ierr); 790 /* ierr = PetscSectionGetStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); */ 791 ierr = PetscSectionGetConstrainedStorageSize(sectionGlobal, &localSize);CHKERRQ(ierr); 792 ierr = MatCreate(PetscObjectComm((PetscObject)dm), J);CHKERRQ(ierr); 793 ierr = MatSetSizes(*J, localSize, localSize, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 794 ierr = MatSetType(*J, mtype);CHKERRQ(ierr); 795 ierr = MatSetFromOptions(*J);CHKERRQ(ierr); 796 ierr = PetscStrcmp(mtype, MATSHELL, &isShell);CHKERRQ(ierr); 797 ierr = PetscStrcmp(mtype, MATBAIJ, &isBlock);CHKERRQ(ierr); 798 ierr = PetscStrcmp(mtype, MATSEQBAIJ, &isSeqBlock);CHKERRQ(ierr); 799 ierr = PetscStrcmp(mtype, MATMPIBAIJ, &isMPIBlock);CHKERRQ(ierr); 800 ierr = PetscStrcmp(mtype, MATSBAIJ, &isSymBlock);CHKERRQ(ierr); 801 ierr = PetscStrcmp(mtype, MATSEQSBAIJ, &isSymSeqBlock);CHKERRQ(ierr); 802 ierr = PetscStrcmp(mtype, MATMPISBAIJ, &isSymMPIBlock);CHKERRQ(ierr); 803 if (!isShell) { 804 PetscBool fillMatrix = (PetscBool) !dm->prealloc_only; 805 PetscInt *dnz, *onz, *dnzu, *onzu, bsLocal, bsMax, bsMin; 806 807 if (bs < 0) { 808 if (isBlock || isSeqBlock || isMPIBlock || isSymBlock || isSymSeqBlock || isSymMPIBlock) { 809 PetscInt pStart, pEnd, p, dof, cdof; 810 811 ierr = PetscSectionGetChart(sectionGlobal, &pStart, &pEnd);CHKERRQ(ierr); 812 for (p = pStart; p < pEnd; ++p) { 813 ierr = PetscSectionGetDof(sectionGlobal, p, &dof);CHKERRQ(ierr); 814 ierr = PetscSectionGetConstraintDof(sectionGlobal, p, &cdof);CHKERRQ(ierr); 815 if (dof-cdof) { 816 if (bs < 0) { 817 bs = dof-cdof; 818 } else if (bs != dof-cdof) { 819 /* Layout does not admit a pointwise block size */ 820 bs = 1; 821 break; 822 } 823 } 824 } 825 /* Must have same blocksize on all procs (some might have no points) */ 826 bsLocal = bs; 827 ierr = MPI_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 828 bsLocal = bs < 0 ? bsMax : bs; 829 ierr = MPI_Allreduce(&bsLocal, &bsMin, 1, MPIU_INT, MPI_MIN, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 830 if (bsMin != bsMax) { 831 bs = 1; 832 } else { 833 bs = bsMax; 834 } 835 } else { 836 bs = 1; 837 } 838 } 839 ierr = PetscCalloc4(localSize/bs, &dnz, localSize/bs, &onz, localSize/bs, &dnzu, localSize/bs, &onzu);CHKERRQ(ierr); 840 ierr = DMPlexPreallocateOperator(dm, bs, dnz, onz, dnzu, onzu, *J, fillMatrix);CHKERRQ(ierr); 841 ierr = PetscFree4(dnz, onz, dnzu, onzu);CHKERRQ(ierr); 842 843 /* Set localtoglobalmapping on the matrix for MatSetValuesLocal() to work */ 844 ierr = DMGetLocalToGlobalMapping(dm,<og);CHKERRQ(ierr); 845 ierr = MatSetLocalToGlobalMapping(*J,ltog,ltog);CHKERRQ(ierr); 846 } 847 PetscFunctionReturn(0); 848 } 849 850 #undef __FUNCT__ 851 #define __FUNCT__ "DMPlexGetChart" 852 /*@ 853 DMPlexGetChart - Return the interval for all mesh points [pStart, pEnd) 854 855 Not collective 856 857 Input Parameter: 858 . mesh - The DMPlex 859 860 Output Parameters: 861 + pStart - The first mesh point 862 - pEnd - The upper bound for mesh points 863 864 Level: beginner 865 866 .seealso: DMPlexCreate(), DMPlexSetChart() 867 @*/ 868 PetscErrorCode DMPlexGetChart(DM dm, PetscInt *pStart, PetscInt *pEnd) 869 { 870 DM_Plex *mesh = (DM_Plex*) dm->data; 871 PetscErrorCode ierr; 872 873 PetscFunctionBegin; 874 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 875 ierr = PetscSectionGetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 876 PetscFunctionReturn(0); 877 } 878 879 #undef __FUNCT__ 880 #define __FUNCT__ "DMPlexSetChart" 881 /*@ 882 DMPlexSetChart - Set the interval for all mesh points [pStart, pEnd) 883 884 Not collective 885 886 Input Parameters: 887 + mesh - The DMPlex 888 . pStart - The first mesh point 889 - pEnd - The upper bound for mesh points 890 891 Output Parameters: 892 893 Level: beginner 894 895 .seealso: DMPlexCreate(), DMPlexGetChart() 896 @*/ 897 PetscErrorCode DMPlexSetChart(DM dm, PetscInt pStart, PetscInt pEnd) 898 { 899 DM_Plex *mesh = (DM_Plex*) dm->data; 900 PetscErrorCode ierr; 901 902 PetscFunctionBegin; 903 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 904 ierr = PetscSectionSetChart(mesh->coneSection, pStart, pEnd);CHKERRQ(ierr); 905 ierr = PetscSectionSetChart(mesh->supportSection, pStart, pEnd);CHKERRQ(ierr); 906 PetscFunctionReturn(0); 907 } 908 909 #undef __FUNCT__ 910 #define __FUNCT__ "DMPlexGetConeSize" 911 /*@ 912 DMPlexGetConeSize - Return the number of in-edges for this point in the Sieve DAG 913 914 Not collective 915 916 Input Parameters: 917 + mesh - The DMPlex 918 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 919 920 Output Parameter: 921 . size - The cone size for point p 922 923 Level: beginner 924 925 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 926 @*/ 927 PetscErrorCode DMPlexGetConeSize(DM dm, PetscInt p, PetscInt *size) 928 { 929 DM_Plex *mesh = (DM_Plex*) dm->data; 930 PetscErrorCode ierr; 931 932 PetscFunctionBegin; 933 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 934 PetscValidPointer(size, 3); 935 ierr = PetscSectionGetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 936 PetscFunctionReturn(0); 937 } 938 939 #undef __FUNCT__ 940 #define __FUNCT__ "DMPlexSetConeSize" 941 /*@ 942 DMPlexSetConeSize - Set the number of in-edges for this point in the Sieve DAG 943 944 Not collective 945 946 Input Parameters: 947 + mesh - The DMPlex 948 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 949 - size - The cone size for point p 950 951 Output Parameter: 952 953 Note: 954 This should be called after DMPlexSetChart(). 955 956 Level: beginner 957 958 .seealso: DMPlexCreate(), DMPlexGetConeSize(), DMPlexSetChart() 959 @*/ 960 PetscErrorCode DMPlexSetConeSize(DM dm, PetscInt p, PetscInt size) 961 { 962 DM_Plex *mesh = (DM_Plex*) dm->data; 963 PetscErrorCode ierr; 964 965 PetscFunctionBegin; 966 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 967 ierr = PetscSectionSetDof(mesh->coneSection, p, size);CHKERRQ(ierr); 968 969 mesh->maxConeSize = PetscMax(mesh->maxConeSize, size); 970 PetscFunctionReturn(0); 971 } 972 973 #undef __FUNCT__ 974 #define __FUNCT__ "DMPlexAddConeSize" 975 /*@ 976 DMPlexAddConeSize - Add the given number of in-edges to this point in the Sieve DAG 977 978 Not collective 979 980 Input Parameters: 981 + mesh - The DMPlex 982 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 983 - size - The additional cone size for point p 984 985 Output Parameter: 986 987 Note: 988 This should be called after DMPlexSetChart(). 989 990 Level: beginner 991 992 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexGetConeSize(), DMPlexSetChart() 993 @*/ 994 PetscErrorCode DMPlexAddConeSize(DM dm, PetscInt p, PetscInt size) 995 { 996 DM_Plex *mesh = (DM_Plex*) dm->data; 997 PetscInt csize; 998 PetscErrorCode ierr; 999 1000 PetscFunctionBegin; 1001 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1002 ierr = PetscSectionAddDof(mesh->coneSection, p, size);CHKERRQ(ierr); 1003 ierr = PetscSectionGetDof(mesh->coneSection, p, &csize);CHKERRQ(ierr); 1004 1005 mesh->maxConeSize = PetscMax(mesh->maxConeSize, csize); 1006 PetscFunctionReturn(0); 1007 } 1008 1009 #undef __FUNCT__ 1010 #define __FUNCT__ "DMPlexGetCone" 1011 /*@C 1012 DMPlexGetCone - Return the points on the in-edges for this point in the Sieve DAG 1013 1014 Not collective 1015 1016 Input Parameters: 1017 + mesh - The DMPlex 1018 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1019 1020 Output Parameter: 1021 . cone - An array of points which are on the in-edges for point p 1022 1023 Level: beginner 1024 1025 Fortran Notes: 1026 Since it returns an array, this routine is only available in Fortran 90, and you must 1027 include petsc.h90 in your code. 1028 1029 You must also call DMPlexRestoreCone() after you finish using the returned array. 1030 1031 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart() 1032 @*/ 1033 PetscErrorCode DMPlexGetCone(DM dm, PetscInt p, const PetscInt *cone[]) 1034 { 1035 DM_Plex *mesh = (DM_Plex*) dm->data; 1036 PetscInt off; 1037 PetscErrorCode ierr; 1038 1039 PetscFunctionBegin; 1040 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1041 PetscValidPointer(cone, 3); 1042 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1043 *cone = &mesh->cones[off]; 1044 PetscFunctionReturn(0); 1045 } 1046 1047 #undef __FUNCT__ 1048 #define __FUNCT__ "DMPlexSetCone" 1049 /*@ 1050 DMPlexSetCone - Set the points on the in-edges for this point in the Sieve DAG 1051 1052 Not collective 1053 1054 Input Parameters: 1055 + mesh - The DMPlex 1056 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1057 - cone - An array of points which are on the in-edges for point p 1058 1059 Output Parameter: 1060 1061 Note: 1062 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1063 1064 Level: beginner 1065 1066 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1067 @*/ 1068 PetscErrorCode DMPlexSetCone(DM dm, PetscInt p, const PetscInt cone[]) 1069 { 1070 DM_Plex *mesh = (DM_Plex*) dm->data; 1071 PetscInt pStart, pEnd; 1072 PetscInt dof, off, c; 1073 PetscErrorCode ierr; 1074 1075 PetscFunctionBegin; 1076 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1077 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1078 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1079 if (dof) PetscValidPointer(cone, 3); 1080 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1081 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1082 for (c = 0; c < dof; ++c) { 1083 if ((cone[c] < pStart) || (cone[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", cone[c], pStart, pEnd); 1084 mesh->cones[off+c] = cone[c]; 1085 } 1086 PetscFunctionReturn(0); 1087 } 1088 1089 #undef __FUNCT__ 1090 #define __FUNCT__ "DMPlexGetConeOrientation" 1091 /*@C 1092 DMPlexGetConeOrientation - Return the orientations on the in-edges for this point in the Sieve DAG 1093 1094 Not collective 1095 1096 Input Parameters: 1097 + mesh - The DMPlex 1098 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1099 1100 Output Parameter: 1101 . coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1102 integer giving the prescription for cone traversal. If it is negative, the cone is 1103 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1104 the index of the cone point on which to start. 1105 1106 Level: beginner 1107 1108 Fortran Notes: 1109 Since it returns an array, this routine is only available in Fortran 90, and you must 1110 include petsc.h90 in your code. 1111 1112 You must also call DMPlexRestoreConeOrientation() after you finish using the returned array. 1113 1114 .seealso: DMPlexCreate(), DMPlexGetCone(), DMPlexSetCone(), DMPlexSetChart() 1115 @*/ 1116 PetscErrorCode DMPlexGetConeOrientation(DM dm, PetscInt p, const PetscInt *coneOrientation[]) 1117 { 1118 DM_Plex *mesh = (DM_Plex*) dm->data; 1119 PetscInt off; 1120 PetscErrorCode ierr; 1121 1122 PetscFunctionBegin; 1123 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1124 #if defined(PETSC_USE_DEBUG) 1125 { 1126 PetscInt dof; 1127 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1128 if (dof) PetscValidPointer(coneOrientation, 3); 1129 } 1130 #endif 1131 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1132 1133 *coneOrientation = &mesh->coneOrientations[off]; 1134 PetscFunctionReturn(0); 1135 } 1136 1137 #undef __FUNCT__ 1138 #define __FUNCT__ "DMPlexSetConeOrientation" 1139 /*@ 1140 DMPlexSetConeOrientation - Set the orientations on the in-edges for this point in the Sieve DAG 1141 1142 Not collective 1143 1144 Input Parameters: 1145 + mesh - The DMPlex 1146 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1147 - coneOrientation - An array of orientations which are on the in-edges for point p. An orientation is an 1148 integer giving the prescription for cone traversal. If it is negative, the cone is 1149 traversed in the opposite direction. Its value 'o', or if negative '-(o+1)', gives 1150 the index of the cone point on which to start. 1151 1152 Output Parameter: 1153 1154 Note: 1155 This should be called after all calls to DMPlexSetConeSize() and DMSetUp(). 1156 1157 Level: beginner 1158 1159 .seealso: DMPlexCreate(), DMPlexGetConeOrientation(), DMPlexSetCone(), DMPlexSetChart(), DMPlexSetConeSize(), DMSetUp() 1160 @*/ 1161 PetscErrorCode DMPlexSetConeOrientation(DM dm, PetscInt p, const PetscInt coneOrientation[]) 1162 { 1163 DM_Plex *mesh = (DM_Plex*) dm->data; 1164 PetscInt pStart, pEnd; 1165 PetscInt dof, off, c; 1166 PetscErrorCode ierr; 1167 1168 PetscFunctionBegin; 1169 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1170 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1171 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1172 if (dof) PetscValidPointer(coneOrientation, 3); 1173 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1174 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1175 for (c = 0; c < dof; ++c) { 1176 PetscInt cdof, o = coneOrientation[c]; 1177 1178 ierr = PetscSectionGetDof(mesh->coneSection, mesh->cones[off+c], &cdof);CHKERRQ(ierr); 1179 if (o && ((o < -(cdof+1)) || (o >= cdof))) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone orientation %D is not in the valid range [%D. %D)", o, -(cdof+1), cdof); 1180 mesh->coneOrientations[off+c] = o; 1181 } 1182 PetscFunctionReturn(0); 1183 } 1184 1185 #undef __FUNCT__ 1186 #define __FUNCT__ "DMPlexInsertCone" 1187 PetscErrorCode DMPlexInsertCone(DM dm, PetscInt p, PetscInt conePos, PetscInt conePoint) 1188 { 1189 DM_Plex *mesh = (DM_Plex*) dm->data; 1190 PetscInt pStart, pEnd; 1191 PetscInt dof, off; 1192 PetscErrorCode ierr; 1193 1194 PetscFunctionBegin; 1195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1196 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1197 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1198 if ((conePoint < pStart) || (conePoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone point %D is not in the valid range [%D, %D)", conePoint, pStart, pEnd); 1199 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1200 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1201 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1202 mesh->cones[off+conePos] = conePoint; 1203 PetscFunctionReturn(0); 1204 } 1205 1206 #undef __FUNCT__ 1207 #define __FUNCT__ "DMPlexInsertConeOrientation" 1208 PetscErrorCode DMPlexInsertConeOrientation(DM dm, PetscInt p, PetscInt conePos, PetscInt coneOrientation) 1209 { 1210 DM_Plex *mesh = (DM_Plex*) dm->data; 1211 PetscInt pStart, pEnd; 1212 PetscInt dof, off; 1213 PetscErrorCode ierr; 1214 1215 PetscFunctionBegin; 1216 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1217 ierr = PetscSectionGetChart(mesh->coneSection, &pStart, &pEnd);CHKERRQ(ierr); 1218 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1219 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1220 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1221 if ((conePos < 0) || (conePos >= dof)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Cone position %D of point %D is not in the valid range [0, %D)", conePos, p, dof); 1222 mesh->coneOrientations[off+conePos] = coneOrientation; 1223 PetscFunctionReturn(0); 1224 } 1225 1226 #undef __FUNCT__ 1227 #define __FUNCT__ "DMPlexGetSupportSize" 1228 /*@ 1229 DMPlexGetSupportSize - Return the number of out-edges for this point in the Sieve DAG 1230 1231 Not collective 1232 1233 Input Parameters: 1234 + mesh - The DMPlex 1235 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1236 1237 Output Parameter: 1238 . size - The support size for point p 1239 1240 Level: beginner 1241 1242 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart(), DMPlexGetConeSize() 1243 @*/ 1244 PetscErrorCode DMPlexGetSupportSize(DM dm, PetscInt p, PetscInt *size) 1245 { 1246 DM_Plex *mesh = (DM_Plex*) dm->data; 1247 PetscErrorCode ierr; 1248 1249 PetscFunctionBegin; 1250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1251 PetscValidPointer(size, 3); 1252 ierr = PetscSectionGetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1253 PetscFunctionReturn(0); 1254 } 1255 1256 #undef __FUNCT__ 1257 #define __FUNCT__ "DMPlexSetSupportSize" 1258 /*@ 1259 DMPlexSetSupportSize - Set the number of out-edges for this point in the Sieve DAG 1260 1261 Not collective 1262 1263 Input Parameters: 1264 + mesh - The DMPlex 1265 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1266 - size - The support size for point p 1267 1268 Output Parameter: 1269 1270 Note: 1271 This should be called after DMPlexSetChart(). 1272 1273 Level: beginner 1274 1275 .seealso: DMPlexCreate(), DMPlexGetSupportSize(), DMPlexSetChart() 1276 @*/ 1277 PetscErrorCode DMPlexSetSupportSize(DM dm, PetscInt p, PetscInt size) 1278 { 1279 DM_Plex *mesh = (DM_Plex*) dm->data; 1280 PetscErrorCode ierr; 1281 1282 PetscFunctionBegin; 1283 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1284 ierr = PetscSectionSetDof(mesh->supportSection, p, size);CHKERRQ(ierr); 1285 1286 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, size); 1287 PetscFunctionReturn(0); 1288 } 1289 1290 #undef __FUNCT__ 1291 #define __FUNCT__ "DMPlexGetSupport" 1292 /*@C 1293 DMPlexGetSupport - Return the points on the out-edges for this point in the Sieve DAG 1294 1295 Not collective 1296 1297 Input Parameters: 1298 + mesh - The DMPlex 1299 - p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1300 1301 Output Parameter: 1302 . support - An array of points which are on the out-edges for point p 1303 1304 Level: beginner 1305 1306 Fortran Notes: 1307 Since it returns an array, this routine is only available in Fortran 90, and you must 1308 include petsc.h90 in your code. 1309 1310 You must also call DMPlexRestoreSupport() after you finish using the returned array. 1311 1312 .seealso: DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1313 @*/ 1314 PetscErrorCode DMPlexGetSupport(DM dm, PetscInt p, const PetscInt *support[]) 1315 { 1316 DM_Plex *mesh = (DM_Plex*) dm->data; 1317 PetscInt off; 1318 PetscErrorCode ierr; 1319 1320 PetscFunctionBegin; 1321 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1322 PetscValidPointer(support, 3); 1323 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1324 *support = &mesh->supports[off]; 1325 PetscFunctionReturn(0); 1326 } 1327 1328 #undef __FUNCT__ 1329 #define __FUNCT__ "DMPlexSetSupport" 1330 /*@ 1331 DMPlexSetSupport - Set the points on the out-edges for this point in the Sieve DAG 1332 1333 Not collective 1334 1335 Input Parameters: 1336 + mesh - The DMPlex 1337 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1338 - support - An array of points which are on the in-edges for point p 1339 1340 Output Parameter: 1341 1342 Note: 1343 This should be called after all calls to DMPlexSetSupportSize() and DMSetUp(). 1344 1345 Level: beginner 1346 1347 .seealso: DMPlexCreate(), DMPlexGetSupport(), DMPlexSetChart(), DMPlexSetSupportSize(), DMSetUp() 1348 @*/ 1349 PetscErrorCode DMPlexSetSupport(DM dm, PetscInt p, const PetscInt support[]) 1350 { 1351 DM_Plex *mesh = (DM_Plex*) dm->data; 1352 PetscInt pStart, pEnd; 1353 PetscInt dof, off, c; 1354 PetscErrorCode ierr; 1355 1356 PetscFunctionBegin; 1357 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1358 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1359 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1360 if (dof) PetscValidPointer(support, 3); 1361 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1362 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1363 for (c = 0; c < dof; ++c) { 1364 if ((support[c] < pStart) || (support[c] >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", support[c], pStart, pEnd); 1365 mesh->supports[off+c] = support[c]; 1366 } 1367 PetscFunctionReturn(0); 1368 } 1369 1370 #undef __FUNCT__ 1371 #define __FUNCT__ "DMPlexInsertSupport" 1372 PetscErrorCode DMPlexInsertSupport(DM dm, PetscInt p, PetscInt supportPos, PetscInt supportPoint) 1373 { 1374 DM_Plex *mesh = (DM_Plex*) dm->data; 1375 PetscInt pStart, pEnd; 1376 PetscInt dof, off; 1377 PetscErrorCode ierr; 1378 1379 PetscFunctionBegin; 1380 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1381 ierr = PetscSectionGetChart(mesh->supportSection, &pStart, &pEnd);CHKERRQ(ierr); 1382 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1383 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 1384 if ((p < pStart) || (p >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Mesh point %D is not in the valid range [%D, %D)", p, pStart, pEnd); 1385 if ((supportPoint < pStart) || (supportPoint >= pEnd)) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support point %D is not in the valid range [%D, %D)", supportPoint, pStart, pEnd); 1386 if (supportPos >= dof) SETERRQ3(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Support position %D of point %D is not in the valid range [0, %D)", supportPos, p, dof); 1387 mesh->supports[off+supportPos] = supportPoint; 1388 PetscFunctionReturn(0); 1389 } 1390 1391 #undef __FUNCT__ 1392 #define __FUNCT__ "DMPlexGetTransitiveClosure" 1393 /*@C 1394 DMPlexGetTransitiveClosure - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1395 1396 Not collective 1397 1398 Input Parameters: 1399 + mesh - The DMPlex 1400 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1401 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1402 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1403 1404 Output Parameters: 1405 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1406 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1407 1408 Note: 1409 If using internal storage (points is NULL on input), each call overwrites the last output. 1410 1411 Fortran Notes: 1412 Since it returns an array, this routine is only available in Fortran 90, and you must 1413 include petsc.h90 in your code. 1414 1415 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1416 1417 Level: beginner 1418 1419 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1420 @*/ 1421 PetscErrorCode DMPlexGetTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1422 { 1423 DM_Plex *mesh = (DM_Plex*) dm->data; 1424 PetscInt *closure, *fifo; 1425 const PetscInt *tmp = NULL, *tmpO = NULL; 1426 PetscInt tmpSize, t; 1427 PetscInt depth = 0, maxSize; 1428 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1429 PetscErrorCode ierr; 1430 1431 PetscFunctionBegin; 1432 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1433 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1434 /* This is only 1-level */ 1435 if (useCone) { 1436 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1437 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1438 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1439 } else { 1440 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1441 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1442 } 1443 if (depth == 1) { 1444 if (*points) { 1445 closure = *points; 1446 } else { 1447 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1448 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1449 } 1450 closure[0] = p; closure[1] = 0; 1451 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1452 closure[closureSize] = tmp[t]; 1453 closure[closureSize+1] = tmpO ? tmpO[t] : 0; 1454 } 1455 if (numPoints) *numPoints = closureSize/2; 1456 if (points) *points = closure; 1457 PetscFunctionReturn(0); 1458 } 1459 { 1460 PetscInt c, coneSeries, s,supportSeries; 1461 1462 c = mesh->maxConeSize; 1463 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1464 s = mesh->maxSupportSize; 1465 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1466 maxSize = 2*PetscMax(coneSeries,supportSeries); 1467 } 1468 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1469 if (*points) { 1470 closure = *points; 1471 } else { 1472 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1473 } 1474 closure[0] = p; closure[1] = 0; 1475 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1476 const PetscInt cp = tmp[t]; 1477 const PetscInt co = tmpO ? tmpO[t] : 0; 1478 1479 closure[closureSize] = cp; 1480 closure[closureSize+1] = co; 1481 fifo[fifoSize] = cp; 1482 fifo[fifoSize+1] = co; 1483 } 1484 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1485 while (fifoSize - fifoStart) { 1486 const PetscInt q = fifo[fifoStart]; 1487 const PetscInt o = fifo[fifoStart+1]; 1488 const PetscInt rev = o >= 0 ? 0 : 1; 1489 const PetscInt off = rev ? -(o+1) : o; 1490 1491 if (useCone) { 1492 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1493 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1494 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1495 } else { 1496 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1497 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1498 tmpO = NULL; 1499 } 1500 for (t = 0; t < tmpSize; ++t) { 1501 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1502 const PetscInt cp = tmp[i]; 1503 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1504 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1505 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1506 PetscInt co = tmpO ? tmpO[i] : 0; 1507 PetscInt c; 1508 1509 if (rev) { 1510 PetscInt childSize, coff; 1511 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1512 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1513 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1514 } 1515 /* Check for duplicate */ 1516 for (c = 0; c < closureSize; c += 2) { 1517 if (closure[c] == cp) break; 1518 } 1519 if (c == closureSize) { 1520 closure[closureSize] = cp; 1521 closure[closureSize+1] = co; 1522 fifo[fifoSize] = cp; 1523 fifo[fifoSize+1] = co; 1524 closureSize += 2; 1525 fifoSize += 2; 1526 } 1527 } 1528 fifoStart += 2; 1529 } 1530 if (numPoints) *numPoints = closureSize/2; 1531 if (points) *points = closure; 1532 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1533 PetscFunctionReturn(0); 1534 } 1535 1536 #undef __FUNCT__ 1537 #define __FUNCT__ "DMPlexGetTransitiveClosure_Internal" 1538 /*@C 1539 DMPlexGetTransitiveClosure_Internal - Return the points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG with a specified initial orientation 1540 1541 Not collective 1542 1543 Input Parameters: 1544 + mesh - The DMPlex 1545 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1546 . orientation - The orientation of the point 1547 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1548 - points - If points is NULL on input, internal storage will be returned, otherwise the provided array is used 1549 1550 Output Parameters: 1551 + numPoints - The number of points in the closure, so points[] is of size 2*numPoints 1552 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...] 1553 1554 Note: 1555 If using internal storage (points is NULL on input), each call overwrites the last output. 1556 1557 Fortran Notes: 1558 Since it returns an array, this routine is only available in Fortran 90, and you must 1559 include petsc.h90 in your code. 1560 1561 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1562 1563 Level: beginner 1564 1565 .seealso: DMPlexRestoreTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1566 @*/ 1567 PetscErrorCode DMPlexGetTransitiveClosure_Internal(DM dm, PetscInt p, PetscInt ornt, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1568 { 1569 DM_Plex *mesh = (DM_Plex*) dm->data; 1570 PetscInt *closure, *fifo; 1571 const PetscInt *tmp = NULL, *tmpO = NULL; 1572 PetscInt tmpSize, t; 1573 PetscInt depth = 0, maxSize; 1574 PetscInt closureSize = 2, fifoSize = 0, fifoStart = 0; 1575 PetscErrorCode ierr; 1576 1577 PetscFunctionBegin; 1578 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1579 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 1580 /* This is only 1-level */ 1581 if (useCone) { 1582 ierr = DMPlexGetConeSize(dm, p, &tmpSize);CHKERRQ(ierr); 1583 ierr = DMPlexGetCone(dm, p, &tmp);CHKERRQ(ierr); 1584 ierr = DMPlexGetConeOrientation(dm, p, &tmpO);CHKERRQ(ierr); 1585 } else { 1586 ierr = DMPlexGetSupportSize(dm, p, &tmpSize);CHKERRQ(ierr); 1587 ierr = DMPlexGetSupport(dm, p, &tmp);CHKERRQ(ierr); 1588 } 1589 if (depth == 1) { 1590 if (*points) { 1591 closure = *points; 1592 } else { 1593 maxSize = 2*(PetscMax(mesh->maxConeSize, mesh->maxSupportSize)+1); 1594 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1595 } 1596 closure[0] = p; closure[1] = ornt; 1597 for (t = 0; t < tmpSize; ++t, closureSize += 2) { 1598 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1599 closure[closureSize] = tmp[i]; 1600 closure[closureSize+1] = tmpO ? tmpO[i] : 0; 1601 } 1602 if (numPoints) *numPoints = closureSize/2; 1603 if (points) *points = closure; 1604 PetscFunctionReturn(0); 1605 } 1606 { 1607 PetscInt c, coneSeries, s,supportSeries; 1608 1609 c = mesh->maxConeSize; 1610 coneSeries = (c > 1) ? ((PetscPowInt(c,depth+1)-1)/(c-1)) : depth+1; 1611 s = mesh->maxSupportSize; 1612 supportSeries = (s > 1) ? ((PetscPowInt(s,depth+1)-1)/(s-1)) : depth+1; 1613 maxSize = 2*PetscMax(coneSeries,supportSeries); 1614 } 1615 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1616 if (*points) { 1617 closure = *points; 1618 } else { 1619 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &closure);CHKERRQ(ierr); 1620 } 1621 closure[0] = p; closure[1] = ornt; 1622 for (t = 0; t < tmpSize; ++t, closureSize += 2, fifoSize += 2) { 1623 const PetscInt i = ornt >= 0 ? (t+ornt)%tmpSize : (-(ornt+1) + tmpSize-t)%tmpSize; 1624 const PetscInt cp = tmp[i]; 1625 PetscInt co = tmpO ? tmpO[i] : 0; 1626 1627 if (ornt < 0) { 1628 PetscInt childSize, coff; 1629 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1630 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1631 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1632 } 1633 closure[closureSize] = cp; 1634 closure[closureSize+1] = co; 1635 fifo[fifoSize] = cp; 1636 fifo[fifoSize+1] = co; 1637 } 1638 /* Should kick out early when depth is reached, rather than checking all vertices for empty cones */ 1639 while (fifoSize - fifoStart) { 1640 const PetscInt q = fifo[fifoStart]; 1641 const PetscInt o = fifo[fifoStart+1]; 1642 const PetscInt rev = o >= 0 ? 0 : 1; 1643 const PetscInt off = rev ? -(o+1) : o; 1644 1645 if (useCone) { 1646 ierr = DMPlexGetConeSize(dm, q, &tmpSize);CHKERRQ(ierr); 1647 ierr = DMPlexGetCone(dm, q, &tmp);CHKERRQ(ierr); 1648 ierr = DMPlexGetConeOrientation(dm, q, &tmpO);CHKERRQ(ierr); 1649 } else { 1650 ierr = DMPlexGetSupportSize(dm, q, &tmpSize);CHKERRQ(ierr); 1651 ierr = DMPlexGetSupport(dm, q, &tmp);CHKERRQ(ierr); 1652 tmpO = NULL; 1653 } 1654 for (t = 0; t < tmpSize; ++t) { 1655 const PetscInt i = ((rev ? tmpSize-t : t) + off)%tmpSize; 1656 const PetscInt cp = tmp[i]; 1657 /* Must propogate orientation: When we reverse orientation, we both reverse the direction of iteration and start at the other end of the chain. */ 1658 /* HACK: It is worse to get the size here, than to change the interpretation of -(*+1) 1659 const PetscInt co = tmpO ? (rev ? -(tmpO[i]+1) : tmpO[i]) : 0; */ 1660 PetscInt co = tmpO ? tmpO[i] : 0; 1661 PetscInt c; 1662 1663 if (rev) { 1664 PetscInt childSize, coff; 1665 ierr = DMPlexGetConeSize(dm, cp, &childSize);CHKERRQ(ierr); 1666 coff = tmpO[i] < 0 ? -(tmpO[i]+1) : tmpO[i]; 1667 co = childSize ? -(((coff+childSize-1)%childSize)+1) : 0; 1668 } 1669 /* Check for duplicate */ 1670 for (c = 0; c < closureSize; c += 2) { 1671 if (closure[c] == cp) break; 1672 } 1673 if (c == closureSize) { 1674 closure[closureSize] = cp; 1675 closure[closureSize+1] = co; 1676 fifo[fifoSize] = cp; 1677 fifo[fifoSize+1] = co; 1678 closureSize += 2; 1679 fifoSize += 2; 1680 } 1681 } 1682 fifoStart += 2; 1683 } 1684 if (numPoints) *numPoints = closureSize/2; 1685 if (points) *points = closure; 1686 ierr = DMRestoreWorkArray(dm, maxSize, PETSC_INT, &fifo);CHKERRQ(ierr); 1687 PetscFunctionReturn(0); 1688 } 1689 1690 #undef __FUNCT__ 1691 #define __FUNCT__ "DMPlexRestoreTransitiveClosure" 1692 /*@C 1693 DMPlexRestoreTransitiveClosure - Restore the array of points on the transitive closure of the in-edges or out-edges for this point in the Sieve DAG 1694 1695 Not collective 1696 1697 Input Parameters: 1698 + mesh - The DMPlex 1699 . p - The Sieve point, which must lie in the chart set with DMPlexSetChart() 1700 . useCone - PETSC_TRUE for in-edges, otherwise use out-edges 1701 . numPoints - The number of points in the closure, so points[] is of size 2*numPoints, zeroed on exit 1702 - points - The points and point orientations, interleaved as pairs [p0, o0, p1, o1, ...], zeroed on exit 1703 1704 Note: 1705 If not using internal storage (points is not NULL on input), this call is unnecessary 1706 1707 Fortran Notes: 1708 Since it returns an array, this routine is only available in Fortran 90, and you must 1709 include petsc.h90 in your code. 1710 1711 The numPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1712 1713 Level: beginner 1714 1715 .seealso: DMPlexGetTransitiveClosure(), DMPlexCreate(), DMPlexSetCone(), DMPlexSetChart(), DMPlexGetCone() 1716 @*/ 1717 PetscErrorCode DMPlexRestoreTransitiveClosure(DM dm, PetscInt p, PetscBool useCone, PetscInt *numPoints, PetscInt *points[]) 1718 { 1719 PetscErrorCode ierr; 1720 1721 PetscFunctionBegin; 1722 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1723 if (numPoints) PetscValidIntPointer(numPoints,4); 1724 if (points) PetscValidPointer(points,5); 1725 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, points);CHKERRQ(ierr); 1726 if (numPoints) *numPoints = 0; 1727 PetscFunctionReturn(0); 1728 } 1729 1730 #undef __FUNCT__ 1731 #define __FUNCT__ "DMPlexGetMaxSizes" 1732 /*@ 1733 DMPlexGetMaxSizes - Return the maximum number of in-edges (cone) and out-edges (support) for any point in the Sieve DAG 1734 1735 Not collective 1736 1737 Input Parameter: 1738 . mesh - The DMPlex 1739 1740 Output Parameters: 1741 + maxConeSize - The maximum number of in-edges 1742 - maxSupportSize - The maximum number of out-edges 1743 1744 Level: beginner 1745 1746 .seealso: DMPlexCreate(), DMPlexSetConeSize(), DMPlexSetChart() 1747 @*/ 1748 PetscErrorCode DMPlexGetMaxSizes(DM dm, PetscInt *maxConeSize, PetscInt *maxSupportSize) 1749 { 1750 DM_Plex *mesh = (DM_Plex*) dm->data; 1751 1752 PetscFunctionBegin; 1753 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1754 if (maxConeSize) *maxConeSize = mesh->maxConeSize; 1755 if (maxSupportSize) *maxSupportSize = mesh->maxSupportSize; 1756 PetscFunctionReturn(0); 1757 } 1758 1759 #undef __FUNCT__ 1760 #define __FUNCT__ "DMSetUp_Plex" 1761 PetscErrorCode DMSetUp_Plex(DM dm) 1762 { 1763 DM_Plex *mesh = (DM_Plex*) dm->data; 1764 PetscInt size; 1765 PetscErrorCode ierr; 1766 1767 PetscFunctionBegin; 1768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1769 ierr = PetscSectionSetUp(mesh->coneSection);CHKERRQ(ierr); 1770 ierr = PetscSectionGetStorageSize(mesh->coneSection, &size);CHKERRQ(ierr); 1771 ierr = PetscMalloc1(size, &mesh->cones);CHKERRQ(ierr); 1772 ierr = PetscCalloc1(size, &mesh->coneOrientations);CHKERRQ(ierr); 1773 if (mesh->maxSupportSize) { 1774 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1775 ierr = PetscSectionGetStorageSize(mesh->supportSection, &size);CHKERRQ(ierr); 1776 ierr = PetscMalloc1(size, &mesh->supports);CHKERRQ(ierr); 1777 } 1778 PetscFunctionReturn(0); 1779 } 1780 1781 #undef __FUNCT__ 1782 #define __FUNCT__ "DMCreateSubDM_Plex" 1783 PetscErrorCode DMCreateSubDM_Plex(DM dm, PetscInt numFields, PetscInt fields[], IS *is, DM *subdm) 1784 { 1785 PetscErrorCode ierr; 1786 1787 PetscFunctionBegin; 1788 if (subdm) {ierr = DMClone(dm, subdm);CHKERRQ(ierr);} 1789 ierr = DMCreateSubDM_Section_Private(dm, numFields, fields, is, subdm);CHKERRQ(ierr); 1790 PetscFunctionReturn(0); 1791 } 1792 1793 #undef __FUNCT__ 1794 #define __FUNCT__ "DMPlexSymmetrize" 1795 /*@ 1796 DMPlexSymmetrize - Creates support (out-edge) information from cone (in-edge) inoformation 1797 1798 Not collective 1799 1800 Input Parameter: 1801 . mesh - The DMPlex 1802 1803 Output Parameter: 1804 1805 Note: 1806 This should be called after all calls to DMPlexSetCone() 1807 1808 Level: beginner 1809 1810 .seealso: DMPlexCreate(), DMPlexSetChart(), DMPlexSetConeSize(), DMPlexSetCone() 1811 @*/ 1812 PetscErrorCode DMPlexSymmetrize(DM dm) 1813 { 1814 DM_Plex *mesh = (DM_Plex*) dm->data; 1815 PetscInt *offsets; 1816 PetscInt supportSize; 1817 PetscInt pStart, pEnd, p; 1818 PetscErrorCode ierr; 1819 1820 PetscFunctionBegin; 1821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1822 if (mesh->supports) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONGSTATE, "Supports were already setup in this DMPlex"); 1823 /* Calculate support sizes */ 1824 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1825 for (p = pStart; p < pEnd; ++p) { 1826 PetscInt dof, off, c; 1827 1828 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1829 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1830 for (c = off; c < off+dof; ++c) { 1831 ierr = PetscSectionAddDof(mesh->supportSection, mesh->cones[c], 1);CHKERRQ(ierr); 1832 } 1833 } 1834 for (p = pStart; p < pEnd; ++p) { 1835 PetscInt dof; 1836 1837 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 1838 1839 mesh->maxSupportSize = PetscMax(mesh->maxSupportSize, dof); 1840 } 1841 ierr = PetscSectionSetUp(mesh->supportSection);CHKERRQ(ierr); 1842 /* Calculate supports */ 1843 ierr = PetscSectionGetStorageSize(mesh->supportSection, &supportSize);CHKERRQ(ierr); 1844 ierr = PetscMalloc1(supportSize, &mesh->supports);CHKERRQ(ierr); 1845 ierr = PetscCalloc1(pEnd - pStart, &offsets);CHKERRQ(ierr); 1846 for (p = pStart; p < pEnd; ++p) { 1847 PetscInt dof, off, c; 1848 1849 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 1850 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 1851 for (c = off; c < off+dof; ++c) { 1852 const PetscInt q = mesh->cones[c]; 1853 PetscInt offS; 1854 1855 ierr = PetscSectionGetOffset(mesh->supportSection, q, &offS);CHKERRQ(ierr); 1856 1857 mesh->supports[offS+offsets[q]] = p; 1858 ++offsets[q]; 1859 } 1860 } 1861 ierr = PetscFree(offsets);CHKERRQ(ierr); 1862 PetscFunctionReturn(0); 1863 } 1864 1865 #undef __FUNCT__ 1866 #define __FUNCT__ "DMPlexStratify" 1867 /*@ 1868 DMPlexStratify - The Sieve DAG for most topologies is a graded poset (http://en.wikipedia.org/wiki/Graded_poset), and 1869 can be illustrated by Hasse Diagram (a http://en.wikipedia.org/wiki/Hasse_diagram). The strata group all points of the 1870 same grade, and this function calculates the strata. This grade can be seen as the height (or depth) of the point in 1871 the DAG. 1872 1873 Not collective 1874 1875 Input Parameter: 1876 . mesh - The DMPlex 1877 1878 Output Parameter: 1879 1880 Notes: 1881 Concretely, DMPlexStratify() creates a new label named "depth" containing the dimension of each element: 0 for vertices, 1882 1 for edges, and so on. The depth label can be accessed through DMPlexGetDepthLabel() or DMPlexGetDepthStratum(), or 1883 manually via DMPlexGetLabel(). The height is defined implicitly by height = maxDimension - depth, and can be accessed 1884 via DMPlexGetHeightStratum(). For example, cells have height 0 and faces have height 1. 1885 1886 DMPlexStratify() should be called after all calls to DMPlexSymmetrize() 1887 1888 Level: beginner 1889 1890 .seealso: DMPlexCreate(), DMPlexSymmetrize() 1891 @*/ 1892 PetscErrorCode DMPlexStratify(DM dm) 1893 { 1894 DMLabel label; 1895 PetscInt pStart, pEnd, p; 1896 PetscInt numRoots = 0, numLeaves = 0; 1897 PetscErrorCode ierr; 1898 1899 PetscFunctionBegin; 1900 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1901 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1902 /* Calculate depth */ 1903 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1904 ierr = DMPlexCreateLabel(dm, "depth");CHKERRQ(ierr); 1905 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 1906 /* Initialize roots and count leaves */ 1907 for (p = pStart; p < pEnd; ++p) { 1908 PetscInt coneSize, supportSize; 1909 1910 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1911 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1912 if (!coneSize && supportSize) { 1913 ++numRoots; 1914 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1915 } else if (!supportSize && coneSize) { 1916 ++numLeaves; 1917 } else if (!supportSize && !coneSize) { 1918 /* Isolated points */ 1919 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1920 } 1921 } 1922 if (numRoots + numLeaves == (pEnd - pStart)) { 1923 for (p = pStart; p < pEnd; ++p) { 1924 PetscInt coneSize, supportSize; 1925 1926 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1927 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1928 if (!supportSize && coneSize) { 1929 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 1930 } 1931 } 1932 } else { 1933 IS pointIS; 1934 PetscInt numPoints = 0, level = 0; 1935 1936 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1937 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1938 while (numPoints) { 1939 const PetscInt *points; 1940 const PetscInt newLevel = level+1; 1941 1942 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 1943 for (p = 0; p < numPoints; ++p) { 1944 const PetscInt point = points[p]; 1945 const PetscInt *support; 1946 PetscInt supportSize, s; 1947 1948 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 1949 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 1950 for (s = 0; s < supportSize; ++s) { 1951 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 1952 } 1953 } 1954 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 1955 ++level; 1956 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1957 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1958 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1959 else {numPoints = 0;} 1960 } 1961 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1962 } 1963 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1964 PetscFunctionReturn(0); 1965 } 1966 1967 #undef __FUNCT__ 1968 #define __FUNCT__ "DMPlexGetJoin" 1969 /*@C 1970 DMPlexGetJoin - Get an array for the join of the set of points 1971 1972 Not Collective 1973 1974 Input Parameters: 1975 + dm - The DMPlex object 1976 . numPoints - The number of input points for the join 1977 - points - The input points 1978 1979 Output Parameters: 1980 + numCoveredPoints - The number of points in the join 1981 - coveredPoints - The points in the join 1982 1983 Level: intermediate 1984 1985 Note: Currently, this is restricted to a single level join 1986 1987 Fortran Notes: 1988 Since it returns an array, this routine is only available in Fortran 90, and you must 1989 include petsc.h90 in your code. 1990 1991 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 1992 1993 .keywords: mesh 1994 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 1995 @*/ 1996 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 1997 { 1998 DM_Plex *mesh = (DM_Plex*) dm->data; 1999 PetscInt *join[2]; 2000 PetscInt joinSize, i = 0; 2001 PetscInt dof, off, p, c, m; 2002 PetscErrorCode ierr; 2003 2004 PetscFunctionBegin; 2005 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2006 PetscValidPointer(points, 2); 2007 PetscValidPointer(numCoveredPoints, 3); 2008 PetscValidPointer(coveredPoints, 4); 2009 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2010 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2011 /* Copy in support of first point */ 2012 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2013 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2014 for (joinSize = 0; joinSize < dof; ++joinSize) { 2015 join[i][joinSize] = mesh->supports[off+joinSize]; 2016 } 2017 /* Check each successive support */ 2018 for (p = 1; p < numPoints; ++p) { 2019 PetscInt newJoinSize = 0; 2020 2021 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2022 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2023 for (c = 0; c < dof; ++c) { 2024 const PetscInt point = mesh->supports[off+c]; 2025 2026 for (m = 0; m < joinSize; ++m) { 2027 if (point == join[i][m]) { 2028 join[1-i][newJoinSize++] = point; 2029 break; 2030 } 2031 } 2032 } 2033 joinSize = newJoinSize; 2034 i = 1-i; 2035 } 2036 *numCoveredPoints = joinSize; 2037 *coveredPoints = join[i]; 2038 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2039 PetscFunctionReturn(0); 2040 } 2041 2042 #undef __FUNCT__ 2043 #define __FUNCT__ "DMPlexRestoreJoin" 2044 /*@C 2045 DMPlexRestoreJoin - Restore an array for the join of the set of points 2046 2047 Not Collective 2048 2049 Input Parameters: 2050 + dm - The DMPlex object 2051 . numPoints - The number of input points for the join 2052 - points - The input points 2053 2054 Output Parameters: 2055 + numCoveredPoints - The number of points in the join 2056 - coveredPoints - The points in the join 2057 2058 Fortran Notes: 2059 Since it returns an array, this routine is only available in Fortran 90, and you must 2060 include petsc.h90 in your code. 2061 2062 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2063 2064 Level: intermediate 2065 2066 .keywords: mesh 2067 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2068 @*/ 2069 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2070 { 2071 PetscErrorCode ierr; 2072 2073 PetscFunctionBegin; 2074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2075 if (points) PetscValidIntPointer(points,3); 2076 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2077 PetscValidPointer(coveredPoints, 5); 2078 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2079 if (numCoveredPoints) *numCoveredPoints = 0; 2080 PetscFunctionReturn(0); 2081 } 2082 2083 #undef __FUNCT__ 2084 #define __FUNCT__ "DMPlexGetFullJoin" 2085 /*@C 2086 DMPlexGetFullJoin - Get an array for the join of the set of points 2087 2088 Not Collective 2089 2090 Input Parameters: 2091 + dm - The DMPlex object 2092 . numPoints - The number of input points for the join 2093 - points - The input points 2094 2095 Output Parameters: 2096 + numCoveredPoints - The number of points in the join 2097 - coveredPoints - The points in the join 2098 2099 Fortran Notes: 2100 Since it returns an array, this routine is only available in Fortran 90, and you must 2101 include petsc.h90 in your code. 2102 2103 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2104 2105 Level: intermediate 2106 2107 .keywords: mesh 2108 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2109 @*/ 2110 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2111 { 2112 DM_Plex *mesh = (DM_Plex*) dm->data; 2113 PetscInt *offsets, **closures; 2114 PetscInt *join[2]; 2115 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2116 PetscInt p, d, c, m, ms; 2117 PetscErrorCode ierr; 2118 2119 PetscFunctionBegin; 2120 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2121 PetscValidPointer(points, 2); 2122 PetscValidPointer(numCoveredPoints, 3); 2123 PetscValidPointer(coveredPoints, 4); 2124 2125 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2126 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2127 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2128 ms = mesh->maxSupportSize; 2129 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2130 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2131 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2132 2133 for (p = 0; p < numPoints; ++p) { 2134 PetscInt closureSize; 2135 2136 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2137 2138 offsets[p*(depth+2)+0] = 0; 2139 for (d = 0; d < depth+1; ++d) { 2140 PetscInt pStart, pEnd, i; 2141 2142 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2143 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2144 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2145 offsets[p*(depth+2)+d+1] = i; 2146 break; 2147 } 2148 } 2149 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2150 } 2151 if (offsets[p*(depth+2)+depth+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(depth+2)+depth+1], closureSize); 2152 } 2153 for (d = 0; d < depth+1; ++d) { 2154 PetscInt dof; 2155 2156 /* Copy in support of first point */ 2157 dof = offsets[d+1] - offsets[d]; 2158 for (joinSize = 0; joinSize < dof; ++joinSize) { 2159 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2160 } 2161 /* Check each successive cone */ 2162 for (p = 1; p < numPoints && joinSize; ++p) { 2163 PetscInt newJoinSize = 0; 2164 2165 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2166 for (c = 0; c < dof; ++c) { 2167 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2168 2169 for (m = 0; m < joinSize; ++m) { 2170 if (point == join[i][m]) { 2171 join[1-i][newJoinSize++] = point; 2172 break; 2173 } 2174 } 2175 } 2176 joinSize = newJoinSize; 2177 i = 1-i; 2178 } 2179 if (joinSize) break; 2180 } 2181 *numCoveredPoints = joinSize; 2182 *coveredPoints = join[i]; 2183 for (p = 0; p < numPoints; ++p) { 2184 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2185 } 2186 ierr = PetscFree(closures);CHKERRQ(ierr); 2187 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2188 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2189 PetscFunctionReturn(0); 2190 } 2191 2192 #undef __FUNCT__ 2193 #define __FUNCT__ "DMPlexGetMeet" 2194 /*@C 2195 DMPlexGetMeet - Get an array for the meet of the set of points 2196 2197 Not Collective 2198 2199 Input Parameters: 2200 + dm - The DMPlex object 2201 . numPoints - The number of input points for the meet 2202 - points - The input points 2203 2204 Output Parameters: 2205 + numCoveredPoints - The number of points in the meet 2206 - coveredPoints - The points in the meet 2207 2208 Level: intermediate 2209 2210 Note: Currently, this is restricted to a single level meet 2211 2212 Fortran Notes: 2213 Since it returns an array, this routine is only available in Fortran 90, and you must 2214 include petsc.h90 in your code. 2215 2216 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2217 2218 .keywords: mesh 2219 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2220 @*/ 2221 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2222 { 2223 DM_Plex *mesh = (DM_Plex*) dm->data; 2224 PetscInt *meet[2]; 2225 PetscInt meetSize, i = 0; 2226 PetscInt dof, off, p, c, m; 2227 PetscErrorCode ierr; 2228 2229 PetscFunctionBegin; 2230 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2231 PetscValidPointer(points, 2); 2232 PetscValidPointer(numCoveringPoints, 3); 2233 PetscValidPointer(coveringPoints, 4); 2234 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2235 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2236 /* Copy in cone of first point */ 2237 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2238 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2239 for (meetSize = 0; meetSize < dof; ++meetSize) { 2240 meet[i][meetSize] = mesh->cones[off+meetSize]; 2241 } 2242 /* Check each successive cone */ 2243 for (p = 1; p < numPoints; ++p) { 2244 PetscInt newMeetSize = 0; 2245 2246 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2247 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2248 for (c = 0; c < dof; ++c) { 2249 const PetscInt point = mesh->cones[off+c]; 2250 2251 for (m = 0; m < meetSize; ++m) { 2252 if (point == meet[i][m]) { 2253 meet[1-i][newMeetSize++] = point; 2254 break; 2255 } 2256 } 2257 } 2258 meetSize = newMeetSize; 2259 i = 1-i; 2260 } 2261 *numCoveringPoints = meetSize; 2262 *coveringPoints = meet[i]; 2263 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2264 PetscFunctionReturn(0); 2265 } 2266 2267 #undef __FUNCT__ 2268 #define __FUNCT__ "DMPlexRestoreMeet" 2269 /*@C 2270 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2271 2272 Not Collective 2273 2274 Input Parameters: 2275 + dm - The DMPlex object 2276 . numPoints - The number of input points for the meet 2277 - points - The input points 2278 2279 Output Parameters: 2280 + numCoveredPoints - The number of points in the meet 2281 - coveredPoints - The points in the meet 2282 2283 Level: intermediate 2284 2285 Fortran Notes: 2286 Since it returns an array, this routine is only available in Fortran 90, and you must 2287 include petsc.h90 in your code. 2288 2289 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2290 2291 .keywords: mesh 2292 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2293 @*/ 2294 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2295 { 2296 PetscErrorCode ierr; 2297 2298 PetscFunctionBegin; 2299 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2300 if (points) PetscValidIntPointer(points,3); 2301 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2302 PetscValidPointer(coveredPoints,5); 2303 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2304 if (numCoveredPoints) *numCoveredPoints = 0; 2305 PetscFunctionReturn(0); 2306 } 2307 2308 #undef __FUNCT__ 2309 #define __FUNCT__ "DMPlexGetFullMeet" 2310 /*@C 2311 DMPlexGetFullMeet - Get an array for the meet of the set of points 2312 2313 Not Collective 2314 2315 Input Parameters: 2316 + dm - The DMPlex object 2317 . numPoints - The number of input points for the meet 2318 - points - The input points 2319 2320 Output Parameters: 2321 + numCoveredPoints - The number of points in the meet 2322 - coveredPoints - The points in the meet 2323 2324 Level: intermediate 2325 2326 Fortran Notes: 2327 Since it returns an array, this routine is only available in Fortran 90, and you must 2328 include petsc.h90 in your code. 2329 2330 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2331 2332 .keywords: mesh 2333 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2334 @*/ 2335 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2336 { 2337 DM_Plex *mesh = (DM_Plex*) dm->data; 2338 PetscInt *offsets, **closures; 2339 PetscInt *meet[2]; 2340 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2341 PetscInt p, h, c, m, mc; 2342 PetscErrorCode ierr; 2343 2344 PetscFunctionBegin; 2345 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2346 PetscValidPointer(points, 2); 2347 PetscValidPointer(numCoveredPoints, 3); 2348 PetscValidPointer(coveredPoints, 4); 2349 2350 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2351 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2352 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2353 mc = mesh->maxConeSize; 2354 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2355 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2356 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2357 2358 for (p = 0; p < numPoints; ++p) { 2359 PetscInt closureSize; 2360 2361 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2362 2363 offsets[p*(height+2)+0] = 0; 2364 for (h = 0; h < height+1; ++h) { 2365 PetscInt pStart, pEnd, i; 2366 2367 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2368 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2369 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2370 offsets[p*(height+2)+h+1] = i; 2371 break; 2372 } 2373 } 2374 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2375 } 2376 if (offsets[p*(height+2)+height+1] != closureSize) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Total size of closure %D should be %D", offsets[p*(height+2)+height+1], closureSize); 2377 } 2378 for (h = 0; h < height+1; ++h) { 2379 PetscInt dof; 2380 2381 /* Copy in cone of first point */ 2382 dof = offsets[h+1] - offsets[h]; 2383 for (meetSize = 0; meetSize < dof; ++meetSize) { 2384 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2385 } 2386 /* Check each successive cone */ 2387 for (p = 1; p < numPoints && meetSize; ++p) { 2388 PetscInt newMeetSize = 0; 2389 2390 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2391 for (c = 0; c < dof; ++c) { 2392 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2393 2394 for (m = 0; m < meetSize; ++m) { 2395 if (point == meet[i][m]) { 2396 meet[1-i][newMeetSize++] = point; 2397 break; 2398 } 2399 } 2400 } 2401 meetSize = newMeetSize; 2402 i = 1-i; 2403 } 2404 if (meetSize) break; 2405 } 2406 *numCoveredPoints = meetSize; 2407 *coveredPoints = meet[i]; 2408 for (p = 0; p < numPoints; ++p) { 2409 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2410 } 2411 ierr = PetscFree(closures);CHKERRQ(ierr); 2412 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2413 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2414 PetscFunctionReturn(0); 2415 } 2416 2417 #undef __FUNCT__ 2418 #define __FUNCT__ "DMPlexEqual" 2419 /*@C 2420 DMPlexEqual - Determine if two DMs have the same topology 2421 2422 Not Collective 2423 2424 Input Parameters: 2425 + dmA - A DMPlex object 2426 - dmB - A DMPlex object 2427 2428 Output Parameters: 2429 . equal - PETSC_TRUE if the topologies are identical 2430 2431 Level: intermediate 2432 2433 Notes: 2434 We are not solving graph isomorphism, so we do not permutation. 2435 2436 .keywords: mesh 2437 .seealso: DMPlexGetCone() 2438 @*/ 2439 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2440 { 2441 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2442 PetscErrorCode ierr; 2443 2444 PetscFunctionBegin; 2445 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2446 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2447 PetscValidPointer(equal, 3); 2448 2449 *equal = PETSC_FALSE; 2450 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2451 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2452 if (depth != depthB) PetscFunctionReturn(0); 2453 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2454 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2455 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2456 for (p = pStart; p < pEnd; ++p) { 2457 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2458 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2459 2460 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2461 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2462 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2463 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2464 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2465 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2466 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2467 for (c = 0; c < coneSize; ++c) { 2468 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2469 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2470 } 2471 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2472 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2473 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2474 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2475 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2476 for (s = 0; s < supportSize; ++s) { 2477 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2478 } 2479 } 2480 *equal = PETSC_TRUE; 2481 PetscFunctionReturn(0); 2482 } 2483 2484 #undef __FUNCT__ 2485 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2486 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2487 { 2488 MPI_Comm comm; 2489 PetscErrorCode ierr; 2490 2491 PetscFunctionBegin; 2492 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2493 PetscValidPointer(numFaceVertices,3); 2494 switch (cellDim) { 2495 case 0: 2496 *numFaceVertices = 0; 2497 break; 2498 case 1: 2499 *numFaceVertices = 1; 2500 break; 2501 case 2: 2502 switch (numCorners) { 2503 case 3: /* triangle */ 2504 *numFaceVertices = 2; /* Edge has 2 vertices */ 2505 break; 2506 case 4: /* quadrilateral */ 2507 *numFaceVertices = 2; /* Edge has 2 vertices */ 2508 break; 2509 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2510 *numFaceVertices = 3; /* Edge has 3 vertices */ 2511 break; 2512 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2513 *numFaceVertices = 3; /* Edge has 3 vertices */ 2514 break; 2515 default: 2516 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2517 } 2518 break; 2519 case 3: 2520 switch (numCorners) { 2521 case 4: /* tetradehdron */ 2522 *numFaceVertices = 3; /* Face has 3 vertices */ 2523 break; 2524 case 6: /* tet cohesive cells */ 2525 *numFaceVertices = 4; /* Face has 4 vertices */ 2526 break; 2527 case 8: /* hexahedron */ 2528 *numFaceVertices = 4; /* Face has 4 vertices */ 2529 break; 2530 case 9: /* tet cohesive Lagrange cells */ 2531 *numFaceVertices = 6; /* Face has 6 vertices */ 2532 break; 2533 case 10: /* quadratic tetrahedron */ 2534 *numFaceVertices = 6; /* Face has 6 vertices */ 2535 break; 2536 case 12: /* hex cohesive Lagrange cells */ 2537 *numFaceVertices = 6; /* Face has 6 vertices */ 2538 break; 2539 case 18: /* quadratic tet cohesive Lagrange cells */ 2540 *numFaceVertices = 6; /* Face has 6 vertices */ 2541 break; 2542 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2543 *numFaceVertices = 9; /* Face has 9 vertices */ 2544 break; 2545 default: 2546 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %d for dimension %d", numCorners, cellDim); 2547 } 2548 break; 2549 default: 2550 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %d", cellDim); 2551 } 2552 PetscFunctionReturn(0); 2553 } 2554 2555 #undef __FUNCT__ 2556 #define __FUNCT__ "DMPlexLocalizeCoordinate" 2557 /*@ 2558 DMPlexLocalizeCoordinate - If a mesh is periodic (a torus with lengths L_i, some of which can be infinite), project the coordinate onto [0, L_i) in each dimension. 2559 2560 Input Parameters: 2561 + dm - The DM 2562 - in - The input coordinate point (dim numbers) 2563 2564 Output Parameter: 2565 . out - The localized coordinate point 2566 2567 Level: developer 2568 2569 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2570 @*/ 2571 PetscErrorCode DMPlexLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 2572 { 2573 PetscInt dim, d; 2574 PetscErrorCode ierr; 2575 2576 PetscFunctionBegin; 2577 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 2578 if (!dm->maxCell) { 2579 for (d = 0; d < dim; ++d) out[d] = in[d]; 2580 } else { 2581 for (d = 0; d < dim; ++d) { 2582 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 2583 } 2584 } 2585 PetscFunctionReturn(0); 2586 } 2587 2588 #undef __FUNCT__ 2589 #define __FUNCT__ "DMPlexLocalizeCoordinate_Internal" 2590 /* 2591 DMPlexLocalizeCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 2592 2593 Input Parameters: 2594 + dm - The DM 2595 . dim - The spatial dimension 2596 . anchor - The anchor point, the input point can be no more than maxCell away from it 2597 - in - The input coordinate point (dim numbers) 2598 2599 Output Parameter: 2600 . out - The localized coordinate point 2601 2602 Level: developer 2603 2604 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 2605 2606 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2607 */ 2608 PetscErrorCode DMPlexLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2609 { 2610 PetscInt d; 2611 2612 PetscFunctionBegin; 2613 if (!dm->maxCell) { 2614 for (d = 0; d < dim; ++d) out[d] = in[d]; 2615 } else { 2616 for (d = 0; d < dim; ++d) { 2617 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2618 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2619 } else { 2620 out[d] = in[d]; 2621 } 2622 } 2623 } 2624 PetscFunctionReturn(0); 2625 } 2626 #undef __FUNCT__ 2627 #define __FUNCT__ "DMPlexLocalizeCoordinateReal_Internal" 2628 PetscErrorCode DMPlexLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 2629 { 2630 PetscInt d; 2631 2632 PetscFunctionBegin; 2633 if (!dm->maxCell) { 2634 for (d = 0; d < dim; ++d) out[d] = in[d]; 2635 } else { 2636 for (d = 0; d < dim; ++d) { 2637 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 2638 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2639 } else { 2640 out[d] = in[d]; 2641 } 2642 } 2643 } 2644 PetscFunctionReturn(0); 2645 } 2646 2647 #undef __FUNCT__ 2648 #define __FUNCT__ "DMPlexLocalizeAddCoordinate_Internal" 2649 /* 2650 DMPlexLocalizeAddCoordinate_Internal - If a mesh is periodic, and the input point is far from the anchor, pick the coordinate sheet of the torus which moves it closer. 2651 2652 Input Parameters: 2653 + dm - The DM 2654 . dim - The spatial dimension 2655 . anchor - The anchor point, the input point can be no more than maxCell away from it 2656 . in - The input coordinate delta (dim numbers) 2657 - out - The input coordinate point (dim numbers) 2658 2659 Output Parameter: 2660 . out - The localized coordinate in + out 2661 2662 Level: developer 2663 2664 Note: This is meant to get a set of coordinates close to each other, as in a cell. The anchor is usually the one of the vertices on a containing cell 2665 2666 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeCoordinate() 2667 */ 2668 PetscErrorCode DMPlexLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2669 { 2670 PetscInt d; 2671 2672 PetscFunctionBegin; 2673 if (!dm->maxCell) { 2674 for (d = 0; d < dim; ++d) out[d] += in[d]; 2675 } else { 2676 for (d = 0; d < dim; ++d) { 2677 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2678 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2679 } else { 2680 out[d] += in[d]; 2681 } 2682 } 2683 } 2684 PetscFunctionReturn(0); 2685 } 2686 2687 #undef __FUNCT__ 2688 #define __FUNCT__ "DMPlexLocalizeCoordinates" 2689 /*@ 2690 DMPlexLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 2691 2692 Input Parameter: 2693 . dm - The DM 2694 2695 Level: developer 2696 2697 .seealso: DMPlexLocalizeCoordinate(), DMPlexLocalizeAddCoordinate() 2698 @*/ 2699 PetscErrorCode DMPlexLocalizeCoordinates(DM dm) 2700 { 2701 PetscSection coordSection, cSection; 2702 Vec coordinates, cVec; 2703 PetscScalar *coords, *coords2, *anchor; 2704 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, dof, d, off, off2, bs, coordSize; 2705 PetscErrorCode ierr; 2706 2707 PetscFunctionBegin; 2708 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2709 if (!dm->maxCell) PetscFunctionReturn(0); 2710 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2711 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 2712 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2713 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2714 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 2715 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 2716 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 2717 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 2718 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 2719 for (v = vStart; v < vEnd; ++v) { 2720 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2721 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 2722 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 2723 } 2724 for (c = cStart; c < cEnd; ++c) { 2725 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 2726 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 2727 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 2728 } 2729 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 2730 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 2731 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 2732 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 2733 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 2734 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2735 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 2736 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2737 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 2738 for (v = vStart; v < vEnd; ++v) { 2739 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2740 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 2741 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 2742 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 2743 } 2744 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2745 for (c = cStart; c < cEnd; ++c) { 2746 PetscScalar *cellCoords = NULL; 2747 PetscInt b; 2748 2749 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2750 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 2751 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 2752 for (d = 0; d < dof/bs; ++d) {ierr = DMPlexLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 2753 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2754 } 2755 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2756 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2757 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 2758 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 2759 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 2760 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2761 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 2762 PetscFunctionReturn(0); 2763 } 2764 2765 #undef __FUNCT__ 2766 #define __FUNCT__ "DMPlexGetDepthLabel" 2767 /*@ 2768 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2769 2770 Not Collective 2771 2772 Input Parameter: 2773 . dm - The DMPlex object 2774 2775 Output Parameter: 2776 . depthLabel - The DMLabel recording point depth 2777 2778 Level: developer 2779 2780 .keywords: mesh, points 2781 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2782 @*/ 2783 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2784 { 2785 DM_Plex *mesh = (DM_Plex*) dm->data; 2786 PetscErrorCode ierr; 2787 2788 PetscFunctionBegin; 2789 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2790 PetscValidPointer(depthLabel, 2); 2791 if (!mesh->depthLabel) {ierr = DMPlexGetLabel(dm, "depth", &mesh->depthLabel);CHKERRQ(ierr);} 2792 *depthLabel = mesh->depthLabel; 2793 PetscFunctionReturn(0); 2794 } 2795 2796 #undef __FUNCT__ 2797 #define __FUNCT__ "DMPlexGetDepth" 2798 /*@ 2799 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2800 2801 Not Collective 2802 2803 Input Parameter: 2804 . dm - The DMPlex object 2805 2806 Output Parameter: 2807 . depth - The number of strata (breadth first levels) in the DAG 2808 2809 Level: developer 2810 2811 .keywords: mesh, points 2812 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2813 @*/ 2814 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2815 { 2816 DMLabel label; 2817 PetscInt d = 0; 2818 PetscErrorCode ierr; 2819 2820 PetscFunctionBegin; 2821 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2822 PetscValidPointer(depth, 2); 2823 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2824 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2825 *depth = d-1; 2826 PetscFunctionReturn(0); 2827 } 2828 2829 #undef __FUNCT__ 2830 #define __FUNCT__ "DMPlexGetDepthStratum" 2831 /*@ 2832 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2833 2834 Not Collective 2835 2836 Input Parameters: 2837 + dm - The DMPlex object 2838 - stratumValue - The requested depth 2839 2840 Output Parameters: 2841 + start - The first point at this depth 2842 - end - One beyond the last point at this depth 2843 2844 Level: developer 2845 2846 .keywords: mesh, points 2847 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2848 @*/ 2849 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2850 { 2851 DMLabel label; 2852 PetscInt pStart, pEnd; 2853 PetscErrorCode ierr; 2854 2855 PetscFunctionBegin; 2856 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2857 if (start) {PetscValidPointer(start, 3); *start = 0;} 2858 if (end) {PetscValidPointer(end, 4); *end = 0;} 2859 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2860 if (pStart == pEnd) PetscFunctionReturn(0); 2861 if (stratumValue < 0) { 2862 if (start) *start = pStart; 2863 if (end) *end = pEnd; 2864 PetscFunctionReturn(0); 2865 } 2866 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2867 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2868 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2869 PetscFunctionReturn(0); 2870 } 2871 2872 #undef __FUNCT__ 2873 #define __FUNCT__ "DMPlexGetHeightStratum" 2874 /*@ 2875 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2876 2877 Not Collective 2878 2879 Input Parameters: 2880 + dm - The DMPlex object 2881 - stratumValue - The requested height 2882 2883 Output Parameters: 2884 + start - The first point at this height 2885 - end - One beyond the last point at this height 2886 2887 Level: developer 2888 2889 .keywords: mesh, points 2890 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2891 @*/ 2892 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2893 { 2894 DMLabel label; 2895 PetscInt depth, pStart, pEnd; 2896 PetscErrorCode ierr; 2897 2898 PetscFunctionBegin; 2899 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2900 if (start) {PetscValidPointer(start, 3); *start = 0;} 2901 if (end) {PetscValidPointer(end, 4); *end = 0;} 2902 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2903 if (pStart == pEnd) PetscFunctionReturn(0); 2904 if (stratumValue < 0) { 2905 if (start) *start = pStart; 2906 if (end) *end = pEnd; 2907 PetscFunctionReturn(0); 2908 } 2909 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2910 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2911 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2912 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2913 PetscFunctionReturn(0); 2914 } 2915 2916 #undef __FUNCT__ 2917 #define __FUNCT__ "DMPlexCreateSectionInitial" 2918 /* Set the number of dof on each point and separate by fields */ 2919 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2920 { 2921 PetscInt *pMax; 2922 PetscInt depth, pStart = 0, pEnd = 0; 2923 PetscInt Nf, p, d, dep, f; 2924 PetscBool *isFE; 2925 PetscErrorCode ierr; 2926 2927 PetscFunctionBegin; 2928 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2929 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2930 for (f = 0; f < numFields; ++f) { 2931 PetscObject obj; 2932 PetscClassId id; 2933 2934 isFE[f] = PETSC_FALSE; 2935 if (f >= Nf) continue; 2936 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2937 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2938 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2939 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2940 } 2941 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2942 if (numFields > 0) { 2943 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2944 if (numComp) { 2945 for (f = 0; f < numFields; ++f) { 2946 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2947 } 2948 } 2949 } 2950 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2951 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2952 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2953 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2954 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2955 for (dep = 0; dep <= depth; ++dep) { 2956 d = dim == depth ? dep : (!dep ? 0 : dim); 2957 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2958 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2959 for (p = pStart; p < pEnd; ++p) { 2960 PetscInt tot = 0; 2961 2962 for (f = 0; f < numFields; ++f) { 2963 if (isFE[f] && p >= pMax[dep]) continue; 2964 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2965 tot += numDof[f*(dim+1)+d]; 2966 } 2967 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2968 } 2969 } 2970 ierr = PetscFree(pMax);CHKERRQ(ierr); 2971 ierr = PetscFree(isFE);CHKERRQ(ierr); 2972 PetscFunctionReturn(0); 2973 } 2974 2975 #undef __FUNCT__ 2976 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2977 /* Set the number of dof on each point and separate by fields 2978 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2979 */ 2980 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2981 { 2982 PetscInt numFields; 2983 PetscInt bc; 2984 PetscSection aSec; 2985 PetscErrorCode ierr; 2986 2987 PetscFunctionBegin; 2988 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 2989 for (bc = 0; bc < numBC; ++bc) { 2990 PetscInt field = 0; 2991 const PetscInt *comp; 2992 const PetscInt *idx; 2993 PetscInt Nc = -1, n, i; 2994 2995 if (numFields) field = bcField[bc]; 2996 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 2997 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 2998 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 2999 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3000 for (i = 0; i < n; ++i) { 3001 const PetscInt p = idx[i]; 3002 PetscInt numConst; 3003 3004 if (numFields) { 3005 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 3006 } else { 3007 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 3008 } 3009 /* If Nc < 0, constrain every dof on the point */ 3010 if (Nc > 0) numConst = PetscMin(numConst, Nc); 3011 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 3012 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 3013 } 3014 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3015 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3016 } 3017 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3018 if (aSec) { 3019 PetscInt aStart, aEnd, a; 3020 3021 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3022 for (a = aStart; a < aEnd; a++) { 3023 PetscInt dof, f; 3024 3025 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3026 if (dof) { 3027 /* if there are point-to-point constraints, then all dofs are constrained */ 3028 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3029 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3030 for (f = 0; f < numFields; f++) { 3031 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3032 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3033 } 3034 } 3035 } 3036 } 3037 PetscFunctionReturn(0); 3038 } 3039 3040 #undef __FUNCT__ 3041 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 3042 /* Set the constrained field indices on each point 3043 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3044 */ 3045 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3046 { 3047 PetscSection aSec; 3048 PetscInt *indices; 3049 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 3050 PetscErrorCode ierr; 3051 3052 PetscFunctionBegin; 3053 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3054 if (!numFields) PetscFunctionReturn(0); 3055 /* Initialize all field indices to -1 */ 3056 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3057 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3058 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3059 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3060 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3061 /* Handle BC constraints */ 3062 for (bc = 0; bc < numBC; ++bc) { 3063 const PetscInt field = bcField[bc]; 3064 const PetscInt *comp, *idx; 3065 PetscInt Nc = -1, n, i; 3066 3067 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3068 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3069 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3070 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3071 for (i = 0; i < n; ++i) { 3072 const PetscInt p = idx[i]; 3073 const PetscInt *find; 3074 PetscInt fcdof, c; 3075 3076 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3077 if (Nc < 0) { 3078 for (d = 0; d < fcdof; ++d) indices[d] = d; 3079 } else { 3080 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3081 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3082 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 3083 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 3084 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 3085 } 3086 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3087 } 3088 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3089 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3090 } 3091 /* Handle anchors */ 3092 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3093 if (aSec) { 3094 PetscInt aStart, aEnd, a; 3095 3096 for (d = 0; d < maxDof; ++d) indices[d] = d; 3097 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3098 for (a = aStart; a < aEnd; a++) { 3099 PetscInt dof, fdof, f; 3100 3101 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3102 if (dof) { 3103 /* if there are point-to-point constraints, then all dofs are constrained */ 3104 for (f = 0; f < numFields; f++) { 3105 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 3106 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3107 } 3108 } 3109 } 3110 } 3111 ierr = PetscFree(indices);CHKERRQ(ierr); 3112 PetscFunctionReturn(0); 3113 } 3114 3115 #undef __FUNCT__ 3116 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 3117 /* Set the constrained indices on each point */ 3118 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3119 { 3120 PetscInt *indices; 3121 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3122 PetscErrorCode ierr; 3123 3124 PetscFunctionBegin; 3125 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3126 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3127 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3128 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3129 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3130 for (p = pStart; p < pEnd; ++p) { 3131 PetscInt cdof, d; 3132 3133 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3134 if (cdof) { 3135 if (numFields) { 3136 PetscInt numConst = 0, foff = 0; 3137 3138 for (f = 0; f < numFields; ++f) { 3139 const PetscInt *find; 3140 PetscInt fcdof, fdof; 3141 3142 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3143 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3144 /* Change constraint numbering from field component to local dof number */ 3145 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3146 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3147 numConst += fcdof; 3148 foff += fdof; 3149 } 3150 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 3151 } else { 3152 for (d = 0; d < cdof; ++d) indices[d] = d; 3153 } 3154 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3155 } 3156 } 3157 ierr = PetscFree(indices);CHKERRQ(ierr); 3158 PetscFunctionReturn(0); 3159 } 3160 3161 #undef __FUNCT__ 3162 #define __FUNCT__ "DMPlexCreateSection" 3163 /*@C 3164 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3165 3166 Not Collective 3167 3168 Input Parameters: 3169 + dm - The DMPlex object 3170 . dim - The spatial dimension of the problem 3171 . numFields - The number of fields in the problem 3172 . numComp - An array of size numFields that holds the number of components for each field 3173 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3174 . numBC - The number of boundary conditions 3175 . bcField - An array of size numBC giving the field number for each boundry condition 3176 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3177 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3178 - perm - Optional permutation of the chart, or NULL 3179 3180 Output Parameter: 3181 . section - The PetscSection object 3182 3183 Notes: numDof[f*(dim+1)+d] gives the number of dof for field f on sieve points of dimension d. For instance, numDof[1] is the 3184 number of dof for field 0 on each edge. 3185 3186 The chart permutation is the same one set using PetscSectionSetPermutation() 3187 3188 Level: developer 3189 3190 Fortran Notes: 3191 A Fortran 90 version is available as DMPlexCreateSectionF90() 3192 3193 .keywords: mesh, elements 3194 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3195 @*/ 3196 PetscErrorCode DMPlexCreateSection(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], IS perm, PetscSection *section) 3197 { 3198 PetscSection aSec; 3199 PetscErrorCode ierr; 3200 3201 PetscFunctionBegin; 3202 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3203 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3204 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3205 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3206 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3207 if (numBC || aSec) { 3208 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3209 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3210 } 3211 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3212 PetscFunctionReturn(0); 3213 } 3214 3215 #undef __FUNCT__ 3216 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 3217 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3218 { 3219 PetscSection section; 3220 PetscErrorCode ierr; 3221 3222 PetscFunctionBegin; 3223 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3224 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3225 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3226 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3227 PetscFunctionReturn(0); 3228 } 3229 3230 #undef __FUNCT__ 3231 #define __FUNCT__ "DMPlexGetConeSection" 3232 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3233 { 3234 DM_Plex *mesh = (DM_Plex*) dm->data; 3235 3236 PetscFunctionBegin; 3237 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3238 if (section) *section = mesh->coneSection; 3239 PetscFunctionReturn(0); 3240 } 3241 3242 #undef __FUNCT__ 3243 #define __FUNCT__ "DMPlexGetSupportSection" 3244 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3245 { 3246 DM_Plex *mesh = (DM_Plex*) dm->data; 3247 3248 PetscFunctionBegin; 3249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3250 if (section) *section = mesh->supportSection; 3251 PetscFunctionReturn(0); 3252 } 3253 3254 #undef __FUNCT__ 3255 #define __FUNCT__ "DMPlexGetCones" 3256 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3257 { 3258 DM_Plex *mesh = (DM_Plex*) dm->data; 3259 3260 PetscFunctionBegin; 3261 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3262 if (cones) *cones = mesh->cones; 3263 PetscFunctionReturn(0); 3264 } 3265 3266 #undef __FUNCT__ 3267 #define __FUNCT__ "DMPlexGetConeOrientations" 3268 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3269 { 3270 DM_Plex *mesh = (DM_Plex*) dm->data; 3271 3272 PetscFunctionBegin; 3273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3274 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3275 PetscFunctionReturn(0); 3276 } 3277 3278 /******************************** FEM Support **********************************/ 3279 3280 #undef __FUNCT__ 3281 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3282 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3283 { 3284 PetscScalar *array, *vArray; 3285 const PetscInt *cone, *coneO; 3286 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3287 PetscErrorCode ierr; 3288 3289 PetscFunctionBeginHot; 3290 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3291 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3292 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3293 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3294 if (!values || !*values) { 3295 if ((point >= pStart) && (point < pEnd)) { 3296 PetscInt dof; 3297 3298 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3299 size += dof; 3300 } 3301 for (p = 0; p < numPoints; ++p) { 3302 const PetscInt cp = cone[p]; 3303 PetscInt dof; 3304 3305 if ((cp < pStart) || (cp >= pEnd)) continue; 3306 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3307 size += dof; 3308 } 3309 if (!values) { 3310 if (csize) *csize = size; 3311 PetscFunctionReturn(0); 3312 } 3313 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3314 } else { 3315 array = *values; 3316 } 3317 size = 0; 3318 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3319 if ((point >= pStart) && (point < pEnd)) { 3320 PetscInt dof, off, d; 3321 PetscScalar *varr; 3322 3323 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3324 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3325 varr = &vArray[off]; 3326 for (d = 0; d < dof; ++d, ++offset) { 3327 array[offset] = varr[d]; 3328 } 3329 size += dof; 3330 } 3331 for (p = 0; p < numPoints; ++p) { 3332 const PetscInt cp = cone[p]; 3333 PetscInt o = coneO[p]; 3334 PetscInt dof, off, d; 3335 PetscScalar *varr; 3336 3337 if ((cp < pStart) || (cp >= pEnd)) continue; 3338 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3339 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3340 varr = &vArray[off]; 3341 if (o >= 0) { 3342 for (d = 0; d < dof; ++d, ++offset) { 3343 array[offset] = varr[d]; 3344 } 3345 } else { 3346 for (d = dof-1; d >= 0; --d, ++offset) { 3347 array[offset] = varr[d]; 3348 } 3349 } 3350 size += dof; 3351 } 3352 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3353 if (!*values) { 3354 if (csize) *csize = size; 3355 *values = array; 3356 } else { 3357 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3358 *csize = size; 3359 } 3360 PetscFunctionReturn(0); 3361 } 3362 3363 #undef __FUNCT__ 3364 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3365 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3366 { 3367 PetscInt offset = 0, p; 3368 PetscErrorCode ierr; 3369 3370 PetscFunctionBeginHot; 3371 *size = 0; 3372 for (p = 0; p < numPoints*2; p += 2) { 3373 const PetscInt point = points[p]; 3374 const PetscInt o = points[p+1]; 3375 PetscInt dof, off, d; 3376 const PetscScalar *varr; 3377 3378 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3379 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3380 varr = &vArray[off]; 3381 if (o >= 0) { 3382 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3383 } else { 3384 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3385 } 3386 } 3387 *size = offset; 3388 PetscFunctionReturn(0); 3389 } 3390 3391 #undef __FUNCT__ 3392 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3393 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3394 { 3395 PetscInt offset = 0, f; 3396 PetscErrorCode ierr; 3397 3398 PetscFunctionBeginHot; 3399 *size = 0; 3400 for (f = 0; f < numFields; ++f) { 3401 PetscInt fcomp, p; 3402 3403 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3404 for (p = 0; p < numPoints*2; p += 2) { 3405 const PetscInt point = points[p]; 3406 const PetscInt o = points[p+1]; 3407 PetscInt fdof, foff, d, c; 3408 const PetscScalar *varr; 3409 3410 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3411 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3412 varr = &vArray[foff]; 3413 if (o >= 0) { 3414 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3415 } else { 3416 for (d = fdof/fcomp-1; d >= 0; --d) { 3417 for (c = 0; c < fcomp; ++c, ++offset) { 3418 array[offset] = varr[d*fcomp+c]; 3419 } 3420 } 3421 } 3422 } 3423 } 3424 *size = offset; 3425 PetscFunctionReturn(0); 3426 } 3427 3428 #undef __FUNCT__ 3429 #define __FUNCT__ "DMPlexVecGetClosure" 3430 /*@C 3431 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3432 3433 Not collective 3434 3435 Input Parameters: 3436 + dm - The DM 3437 . section - The section describing the layout in v, or NULL to use the default section 3438 . v - The local vector 3439 - point - The sieve point in the DM 3440 3441 Output Parameters: 3442 + csize - The number of values in the closure, or NULL 3443 - values - The array of values, which is a borrowed array and should not be freed 3444 3445 Fortran Notes: 3446 Since it returns an array, this routine is only available in Fortran 90, and you must 3447 include petsc.h90 in your code. 3448 3449 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3450 3451 Level: intermediate 3452 3453 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3454 @*/ 3455 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3456 { 3457 PetscSection clSection; 3458 IS clPoints; 3459 PetscScalar *array, *vArray; 3460 PetscInt *points = NULL; 3461 const PetscInt *clp; 3462 PetscInt depth, numFields, numPoints, size; 3463 PetscErrorCode ierr; 3464 3465 PetscFunctionBeginHot; 3466 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3467 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3468 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3469 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3470 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3471 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3472 if (depth == 1 && numFields < 2) { 3473 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3474 PetscFunctionReturn(0); 3475 } 3476 /* Get points */ 3477 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3478 if (!clPoints) { 3479 PetscInt pStart, pEnd, p, q; 3480 3481 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3482 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3483 /* Compress out points not in the section */ 3484 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3485 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3486 points[q*2] = points[p]; 3487 points[q*2+1] = points[p+1]; 3488 ++q; 3489 } 3490 } 3491 numPoints = q; 3492 } else { 3493 PetscInt dof, off; 3494 3495 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3496 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3497 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3498 numPoints = dof/2; 3499 points = (PetscInt *) &clp[off]; 3500 } 3501 /* Get array */ 3502 if (!values || !*values) { 3503 PetscInt asize = 0, dof, p; 3504 3505 for (p = 0; p < numPoints*2; p += 2) { 3506 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3507 asize += dof; 3508 } 3509 if (!values) { 3510 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3511 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3512 if (csize) *csize = asize; 3513 PetscFunctionReturn(0); 3514 } 3515 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3516 } else { 3517 array = *values; 3518 } 3519 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3520 /* Get values */ 3521 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3522 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3523 /* Cleanup points */ 3524 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3525 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3526 /* Cleanup array */ 3527 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3528 if (!*values) { 3529 if (csize) *csize = size; 3530 *values = array; 3531 } else { 3532 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3533 *csize = size; 3534 } 3535 PetscFunctionReturn(0); 3536 } 3537 3538 #undef __FUNCT__ 3539 #define __FUNCT__ "DMPlexVecRestoreClosure" 3540 /*@C 3541 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3542 3543 Not collective 3544 3545 Input Parameters: 3546 + dm - The DM 3547 . section - The section describing the layout in v, or NULL to use the default section 3548 . v - The local vector 3549 . point - The sieve point in the DM 3550 . csize - The number of values in the closure, or NULL 3551 - values - The array of values, which is a borrowed array and should not be freed 3552 3553 Fortran Notes: 3554 Since it returns an array, this routine is only available in Fortran 90, and you must 3555 include petsc.h90 in your code. 3556 3557 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3558 3559 Level: intermediate 3560 3561 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3562 @*/ 3563 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3564 { 3565 PetscInt size = 0; 3566 PetscErrorCode ierr; 3567 3568 PetscFunctionBegin; 3569 /* Should work without recalculating size */ 3570 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3571 PetscFunctionReturn(0); 3572 } 3573 3574 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3575 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3576 3577 #undef __FUNCT__ 3578 #define __FUNCT__ "updatePoint_private" 3579 PETSC_STATIC_INLINE PetscErrorCode updatePoint_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3580 { 3581 PetscInt cdof; /* The number of constraints on this point */ 3582 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3583 PetscScalar *a; 3584 PetscInt off, cind = 0, k; 3585 PetscErrorCode ierr; 3586 3587 PetscFunctionBegin; 3588 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3589 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3590 a = &array[off]; 3591 if (!cdof || setBC) { 3592 if (orientation >= 0) { 3593 for (k = 0; k < dof; ++k) { 3594 fuse(&a[k], values[k]); 3595 } 3596 } else { 3597 for (k = 0; k < dof; ++k) { 3598 fuse(&a[k], values[dof-k-1]); 3599 } 3600 } 3601 } else { 3602 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3603 if (orientation >= 0) { 3604 for (k = 0; k < dof; ++k) { 3605 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3606 fuse(&a[k], values[k]); 3607 } 3608 } else { 3609 for (k = 0; k < dof; ++k) { 3610 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3611 fuse(&a[k], values[dof-k-1]); 3612 } 3613 } 3614 } 3615 PetscFunctionReturn(0); 3616 } 3617 3618 #undef __FUNCT__ 3619 #define __FUNCT__ "updatePointBC_private" 3620 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3621 { 3622 PetscInt cdof; /* The number of constraints on this point */ 3623 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3624 PetscScalar *a; 3625 PetscInt off, cind = 0, k; 3626 PetscErrorCode ierr; 3627 3628 PetscFunctionBegin; 3629 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3630 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3631 a = &array[off]; 3632 if (cdof) { 3633 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3634 if (orientation >= 0) { 3635 for (k = 0; k < dof; ++k) { 3636 if ((cind < cdof) && (k == cdofs[cind])) { 3637 fuse(&a[k], values[k]); 3638 ++cind; 3639 } 3640 } 3641 } else { 3642 for (k = 0; k < dof; ++k) { 3643 if ((cind < cdof) && (k == cdofs[cind])) { 3644 fuse(&a[k], values[dof-k-1]); 3645 ++cind; 3646 } 3647 } 3648 } 3649 } 3650 PetscFunctionReturn(0); 3651 } 3652 3653 #undef __FUNCT__ 3654 #define __FUNCT__ "updatePointFields_private" 3655 PETSC_STATIC_INLINE PetscErrorCode updatePointFields_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), PetscBool setBC, const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3656 { 3657 PetscScalar *a; 3658 PetscInt fdof, foff, fcdof, foffset = *offset; 3659 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3660 PetscInt cind = 0, k, c; 3661 PetscErrorCode ierr; 3662 3663 PetscFunctionBegin; 3664 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3665 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3666 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3667 a = &array[foff]; 3668 if (!fcdof || setBC) { 3669 if (o >= 0) { 3670 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3671 } else { 3672 for (k = fdof/fcomp-1; k >= 0; --k) { 3673 for (c = 0; c < fcomp; ++c) { 3674 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3675 } 3676 } 3677 } 3678 } else { 3679 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3680 if (o >= 0) { 3681 for (k = 0; k < fdof; ++k) { 3682 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3683 fuse(&a[k], values[foffset+k]); 3684 } 3685 } else { 3686 for (k = fdof/fcomp-1; k >= 0; --k) { 3687 for (c = 0; c < fcomp; ++c) { 3688 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3689 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3690 } 3691 } 3692 } 3693 } 3694 *offset += fdof; 3695 PetscFunctionReturn(0); 3696 } 3697 3698 #undef __FUNCT__ 3699 #define __FUNCT__ "updatePointFieldsBC_private" 3700 PETSC_STATIC_INLINE PetscErrorCode updatePointFieldsBC_private(PetscSection section, PetscInt point, PetscInt o, PetscInt f, PetscInt fcomp, void (*fuse)(PetscScalar*, PetscScalar), const PetscScalar values[], PetscInt *offset, PetscScalar array[]) 3701 { 3702 PetscScalar *a; 3703 PetscInt fdof, foff, fcdof, foffset = *offset; 3704 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3705 PetscInt cind = 0, k, c; 3706 PetscErrorCode ierr; 3707 3708 PetscFunctionBegin; 3709 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3710 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3711 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3712 a = &array[foff]; 3713 if (fcdof) { 3714 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3715 if (o >= 0) { 3716 for (k = 0; k < fdof; ++k) { 3717 if ((cind < fcdof) && (k == fcdofs[cind])) { 3718 fuse(&a[k], values[foffset+k]); 3719 ++cind; 3720 } 3721 } 3722 } else { 3723 for (k = fdof/fcomp-1; k >= 0; --k) { 3724 for (c = 0; c < fcomp; ++c) { 3725 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3726 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3727 ++cind; 3728 } 3729 } 3730 } 3731 } 3732 } 3733 *offset += fdof; 3734 PetscFunctionReturn(0); 3735 } 3736 3737 #undef __FUNCT__ 3738 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3739 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3740 { 3741 PetscScalar *array; 3742 const PetscInt *cone, *coneO; 3743 PetscInt pStart, pEnd, p, numPoints, off, dof; 3744 PetscErrorCode ierr; 3745 3746 PetscFunctionBeginHot; 3747 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3748 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3749 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3750 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3751 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3752 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3753 const PetscInt cp = !p ? point : cone[p-1]; 3754 const PetscInt o = !p ? 0 : coneO[p-1]; 3755 3756 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3757 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3758 /* ADD_VALUES */ 3759 { 3760 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3761 PetscScalar *a; 3762 PetscInt cdof, coff, cind = 0, k; 3763 3764 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3765 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3766 a = &array[coff]; 3767 if (!cdof) { 3768 if (o >= 0) { 3769 for (k = 0; k < dof; ++k) { 3770 a[k] += values[off+k]; 3771 } 3772 } else { 3773 for (k = 0; k < dof; ++k) { 3774 a[k] += values[off+dof-k-1]; 3775 } 3776 } 3777 } else { 3778 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3779 if (o >= 0) { 3780 for (k = 0; k < dof; ++k) { 3781 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3782 a[k] += values[off+k]; 3783 } 3784 } else { 3785 for (k = 0; k < dof; ++k) { 3786 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3787 a[k] += values[off+dof-k-1]; 3788 } 3789 } 3790 } 3791 } 3792 } 3793 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3794 PetscFunctionReturn(0); 3795 } 3796 3797 #undef __FUNCT__ 3798 #define __FUNCT__ "DMPlexVecSetClosure" 3799 /*@C 3800 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3801 3802 Not collective 3803 3804 Input Parameters: 3805 + dm - The DM 3806 . section - The section describing the layout in v, or NULL to use the default section 3807 . v - The local vector 3808 . point - The sieve point in the DM 3809 . values - The array of values 3810 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3811 3812 Fortran Notes: 3813 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3814 3815 Level: intermediate 3816 3817 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3818 @*/ 3819 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3820 { 3821 PetscSection clSection; 3822 IS clPoints; 3823 PetscScalar *array; 3824 PetscInt *points = NULL; 3825 const PetscInt *clp; 3826 PetscInt depth, numFields, numPoints, p; 3827 PetscErrorCode ierr; 3828 3829 PetscFunctionBeginHot; 3830 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3831 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3832 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3833 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3834 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3835 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3836 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3837 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3838 PetscFunctionReturn(0); 3839 } 3840 /* Get points */ 3841 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3842 if (!clPoints) { 3843 PetscInt pStart, pEnd, q; 3844 3845 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3846 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3847 /* Compress out points not in the section */ 3848 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3849 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3850 points[q*2] = points[p]; 3851 points[q*2+1] = points[p+1]; 3852 ++q; 3853 } 3854 } 3855 numPoints = q; 3856 } else { 3857 PetscInt dof, off; 3858 3859 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3860 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3861 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3862 numPoints = dof/2; 3863 points = (PetscInt *) &clp[off]; 3864 } 3865 /* Get array */ 3866 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3867 /* Get values */ 3868 if (numFields > 0) { 3869 PetscInt offset = 0, fcomp, f; 3870 for (f = 0; f < numFields; ++f) { 3871 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3872 switch (mode) { 3873 case INSERT_VALUES: 3874 for (p = 0; p < numPoints*2; p += 2) { 3875 const PetscInt point = points[p]; 3876 const PetscInt o = points[p+1]; 3877 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3878 } break; 3879 case INSERT_ALL_VALUES: 3880 for (p = 0; p < numPoints*2; p += 2) { 3881 const PetscInt point = points[p]; 3882 const PetscInt o = points[p+1]; 3883 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3884 } break; 3885 case INSERT_BC_VALUES: 3886 for (p = 0; p < numPoints*2; p += 2) { 3887 const PetscInt point = points[p]; 3888 const PetscInt o = points[p+1]; 3889 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3890 } break; 3891 case ADD_VALUES: 3892 for (p = 0; p < numPoints*2; p += 2) { 3893 const PetscInt point = points[p]; 3894 const PetscInt o = points[p+1]; 3895 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3896 } break; 3897 case ADD_ALL_VALUES: 3898 for (p = 0; p < numPoints*2; p += 2) { 3899 const PetscInt point = points[p]; 3900 const PetscInt o = points[p+1]; 3901 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3902 } break; 3903 default: 3904 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 3905 } 3906 } 3907 } else { 3908 PetscInt dof, off; 3909 3910 switch (mode) { 3911 case INSERT_VALUES: 3912 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3913 PetscInt o = points[p+1]; 3914 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3915 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3916 } break; 3917 case INSERT_ALL_VALUES: 3918 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3919 PetscInt o = points[p+1]; 3920 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3921 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3922 } break; 3923 case INSERT_BC_VALUES: 3924 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3925 PetscInt o = points[p+1]; 3926 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3927 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3928 } break; 3929 case ADD_VALUES: 3930 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3931 PetscInt o = points[p+1]; 3932 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3933 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3934 } break; 3935 case ADD_ALL_VALUES: 3936 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3937 PetscInt o = points[p+1]; 3938 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3939 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3940 } break; 3941 default: 3942 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 3943 } 3944 } 3945 /* Cleanup points */ 3946 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3947 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3948 /* Cleanup array */ 3949 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3950 PetscFunctionReturn(0); 3951 } 3952 3953 #undef __FUNCT__ 3954 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3955 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3956 { 3957 PetscSection clSection; 3958 IS clPoints; 3959 PetscScalar *array; 3960 PetscInt *points = NULL; 3961 const PetscInt *clp; 3962 PetscInt numFields, numPoints, p; 3963 PetscInt offset = 0, fcomp, f; 3964 PetscErrorCode ierr; 3965 3966 PetscFunctionBeginHot; 3967 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3968 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3969 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3970 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3971 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3972 /* Get points */ 3973 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3974 if (!clPoints) { 3975 PetscInt pStart, pEnd, q; 3976 3977 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3978 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3979 /* Compress out points not in the section */ 3980 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3981 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3982 points[q*2] = points[p]; 3983 points[q*2+1] = points[p+1]; 3984 ++q; 3985 } 3986 } 3987 numPoints = q; 3988 } else { 3989 PetscInt dof, off; 3990 3991 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3992 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3993 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3994 numPoints = dof/2; 3995 points = (PetscInt *) &clp[off]; 3996 } 3997 /* Get array */ 3998 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3999 /* Get values */ 4000 for (f = 0; f < numFields; ++f) { 4001 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4002 if (!fieldActive[f]) { 4003 for (p = 0; p < numPoints*2; p += 2) { 4004 PetscInt fdof; 4005 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4006 offset += fdof; 4007 } 4008 continue; 4009 } 4010 switch (mode) { 4011 case INSERT_VALUES: 4012 for (p = 0; p < numPoints*2; p += 2) { 4013 const PetscInt point = points[p]; 4014 const PetscInt o = points[p+1]; 4015 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 4016 } break; 4017 case INSERT_ALL_VALUES: 4018 for (p = 0; p < numPoints*2; p += 2) { 4019 const PetscInt point = points[p]; 4020 const PetscInt o = points[p+1]; 4021 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 4022 } break; 4023 case INSERT_BC_VALUES: 4024 for (p = 0; p < numPoints*2; p += 2) { 4025 const PetscInt point = points[p]; 4026 const PetscInt o = points[p+1]; 4027 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 4028 } break; 4029 case ADD_VALUES: 4030 for (p = 0; p < numPoints*2; p += 2) { 4031 const PetscInt point = points[p]; 4032 const PetscInt o = points[p+1]; 4033 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 4034 } break; 4035 case ADD_ALL_VALUES: 4036 for (p = 0; p < numPoints*2; p += 2) { 4037 const PetscInt point = points[p]; 4038 const PetscInt o = points[p+1]; 4039 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 4040 } break; 4041 default: 4042 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %D", mode); 4043 } 4044 } 4045 /* Cleanup points */ 4046 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4047 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4048 /* Cleanup array */ 4049 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4050 PetscFunctionReturn(0); 4051 } 4052 4053 #undef __FUNCT__ 4054 #define __FUNCT__ "DMPlexPrintMatSetValues" 4055 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4056 { 4057 PetscMPIInt rank; 4058 PetscInt i, j; 4059 PetscErrorCode ierr; 4060 4061 PetscFunctionBegin; 4062 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4063 ierr = PetscViewerASCIIPrintf(viewer, "[%D]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4064 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4065 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4066 numCIndices = numCIndices ? numCIndices : numRIndices; 4067 for (i = 0; i < numRIndices; i++) { 4068 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4069 for (j = 0; j < numCIndices; j++) { 4070 #if defined(PETSC_USE_COMPLEX) 4071 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4072 #else 4073 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4074 #endif 4075 } 4076 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4077 } 4078 PetscFunctionReturn(0); 4079 } 4080 4081 #undef __FUNCT__ 4082 #define __FUNCT__ "indicesPoint_private" 4083 /* . off - The global offset of this point */ 4084 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4085 { 4086 PetscInt dof; /* The number of unknowns on this point */ 4087 PetscInt cdof; /* The number of constraints on this point */ 4088 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4089 PetscInt cind = 0, k; 4090 PetscErrorCode ierr; 4091 4092 PetscFunctionBegin; 4093 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4094 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4095 if (!cdof || setBC) { 4096 if (orientation >= 0) { 4097 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4098 } else { 4099 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4100 } 4101 } else { 4102 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4103 if (orientation >= 0) { 4104 for (k = 0; k < dof; ++k) { 4105 if ((cind < cdof) && (k == cdofs[cind])) { 4106 /* Insert check for returning constrained indices */ 4107 indices[*loff+k] = -(off+k+1); 4108 ++cind; 4109 } else { 4110 indices[*loff+k] = off+k-cind; 4111 } 4112 } 4113 } else { 4114 for (k = 0; k < dof; ++k) { 4115 if ((cind < cdof) && (k == cdofs[cind])) { 4116 /* Insert check for returning constrained indices */ 4117 indices[*loff+dof-k-1] = -(off+k+1); 4118 ++cind; 4119 } else { 4120 indices[*loff+dof-k-1] = off+k-cind; 4121 } 4122 } 4123 } 4124 } 4125 *loff += dof; 4126 PetscFunctionReturn(0); 4127 } 4128 4129 #undef __FUNCT__ 4130 #define __FUNCT__ "indicesPointFields_private" 4131 /* . off - The global offset of this point */ 4132 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4133 { 4134 PetscInt numFields, foff, f; 4135 PetscErrorCode ierr; 4136 4137 PetscFunctionBegin; 4138 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4139 for (f = 0, foff = 0; f < numFields; ++f) { 4140 PetscInt fdof, fcomp, cfdof; 4141 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4142 PetscInt cind = 0, k, c; 4143 4144 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4145 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4146 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4147 if (!cfdof || setBC) { 4148 if (orientation >= 0) { 4149 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4150 } else { 4151 for (k = fdof/fcomp-1; k >= 0; --k) { 4152 for (c = 0; c < fcomp; ++c) { 4153 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4154 } 4155 } 4156 } 4157 } else { 4158 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4159 if (orientation >= 0) { 4160 for (k = 0; k < fdof; ++k) { 4161 if ((cind < cfdof) && (k == fcdofs[cind])) { 4162 indices[foffs[f]+k] = -(off+foff+k+1); 4163 ++cind; 4164 } else { 4165 indices[foffs[f]+k] = off+foff+k-cind; 4166 } 4167 } 4168 } else { 4169 for (k = fdof/fcomp-1; k >= 0; --k) { 4170 for (c = 0; c < fcomp; ++c) { 4171 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4172 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4173 ++cind; 4174 } else { 4175 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4176 } 4177 } 4178 } 4179 } 4180 } 4181 foff += fdof - cfdof; 4182 foffs[f] += fdof; 4183 } 4184 PetscFunctionReturn(0); 4185 } 4186 4187 #undef __FUNCT__ 4188 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4189 static PetscErrorCode DMPlexAnchorsModifyMat(DM dm, PetscSection section, PetscInt numPoints, PetscInt numIndices, const PetscInt points[], const PetscScalar values[], PetscInt *outNumPoints, PetscInt *outNumIndices, PetscInt *outPoints[], PetscScalar *outValues[], PetscInt offsets[]) 4190 { 4191 Mat cMat; 4192 PetscSection aSec, cSec; 4193 IS aIS; 4194 PetscInt aStart = -1, aEnd = -1; 4195 const PetscInt *anchors; 4196 PetscInt numFields, f, p, q, newP = 0; 4197 PetscInt newNumPoints = 0, newNumIndices = 0; 4198 PetscInt *newPoints, *indices, *newIndices; 4199 PetscInt maxAnchor, maxDof; 4200 PetscInt newOffsets[32]; 4201 PetscInt *pointMatOffsets[32]; 4202 PetscInt *newPointOffsets[32]; 4203 PetscScalar *pointMat[32]; 4204 PetscScalar *newValues,*tmpValues; 4205 PetscBool anyConstrained = PETSC_FALSE; 4206 PetscErrorCode ierr; 4207 4208 PetscFunctionBegin; 4209 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4210 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4211 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4212 4213 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4214 /* if there are point-to-point constraints */ 4215 if (aSec) { 4216 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4217 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4218 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4219 /* figure out how many points are going to be in the new element matrix 4220 * (we allow double counting, because it's all just going to be summed 4221 * into the global matrix anyway) */ 4222 for (p = 0; p < 2*numPoints; p+=2) { 4223 PetscInt b = points[p]; 4224 PetscInt bDof = 0; 4225 4226 if (b >= aStart && b < aEnd) { 4227 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4228 } 4229 if (bDof) { 4230 /* this point is constrained */ 4231 /* it is going to be replaced by its anchors */ 4232 PetscInt bOff, q; 4233 4234 anyConstrained = PETSC_TRUE; 4235 newNumPoints += bDof; 4236 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4237 for (q = 0; q < bDof; q++) { 4238 PetscInt a = anchors[bOff + q]; 4239 PetscInt aDof; 4240 4241 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4242 newNumIndices += aDof; 4243 for (f = 0; f < numFields; ++f) { 4244 PetscInt fDof; 4245 4246 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4247 newOffsets[f+1] += fDof; 4248 } 4249 } 4250 } 4251 else { 4252 /* this point is not constrained */ 4253 newNumPoints++; 4254 ierr = PetscSectionGetDof(section,b,&bDof);CHKERRQ(ierr); 4255 newNumIndices += bDof; 4256 for (f = 0; f < numFields; ++f) { 4257 PetscInt fDof; 4258 4259 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4260 newOffsets[f+1] += fDof; 4261 } 4262 } 4263 } 4264 } 4265 if (!anyConstrained) { 4266 *outNumPoints = 0; 4267 *outNumIndices = 0; 4268 *outPoints = NULL; 4269 *outValues = NULL; 4270 if (aSec) { 4271 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4272 } 4273 PetscFunctionReturn(0); 4274 } 4275 4276 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4277 4278 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", newOffsets[numFields], newNumIndices); 4279 4280 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4281 4282 /* output arrays */ 4283 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4284 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4285 4286 /* workspaces */ 4287 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4288 if (numFields) { 4289 for (f = 0; f < numFields; f++) { 4290 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4291 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4292 } 4293 } 4294 else { 4295 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4296 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4297 } 4298 4299 /* get workspaces for the point-to-point matrices */ 4300 if (numFields) { 4301 for (p = 0; p < numPoints; p++) { 4302 PetscInt b = points[2*p]; 4303 PetscInt bDof = 0; 4304 4305 if (b >= aStart && b < aEnd) { 4306 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4307 } 4308 if (bDof) { 4309 for (f = 0; f < numFields; f++) { 4310 PetscInt fDof, q, bOff, allFDof = 0; 4311 4312 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4313 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4314 for (q = 0; q < bDof; q++) { 4315 PetscInt a = anchors[bOff + q]; 4316 PetscInt aFDof; 4317 4318 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4319 allFDof += aFDof; 4320 } 4321 newPointOffsets[f][p+1] = allFDof; 4322 pointMatOffsets[f][p+1] = fDof * allFDof; 4323 } 4324 } 4325 else { 4326 for (f = 0; f < numFields; f++) { 4327 PetscInt fDof; 4328 4329 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4330 newPointOffsets[f][p+1] = fDof; 4331 pointMatOffsets[f][p+1] = 0; 4332 } 4333 } 4334 } 4335 for (f = 0; f < numFields; f++) { 4336 newPointOffsets[f][0] = 0; 4337 pointMatOffsets[f][0] = 0; 4338 for (p = 0; p < numPoints; p++) { 4339 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4340 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4341 } 4342 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4343 } 4344 } 4345 else { 4346 for (p = 0; p < numPoints; p++) { 4347 PetscInt b = points[2*p]; 4348 PetscInt bDof = 0; 4349 4350 if (b >= aStart && b < aEnd) { 4351 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4352 } 4353 if (bDof) { 4354 PetscInt dof, bOff, q, allDof = 0; 4355 4356 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4357 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4358 for (q = 0; q < bDof; q++) { 4359 PetscInt a = anchors[bOff + q], aDof; 4360 4361 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4362 allDof += aDof; 4363 } 4364 newPointOffsets[0][p+1] = allDof; 4365 pointMatOffsets[0][p+1] = dof * allDof; 4366 } 4367 else { 4368 PetscInt dof; 4369 4370 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4371 newPointOffsets[0][p+1] = dof; 4372 pointMatOffsets[0][p+1] = 0; 4373 } 4374 } 4375 newPointOffsets[0][0] = 0; 4376 pointMatOffsets[0][0] = 0; 4377 for (p = 0; p < numPoints; p++) { 4378 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4379 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4380 } 4381 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4382 } 4383 4384 /* get the point-to-point matrices; construct newPoints */ 4385 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4386 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4387 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4388 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4389 if (numFields) { 4390 for (p = 0, newP = 0; p < numPoints; p++) { 4391 PetscInt b = points[2*p]; 4392 PetscInt o = points[2*p+1]; 4393 PetscInt bDof = 0; 4394 4395 if (b >= aStart && b < aEnd) { 4396 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4397 } 4398 if (bDof) { 4399 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4400 4401 fStart[0] = 0; 4402 fEnd[0] = 0; 4403 for (f = 0; f < numFields; f++) { 4404 PetscInt fDof; 4405 4406 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4407 fStart[f+1] = fStart[f] + fDof; 4408 fEnd[f+1] = fStart[f+1]; 4409 } 4410 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4411 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4412 4413 fAnchorStart[0] = 0; 4414 fAnchorEnd[0] = 0; 4415 for (f = 0; f < numFields; f++) { 4416 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4417 4418 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4419 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4420 } 4421 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4422 for (q = 0; q < bDof; q++) { 4423 PetscInt a = anchors[bOff + q], aOff; 4424 4425 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4426 newPoints[2*(newP + q)] = a; 4427 newPoints[2*(newP + q) + 1] = 0; 4428 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4429 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4430 } 4431 newP += bDof; 4432 4433 /* get the point-to-point submatrix */ 4434 for (f = 0; f < numFields; f++) { 4435 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4436 } 4437 } 4438 else { 4439 newPoints[2 * newP] = b; 4440 newPoints[2 * newP + 1] = o; 4441 newP++; 4442 } 4443 } 4444 } else { 4445 for (p = 0; p < numPoints; p++) { 4446 PetscInt b = points[2*p]; 4447 PetscInt o = points[2*p+1]; 4448 PetscInt bDof = 0; 4449 4450 if (b >= aStart && b < aEnd) { 4451 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4452 } 4453 if (bDof) { 4454 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4455 4456 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4457 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4458 4459 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4460 for (q = 0; q < bDof; q++) { 4461 PetscInt a = anchors[bOff + q], aOff; 4462 4463 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4464 4465 newPoints[2*(newP + q)] = a; 4466 newPoints[2*(newP + q) + 1] = 0; 4467 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4468 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4469 } 4470 newP += bDof; 4471 4472 /* get the point-to-point submatrix */ 4473 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4474 } 4475 else { 4476 newPoints[2 * newP] = b; 4477 newPoints[2 * newP + 1] = o; 4478 newP++; 4479 } 4480 } 4481 } 4482 4483 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4484 /* multiply constraints on the right */ 4485 if (numFields) { 4486 for (f = 0; f < numFields; f++) { 4487 PetscInt oldOff = offsets[f]; 4488 4489 for (p = 0; p < numPoints; p++) { 4490 PetscInt cStart = newPointOffsets[f][p]; 4491 PetscInt b = points[2 * p]; 4492 PetscInt c, r, k; 4493 PetscInt dof; 4494 4495 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4496 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4497 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4498 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4499 4500 for (r = 0; r < numIndices; r++) { 4501 for (c = 0; c < nCols; c++) { 4502 for (k = 0; k < dof; k++) { 4503 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4504 } 4505 } 4506 } 4507 } 4508 else { 4509 /* copy this column as is */ 4510 for (r = 0; r < numIndices; r++) { 4511 for (c = 0; c < dof; c++) { 4512 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4513 } 4514 } 4515 } 4516 oldOff += dof; 4517 } 4518 } 4519 } 4520 else { 4521 PetscInt oldOff = 0; 4522 for (p = 0; p < numPoints; p++) { 4523 PetscInt cStart = newPointOffsets[0][p]; 4524 PetscInt b = points[2 * p]; 4525 PetscInt c, r, k; 4526 PetscInt dof; 4527 4528 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4529 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4530 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4531 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4532 4533 for (r = 0; r < numIndices; r++) { 4534 for (c = 0; c < nCols; c++) { 4535 for (k = 0; k < dof; k++) { 4536 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4537 } 4538 } 4539 } 4540 } 4541 else { 4542 /* copy this column as is */ 4543 for (r = 0; r < numIndices; r++) { 4544 for (c = 0; c < dof; c++) { 4545 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4546 } 4547 } 4548 } 4549 oldOff += dof; 4550 } 4551 } 4552 4553 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4554 /* multiply constraints transpose on the left */ 4555 if (numFields) { 4556 for (f = 0; f < numFields; f++) { 4557 PetscInt oldOff = offsets[f]; 4558 4559 for (p = 0; p < numPoints; p++) { 4560 PetscInt rStart = newPointOffsets[f][p]; 4561 PetscInt b = points[2 * p]; 4562 PetscInt c, r, k; 4563 PetscInt dof; 4564 4565 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4566 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4567 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4568 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4569 4570 for (r = 0; r < nRows; r++) { 4571 for (c = 0; c < newNumIndices; c++) { 4572 for (k = 0; k < dof; k++) { 4573 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4574 } 4575 } 4576 } 4577 } 4578 else { 4579 /* copy this row as is */ 4580 for (r = 0; r < dof; r++) { 4581 for (c = 0; c < newNumIndices; c++) { 4582 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4583 } 4584 } 4585 } 4586 oldOff += dof; 4587 } 4588 } 4589 } 4590 else { 4591 PetscInt oldOff = 0; 4592 4593 for (p = 0; p < numPoints; p++) { 4594 PetscInt rStart = newPointOffsets[0][p]; 4595 PetscInt b = points[2 * p]; 4596 PetscInt c, r, k; 4597 PetscInt dof; 4598 4599 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4600 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4601 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4602 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4603 4604 for (r = 0; r < nRows; r++) { 4605 for (c = 0; c < newNumIndices; c++) { 4606 for (k = 0; k < dof; k++) { 4607 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4608 } 4609 } 4610 } 4611 } 4612 else { 4613 /* copy this row as is */ 4614 for (r = 0; r < dof; c++) { 4615 for (c = 0; c < newNumIndices; c++) { 4616 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4617 } 4618 } 4619 } 4620 oldOff += dof; 4621 } 4622 } 4623 4624 /* clean up */ 4625 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4626 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4627 if (numFields) { 4628 for (f = 0; f < numFields; f++) { 4629 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4630 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4631 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4632 } 4633 } 4634 else { 4635 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4636 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4637 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4638 } 4639 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4640 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4641 4642 /* output */ 4643 *outNumPoints = newNumPoints; 4644 *outNumIndices = newNumIndices; 4645 *outPoints = newPoints; 4646 *outValues = newValues; 4647 for (f = 0; f < numFields; f++) { 4648 offsets[f] = newOffsets[f]; 4649 } 4650 PetscFunctionReturn(0); 4651 } 4652 4653 #undef __FUNCT__ 4654 #define __FUNCT__ "DMPlexMatSetClosure" 4655 /*@C 4656 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4657 4658 Not collective 4659 4660 Input Parameters: 4661 + dm - The DM 4662 . section - The section describing the layout in v, or NULL to use the default section 4663 . globalSection - The section describing the layout in v, or NULL to use the default global section 4664 . A - The matrix 4665 . point - The sieve point in the DM 4666 . values - The array of values 4667 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4668 4669 Fortran Notes: 4670 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4671 4672 Level: intermediate 4673 4674 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4675 @*/ 4676 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4677 { 4678 DM_Plex *mesh = (DM_Plex*) dm->data; 4679 PetscSection clSection; 4680 IS clPoints; 4681 PetscInt *points = NULL, *newPoints; 4682 const PetscInt *clp; 4683 PetscInt *indices; 4684 PetscInt offsets[32]; 4685 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4686 PetscScalar *newValues; 4687 PetscErrorCode ierr; 4688 4689 PetscFunctionBegin; 4690 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4691 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4692 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4693 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4694 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4695 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4696 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4697 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4698 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4699 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4700 if (!clPoints) { 4701 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4702 /* Compress out points not in the section */ 4703 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4704 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4705 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4706 points[q*2] = points[p]; 4707 points[q*2+1] = points[p+1]; 4708 ++q; 4709 } 4710 } 4711 numPoints = q; 4712 } else { 4713 PetscInt dof, off; 4714 4715 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4716 numPoints = dof/2; 4717 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4718 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4719 points = (PetscInt *) &clp[off]; 4720 } 4721 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4722 PetscInt fdof; 4723 4724 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4725 for (f = 0; f < numFields; ++f) { 4726 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4727 offsets[f+1] += fdof; 4728 } 4729 numIndices += dof; 4730 } 4731 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4732 4733 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4734 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets);CHKERRQ(ierr); 4735 if (newNumPoints) { 4736 if (!clPoints) { 4737 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4738 } else { 4739 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4740 } 4741 numPoints = newNumPoints; 4742 numIndices = newNumIndices; 4743 points = newPoints; 4744 values = newValues; 4745 } 4746 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4747 if (numFields) { 4748 for (p = 0; p < numPoints*2; p += 2) { 4749 PetscInt o = points[p+1]; 4750 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4751 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4752 } 4753 } else { 4754 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4755 PetscInt o = points[p+1]; 4756 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4757 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4758 } 4759 } 4760 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4761 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4762 if (mesh->printFEM > 1) { 4763 PetscInt i; 4764 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4765 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4766 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4767 } 4768 if (ierr) { 4769 PetscMPIInt rank; 4770 PetscErrorCode ierr2; 4771 4772 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4773 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4774 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4775 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4776 CHKERRQ(ierr); 4777 } 4778 if (newNumPoints) { 4779 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4780 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4781 } 4782 else { 4783 if (!clPoints) { 4784 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4785 } else { 4786 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4787 } 4788 } 4789 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4790 PetscFunctionReturn(0); 4791 } 4792 4793 #undef __FUNCT__ 4794 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4795 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4796 { 4797 DM_Plex *mesh = (DM_Plex*) dmf->data; 4798 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4799 PetscInt *cpoints = NULL; 4800 PetscInt *findices, *cindices; 4801 PetscInt foffsets[32], coffsets[32]; 4802 CellRefiner cellRefiner; 4803 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4804 PetscErrorCode ierr; 4805 4806 PetscFunctionBegin; 4807 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4808 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4809 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4810 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4811 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4812 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4813 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4814 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4815 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4816 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4817 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4818 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4819 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4820 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4821 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4822 /* Column indices */ 4823 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4824 maxFPoints = numCPoints; 4825 /* Compress out points not in the section */ 4826 /* TODO: Squeeze out points with 0 dof as well */ 4827 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4828 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4829 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4830 cpoints[q*2] = cpoints[p]; 4831 cpoints[q*2+1] = cpoints[p+1]; 4832 ++q; 4833 } 4834 } 4835 numCPoints = q; 4836 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4837 PetscInt fdof; 4838 4839 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4840 if (!dof) continue; 4841 for (f = 0; f < numFields; ++f) { 4842 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4843 coffsets[f+1] += fdof; 4844 } 4845 numCIndices += dof; 4846 } 4847 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4848 /* Row indices */ 4849 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4850 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4851 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4852 for (r = 0, q = 0; r < numSubcells; ++r) { 4853 /* TODO Map from coarse to fine cells */ 4854 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4855 /* Compress out points not in the section */ 4856 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4857 for (p = 0; p < numFPoints*2; p += 2) { 4858 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4859 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4860 if (!dof) continue; 4861 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4862 if (s < q) continue; 4863 ftotpoints[q*2] = fpoints[p]; 4864 ftotpoints[q*2+1] = fpoints[p+1]; 4865 ++q; 4866 } 4867 } 4868 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4869 } 4870 numFPoints = q; 4871 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4872 PetscInt fdof; 4873 4874 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4875 if (!dof) continue; 4876 for (f = 0; f < numFields; ++f) { 4877 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4878 foffsets[f+1] += fdof; 4879 } 4880 numFIndices += dof; 4881 } 4882 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 4883 4884 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 4885 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 4886 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4887 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4888 if (numFields) { 4889 for (p = 0; p < numFPoints*2; p += 2) { 4890 PetscInt o = ftotpoints[p+1]; 4891 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4892 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 4893 } 4894 for (p = 0; p < numCPoints*2; p += 2) { 4895 PetscInt o = cpoints[p+1]; 4896 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4897 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 4898 } 4899 } else { 4900 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 4901 PetscInt o = ftotpoints[p+1]; 4902 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 4903 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 4904 } 4905 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 4906 PetscInt o = cpoints[p+1]; 4907 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 4908 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 4909 } 4910 } 4911 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 4912 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 4913 if (ierr) { 4914 PetscMPIInt rank; 4915 PetscErrorCode ierr2; 4916 4917 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4918 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4919 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 4920 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 4921 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 4922 CHKERRQ(ierr); 4923 } 4924 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4925 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4926 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 4927 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 4928 PetscFunctionReturn(0); 4929 } 4930 4931 #undef __FUNCT__ 4932 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 4933 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 4934 { 4935 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4936 PetscInt *cpoints = NULL; 4937 PetscInt foffsets[32], coffsets[32]; 4938 CellRefiner cellRefiner; 4939 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4940 PetscErrorCode ierr; 4941 4942 PetscFunctionBegin; 4943 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4944 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4945 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4946 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4947 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4948 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4949 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4950 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4951 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4952 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4953 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4954 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4955 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4956 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4957 /* Column indices */ 4958 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4959 maxFPoints = numCPoints; 4960 /* Compress out points not in the section */ 4961 /* TODO: Squeeze out points with 0 dof as well */ 4962 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4963 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4964 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4965 cpoints[q*2] = cpoints[p]; 4966 cpoints[q*2+1] = cpoints[p+1]; 4967 ++q; 4968 } 4969 } 4970 numCPoints = q; 4971 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4972 PetscInt fdof; 4973 4974 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4975 if (!dof) continue; 4976 for (f = 0; f < numFields; ++f) { 4977 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4978 coffsets[f+1] += fdof; 4979 } 4980 numCIndices += dof; 4981 } 4982 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4983 /* Row indices */ 4984 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4985 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4986 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4987 for (r = 0, q = 0; r < numSubcells; ++r) { 4988 /* TODO Map from coarse to fine cells */ 4989 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4990 /* Compress out points not in the section */ 4991 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4992 for (p = 0; p < numFPoints*2; p += 2) { 4993 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4994 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4995 if (!dof) continue; 4996 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4997 if (s < q) continue; 4998 ftotpoints[q*2] = fpoints[p]; 4999 ftotpoints[q*2+1] = fpoints[p+1]; 5000 ++q; 5001 } 5002 } 5003 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5004 } 5005 numFPoints = q; 5006 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5007 PetscInt fdof; 5008 5009 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5010 if (!dof) continue; 5011 for (f = 0; f < numFields; ++f) { 5012 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5013 foffsets[f+1] += fdof; 5014 } 5015 numFIndices += dof; 5016 } 5017 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5018 5019 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5020 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5021 if (numFields) { 5022 for (p = 0; p < numFPoints*2; p += 2) { 5023 PetscInt o = ftotpoints[p+1]; 5024 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5025 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5026 } 5027 for (p = 0; p < numCPoints*2; p += 2) { 5028 PetscInt o = cpoints[p+1]; 5029 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5030 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5031 } 5032 } else { 5033 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5034 PetscInt o = ftotpoints[p+1]; 5035 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5036 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5037 } 5038 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5039 PetscInt o = cpoints[p+1]; 5040 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5041 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5042 } 5043 } 5044 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5045 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5046 PetscFunctionReturn(0); 5047 } 5048 5049 #undef __FUNCT__ 5050 #define __FUNCT__ "DMPlexGetHybridBounds" 5051 /*@ 5052 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5053 5054 Input Parameter: 5055 . dm - The DMPlex object 5056 5057 Output Parameters: 5058 + cMax - The first hybrid cell 5059 . fMax - The first hybrid face 5060 . eMax - The first hybrid edge 5061 - vMax - The first hybrid vertex 5062 5063 Level: developer 5064 5065 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5066 @*/ 5067 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5068 { 5069 DM_Plex *mesh = (DM_Plex*) dm->data; 5070 PetscInt dim; 5071 PetscErrorCode ierr; 5072 5073 PetscFunctionBegin; 5074 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5075 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5076 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5077 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5078 if (eMax) *eMax = mesh->hybridPointMax[1]; 5079 if (vMax) *vMax = mesh->hybridPointMax[0]; 5080 PetscFunctionReturn(0); 5081 } 5082 5083 #undef __FUNCT__ 5084 #define __FUNCT__ "DMPlexSetHybridBounds" 5085 /*@ 5086 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5087 5088 Input Parameters: 5089 . dm - The DMPlex object 5090 . cMax - The first hybrid cell 5091 . fMax - The first hybrid face 5092 . eMax - The first hybrid edge 5093 - vMax - The first hybrid vertex 5094 5095 Level: developer 5096 5097 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5098 @*/ 5099 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5100 { 5101 DM_Plex *mesh = (DM_Plex*) dm->data; 5102 PetscInt dim; 5103 PetscErrorCode ierr; 5104 5105 PetscFunctionBegin; 5106 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5107 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5108 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5109 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5110 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5111 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5112 PetscFunctionReturn(0); 5113 } 5114 5115 #undef __FUNCT__ 5116 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5117 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5118 { 5119 DM_Plex *mesh = (DM_Plex*) dm->data; 5120 5121 PetscFunctionBegin; 5122 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5123 PetscValidPointer(cellHeight, 2); 5124 *cellHeight = mesh->vtkCellHeight; 5125 PetscFunctionReturn(0); 5126 } 5127 5128 #undef __FUNCT__ 5129 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5130 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5131 { 5132 DM_Plex *mesh = (DM_Plex*) dm->data; 5133 5134 PetscFunctionBegin; 5135 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5136 mesh->vtkCellHeight = cellHeight; 5137 PetscFunctionReturn(0); 5138 } 5139 5140 #undef __FUNCT__ 5141 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5142 /* We can easily have a form that takes an IS instead */ 5143 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5144 { 5145 PetscSection section, globalSection; 5146 PetscInt *numbers, p; 5147 PetscErrorCode ierr; 5148 5149 PetscFunctionBegin; 5150 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5151 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5152 for (p = pStart; p < pEnd; ++p) { 5153 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5154 } 5155 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5156 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5157 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5158 for (p = pStart; p < pEnd; ++p) { 5159 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5160 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5161 else numbers[p-pStart] += shift; 5162 } 5163 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5164 if (globalSize) { 5165 PetscLayout layout; 5166 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5167 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5168 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5169 } 5170 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5171 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5172 PetscFunctionReturn(0); 5173 } 5174 5175 #undef __FUNCT__ 5176 #define __FUNCT__ "DMPlexGetCellNumbering" 5177 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5178 { 5179 DM_Plex *mesh = (DM_Plex*) dm->data; 5180 PetscInt cellHeight, cStart, cEnd, cMax; 5181 PetscErrorCode ierr; 5182 5183 PetscFunctionBegin; 5184 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5185 if (!mesh->globalCellNumbers) { 5186 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5187 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5188 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5189 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5190 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5191 } 5192 *globalCellNumbers = mesh->globalCellNumbers; 5193 PetscFunctionReturn(0); 5194 } 5195 5196 #undef __FUNCT__ 5197 #define __FUNCT__ "DMPlexGetVertexNumbering" 5198 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5199 { 5200 DM_Plex *mesh = (DM_Plex*) dm->data; 5201 PetscInt vStart, vEnd, vMax; 5202 PetscErrorCode ierr; 5203 5204 PetscFunctionBegin; 5205 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5206 if (!mesh->globalVertexNumbers) { 5207 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5208 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5209 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5210 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5211 } 5212 *globalVertexNumbers = mesh->globalVertexNumbers; 5213 PetscFunctionReturn(0); 5214 } 5215 5216 #undef __FUNCT__ 5217 #define __FUNCT__ "DMPlexCreatePointNumbering" 5218 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5219 { 5220 IS nums[4]; 5221 PetscInt depths[4]; 5222 PetscInt depth, d, shift = 0; 5223 PetscErrorCode ierr; 5224 5225 PetscFunctionBegin; 5226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5227 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5228 /* For unstratified meshes use dim instead of depth */ 5229 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5230 depths[0] = depth; depths[1] = 0; 5231 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5232 for (d = 0; d <= depth; ++d) { 5233 PetscInt pStart, pEnd, gsize; 5234 5235 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5236 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5237 shift += gsize; 5238 } 5239 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5240 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5241 PetscFunctionReturn(0); 5242 } 5243 5244 5245 #undef __FUNCT__ 5246 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 5247 /*@C 5248 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 5249 the local section and an SF describing the section point overlap. 5250 5251 Input Parameters: 5252 + s - The PetscSection for the local field layout 5253 . sf - The SF describing parallel layout of the section points 5254 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 5255 . label - The label specifying the points 5256 - labelValue - The label stratum specifying the points 5257 5258 Output Parameter: 5259 . gsection - The PetscSection for the global field layout 5260 5261 Note: This gives negative sizes and offsets to points not owned by this process 5262 5263 Level: developer 5264 5265 .seealso: PetscSectionCreate() 5266 @*/ 5267 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 5268 { 5269 PetscInt *neg = NULL, *tmpOff = NULL; 5270 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 5271 PetscErrorCode ierr; 5272 5273 PetscFunctionBegin; 5274 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 5275 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 5276 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 5277 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 5278 if (nroots >= 0) { 5279 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 5280 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 5281 if (nroots > pEnd-pStart) { 5282 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 5283 } else { 5284 tmpOff = &(*gsection)->atlasDof[-pStart]; 5285 } 5286 } 5287 /* Mark ghost points with negative dof */ 5288 for (p = pStart; p < pEnd; ++p) { 5289 PetscInt value; 5290 5291 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 5292 if (value != labelValue) continue; 5293 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 5294 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 5295 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 5296 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 5297 if (neg) neg[p] = -(dof+1); 5298 } 5299 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 5300 if (nroots >= 0) { 5301 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5302 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5303 if (nroots > pEnd-pStart) { 5304 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 5305 } 5306 } 5307 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 5308 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5309 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 5310 (*gsection)->atlasOff[p] = off; 5311 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 5312 } 5313 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); 5314 globalOff -= off; 5315 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5316 (*gsection)->atlasOff[p] += globalOff; 5317 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 5318 } 5319 /* Put in negative offsets for ghost points */ 5320 if (nroots >= 0) { 5321 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5322 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5323 if (nroots > pEnd-pStart) { 5324 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 5325 } 5326 } 5327 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 5328 ierr = PetscFree(neg);CHKERRQ(ierr); 5329 PetscFunctionReturn(0); 5330 } 5331 5332 #undef __FUNCT__ 5333 #define __FUNCT__ "DMPlexCheckSymmetry" 5334 /*@ 5335 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5336 5337 Input Parameters: 5338 + dm - The DMPlex object 5339 5340 Note: This is a useful diagnostic when creating meshes programmatically. 5341 5342 Level: developer 5343 5344 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5345 @*/ 5346 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5347 { 5348 PetscSection coneSection, supportSection; 5349 const PetscInt *cone, *support; 5350 PetscInt coneSize, c, supportSize, s; 5351 PetscInt pStart, pEnd, p, csize, ssize; 5352 PetscErrorCode ierr; 5353 5354 PetscFunctionBegin; 5355 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5356 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5357 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5358 /* Check that point p is found in the support of its cone points, and vice versa */ 5359 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5360 for (p = pStart; p < pEnd; ++p) { 5361 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5362 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5363 for (c = 0; c < coneSize; ++c) { 5364 PetscBool dup = PETSC_FALSE; 5365 PetscInt d; 5366 for (d = c-1; d >= 0; --d) { 5367 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5368 } 5369 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5370 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5371 for (s = 0; s < supportSize; ++s) { 5372 if (support[s] == p) break; 5373 } 5374 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5375 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5376 for (s = 0; s < coneSize; ++s) { 5377 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5378 } 5379 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5380 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5381 for (s = 0; s < supportSize; ++s) { 5382 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5383 } 5384 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5385 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5386 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5387 } 5388 } 5389 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5390 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5391 for (s = 0; s < supportSize; ++s) { 5392 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5393 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5394 for (c = 0; c < coneSize; ++c) { 5395 if (cone[c] == p) break; 5396 } 5397 if (c >= coneSize) { 5398 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5399 for (c = 0; c < supportSize; ++c) { 5400 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5401 } 5402 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5403 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5404 for (c = 0; c < coneSize; ++c) { 5405 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5406 } 5407 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5408 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5409 } 5410 } 5411 } 5412 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5413 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5414 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5415 PetscFunctionReturn(0); 5416 } 5417 5418 #undef __FUNCT__ 5419 #define __FUNCT__ "DMPlexCheckSkeleton" 5420 /*@ 5421 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5422 5423 Input Parameters: 5424 + dm - The DMPlex object 5425 . isSimplex - Are the cells simplices or tensor products 5426 - cellHeight - Normally 0 5427 5428 Note: This is a useful diagnostic when creating meshes programmatically. 5429 5430 Level: developer 5431 5432 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5433 @*/ 5434 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5435 { 5436 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5437 PetscErrorCode ierr; 5438 5439 PetscFunctionBegin; 5440 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5441 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5442 switch (dim) { 5443 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5444 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5445 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5446 default: 5447 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5448 } 5449 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5450 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5451 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5452 cMax = cMax >= 0 ? cMax : cEnd; 5453 for (c = cStart; c < cMax; ++c) { 5454 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5455 5456 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5457 for (cl = 0; cl < closureSize*2; cl += 2) { 5458 const PetscInt p = closure[cl]; 5459 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5460 } 5461 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5462 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5463 } 5464 for (c = cMax; c < cEnd; ++c) { 5465 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5466 5467 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5468 for (cl = 0; cl < closureSize*2; cl += 2) { 5469 const PetscInt p = closure[cl]; 5470 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5471 } 5472 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5473 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5474 } 5475 PetscFunctionReturn(0); 5476 } 5477 5478 #undef __FUNCT__ 5479 #define __FUNCT__ "DMPlexCheckFaces" 5480 /*@ 5481 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5482 5483 Input Parameters: 5484 + dm - The DMPlex object 5485 . isSimplex - Are the cells simplices or tensor products 5486 - cellHeight - Normally 0 5487 5488 Note: This is a useful diagnostic when creating meshes programmatically. 5489 5490 Level: developer 5491 5492 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5493 @*/ 5494 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5495 { 5496 PetscInt pMax[4]; 5497 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5498 PetscErrorCode ierr; 5499 5500 PetscFunctionBegin; 5501 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5502 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5503 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5504 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5505 for (h = cellHeight; h < dim; ++h) { 5506 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5507 for (c = cStart; c < cEnd; ++c) { 5508 const PetscInt *cone, *ornt, *faces; 5509 PetscInt numFaces, faceSize, coneSize,f; 5510 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5511 5512 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5513 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5514 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5515 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5516 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5517 for (cl = 0; cl < closureSize*2; cl += 2) { 5518 const PetscInt p = closure[cl]; 5519 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5520 } 5521 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5522 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5523 for (f = 0; f < numFaces; ++f) { 5524 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5525 5526 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5527 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5528 const PetscInt p = fclosure[cl]; 5529 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5530 } 5531 if (fnumCorners != faceSize) SETERRQ5(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d has %d vertices but should have %d", cone[f], f, c, fnumCorners, faceSize); 5532 for (v = 0; v < fnumCorners; ++v) { 5533 if (fclosure[v] != faces[f*faceSize+v]) SETERRQ6(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Face %d (%d) of cell %d vertex %d, %d != %d", cone[f], f, c, v, fclosure[v], faces[f*faceSize+v]); 5534 } 5535 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5536 } 5537 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5538 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5539 } 5540 } 5541 PetscFunctionReturn(0); 5542 } 5543 5544 #undef __FUNCT__ 5545 #define __FUNCT__ "DMCreateInterpolation_Plex" 5546 /* Pointwise interpolation 5547 Just code FEM for now 5548 u^f = I u^c 5549 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5550 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5551 I_{ij} = psi^f_i phi^c_j 5552 */ 5553 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5554 { 5555 PetscSection gsc, gsf; 5556 PetscInt m, n; 5557 void *ctx; 5558 PetscErrorCode ierr; 5559 5560 PetscFunctionBegin; 5561 /* 5562 Loop over coarse cells 5563 Loop over coarse basis functions 5564 Loop over fine cells in coarse cell 5565 Loop over fine dual basis functions 5566 Evaluate coarse basis on fine dual basis quad points 5567 Sum 5568 Update local element matrix 5569 Accumulate to interpolation matrix 5570 5571 Can extend PetscFEIntegrateJacobian_Basic() to do a specialized cell loop 5572 */ 5573 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5574 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5575 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5576 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5577 /* We need to preallocate properly */ 5578 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5579 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5580 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5581 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5582 ierr = DMPlexComputeInterpolatorFEM(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr); 5583 /* Use naive scaling */ 5584 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5585 PetscFunctionReturn(0); 5586 } 5587 5588 #undef __FUNCT__ 5589 #define __FUNCT__ "DMCreateInjection_Plex" 5590 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5591 { 5592 PetscErrorCode ierr; 5593 VecScatter ctx; 5594 5595 PetscFunctionBegin; 5596 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5597 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5598 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5599 PetscFunctionReturn(0); 5600 } 5601 5602 #undef __FUNCT__ 5603 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5604 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5605 { 5606 PetscSection section; 5607 IS *bcPoints, *bcComps; 5608 PetscBool *isFE; 5609 PetscInt *bcFields, *numComp, *numDof; 5610 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5611 PetscInt cStart, cEnd, cEndInterior; 5612 PetscErrorCode ierr; 5613 5614 PetscFunctionBegin; 5615 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5616 /* FE and FV boundary conditions are handled slightly differently */ 5617 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5618 for (f = 0; f < numFields; ++f) { 5619 PetscObject obj; 5620 PetscClassId id; 5621 5622 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5623 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5624 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5625 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5626 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5627 } 5628 /* Allocate boundary point storage for FEM boundaries */ 5629 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5630 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5631 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5632 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5633 ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5634 for (bd = 0; bd < numBd; ++bd) { 5635 PetscInt field; 5636 PetscBool isEssential; 5637 5638 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5639 if (isFE[field] && isEssential) ++numBC; 5640 } 5641 /* Add ghost cell boundaries for FVM */ 5642 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5643 ierr = PetscMalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5644 /* Constrain ghost cells for FV */ 5645 for (f = 0; f < numFields; ++f) { 5646 PetscInt *newidx, c; 5647 5648 if (isFE[f] || cEndInterior < 0) continue; 5649 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5650 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5651 bcFields[bc] = f; 5652 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5653 } 5654 /* Handle FEM Dirichlet boundaries */ 5655 for (bd = 0; bd < numBd; ++bd) { 5656 const char *bdLabel; 5657 DMLabel label; 5658 const PetscInt *comps; 5659 const PetscInt *values; 5660 PetscInt bd2, field, numComps, numValues; 5661 PetscBool isEssential, duplicate = PETSC_FALSE; 5662 5663 bcComps[bc] = NULL; 5664 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5665 if (!isFE[field]) continue; 5666 ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5667 /* Only want to modify label once */ 5668 for (bd2 = 0; bd2 < bd; ++bd2) { 5669 const char *bdname; 5670 ierr = DMPlexGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5671 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5672 if (duplicate) break; 5673 } 5674 if (!duplicate && (isFE[field])) { 5675 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 5676 ierr = DMPlexLabelAddCells(dm, label);CHKERRQ(ierr); 5677 } 5678 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5679 if (isEssential) { 5680 PetscInt *newidx; 5681 PetscInt n, newn = 0, p, v; 5682 5683 bcFields[bc] = field; 5684 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 5685 for (v = 0; v < numValues; ++v) { 5686 IS tmp; 5687 const PetscInt *idx; 5688 5689 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5690 if (!tmp) continue; 5691 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5692 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5693 if (isFE[field]) { 5694 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5695 } else { 5696 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5697 } 5698 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5699 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5700 } 5701 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5702 newn = 0; 5703 for (v = 0; v < numValues; ++v) { 5704 IS tmp; 5705 const PetscInt *idx; 5706 5707 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5708 if (!tmp) continue; 5709 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5710 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5711 if (isFE[field]) { 5712 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5713 } else { 5714 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5715 } 5716 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5717 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5718 } 5719 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5720 } 5721 } 5722 /* Handle discretization */ 5723 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5724 for (f = 0; f < numFields; ++f) { 5725 PetscObject obj; 5726 5727 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5728 if (isFE[f]) { 5729 PetscFE fe = (PetscFE) obj; 5730 const PetscInt *numFieldDof; 5731 PetscInt d; 5732 5733 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5734 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5735 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5736 } else { 5737 PetscFV fv = (PetscFV) obj; 5738 5739 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5740 numDof[f*(dim+1)+dim] = numComp[f]; 5741 } 5742 } 5743 for (f = 0; f < numFields; ++f) { 5744 PetscInt d; 5745 for (d = 1; d < dim; ++d) { 5746 if ((numDof[f*(dim+1)+d] > 0) && (depth < dim)) SETERRQ(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Mesh must be interpolated when unknowns are specified on edges or faces."); 5747 } 5748 } 5749 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 5750 for (f = 0; f < numFields; ++f) { 5751 PetscFE fe; 5752 const char *name; 5753 5754 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5755 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5756 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5757 } 5758 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5759 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5760 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 5761 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 5762 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5763 ierr = PetscFree(isFE);CHKERRQ(ierr); 5764 PetscFunctionReturn(0); 5765 } 5766 5767 #undef __FUNCT__ 5768 #define __FUNCT__ "DMPlexGetCoarseDM" 5769 /*@ 5770 DMPlexGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5771 5772 Input Parameter: 5773 . dm - The DMPlex object 5774 5775 Output Parameter: 5776 . cdm - The coarse DM 5777 5778 Level: intermediate 5779 5780 .seealso: DMPlexSetCoarseDM() 5781 @*/ 5782 PetscErrorCode DMPlexGetCoarseDM(DM dm, DM *cdm) 5783 { 5784 PetscFunctionBegin; 5785 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5786 PetscValidPointer(cdm, 2); 5787 *cdm = ((DM_Plex *) dm->data)->coarseMesh; 5788 PetscFunctionReturn(0); 5789 } 5790 5791 #undef __FUNCT__ 5792 #define __FUNCT__ "DMPlexSetCoarseDM" 5793 /*@ 5794 DMPlexSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5795 5796 Input Parameters: 5797 + dm - The DMPlex object 5798 - cdm - The coarse DM 5799 5800 Level: intermediate 5801 5802 .seealso: DMPlexGetCoarseDM() 5803 @*/ 5804 PetscErrorCode DMPlexSetCoarseDM(DM dm, DM cdm) 5805 { 5806 DM_Plex *mesh; 5807 PetscErrorCode ierr; 5808 5809 PetscFunctionBegin; 5810 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5811 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5812 mesh = (DM_Plex *) dm->data; 5813 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 5814 mesh->coarseMesh = cdm; 5815 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 5816 PetscFunctionReturn(0); 5817 } 5818 5819 /* anchors */ 5820 #undef __FUNCT__ 5821 #define __FUNCT__ "DMPlexGetAnchors" 5822 /*@ 5823 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5824 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5825 5826 not collective 5827 5828 Input Parameters: 5829 . dm - The DMPlex object 5830 5831 Output Parameters: 5832 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5833 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5834 5835 5836 Level: intermediate 5837 5838 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5839 @*/ 5840 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 5841 { 5842 DM_Plex *plex = (DM_Plex *)dm->data; 5843 PetscErrorCode ierr; 5844 5845 PetscFunctionBegin; 5846 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5847 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 5848 if (anchorSection) *anchorSection = plex->anchorSection; 5849 if (anchorIS) *anchorIS = plex->anchorIS; 5850 PetscFunctionReturn(0); 5851 } 5852 5853 #undef __FUNCT__ 5854 #define __FUNCT__ "DMPlexSetAnchors" 5855 /*@ 5856 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 5857 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 5858 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 5859 5860 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 5861 DMGetConstraints() and filling in the entries in the constraint matrix. 5862 5863 collective on dm 5864 5865 Input Parameters: 5866 + dm - The DMPlex object 5867 . anchorSection - The section that describes the mapping from constrained points to the anchor points listed in anchorIS. Must have a local communicator (PETSC_COMM_SELF or derivative). 5868 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 5869 5870 The reference counts of anchorSection and anchorIS are incremented. 5871 5872 Level: intermediate 5873 5874 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 5875 @*/ 5876 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 5877 { 5878 DM_Plex *plex = (DM_Plex *)dm->data; 5879 PetscMPIInt result; 5880 PetscErrorCode ierr; 5881 5882 PetscFunctionBegin; 5883 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5884 if (anchorSection) { 5885 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 5886 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 5887 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 5888 } 5889 if (anchorIS) { 5890 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 5891 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 5892 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 5893 } 5894 5895 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 5896 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 5897 plex->anchorSection = anchorSection; 5898 5899 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 5900 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 5901 plex->anchorIS = anchorIS; 5902 5903 #if defined(PETSC_USE_DEBUG) 5904 if (anchorIS && anchorSection) { 5905 PetscInt size, a, pStart, pEnd; 5906 const PetscInt *anchors; 5907 5908 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5909 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 5910 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 5911 for (a = 0; a < size; a++) { 5912 PetscInt p; 5913 5914 p = anchors[a]; 5915 if (p >= pStart && p < pEnd) { 5916 PetscInt dof; 5917 5918 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5919 if (dof) { 5920 PetscErrorCode ierr2; 5921 5922 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 5923 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 5924 } 5925 } 5926 } 5927 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 5928 } 5929 #endif 5930 /* reset the generic constraints */ 5931 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 5932 PetscFunctionReturn(0); 5933 } 5934 5935 #undef __FUNCT__ 5936 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 5937 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 5938 { 5939 PetscSection anchorSection; 5940 PetscInt pStart, pEnd, p, dof, numFields, f; 5941 PetscErrorCode ierr; 5942 5943 PetscFunctionBegin; 5944 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5945 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 5946 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 5947 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5948 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 5949 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 5950 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 5951 for (p = pStart; p < pEnd; p++) { 5952 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 5953 if (dof) { 5954 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 5955 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 5956 for (f = 0; f < numFields; f++) { 5957 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 5958 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 5959 } 5960 } 5961 } 5962 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 5963 PetscFunctionReturn(0); 5964 } 5965 5966 #undef __FUNCT__ 5967 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 5968 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 5969 { 5970 PetscSection aSec; 5971 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 5972 const PetscInt *anchors; 5973 PetscInt numFields, f; 5974 IS aIS; 5975 PetscErrorCode ierr; 5976 5977 PetscFunctionBegin; 5978 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5979 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 5980 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 5981 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 5982 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 5983 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 5984 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 5985 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 5986 ierr = PetscSectionGetChart(aSec,&pStart,&pEnd);CHKERRQ(ierr); 5987 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 5988 i[0] = 0; 5989 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 5990 for (p = pStart; p < pEnd; p++) { 5991 ierr = PetscSectionGetDof(aSec,p,&dof);CHKERRQ(ierr); 5992 if (!dof) continue; 5993 ierr = PetscSectionGetOffset(aSec,p,&off);CHKERRQ(ierr); 5994 if (numFields) { 5995 for (f = 0; f < numFields; f++) { 5996 annz = 0; 5997 for (q = 0; q < dof; q++) { 5998 a = anchors[off + q]; 5999 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6000 annz += aDof; 6001 } 6002 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6003 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6004 for (q = 0; q < dof; q++) { 6005 i[off + q + 1] = i[off + q] + annz; 6006 } 6007 } 6008 } 6009 else { 6010 annz = 0; 6011 for (q = 0; q < dof; q++) { 6012 a = anchors[off + q]; 6013 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6014 annz += aDof; 6015 } 6016 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6017 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6018 for (q = 0; q < dof; q++) { 6019 i[off + q + 1] = i[off + q] + annz; 6020 } 6021 } 6022 } 6023 nnz = i[m]; 6024 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6025 offset = 0; 6026 for (p = pStart; p < pEnd; p++) { 6027 if (numFields) { 6028 for (f = 0; f < numFields; f++) { 6029 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6030 for (q = 0; q < dof; q++) { 6031 PetscInt rDof, rOff, r; 6032 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6033 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6034 for (r = 0; r < rDof; r++) { 6035 PetscInt s; 6036 6037 a = anchors[rOff + r]; 6038 6039 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6040 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6041 for (s = 0; s < aDof; s++) { 6042 j[offset++] = aOff + s; 6043 } 6044 } 6045 } 6046 } 6047 } 6048 else { 6049 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6050 for (q = 0; q < dof; q++) { 6051 PetscInt rDof, rOff, r; 6052 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6053 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6054 for (r = 0; r < rDof; r++) { 6055 PetscInt s; 6056 6057 a = anchors[rOff + r]; 6058 6059 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6060 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6061 for (s = 0; s < aDof; s++) { 6062 j[offset++] = aOff + s; 6063 } 6064 } 6065 } 6066 } 6067 } 6068 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6069 ierr = PetscFree(i);CHKERRQ(ierr); 6070 ierr = PetscFree(j);CHKERRQ(ierr); 6071 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6072 PetscFunctionReturn(0); 6073 } 6074 6075 #undef __FUNCT__ 6076 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6077 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6078 { 6079 DM_Plex *plex = (DM_Plex *)dm->data; 6080 PetscSection anchorSection, section, cSec; 6081 Mat cMat; 6082 PetscErrorCode ierr; 6083 6084 PetscFunctionBegin; 6085 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6086 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6087 if (anchorSection) { 6088 PetscDS ds; 6089 PetscInt nf; 6090 6091 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6092 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6093 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6094 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6095 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6096 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6097 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6098 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6099 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6100 } 6101 PetscFunctionReturn(0); 6102 } 6103