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