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)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 428 ierr = PetscOptionsGetBool(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 429 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 430 if (!useLabels) numLabels = 0; 431 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->options,((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)->options,((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 = MPIU_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 = MPIU_Allreduce(&bsLocal, &bsMax, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 838 bsLocal = bs < 0 ? bsMax : bs; 839 ierr = MPIU_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 DM_Plex *mesh = (DM_Plex*) dm->data; 1905 DMLabel label; 1906 PetscInt pStart, pEnd, p; 1907 PetscInt numRoots = 0, numLeaves = 0; 1908 PetscErrorCode ierr; 1909 1910 PetscFunctionBegin; 1911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 1912 ierr = PetscLogEventBegin(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1913 /* Calculate depth */ 1914 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 1915 ierr = DMPlexCreateLabel(dm, "depth");CHKERRQ(ierr); 1916 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 1917 /* Initialize roots and count leaves */ 1918 for (p = pStart; p < pEnd; ++p) { 1919 PetscInt coneSize, supportSize; 1920 1921 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1922 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1923 if (!coneSize && supportSize) { 1924 ++numRoots; 1925 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1926 } else if (!supportSize && coneSize) { 1927 ++numLeaves; 1928 } else if (!supportSize && !coneSize) { 1929 /* Isolated points */ 1930 ierr = DMLabelSetValue(label, p, 0);CHKERRQ(ierr); 1931 } 1932 } 1933 if (numRoots + numLeaves == (pEnd - pStart)) { 1934 for (p = pStart; p < pEnd; ++p) { 1935 PetscInt coneSize, supportSize; 1936 1937 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 1938 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 1939 if (!supportSize && coneSize) { 1940 ierr = DMLabelSetValue(label, p, 1);CHKERRQ(ierr); 1941 } 1942 } 1943 } else { 1944 IS pointIS; 1945 PetscInt numPoints = 0, level = 0; 1946 1947 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1948 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1949 while (numPoints) { 1950 const PetscInt *points; 1951 const PetscInt newLevel = level+1; 1952 1953 ierr = ISGetIndices(pointIS, &points);CHKERRQ(ierr); 1954 for (p = 0; p < numPoints; ++p) { 1955 const PetscInt point = points[p]; 1956 const PetscInt *support; 1957 PetscInt supportSize, s; 1958 1959 ierr = DMPlexGetSupportSize(dm, point, &supportSize);CHKERRQ(ierr); 1960 ierr = DMPlexGetSupport(dm, point, &support);CHKERRQ(ierr); 1961 for (s = 0; s < supportSize; ++s) { 1962 ierr = DMLabelSetValue(label, support[s], newLevel);CHKERRQ(ierr); 1963 } 1964 } 1965 ierr = ISRestoreIndices(pointIS, &points);CHKERRQ(ierr); 1966 ++level; 1967 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1968 ierr = DMLabelGetStratumIS(label, level, &pointIS);CHKERRQ(ierr); 1969 if (pointIS) {ierr = ISGetLocalSize(pointIS, &numPoints);CHKERRQ(ierr);} 1970 else {numPoints = 0;} 1971 } 1972 ierr = ISDestroy(&pointIS);CHKERRQ(ierr); 1973 } 1974 ierr = DMLabelGetState(label, &mesh->depthState);CHKERRQ(ierr); 1975 ierr = PetscLogEventEnd(DMPLEX_Stratify,dm,0,0,0);CHKERRQ(ierr); 1976 PetscFunctionReturn(0); 1977 } 1978 1979 #undef __FUNCT__ 1980 #define __FUNCT__ "DMPlexGetJoin" 1981 /*@C 1982 DMPlexGetJoin - Get an array for the join of the set of points 1983 1984 Not Collective 1985 1986 Input Parameters: 1987 + dm - The DMPlex object 1988 . numPoints - The number of input points for the join 1989 - points - The input points 1990 1991 Output Parameters: 1992 + numCoveredPoints - The number of points in the join 1993 - coveredPoints - The points in the join 1994 1995 Level: intermediate 1996 1997 Note: Currently, this is restricted to a single level join 1998 1999 Fortran Notes: 2000 Since it returns an array, this routine is only available in Fortran 90, and you must 2001 include petsc.h90 in your code. 2002 2003 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2004 2005 .keywords: mesh 2006 .seealso: DMPlexRestoreJoin(), DMPlexGetMeet() 2007 @*/ 2008 PetscErrorCode DMPlexGetJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2009 { 2010 DM_Plex *mesh = (DM_Plex*) dm->data; 2011 PetscInt *join[2]; 2012 PetscInt joinSize, i = 0; 2013 PetscInt dof, off, p, c, m; 2014 PetscErrorCode ierr; 2015 2016 PetscFunctionBegin; 2017 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2018 PetscValidPointer(points, 2); 2019 PetscValidPointer(numCoveredPoints, 3); 2020 PetscValidPointer(coveredPoints, 4); 2021 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2022 ierr = DMGetWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2023 /* Copy in support of first point */ 2024 ierr = PetscSectionGetDof(mesh->supportSection, points[0], &dof);CHKERRQ(ierr); 2025 ierr = PetscSectionGetOffset(mesh->supportSection, points[0], &off);CHKERRQ(ierr); 2026 for (joinSize = 0; joinSize < dof; ++joinSize) { 2027 join[i][joinSize] = mesh->supports[off+joinSize]; 2028 } 2029 /* Check each successive support */ 2030 for (p = 1; p < numPoints; ++p) { 2031 PetscInt newJoinSize = 0; 2032 2033 ierr = PetscSectionGetDof(mesh->supportSection, points[p], &dof);CHKERRQ(ierr); 2034 ierr = PetscSectionGetOffset(mesh->supportSection, points[p], &off);CHKERRQ(ierr); 2035 for (c = 0; c < dof; ++c) { 2036 const PetscInt point = mesh->supports[off+c]; 2037 2038 for (m = 0; m < joinSize; ++m) { 2039 if (point == join[i][m]) { 2040 join[1-i][newJoinSize++] = point; 2041 break; 2042 } 2043 } 2044 } 2045 joinSize = newJoinSize; 2046 i = 1-i; 2047 } 2048 *numCoveredPoints = joinSize; 2049 *coveredPoints = join[i]; 2050 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2051 PetscFunctionReturn(0); 2052 } 2053 2054 #undef __FUNCT__ 2055 #define __FUNCT__ "DMPlexRestoreJoin" 2056 /*@C 2057 DMPlexRestoreJoin - Restore an array for the join of the set of points 2058 2059 Not Collective 2060 2061 Input Parameters: 2062 + dm - The DMPlex object 2063 . numPoints - The number of input points for the join 2064 - points - The input points 2065 2066 Output Parameters: 2067 + numCoveredPoints - The number of points in the join 2068 - coveredPoints - The points in the join 2069 2070 Fortran Notes: 2071 Since it returns an array, this routine is only available in Fortran 90, and you must 2072 include petsc.h90 in your code. 2073 2074 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2075 2076 Level: intermediate 2077 2078 .keywords: mesh 2079 .seealso: DMPlexGetJoin(), DMPlexGetFullJoin(), DMPlexGetMeet() 2080 @*/ 2081 PetscErrorCode DMPlexRestoreJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2082 { 2083 PetscErrorCode ierr; 2084 2085 PetscFunctionBegin; 2086 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2087 if (points) PetscValidIntPointer(points,3); 2088 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2089 PetscValidPointer(coveredPoints, 5); 2090 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2091 if (numCoveredPoints) *numCoveredPoints = 0; 2092 PetscFunctionReturn(0); 2093 } 2094 2095 #undef __FUNCT__ 2096 #define __FUNCT__ "DMPlexGetFullJoin" 2097 /*@C 2098 DMPlexGetFullJoin - Get an array for the join of the set of points 2099 2100 Not Collective 2101 2102 Input Parameters: 2103 + dm - The DMPlex object 2104 . numPoints - The number of input points for the join 2105 - points - The input points 2106 2107 Output Parameters: 2108 + numCoveredPoints - The number of points in the join 2109 - coveredPoints - The points in the join 2110 2111 Fortran Notes: 2112 Since it returns an array, this routine is only available in Fortran 90, and you must 2113 include petsc.h90 in your code. 2114 2115 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2116 2117 Level: intermediate 2118 2119 .keywords: mesh 2120 .seealso: DMPlexGetJoin(), DMPlexRestoreJoin(), DMPlexGetMeet() 2121 @*/ 2122 PetscErrorCode DMPlexGetFullJoin(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2123 { 2124 DM_Plex *mesh = (DM_Plex*) dm->data; 2125 PetscInt *offsets, **closures; 2126 PetscInt *join[2]; 2127 PetscInt depth = 0, maxSize, joinSize = 0, i = 0; 2128 PetscInt p, d, c, m, ms; 2129 PetscErrorCode ierr; 2130 2131 PetscFunctionBegin; 2132 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2133 PetscValidPointer(points, 2); 2134 PetscValidPointer(numCoveredPoints, 3); 2135 PetscValidPointer(coveredPoints, 4); 2136 2137 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2138 ierr = PetscCalloc1(numPoints, &closures);CHKERRQ(ierr); 2139 ierr = DMGetWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2140 ms = mesh->maxSupportSize; 2141 maxSize = (ms > 1) ? ((PetscPowInt(ms,depth+1)-1)/(ms-1)) : depth + 1; 2142 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[0]);CHKERRQ(ierr); 2143 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &join[1]);CHKERRQ(ierr); 2144 2145 for (p = 0; p < numPoints; ++p) { 2146 PetscInt closureSize; 2147 2148 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_FALSE, &closureSize, &closures[p]);CHKERRQ(ierr); 2149 2150 offsets[p*(depth+2)+0] = 0; 2151 for (d = 0; d < depth+1; ++d) { 2152 PetscInt pStart, pEnd, i; 2153 2154 ierr = DMPlexGetDepthStratum(dm, d, &pStart, &pEnd);CHKERRQ(ierr); 2155 for (i = offsets[p*(depth+2)+d]; i < closureSize; ++i) { 2156 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2157 offsets[p*(depth+2)+d+1] = i; 2158 break; 2159 } 2160 } 2161 if (i == closureSize) offsets[p*(depth+2)+d+1] = i; 2162 } 2163 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); 2164 } 2165 for (d = 0; d < depth+1; ++d) { 2166 PetscInt dof; 2167 2168 /* Copy in support of first point */ 2169 dof = offsets[d+1] - offsets[d]; 2170 for (joinSize = 0; joinSize < dof; ++joinSize) { 2171 join[i][joinSize] = closures[0][(offsets[d]+joinSize)*2]; 2172 } 2173 /* Check each successive cone */ 2174 for (p = 1; p < numPoints && joinSize; ++p) { 2175 PetscInt newJoinSize = 0; 2176 2177 dof = offsets[p*(depth+2)+d+1] - offsets[p*(depth+2)+d]; 2178 for (c = 0; c < dof; ++c) { 2179 const PetscInt point = closures[p][(offsets[p*(depth+2)+d]+c)*2]; 2180 2181 for (m = 0; m < joinSize; ++m) { 2182 if (point == join[i][m]) { 2183 join[1-i][newJoinSize++] = point; 2184 break; 2185 } 2186 } 2187 } 2188 joinSize = newJoinSize; 2189 i = 1-i; 2190 } 2191 if (joinSize) break; 2192 } 2193 *numCoveredPoints = joinSize; 2194 *coveredPoints = join[i]; 2195 for (p = 0; p < numPoints; ++p) { 2196 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_FALSE, NULL, &closures[p]);CHKERRQ(ierr); 2197 } 2198 ierr = PetscFree(closures);CHKERRQ(ierr); 2199 ierr = DMRestoreWorkArray(dm, numPoints*(depth+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2200 ierr = DMRestoreWorkArray(dm, mesh->maxSupportSize, PETSC_INT, &join[1-i]);CHKERRQ(ierr); 2201 PetscFunctionReturn(0); 2202 } 2203 2204 #undef __FUNCT__ 2205 #define __FUNCT__ "DMPlexGetMeet" 2206 /*@C 2207 DMPlexGetMeet - Get an array for the meet of the set of points 2208 2209 Not Collective 2210 2211 Input Parameters: 2212 + dm - The DMPlex object 2213 . numPoints - The number of input points for the meet 2214 - points - The input points 2215 2216 Output Parameters: 2217 + numCoveredPoints - The number of points in the meet 2218 - coveredPoints - The points in the meet 2219 2220 Level: intermediate 2221 2222 Note: Currently, this is restricted to a single level meet 2223 2224 Fortran Notes: 2225 Since it returns an array, this routine is only available in Fortran 90, and you must 2226 include petsc.h90 in your code. 2227 2228 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2229 2230 .keywords: mesh 2231 .seealso: DMPlexRestoreMeet(), DMPlexGetJoin() 2232 @*/ 2233 PetscErrorCode DMPlexGetMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveringPoints, const PetscInt **coveringPoints) 2234 { 2235 DM_Plex *mesh = (DM_Plex*) dm->data; 2236 PetscInt *meet[2]; 2237 PetscInt meetSize, i = 0; 2238 PetscInt dof, off, p, c, m; 2239 PetscErrorCode ierr; 2240 2241 PetscFunctionBegin; 2242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2243 PetscValidPointer(points, 2); 2244 PetscValidPointer(numCoveringPoints, 3); 2245 PetscValidPointer(coveringPoints, 4); 2246 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2247 ierr = DMGetWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2248 /* Copy in cone of first point */ 2249 ierr = PetscSectionGetDof(mesh->coneSection, points[0], &dof);CHKERRQ(ierr); 2250 ierr = PetscSectionGetOffset(mesh->coneSection, points[0], &off);CHKERRQ(ierr); 2251 for (meetSize = 0; meetSize < dof; ++meetSize) { 2252 meet[i][meetSize] = mesh->cones[off+meetSize]; 2253 } 2254 /* Check each successive cone */ 2255 for (p = 1; p < numPoints; ++p) { 2256 PetscInt newMeetSize = 0; 2257 2258 ierr = PetscSectionGetDof(mesh->coneSection, points[p], &dof);CHKERRQ(ierr); 2259 ierr = PetscSectionGetOffset(mesh->coneSection, points[p], &off);CHKERRQ(ierr); 2260 for (c = 0; c < dof; ++c) { 2261 const PetscInt point = mesh->cones[off+c]; 2262 2263 for (m = 0; m < meetSize; ++m) { 2264 if (point == meet[i][m]) { 2265 meet[1-i][newMeetSize++] = point; 2266 break; 2267 } 2268 } 2269 } 2270 meetSize = newMeetSize; 2271 i = 1-i; 2272 } 2273 *numCoveringPoints = meetSize; 2274 *coveringPoints = meet[i]; 2275 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2276 PetscFunctionReturn(0); 2277 } 2278 2279 #undef __FUNCT__ 2280 #define __FUNCT__ "DMPlexRestoreMeet" 2281 /*@C 2282 DMPlexRestoreMeet - Restore an array for the meet of the set of points 2283 2284 Not Collective 2285 2286 Input Parameters: 2287 + dm - The DMPlex object 2288 . numPoints - The number of input points for the meet 2289 - points - The input points 2290 2291 Output Parameters: 2292 + numCoveredPoints - The number of points in the meet 2293 - coveredPoints - The points in the meet 2294 2295 Level: intermediate 2296 2297 Fortran Notes: 2298 Since it returns an array, this routine is only available in Fortran 90, and you must 2299 include petsc.h90 in your code. 2300 2301 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2302 2303 .keywords: mesh 2304 .seealso: DMPlexGetMeet(), DMPlexGetFullMeet(), DMPlexGetJoin() 2305 @*/ 2306 PetscErrorCode DMPlexRestoreMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2307 { 2308 PetscErrorCode ierr; 2309 2310 PetscFunctionBegin; 2311 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2312 if (points) PetscValidIntPointer(points,3); 2313 if (numCoveredPoints) PetscValidIntPointer(numCoveredPoints,4); 2314 PetscValidPointer(coveredPoints,5); 2315 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, (void*) coveredPoints);CHKERRQ(ierr); 2316 if (numCoveredPoints) *numCoveredPoints = 0; 2317 PetscFunctionReturn(0); 2318 } 2319 2320 #undef __FUNCT__ 2321 #define __FUNCT__ "DMPlexGetFullMeet" 2322 /*@C 2323 DMPlexGetFullMeet - Get an array for the meet of the set of points 2324 2325 Not Collective 2326 2327 Input Parameters: 2328 + dm - The DMPlex object 2329 . numPoints - The number of input points for the meet 2330 - points - The input points 2331 2332 Output Parameters: 2333 + numCoveredPoints - The number of points in the meet 2334 - coveredPoints - The points in the meet 2335 2336 Level: intermediate 2337 2338 Fortran Notes: 2339 Since it returns an array, this routine is only available in Fortran 90, and you must 2340 include petsc.h90 in your code. 2341 2342 The numCoveredPoints argument is not present in the Fortran 90 binding since it is internal to the array. 2343 2344 .keywords: mesh 2345 .seealso: DMPlexGetMeet(), DMPlexRestoreMeet(), DMPlexGetJoin() 2346 @*/ 2347 PetscErrorCode DMPlexGetFullMeet(DM dm, PetscInt numPoints, const PetscInt points[], PetscInt *numCoveredPoints, const PetscInt **coveredPoints) 2348 { 2349 DM_Plex *mesh = (DM_Plex*) dm->data; 2350 PetscInt *offsets, **closures; 2351 PetscInt *meet[2]; 2352 PetscInt height = 0, maxSize, meetSize = 0, i = 0; 2353 PetscInt p, h, c, m, mc; 2354 PetscErrorCode ierr; 2355 2356 PetscFunctionBegin; 2357 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2358 PetscValidPointer(points, 2); 2359 PetscValidPointer(numCoveredPoints, 3); 2360 PetscValidPointer(coveredPoints, 4); 2361 2362 ierr = DMPlexGetDepth(dm, &height);CHKERRQ(ierr); 2363 ierr = PetscMalloc1(numPoints, &closures);CHKERRQ(ierr); 2364 ierr = DMGetWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2365 mc = mesh->maxConeSize; 2366 maxSize = (mc > 1) ? ((PetscPowInt(mc,height+1)-1)/(mc-1)) : height + 1; 2367 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[0]);CHKERRQ(ierr); 2368 ierr = DMGetWorkArray(dm, maxSize, PETSC_INT, &meet[1]);CHKERRQ(ierr); 2369 2370 for (p = 0; p < numPoints; ++p) { 2371 PetscInt closureSize; 2372 2373 ierr = DMPlexGetTransitiveClosure(dm, points[p], PETSC_TRUE, &closureSize, &closures[p]);CHKERRQ(ierr); 2374 2375 offsets[p*(height+2)+0] = 0; 2376 for (h = 0; h < height+1; ++h) { 2377 PetscInt pStart, pEnd, i; 2378 2379 ierr = DMPlexGetHeightStratum(dm, h, &pStart, &pEnd);CHKERRQ(ierr); 2380 for (i = offsets[p*(height+2)+h]; i < closureSize; ++i) { 2381 if ((pStart > closures[p][i*2]) || (pEnd <= closures[p][i*2])) { 2382 offsets[p*(height+2)+h+1] = i; 2383 break; 2384 } 2385 } 2386 if (i == closureSize) offsets[p*(height+2)+h+1] = i; 2387 } 2388 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); 2389 } 2390 for (h = 0; h < height+1; ++h) { 2391 PetscInt dof; 2392 2393 /* Copy in cone of first point */ 2394 dof = offsets[h+1] - offsets[h]; 2395 for (meetSize = 0; meetSize < dof; ++meetSize) { 2396 meet[i][meetSize] = closures[0][(offsets[h]+meetSize)*2]; 2397 } 2398 /* Check each successive cone */ 2399 for (p = 1; p < numPoints && meetSize; ++p) { 2400 PetscInt newMeetSize = 0; 2401 2402 dof = offsets[p*(height+2)+h+1] - offsets[p*(height+2)+h]; 2403 for (c = 0; c < dof; ++c) { 2404 const PetscInt point = closures[p][(offsets[p*(height+2)+h]+c)*2]; 2405 2406 for (m = 0; m < meetSize; ++m) { 2407 if (point == meet[i][m]) { 2408 meet[1-i][newMeetSize++] = point; 2409 break; 2410 } 2411 } 2412 } 2413 meetSize = newMeetSize; 2414 i = 1-i; 2415 } 2416 if (meetSize) break; 2417 } 2418 *numCoveredPoints = meetSize; 2419 *coveredPoints = meet[i]; 2420 for (p = 0; p < numPoints; ++p) { 2421 ierr = DMPlexRestoreTransitiveClosure(dm, points[p], PETSC_TRUE, NULL, &closures[p]);CHKERRQ(ierr); 2422 } 2423 ierr = PetscFree(closures);CHKERRQ(ierr); 2424 ierr = DMRestoreWorkArray(dm, numPoints*(height+2), PETSC_INT, &offsets);CHKERRQ(ierr); 2425 ierr = DMRestoreWorkArray(dm, mesh->maxConeSize, PETSC_INT, &meet[1-i]);CHKERRQ(ierr); 2426 PetscFunctionReturn(0); 2427 } 2428 2429 #undef __FUNCT__ 2430 #define __FUNCT__ "DMPlexEqual" 2431 /*@C 2432 DMPlexEqual - Determine if two DMs have the same topology 2433 2434 Not Collective 2435 2436 Input Parameters: 2437 + dmA - A DMPlex object 2438 - dmB - A DMPlex object 2439 2440 Output Parameters: 2441 . equal - PETSC_TRUE if the topologies are identical 2442 2443 Level: intermediate 2444 2445 Notes: 2446 We are not solving graph isomorphism, so we do not permutation. 2447 2448 .keywords: mesh 2449 .seealso: DMPlexGetCone() 2450 @*/ 2451 PetscErrorCode DMPlexEqual(DM dmA, DM dmB, PetscBool *equal) 2452 { 2453 PetscInt depth, depthB, pStart, pEnd, pStartB, pEndB, p; 2454 PetscErrorCode ierr; 2455 2456 PetscFunctionBegin; 2457 PetscValidHeaderSpecific(dmA, DM_CLASSID, 1); 2458 PetscValidHeaderSpecific(dmB, DM_CLASSID, 2); 2459 PetscValidPointer(equal, 3); 2460 2461 *equal = PETSC_FALSE; 2462 ierr = DMPlexGetDepth(dmA, &depth);CHKERRQ(ierr); 2463 ierr = DMPlexGetDepth(dmB, &depthB);CHKERRQ(ierr); 2464 if (depth != depthB) PetscFunctionReturn(0); 2465 ierr = DMPlexGetChart(dmA, &pStart, &pEnd);CHKERRQ(ierr); 2466 ierr = DMPlexGetChart(dmB, &pStartB, &pEndB);CHKERRQ(ierr); 2467 if ((pStart != pStartB) || (pEnd != pEndB)) PetscFunctionReturn(0); 2468 for (p = pStart; p < pEnd; ++p) { 2469 const PetscInt *cone, *coneB, *ornt, *orntB, *support, *supportB; 2470 PetscInt coneSize, coneSizeB, c, supportSize, supportSizeB, s; 2471 2472 ierr = DMPlexGetConeSize(dmA, p, &coneSize);CHKERRQ(ierr); 2473 ierr = DMPlexGetCone(dmA, p, &cone);CHKERRQ(ierr); 2474 ierr = DMPlexGetConeOrientation(dmA, p, &ornt);CHKERRQ(ierr); 2475 ierr = DMPlexGetConeSize(dmB, p, &coneSizeB);CHKERRQ(ierr); 2476 ierr = DMPlexGetCone(dmB, p, &coneB);CHKERRQ(ierr); 2477 ierr = DMPlexGetConeOrientation(dmB, p, &orntB);CHKERRQ(ierr); 2478 if (coneSize != coneSizeB) PetscFunctionReturn(0); 2479 for (c = 0; c < coneSize; ++c) { 2480 if (cone[c] != coneB[c]) PetscFunctionReturn(0); 2481 if (ornt[c] != orntB[c]) PetscFunctionReturn(0); 2482 } 2483 ierr = DMPlexGetSupportSize(dmA, p, &supportSize);CHKERRQ(ierr); 2484 ierr = DMPlexGetSupport(dmA, p, &support);CHKERRQ(ierr); 2485 ierr = DMPlexGetSupportSize(dmB, p, &supportSizeB);CHKERRQ(ierr); 2486 ierr = DMPlexGetSupport(dmB, p, &supportB);CHKERRQ(ierr); 2487 if (supportSize != supportSizeB) PetscFunctionReturn(0); 2488 for (s = 0; s < supportSize; ++s) { 2489 if (support[s] != supportB[s]) PetscFunctionReturn(0); 2490 } 2491 } 2492 *equal = PETSC_TRUE; 2493 PetscFunctionReturn(0); 2494 } 2495 2496 #undef __FUNCT__ 2497 #define __FUNCT__ "DMPlexGetNumFaceVertices" 2498 PetscErrorCode DMPlexGetNumFaceVertices(DM dm, PetscInt cellDim, PetscInt numCorners, PetscInt *numFaceVertices) 2499 { 2500 MPI_Comm comm; 2501 PetscErrorCode ierr; 2502 2503 PetscFunctionBegin; 2504 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 2505 PetscValidPointer(numFaceVertices,3); 2506 switch (cellDim) { 2507 case 0: 2508 *numFaceVertices = 0; 2509 break; 2510 case 1: 2511 *numFaceVertices = 1; 2512 break; 2513 case 2: 2514 switch (numCorners) { 2515 case 3: /* triangle */ 2516 *numFaceVertices = 2; /* Edge has 2 vertices */ 2517 break; 2518 case 4: /* quadrilateral */ 2519 *numFaceVertices = 2; /* Edge has 2 vertices */ 2520 break; 2521 case 6: /* quadratic triangle, tri and quad cohesive Lagrange cells */ 2522 *numFaceVertices = 3; /* Edge has 3 vertices */ 2523 break; 2524 case 9: /* quadratic quadrilateral, quadratic quad cohesive Lagrange cells */ 2525 *numFaceVertices = 3; /* Edge has 3 vertices */ 2526 break; 2527 default: 2528 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2529 } 2530 break; 2531 case 3: 2532 switch (numCorners) { 2533 case 4: /* tetradehdron */ 2534 *numFaceVertices = 3; /* Face has 3 vertices */ 2535 break; 2536 case 6: /* tet cohesive cells */ 2537 *numFaceVertices = 4; /* Face has 4 vertices */ 2538 break; 2539 case 8: /* hexahedron */ 2540 *numFaceVertices = 4; /* Face has 4 vertices */ 2541 break; 2542 case 9: /* tet cohesive Lagrange cells */ 2543 *numFaceVertices = 6; /* Face has 6 vertices */ 2544 break; 2545 case 10: /* quadratic tetrahedron */ 2546 *numFaceVertices = 6; /* Face has 6 vertices */ 2547 break; 2548 case 12: /* hex cohesive Lagrange cells */ 2549 *numFaceVertices = 6; /* Face has 6 vertices */ 2550 break; 2551 case 18: /* quadratic tet cohesive Lagrange cells */ 2552 *numFaceVertices = 6; /* Face has 6 vertices */ 2553 break; 2554 case 27: /* quadratic hexahedron, quadratic hex cohesive Lagrange cells */ 2555 *numFaceVertices = 9; /* Face has 9 vertices */ 2556 break; 2557 default: 2558 SETERRQ2(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid number of face corners %D for dimension %D", numCorners, cellDim); 2559 } 2560 break; 2561 default: 2562 SETERRQ1(comm, PETSC_ERR_ARG_OUTOFRANGE, "Invalid cell dimension %D", cellDim); 2563 } 2564 PetscFunctionReturn(0); 2565 } 2566 2567 #undef __FUNCT__ 2568 #define __FUNCT__ "DMPlexLocalizeCoordinate" 2569 /*@ 2570 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. 2571 2572 Input Parameters: 2573 + dm - The DM 2574 - in - The input coordinate point (dim numbers) 2575 2576 Output Parameter: 2577 . out - The localized coordinate point 2578 2579 Level: developer 2580 2581 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2582 @*/ 2583 PetscErrorCode DMPlexLocalizeCoordinate(DM dm, const PetscScalar in[], PetscScalar out[]) 2584 { 2585 PetscInt dim, d; 2586 PetscErrorCode ierr; 2587 2588 PetscFunctionBegin; 2589 ierr = DMGetCoordinateDim(dm, &dim);CHKERRQ(ierr); 2590 if (!dm->maxCell) { 2591 for (d = 0; d < dim; ++d) out[d] = in[d]; 2592 } else { 2593 for (d = 0; d < dim; ++d) { 2594 out[d] = in[d] - dm->L[d]*floor(PetscRealPart(in[d])/dm->L[d]); 2595 } 2596 } 2597 PetscFunctionReturn(0); 2598 } 2599 2600 #undef __FUNCT__ 2601 #define __FUNCT__ "DMPlexLocalizeCoordinate_Internal" 2602 /* 2603 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. 2604 2605 Input Parameters: 2606 + dm - The DM 2607 . dim - The spatial dimension 2608 . anchor - The anchor point, the input point can be no more than maxCell away from it 2609 - in - The input coordinate point (dim numbers) 2610 2611 Output Parameter: 2612 . out - The localized coordinate point 2613 2614 Level: developer 2615 2616 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 2617 2618 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeAddCoordinate() 2619 */ 2620 PetscErrorCode DMPlexLocalizeCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2621 { 2622 PetscInt d; 2623 2624 PetscFunctionBegin; 2625 if (!dm->maxCell) { 2626 for (d = 0; d < dim; ++d) out[d] = in[d]; 2627 } else { 2628 for (d = 0; d < dim; ++d) { 2629 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2630 out[d] = PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2631 } else { 2632 out[d] = in[d]; 2633 } 2634 } 2635 } 2636 PetscFunctionReturn(0); 2637 } 2638 #undef __FUNCT__ 2639 #define __FUNCT__ "DMPlexLocalizeCoordinateReal_Internal" 2640 PetscErrorCode DMPlexLocalizeCoordinateReal_Internal(DM dm, PetscInt dim, const PetscReal anchor[], const PetscReal in[], PetscReal out[]) 2641 { 2642 PetscInt d; 2643 2644 PetscFunctionBegin; 2645 if (!dm->maxCell) { 2646 for (d = 0; d < dim; ++d) out[d] = in[d]; 2647 } else { 2648 for (d = 0; d < dim; ++d) { 2649 if (PetscAbsReal(anchor[d] - in[d]) > dm->maxCell[d]) { 2650 out[d] = anchor[d] > in[d] ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2651 } else { 2652 out[d] = in[d]; 2653 } 2654 } 2655 } 2656 PetscFunctionReturn(0); 2657 } 2658 2659 #undef __FUNCT__ 2660 #define __FUNCT__ "DMPlexLocalizeAddCoordinate_Internal" 2661 /* 2662 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. 2663 2664 Input Parameters: 2665 + dm - The DM 2666 . dim - The spatial dimension 2667 . anchor - The anchor point, the input point can be no more than maxCell away from it 2668 . in - The input coordinate delta (dim numbers) 2669 - out - The input coordinate point (dim numbers) 2670 2671 Output Parameter: 2672 . out - The localized coordinate in + out 2673 2674 Level: developer 2675 2676 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 2677 2678 .seealso: DMPlexLocalizeCoordinates(), DMPlexLocalizeCoordinate() 2679 */ 2680 PetscErrorCode DMPlexLocalizeAddCoordinate_Internal(DM dm, PetscInt dim, const PetscScalar anchor[], const PetscScalar in[], PetscScalar out[]) 2681 { 2682 PetscInt d; 2683 2684 PetscFunctionBegin; 2685 if (!dm->maxCell) { 2686 for (d = 0; d < dim; ++d) out[d] += in[d]; 2687 } else { 2688 for (d = 0; d < dim; ++d) { 2689 if (PetscAbsScalar(anchor[d] - in[d]) > dm->maxCell[d]) { 2690 out[d] += PetscRealPart(anchor[d]) > PetscRealPart(in[d]) ? dm->L[d] + in[d] : in[d] - dm->L[d]; 2691 } else { 2692 out[d] += in[d]; 2693 } 2694 } 2695 } 2696 PetscFunctionReturn(0); 2697 } 2698 2699 #undef __FUNCT__ 2700 #define __FUNCT__ "DMPlexLocalizeCoordinates" 2701 /*@ 2702 DMPlexLocalizeCoordinates - If a mesh is periodic, create local coordinates for each cell 2703 2704 Input Parameter: 2705 . dm - The DM 2706 2707 Level: developer 2708 2709 .seealso: DMPlexLocalizeCoordinate(), DMPlexLocalizeAddCoordinate() 2710 @*/ 2711 PetscErrorCode DMPlexLocalizeCoordinates(DM dm) 2712 { 2713 PetscSection coordSection, cSection; 2714 Vec coordinates, cVec; 2715 PetscScalar *coords, *coords2, *anchor; 2716 PetscInt Nc, cStart, cEnd, c, vStart, vEnd, v, dof, d, off, off2, bs, coordSize; 2717 PetscErrorCode ierr; 2718 2719 PetscFunctionBegin; 2720 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2721 if (!dm->maxCell) PetscFunctionReturn(0); 2722 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 2723 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 2724 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 2725 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 2726 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) dm), &cSection);CHKERRQ(ierr); 2727 ierr = PetscSectionSetNumFields(cSection, 1);CHKERRQ(ierr); 2728 ierr = PetscSectionGetFieldComponents(coordSection, 0, &Nc);CHKERRQ(ierr); 2729 ierr = PetscSectionSetFieldComponents(cSection, 0, Nc);CHKERRQ(ierr); 2730 ierr = PetscSectionSetChart(cSection, cStart, vEnd);CHKERRQ(ierr); 2731 for (v = vStart; v < vEnd; ++v) { 2732 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2733 ierr = PetscSectionSetDof(cSection, v, dof);CHKERRQ(ierr); 2734 ierr = PetscSectionSetFieldDof(cSection, v, 0, dof);CHKERRQ(ierr); 2735 } 2736 for (c = cStart; c < cEnd; ++c) { 2737 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, NULL);CHKERRQ(ierr); 2738 ierr = PetscSectionSetDof(cSection, c, dof);CHKERRQ(ierr); 2739 ierr = PetscSectionSetFieldDof(cSection, c, 0, dof);CHKERRQ(ierr); 2740 } 2741 ierr = PetscSectionSetUp(cSection);CHKERRQ(ierr); 2742 ierr = PetscSectionGetStorageSize(cSection, &coordSize);CHKERRQ(ierr); 2743 ierr = VecCreate(PetscObjectComm((PetscObject) dm), &cVec);CHKERRQ(ierr); 2744 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 2745 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 2746 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2747 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 2748 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2749 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 2750 for (v = vStart; v < vEnd; ++v) { 2751 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2752 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 2753 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 2754 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 2755 } 2756 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2757 for (c = cStart; c < cEnd; ++c) { 2758 PetscScalar *cellCoords = NULL; 2759 PetscInt b; 2760 2761 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2762 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 2763 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 2764 for (d = 0; d < dof/bs; ++d) {ierr = DMPlexLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 2765 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2766 } 2767 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2768 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2769 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 2770 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 2771 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 2772 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2773 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 2774 PetscFunctionReturn(0); 2775 } 2776 2777 #undef __FUNCT__ 2778 #define __FUNCT__ "DMPlexGetDepthLabel" 2779 /*@ 2780 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2781 2782 Not Collective 2783 2784 Input Parameter: 2785 . dm - The DMPlex object 2786 2787 Output Parameter: 2788 . depthLabel - The DMLabel recording point depth 2789 2790 Level: developer 2791 2792 .keywords: mesh, points 2793 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2794 @*/ 2795 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2796 { 2797 DM_Plex *mesh = (DM_Plex*) dm->data; 2798 PetscErrorCode ierr; 2799 2800 PetscFunctionBegin; 2801 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2802 PetscValidPointer(depthLabel, 2); 2803 if (!mesh->depthLabel) {ierr = DMPlexGetLabel(dm, "depth", &mesh->depthLabel);CHKERRQ(ierr);} 2804 *depthLabel = mesh->depthLabel; 2805 PetscFunctionReturn(0); 2806 } 2807 2808 #undef __FUNCT__ 2809 #define __FUNCT__ "DMPlexGetDepth" 2810 /*@ 2811 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2812 2813 Not Collective 2814 2815 Input Parameter: 2816 . dm - The DMPlex object 2817 2818 Output Parameter: 2819 . depth - The number of strata (breadth first levels) in the DAG 2820 2821 Level: developer 2822 2823 .keywords: mesh, points 2824 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2825 @*/ 2826 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2827 { 2828 DMLabel label; 2829 PetscInt d = 0; 2830 PetscErrorCode ierr; 2831 2832 PetscFunctionBegin; 2833 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2834 PetscValidPointer(depth, 2); 2835 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2836 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2837 *depth = d-1; 2838 PetscFunctionReturn(0); 2839 } 2840 2841 #undef __FUNCT__ 2842 #define __FUNCT__ "DMPlexGetDepthStratum" 2843 /*@ 2844 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2845 2846 Not Collective 2847 2848 Input Parameters: 2849 + dm - The DMPlex object 2850 - stratumValue - The requested depth 2851 2852 Output Parameters: 2853 + start - The first point at this depth 2854 - end - One beyond the last point at this depth 2855 2856 Level: developer 2857 2858 .keywords: mesh, points 2859 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2860 @*/ 2861 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2862 { 2863 DMLabel label; 2864 PetscInt pStart, pEnd; 2865 PetscErrorCode ierr; 2866 2867 PetscFunctionBegin; 2868 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2869 if (start) {PetscValidPointer(start, 3); *start = 0;} 2870 if (end) {PetscValidPointer(end, 4); *end = 0;} 2871 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2872 if (pStart == pEnd) PetscFunctionReturn(0); 2873 if (stratumValue < 0) { 2874 if (start) *start = pStart; 2875 if (end) *end = pEnd; 2876 PetscFunctionReturn(0); 2877 } 2878 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2879 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2880 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2881 PetscFunctionReturn(0); 2882 } 2883 2884 #undef __FUNCT__ 2885 #define __FUNCT__ "DMPlexGetHeightStratum" 2886 /*@ 2887 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2888 2889 Not Collective 2890 2891 Input Parameters: 2892 + dm - The DMPlex object 2893 - stratumValue - The requested height 2894 2895 Output Parameters: 2896 + start - The first point at this height 2897 - end - One beyond the last point at this height 2898 2899 Level: developer 2900 2901 .keywords: mesh, points 2902 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2903 @*/ 2904 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2905 { 2906 DMLabel label; 2907 PetscInt depth, pStart, pEnd; 2908 PetscErrorCode ierr; 2909 2910 PetscFunctionBegin; 2911 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2912 if (start) {PetscValidPointer(start, 3); *start = 0;} 2913 if (end) {PetscValidPointer(end, 4); *end = 0;} 2914 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2915 if (pStart == pEnd) PetscFunctionReturn(0); 2916 if (stratumValue < 0) { 2917 if (start) *start = pStart; 2918 if (end) *end = pEnd; 2919 PetscFunctionReturn(0); 2920 } 2921 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2922 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2923 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2924 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2925 PetscFunctionReturn(0); 2926 } 2927 2928 #undef __FUNCT__ 2929 #define __FUNCT__ "DMPlexCreateSectionInitial" 2930 /* Set the number of dof on each point and separate by fields */ 2931 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2932 { 2933 PetscInt *pMax; 2934 PetscInt depth, pStart = 0, pEnd = 0; 2935 PetscInt Nf, p, d, dep, f; 2936 PetscBool *isFE; 2937 PetscErrorCode ierr; 2938 2939 PetscFunctionBegin; 2940 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2941 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2942 for (f = 0; f < numFields; ++f) { 2943 PetscObject obj; 2944 PetscClassId id; 2945 2946 isFE[f] = PETSC_FALSE; 2947 if (f >= Nf) continue; 2948 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2949 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2950 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2951 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2952 } 2953 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2954 if (numFields > 0) { 2955 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2956 if (numComp) { 2957 for (f = 0; f < numFields; ++f) { 2958 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2959 } 2960 } 2961 } 2962 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2963 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2964 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2965 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2966 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2967 for (dep = 0; dep <= depth; ++dep) { 2968 d = dim == depth ? dep : (!dep ? 0 : dim); 2969 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2970 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2971 for (p = pStart; p < pEnd; ++p) { 2972 PetscInt tot = 0; 2973 2974 for (f = 0; f < numFields; ++f) { 2975 if (isFE[f] && p >= pMax[dep]) continue; 2976 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2977 tot += numDof[f*(dim+1)+d]; 2978 } 2979 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2980 } 2981 } 2982 ierr = PetscFree(pMax);CHKERRQ(ierr); 2983 ierr = PetscFree(isFE);CHKERRQ(ierr); 2984 PetscFunctionReturn(0); 2985 } 2986 2987 #undef __FUNCT__ 2988 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2989 /* Set the number of dof on each point and separate by fields 2990 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2991 */ 2992 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2993 { 2994 PetscInt numFields; 2995 PetscInt bc; 2996 PetscSection aSec; 2997 PetscErrorCode ierr; 2998 2999 PetscFunctionBegin; 3000 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3001 for (bc = 0; bc < numBC; ++bc) { 3002 PetscInt field = 0; 3003 const PetscInt *comp; 3004 const PetscInt *idx; 3005 PetscInt Nc = -1, n, i; 3006 3007 if (numFields) field = bcField[bc]; 3008 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3009 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3010 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3011 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3012 for (i = 0; i < n; ++i) { 3013 const PetscInt p = idx[i]; 3014 PetscInt numConst; 3015 3016 if (numFields) { 3017 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 3018 } else { 3019 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 3020 } 3021 /* If Nc < 0, constrain every dof on the point */ 3022 if (Nc > 0) numConst = PetscMin(numConst, Nc); 3023 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 3024 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 3025 } 3026 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3027 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3028 } 3029 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3030 if (aSec) { 3031 PetscInt aStart, aEnd, a; 3032 3033 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3034 for (a = aStart; a < aEnd; a++) { 3035 PetscInt dof, f; 3036 3037 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3038 if (dof) { 3039 /* if there are point-to-point constraints, then all dofs are constrained */ 3040 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3041 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3042 for (f = 0; f < numFields; f++) { 3043 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3044 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3045 } 3046 } 3047 } 3048 } 3049 PetscFunctionReturn(0); 3050 } 3051 3052 #undef __FUNCT__ 3053 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 3054 /* Set the constrained field indices on each point 3055 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3056 */ 3057 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3058 { 3059 PetscSection aSec; 3060 PetscInt *indices; 3061 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 3062 PetscErrorCode ierr; 3063 3064 PetscFunctionBegin; 3065 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3066 if (!numFields) PetscFunctionReturn(0); 3067 /* Initialize all field indices to -1 */ 3068 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3069 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3070 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3071 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3072 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3073 /* Handle BC constraints */ 3074 for (bc = 0; bc < numBC; ++bc) { 3075 const PetscInt field = bcField[bc]; 3076 const PetscInt *comp, *idx; 3077 PetscInt Nc = -1, n, i; 3078 3079 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3080 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3081 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3082 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3083 for (i = 0; i < n; ++i) { 3084 const PetscInt p = idx[i]; 3085 const PetscInt *find; 3086 PetscInt fcdof, c; 3087 3088 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3089 if (Nc < 0) { 3090 for (d = 0; d < fcdof; ++d) indices[d] = d; 3091 } else { 3092 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3093 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3094 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 3095 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 3096 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 3097 } 3098 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3099 } 3100 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3101 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3102 } 3103 /* Handle anchors */ 3104 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3105 if (aSec) { 3106 PetscInt aStart, aEnd, a; 3107 3108 for (d = 0; d < maxDof; ++d) indices[d] = d; 3109 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3110 for (a = aStart; a < aEnd; a++) { 3111 PetscInt dof, fdof, f; 3112 3113 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3114 if (dof) { 3115 /* if there are point-to-point constraints, then all dofs are constrained */ 3116 for (f = 0; f < numFields; f++) { 3117 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 3118 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3119 } 3120 } 3121 } 3122 } 3123 ierr = PetscFree(indices);CHKERRQ(ierr); 3124 PetscFunctionReturn(0); 3125 } 3126 3127 #undef __FUNCT__ 3128 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 3129 /* Set the constrained indices on each point */ 3130 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3131 { 3132 PetscInt *indices; 3133 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3134 PetscErrorCode ierr; 3135 3136 PetscFunctionBegin; 3137 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3138 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3139 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3140 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3141 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3142 for (p = pStart; p < pEnd; ++p) { 3143 PetscInt cdof, d; 3144 3145 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3146 if (cdof) { 3147 if (numFields) { 3148 PetscInt numConst = 0, foff = 0; 3149 3150 for (f = 0; f < numFields; ++f) { 3151 const PetscInt *find; 3152 PetscInt fcdof, fdof; 3153 3154 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3155 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3156 /* Change constraint numbering from field component to local dof number */ 3157 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3158 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3159 numConst += fcdof; 3160 foff += fdof; 3161 } 3162 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 3163 } else { 3164 for (d = 0; d < cdof; ++d) indices[d] = d; 3165 } 3166 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3167 } 3168 } 3169 ierr = PetscFree(indices);CHKERRQ(ierr); 3170 PetscFunctionReturn(0); 3171 } 3172 3173 #undef __FUNCT__ 3174 #define __FUNCT__ "DMPlexCreateSection" 3175 /*@C 3176 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3177 3178 Not Collective 3179 3180 Input Parameters: 3181 + dm - The DMPlex object 3182 . dim - The spatial dimension of the problem 3183 . numFields - The number of fields in the problem 3184 . numComp - An array of size numFields that holds the number of components for each field 3185 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3186 . numBC - The number of boundary conditions 3187 . bcField - An array of size numBC giving the field number for each boundry condition 3188 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3189 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3190 - perm - Optional permutation of the chart, or NULL 3191 3192 Output Parameter: 3193 . section - The PetscSection object 3194 3195 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 3196 number of dof for field 0 on each edge. 3197 3198 The chart permutation is the same one set using PetscSectionSetPermutation() 3199 3200 Level: developer 3201 3202 Fortran Notes: 3203 A Fortran 90 version is available as DMPlexCreateSectionF90() 3204 3205 .keywords: mesh, elements 3206 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3207 @*/ 3208 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) 3209 { 3210 PetscSection aSec; 3211 PetscErrorCode ierr; 3212 3213 PetscFunctionBegin; 3214 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3215 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3216 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3217 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3218 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3219 if (numBC || aSec) { 3220 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3221 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3222 } 3223 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3224 PetscFunctionReturn(0); 3225 } 3226 3227 #undef __FUNCT__ 3228 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 3229 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3230 { 3231 PetscSection section; 3232 PetscErrorCode ierr; 3233 3234 PetscFunctionBegin; 3235 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3236 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3237 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3238 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3239 PetscFunctionReturn(0); 3240 } 3241 3242 #undef __FUNCT__ 3243 #define __FUNCT__ "DMPlexGetConeSection" 3244 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3245 { 3246 DM_Plex *mesh = (DM_Plex*) dm->data; 3247 3248 PetscFunctionBegin; 3249 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3250 if (section) *section = mesh->coneSection; 3251 PetscFunctionReturn(0); 3252 } 3253 3254 #undef __FUNCT__ 3255 #define __FUNCT__ "DMPlexGetSupportSection" 3256 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3257 { 3258 DM_Plex *mesh = (DM_Plex*) dm->data; 3259 3260 PetscFunctionBegin; 3261 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3262 if (section) *section = mesh->supportSection; 3263 PetscFunctionReturn(0); 3264 } 3265 3266 #undef __FUNCT__ 3267 #define __FUNCT__ "DMPlexGetCones" 3268 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3269 { 3270 DM_Plex *mesh = (DM_Plex*) dm->data; 3271 3272 PetscFunctionBegin; 3273 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3274 if (cones) *cones = mesh->cones; 3275 PetscFunctionReturn(0); 3276 } 3277 3278 #undef __FUNCT__ 3279 #define __FUNCT__ "DMPlexGetConeOrientations" 3280 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3281 { 3282 DM_Plex *mesh = (DM_Plex*) dm->data; 3283 3284 PetscFunctionBegin; 3285 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3286 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3287 PetscFunctionReturn(0); 3288 } 3289 3290 /******************************** FEM Support **********************************/ 3291 3292 #undef __FUNCT__ 3293 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3294 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3295 { 3296 PetscScalar *array, *vArray; 3297 const PetscInt *cone, *coneO; 3298 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3299 PetscErrorCode ierr; 3300 3301 PetscFunctionBeginHot; 3302 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3303 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3304 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3305 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3306 if (!values || !*values) { 3307 if ((point >= pStart) && (point < pEnd)) { 3308 PetscInt dof; 3309 3310 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3311 size += dof; 3312 } 3313 for (p = 0; p < numPoints; ++p) { 3314 const PetscInt cp = cone[p]; 3315 PetscInt dof; 3316 3317 if ((cp < pStart) || (cp >= pEnd)) continue; 3318 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3319 size += dof; 3320 } 3321 if (!values) { 3322 if (csize) *csize = size; 3323 PetscFunctionReturn(0); 3324 } 3325 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3326 } else { 3327 array = *values; 3328 } 3329 size = 0; 3330 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3331 if ((point >= pStart) && (point < pEnd)) { 3332 PetscInt dof, off, d; 3333 PetscScalar *varr; 3334 3335 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3336 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3337 varr = &vArray[off]; 3338 for (d = 0; d < dof; ++d, ++offset) { 3339 array[offset] = varr[d]; 3340 } 3341 size += dof; 3342 } 3343 for (p = 0; p < numPoints; ++p) { 3344 const PetscInt cp = cone[p]; 3345 PetscInt o = coneO[p]; 3346 PetscInt dof, off, d; 3347 PetscScalar *varr; 3348 3349 if ((cp < pStart) || (cp >= pEnd)) continue; 3350 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3351 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3352 varr = &vArray[off]; 3353 if (o >= 0) { 3354 for (d = 0; d < dof; ++d, ++offset) { 3355 array[offset] = varr[d]; 3356 } 3357 } else { 3358 for (d = dof-1; d >= 0; --d, ++offset) { 3359 array[offset] = varr[d]; 3360 } 3361 } 3362 size += dof; 3363 } 3364 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3365 if (!*values) { 3366 if (csize) *csize = size; 3367 *values = array; 3368 } else { 3369 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3370 *csize = size; 3371 } 3372 PetscFunctionReturn(0); 3373 } 3374 3375 #undef __FUNCT__ 3376 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3377 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3378 { 3379 PetscInt offset = 0, p; 3380 PetscErrorCode ierr; 3381 3382 PetscFunctionBeginHot; 3383 *size = 0; 3384 for (p = 0; p < numPoints*2; p += 2) { 3385 const PetscInt point = points[p]; 3386 const PetscInt o = points[p+1]; 3387 PetscInt dof, off, d; 3388 const PetscScalar *varr; 3389 3390 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3391 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3392 varr = &vArray[off]; 3393 if (o >= 0) { 3394 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3395 } else { 3396 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3397 } 3398 } 3399 *size = offset; 3400 PetscFunctionReturn(0); 3401 } 3402 3403 #undef __FUNCT__ 3404 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3405 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3406 { 3407 PetscInt offset = 0, f; 3408 PetscErrorCode ierr; 3409 3410 PetscFunctionBeginHot; 3411 *size = 0; 3412 for (f = 0; f < numFields; ++f) { 3413 PetscInt fcomp, p; 3414 3415 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3416 for (p = 0; p < numPoints*2; p += 2) { 3417 const PetscInt point = points[p]; 3418 const PetscInt o = points[p+1]; 3419 PetscInt fdof, foff, d, c; 3420 const PetscScalar *varr; 3421 3422 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3423 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3424 varr = &vArray[foff]; 3425 if (o >= 0) { 3426 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3427 } else { 3428 for (d = fdof/fcomp-1; d >= 0; --d) { 3429 for (c = 0; c < fcomp; ++c, ++offset) { 3430 array[offset] = varr[d*fcomp+c]; 3431 } 3432 } 3433 } 3434 } 3435 } 3436 *size = offset; 3437 PetscFunctionReturn(0); 3438 } 3439 3440 #undef __FUNCT__ 3441 #define __FUNCT__ "DMPlexVecGetClosure" 3442 /*@C 3443 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3444 3445 Not collective 3446 3447 Input Parameters: 3448 + dm - The DM 3449 . section - The section describing the layout in v, or NULL to use the default section 3450 . v - The local vector 3451 - point - The sieve point in the DM 3452 3453 Output Parameters: 3454 + csize - The number of values in the closure, or NULL 3455 - values - The array of values, which is a borrowed array and should not be freed 3456 3457 Fortran Notes: 3458 Since it returns an array, this routine is only available in Fortran 90, and you must 3459 include petsc.h90 in your code. 3460 3461 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3462 3463 Level: intermediate 3464 3465 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3466 @*/ 3467 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3468 { 3469 PetscSection clSection; 3470 IS clPoints; 3471 PetscScalar *array, *vArray; 3472 PetscInt *points = NULL; 3473 const PetscInt *clp; 3474 PetscInt depth, numFields, numPoints, size; 3475 PetscErrorCode ierr; 3476 3477 PetscFunctionBeginHot; 3478 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3479 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3480 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3481 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3482 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3483 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3484 if (depth == 1 && numFields < 2) { 3485 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3486 PetscFunctionReturn(0); 3487 } 3488 /* Get points */ 3489 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3490 if (!clPoints) { 3491 PetscInt pStart, pEnd, p, q; 3492 3493 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3494 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3495 /* Compress out points not in the section */ 3496 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3497 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3498 points[q*2] = points[p]; 3499 points[q*2+1] = points[p+1]; 3500 ++q; 3501 } 3502 } 3503 numPoints = q; 3504 } else { 3505 PetscInt dof, off; 3506 3507 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3508 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3509 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3510 numPoints = dof/2; 3511 points = (PetscInt *) &clp[off]; 3512 } 3513 /* Get array */ 3514 if (!values || !*values) { 3515 PetscInt asize = 0, dof, p; 3516 3517 for (p = 0; p < numPoints*2; p += 2) { 3518 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3519 asize += dof; 3520 } 3521 if (!values) { 3522 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3523 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3524 if (csize) *csize = asize; 3525 PetscFunctionReturn(0); 3526 } 3527 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3528 } else { 3529 array = *values; 3530 } 3531 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3532 /* Get values */ 3533 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3534 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3535 /* Cleanup points */ 3536 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3537 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3538 /* Cleanup array */ 3539 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3540 if (!*values) { 3541 if (csize) *csize = size; 3542 *values = array; 3543 } else { 3544 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3545 *csize = size; 3546 } 3547 PetscFunctionReturn(0); 3548 } 3549 3550 #undef __FUNCT__ 3551 #define __FUNCT__ "DMPlexVecRestoreClosure" 3552 /*@C 3553 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3554 3555 Not collective 3556 3557 Input Parameters: 3558 + dm - The DM 3559 . section - The section describing the layout in v, or NULL to use the default section 3560 . v - The local vector 3561 . point - The sieve point in the DM 3562 . csize - The number of values in the closure, or NULL 3563 - values - The array of values, which is a borrowed array and should not be freed 3564 3565 Fortran Notes: 3566 Since it returns an array, this routine is only available in Fortran 90, and you must 3567 include petsc.h90 in your code. 3568 3569 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3570 3571 Level: intermediate 3572 3573 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3574 @*/ 3575 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3576 { 3577 PetscInt size = 0; 3578 PetscErrorCode ierr; 3579 3580 PetscFunctionBegin; 3581 /* Should work without recalculating size */ 3582 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3583 PetscFunctionReturn(0); 3584 } 3585 3586 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3587 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3588 3589 #undef __FUNCT__ 3590 #define __FUNCT__ "updatePoint_private" 3591 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[]) 3592 { 3593 PetscInt cdof; /* The number of constraints on this point */ 3594 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3595 PetscScalar *a; 3596 PetscInt off, cind = 0, k; 3597 PetscErrorCode ierr; 3598 3599 PetscFunctionBegin; 3600 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3601 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3602 a = &array[off]; 3603 if (!cdof || setBC) { 3604 if (orientation >= 0) { 3605 for (k = 0; k < dof; ++k) { 3606 fuse(&a[k], values[k]); 3607 } 3608 } else { 3609 for (k = 0; k < dof; ++k) { 3610 fuse(&a[k], values[dof-k-1]); 3611 } 3612 } 3613 } else { 3614 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3615 if (orientation >= 0) { 3616 for (k = 0; k < dof; ++k) { 3617 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3618 fuse(&a[k], values[k]); 3619 } 3620 } else { 3621 for (k = 0; k < dof; ++k) { 3622 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3623 fuse(&a[k], values[dof-k-1]); 3624 } 3625 } 3626 } 3627 PetscFunctionReturn(0); 3628 } 3629 3630 #undef __FUNCT__ 3631 #define __FUNCT__ "updatePointBC_private" 3632 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3633 { 3634 PetscInt cdof; /* The number of constraints on this point */ 3635 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3636 PetscScalar *a; 3637 PetscInt off, cind = 0, k; 3638 PetscErrorCode ierr; 3639 3640 PetscFunctionBegin; 3641 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3642 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3643 a = &array[off]; 3644 if (cdof) { 3645 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3646 if (orientation >= 0) { 3647 for (k = 0; k < dof; ++k) { 3648 if ((cind < cdof) && (k == cdofs[cind])) { 3649 fuse(&a[k], values[k]); 3650 ++cind; 3651 } 3652 } 3653 } else { 3654 for (k = 0; k < dof; ++k) { 3655 if ((cind < cdof) && (k == cdofs[cind])) { 3656 fuse(&a[k], values[dof-k-1]); 3657 ++cind; 3658 } 3659 } 3660 } 3661 } 3662 PetscFunctionReturn(0); 3663 } 3664 3665 #undef __FUNCT__ 3666 #define __FUNCT__ "updatePointFields_private" 3667 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[]) 3668 { 3669 PetscScalar *a; 3670 PetscInt fdof, foff, fcdof, foffset = *offset; 3671 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3672 PetscInt cind = 0, k, c; 3673 PetscErrorCode ierr; 3674 3675 PetscFunctionBegin; 3676 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3677 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3678 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3679 a = &array[foff]; 3680 if (!fcdof || setBC) { 3681 if (o >= 0) { 3682 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3683 } else { 3684 for (k = fdof/fcomp-1; k >= 0; --k) { 3685 for (c = 0; c < fcomp; ++c) { 3686 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3687 } 3688 } 3689 } 3690 } else { 3691 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3692 if (o >= 0) { 3693 for (k = 0; k < fdof; ++k) { 3694 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3695 fuse(&a[k], values[foffset+k]); 3696 } 3697 } else { 3698 for (k = fdof/fcomp-1; k >= 0; --k) { 3699 for (c = 0; c < fcomp; ++c) { 3700 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3701 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3702 } 3703 } 3704 } 3705 } 3706 *offset += fdof; 3707 PetscFunctionReturn(0); 3708 } 3709 3710 #undef __FUNCT__ 3711 #define __FUNCT__ "updatePointFieldsBC_private" 3712 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[]) 3713 { 3714 PetscScalar *a; 3715 PetscInt fdof, foff, fcdof, foffset = *offset; 3716 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3717 PetscInt cind = 0, k, c; 3718 PetscErrorCode ierr; 3719 3720 PetscFunctionBegin; 3721 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3722 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3723 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3724 a = &array[foff]; 3725 if (fcdof) { 3726 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3727 if (o >= 0) { 3728 for (k = 0; k < fdof; ++k) { 3729 if ((cind < fcdof) && (k == fcdofs[cind])) { 3730 fuse(&a[k], values[foffset+k]); 3731 ++cind; 3732 } 3733 } 3734 } else { 3735 for (k = fdof/fcomp-1; k >= 0; --k) { 3736 for (c = 0; c < fcomp; ++c) { 3737 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3738 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3739 ++cind; 3740 } 3741 } 3742 } 3743 } 3744 } 3745 *offset += fdof; 3746 PetscFunctionReturn(0); 3747 } 3748 3749 #undef __FUNCT__ 3750 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3751 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3752 { 3753 PetscScalar *array; 3754 const PetscInt *cone, *coneO; 3755 PetscInt pStart, pEnd, p, numPoints, off, dof; 3756 PetscErrorCode ierr; 3757 3758 PetscFunctionBeginHot; 3759 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3760 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3761 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3762 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3763 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3764 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3765 const PetscInt cp = !p ? point : cone[p-1]; 3766 const PetscInt o = !p ? 0 : coneO[p-1]; 3767 3768 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3769 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3770 /* ADD_VALUES */ 3771 { 3772 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3773 PetscScalar *a; 3774 PetscInt cdof, coff, cind = 0, k; 3775 3776 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3777 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3778 a = &array[coff]; 3779 if (!cdof) { 3780 if (o >= 0) { 3781 for (k = 0; k < dof; ++k) { 3782 a[k] += values[off+k]; 3783 } 3784 } else { 3785 for (k = 0; k < dof; ++k) { 3786 a[k] += values[off+dof-k-1]; 3787 } 3788 } 3789 } else { 3790 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3791 if (o >= 0) { 3792 for (k = 0; k < dof; ++k) { 3793 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3794 a[k] += values[off+k]; 3795 } 3796 } else { 3797 for (k = 0; k < dof; ++k) { 3798 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3799 a[k] += values[off+dof-k-1]; 3800 } 3801 } 3802 } 3803 } 3804 } 3805 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3806 PetscFunctionReturn(0); 3807 } 3808 3809 #undef __FUNCT__ 3810 #define __FUNCT__ "DMPlexVecSetClosure" 3811 /*@C 3812 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3813 3814 Not collective 3815 3816 Input Parameters: 3817 + dm - The DM 3818 . section - The section describing the layout in v, or NULL to use the default section 3819 . v - The local vector 3820 . point - The sieve point in the DM 3821 . values - The array of values 3822 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3823 3824 Fortran Notes: 3825 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3826 3827 Level: intermediate 3828 3829 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3830 @*/ 3831 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3832 { 3833 PetscSection clSection; 3834 IS clPoints; 3835 PetscScalar *array; 3836 PetscInt *points = NULL; 3837 const PetscInt *clp; 3838 PetscInt depth, numFields, numPoints, p; 3839 PetscErrorCode ierr; 3840 3841 PetscFunctionBeginHot; 3842 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3843 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3844 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3845 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3846 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3847 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3848 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3849 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3850 PetscFunctionReturn(0); 3851 } 3852 /* Get points */ 3853 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3854 if (!clPoints) { 3855 PetscInt pStart, pEnd, q; 3856 3857 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3858 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3859 /* Compress out points not in the section */ 3860 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3861 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3862 points[q*2] = points[p]; 3863 points[q*2+1] = points[p+1]; 3864 ++q; 3865 } 3866 } 3867 numPoints = q; 3868 } else { 3869 PetscInt dof, off; 3870 3871 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3872 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3873 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3874 numPoints = dof/2; 3875 points = (PetscInt *) &clp[off]; 3876 } 3877 /* Get array */ 3878 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3879 /* Get values */ 3880 if (numFields > 0) { 3881 PetscInt offset = 0, fcomp, f; 3882 for (f = 0; f < numFields; ++f) { 3883 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3884 switch (mode) { 3885 case INSERT_VALUES: 3886 for (p = 0; p < numPoints*2; p += 2) { 3887 const PetscInt point = points[p]; 3888 const PetscInt o = points[p+1]; 3889 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3890 } break; 3891 case INSERT_ALL_VALUES: 3892 for (p = 0; p < numPoints*2; p += 2) { 3893 const PetscInt point = points[p]; 3894 const PetscInt o = points[p+1]; 3895 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3896 } break; 3897 case INSERT_BC_VALUES: 3898 for (p = 0; p < numPoints*2; p += 2) { 3899 const PetscInt point = points[p]; 3900 const PetscInt o = points[p+1]; 3901 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3902 } break; 3903 case ADD_VALUES: 3904 for (p = 0; p < numPoints*2; p += 2) { 3905 const PetscInt point = points[p]; 3906 const PetscInt o = points[p+1]; 3907 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3908 } break; 3909 case ADD_ALL_VALUES: 3910 for (p = 0; p < numPoints*2; p += 2) { 3911 const PetscInt point = points[p]; 3912 const PetscInt o = points[p+1]; 3913 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3914 } break; 3915 default: 3916 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3917 } 3918 } 3919 } else { 3920 PetscInt dof, off; 3921 3922 switch (mode) { 3923 case INSERT_VALUES: 3924 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3925 PetscInt o = points[p+1]; 3926 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3927 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3928 } break; 3929 case INSERT_ALL_VALUES: 3930 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3931 PetscInt o = points[p+1]; 3932 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3933 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3934 } break; 3935 case INSERT_BC_VALUES: 3936 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3937 PetscInt o = points[p+1]; 3938 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3939 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3940 } break; 3941 case ADD_VALUES: 3942 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3943 PetscInt o = points[p+1]; 3944 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3945 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3946 } break; 3947 case ADD_ALL_VALUES: 3948 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3949 PetscInt o = points[p+1]; 3950 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3951 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3952 } break; 3953 default: 3954 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3955 } 3956 } 3957 /* Cleanup points */ 3958 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3959 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3960 /* Cleanup array */ 3961 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3962 PetscFunctionReturn(0); 3963 } 3964 3965 #undef __FUNCT__ 3966 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3967 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3968 { 3969 PetscSection clSection; 3970 IS clPoints; 3971 PetscScalar *array; 3972 PetscInt *points = NULL; 3973 const PetscInt *clp; 3974 PetscInt numFields, numPoints, p; 3975 PetscInt offset = 0, fcomp, f; 3976 PetscErrorCode ierr; 3977 3978 PetscFunctionBeginHot; 3979 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3980 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3981 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3982 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3983 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3984 /* Get points */ 3985 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3986 if (!clPoints) { 3987 PetscInt pStart, pEnd, q; 3988 3989 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3990 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3991 /* Compress out points not in the section */ 3992 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3993 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3994 points[q*2] = points[p]; 3995 points[q*2+1] = points[p+1]; 3996 ++q; 3997 } 3998 } 3999 numPoints = q; 4000 } else { 4001 PetscInt dof, off; 4002 4003 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4004 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4005 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4006 numPoints = dof/2; 4007 points = (PetscInt *) &clp[off]; 4008 } 4009 /* Get array */ 4010 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4011 /* Get values */ 4012 for (f = 0; f < numFields; ++f) { 4013 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4014 if (!fieldActive[f]) { 4015 for (p = 0; p < numPoints*2; p += 2) { 4016 PetscInt fdof; 4017 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4018 offset += fdof; 4019 } 4020 continue; 4021 } 4022 switch (mode) { 4023 case INSERT_VALUES: 4024 for (p = 0; p < numPoints*2; p += 2) { 4025 const PetscInt point = points[p]; 4026 const PetscInt o = points[p+1]; 4027 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 4028 } break; 4029 case INSERT_ALL_VALUES: 4030 for (p = 0; p < numPoints*2; p += 2) { 4031 const PetscInt point = points[p]; 4032 const PetscInt o = points[p+1]; 4033 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 4034 } break; 4035 case INSERT_BC_VALUES: 4036 for (p = 0; p < numPoints*2; p += 2) { 4037 const PetscInt point = points[p]; 4038 const PetscInt o = points[p+1]; 4039 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 4040 } break; 4041 case ADD_VALUES: 4042 for (p = 0; p < numPoints*2; p += 2) { 4043 const PetscInt point = points[p]; 4044 const PetscInt o = points[p+1]; 4045 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 4046 } break; 4047 case ADD_ALL_VALUES: 4048 for (p = 0; p < numPoints*2; p += 2) { 4049 const PetscInt point = points[p]; 4050 const PetscInt o = points[p+1]; 4051 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 4052 } break; 4053 default: 4054 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4055 } 4056 } 4057 /* Cleanup points */ 4058 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4059 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4060 /* Cleanup array */ 4061 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4062 PetscFunctionReturn(0); 4063 } 4064 4065 #undef __FUNCT__ 4066 #define __FUNCT__ "DMPlexPrintMatSetValues" 4067 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4068 { 4069 PetscMPIInt rank; 4070 PetscInt i, j; 4071 PetscErrorCode ierr; 4072 4073 PetscFunctionBegin; 4074 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4075 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4076 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4077 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4078 numCIndices = numCIndices ? numCIndices : numRIndices; 4079 for (i = 0; i < numRIndices; i++) { 4080 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4081 for (j = 0; j < numCIndices; j++) { 4082 #if defined(PETSC_USE_COMPLEX) 4083 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4084 #else 4085 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4086 #endif 4087 } 4088 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4089 } 4090 PetscFunctionReturn(0); 4091 } 4092 4093 #undef __FUNCT__ 4094 #define __FUNCT__ "indicesPoint_private" 4095 /* . off - The global offset of this point */ 4096 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4097 { 4098 PetscInt dof; /* The number of unknowns on this point */ 4099 PetscInt cdof; /* The number of constraints on this point */ 4100 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4101 PetscInt cind = 0, k; 4102 PetscErrorCode ierr; 4103 4104 PetscFunctionBegin; 4105 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4106 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4107 if (!cdof || setBC) { 4108 if (orientation >= 0) { 4109 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4110 } else { 4111 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4112 } 4113 } else { 4114 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4115 if (orientation >= 0) { 4116 for (k = 0; k < dof; ++k) { 4117 if ((cind < cdof) && (k == cdofs[cind])) { 4118 /* Insert check for returning constrained indices */ 4119 indices[*loff+k] = -(off+k+1); 4120 ++cind; 4121 } else { 4122 indices[*loff+k] = off+k-cind; 4123 } 4124 } 4125 } else { 4126 for (k = 0; k < dof; ++k) { 4127 if ((cind < cdof) && (k == cdofs[cind])) { 4128 /* Insert check for returning constrained indices */ 4129 indices[*loff+dof-k-1] = -(off+k+1); 4130 ++cind; 4131 } else { 4132 indices[*loff+dof-k-1] = off+k-cind; 4133 } 4134 } 4135 } 4136 } 4137 *loff += dof; 4138 PetscFunctionReturn(0); 4139 } 4140 4141 #undef __FUNCT__ 4142 #define __FUNCT__ "indicesPointFields_private" 4143 /* . off - The global offset of this point */ 4144 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4145 { 4146 PetscInt numFields, foff, f; 4147 PetscErrorCode ierr; 4148 4149 PetscFunctionBegin; 4150 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4151 for (f = 0, foff = 0; f < numFields; ++f) { 4152 PetscInt fdof, fcomp, cfdof; 4153 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4154 PetscInt cind = 0, k, c; 4155 4156 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4157 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4158 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4159 if (!cfdof || setBC) { 4160 if (orientation >= 0) { 4161 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4162 } else { 4163 for (k = fdof/fcomp-1; k >= 0; --k) { 4164 for (c = 0; c < fcomp; ++c) { 4165 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4166 } 4167 } 4168 } 4169 } else { 4170 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4171 if (orientation >= 0) { 4172 for (k = 0; k < fdof; ++k) { 4173 if ((cind < cfdof) && (k == fcdofs[cind])) { 4174 indices[foffs[f]+k] = -(off+foff+k+1); 4175 ++cind; 4176 } else { 4177 indices[foffs[f]+k] = off+foff+k-cind; 4178 } 4179 } 4180 } else { 4181 for (k = fdof/fcomp-1; k >= 0; --k) { 4182 for (c = 0; c < fcomp; ++c) { 4183 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4184 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4185 ++cind; 4186 } else { 4187 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4188 } 4189 } 4190 } 4191 } 4192 } 4193 foff += fdof - cfdof; 4194 foffs[f] += fdof; 4195 } 4196 PetscFunctionReturn(0); 4197 } 4198 4199 #undef __FUNCT__ 4200 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4201 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[]) 4202 { 4203 Mat cMat; 4204 PetscSection aSec, cSec; 4205 IS aIS; 4206 PetscInt aStart = -1, aEnd = -1; 4207 const PetscInt *anchors; 4208 PetscInt numFields, f, p, q, newP = 0; 4209 PetscInt newNumPoints = 0, newNumIndices = 0; 4210 PetscInt *newPoints, *indices, *newIndices; 4211 PetscInt maxAnchor, maxDof; 4212 PetscInt newOffsets[32]; 4213 PetscInt *pointMatOffsets[32]; 4214 PetscInt *newPointOffsets[32]; 4215 PetscScalar *pointMat[32]; 4216 PetscScalar *newValues,*tmpValues; 4217 PetscBool anyConstrained = PETSC_FALSE; 4218 PetscErrorCode ierr; 4219 4220 PetscFunctionBegin; 4221 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4222 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4223 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4224 4225 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4226 /* if there are point-to-point constraints */ 4227 if (aSec) { 4228 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4229 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4230 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4231 /* figure out how many points are going to be in the new element matrix 4232 * (we allow double counting, because it's all just going to be summed 4233 * into the global matrix anyway) */ 4234 for (p = 0; p < 2*numPoints; p+=2) { 4235 PetscInt b = points[p]; 4236 PetscInt bDof = 0; 4237 4238 if (b >= aStart && b < aEnd) { 4239 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4240 } 4241 if (bDof) { 4242 /* this point is constrained */ 4243 /* it is going to be replaced by its anchors */ 4244 PetscInt bOff, q; 4245 4246 anyConstrained = PETSC_TRUE; 4247 newNumPoints += bDof; 4248 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4249 for (q = 0; q < bDof; q++) { 4250 PetscInt a = anchors[bOff + q]; 4251 PetscInt aDof; 4252 4253 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4254 newNumIndices += aDof; 4255 for (f = 0; f < numFields; ++f) { 4256 PetscInt fDof; 4257 4258 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4259 newOffsets[f+1] += fDof; 4260 } 4261 } 4262 } 4263 else { 4264 /* this point is not constrained */ 4265 newNumPoints++; 4266 ierr = PetscSectionGetDof(section,b,&bDof);CHKERRQ(ierr); 4267 newNumIndices += bDof; 4268 for (f = 0; f < numFields; ++f) { 4269 PetscInt fDof; 4270 4271 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4272 newOffsets[f+1] += fDof; 4273 } 4274 } 4275 } 4276 } 4277 if (!anyConstrained) { 4278 if (outNumPoints) *outNumPoints = 0; 4279 if (outNumIndices) *outNumIndices = 0; 4280 if (outPoints) *outPoints = NULL; 4281 if (outValues) *outValues = NULL; 4282 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4283 PetscFunctionReturn(0); 4284 } 4285 4286 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4287 4288 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4289 4290 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4291 4292 /* output arrays */ 4293 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4294 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4295 4296 /* workspaces */ 4297 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4298 if (numFields) { 4299 for (f = 0; f < numFields; f++) { 4300 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4301 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4302 } 4303 } 4304 else { 4305 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4306 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4307 } 4308 4309 /* get workspaces for the point-to-point matrices */ 4310 if (numFields) { 4311 for (p = 0; p < numPoints; p++) { 4312 PetscInt b = points[2*p]; 4313 PetscInt bDof = 0; 4314 4315 if (b >= aStart && b < aEnd) { 4316 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4317 } 4318 if (bDof) { 4319 for (f = 0; f < numFields; f++) { 4320 PetscInt fDof, q, bOff, allFDof = 0; 4321 4322 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4323 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4324 for (q = 0; q < bDof; q++) { 4325 PetscInt a = anchors[bOff + q]; 4326 PetscInt aFDof; 4327 4328 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4329 allFDof += aFDof; 4330 } 4331 newPointOffsets[f][p+1] = allFDof; 4332 pointMatOffsets[f][p+1] = fDof * allFDof; 4333 } 4334 } 4335 else { 4336 for (f = 0; f < numFields; f++) { 4337 PetscInt fDof; 4338 4339 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4340 newPointOffsets[f][p+1] = fDof; 4341 pointMatOffsets[f][p+1] = 0; 4342 } 4343 } 4344 } 4345 for (f = 0; f < numFields; f++) { 4346 newPointOffsets[f][0] = 0; 4347 pointMatOffsets[f][0] = 0; 4348 for (p = 0; p < numPoints; p++) { 4349 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4350 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4351 } 4352 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4353 } 4354 } 4355 else { 4356 for (p = 0; p < numPoints; p++) { 4357 PetscInt b = points[2*p]; 4358 PetscInt bDof = 0; 4359 4360 if (b >= aStart && b < aEnd) { 4361 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4362 } 4363 if (bDof) { 4364 PetscInt dof, bOff, q, allDof = 0; 4365 4366 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4367 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4368 for (q = 0; q < bDof; q++) { 4369 PetscInt a = anchors[bOff + q], aDof; 4370 4371 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4372 allDof += aDof; 4373 } 4374 newPointOffsets[0][p+1] = allDof; 4375 pointMatOffsets[0][p+1] = dof * allDof; 4376 } 4377 else { 4378 PetscInt dof; 4379 4380 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4381 newPointOffsets[0][p+1] = dof; 4382 pointMatOffsets[0][p+1] = 0; 4383 } 4384 } 4385 newPointOffsets[0][0] = 0; 4386 pointMatOffsets[0][0] = 0; 4387 for (p = 0; p < numPoints; p++) { 4388 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4389 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4390 } 4391 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4392 } 4393 4394 /* get the point-to-point matrices; construct newPoints */ 4395 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4396 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4397 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4398 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4399 if (numFields) { 4400 for (p = 0, newP = 0; p < numPoints; p++) { 4401 PetscInt b = points[2*p]; 4402 PetscInt o = points[2*p+1]; 4403 PetscInt bDof = 0; 4404 4405 if (b >= aStart && b < aEnd) { 4406 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4407 } 4408 if (bDof) { 4409 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4410 4411 fStart[0] = 0; 4412 fEnd[0] = 0; 4413 for (f = 0; f < numFields; f++) { 4414 PetscInt fDof; 4415 4416 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4417 fStart[f+1] = fStart[f] + fDof; 4418 fEnd[f+1] = fStart[f+1]; 4419 } 4420 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4421 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4422 4423 fAnchorStart[0] = 0; 4424 fAnchorEnd[0] = 0; 4425 for (f = 0; f < numFields; f++) { 4426 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4427 4428 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4429 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4430 } 4431 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4432 for (q = 0; q < bDof; q++) { 4433 PetscInt a = anchors[bOff + q], aOff; 4434 4435 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4436 newPoints[2*(newP + q)] = a; 4437 newPoints[2*(newP + q) + 1] = 0; 4438 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4439 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4440 } 4441 newP += bDof; 4442 4443 /* get the point-to-point submatrix */ 4444 for (f = 0; f < numFields; f++) { 4445 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4446 } 4447 } 4448 else { 4449 newPoints[2 * newP] = b; 4450 newPoints[2 * newP + 1] = o; 4451 newP++; 4452 } 4453 } 4454 } else { 4455 for (p = 0; p < numPoints; p++) { 4456 PetscInt b = points[2*p]; 4457 PetscInt o = points[2*p+1]; 4458 PetscInt bDof = 0; 4459 4460 if (b >= aStart && b < aEnd) { 4461 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4462 } 4463 if (bDof) { 4464 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4465 4466 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4467 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4468 4469 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4470 for (q = 0; q < bDof; q++) { 4471 PetscInt a = anchors[bOff + q], aOff; 4472 4473 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4474 4475 newPoints[2*(newP + q)] = a; 4476 newPoints[2*(newP + q) + 1] = 0; 4477 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4478 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4479 } 4480 newP += bDof; 4481 4482 /* get the point-to-point submatrix */ 4483 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4484 } 4485 else { 4486 newPoints[2 * newP] = b; 4487 newPoints[2 * newP + 1] = o; 4488 newP++; 4489 } 4490 } 4491 } 4492 4493 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4494 /* multiply constraints on the right */ 4495 if (numFields) { 4496 for (f = 0; f < numFields; f++) { 4497 PetscInt oldOff = offsets[f]; 4498 4499 for (p = 0; p < numPoints; p++) { 4500 PetscInt cStart = newPointOffsets[f][p]; 4501 PetscInt b = points[2 * p]; 4502 PetscInt c, r, k; 4503 PetscInt dof; 4504 4505 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4506 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4507 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4508 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4509 4510 for (r = 0; r < numIndices; r++) { 4511 for (c = 0; c < nCols; c++) { 4512 for (k = 0; k < dof; k++) { 4513 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4514 } 4515 } 4516 } 4517 } 4518 else { 4519 /* copy this column as is */ 4520 for (r = 0; r < numIndices; r++) { 4521 for (c = 0; c < dof; c++) { 4522 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4523 } 4524 } 4525 } 4526 oldOff += dof; 4527 } 4528 } 4529 } 4530 else { 4531 PetscInt oldOff = 0; 4532 for (p = 0; p < numPoints; p++) { 4533 PetscInt cStart = newPointOffsets[0][p]; 4534 PetscInt b = points[2 * p]; 4535 PetscInt c, r, k; 4536 PetscInt dof; 4537 4538 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4539 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4540 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4541 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4542 4543 for (r = 0; r < numIndices; r++) { 4544 for (c = 0; c < nCols; c++) { 4545 for (k = 0; k < dof; k++) { 4546 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4547 } 4548 } 4549 } 4550 } 4551 else { 4552 /* copy this column as is */ 4553 for (r = 0; r < numIndices; r++) { 4554 for (c = 0; c < dof; c++) { 4555 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4556 } 4557 } 4558 } 4559 oldOff += dof; 4560 } 4561 } 4562 4563 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4564 /* multiply constraints transpose on the left */ 4565 if (numFields) { 4566 for (f = 0; f < numFields; f++) { 4567 PetscInt oldOff = offsets[f]; 4568 4569 for (p = 0; p < numPoints; p++) { 4570 PetscInt rStart = newPointOffsets[f][p]; 4571 PetscInt b = points[2 * p]; 4572 PetscInt c, r, k; 4573 PetscInt dof; 4574 4575 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4576 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4577 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4578 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4579 4580 for (r = 0; r < nRows; r++) { 4581 for (c = 0; c < newNumIndices; c++) { 4582 for (k = 0; k < dof; k++) { 4583 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4584 } 4585 } 4586 } 4587 } 4588 else { 4589 /* copy this row as is */ 4590 for (r = 0; r < dof; r++) { 4591 for (c = 0; c < newNumIndices; c++) { 4592 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4593 } 4594 } 4595 } 4596 oldOff += dof; 4597 } 4598 } 4599 } 4600 else { 4601 PetscInt oldOff = 0; 4602 4603 for (p = 0; p < numPoints; p++) { 4604 PetscInt rStart = newPointOffsets[0][p]; 4605 PetscInt b = points[2 * p]; 4606 PetscInt c, r, k; 4607 PetscInt dof; 4608 4609 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4610 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4611 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4612 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4613 4614 for (r = 0; r < nRows; r++) { 4615 for (c = 0; c < newNumIndices; c++) { 4616 for (k = 0; k < dof; k++) { 4617 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4618 } 4619 } 4620 } 4621 } 4622 else { 4623 /* copy this row as is */ 4624 for (r = 0; r < dof; c++) { 4625 for (c = 0; c < newNumIndices; c++) { 4626 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4627 } 4628 } 4629 } 4630 oldOff += dof; 4631 } 4632 } 4633 4634 /* clean up */ 4635 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4636 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4637 if (numFields) { 4638 for (f = 0; f < numFields; f++) { 4639 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4640 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4641 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4642 } 4643 } 4644 else { 4645 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4646 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4647 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4648 } 4649 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4650 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4651 4652 /* output */ 4653 *outNumPoints = newNumPoints; 4654 *outNumIndices = newNumIndices; 4655 *outPoints = newPoints; 4656 *outValues = newValues; 4657 for (f = 0; f < numFields; f++) { 4658 offsets[f] = newOffsets[f]; 4659 } 4660 PetscFunctionReturn(0); 4661 } 4662 4663 #undef __FUNCT__ 4664 #define __FUNCT__ "DMPlexGetClosureIndices" 4665 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4666 { 4667 PetscSection clSection; 4668 IS clPoints; 4669 const PetscInt *clp; 4670 PetscInt *points = NULL, *pointsNew; 4671 PetscInt numPoints, numPointsNew; 4672 PetscInt offsets[32]; 4673 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4674 PetscErrorCode ierr; 4675 4676 PetscFunctionBegin; 4677 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4678 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4679 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4680 if (numIndices) PetscValidPointer(numIndices, 4); 4681 PetscValidPointer(indices, 5); 4682 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4683 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4684 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4685 /* Get points in closure */ 4686 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4687 if (!clPoints) { 4688 PetscInt pStart, pEnd, q; 4689 4690 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4691 /* Compress out points not in the section */ 4692 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4693 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4694 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4695 points[q*2] = points[p]; 4696 points[q*2+1] = points[p+1]; 4697 ++q; 4698 } 4699 } 4700 numPoints = q; 4701 } else { 4702 PetscInt dof, off; 4703 4704 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4705 numPoints = dof/2; 4706 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4707 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4708 points = (PetscInt *) &clp[off]; 4709 } 4710 /* Get number of indices and indices per field */ 4711 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4712 PetscInt dof, fdof; 4713 4714 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4715 for (f = 0; f < Nf; ++f) { 4716 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4717 offsets[f+1] += fdof; 4718 } 4719 Nind += dof; 4720 } 4721 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4722 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4723 /* Correct for hanging node constraints */ 4724 { 4725 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets);CHKERRQ(ierr); 4726 if (numPointsNew) { 4727 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4728 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4729 numPoints = numPointsNew; 4730 Nind = NindNew; 4731 points = pointsNew; 4732 } 4733 } 4734 /* Calculate indices */ 4735 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 4736 if (Nf) { 4737 for (p = 0; p < numPoints*2; p += 2) { 4738 PetscInt o = points[p+1]; 4739 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4740 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 4741 } 4742 } else { 4743 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4744 PetscInt o = points[p+1]; 4745 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4746 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 4747 } 4748 } 4749 /* Cleanup points */ 4750 if (numPointsNew) { 4751 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 4752 } else { 4753 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4754 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4755 } 4756 if (numIndices) *numIndices = Nind; 4757 PetscFunctionReturn(0); 4758 } 4759 4760 #undef __FUNCT__ 4761 #define __FUNCT__ "DMPlexRestoreClosureIndices" 4762 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4763 { 4764 PetscErrorCode ierr; 4765 4766 PetscFunctionBegin; 4767 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4768 PetscValidPointer(indices, 5); 4769 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 4770 PetscFunctionReturn(0); 4771 } 4772 4773 #undef __FUNCT__ 4774 #define __FUNCT__ "DMPlexMatSetClosure" 4775 /*@C 4776 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4777 4778 Not collective 4779 4780 Input Parameters: 4781 + dm - The DM 4782 . section - The section describing the layout in v, or NULL to use the default section 4783 . globalSection - The section describing the layout in v, or NULL to use the default global section 4784 . A - The matrix 4785 . point - The sieve point in the DM 4786 . values - The array of values 4787 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4788 4789 Fortran Notes: 4790 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4791 4792 Level: intermediate 4793 4794 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4795 @*/ 4796 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4797 { 4798 DM_Plex *mesh = (DM_Plex*) dm->data; 4799 PetscSection clSection; 4800 IS clPoints; 4801 PetscInt *points = NULL, *newPoints; 4802 const PetscInt *clp; 4803 PetscInt *indices; 4804 PetscInt offsets[32]; 4805 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4806 PetscScalar *newValues; 4807 PetscErrorCode ierr; 4808 4809 PetscFunctionBegin; 4810 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4811 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4812 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4813 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4814 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4815 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4816 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4817 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4818 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4819 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4820 if (!clPoints) { 4821 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4822 /* Compress out points not in the section */ 4823 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4824 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4825 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4826 points[q*2] = points[p]; 4827 points[q*2+1] = points[p+1]; 4828 ++q; 4829 } 4830 } 4831 numPoints = q; 4832 } else { 4833 PetscInt dof, off; 4834 4835 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4836 numPoints = dof/2; 4837 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4838 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4839 points = (PetscInt *) &clp[off]; 4840 } 4841 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4842 PetscInt fdof; 4843 4844 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4845 for (f = 0; f < numFields; ++f) { 4846 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4847 offsets[f+1] += fdof; 4848 } 4849 numIndices += dof; 4850 } 4851 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4852 4853 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4854 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets);CHKERRQ(ierr); 4855 if (newNumPoints) { 4856 if (!clPoints) { 4857 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4858 } else { 4859 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4860 } 4861 numPoints = newNumPoints; 4862 numIndices = newNumIndices; 4863 points = newPoints; 4864 values = newValues; 4865 } 4866 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4867 if (numFields) { 4868 for (p = 0; p < numPoints*2; p += 2) { 4869 PetscInt o = points[p+1]; 4870 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4871 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4872 } 4873 } else { 4874 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4875 PetscInt o = points[p+1]; 4876 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4877 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4878 } 4879 } 4880 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4881 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4882 if (mesh->printFEM > 1) { 4883 PetscInt i; 4884 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4885 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4886 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4887 } 4888 if (ierr) { 4889 PetscMPIInt rank; 4890 PetscErrorCode ierr2; 4891 4892 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4893 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4894 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4895 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4896 CHKERRQ(ierr); 4897 } 4898 if (newNumPoints) { 4899 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4900 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4901 } 4902 else { 4903 if (!clPoints) { 4904 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4905 } else { 4906 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4907 } 4908 } 4909 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4910 PetscFunctionReturn(0); 4911 } 4912 4913 #undef __FUNCT__ 4914 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4915 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4916 { 4917 DM_Plex *mesh = (DM_Plex*) dmf->data; 4918 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4919 PetscInt *cpoints = NULL; 4920 PetscInt *findices, *cindices; 4921 PetscInt foffsets[32], coffsets[32]; 4922 CellRefiner cellRefiner; 4923 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4924 PetscErrorCode ierr; 4925 4926 PetscFunctionBegin; 4927 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4928 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4929 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4930 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4931 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4932 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4933 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4934 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4935 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4936 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4937 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4938 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4939 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4940 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4941 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4942 /* Column indices */ 4943 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4944 maxFPoints = numCPoints; 4945 /* Compress out points not in the section */ 4946 /* TODO: Squeeze out points with 0 dof as well */ 4947 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4948 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4949 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4950 cpoints[q*2] = cpoints[p]; 4951 cpoints[q*2+1] = cpoints[p+1]; 4952 ++q; 4953 } 4954 } 4955 numCPoints = q; 4956 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4957 PetscInt fdof; 4958 4959 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4960 if (!dof) continue; 4961 for (f = 0; f < numFields; ++f) { 4962 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4963 coffsets[f+1] += fdof; 4964 } 4965 numCIndices += dof; 4966 } 4967 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4968 /* Row indices */ 4969 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4970 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4971 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4972 for (r = 0, q = 0; r < numSubcells; ++r) { 4973 /* TODO Map from coarse to fine cells */ 4974 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4975 /* Compress out points not in the section */ 4976 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4977 for (p = 0; p < numFPoints*2; p += 2) { 4978 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4979 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4980 if (!dof) continue; 4981 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4982 if (s < q) continue; 4983 ftotpoints[q*2] = fpoints[p]; 4984 ftotpoints[q*2+1] = fpoints[p+1]; 4985 ++q; 4986 } 4987 } 4988 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4989 } 4990 numFPoints = q; 4991 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4992 PetscInt fdof; 4993 4994 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4995 if (!dof) continue; 4996 for (f = 0; f < numFields; ++f) { 4997 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4998 foffsets[f+1] += fdof; 4999 } 5000 numFIndices += dof; 5001 } 5002 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5003 5004 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5005 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5006 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5007 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5008 if (numFields) { 5009 for (p = 0; p < numFPoints*2; p += 2) { 5010 PetscInt o = ftotpoints[p+1]; 5011 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5012 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5013 } 5014 for (p = 0; p < numCPoints*2; p += 2) { 5015 PetscInt o = cpoints[p+1]; 5016 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5017 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5018 } 5019 } else { 5020 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5021 PetscInt o = ftotpoints[p+1]; 5022 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5023 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5024 } 5025 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5026 PetscInt o = cpoints[p+1]; 5027 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5028 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5029 } 5030 } 5031 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5032 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5033 if (ierr) { 5034 PetscMPIInt rank; 5035 PetscErrorCode ierr2; 5036 5037 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5038 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5039 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5040 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5041 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5042 CHKERRQ(ierr); 5043 } 5044 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5045 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5046 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5047 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5048 PetscFunctionReturn(0); 5049 } 5050 5051 #undef __FUNCT__ 5052 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5053 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5054 { 5055 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5056 PetscInt *cpoints = NULL; 5057 PetscInt foffsets[32], coffsets[32]; 5058 CellRefiner cellRefiner; 5059 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5060 PetscErrorCode ierr; 5061 5062 PetscFunctionBegin; 5063 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5064 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5065 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5066 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5067 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5068 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5069 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5070 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5071 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5072 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5073 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5074 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5075 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5076 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5077 /* Column indices */ 5078 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5079 maxFPoints = numCPoints; 5080 /* Compress out points not in the section */ 5081 /* TODO: Squeeze out points with 0 dof as well */ 5082 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5083 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5084 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5085 cpoints[q*2] = cpoints[p]; 5086 cpoints[q*2+1] = cpoints[p+1]; 5087 ++q; 5088 } 5089 } 5090 numCPoints = q; 5091 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5092 PetscInt fdof; 5093 5094 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5095 if (!dof) continue; 5096 for (f = 0; f < numFields; ++f) { 5097 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5098 coffsets[f+1] += fdof; 5099 } 5100 numCIndices += dof; 5101 } 5102 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5103 /* Row indices */ 5104 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5105 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5106 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5107 for (r = 0, q = 0; r < numSubcells; ++r) { 5108 /* TODO Map from coarse to fine cells */ 5109 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5110 /* Compress out points not in the section */ 5111 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5112 for (p = 0; p < numFPoints*2; p += 2) { 5113 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5114 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5115 if (!dof) continue; 5116 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5117 if (s < q) continue; 5118 ftotpoints[q*2] = fpoints[p]; 5119 ftotpoints[q*2+1] = fpoints[p+1]; 5120 ++q; 5121 } 5122 } 5123 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5124 } 5125 numFPoints = q; 5126 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5127 PetscInt fdof; 5128 5129 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5130 if (!dof) continue; 5131 for (f = 0; f < numFields; ++f) { 5132 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5133 foffsets[f+1] += fdof; 5134 } 5135 numFIndices += dof; 5136 } 5137 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5138 5139 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5140 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5141 if (numFields) { 5142 for (p = 0; p < numFPoints*2; p += 2) { 5143 PetscInt o = ftotpoints[p+1]; 5144 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5145 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5146 } 5147 for (p = 0; p < numCPoints*2; p += 2) { 5148 PetscInt o = cpoints[p+1]; 5149 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5150 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5151 } 5152 } else { 5153 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5154 PetscInt o = ftotpoints[p+1]; 5155 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5156 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5157 } 5158 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5159 PetscInt o = cpoints[p+1]; 5160 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5161 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5162 } 5163 } 5164 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5165 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5166 PetscFunctionReturn(0); 5167 } 5168 5169 #undef __FUNCT__ 5170 #define __FUNCT__ "DMPlexGetHybridBounds" 5171 /*@ 5172 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5173 5174 Input Parameter: 5175 . dm - The DMPlex object 5176 5177 Output Parameters: 5178 + cMax - The first hybrid cell 5179 . fMax - The first hybrid face 5180 . eMax - The first hybrid edge 5181 - vMax - The first hybrid vertex 5182 5183 Level: developer 5184 5185 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5186 @*/ 5187 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5188 { 5189 DM_Plex *mesh = (DM_Plex*) dm->data; 5190 PetscInt dim; 5191 PetscErrorCode ierr; 5192 5193 PetscFunctionBegin; 5194 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5195 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5196 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5197 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5198 if (eMax) *eMax = mesh->hybridPointMax[1]; 5199 if (vMax) *vMax = mesh->hybridPointMax[0]; 5200 PetscFunctionReturn(0); 5201 } 5202 5203 #undef __FUNCT__ 5204 #define __FUNCT__ "DMPlexSetHybridBounds" 5205 /*@ 5206 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5207 5208 Input Parameters: 5209 . dm - The DMPlex object 5210 . cMax - The first hybrid cell 5211 . fMax - The first hybrid face 5212 . eMax - The first hybrid edge 5213 - vMax - The first hybrid vertex 5214 5215 Level: developer 5216 5217 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5218 @*/ 5219 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5220 { 5221 DM_Plex *mesh = (DM_Plex*) dm->data; 5222 PetscInt dim; 5223 PetscErrorCode ierr; 5224 5225 PetscFunctionBegin; 5226 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5227 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5228 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5229 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5230 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5231 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5232 PetscFunctionReturn(0); 5233 } 5234 5235 #undef __FUNCT__ 5236 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5237 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5238 { 5239 DM_Plex *mesh = (DM_Plex*) dm->data; 5240 5241 PetscFunctionBegin; 5242 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5243 PetscValidPointer(cellHeight, 2); 5244 *cellHeight = mesh->vtkCellHeight; 5245 PetscFunctionReturn(0); 5246 } 5247 5248 #undef __FUNCT__ 5249 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5250 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5251 { 5252 DM_Plex *mesh = (DM_Plex*) dm->data; 5253 5254 PetscFunctionBegin; 5255 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5256 mesh->vtkCellHeight = cellHeight; 5257 PetscFunctionReturn(0); 5258 } 5259 5260 #undef __FUNCT__ 5261 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5262 /* We can easily have a form that takes an IS instead */ 5263 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5264 { 5265 PetscSection section, globalSection; 5266 PetscInt *numbers, p; 5267 PetscErrorCode ierr; 5268 5269 PetscFunctionBegin; 5270 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5271 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5272 for (p = pStart; p < pEnd; ++p) { 5273 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5274 } 5275 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5276 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5277 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5278 for (p = pStart; p < pEnd; ++p) { 5279 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5280 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5281 else numbers[p-pStart] += shift; 5282 } 5283 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5284 if (globalSize) { 5285 PetscLayout layout; 5286 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5287 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5288 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5289 } 5290 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5291 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5292 PetscFunctionReturn(0); 5293 } 5294 5295 #undef __FUNCT__ 5296 #define __FUNCT__ "DMPlexGetCellNumbering" 5297 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5298 { 5299 DM_Plex *mesh = (DM_Plex*) dm->data; 5300 PetscInt cellHeight, cStart, cEnd, cMax; 5301 PetscErrorCode ierr; 5302 5303 PetscFunctionBegin; 5304 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5305 if (!mesh->globalCellNumbers) { 5306 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5307 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5308 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5309 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5310 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5311 } 5312 *globalCellNumbers = mesh->globalCellNumbers; 5313 PetscFunctionReturn(0); 5314 } 5315 5316 #undef __FUNCT__ 5317 #define __FUNCT__ "DMPlexGetVertexNumbering" 5318 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5319 { 5320 DM_Plex *mesh = (DM_Plex*) dm->data; 5321 PetscInt vStart, vEnd, vMax; 5322 PetscErrorCode ierr; 5323 5324 PetscFunctionBegin; 5325 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5326 if (!mesh->globalVertexNumbers) { 5327 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5328 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5329 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5330 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5331 } 5332 *globalVertexNumbers = mesh->globalVertexNumbers; 5333 PetscFunctionReturn(0); 5334 } 5335 5336 #undef __FUNCT__ 5337 #define __FUNCT__ "DMPlexCreatePointNumbering" 5338 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5339 { 5340 IS nums[4]; 5341 PetscInt depths[4]; 5342 PetscInt depth, d, shift = 0; 5343 PetscErrorCode ierr; 5344 5345 PetscFunctionBegin; 5346 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5347 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5348 /* For unstratified meshes use dim instead of depth */ 5349 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5350 depths[0] = depth; depths[1] = 0; 5351 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5352 for (d = 0; d <= depth; ++d) { 5353 PetscInt pStart, pEnd, gsize; 5354 5355 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5356 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5357 shift += gsize; 5358 } 5359 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5360 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5361 PetscFunctionReturn(0); 5362 } 5363 5364 5365 #undef __FUNCT__ 5366 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 5367 /*@C 5368 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 5369 the local section and an SF describing the section point overlap. 5370 5371 Input Parameters: 5372 + s - The PetscSection for the local field layout 5373 . sf - The SF describing parallel layout of the section points 5374 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 5375 . label - The label specifying the points 5376 - labelValue - The label stratum specifying the points 5377 5378 Output Parameter: 5379 . gsection - The PetscSection for the global field layout 5380 5381 Note: This gives negative sizes and offsets to points not owned by this process 5382 5383 Level: developer 5384 5385 .seealso: PetscSectionCreate() 5386 @*/ 5387 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 5388 { 5389 PetscInt *neg = NULL, *tmpOff = NULL; 5390 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 5391 PetscErrorCode ierr; 5392 5393 PetscFunctionBegin; 5394 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 5395 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 5396 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 5397 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 5398 if (nroots >= 0) { 5399 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 5400 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 5401 if (nroots > pEnd-pStart) { 5402 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 5403 } else { 5404 tmpOff = &(*gsection)->atlasDof[-pStart]; 5405 } 5406 } 5407 /* Mark ghost points with negative dof */ 5408 for (p = pStart; p < pEnd; ++p) { 5409 PetscInt value; 5410 5411 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 5412 if (value != labelValue) continue; 5413 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 5414 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 5415 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 5416 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 5417 if (neg) neg[p] = -(dof+1); 5418 } 5419 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 5420 if (nroots >= 0) { 5421 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5422 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5423 if (nroots > pEnd-pStart) { 5424 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 5425 } 5426 } 5427 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 5428 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5429 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 5430 (*gsection)->atlasOff[p] = off; 5431 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 5432 } 5433 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); 5434 globalOff -= off; 5435 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5436 (*gsection)->atlasOff[p] += globalOff; 5437 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 5438 } 5439 /* Put in negative offsets for ghost points */ 5440 if (nroots >= 0) { 5441 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5442 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5443 if (nroots > pEnd-pStart) { 5444 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 5445 } 5446 } 5447 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 5448 ierr = PetscFree(neg);CHKERRQ(ierr); 5449 PetscFunctionReturn(0); 5450 } 5451 5452 #undef __FUNCT__ 5453 #define __FUNCT__ "DMPlexCheckSymmetry" 5454 /*@ 5455 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5456 5457 Input Parameters: 5458 + dm - The DMPlex object 5459 5460 Note: This is a useful diagnostic when creating meshes programmatically. 5461 5462 Level: developer 5463 5464 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5465 @*/ 5466 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5467 { 5468 PetscSection coneSection, supportSection; 5469 const PetscInt *cone, *support; 5470 PetscInt coneSize, c, supportSize, s; 5471 PetscInt pStart, pEnd, p, csize, ssize; 5472 PetscErrorCode ierr; 5473 5474 PetscFunctionBegin; 5475 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5476 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5477 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5478 /* Check that point p is found in the support of its cone points, and vice versa */ 5479 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5480 for (p = pStart; p < pEnd; ++p) { 5481 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5482 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5483 for (c = 0; c < coneSize; ++c) { 5484 PetscBool dup = PETSC_FALSE; 5485 PetscInt d; 5486 for (d = c-1; d >= 0; --d) { 5487 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5488 } 5489 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5490 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5491 for (s = 0; s < supportSize; ++s) { 5492 if (support[s] == p) break; 5493 } 5494 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5495 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5496 for (s = 0; s < coneSize; ++s) { 5497 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5498 } 5499 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5500 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5501 for (s = 0; s < supportSize; ++s) { 5502 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5503 } 5504 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5505 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5506 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5507 } 5508 } 5509 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5510 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5511 for (s = 0; s < supportSize; ++s) { 5512 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5513 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5514 for (c = 0; c < coneSize; ++c) { 5515 if (cone[c] == p) break; 5516 } 5517 if (c >= coneSize) { 5518 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5519 for (c = 0; c < supportSize; ++c) { 5520 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5521 } 5522 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5523 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5524 for (c = 0; c < coneSize; ++c) { 5525 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5526 } 5527 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5528 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5529 } 5530 } 5531 } 5532 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5533 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5534 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5535 PetscFunctionReturn(0); 5536 } 5537 5538 #undef __FUNCT__ 5539 #define __FUNCT__ "DMPlexCheckSkeleton" 5540 /*@ 5541 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5542 5543 Input Parameters: 5544 + dm - The DMPlex object 5545 . isSimplex - Are the cells simplices or tensor products 5546 - cellHeight - Normally 0 5547 5548 Note: This is a useful diagnostic when creating meshes programmatically. 5549 5550 Level: developer 5551 5552 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5553 @*/ 5554 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5555 { 5556 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5557 PetscErrorCode ierr; 5558 5559 PetscFunctionBegin; 5560 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5561 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5562 switch (dim) { 5563 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5564 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5565 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5566 default: 5567 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5568 } 5569 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5570 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5571 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5572 cMax = cMax >= 0 ? cMax : cEnd; 5573 for (c = cStart; c < cMax; ++c) { 5574 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5575 5576 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5577 for (cl = 0; cl < closureSize*2; cl += 2) { 5578 const PetscInt p = closure[cl]; 5579 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5580 } 5581 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5582 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5583 } 5584 for (c = cMax; c < cEnd; ++c) { 5585 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5586 5587 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5588 for (cl = 0; cl < closureSize*2; cl += 2) { 5589 const PetscInt p = closure[cl]; 5590 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5591 } 5592 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5593 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5594 } 5595 PetscFunctionReturn(0); 5596 } 5597 5598 #undef __FUNCT__ 5599 #define __FUNCT__ "DMPlexCheckFaces" 5600 /*@ 5601 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5602 5603 Input Parameters: 5604 + dm - The DMPlex object 5605 . isSimplex - Are the cells simplices or tensor products 5606 - cellHeight - Normally 0 5607 5608 Note: This is a useful diagnostic when creating meshes programmatically. 5609 5610 Level: developer 5611 5612 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5613 @*/ 5614 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5615 { 5616 PetscInt pMax[4]; 5617 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5618 PetscErrorCode ierr; 5619 5620 PetscFunctionBegin; 5621 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5622 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5623 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5624 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5625 for (h = cellHeight; h < dim; ++h) { 5626 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5627 for (c = cStart; c < cEnd; ++c) { 5628 const PetscInt *cone, *ornt, *faces; 5629 PetscInt numFaces, faceSize, coneSize,f; 5630 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5631 5632 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5633 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5634 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5635 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5636 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5637 for (cl = 0; cl < closureSize*2; cl += 2) { 5638 const PetscInt p = closure[cl]; 5639 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5640 } 5641 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5642 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5643 for (f = 0; f < numFaces; ++f) { 5644 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5645 5646 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5647 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5648 const PetscInt p = fclosure[cl]; 5649 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5650 } 5651 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); 5652 for (v = 0; v < fnumCorners; ++v) { 5653 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]); 5654 } 5655 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5656 } 5657 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5658 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5659 } 5660 } 5661 PetscFunctionReturn(0); 5662 } 5663 5664 #undef __FUNCT__ 5665 #define __FUNCT__ "DMCreateInterpolation_Plex" 5666 /* Pointwise interpolation 5667 Just code FEM for now 5668 u^f = I u^c 5669 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5670 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5671 I_{ij} = psi^f_i phi^c_j 5672 */ 5673 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5674 { 5675 PetscSection gsc, gsf; 5676 PetscInt m, n; 5677 void *ctx; 5678 DM cdm; 5679 PetscBool regular; 5680 PetscErrorCode ierr; 5681 5682 PetscFunctionBegin; 5683 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5684 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5685 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5686 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5687 5688 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5689 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5690 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5691 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5692 5693 ierr = DMPlexGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5694 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5695 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5696 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5697 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5698 /* Use naive scaling */ 5699 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5700 PetscFunctionReturn(0); 5701 } 5702 5703 #undef __FUNCT__ 5704 #define __FUNCT__ "DMCreateInjection_Plex" 5705 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5706 { 5707 PetscErrorCode ierr; 5708 VecScatter ctx; 5709 5710 PetscFunctionBegin; 5711 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5712 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5713 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5714 PetscFunctionReturn(0); 5715 } 5716 5717 #undef __FUNCT__ 5718 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5719 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5720 { 5721 PetscSection section; 5722 IS *bcPoints, *bcComps; 5723 PetscBool *isFE; 5724 PetscInt *bcFields, *numComp, *numDof; 5725 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5726 PetscInt cStart, cEnd, cEndInterior; 5727 PetscErrorCode ierr; 5728 5729 PetscFunctionBegin; 5730 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 5731 if (!numFields) PetscFunctionReturn(0); 5732 /* FE and FV boundary conditions are handled slightly differently */ 5733 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 5734 for (f = 0; f < numFields; ++f) { 5735 PetscObject obj; 5736 PetscClassId id; 5737 5738 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5739 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 5740 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 5741 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 5742 else SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Unknown discretization type for field %d", f); 5743 } 5744 /* Allocate boundary point storage for FEM boundaries */ 5745 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5746 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5747 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 5748 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 5749 ierr = DMPlexGetNumBoundary(dm, &numBd);CHKERRQ(ierr); 5750 for (bd = 0; bd < numBd; ++bd) { 5751 PetscInt field; 5752 PetscBool isEssential; 5753 5754 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, NULL, &field, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5755 if (isFE[field] && isEssential) ++numBC; 5756 } 5757 /* Add ghost cell boundaries for FVM */ 5758 for (f = 0; f < numFields; ++f) if (!isFE[f] && cEndInterior >= 0) ++numBC; 5759 ierr = PetscCalloc3(numBC,&bcFields,numBC,&bcPoints,numBC,&bcComps);CHKERRQ(ierr); 5760 /* Constrain ghost cells for FV */ 5761 for (f = 0; f < numFields; ++f) { 5762 PetscInt *newidx, c; 5763 5764 if (isFE[f] || cEndInterior < 0) continue; 5765 ierr = PetscMalloc1(cEnd-cEndInterior,&newidx);CHKERRQ(ierr); 5766 for (c = cEndInterior; c < cEnd; ++c) newidx[c-cEndInterior] = c; 5767 bcFields[bc] = f; 5768 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), cEnd-cEndInterior, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5769 } 5770 /* Handle FEM Dirichlet boundaries */ 5771 for (bd = 0; bd < numBd; ++bd) { 5772 const char *bdLabel; 5773 DMLabel label; 5774 const PetscInt *comps; 5775 const PetscInt *values; 5776 PetscInt bd2, field, numComps, numValues; 5777 PetscBool isEssential, duplicate = PETSC_FALSE; 5778 5779 ierr = DMPlexGetBoundary(dm, bd, &isEssential, NULL, &bdLabel, &field, &numComps, &comps, NULL, &numValues, &values, NULL);CHKERRQ(ierr); 5780 if (!isFE[field]) continue; 5781 ierr = DMPlexGetLabel(dm, bdLabel, &label);CHKERRQ(ierr); 5782 /* Only want to modify label once */ 5783 for (bd2 = 0; bd2 < bd; ++bd2) { 5784 const char *bdname; 5785 ierr = DMPlexGetBoundary(dm, bd2, NULL, NULL, &bdname, NULL, NULL, NULL, NULL, NULL, NULL, NULL);CHKERRQ(ierr); 5786 ierr = PetscStrcmp(bdname, bdLabel, &duplicate);CHKERRQ(ierr); 5787 if (duplicate) break; 5788 } 5789 if (!duplicate && (isFE[field])) { 5790 ierr = DMPlexLabelComplete(dm, label);CHKERRQ(ierr); 5791 ierr = DMPlexLabelAddCells(dm, label);CHKERRQ(ierr); 5792 } 5793 /* Filter out cells, if you actually want to constrain cells you need to do things by hand right now */ 5794 if (isEssential) { 5795 PetscInt *newidx; 5796 PetscInt n, newn = 0, p, v; 5797 5798 bcFields[bc] = field; 5799 if (numComps) {ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), numComps, comps, PETSC_COPY_VALUES, &bcComps[bc]);CHKERRQ(ierr);} 5800 for (v = 0; v < numValues; ++v) { 5801 IS tmp; 5802 const PetscInt *idx; 5803 5804 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5805 if (!tmp) continue; 5806 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5807 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5808 if (isFE[field]) { 5809 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) ++newn; 5810 } else { 5811 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) ++newn; 5812 } 5813 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5814 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5815 } 5816 ierr = PetscMalloc1(newn,&newidx);CHKERRQ(ierr); 5817 newn = 0; 5818 for (v = 0; v < numValues; ++v) { 5819 IS tmp; 5820 const PetscInt *idx; 5821 5822 ierr = DMPlexGetStratumIS(dm, bdLabel, values[v], &tmp);CHKERRQ(ierr); 5823 if (!tmp) continue; 5824 ierr = ISGetLocalSize(tmp, &n);CHKERRQ(ierr); 5825 ierr = ISGetIndices(tmp, &idx);CHKERRQ(ierr); 5826 if (isFE[field]) { 5827 for (p = 0; p < n; ++p) if ((idx[p] < cStart) || (idx[p] >= cEnd)) newidx[newn++] = idx[p]; 5828 } else { 5829 for (p = 0; p < n; ++p) if ((idx[p] >= cStart) || (idx[p] < cEnd)) newidx[newn++] = idx[p]; 5830 } 5831 ierr = ISRestoreIndices(tmp, &idx);CHKERRQ(ierr); 5832 ierr = ISDestroy(&tmp);CHKERRQ(ierr); 5833 } 5834 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), newn, newidx, PETSC_OWN_POINTER, &bcPoints[bc++]);CHKERRQ(ierr); 5835 } 5836 } 5837 /* Handle discretization */ 5838 ierr = PetscCalloc2(numFields,&numComp,numFields*(dim+1),&numDof);CHKERRQ(ierr); 5839 for (f = 0; f < numFields; ++f) { 5840 PetscObject obj; 5841 5842 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 5843 if (isFE[f]) { 5844 PetscFE fe = (PetscFE) obj; 5845 const PetscInt *numFieldDof; 5846 PetscInt d; 5847 5848 ierr = PetscFEGetNumComponents(fe, &numComp[f]);CHKERRQ(ierr); 5849 ierr = PetscFEGetNumDof(fe, &numFieldDof);CHKERRQ(ierr); 5850 for (d = 0; d < dim+1; ++d) numDof[f*(dim+1)+d] = numFieldDof[d]; 5851 } else { 5852 PetscFV fv = (PetscFV) obj; 5853 5854 ierr = PetscFVGetNumComponents(fv, &numComp[f]);CHKERRQ(ierr); 5855 numDof[f*(dim+1)+dim] = numComp[f]; 5856 } 5857 } 5858 for (f = 0; f < numFields; ++f) { 5859 PetscInt d; 5860 for (d = 1; d < dim; ++d) { 5861 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."); 5862 } 5863 } 5864 ierr = DMPlexCreateSection(dm, dim, numFields, numComp, numDof, numBC, bcFields, bcComps, bcPoints, NULL, §ion);CHKERRQ(ierr); 5865 for (f = 0; f < numFields; ++f) { 5866 PetscFE fe; 5867 const char *name; 5868 5869 ierr = DMGetField(dm, f, (PetscObject *) &fe);CHKERRQ(ierr); 5870 ierr = PetscObjectGetName((PetscObject) fe, &name);CHKERRQ(ierr); 5871 ierr = PetscSectionSetFieldName(section, f, name);CHKERRQ(ierr); 5872 } 5873 ierr = DMSetDefaultSection(dm, section);CHKERRQ(ierr); 5874 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5875 for (bc = 0; bc < numBC; ++bc) {ierr = ISDestroy(&bcPoints[bc]);CHKERRQ(ierr);ierr = ISDestroy(&bcComps[bc]);CHKERRQ(ierr);} 5876 ierr = PetscFree3(bcFields,bcPoints,bcComps);CHKERRQ(ierr); 5877 ierr = PetscFree2(numComp,numDof);CHKERRQ(ierr); 5878 ierr = PetscFree(isFE);CHKERRQ(ierr); 5879 PetscFunctionReturn(0); 5880 } 5881 5882 #undef __FUNCT__ 5883 #define __FUNCT__ "DMPlexGetCoarseDM" 5884 /*@ 5885 DMPlexGetCoarseDM - Get the coarse mesh from which this was obtained by refinement 5886 5887 Input Parameter: 5888 . dm - The DMPlex object 5889 5890 Output Parameter: 5891 . cdm - The coarse DM 5892 5893 Level: intermediate 5894 5895 .seealso: DMPlexSetCoarseDM() 5896 @*/ 5897 PetscErrorCode DMPlexGetCoarseDM(DM dm, DM *cdm) 5898 { 5899 PetscFunctionBegin; 5900 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5901 PetscValidPointer(cdm, 2); 5902 *cdm = ((DM_Plex *) dm->data)->coarseMesh; 5903 PetscFunctionReturn(0); 5904 } 5905 5906 #undef __FUNCT__ 5907 #define __FUNCT__ "DMPlexSetCoarseDM" 5908 /*@ 5909 DMPlexSetCoarseDM - Set the coarse mesh from which this was obtained by refinement 5910 5911 Input Parameters: 5912 + dm - The DMPlex object 5913 - cdm - The coarse DM 5914 5915 Level: intermediate 5916 5917 .seealso: DMPlexGetCoarseDM() 5918 @*/ 5919 PetscErrorCode DMPlexSetCoarseDM(DM dm, DM cdm) 5920 { 5921 DM_Plex *mesh; 5922 PetscErrorCode ierr; 5923 5924 PetscFunctionBegin; 5925 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5926 if (cdm) PetscValidHeaderSpecific(cdm, DM_CLASSID, 2); 5927 mesh = (DM_Plex *) dm->data; 5928 ierr = DMDestroy(&mesh->coarseMesh);CHKERRQ(ierr); 5929 mesh->coarseMesh = cdm; 5930 ierr = PetscObjectReference((PetscObject) mesh->coarseMesh);CHKERRQ(ierr); 5931 PetscFunctionReturn(0); 5932 } 5933 5934 #undef __FUNCT__ 5935 #define __FUNCT__ "DMPlexGetRegularRefinement" 5936 /*@ 5937 DMPlexGetRegularRefinement - Get the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5938 5939 Input Parameter: 5940 . dm - The DMPlex object 5941 5942 Output Parameter: 5943 . regular - The flag 5944 5945 Level: intermediate 5946 5947 .seealso: DMPlexSetRegularRefinement() 5948 @*/ 5949 PetscErrorCode DMPlexGetRegularRefinement(DM dm, PetscBool *regular) 5950 { 5951 PetscFunctionBegin; 5952 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5953 PetscValidPointer(regular, 2); 5954 *regular = ((DM_Plex *) dm->data)->regularRefinement; 5955 PetscFunctionReturn(0); 5956 } 5957 5958 #undef __FUNCT__ 5959 #define __FUNCT__ "DMPlexSetRegularRefinement" 5960 /*@ 5961 DMPlexSetRegularRefinement - Set the flag indicating that this mesh was obtained by regular refinement from its coarse mesh 5962 5963 Input Parameters: 5964 + dm - The DMPlex object 5965 - regular - The flag 5966 5967 Level: intermediate 5968 5969 .seealso: DMPlexGetRegularRefinement() 5970 @*/ 5971 PetscErrorCode DMPlexSetRegularRefinement(DM dm, PetscBool regular) 5972 { 5973 PetscFunctionBegin; 5974 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5975 ((DM_Plex *) dm->data)->regularRefinement = regular; 5976 PetscFunctionReturn(0); 5977 } 5978 5979 /* anchors */ 5980 #undef __FUNCT__ 5981 #define __FUNCT__ "DMPlexGetAnchors" 5982 /*@ 5983 DMPlexGetAnchors - Get the layout of the anchor (point-to-point) constraints. Typically, the user will not have to 5984 call DMPlexGetAnchors() directly: if there are anchors, then DMPlexGetAnchors() is called during DMGetConstraints(). 5985 5986 not collective 5987 5988 Input Parameters: 5989 . dm - The DMPlex object 5990 5991 Output Parameters: 5992 + anchorSection - If not NULL, set to the section describing which points anchor the constrained points. 5993 - anchorIS - If not NULL, set to the list of anchors indexed by anchorSection 5994 5995 5996 Level: intermediate 5997 5998 .seealso: DMPlexSetAnchors(), DMGetConstraints(), DMSetConstraints() 5999 @*/ 6000 PetscErrorCode DMPlexGetAnchors(DM dm, PetscSection *anchorSection, IS *anchorIS) 6001 { 6002 DM_Plex *plex = (DM_Plex *)dm->data; 6003 PetscErrorCode ierr; 6004 6005 PetscFunctionBegin; 6006 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6007 if (!plex->anchorSection && !plex->anchorIS && plex->createanchors) {ierr = (*plex->createanchors)(dm);CHKERRQ(ierr);} 6008 if (anchorSection) *anchorSection = plex->anchorSection; 6009 if (anchorIS) *anchorIS = plex->anchorIS; 6010 PetscFunctionReturn(0); 6011 } 6012 6013 #undef __FUNCT__ 6014 #define __FUNCT__ "DMPlexSetAnchors" 6015 /*@ 6016 DMPlexSetAnchors - Set the layout of the local anchor (point-to-point) constraints. Unlike boundary conditions, 6017 when a point's degrees of freedom in a section are constrained to an outside value, the anchor constraints set a 6018 point's degrees of freedom to be a linear combination of other points' degrees of freedom. 6019 6020 After specifying the layout of constraints with DMPlexSetAnchors(), one specifies the constraints by calling 6021 DMGetConstraints() and filling in the entries in the constraint matrix. 6022 6023 collective on dm 6024 6025 Input Parameters: 6026 + dm - The DMPlex object 6027 . 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). 6028 - anchorIS - The list of all anchor points. Must have a local communicator (PETSC_COMM_SELF or derivative). 6029 6030 The reference counts of anchorSection and anchorIS are incremented. 6031 6032 Level: intermediate 6033 6034 .seealso: DMPlexGetAnchors(), DMGetConstraints(), DMSetConstraints() 6035 @*/ 6036 PetscErrorCode DMPlexSetAnchors(DM dm, PetscSection anchorSection, IS anchorIS) 6037 { 6038 DM_Plex *plex = (DM_Plex *)dm->data; 6039 PetscMPIInt result; 6040 PetscErrorCode ierr; 6041 6042 PetscFunctionBegin; 6043 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6044 if (anchorSection) { 6045 PetscValidHeaderSpecific(anchorSection,PETSC_SECTION_CLASSID,2); 6046 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorSection),&result);CHKERRQ(ierr); 6047 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor section must have local communicator"); 6048 } 6049 if (anchorIS) { 6050 PetscValidHeaderSpecific(anchorIS,IS_CLASSID,3); 6051 ierr = MPI_Comm_compare(PETSC_COMM_SELF,PetscObjectComm((PetscObject)anchorIS),&result);CHKERRQ(ierr); 6052 if (result != MPI_CONGRUENT) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_ARG_NOTSAMECOMM,"anchor IS must have local communicator"); 6053 } 6054 6055 ierr = PetscObjectReference((PetscObject)anchorSection);CHKERRQ(ierr); 6056 ierr = PetscSectionDestroy(&plex->anchorSection);CHKERRQ(ierr); 6057 plex->anchorSection = anchorSection; 6058 6059 ierr = PetscObjectReference((PetscObject)anchorIS);CHKERRQ(ierr); 6060 ierr = ISDestroy(&plex->anchorIS);CHKERRQ(ierr); 6061 plex->anchorIS = anchorIS; 6062 6063 #if defined(PETSC_USE_DEBUG) 6064 if (anchorIS && anchorSection) { 6065 PetscInt size, a, pStart, pEnd; 6066 const PetscInt *anchors; 6067 6068 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6069 ierr = ISGetLocalSize(anchorIS,&size);CHKERRQ(ierr); 6070 ierr = ISGetIndices(anchorIS,&anchors);CHKERRQ(ierr); 6071 for (a = 0; a < size; a++) { 6072 PetscInt p; 6073 6074 p = anchors[a]; 6075 if (p >= pStart && p < pEnd) { 6076 PetscInt dof; 6077 6078 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6079 if (dof) { 6080 PetscErrorCode ierr2; 6081 6082 ierr2 = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr2); 6083 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_INCOMP,"Point %d cannot be constrained and an anchor",p); 6084 } 6085 } 6086 } 6087 ierr = ISRestoreIndices(anchorIS,&anchors);CHKERRQ(ierr); 6088 } 6089 #endif 6090 /* reset the generic constraints */ 6091 ierr = DMSetDefaultConstraints(dm,NULL,NULL);CHKERRQ(ierr); 6092 PetscFunctionReturn(0); 6093 } 6094 6095 #undef __FUNCT__ 6096 #define __FUNCT__ "DMPlexCreateConstraintSection_Anchors" 6097 static PetscErrorCode DMPlexCreateConstraintSection_Anchors(DM dm, PetscSection section, PetscSection *cSec) 6098 { 6099 PetscSection anchorSection; 6100 PetscInt pStart, pEnd, sStart, sEnd, p, dof, numFields, f; 6101 PetscErrorCode ierr; 6102 6103 PetscFunctionBegin; 6104 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6105 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6106 ierr = PetscSectionCreate(PETSC_COMM_SELF,cSec);CHKERRQ(ierr); 6107 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6108 if (numFields) { 6109 ierr = PetscSectionSetNumFields(*cSec,numFields);CHKERRQ(ierr); 6110 } 6111 ierr = PetscSectionGetChart(anchorSection,&pStart,&pEnd);CHKERRQ(ierr); 6112 ierr = PetscSectionGetChart(section,&sStart,&sEnd);CHKERRQ(ierr); 6113 pStart = PetscMax(pStart,sStart); 6114 pEnd = PetscMin(pEnd,sEnd); 6115 pEnd = PetscMax(pStart,pEnd); 6116 ierr = PetscSectionSetChart(*cSec,pStart,pEnd);CHKERRQ(ierr); 6117 for (p = pStart; p < pEnd; p++) { 6118 ierr = PetscSectionGetDof(anchorSection,p,&dof);CHKERRQ(ierr); 6119 if (dof) { 6120 ierr = PetscSectionGetDof(section,p,&dof);CHKERRQ(ierr); 6121 ierr = PetscSectionSetDof(*cSec,p,dof);CHKERRQ(ierr); 6122 for (f = 0; f < numFields; f++) { 6123 ierr = PetscSectionGetFieldDof(section,p,f,&dof);CHKERRQ(ierr); 6124 ierr = PetscSectionSetFieldDof(*cSec,p,f,dof);CHKERRQ(ierr); 6125 } 6126 } 6127 } 6128 ierr = PetscSectionSetUp(*cSec);CHKERRQ(ierr); 6129 PetscFunctionReturn(0); 6130 } 6131 6132 #undef __FUNCT__ 6133 #define __FUNCT__ "DMPlexCreateConstraintMatrix_Anchors" 6134 static PetscErrorCode DMPlexCreateConstraintMatrix_Anchors(DM dm, PetscSection section, PetscSection cSec, Mat *cMat) 6135 { 6136 PetscSection aSec; 6137 PetscInt pStart, pEnd, p, dof, aDof, aOff, off, nnz, annz, m, n, q, a, offset, *i, *j; 6138 const PetscInt *anchors; 6139 PetscInt numFields, f; 6140 IS aIS; 6141 PetscErrorCode ierr; 6142 6143 PetscFunctionBegin; 6144 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6145 ierr = PetscSectionGetStorageSize(cSec, &m);CHKERRQ(ierr); 6146 ierr = PetscSectionGetStorageSize(section, &n);CHKERRQ(ierr); 6147 ierr = MatCreate(PETSC_COMM_SELF,cMat);CHKERRQ(ierr); 6148 ierr = MatSetSizes(*cMat,m,n,m,n);CHKERRQ(ierr); 6149 ierr = MatSetType(*cMat,MATSEQAIJ);CHKERRQ(ierr); 6150 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 6151 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 6152 /* cSec will be a subset of aSec and section */ 6153 ierr = PetscSectionGetChart(cSec,&pStart,&pEnd);CHKERRQ(ierr); 6154 ierr = PetscMalloc1(m+1,&i);CHKERRQ(ierr); 6155 i[0] = 0; 6156 ierr = PetscSectionGetNumFields(section,&numFields);CHKERRQ(ierr); 6157 for (p = pStart; p < pEnd; p++) { 6158 ierr = PetscSectionGetDof(aSec,p,&dof);CHKERRQ(ierr); 6159 if (!dof) continue; 6160 ierr = PetscSectionGetOffset(aSec,p,&off);CHKERRQ(ierr); 6161 if (numFields) { 6162 for (f = 0; f < numFields; f++) { 6163 annz = 0; 6164 for (q = 0; q < dof; q++) { 6165 a = anchors[off + q]; 6166 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6167 annz += aDof; 6168 } 6169 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6170 ierr = PetscSectionGetFieldOffset(cSec,p,f,&off);CHKERRQ(ierr); 6171 for (q = 0; q < dof; q++) { 6172 i[off + q + 1] = i[off + q] + annz; 6173 } 6174 } 6175 } 6176 else { 6177 annz = 0; 6178 for (q = 0; q < dof; q++) { 6179 a = anchors[off + q]; 6180 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6181 annz += aDof; 6182 } 6183 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6184 ierr = PetscSectionGetOffset(cSec,p,&off);CHKERRQ(ierr); 6185 for (q = 0; q < dof; q++) { 6186 i[off + q + 1] = i[off + q] + annz; 6187 } 6188 } 6189 } 6190 nnz = i[m]; 6191 ierr = PetscMalloc1(nnz,&j);CHKERRQ(ierr); 6192 offset = 0; 6193 for (p = pStart; p < pEnd; p++) { 6194 if (numFields) { 6195 for (f = 0; f < numFields; f++) { 6196 ierr = PetscSectionGetFieldDof(cSec,p,f,&dof);CHKERRQ(ierr); 6197 for (q = 0; q < dof; q++) { 6198 PetscInt rDof, rOff, r; 6199 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6200 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6201 for (r = 0; r < rDof; r++) { 6202 PetscInt s; 6203 6204 a = anchors[rOff + r]; 6205 ierr = PetscSectionGetFieldDof(section,a,f,&aDof);CHKERRQ(ierr); 6206 ierr = PetscSectionGetFieldOffset(section,a,f,&aOff);CHKERRQ(ierr); 6207 for (s = 0; s < aDof; s++) { 6208 j[offset++] = aOff + s; 6209 } 6210 } 6211 } 6212 } 6213 } 6214 else { 6215 ierr = PetscSectionGetDof(cSec,p,&dof);CHKERRQ(ierr); 6216 for (q = 0; q < dof; q++) { 6217 PetscInt rDof, rOff, r; 6218 ierr = PetscSectionGetDof(aSec,p,&rDof);CHKERRQ(ierr); 6219 ierr = PetscSectionGetOffset(aSec,p,&rOff);CHKERRQ(ierr); 6220 for (r = 0; r < rDof; r++) { 6221 PetscInt s; 6222 6223 a = anchors[rOff + r]; 6224 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 6225 ierr = PetscSectionGetOffset(section,a,&aOff);CHKERRQ(ierr); 6226 for (s = 0; s < aDof; s++) { 6227 j[offset++] = aOff + s; 6228 } 6229 } 6230 } 6231 } 6232 } 6233 ierr = MatSeqAIJSetPreallocationCSR(*cMat,i,j,NULL);CHKERRQ(ierr); 6234 ierr = PetscFree(i);CHKERRQ(ierr); 6235 ierr = PetscFree(j);CHKERRQ(ierr); 6236 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 6237 PetscFunctionReturn(0); 6238 } 6239 6240 #undef __FUNCT__ 6241 #define __FUNCT__ "DMCreateDefaultConstraints_Plex" 6242 PetscErrorCode DMCreateDefaultConstraints_Plex(DM dm) 6243 { 6244 DM_Plex *plex = (DM_Plex *)dm->data; 6245 PetscSection anchorSection, section, cSec; 6246 Mat cMat; 6247 PetscErrorCode ierr; 6248 6249 PetscFunctionBegin; 6250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 6251 ierr = DMPlexGetAnchors(dm,&anchorSection,NULL);CHKERRQ(ierr); 6252 if (anchorSection) { 6253 PetscDS ds; 6254 PetscInt nf; 6255 6256 ierr = DMGetDefaultSection(dm,§ion);CHKERRQ(ierr); 6257 ierr = DMPlexCreateConstraintSection_Anchors(dm,section,&cSec);CHKERRQ(ierr); 6258 ierr = DMPlexCreateConstraintMatrix_Anchors(dm,section,cSec,&cMat);CHKERRQ(ierr); 6259 ierr = DMGetDS(dm,&ds);CHKERRQ(ierr); 6260 ierr = PetscDSGetNumFields(ds,&nf);CHKERRQ(ierr); 6261 if (nf && plex->computeanchormatrix) {ierr = (*plex->computeanchormatrix)(dm,section,cSec,cMat);CHKERRQ(ierr);} 6262 ierr = DMSetDefaultConstraints(dm,cSec,cMat);CHKERRQ(ierr); 6263 ierr = PetscSectionDestroy(&cSec);CHKERRQ(ierr); 6264 ierr = MatDestroy(&cMat);CHKERRQ(ierr); 6265 } 6266 PetscFunctionReturn(0); 6267 } 6268