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