1 #include <petsc/private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 2 #include <petsc/private/isimpl.h> 3 #include <petscsf.h> 4 #include <petscds.h> 5 6 /* Logging support */ 7 PetscLogEvent DMPLEX_Interpolate, PETSCPARTITIONER_Partition, DMPLEX_Distribute, DMPLEX_DistributeCones, DMPLEX_DistributeLabels, DMPLEX_DistributeSF, DMPLEX_DistributeOverlap, DMPLEX_DistributeField, DMPLEX_DistributeData, DMPLEX_Migrate, DMPLEX_GlobalToNaturalBegin, DMPLEX_GlobalToNaturalEnd, DMPLEX_NaturalToGlobalBegin, DMPLEX_NaturalToGlobalEnd, DMPLEX_Stratify, DMPLEX_Preallocate, DMPLEX_ResidualFEM, DMPLEX_JacobianFEM, DMPLEX_InterpolatorFEM, DMPLEX_InjectorFEM, DMPLEX_IntegralFEM, DMPLEX_CreateGmsh; 8 9 PETSC_EXTERN PetscErrorCode VecView_Seq(Vec, PetscViewer); 10 PETSC_EXTERN PetscErrorCode VecView_MPI(Vec, PetscViewer); 11 PETSC_EXTERN PetscErrorCode VecLoad_Default(Vec, PetscViewer); 12 13 #undef __FUNCT__ 14 #define __FUNCT__ "DMPlexGetFieldType_Internal" 15 PetscErrorCode DMPlexGetFieldType_Internal(DM dm, PetscSection section, PetscInt field, PetscInt *sStart, PetscInt *sEnd, PetscViewerVTKFieldType *ft) 16 { 17 PetscInt dim, pStart, pEnd, vStart, vEnd, cStart, cEnd, cEndInterior, vdof = 0, cdof = 0; 18 PetscErrorCode ierr; 19 20 PetscFunctionBegin; 21 *ft = PETSC_VTK_POINT_FIELD; 22 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 23 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 24 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 25 ierr = DMPlexGetHybridBounds(dm, &cEndInterior, NULL, NULL, NULL);CHKERRQ(ierr); 26 cEnd = cEndInterior < 0 ? cEnd : cEndInterior; 27 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 28 if (field >= 0) { 29 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, vStart, field, &vdof);CHKERRQ(ierr);} 30 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetFieldDof(section, cStart, field, &cdof);CHKERRQ(ierr);} 31 } else { 32 if ((vStart >= pStart) && (vStart < pEnd)) {ierr = PetscSectionGetDof(section, vStart, &vdof);CHKERRQ(ierr);} 33 if ((cStart >= pStart) && (cStart < pEnd)) {ierr = PetscSectionGetDof(section, cStart, &cdof);CHKERRQ(ierr);} 34 } 35 if (vdof) { 36 *sStart = vStart; 37 *sEnd = vEnd; 38 if (vdof == dim) *ft = PETSC_VTK_POINT_VECTOR_FIELD; 39 else *ft = PETSC_VTK_POINT_FIELD; 40 } else if (cdof) { 41 *sStart = cStart; 42 *sEnd = cEnd; 43 if (cdof == dim) *ft = PETSC_VTK_CELL_VECTOR_FIELD; 44 else *ft = PETSC_VTK_CELL_FIELD; 45 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "Could not classify input Vec for VTK"); 46 PetscFunctionReturn(0); 47 } 48 49 #undef __FUNCT__ 50 #define __FUNCT__ "VecView_Plex_Local" 51 PetscErrorCode VecView_Plex_Local(Vec v, PetscViewer viewer) 52 { 53 DM dm; 54 PetscBool isvtk, ishdf5, isseq; 55 PetscErrorCode ierr; 56 57 PetscFunctionBegin; 58 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 59 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 60 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 61 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 62 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 63 if (isvtk || ishdf5) { 64 PetscInt numFields; 65 PetscBool fem = PETSC_FALSE; 66 67 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 68 if (numFields) { 69 PetscObject fe; 70 71 ierr = DMGetField(dm, 0, &fe);CHKERRQ(ierr); 72 if (fe->classid == PETSCFE_CLASSID) fem = PETSC_TRUE; 73 } 74 if (fem) {ierr = DMPlexInsertBoundaryValues(dm, v, 0.0, NULL, NULL, NULL);CHKERRQ(ierr);} 75 } 76 if (isvtk) { 77 PetscSection section; 78 PetscViewerVTKFieldType ft; 79 PetscInt pStart, pEnd; 80 81 ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr); 82 ierr = DMPlexGetFieldType_Internal(dm, section, PETSC_DETERMINE, &pStart, &pEnd, &ft);CHKERRQ(ierr); 83 ierr = PetscObjectReference((PetscObject) dm);CHKERRQ(ierr); /* viewer drops reference */ 84 ierr = PetscObjectReference((PetscObject) v);CHKERRQ(ierr); /* viewer drops reference */ 85 ierr = PetscViewerVTKAddField(viewer, (PetscObject) dm, DMPlexVTKWriteAll, ft, (PetscObject) v);CHKERRQ(ierr); 86 } else if (ishdf5) { 87 #if defined(PETSC_HAVE_HDF5) 88 ierr = VecView_Plex_Local_HDF5(v, viewer);CHKERRQ(ierr); 89 #else 90 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 91 #endif 92 } else { 93 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 94 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 95 } 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "VecView_Plex" 101 PetscErrorCode VecView_Plex(Vec v, PetscViewer viewer) 102 { 103 DM dm; 104 PetscBool isvtk, ishdf5, isseq; 105 PetscErrorCode ierr; 106 107 PetscFunctionBegin; 108 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 109 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 110 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 111 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 112 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 113 if (isvtk) { 114 Vec locv; 115 const char *name; 116 117 ierr = DMGetLocalVector(dm, &locv);CHKERRQ(ierr); 118 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 119 ierr = PetscObjectSetName((PetscObject) locv, name);CHKERRQ(ierr); 120 ierr = DMGlobalToLocalBegin(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 121 ierr = DMGlobalToLocalEnd(dm, v, INSERT_VALUES, locv);CHKERRQ(ierr); 122 ierr = VecView_Plex_Local(locv, viewer);CHKERRQ(ierr); 123 ierr = DMRestoreLocalVector(dm, &locv);CHKERRQ(ierr); 124 } else if (ishdf5) { 125 #if defined(PETSC_HAVE_HDF5) 126 ierr = VecView_Plex_HDF5(v, viewer);CHKERRQ(ierr); 127 #else 128 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 129 #endif 130 } else { 131 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 132 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 133 } 134 PetscFunctionReturn(0); 135 } 136 137 #undef __FUNCT__ 138 #define __FUNCT__ "VecView_Plex_Native" 139 PetscErrorCode VecView_Plex_Native(Vec originalv, PetscViewer viewer) 140 { 141 DM dm; 142 MPI_Comm comm; 143 PetscViewerFormat format; 144 Vec v; 145 PetscBool isvtk, ishdf5; 146 PetscErrorCode ierr; 147 148 PetscFunctionBegin; 149 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 150 ierr = PetscObjectGetComm((PetscObject) originalv, &comm);CHKERRQ(ierr); 151 if (!dm) SETERRQ(comm, PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 152 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 153 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 154 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 155 if (format == PETSC_VIEWER_NATIVE) { 156 const char *vecname; 157 PetscInt n, nroots; 158 159 if (dm->sfNatural) { 160 ierr = VecGetLocalSize(originalv, &n); 161 ierr = PetscSFGetGraph(dm->sfNatural, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 162 if (n == nroots) { 163 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 164 ierr = DMPlexGlobalToNaturalBegin(dm, originalv, v);CHKERRQ(ierr); 165 ierr = DMPlexGlobalToNaturalEnd(dm, originalv, v);CHKERRQ(ierr); 166 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 167 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 168 } else SETERRQ(comm, PETSC_ERR_ARG_WRONG, "DM global to natural SF only handles global vectors"); 169 } else SETERRQ(comm, PETSC_ERR_ARG_WRONGSTATE, "DM global to natural SF was not created"); 170 } else { 171 /* we are viewing a natural DMPlex vec. */ 172 v = originalv; 173 } 174 if (ishdf5) { 175 #if defined(PETSC_HAVE_HDF5) 176 ierr = VecView_Plex_HDF5_Native(v, viewer);CHKERRQ(ierr); 177 #else 178 SETERRQ(comm, PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 179 #endif 180 } else if (isvtk) { 181 SETERRQ(comm, PETSC_ERR_SUP, "VTK format does not support viewing in natural order. Please switch to HDF5."); 182 } else { 183 PetscBool isseq; 184 185 ierr = PetscObjectTypeCompare((PetscObject) v, VECSEQ, &isseq);CHKERRQ(ierr); 186 if (isseq) {ierr = VecView_Seq(v, viewer);CHKERRQ(ierr);} 187 else {ierr = VecView_MPI(v, viewer);CHKERRQ(ierr);} 188 } 189 if (format == PETSC_VIEWER_NATIVE) {ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr);} 190 PetscFunctionReturn(0); 191 } 192 193 #undef __FUNCT__ 194 #define __FUNCT__ "VecLoad_Plex_Local" 195 PetscErrorCode VecLoad_Plex_Local(Vec v, PetscViewer viewer) 196 { 197 DM dm; 198 PetscBool ishdf5; 199 PetscErrorCode ierr; 200 201 PetscFunctionBegin; 202 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 203 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 204 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 205 if (ishdf5) { 206 DM dmBC; 207 Vec gv; 208 const char *name; 209 210 ierr = DMGetOutputDM(dm, &dmBC);CHKERRQ(ierr); 211 ierr = DMGetGlobalVector(dmBC, &gv);CHKERRQ(ierr); 212 ierr = PetscObjectGetName((PetscObject) v, &name);CHKERRQ(ierr); 213 ierr = PetscObjectSetName((PetscObject) gv, name);CHKERRQ(ierr); 214 ierr = VecLoad_Default(gv, viewer);CHKERRQ(ierr); 215 ierr = DMGlobalToLocalBegin(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 216 ierr = DMGlobalToLocalEnd(dmBC, gv, INSERT_VALUES, v);CHKERRQ(ierr); 217 ierr = DMRestoreGlobalVector(dmBC, &gv);CHKERRQ(ierr); 218 } else { 219 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 220 } 221 PetscFunctionReturn(0); 222 } 223 224 #undef __FUNCT__ 225 #define __FUNCT__ "VecLoad_Plex" 226 PetscErrorCode VecLoad_Plex(Vec v, PetscViewer viewer) 227 { 228 DM dm; 229 PetscBool ishdf5; 230 PetscErrorCode ierr; 231 232 PetscFunctionBegin; 233 ierr = VecGetDM(v, &dm);CHKERRQ(ierr); 234 if (!dm) SETERRQ(PetscObjectComm((PetscObject)v), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 235 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 236 if (ishdf5) { 237 #if defined(PETSC_HAVE_HDF5) 238 ierr = VecLoad_Plex_HDF5(v, viewer);CHKERRQ(ierr); 239 #else 240 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 241 #endif 242 } else { 243 ierr = VecLoad_Default(v, viewer);CHKERRQ(ierr); 244 } 245 PetscFunctionReturn(0); 246 } 247 248 #undef __FUNCT__ 249 #define __FUNCT__ "VecLoad_Plex_Native" 250 PetscErrorCode VecLoad_Plex_Native(Vec originalv, PetscViewer viewer) 251 { 252 DM dm; 253 PetscViewerFormat format; 254 PetscBool ishdf5; 255 PetscErrorCode ierr; 256 257 PetscFunctionBegin; 258 ierr = VecGetDM(originalv, &dm);CHKERRQ(ierr); 259 if (!dm) SETERRQ(PetscObjectComm((PetscObject) originalv), PETSC_ERR_ARG_WRONG, "Vector not generated from a DM"); 260 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 261 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERHDF5, &ishdf5);CHKERRQ(ierr); 262 if (format == PETSC_VIEWER_NATIVE) { 263 if (dm->sfNatural) { 264 if (ishdf5) { 265 #if defined(PETSC_HAVE_HDF5) 266 Vec v; 267 const char *vecname; 268 269 ierr = DMGetGlobalVector(dm, &v);CHKERRQ(ierr); 270 ierr = PetscObjectGetName((PetscObject) originalv, &vecname);CHKERRQ(ierr); 271 ierr = PetscObjectSetName((PetscObject) v, vecname);CHKERRQ(ierr); 272 ierr = VecLoad_Plex_HDF5_Native(v, viewer);CHKERRQ(ierr); 273 ierr = DMPlexNaturalToGlobalBegin(dm, v, originalv);CHKERRQ(ierr); 274 ierr = DMPlexNaturalToGlobalEnd(dm, v, originalv);CHKERRQ(ierr); 275 ierr = DMRestoreGlobalVector(dm, &v);CHKERRQ(ierr); 276 #else 277 SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "HDF5 not supported in this build.\nPlease reconfigure using --download-hdf5"); 278 #endif 279 } else SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_SUP, "Reading in natural order is not supported for anything but HDF5."); 280 } 281 } 282 PetscFunctionReturn(0); 283 } 284 285 #undef __FUNCT__ 286 #define __FUNCT__ "DMPlexView_Ascii_Geometry" 287 PetscErrorCode DMPlexView_Ascii_Geometry(DM dm, PetscViewer viewer) 288 { 289 PetscSection coordSection; 290 Vec coordinates; 291 DMLabel depthLabel; 292 const char *name[4]; 293 const PetscScalar *a; 294 PetscInt dim, pStart, pEnd, cStart, cEnd, c; 295 PetscErrorCode ierr; 296 297 PetscFunctionBegin; 298 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 299 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 300 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 301 ierr = DMPlexGetDepthLabel(dm, &depthLabel);CHKERRQ(ierr); 302 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 303 ierr = PetscSectionGetChart(coordSection, &pStart, &pEnd);CHKERRQ(ierr); 304 ierr = VecGetArrayRead(coordinates, &a);CHKERRQ(ierr); 305 name[0] = "vertex"; 306 name[1] = "edge"; 307 name[dim-1] = "face"; 308 name[dim] = "cell"; 309 for (c = cStart; c < cEnd; ++c) { 310 PetscInt *closure = NULL; 311 PetscInt closureSize, cl; 312 313 ierr = PetscViewerASCIIPrintf(viewer, "Geometry for cell %D:\n", c);CHKERRQ(ierr); 314 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 315 ierr = PetscViewerASCIIPushTab(viewer);CHKERRQ(ierr); 316 for (cl = 0; cl < closureSize*2; cl += 2) { 317 PetscInt point = closure[cl], depth, dof, off, d, p; 318 319 if ((point < pStart) || (point >= pEnd)) continue; 320 ierr = PetscSectionGetDof(coordSection, point, &dof);CHKERRQ(ierr); 321 if (!dof) continue; 322 ierr = DMLabelGetValue(depthLabel, point, &depth);CHKERRQ(ierr); 323 ierr = PetscSectionGetOffset(coordSection, point, &off);CHKERRQ(ierr); 324 ierr = PetscViewerASCIIPrintf(viewer, "%s %D coords:", name[depth], point);CHKERRQ(ierr); 325 for (p = 0; p < dof/dim; ++p) { 326 ierr = PetscViewerASCIIPrintf(viewer, " (");CHKERRQ(ierr); 327 for (d = 0; d < dim; ++d) { 328 if (d > 0) {ierr = PetscViewerASCIIPrintf(viewer, ", ");CHKERRQ(ierr);} 329 ierr = PetscViewerASCIIPrintf(viewer, "%g", PetscRealPart(a[off+p*dim+d]));CHKERRQ(ierr); 330 } 331 ierr = PetscViewerASCIIPrintf(viewer, ")");CHKERRQ(ierr); 332 } 333 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 334 } 335 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 336 ierr = PetscViewerASCIIPopTab(viewer);CHKERRQ(ierr); 337 } 338 ierr = VecRestoreArrayRead(coordinates, &a);CHKERRQ(ierr); 339 PetscFunctionReturn(0); 340 } 341 342 #undef __FUNCT__ 343 #define __FUNCT__ "DMPlexView_Ascii" 344 PetscErrorCode DMPlexView_Ascii(DM dm, PetscViewer viewer) 345 { 346 DM_Plex *mesh = (DM_Plex*) dm->data; 347 DM cdm; 348 DMLabel markers; 349 PetscSection coordSection; 350 Vec coordinates; 351 PetscViewerFormat format; 352 PetscErrorCode ierr; 353 354 PetscFunctionBegin; 355 ierr = DMGetCoordinateDM(dm, &cdm);CHKERRQ(ierr); 356 ierr = DMGetDefaultSection(cdm, &coordSection);CHKERRQ(ierr); 357 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 358 ierr = PetscViewerGetFormat(viewer, &format);CHKERRQ(ierr); 359 if (format == PETSC_VIEWER_ASCII_INFO_DETAIL) { 360 const char *name; 361 PetscInt maxConeSize, maxSupportSize; 362 PetscInt pStart, pEnd, p; 363 PetscMPIInt rank, size; 364 365 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 366 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 367 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 368 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 369 ierr = DMPlexGetMaxSizes(dm, &maxConeSize, &maxSupportSize);CHKERRQ(ierr); 370 ierr = PetscViewerASCIIPrintf(viewer, "Mesh '%s':\n", name);CHKERRQ(ierr); 371 ierr = PetscViewerASCIIPrintf(viewer, "orientation is missing\n", name);CHKERRQ(ierr); 372 ierr = PetscViewerASCIIPrintf(viewer, "cap --> base:\n", name);CHKERRQ(ierr); 373 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 374 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d] Max sizes cone: %D support: %D\n", rank,maxConeSize, maxSupportSize);CHKERRQ(ierr); 375 for (p = pStart; p < pEnd; ++p) { 376 PetscInt dof, off, s; 377 378 ierr = PetscSectionGetDof(mesh->supportSection, p, &dof);CHKERRQ(ierr); 379 ierr = PetscSectionGetOffset(mesh->supportSection, p, &off);CHKERRQ(ierr); 380 for (s = off; s < off+dof; ++s) { 381 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D ----> %D\n", rank, p, mesh->supports[s]);CHKERRQ(ierr); 382 } 383 } 384 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 385 ierr = PetscViewerASCIIPrintf(viewer, "base <-- cap:\n", name);CHKERRQ(ierr); 386 for (p = pStart; p < pEnd; ++p) { 387 PetscInt dof, off, c; 388 389 ierr = PetscSectionGetDof(mesh->coneSection, p, &dof);CHKERRQ(ierr); 390 ierr = PetscSectionGetOffset(mesh->coneSection, p, &off);CHKERRQ(ierr); 391 for (c = off; c < off+dof; ++c) { 392 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "[%d]: %D <---- %D (%D)\n", rank, p, mesh->cones[c], mesh->coneOrientations[c]);CHKERRQ(ierr); 393 } 394 } 395 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 396 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 397 ierr = PetscSectionGetChart(coordSection, &pStart, NULL);CHKERRQ(ierr); 398 if (pStart >= 0) {ierr = PetscSectionVecView(coordSection, coordinates, viewer);CHKERRQ(ierr);} 399 ierr = DMPlexGetLabel(dm, "marker", &markers);CHKERRQ(ierr); 400 ierr = DMLabelView(markers,viewer);CHKERRQ(ierr); 401 if (size > 1) { 402 PetscSF sf; 403 404 ierr = DMGetPointSF(dm, &sf);CHKERRQ(ierr); 405 ierr = PetscSFView(sf, viewer);CHKERRQ(ierr); 406 } 407 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 408 } else if (format == PETSC_VIEWER_ASCII_LATEX) { 409 const char *name, *color; 410 const char *defcolors[3] = {"gray", "orange", "green"}; 411 const char *deflcolors[4] = {"blue", "cyan", "red", "magenta"}; 412 PetscReal scale = 2.0; 413 PetscBool useNumbers = PETSC_TRUE, useLabels, useColors; 414 double tcoords[3]; 415 PetscScalar *coords; 416 PetscInt numLabels, l, numColors, numLColors, dim, depth, cStart, cEnd, c, vStart, vEnd, v, eStart = 0, eEnd = 0, e, p; 417 PetscMPIInt rank, size; 418 char **names, **colors, **lcolors; 419 420 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 421 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 422 ierr = DMPlexGetNumLabels(dm, &numLabels);CHKERRQ(ierr); 423 numLabels = PetscMax(numLabels, 10); 424 numColors = 10; 425 numLColors = 10; 426 ierr = PetscCalloc3(numLabels, &names, numColors, &colors, numLColors, &lcolors);CHKERRQ(ierr); 427 ierr = PetscOptionsGetReal(((PetscObject) viewer)->prefix, "-dm_plex_view_scale", &scale, NULL);CHKERRQ(ierr); 428 ierr = PetscOptionsGetBool(((PetscObject) viewer)->prefix, "-dm_plex_view_numbers", &useNumbers, NULL);CHKERRQ(ierr); 429 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_labels", names, &numLabels, &useLabels);CHKERRQ(ierr); 430 if (!useLabels) numLabels = 0; 431 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_colors", colors, &numColors, &useColors);CHKERRQ(ierr); 432 if (!useColors) { 433 numColors = 3; 434 for (c = 0; c < numColors; ++c) {ierr = PetscStrallocpy(defcolors[c], &colors[c]);CHKERRQ(ierr);} 435 } 436 ierr = PetscOptionsGetStringArray(((PetscObject) viewer)->prefix, "-dm_plex_view_lcolors", lcolors, &numLColors, &useColors);CHKERRQ(ierr); 437 if (!useColors) { 438 numLColors = 4; 439 for (c = 0; c < numLColors; ++c) {ierr = PetscStrallocpy(deflcolors[c], &lcolors[c]);CHKERRQ(ierr);} 440 } 441 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank);CHKERRQ(ierr); 442 ierr = MPI_Comm_size(PetscObjectComm((PetscObject)dm), &size);CHKERRQ(ierr); 443 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 444 ierr = PetscViewerASCIIPrintf(viewer, "\ 445 \\documentclass[tikz]{standalone}\n\n\ 446 \\usepackage{pgflibraryshapes}\n\ 447 \\usetikzlibrary{backgrounds}\n\ 448 \\usetikzlibrary{arrows}\n\ 449 \\begin{document}\n");CHKERRQ(ierr); 450 if (size > 1) { 451 ierr = PetscViewerASCIIPrintf(viewer, "%s for process ", name);CHKERRQ(ierr); 452 for (p = 0; p < size; ++p) { 453 if (p > 0 && p == size-1) { 454 ierr = PetscViewerASCIIPrintf(viewer, ", and ", colors[p%numColors], p);CHKERRQ(ierr); 455 } else if (p > 0) { 456 ierr = PetscViewerASCIIPrintf(viewer, ", ", colors[p%numColors], p);CHKERRQ(ierr); 457 } 458 ierr = PetscViewerASCIIPrintf(viewer, "{\\textcolor{%s}%D}", colors[p%numColors], p);CHKERRQ(ierr); 459 } 460 ierr = PetscViewerASCIIPrintf(viewer, ".\n\n\n");CHKERRQ(ierr); 461 } 462 ierr = PetscViewerASCIIPrintf(viewer, "\\begin{tikzpicture}[scale = %g,font=\\fontsize{8}{8}\\selectfont]\n", 1.0);CHKERRQ(ierr); 463 /* Plot vertices */ 464 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 465 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 466 ierr = PetscViewerASCIIPushSynchronized(viewer);CHKERRQ(ierr); 467 for (v = vStart; v < vEnd; ++v) { 468 PetscInt off, dof, d; 469 PetscBool isLabeled = PETSC_FALSE; 470 471 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 472 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 473 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\path (");CHKERRQ(ierr); 474 if (PetscUnlikely(dof > 3)) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB,"coordSection vertex %D has dof %D > 3",v,dof); 475 for (d = 0; d < dof; ++d) { 476 tcoords[d] = (double) (scale*PetscRealPart(coords[off+d])); 477 tcoords[d] = PetscAbsReal(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 478 } 479 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 480 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 481 for (d = 0; d < dof; ++d) { 482 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 483 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", tcoords[d]);CHKERRQ(ierr); 484 } 485 color = colors[rank%numColors]; 486 for (l = 0; l < numLabels; ++l) { 487 PetscInt val; 488 ierr = DMPlexGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 489 if (val >= 0) {color = lcolors[l%numLColors]; isLabeled = PETSC_TRUE; break;} 490 } 491 if (useNumbers) { 492 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D};\n", v, rank, color, v);CHKERRQ(ierr); 493 } else { 494 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [fill,inner sep=%dpt,shape=circle,color=%s] {};\n", v, rank, !isLabeled ? 1 : 2, color);CHKERRQ(ierr); 495 } 496 } 497 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 498 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 499 /* Plot edges */ 500 if (depth > 1) {ierr = DMPlexGetDepthStratum(dm, 1, &eStart, &eEnd);CHKERRQ(ierr);} 501 if (dim < 3 && useNumbers) { 502 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 503 ierr = PetscViewerASCIIPrintf(viewer, "\\path\n");CHKERRQ(ierr); 504 for (e = eStart; e < eEnd; ++e) { 505 const PetscInt *cone; 506 PetscInt coneSize, offA, offB, dof, d; 507 508 ierr = DMPlexGetConeSize(dm, e, &coneSize);CHKERRQ(ierr); 509 if (coneSize != 2) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Edge %D cone should have two vertices, not %D", e, coneSize); 510 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 511 ierr = PetscSectionGetDof(coordSection, cone[0], &dof);CHKERRQ(ierr); 512 ierr = PetscSectionGetOffset(coordSection, cone[0], &offA);CHKERRQ(ierr); 513 ierr = PetscSectionGetOffset(coordSection, cone[1], &offB);CHKERRQ(ierr); 514 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(");CHKERRQ(ierr); 515 for (d = 0; d < dof; ++d) { 516 tcoords[d] = (double) (scale*PetscRealPart(coords[offA+d]+coords[offB+d])); 517 tcoords[d] = PetscAbsReal(tcoords[d]) < 1e-10 ? 0.0 : tcoords[d]; 518 } 519 /* Rotate coordinates since PGF makes z point out of the page instead of up */ 520 if (dim == 3) {PetscReal tmp = tcoords[1]; tcoords[1] = tcoords[2]; tcoords[2] = -tmp;} 521 for (d = 0; d < dof; ++d) { 522 if (d > 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, ",");CHKERRQ(ierr);} 523 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "%g", (double)tcoords[d]);CHKERRQ(ierr); 524 } 525 color = colors[rank%numColors]; 526 for (l = 0; l < numLabels; ++l) { 527 PetscInt val; 528 ierr = DMPlexGetLabelValue(dm, names[l], v, &val);CHKERRQ(ierr); 529 if (val >= 0) {color = lcolors[l%numLColors]; break;} 530 } 531 ierr = PetscViewerASCIISynchronizedPrintf(viewer, ") node(%D_%d) [draw,shape=circle,color=%s] {%D} --\n", e, rank, color, e);CHKERRQ(ierr); 532 } 533 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 534 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 535 ierr = PetscViewerASCIIPrintf(viewer, "(0,0);\n");CHKERRQ(ierr); 536 } 537 /* Plot cells */ 538 if (dim == 3 || !useNumbers) { 539 for (e = eStart; e < eEnd; ++e) { 540 const PetscInt *cone; 541 542 color = colors[rank%numColors]; 543 for (l = 0; l < numLabels; ++l) { 544 PetscInt val; 545 ierr = DMPlexGetLabelValue(dm, names[l], e, &val);CHKERRQ(ierr); 546 if (val >= 0) {color = lcolors[l%numLColors]; break;} 547 } 548 ierr = DMPlexGetCone(dm, e, &cone);CHKERRQ(ierr); 549 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] (%D_%d) -- (%D_%d);\n", color, cone[0], rank, cone[1], rank);CHKERRQ(ierr); 550 } 551 } else { 552 ierr = DMPlexGetHeightStratum(dm, 0, &cStart, &cEnd);CHKERRQ(ierr); 553 for (c = cStart; c < cEnd; ++c) { 554 PetscInt *closure = NULL; 555 PetscInt closureSize, firstPoint = -1; 556 557 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 558 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "\\draw[color=%s] ", colors[rank%numColors]);CHKERRQ(ierr); 559 for (p = 0; p < closureSize*2; p += 2) { 560 const PetscInt point = closure[p]; 561 562 if ((point < vStart) || (point >= vEnd)) continue; 563 if (firstPoint >= 0) {ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- ");CHKERRQ(ierr);} 564 ierr = PetscViewerASCIISynchronizedPrintf(viewer, "(%D_%d)", point, rank);CHKERRQ(ierr); 565 if (firstPoint < 0) firstPoint = point; 566 } 567 /* Why doesn't this work? ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- cycle;\n");CHKERRQ(ierr); */ 568 ierr = PetscViewerASCIISynchronizedPrintf(viewer, " -- (%D_%d);\n", firstPoint, rank);CHKERRQ(ierr); 569 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 570 } 571 } 572 ierr = PetscViewerFlush(viewer);CHKERRQ(ierr); 573 ierr = PetscViewerASCIIPopSynchronized(viewer);CHKERRQ(ierr); 574 ierr = PetscViewerASCIIPrintf(viewer, "\\end{tikzpicture}\n");CHKERRQ(ierr); 575 ierr = PetscViewerASCIIPrintf(viewer, "\\end{document}\n", name);CHKERRQ(ierr); 576 for (l = 0; l < numLabels; ++l) {ierr = PetscFree(names[l]);CHKERRQ(ierr);} 577 for (c = 0; c < numColors; ++c) {ierr = PetscFree(colors[c]);CHKERRQ(ierr);} 578 for (c = 0; c < numLColors; ++c) {ierr = PetscFree(lcolors[c]);CHKERRQ(ierr);} 579 ierr = PetscFree3(names, colors, lcolors);CHKERRQ(ierr); 580 } else { 581 MPI_Comm comm; 582 PetscInt *sizes, *hybsizes; 583 PetscInt locDepth, depth, dim, d, pMax[4]; 584 PetscInt pStart, pEnd, p; 585 PetscInt numLabels, l; 586 const char *name; 587 PetscMPIInt size; 588 589 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 590 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 591 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 592 ierr = PetscObjectGetName((PetscObject) dm, &name);CHKERRQ(ierr); 593 if (name) {ierr = PetscViewerASCIIPrintf(viewer, "%s in %D dimensions:\n", name, dim);CHKERRQ(ierr);} 594 else {ierr = PetscViewerASCIIPrintf(viewer, "Mesh in %D dimensions:\n", dim);CHKERRQ(ierr);} 595 ierr = DMPlexGetDepth(dm, &locDepth);CHKERRQ(ierr); 596 ierr = 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 = PetscObjectSetName((PetscObject)cVec,"coordinates");CHKERRQ(ierr); 2745 ierr = VecGetBlockSize(coordinates, &bs);CHKERRQ(ierr); 2746 ierr = VecSetBlockSize(cVec, bs);CHKERRQ(ierr); 2747 ierr = VecSetSizes(cVec, coordSize, PETSC_DETERMINE);CHKERRQ(ierr); 2748 ierr = VecSetType(cVec,VECSTANDARD);CHKERRQ(ierr); 2749 ierr = VecGetArray(coordinates, &coords);CHKERRQ(ierr); 2750 ierr = VecGetArray(cVec, &coords2);CHKERRQ(ierr); 2751 for (v = vStart; v < vEnd; ++v) { 2752 ierr = PetscSectionGetDof(coordSection, v, &dof);CHKERRQ(ierr); 2753 ierr = PetscSectionGetOffset(coordSection, v, &off);CHKERRQ(ierr); 2754 ierr = PetscSectionGetOffset(cSection, v, &off2);CHKERRQ(ierr); 2755 for (d = 0; d < dof; ++d) coords2[off2+d] = coords[off+d]; 2756 } 2757 ierr = DMGetWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2758 for (c = cStart; c < cEnd; ++c) { 2759 PetscScalar *cellCoords = NULL; 2760 PetscInt b; 2761 2762 ierr = DMPlexVecGetClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2763 ierr = PetscSectionGetOffset(cSection, c, &off2);CHKERRQ(ierr); 2764 for (b = 0; b < bs; ++b) anchor[b] = cellCoords[b]; 2765 for (d = 0; d < dof/bs; ++d) {ierr = DMPlexLocalizeCoordinate_Internal(dm, bs, anchor, &cellCoords[d*bs], &coords2[off2+d*bs]);CHKERRQ(ierr);} 2766 ierr = DMPlexVecRestoreClosure(dm, coordSection, coordinates, c, &dof, &cellCoords);CHKERRQ(ierr); 2767 } 2768 ierr = DMRestoreWorkArray(dm, 3, PETSC_SCALAR, &anchor);CHKERRQ(ierr); 2769 ierr = VecRestoreArray(coordinates, &coords);CHKERRQ(ierr); 2770 ierr = VecRestoreArray(cVec, &coords2);CHKERRQ(ierr); 2771 ierr = DMSetCoordinateSection(dm, PETSC_DETERMINE, cSection);CHKERRQ(ierr); 2772 ierr = DMSetCoordinatesLocal(dm, cVec);CHKERRQ(ierr); 2773 ierr = VecDestroy(&cVec);CHKERRQ(ierr); 2774 ierr = PetscSectionDestroy(&cSection);CHKERRQ(ierr); 2775 PetscFunctionReturn(0); 2776 } 2777 2778 #undef __FUNCT__ 2779 #define __FUNCT__ "DMPlexGetDepthLabel" 2780 /*@ 2781 DMPlexGetDepthLabel - Get the DMLabel recording the depth of each point 2782 2783 Not Collective 2784 2785 Input Parameter: 2786 . dm - The DMPlex object 2787 2788 Output Parameter: 2789 . depthLabel - The DMLabel recording point depth 2790 2791 Level: developer 2792 2793 .keywords: mesh, points 2794 .seealso: DMPlexGetDepth(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2795 @*/ 2796 PetscErrorCode DMPlexGetDepthLabel(DM dm, DMLabel *depthLabel) 2797 { 2798 DM_Plex *mesh = (DM_Plex*) dm->data; 2799 PetscErrorCode ierr; 2800 2801 PetscFunctionBegin; 2802 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2803 PetscValidPointer(depthLabel, 2); 2804 if (!mesh->depthLabel) {ierr = DMPlexGetLabel(dm, "depth", &mesh->depthLabel);CHKERRQ(ierr);} 2805 *depthLabel = mesh->depthLabel; 2806 PetscFunctionReturn(0); 2807 } 2808 2809 #undef __FUNCT__ 2810 #define __FUNCT__ "DMPlexGetDepth" 2811 /*@ 2812 DMPlexGetDepth - Get the depth of the DAG representing this mesh 2813 2814 Not Collective 2815 2816 Input Parameter: 2817 . dm - The DMPlex object 2818 2819 Output Parameter: 2820 . depth - The number of strata (breadth first levels) in the DAG 2821 2822 Level: developer 2823 2824 .keywords: mesh, points 2825 .seealso: DMPlexGetDepthLabel(), DMPlexGetHeightStratum(), DMPlexGetDepthStratum() 2826 @*/ 2827 PetscErrorCode DMPlexGetDepth(DM dm, PetscInt *depth) 2828 { 2829 DMLabel label; 2830 PetscInt d = 0; 2831 PetscErrorCode ierr; 2832 2833 PetscFunctionBegin; 2834 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2835 PetscValidPointer(depth, 2); 2836 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2837 if (label) {ierr = DMLabelGetNumValues(label, &d);CHKERRQ(ierr);} 2838 *depth = d-1; 2839 PetscFunctionReturn(0); 2840 } 2841 2842 #undef __FUNCT__ 2843 #define __FUNCT__ "DMPlexGetDepthStratum" 2844 /*@ 2845 DMPlexGetDepthStratum - Get the bounds [start, end) for all points at a certain depth. 2846 2847 Not Collective 2848 2849 Input Parameters: 2850 + dm - The DMPlex object 2851 - stratumValue - The requested depth 2852 2853 Output Parameters: 2854 + start - The first point at this depth 2855 - end - One beyond the last point at this depth 2856 2857 Level: developer 2858 2859 .keywords: mesh, points 2860 .seealso: DMPlexGetHeightStratum(), DMPlexGetDepth() 2861 @*/ 2862 PetscErrorCode DMPlexGetDepthStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2863 { 2864 DMLabel label; 2865 PetscInt pStart, pEnd; 2866 PetscErrorCode ierr; 2867 2868 PetscFunctionBegin; 2869 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2870 if (start) {PetscValidPointer(start, 3); *start = 0;} 2871 if (end) {PetscValidPointer(end, 4); *end = 0;} 2872 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2873 if (pStart == pEnd) PetscFunctionReturn(0); 2874 if (stratumValue < 0) { 2875 if (start) *start = pStart; 2876 if (end) *end = pEnd; 2877 PetscFunctionReturn(0); 2878 } 2879 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2880 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found"); 2881 ierr = DMLabelGetStratumBounds(label, stratumValue, start, end);CHKERRQ(ierr); 2882 PetscFunctionReturn(0); 2883 } 2884 2885 #undef __FUNCT__ 2886 #define __FUNCT__ "DMPlexGetHeightStratum" 2887 /*@ 2888 DMPlexGetHeightStratum - Get the bounds [start, end) for all points at a certain height. 2889 2890 Not Collective 2891 2892 Input Parameters: 2893 + dm - The DMPlex object 2894 - stratumValue - The requested height 2895 2896 Output Parameters: 2897 + start - The first point at this height 2898 - end - One beyond the last point at this height 2899 2900 Level: developer 2901 2902 .keywords: mesh, points 2903 .seealso: DMPlexGetDepthStratum(), DMPlexGetDepth() 2904 @*/ 2905 PetscErrorCode DMPlexGetHeightStratum(DM dm, PetscInt stratumValue, PetscInt *start, PetscInt *end) 2906 { 2907 DMLabel label; 2908 PetscInt depth, pStart, pEnd; 2909 PetscErrorCode ierr; 2910 2911 PetscFunctionBegin; 2912 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 2913 if (start) {PetscValidPointer(start, 3); *start = 0;} 2914 if (end) {PetscValidPointer(end, 4); *end = 0;} 2915 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2916 if (pStart == pEnd) PetscFunctionReturn(0); 2917 if (stratumValue < 0) { 2918 if (start) *start = pStart; 2919 if (end) *end = pEnd; 2920 PetscFunctionReturn(0); 2921 } 2922 ierr = DMPlexGetDepthLabel(dm, &label);CHKERRQ(ierr); 2923 if (!label) SETERRQ(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_WRONG, "No label named depth was found");CHKERRQ(ierr); 2924 ierr = DMLabelGetNumValues(label, &depth);CHKERRQ(ierr); 2925 ierr = DMLabelGetStratumBounds(label, depth-1-stratumValue, start, end);CHKERRQ(ierr); 2926 PetscFunctionReturn(0); 2927 } 2928 2929 #undef __FUNCT__ 2930 #define __FUNCT__ "DMPlexCreateSectionInitial" 2931 /* Set the number of dof on each point and separate by fields */ 2932 PetscErrorCode DMPlexCreateSectionInitial(DM dm, PetscInt dim, PetscInt numFields,const PetscInt numComp[],const PetscInt numDof[], PetscSection *section) 2933 { 2934 PetscInt *pMax; 2935 PetscInt depth, pStart = 0, pEnd = 0; 2936 PetscInt Nf, p, d, dep, f; 2937 PetscBool *isFE; 2938 PetscErrorCode ierr; 2939 2940 PetscFunctionBegin; 2941 ierr = PetscMalloc1(numFields, &isFE);CHKERRQ(ierr); 2942 ierr = DMGetNumFields(dm, &Nf);CHKERRQ(ierr); 2943 for (f = 0; f < numFields; ++f) { 2944 PetscObject obj; 2945 PetscClassId id; 2946 2947 isFE[f] = PETSC_FALSE; 2948 if (f >= Nf) continue; 2949 ierr = DMGetField(dm, f, &obj);CHKERRQ(ierr); 2950 ierr = PetscObjectGetClassId(obj, &id);CHKERRQ(ierr); 2951 if (id == PETSCFE_CLASSID) {isFE[f] = PETSC_TRUE;} 2952 else if (id == PETSCFV_CLASSID) {isFE[f] = PETSC_FALSE;} 2953 } 2954 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), section);CHKERRQ(ierr); 2955 if (numFields > 0) { 2956 ierr = PetscSectionSetNumFields(*section, numFields);CHKERRQ(ierr); 2957 if (numComp) { 2958 for (f = 0; f < numFields; ++f) { 2959 ierr = PetscSectionSetFieldComponents(*section, f, numComp[f]);CHKERRQ(ierr); 2960 } 2961 } 2962 } 2963 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 2964 ierr = PetscSectionSetChart(*section, pStart, pEnd);CHKERRQ(ierr); 2965 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 2966 ierr = PetscMalloc1(depth+1,&pMax);CHKERRQ(ierr); 2967 ierr = DMPlexGetHybridBounds(dm, depth >= 0 ? &pMax[depth] : NULL, depth>1 ? &pMax[depth-1] : NULL, depth>2 ? &pMax[1] : NULL, &pMax[0]);CHKERRQ(ierr); 2968 for (dep = 0; dep <= depth; ++dep) { 2969 d = dim == depth ? dep : (!dep ? 0 : dim); 2970 ierr = DMPlexGetDepthStratum(dm, dep, &pStart, &pEnd);CHKERRQ(ierr); 2971 pMax[dep] = pMax[dep] < 0 ? pEnd : pMax[dep]; 2972 for (p = pStart; p < pEnd; ++p) { 2973 PetscInt tot = 0; 2974 2975 for (f = 0; f < numFields; ++f) { 2976 if (isFE[f] && p >= pMax[dep]) continue; 2977 ierr = PetscSectionSetFieldDof(*section, p, f, numDof[f*(dim+1)+d]);CHKERRQ(ierr); 2978 tot += numDof[f*(dim+1)+d]; 2979 } 2980 ierr = PetscSectionSetDof(*section, p, tot);CHKERRQ(ierr); 2981 } 2982 } 2983 ierr = PetscFree(pMax);CHKERRQ(ierr); 2984 ierr = PetscFree(isFE);CHKERRQ(ierr); 2985 PetscFunctionReturn(0); 2986 } 2987 2988 #undef __FUNCT__ 2989 #define __FUNCT__ "DMPlexCreateSectionBCDof" 2990 /* Set the number of dof on each point and separate by fields 2991 If bcComps is NULL or the IS is NULL, constrain every dof on the point 2992 */ 2993 PetscErrorCode DMPlexCreateSectionBCDof(DM dm, PetscInt numBC, const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 2994 { 2995 PetscInt numFields; 2996 PetscInt bc; 2997 PetscSection aSec; 2998 PetscErrorCode ierr; 2999 3000 PetscFunctionBegin; 3001 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3002 for (bc = 0; bc < numBC; ++bc) { 3003 PetscInt field = 0; 3004 const PetscInt *comp; 3005 const PetscInt *idx; 3006 PetscInt Nc = -1, n, i; 3007 3008 if (numFields) field = bcField[bc]; 3009 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3010 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3011 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3012 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3013 for (i = 0; i < n; ++i) { 3014 const PetscInt p = idx[i]; 3015 PetscInt numConst; 3016 3017 if (numFields) { 3018 ierr = PetscSectionGetFieldDof(section, p, field, &numConst);CHKERRQ(ierr); 3019 } else { 3020 ierr = PetscSectionGetDof(section, p, &numConst);CHKERRQ(ierr); 3021 } 3022 /* If Nc < 0, constrain every dof on the point */ 3023 if (Nc > 0) numConst = PetscMin(numConst, Nc); 3024 if (numFields) {ierr = PetscSectionAddFieldConstraintDof(section, p, field, numConst);CHKERRQ(ierr);} 3025 ierr = PetscSectionAddConstraintDof(section, p, numConst);CHKERRQ(ierr); 3026 } 3027 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3028 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3029 } 3030 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3031 if (aSec) { 3032 PetscInt aStart, aEnd, a; 3033 3034 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3035 for (a = aStart; a < aEnd; a++) { 3036 PetscInt dof, f; 3037 3038 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3039 if (dof) { 3040 /* if there are point-to-point constraints, then all dofs are constrained */ 3041 ierr = PetscSectionGetDof(section, a, &dof);CHKERRQ(ierr); 3042 ierr = PetscSectionSetConstraintDof(section, a, dof);CHKERRQ(ierr); 3043 for (f = 0; f < numFields; f++) { 3044 ierr = PetscSectionGetFieldDof(section, a, f, &dof);CHKERRQ(ierr); 3045 ierr = PetscSectionSetFieldConstraintDof(section, a, f, dof);CHKERRQ(ierr); 3046 } 3047 } 3048 } 3049 } 3050 PetscFunctionReturn(0); 3051 } 3052 3053 #undef __FUNCT__ 3054 #define __FUNCT__ "DMPlexCreateSectionBCIndicesField" 3055 /* Set the constrained field indices on each point 3056 If bcComps is NULL or the IS is NULL, constrain every dof on the point 3057 */ 3058 PetscErrorCode DMPlexCreateSectionBCIndicesField(DM dm, PetscInt numBC,const PetscInt bcField[], const IS bcComps[], const IS bcPoints[], PetscSection section) 3059 { 3060 PetscSection aSec; 3061 PetscInt *indices; 3062 PetscInt numFields, maxDof, pStart, pEnd, p, bc, f, d; 3063 PetscErrorCode ierr; 3064 3065 PetscFunctionBegin; 3066 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3067 if (!numFields) PetscFunctionReturn(0); 3068 /* Initialize all field indices to -1 */ 3069 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3070 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3071 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3072 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3073 for (p = pStart; p < pEnd; ++p) for (f = 0; f < numFields; ++f) {ierr = PetscSectionSetFieldConstraintIndices(section, p, f, indices);CHKERRQ(ierr);} 3074 /* Handle BC constraints */ 3075 for (bc = 0; bc < numBC; ++bc) { 3076 const PetscInt field = bcField[bc]; 3077 const PetscInt *comp, *idx; 3078 PetscInt Nc = -1, n, i; 3079 3080 if (bcComps && bcComps[bc]) {ierr = ISGetLocalSize(bcComps[bc], &Nc);CHKERRQ(ierr);} 3081 if (bcComps && bcComps[bc]) {ierr = ISGetIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3082 ierr = ISGetLocalSize(bcPoints[bc], &n);CHKERRQ(ierr); 3083 ierr = ISGetIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3084 for (i = 0; i < n; ++i) { 3085 const PetscInt p = idx[i]; 3086 const PetscInt *find; 3087 PetscInt fcdof, c; 3088 3089 ierr = PetscSectionGetFieldConstraintDof(section, p, field, &fcdof);CHKERRQ(ierr); 3090 if (Nc < 0) { 3091 for (d = 0; d < fcdof; ++d) indices[d] = d; 3092 } else { 3093 ierr = PetscSectionGetFieldConstraintIndices(section, p, field, &find);CHKERRQ(ierr); 3094 for (d = 0; d < fcdof; ++d) {if (find[d] < 0) break; indices[d] = find[d];} 3095 for (c = 0; c < Nc; ++c) indices[d+c] = comp[c]; 3096 ierr = PetscSortInt(d+Nc, indices);CHKERRQ(ierr); 3097 for (c = d+Nc; c < fcdof; ++c) indices[c] = -1; 3098 } 3099 ierr = PetscSectionSetFieldConstraintIndices(section, p, field, indices);CHKERRQ(ierr); 3100 } 3101 if (bcComps && bcComps[bc]) {ierr = ISRestoreIndices(bcComps[bc], &comp);CHKERRQ(ierr);} 3102 ierr = ISRestoreIndices(bcPoints[bc], &idx);CHKERRQ(ierr); 3103 } 3104 /* Handle anchors */ 3105 ierr = DMPlexGetAnchors(dm, &aSec, NULL);CHKERRQ(ierr); 3106 if (aSec) { 3107 PetscInt aStart, aEnd, a; 3108 3109 for (d = 0; d < maxDof; ++d) indices[d] = d; 3110 ierr = PetscSectionGetChart(aSec, &aStart, &aEnd);CHKERRQ(ierr); 3111 for (a = aStart; a < aEnd; a++) { 3112 PetscInt dof, fdof, f; 3113 3114 ierr = PetscSectionGetDof(aSec, a, &dof);CHKERRQ(ierr); 3115 if (dof) { 3116 /* if there are point-to-point constraints, then all dofs are constrained */ 3117 for (f = 0; f < numFields; f++) { 3118 ierr = PetscSectionGetFieldDof(section, a, f, &fdof);CHKERRQ(ierr); 3119 ierr = PetscSectionSetFieldConstraintIndices(section, a, f, indices);CHKERRQ(ierr); 3120 } 3121 } 3122 } 3123 } 3124 ierr = PetscFree(indices);CHKERRQ(ierr); 3125 PetscFunctionReturn(0); 3126 } 3127 3128 #undef __FUNCT__ 3129 #define __FUNCT__ "DMPlexCreateSectionBCIndices" 3130 /* Set the constrained indices on each point */ 3131 PetscErrorCode DMPlexCreateSectionBCIndices(DM dm, PetscSection section) 3132 { 3133 PetscInt *indices; 3134 PetscInt numFields, maxDof, pStart, pEnd, p, f, d; 3135 PetscErrorCode ierr; 3136 3137 PetscFunctionBegin; 3138 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3139 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 3140 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3141 ierr = PetscMalloc1(maxDof, &indices);CHKERRQ(ierr); 3142 for (d = 0; d < maxDof; ++d) indices[d] = -1; 3143 for (p = pStart; p < pEnd; ++p) { 3144 PetscInt cdof, d; 3145 3146 ierr = PetscSectionGetConstraintDof(section, p, &cdof);CHKERRQ(ierr); 3147 if (cdof) { 3148 if (numFields) { 3149 PetscInt numConst = 0, foff = 0; 3150 3151 for (f = 0; f < numFields; ++f) { 3152 const PetscInt *find; 3153 PetscInt fcdof, fdof; 3154 3155 ierr = PetscSectionGetFieldDof(section, p, f, &fdof);CHKERRQ(ierr); 3156 ierr = PetscSectionGetFieldConstraintDof(section, p, f, &fcdof);CHKERRQ(ierr); 3157 /* Change constraint numbering from field component to local dof number */ 3158 ierr = PetscSectionGetFieldConstraintIndices(section, p, f, &find);CHKERRQ(ierr); 3159 for (d = 0; d < fcdof; ++d) indices[numConst+d] = find[d] + foff; 3160 numConst += fcdof; 3161 foff += fdof; 3162 } 3163 if (cdof != numConst) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_LIB, "Total number of field constraints %D should be %D", numConst, cdof); 3164 } else { 3165 for (d = 0; d < cdof; ++d) indices[d] = d; 3166 } 3167 ierr = PetscSectionSetConstraintIndices(section, p, indices);CHKERRQ(ierr); 3168 } 3169 } 3170 ierr = PetscFree(indices);CHKERRQ(ierr); 3171 PetscFunctionReturn(0); 3172 } 3173 3174 #undef __FUNCT__ 3175 #define __FUNCT__ "DMPlexCreateSection" 3176 /*@C 3177 DMPlexCreateSection - Create a PetscSection based upon the dof layout specification provided. 3178 3179 Not Collective 3180 3181 Input Parameters: 3182 + dm - The DMPlex object 3183 . dim - The spatial dimension of the problem 3184 . numFields - The number of fields in the problem 3185 . numComp - An array of size numFields that holds the number of components for each field 3186 . numDof - An array of size numFields*(dim+1) which holds the number of dof for each field on a mesh piece of dimension d 3187 . numBC - The number of boundary conditions 3188 . bcField - An array of size numBC giving the field number for each boundry condition 3189 . bcComps - [Optional] An array of size numBC giving an IS holding the field components to which each boundary condition applies 3190 . bcPoints - An array of size numBC giving an IS holding the Plex points to which each boundary condition applies 3191 - perm - Optional permutation of the chart, or NULL 3192 3193 Output Parameter: 3194 . section - The PetscSection object 3195 3196 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 3197 number of dof for field 0 on each edge. 3198 3199 The chart permutation is the same one set using PetscSectionSetPermutation() 3200 3201 Level: developer 3202 3203 Fortran Notes: 3204 A Fortran 90 version is available as DMPlexCreateSectionF90() 3205 3206 .keywords: mesh, elements 3207 .seealso: DMPlexCreate(), PetscSectionCreate(), PetscSectionSetPermutation() 3208 @*/ 3209 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) 3210 { 3211 PetscSection aSec; 3212 PetscErrorCode ierr; 3213 3214 PetscFunctionBegin; 3215 ierr = DMPlexCreateSectionInitial(dm, dim, numFields, numComp, numDof, section);CHKERRQ(ierr); 3216 ierr = DMPlexCreateSectionBCDof(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3217 if (perm) {ierr = PetscSectionSetPermutation(*section, perm);CHKERRQ(ierr);} 3218 ierr = PetscSectionSetUp(*section);CHKERRQ(ierr); 3219 ierr = DMPlexGetAnchors(dm,&aSec,NULL);CHKERRQ(ierr); 3220 if (numBC || aSec) { 3221 ierr = DMPlexCreateSectionBCIndicesField(dm, numBC, bcField, bcComps, bcPoints, *section);CHKERRQ(ierr); 3222 ierr = DMPlexCreateSectionBCIndices(dm, *section);CHKERRQ(ierr); 3223 } 3224 ierr = PetscSectionViewFromOptions(*section,NULL,"-section_view");CHKERRQ(ierr); 3225 PetscFunctionReturn(0); 3226 } 3227 3228 #undef __FUNCT__ 3229 #define __FUNCT__ "DMCreateCoordinateDM_Plex" 3230 PetscErrorCode DMCreateCoordinateDM_Plex(DM dm, DM *cdm) 3231 { 3232 PetscSection section; 3233 PetscErrorCode ierr; 3234 3235 PetscFunctionBegin; 3236 ierr = DMClone(dm, cdm);CHKERRQ(ierr); 3237 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 3238 ierr = DMSetDefaultSection(*cdm, section);CHKERRQ(ierr); 3239 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 3240 PetscFunctionReturn(0); 3241 } 3242 3243 #undef __FUNCT__ 3244 #define __FUNCT__ "DMPlexGetConeSection" 3245 PetscErrorCode DMPlexGetConeSection(DM dm, PetscSection *section) 3246 { 3247 DM_Plex *mesh = (DM_Plex*) dm->data; 3248 3249 PetscFunctionBegin; 3250 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3251 if (section) *section = mesh->coneSection; 3252 PetscFunctionReturn(0); 3253 } 3254 3255 #undef __FUNCT__ 3256 #define __FUNCT__ "DMPlexGetSupportSection" 3257 PetscErrorCode DMPlexGetSupportSection(DM dm, PetscSection *section) 3258 { 3259 DM_Plex *mesh = (DM_Plex*) dm->data; 3260 3261 PetscFunctionBegin; 3262 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3263 if (section) *section = mesh->supportSection; 3264 PetscFunctionReturn(0); 3265 } 3266 3267 #undef __FUNCT__ 3268 #define __FUNCT__ "DMPlexGetCones" 3269 PetscErrorCode DMPlexGetCones(DM dm, PetscInt *cones[]) 3270 { 3271 DM_Plex *mesh = (DM_Plex*) dm->data; 3272 3273 PetscFunctionBegin; 3274 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3275 if (cones) *cones = mesh->cones; 3276 PetscFunctionReturn(0); 3277 } 3278 3279 #undef __FUNCT__ 3280 #define __FUNCT__ "DMPlexGetConeOrientations" 3281 PetscErrorCode DMPlexGetConeOrientations(DM dm, PetscInt *coneOrientations[]) 3282 { 3283 DM_Plex *mesh = (DM_Plex*) dm->data; 3284 3285 PetscFunctionBegin; 3286 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3287 if (coneOrientations) *coneOrientations = mesh->coneOrientations; 3288 PetscFunctionReturn(0); 3289 } 3290 3291 /******************************** FEM Support **********************************/ 3292 3293 #undef __FUNCT__ 3294 #define __FUNCT__ "DMPlexVecGetClosure_Depth1_Static" 3295 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Depth1_Static(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3296 { 3297 PetscScalar *array, *vArray; 3298 const PetscInt *cone, *coneO; 3299 PetscInt pStart, pEnd, p, numPoints, size = 0, offset = 0; 3300 PetscErrorCode ierr; 3301 3302 PetscFunctionBeginHot; 3303 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3304 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3305 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3306 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3307 if (!values || !*values) { 3308 if ((point >= pStart) && (point < pEnd)) { 3309 PetscInt dof; 3310 3311 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3312 size += dof; 3313 } 3314 for (p = 0; p < numPoints; ++p) { 3315 const PetscInt cp = cone[p]; 3316 PetscInt dof; 3317 3318 if ((cp < pStart) || (cp >= pEnd)) continue; 3319 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3320 size += dof; 3321 } 3322 if (!values) { 3323 if (csize) *csize = size; 3324 PetscFunctionReturn(0); 3325 } 3326 ierr = DMGetWorkArray(dm, size, PETSC_SCALAR, &array);CHKERRQ(ierr); 3327 } else { 3328 array = *values; 3329 } 3330 size = 0; 3331 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3332 if ((point >= pStart) && (point < pEnd)) { 3333 PetscInt dof, off, d; 3334 PetscScalar *varr; 3335 3336 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3337 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3338 varr = &vArray[off]; 3339 for (d = 0; d < dof; ++d, ++offset) { 3340 array[offset] = varr[d]; 3341 } 3342 size += dof; 3343 } 3344 for (p = 0; p < numPoints; ++p) { 3345 const PetscInt cp = cone[p]; 3346 PetscInt o = coneO[p]; 3347 PetscInt dof, off, d; 3348 PetscScalar *varr; 3349 3350 if ((cp < pStart) || (cp >= pEnd)) continue; 3351 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3352 ierr = PetscSectionGetOffset(section, cp, &off);CHKERRQ(ierr); 3353 varr = &vArray[off]; 3354 if (o >= 0) { 3355 for (d = 0; d < dof; ++d, ++offset) { 3356 array[offset] = varr[d]; 3357 } 3358 } else { 3359 for (d = dof-1; d >= 0; --d, ++offset) { 3360 array[offset] = varr[d]; 3361 } 3362 } 3363 size += dof; 3364 } 3365 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3366 if (!*values) { 3367 if (csize) *csize = size; 3368 *values = array; 3369 } else { 3370 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %d < actual size %d", *csize, size); 3371 *csize = size; 3372 } 3373 PetscFunctionReturn(0); 3374 } 3375 3376 #undef __FUNCT__ 3377 #define __FUNCT__ "DMPlexVecGetClosure_Static" 3378 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3379 { 3380 PetscInt offset = 0, p; 3381 PetscErrorCode ierr; 3382 3383 PetscFunctionBeginHot; 3384 *size = 0; 3385 for (p = 0; p < numPoints*2; p += 2) { 3386 const PetscInt point = points[p]; 3387 const PetscInt o = points[p+1]; 3388 PetscInt dof, off, d; 3389 const PetscScalar *varr; 3390 3391 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 3392 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3393 varr = &vArray[off]; 3394 if (o >= 0) { 3395 for (d = 0; d < dof; ++d, ++offset) array[offset] = varr[d]; 3396 } else { 3397 for (d = dof-1; d >= 0; --d, ++offset) array[offset] = varr[d]; 3398 } 3399 } 3400 *size = offset; 3401 PetscFunctionReturn(0); 3402 } 3403 3404 #undef __FUNCT__ 3405 #define __FUNCT__ "DMPlexVecGetClosure_Fields_Static" 3406 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecGetClosure_Fields_Static(PetscSection section, PetscInt numPoints, const PetscInt points[], PetscInt numFields, const PetscScalar vArray[], PetscInt *size, PetscScalar array[]) 3407 { 3408 PetscInt offset = 0, f; 3409 PetscErrorCode ierr; 3410 3411 PetscFunctionBeginHot; 3412 *size = 0; 3413 for (f = 0; f < numFields; ++f) { 3414 PetscInt fcomp, p; 3415 3416 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3417 for (p = 0; p < numPoints*2; p += 2) { 3418 const PetscInt point = points[p]; 3419 const PetscInt o = points[p+1]; 3420 PetscInt fdof, foff, d, c; 3421 const PetscScalar *varr; 3422 3423 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3424 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3425 varr = &vArray[foff]; 3426 if (o >= 0) { 3427 for (d = 0; d < fdof; ++d, ++offset) array[offset] = varr[d]; 3428 } else { 3429 for (d = fdof/fcomp-1; d >= 0; --d) { 3430 for (c = 0; c < fcomp; ++c, ++offset) { 3431 array[offset] = varr[d*fcomp+c]; 3432 } 3433 } 3434 } 3435 } 3436 } 3437 *size = offset; 3438 PetscFunctionReturn(0); 3439 } 3440 3441 #undef __FUNCT__ 3442 #define __FUNCT__ "DMPlexVecGetClosure" 3443 /*@C 3444 DMPlexVecGetClosure - Get an array of the values on the closure of 'point' 3445 3446 Not collective 3447 3448 Input Parameters: 3449 + dm - The DM 3450 . section - The section describing the layout in v, or NULL to use the default section 3451 . v - The local vector 3452 - point - The sieve point in the DM 3453 3454 Output Parameters: 3455 + csize - The number of values in the closure, or NULL 3456 - values - The array of values, which is a borrowed array and should not be freed 3457 3458 Fortran Notes: 3459 Since it returns an array, this routine is only available in Fortran 90, and you must 3460 include petsc.h90 in your code. 3461 3462 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3463 3464 Level: intermediate 3465 3466 .seealso DMPlexVecRestoreClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3467 @*/ 3468 PetscErrorCode DMPlexVecGetClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3469 { 3470 PetscSection clSection; 3471 IS clPoints; 3472 PetscScalar *array, *vArray; 3473 PetscInt *points = NULL; 3474 const PetscInt *clp; 3475 PetscInt depth, numFields, numPoints, size; 3476 PetscErrorCode ierr; 3477 3478 PetscFunctionBeginHot; 3479 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3480 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3481 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3482 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3483 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3484 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3485 if (depth == 1 && numFields < 2) { 3486 ierr = DMPlexVecGetClosure_Depth1_Static(dm, section, v, point, csize, values);CHKERRQ(ierr); 3487 PetscFunctionReturn(0); 3488 } 3489 /* Get points */ 3490 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3491 if (!clPoints) { 3492 PetscInt pStart, pEnd, p, q; 3493 3494 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3495 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3496 /* Compress out points not in the section */ 3497 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3498 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3499 points[q*2] = points[p]; 3500 points[q*2+1] = points[p+1]; 3501 ++q; 3502 } 3503 } 3504 numPoints = q; 3505 } else { 3506 PetscInt dof, off; 3507 3508 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3509 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3510 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3511 numPoints = dof/2; 3512 points = (PetscInt *) &clp[off]; 3513 } 3514 /* Get array */ 3515 if (!values || !*values) { 3516 PetscInt asize = 0, dof, p; 3517 3518 for (p = 0; p < numPoints*2; p += 2) { 3519 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3520 asize += dof; 3521 } 3522 if (!values) { 3523 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3524 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3525 if (csize) *csize = asize; 3526 PetscFunctionReturn(0); 3527 } 3528 ierr = DMGetWorkArray(dm, asize, PETSC_SCALAR, &array);CHKERRQ(ierr); 3529 } else { 3530 array = *values; 3531 } 3532 ierr = VecGetArray(v, &vArray);CHKERRQ(ierr); 3533 /* Get values */ 3534 if (numFields > 0) {ierr = DMPlexVecGetClosure_Fields_Static(section, numPoints, points, numFields, vArray, &size, array);CHKERRQ(ierr);} 3535 else {ierr = DMPlexVecGetClosure_Static(section, numPoints, points, vArray, &size, array);CHKERRQ(ierr);} 3536 /* Cleanup points */ 3537 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3538 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3539 /* Cleanup array */ 3540 ierr = VecRestoreArray(v, &vArray);CHKERRQ(ierr); 3541 if (!*values) { 3542 if (csize) *csize = size; 3543 *values = array; 3544 } else { 3545 if (size > *csize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Size of input array %D < actual size %D", *csize, size); 3546 *csize = size; 3547 } 3548 PetscFunctionReturn(0); 3549 } 3550 3551 #undef __FUNCT__ 3552 #define __FUNCT__ "DMPlexVecRestoreClosure" 3553 /*@C 3554 DMPlexVecRestoreClosure - Restore the array of the values on the closure of 'point' 3555 3556 Not collective 3557 3558 Input Parameters: 3559 + dm - The DM 3560 . section - The section describing the layout in v, or NULL to use the default section 3561 . v - The local vector 3562 . point - The sieve point in the DM 3563 . csize - The number of values in the closure, or NULL 3564 - values - The array of values, which is a borrowed array and should not be freed 3565 3566 Fortran Notes: 3567 Since it returns an array, this routine is only available in Fortran 90, and you must 3568 include petsc.h90 in your code. 3569 3570 The csize argument is not present in the Fortran 90 binding since it is internal to the array. 3571 3572 Level: intermediate 3573 3574 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure(), DMPlexMatSetClosure() 3575 @*/ 3576 PetscErrorCode DMPlexVecRestoreClosure(DM dm, PetscSection section, Vec v, PetscInt point, PetscInt *csize, PetscScalar *values[]) 3577 { 3578 PetscInt size = 0; 3579 PetscErrorCode ierr; 3580 3581 PetscFunctionBegin; 3582 /* Should work without recalculating size */ 3583 ierr = DMRestoreWorkArray(dm, size, PETSC_SCALAR, (void*) values);CHKERRQ(ierr); 3584 PetscFunctionReturn(0); 3585 } 3586 3587 PETSC_STATIC_INLINE void add (PetscScalar *x, PetscScalar y) {*x += y;} 3588 PETSC_STATIC_INLINE void insert(PetscScalar *x, PetscScalar y) {*x = y;} 3589 3590 #undef __FUNCT__ 3591 #define __FUNCT__ "updatePoint_private" 3592 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[]) 3593 { 3594 PetscInt cdof; /* The number of constraints on this point */ 3595 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3596 PetscScalar *a; 3597 PetscInt off, cind = 0, k; 3598 PetscErrorCode ierr; 3599 3600 PetscFunctionBegin; 3601 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3602 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3603 a = &array[off]; 3604 if (!cdof || setBC) { 3605 if (orientation >= 0) { 3606 for (k = 0; k < dof; ++k) { 3607 fuse(&a[k], values[k]); 3608 } 3609 } else { 3610 for (k = 0; k < dof; ++k) { 3611 fuse(&a[k], values[dof-k-1]); 3612 } 3613 } 3614 } else { 3615 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3616 if (orientation >= 0) { 3617 for (k = 0; k < dof; ++k) { 3618 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3619 fuse(&a[k], values[k]); 3620 } 3621 } else { 3622 for (k = 0; k < dof; ++k) { 3623 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3624 fuse(&a[k], values[dof-k-1]); 3625 } 3626 } 3627 } 3628 PetscFunctionReturn(0); 3629 } 3630 3631 #undef __FUNCT__ 3632 #define __FUNCT__ "updatePointBC_private" 3633 PETSC_STATIC_INLINE PetscErrorCode updatePointBC_private(PetscSection section, PetscInt point, PetscInt dof, void (*fuse)(PetscScalar*, PetscScalar), PetscInt orientation, const PetscScalar values[], PetscScalar array[]) 3634 { 3635 PetscInt cdof; /* The number of constraints on this point */ 3636 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3637 PetscScalar *a; 3638 PetscInt off, cind = 0, k; 3639 PetscErrorCode ierr; 3640 3641 PetscFunctionBegin; 3642 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 3643 ierr = PetscSectionGetOffset(section, point, &off);CHKERRQ(ierr); 3644 a = &array[off]; 3645 if (cdof) { 3646 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 3647 if (orientation >= 0) { 3648 for (k = 0; k < dof; ++k) { 3649 if ((cind < cdof) && (k == cdofs[cind])) { 3650 fuse(&a[k], values[k]); 3651 ++cind; 3652 } 3653 } 3654 } else { 3655 for (k = 0; k < dof; ++k) { 3656 if ((cind < cdof) && (k == cdofs[cind])) { 3657 fuse(&a[k], values[dof-k-1]); 3658 ++cind; 3659 } 3660 } 3661 } 3662 } 3663 PetscFunctionReturn(0); 3664 } 3665 3666 #undef __FUNCT__ 3667 #define __FUNCT__ "updatePointFields_private" 3668 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[]) 3669 { 3670 PetscScalar *a; 3671 PetscInt fdof, foff, fcdof, foffset = *offset; 3672 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3673 PetscInt cind = 0, k, c; 3674 PetscErrorCode ierr; 3675 3676 PetscFunctionBegin; 3677 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3678 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3679 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3680 a = &array[foff]; 3681 if (!fcdof || setBC) { 3682 if (o >= 0) { 3683 for (k = 0; k < fdof; ++k) fuse(&a[k], values[foffset+k]); 3684 } else { 3685 for (k = fdof/fcomp-1; k >= 0; --k) { 3686 for (c = 0; c < fcomp; ++c) { 3687 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3688 } 3689 } 3690 } 3691 } else { 3692 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3693 if (o >= 0) { 3694 for (k = 0; k < fdof; ++k) { 3695 if ((cind < fcdof) && (k == fcdofs[cind])) {++cind; continue;} 3696 fuse(&a[k], values[foffset+k]); 3697 } 3698 } else { 3699 for (k = fdof/fcomp-1; k >= 0; --k) { 3700 for (c = 0; c < fcomp; ++c) { 3701 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) {++cind; continue;} 3702 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3703 } 3704 } 3705 } 3706 } 3707 *offset += fdof; 3708 PetscFunctionReturn(0); 3709 } 3710 3711 #undef __FUNCT__ 3712 #define __FUNCT__ "updatePointFieldsBC_private" 3713 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[]) 3714 { 3715 PetscScalar *a; 3716 PetscInt fdof, foff, fcdof, foffset = *offset; 3717 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 3718 PetscInt cind = 0, k, c; 3719 PetscErrorCode ierr; 3720 3721 PetscFunctionBegin; 3722 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 3723 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &fcdof);CHKERRQ(ierr); 3724 ierr = PetscSectionGetFieldOffset(section, point, f, &foff);CHKERRQ(ierr); 3725 a = &array[foff]; 3726 if (fcdof) { 3727 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 3728 if (o >= 0) { 3729 for (k = 0; k < fdof; ++k) { 3730 if ((cind < fcdof) && (k == fcdofs[cind])) { 3731 fuse(&a[k], values[foffset+k]); 3732 ++cind; 3733 } 3734 } 3735 } else { 3736 for (k = fdof/fcomp-1; k >= 0; --k) { 3737 for (c = 0; c < fcomp; ++c) { 3738 if ((cind < fcdof) && (k*fcomp+c == fcdofs[cind])) { 3739 fuse(&a[(fdof/fcomp-1-k)*fcomp+c], values[foffset+k*fcomp+c]); 3740 ++cind; 3741 } 3742 } 3743 } 3744 } 3745 } 3746 *offset += fdof; 3747 PetscFunctionReturn(0); 3748 } 3749 3750 #undef __FUNCT__ 3751 #define __FUNCT__ "DMPlexVecSetClosure_Static" 3752 PETSC_STATIC_INLINE PetscErrorCode DMPlexVecSetClosure_Static(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3753 { 3754 PetscScalar *array; 3755 const PetscInt *cone, *coneO; 3756 PetscInt pStart, pEnd, p, numPoints, off, dof; 3757 PetscErrorCode ierr; 3758 3759 PetscFunctionBeginHot; 3760 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3761 ierr = DMPlexGetConeSize(dm, point, &numPoints);CHKERRQ(ierr); 3762 ierr = DMPlexGetCone(dm, point, &cone);CHKERRQ(ierr); 3763 ierr = DMPlexGetConeOrientation(dm, point, &coneO);CHKERRQ(ierr); 3764 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3765 for (p = 0, off = 0; p <= numPoints; ++p, off += dof) { 3766 const PetscInt cp = !p ? point : cone[p-1]; 3767 const PetscInt o = !p ? 0 : coneO[p-1]; 3768 3769 if ((cp < pStart) || (cp >= pEnd)) {dof = 0; continue;} 3770 ierr = PetscSectionGetDof(section, cp, &dof);CHKERRQ(ierr); 3771 /* ADD_VALUES */ 3772 { 3773 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 3774 PetscScalar *a; 3775 PetscInt cdof, coff, cind = 0, k; 3776 3777 ierr = PetscSectionGetConstraintDof(section, cp, &cdof);CHKERRQ(ierr); 3778 ierr = PetscSectionGetOffset(section, cp, &coff);CHKERRQ(ierr); 3779 a = &array[coff]; 3780 if (!cdof) { 3781 if (o >= 0) { 3782 for (k = 0; k < dof; ++k) { 3783 a[k] += values[off+k]; 3784 } 3785 } else { 3786 for (k = 0; k < dof; ++k) { 3787 a[k] += values[off+dof-k-1]; 3788 } 3789 } 3790 } else { 3791 ierr = PetscSectionGetConstraintIndices(section, cp, &cdofs);CHKERRQ(ierr); 3792 if (o >= 0) { 3793 for (k = 0; k < dof; ++k) { 3794 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3795 a[k] += values[off+k]; 3796 } 3797 } else { 3798 for (k = 0; k < dof; ++k) { 3799 if ((cind < cdof) && (k == cdofs[cind])) {++cind; continue;} 3800 a[k] += values[off+dof-k-1]; 3801 } 3802 } 3803 } 3804 } 3805 } 3806 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3807 PetscFunctionReturn(0); 3808 } 3809 3810 #undef __FUNCT__ 3811 #define __FUNCT__ "DMPlexVecSetClosure" 3812 /*@C 3813 DMPlexVecSetClosure - Set an array of the values on the closure of 'point' 3814 3815 Not collective 3816 3817 Input Parameters: 3818 + dm - The DM 3819 . section - The section describing the layout in v, or NULL to use the default section 3820 . v - The local vector 3821 . point - The sieve point in the DM 3822 . values - The array of values 3823 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 3824 3825 Fortran Notes: 3826 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 3827 3828 Level: intermediate 3829 3830 .seealso DMPlexVecGetClosure(), DMPlexMatSetClosure() 3831 @*/ 3832 PetscErrorCode DMPlexVecSetClosure(DM dm, PetscSection section, Vec v, PetscInt point, const PetscScalar values[], InsertMode mode) 3833 { 3834 PetscSection clSection; 3835 IS clPoints; 3836 PetscScalar *array; 3837 PetscInt *points = NULL; 3838 const PetscInt *clp; 3839 PetscInt depth, numFields, numPoints, p; 3840 PetscErrorCode ierr; 3841 3842 PetscFunctionBeginHot; 3843 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3844 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3845 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3846 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3847 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 3848 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3849 if (depth == 1 && numFields < 2 && mode == ADD_VALUES) { 3850 ierr = DMPlexVecSetClosure_Static(dm, section, v, point, values, mode);CHKERRQ(ierr); 3851 PetscFunctionReturn(0); 3852 } 3853 /* Get points */ 3854 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3855 if (!clPoints) { 3856 PetscInt pStart, pEnd, q; 3857 3858 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3859 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3860 /* Compress out points not in the section */ 3861 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3862 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3863 points[q*2] = points[p]; 3864 points[q*2+1] = points[p+1]; 3865 ++q; 3866 } 3867 } 3868 numPoints = q; 3869 } else { 3870 PetscInt dof, off; 3871 3872 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 3873 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 3874 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 3875 numPoints = dof/2; 3876 points = (PetscInt *) &clp[off]; 3877 } 3878 /* Get array */ 3879 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 3880 /* Get values */ 3881 if (numFields > 0) { 3882 PetscInt offset = 0, fcomp, f; 3883 for (f = 0; f < numFields; ++f) { 3884 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 3885 switch (mode) { 3886 case INSERT_VALUES: 3887 for (p = 0; p < numPoints*2; p += 2) { 3888 const PetscInt point = points[p]; 3889 const PetscInt o = points[p+1]; 3890 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 3891 } break; 3892 case INSERT_ALL_VALUES: 3893 for (p = 0; p < numPoints*2; p += 2) { 3894 const PetscInt point = points[p]; 3895 const PetscInt o = points[p+1]; 3896 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 3897 } break; 3898 case INSERT_BC_VALUES: 3899 for (p = 0; p < numPoints*2; p += 2) { 3900 const PetscInt point = points[p]; 3901 const PetscInt o = points[p+1]; 3902 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 3903 } break; 3904 case ADD_VALUES: 3905 for (p = 0; p < numPoints*2; p += 2) { 3906 const PetscInt point = points[p]; 3907 const PetscInt o = points[p+1]; 3908 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 3909 } break; 3910 case ADD_ALL_VALUES: 3911 for (p = 0; p < numPoints*2; p += 2) { 3912 const PetscInt point = points[p]; 3913 const PetscInt o = points[p+1]; 3914 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 3915 } break; 3916 default: 3917 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3918 } 3919 } 3920 } else { 3921 PetscInt dof, off; 3922 3923 switch (mode) { 3924 case INSERT_VALUES: 3925 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3926 PetscInt o = points[p+1]; 3927 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3928 updatePoint_private(section, points[p], dof, insert, PETSC_FALSE, o, &values[off], array); 3929 } break; 3930 case INSERT_ALL_VALUES: 3931 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3932 PetscInt o = points[p+1]; 3933 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3934 updatePoint_private(section, points[p], dof, insert, PETSC_TRUE, o, &values[off], array); 3935 } break; 3936 case INSERT_BC_VALUES: 3937 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3938 PetscInt o = points[p+1]; 3939 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3940 updatePointBC_private(section, points[p], dof, insert, o, &values[off], array); 3941 } break; 3942 case ADD_VALUES: 3943 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3944 PetscInt o = points[p+1]; 3945 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3946 updatePoint_private(section, points[p], dof, add, PETSC_FALSE, o, &values[off], array); 3947 } break; 3948 case ADD_ALL_VALUES: 3949 for (p = 0, off = 0; p < numPoints*2; p += 2, off += dof) { 3950 PetscInt o = points[p+1]; 3951 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 3952 updatePoint_private(section, points[p], dof, add, PETSC_TRUE, o, &values[off], array); 3953 } break; 3954 default: 3955 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 3956 } 3957 } 3958 /* Cleanup points */ 3959 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 3960 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 3961 /* Cleanup array */ 3962 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 3963 PetscFunctionReturn(0); 3964 } 3965 3966 #undef __FUNCT__ 3967 #define __FUNCT__ "DMPlexVecSetFieldClosure_Internal" 3968 PetscErrorCode DMPlexVecSetFieldClosure_Internal(DM dm, PetscSection section, Vec v, PetscBool fieldActive[], PetscInt point, const PetscScalar values[], InsertMode mode) 3969 { 3970 PetscSection clSection; 3971 IS clPoints; 3972 PetscScalar *array; 3973 PetscInt *points = NULL; 3974 const PetscInt *clp; 3975 PetscInt numFields, numPoints, p; 3976 PetscInt offset = 0, fcomp, f; 3977 PetscErrorCode ierr; 3978 3979 PetscFunctionBeginHot; 3980 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 3981 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 3982 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 3983 PetscValidHeaderSpecific(v, VEC_CLASSID, 3); 3984 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 3985 /* Get points */ 3986 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 3987 if (!clPoints) { 3988 PetscInt pStart, pEnd, q; 3989 3990 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 3991 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 3992 /* Compress out points not in the section */ 3993 for (p = 0, q = 0; p < numPoints*2; p += 2) { 3994 if ((points[p] >= pStart) && (points[p] < pEnd)) { 3995 points[q*2] = points[p]; 3996 points[q*2+1] = points[p+1]; 3997 ++q; 3998 } 3999 } 4000 numPoints = q; 4001 } else { 4002 PetscInt dof, off; 4003 4004 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4005 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4006 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4007 numPoints = dof/2; 4008 points = (PetscInt *) &clp[off]; 4009 } 4010 /* Get array */ 4011 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 4012 /* Get values */ 4013 for (f = 0; f < numFields; ++f) { 4014 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4015 if (!fieldActive[f]) { 4016 for (p = 0; p < numPoints*2; p += 2) { 4017 PetscInt fdof; 4018 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4019 offset += fdof; 4020 } 4021 continue; 4022 } 4023 switch (mode) { 4024 case INSERT_VALUES: 4025 for (p = 0; p < numPoints*2; p += 2) { 4026 const PetscInt point = points[p]; 4027 const PetscInt o = points[p+1]; 4028 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_FALSE, values, &offset, array); 4029 } break; 4030 case INSERT_ALL_VALUES: 4031 for (p = 0; p < numPoints*2; p += 2) { 4032 const PetscInt point = points[p]; 4033 const PetscInt o = points[p+1]; 4034 updatePointFields_private(section, point, o, f, fcomp, insert, PETSC_TRUE, values, &offset, array); 4035 } break; 4036 case INSERT_BC_VALUES: 4037 for (p = 0; p < numPoints*2; p += 2) { 4038 const PetscInt point = points[p]; 4039 const PetscInt o = points[p+1]; 4040 updatePointFieldsBC_private(section, point, o, f, fcomp, insert, values, &offset, array); 4041 } break; 4042 case ADD_VALUES: 4043 for (p = 0; p < numPoints*2; p += 2) { 4044 const PetscInt point = points[p]; 4045 const PetscInt o = points[p+1]; 4046 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_FALSE, values, &offset, array); 4047 } break; 4048 case ADD_ALL_VALUES: 4049 for (p = 0; p < numPoints*2; p += 2) { 4050 const PetscInt point = points[p]; 4051 const PetscInt o = points[p+1]; 4052 updatePointFields_private(section, point, o, f, fcomp, add, PETSC_TRUE, values, &offset, array); 4053 } break; 4054 default: 4055 SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Invalid insert mode %d", mode); 4056 } 4057 } 4058 /* Cleanup points */ 4059 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4060 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4061 /* Cleanup array */ 4062 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 4063 PetscFunctionReturn(0); 4064 } 4065 4066 #undef __FUNCT__ 4067 #define __FUNCT__ "DMPlexPrintMatSetValues" 4068 PetscErrorCode DMPlexPrintMatSetValues(PetscViewer viewer, Mat A, PetscInt point, PetscInt numRIndices, const PetscInt rindices[], PetscInt numCIndices, const PetscInt cindices[], const PetscScalar values[]) 4069 { 4070 PetscMPIInt rank; 4071 PetscInt i, j; 4072 PetscErrorCode ierr; 4073 4074 PetscFunctionBegin; 4075 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr); 4076 ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat for sieve point %D\n", rank, point);CHKERRQ(ierr); 4077 for (i = 0; i < numRIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat row indices[%D] = %D\n", rank, i, rindices[i]);CHKERRQ(ierr);} 4078 for (i = 0; i < numCIndices; i++) {ierr = PetscViewerASCIIPrintf(viewer, "[%d]mat col indices[%D] = %D\n", rank, i, cindices[i]);CHKERRQ(ierr);} 4079 numCIndices = numCIndices ? numCIndices : numRIndices; 4080 for (i = 0; i < numRIndices; i++) { 4081 ierr = PetscViewerASCIIPrintf(viewer, "[%d]", rank);CHKERRQ(ierr); 4082 for (j = 0; j < numCIndices; j++) { 4083 #if defined(PETSC_USE_COMPLEX) 4084 ierr = PetscViewerASCIIPrintf(viewer, " (%g,%g)", (double)PetscRealPart(values[i*numCIndices+j]), (double)PetscImaginaryPart(values[i*numCIndices+j]));CHKERRQ(ierr); 4085 #else 4086 ierr = PetscViewerASCIIPrintf(viewer, " %g", (double)values[i*numCIndices+j]);CHKERRQ(ierr); 4087 #endif 4088 } 4089 ierr = PetscViewerASCIIPrintf(viewer, "\n");CHKERRQ(ierr); 4090 } 4091 PetscFunctionReturn(0); 4092 } 4093 4094 #undef __FUNCT__ 4095 #define __FUNCT__ "indicesPoint_private" 4096 /* . off - The global offset of this point */ 4097 PetscErrorCode indicesPoint_private(PetscSection section, PetscInt point, PetscInt off, PetscInt *loff, PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4098 { 4099 PetscInt dof; /* The number of unknowns on this point */ 4100 PetscInt cdof; /* The number of constraints on this point */ 4101 const PetscInt *cdofs; /* The indices of the constrained dofs on this point */ 4102 PetscInt cind = 0, k; 4103 PetscErrorCode ierr; 4104 4105 PetscFunctionBegin; 4106 ierr = PetscSectionGetDof(section, point, &dof);CHKERRQ(ierr); 4107 ierr = PetscSectionGetConstraintDof(section, point, &cdof);CHKERRQ(ierr); 4108 if (!cdof || setBC) { 4109 if (orientation >= 0) { 4110 for (k = 0; k < dof; ++k) indices[*loff+k] = off+k; 4111 } else { 4112 for (k = 0; k < dof; ++k) indices[*loff+dof-k-1] = off+k; 4113 } 4114 } else { 4115 ierr = PetscSectionGetConstraintIndices(section, point, &cdofs);CHKERRQ(ierr); 4116 if (orientation >= 0) { 4117 for (k = 0; k < dof; ++k) { 4118 if ((cind < cdof) && (k == cdofs[cind])) { 4119 /* Insert check for returning constrained indices */ 4120 indices[*loff+k] = -(off+k+1); 4121 ++cind; 4122 } else { 4123 indices[*loff+k] = off+k-cind; 4124 } 4125 } 4126 } else { 4127 for (k = 0; k < dof; ++k) { 4128 if ((cind < cdof) && (k == cdofs[cind])) { 4129 /* Insert check for returning constrained indices */ 4130 indices[*loff+dof-k-1] = -(off+k+1); 4131 ++cind; 4132 } else { 4133 indices[*loff+dof-k-1] = off+k-cind; 4134 } 4135 } 4136 } 4137 } 4138 *loff += dof; 4139 PetscFunctionReturn(0); 4140 } 4141 4142 #undef __FUNCT__ 4143 #define __FUNCT__ "indicesPointFields_private" 4144 /* . off - The global offset of this point */ 4145 PetscErrorCode indicesPointFields_private(PetscSection section, PetscInt point, PetscInt off, PetscInt foffs[], PetscBool setBC, PetscInt orientation, PetscInt indices[]) 4146 { 4147 PetscInt numFields, foff, f; 4148 PetscErrorCode ierr; 4149 4150 PetscFunctionBegin; 4151 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4152 for (f = 0, foff = 0; f < numFields; ++f) { 4153 PetscInt fdof, fcomp, cfdof; 4154 const PetscInt *fcdofs; /* The indices of the constrained dofs for field f on this point */ 4155 PetscInt cind = 0, k, c; 4156 4157 ierr = PetscSectionGetFieldComponents(section, f, &fcomp);CHKERRQ(ierr); 4158 ierr = PetscSectionGetFieldDof(section, point, f, &fdof);CHKERRQ(ierr); 4159 ierr = PetscSectionGetFieldConstraintDof(section, point, f, &cfdof);CHKERRQ(ierr); 4160 if (!cfdof || setBC) { 4161 if (orientation >= 0) { 4162 for (k = 0; k < fdof; ++k) indices[foffs[f]+k] = off+foff+k; 4163 } else { 4164 for (k = fdof/fcomp-1; k >= 0; --k) { 4165 for (c = 0; c < fcomp; ++c) { 4166 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c; 4167 } 4168 } 4169 } 4170 } else { 4171 ierr = PetscSectionGetFieldConstraintIndices(section, point, f, &fcdofs);CHKERRQ(ierr); 4172 if (orientation >= 0) { 4173 for (k = 0; k < fdof; ++k) { 4174 if ((cind < cfdof) && (k == fcdofs[cind])) { 4175 indices[foffs[f]+k] = -(off+foff+k+1); 4176 ++cind; 4177 } else { 4178 indices[foffs[f]+k] = off+foff+k-cind; 4179 } 4180 } 4181 } else { 4182 for (k = fdof/fcomp-1; k >= 0; --k) { 4183 for (c = 0; c < fcomp; ++c) { 4184 if ((cind < cfdof) && ((fdof/fcomp-1-k)*fcomp+c == fcdofs[cind])) { 4185 indices[foffs[f]+k*fcomp+c] = -(off+foff+(fdof/fcomp-1-k)*fcomp+c+1); 4186 ++cind; 4187 } else { 4188 indices[foffs[f]+k*fcomp+c] = off+foff+(fdof/fcomp-1-k)*fcomp+c-cind; 4189 } 4190 } 4191 } 4192 } 4193 } 4194 foff += fdof - cfdof; 4195 foffs[f] += fdof; 4196 } 4197 PetscFunctionReturn(0); 4198 } 4199 4200 #undef __FUNCT__ 4201 #define __FUNCT__ "DMPlexAnchorsModifyMat" 4202 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[]) 4203 { 4204 Mat cMat; 4205 PetscSection aSec, cSec; 4206 IS aIS; 4207 PetscInt aStart = -1, aEnd = -1; 4208 const PetscInt *anchors; 4209 PetscInt numFields, f, p, q, newP = 0; 4210 PetscInt newNumPoints = 0, newNumIndices = 0; 4211 PetscInt *newPoints, *indices, *newIndices; 4212 PetscInt maxAnchor, maxDof; 4213 PetscInt newOffsets[32]; 4214 PetscInt *pointMatOffsets[32]; 4215 PetscInt *newPointOffsets[32]; 4216 PetscScalar *pointMat[32]; 4217 PetscScalar *newValues,*tmpValues; 4218 PetscBool anyConstrained = PETSC_FALSE; 4219 PetscErrorCode ierr; 4220 4221 PetscFunctionBegin; 4222 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4223 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4224 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4225 4226 ierr = DMPlexGetAnchors(dm,&aSec,&aIS);CHKERRQ(ierr); 4227 /* if there are point-to-point constraints */ 4228 if (aSec) { 4229 ierr = PetscMemzero(newOffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4230 ierr = ISGetIndices(aIS,&anchors);CHKERRQ(ierr); 4231 ierr = PetscSectionGetChart(aSec,&aStart,&aEnd);CHKERRQ(ierr); 4232 /* figure out how many points are going to be in the new element matrix 4233 * (we allow double counting, because it's all just going to be summed 4234 * into the global matrix anyway) */ 4235 for (p = 0; p < 2*numPoints; p+=2) { 4236 PetscInt b = points[p]; 4237 PetscInt bDof = 0; 4238 4239 if (b >= aStart && b < aEnd) { 4240 ierr = PetscSectionGetDof(aSec,b,&bDof);CHKERRQ(ierr); 4241 } 4242 if (bDof) { 4243 /* this point is constrained */ 4244 /* it is going to be replaced by its anchors */ 4245 PetscInt bOff, q; 4246 4247 anyConstrained = PETSC_TRUE; 4248 newNumPoints += bDof; 4249 ierr = PetscSectionGetOffset(aSec,b,&bOff);CHKERRQ(ierr); 4250 for (q = 0; q < bDof; q++) { 4251 PetscInt a = anchors[bOff + q]; 4252 PetscInt aDof; 4253 4254 ierr = PetscSectionGetDof(section,a,&aDof);CHKERRQ(ierr); 4255 newNumIndices += aDof; 4256 for (f = 0; f < numFields; ++f) { 4257 PetscInt fDof; 4258 4259 ierr = PetscSectionGetFieldDof(section, a, f, &fDof);CHKERRQ(ierr); 4260 newOffsets[f+1] += fDof; 4261 } 4262 } 4263 } 4264 else { 4265 /* this point is not constrained */ 4266 newNumPoints++; 4267 ierr = PetscSectionGetDof(section,b,&bDof);CHKERRQ(ierr); 4268 newNumIndices += bDof; 4269 for (f = 0; f < numFields; ++f) { 4270 PetscInt fDof; 4271 4272 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4273 newOffsets[f+1] += fDof; 4274 } 4275 } 4276 } 4277 } 4278 if (!anyConstrained) { 4279 if (outNumPoints) *outNumPoints = 0; 4280 if (outNumIndices) *outNumIndices = 0; 4281 if (outPoints) *outPoints = NULL; 4282 if (outValues) *outValues = NULL; 4283 if (aSec) {ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr);} 4284 PetscFunctionReturn(0); 4285 } 4286 4287 for (f = 1; f < numFields; ++f) newOffsets[f+1] += newOffsets[f]; 4288 4289 if (numFields && newOffsets[numFields] != newNumIndices) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Invalid size for closure %D should be %D", newOffsets[numFields], newNumIndices); 4290 4291 ierr = DMGetDefaultConstraints(dm, &cSec, &cMat);CHKERRQ(ierr); 4292 4293 /* output arrays */ 4294 ierr = DMGetWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4295 ierr = DMGetWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4296 4297 /* workspaces */ 4298 ierr = DMGetWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4299 if (numFields) { 4300 for (f = 0; f < numFields; f++) { 4301 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4302 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4303 } 4304 } 4305 else { 4306 ierr = DMGetWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4307 ierr = DMGetWorkArray(dm,numPoints,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4308 } 4309 4310 /* get workspaces for the point-to-point matrices */ 4311 if (numFields) { 4312 for (p = 0; p < numPoints; p++) { 4313 PetscInt b = points[2*p]; 4314 PetscInt bDof = 0; 4315 4316 if (b >= aStart && b < aEnd) { 4317 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4318 } 4319 if (bDof) { 4320 for (f = 0; f < numFields; f++) { 4321 PetscInt fDof, q, bOff, allFDof = 0; 4322 4323 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4324 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4325 for (q = 0; q < bDof; q++) { 4326 PetscInt a = anchors[bOff + q]; 4327 PetscInt aFDof; 4328 4329 ierr = PetscSectionGetFieldDof(section, a, f, &aFDof);CHKERRQ(ierr); 4330 allFDof += aFDof; 4331 } 4332 newPointOffsets[f][p+1] = allFDof; 4333 pointMatOffsets[f][p+1] = fDof * allFDof; 4334 } 4335 } 4336 else { 4337 for (f = 0; f < numFields; f++) { 4338 PetscInt fDof; 4339 4340 ierr = PetscSectionGetFieldDof(section, b, f, &fDof);CHKERRQ(ierr); 4341 newPointOffsets[f][p+1] = fDof; 4342 pointMatOffsets[f][p+1] = 0; 4343 } 4344 } 4345 } 4346 for (f = 0; f < numFields; f++) { 4347 newPointOffsets[f][0] = 0; 4348 pointMatOffsets[f][0] = 0; 4349 for (p = 0; p < numPoints; p++) { 4350 newPointOffsets[f][p+1] += newPointOffsets[f][p]; 4351 pointMatOffsets[f][p+1] += pointMatOffsets[f][p]; 4352 } 4353 ierr = DMGetWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4354 } 4355 } 4356 else { 4357 for (p = 0; p < numPoints; p++) { 4358 PetscInt b = points[2*p]; 4359 PetscInt bDof = 0; 4360 4361 if (b >= aStart && b < aEnd) { 4362 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4363 } 4364 if (bDof) { 4365 PetscInt dof, bOff, q, allDof = 0; 4366 4367 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4368 ierr = PetscSectionGetOffset(aSec, b, &bOff);CHKERRQ(ierr); 4369 for (q = 0; q < bDof; q++) { 4370 PetscInt a = anchors[bOff + q], aDof; 4371 4372 ierr = PetscSectionGetDof(section, a, &aDof);CHKERRQ(ierr); 4373 allDof += aDof; 4374 } 4375 newPointOffsets[0][p+1] = allDof; 4376 pointMatOffsets[0][p+1] = dof * allDof; 4377 } 4378 else { 4379 PetscInt dof; 4380 4381 ierr = PetscSectionGetDof(section, b, &dof);CHKERRQ(ierr); 4382 newPointOffsets[0][p+1] = dof; 4383 pointMatOffsets[0][p+1] = 0; 4384 } 4385 } 4386 newPointOffsets[0][0] = 0; 4387 pointMatOffsets[0][0] = 0; 4388 for (p = 0; p < numPoints; p++) { 4389 newPointOffsets[0][p+1] += newPointOffsets[0][p]; 4390 pointMatOffsets[0][p+1] += pointMatOffsets[0][p]; 4391 } 4392 ierr = DMGetWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4393 } 4394 4395 /* get the point-to-point matrices; construct newPoints */ 4396 ierr = PetscSectionGetMaxDof(aSec, &maxAnchor);CHKERRQ(ierr); 4397 ierr = PetscSectionGetMaxDof(section, &maxDof);CHKERRQ(ierr); 4398 ierr = DMGetWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4399 ierr = DMGetWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4400 if (numFields) { 4401 for (p = 0, newP = 0; p < numPoints; p++) { 4402 PetscInt b = points[2*p]; 4403 PetscInt o = points[2*p+1]; 4404 PetscInt bDof = 0; 4405 4406 if (b >= aStart && b < aEnd) { 4407 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4408 } 4409 if (bDof) { 4410 PetscInt fStart[32], fEnd[32], fAnchorStart[32], fAnchorEnd[32], bOff, q; 4411 4412 fStart[0] = 0; 4413 fEnd[0] = 0; 4414 for (f = 0; f < numFields; f++) { 4415 PetscInt fDof; 4416 4417 ierr = PetscSectionGetFieldDof(cSec, b, f, &fDof);CHKERRQ(ierr); 4418 fStart[f+1] = fStart[f] + fDof; 4419 fEnd[f+1] = fStart[f+1]; 4420 } 4421 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4422 ierr = indicesPointFields_private(cSec, b, bOff, fEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4423 4424 fAnchorStart[0] = 0; 4425 fAnchorEnd[0] = 0; 4426 for (f = 0; f < numFields; f++) { 4427 PetscInt fDof = newPointOffsets[f][p + 1] - newPointOffsets[f][p]; 4428 4429 fAnchorStart[f+1] = fAnchorStart[f] + fDof; 4430 fAnchorEnd[f+1] = fAnchorStart[f + 1]; 4431 } 4432 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4433 for (q = 0; q < bDof; q++) { 4434 PetscInt a = anchors[bOff + q], aOff; 4435 4436 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4437 newPoints[2*(newP + q)] = a; 4438 newPoints[2*(newP + q) + 1] = 0; 4439 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4440 ierr = indicesPointFields_private(section, a, aOff, fAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4441 } 4442 newP += bDof; 4443 4444 /* get the point-to-point submatrix */ 4445 for (f = 0; f < numFields; f++) { 4446 ierr = MatGetValues(cMat,fEnd[f]-fStart[f],indices + fStart[f],fAnchorEnd[f] - fAnchorStart[f],newIndices + fAnchorStart[f],pointMat[f] + pointMatOffsets[f][p]);CHKERRQ(ierr); 4447 } 4448 } 4449 else { 4450 newPoints[2 * newP] = b; 4451 newPoints[2 * newP + 1] = o; 4452 newP++; 4453 } 4454 } 4455 } else { 4456 for (p = 0; p < numPoints; p++) { 4457 PetscInt b = points[2*p]; 4458 PetscInt o = points[2*p+1]; 4459 PetscInt bDof = 0; 4460 4461 if (b >= aStart && b < aEnd) { 4462 ierr = PetscSectionGetDof(aSec, b, &bDof);CHKERRQ(ierr); 4463 } 4464 if (bDof) { 4465 PetscInt bEnd = 0, bAnchorEnd = 0, bOff; 4466 4467 ierr = PetscSectionGetOffset(cSec, b, &bOff);CHKERRQ(ierr); 4468 ierr = indicesPoint_private(cSec, b, bOff, &bEnd, PETSC_TRUE, o, indices);CHKERRQ(ierr); 4469 4470 ierr = PetscSectionGetOffset (aSec, b, &bOff);CHKERRQ(ierr); 4471 for (q = 0; q < bDof; q++) { 4472 PetscInt a = anchors[bOff + q], aOff; 4473 4474 /* we take the orientation of ap into account in the order that we constructed the indices above: the newly added points have no orientation */ 4475 4476 newPoints[2*(newP + q)] = a; 4477 newPoints[2*(newP + q) + 1] = 0; 4478 ierr = PetscSectionGetOffset(section, a, &aOff);CHKERRQ(ierr); 4479 ierr = indicesPoint_private(section, a, aOff, &bAnchorEnd, PETSC_TRUE, 0, newIndices);CHKERRQ(ierr); 4480 } 4481 newP += bDof; 4482 4483 /* get the point-to-point submatrix */ 4484 ierr = MatGetValues(cMat,bEnd,indices,bAnchorEnd,newIndices,pointMat[0] + pointMatOffsets[0][p]);CHKERRQ(ierr); 4485 } 4486 else { 4487 newPoints[2 * newP] = b; 4488 newPoints[2 * newP + 1] = o; 4489 newP++; 4490 } 4491 } 4492 } 4493 4494 ierr = PetscMemzero(tmpValues,newNumIndices*numIndices*sizeof(*tmpValues));CHKERRQ(ierr); 4495 /* multiply constraints on the right */ 4496 if (numFields) { 4497 for (f = 0; f < numFields; f++) { 4498 PetscInt oldOff = offsets[f]; 4499 4500 for (p = 0; p < numPoints; p++) { 4501 PetscInt cStart = newPointOffsets[f][p]; 4502 PetscInt b = points[2 * p]; 4503 PetscInt c, r, k; 4504 PetscInt dof; 4505 4506 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4507 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4508 PetscInt nCols = newPointOffsets[f][p+1]-cStart; 4509 const PetscScalar *mat = pointMat[f] + pointMatOffsets[f][p]; 4510 4511 for (r = 0; r < numIndices; r++) { 4512 for (c = 0; c < nCols; c++) { 4513 for (k = 0; k < dof; k++) { 4514 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4515 } 4516 } 4517 } 4518 } 4519 else { 4520 /* copy this column as is */ 4521 for (r = 0; r < numIndices; r++) { 4522 for (c = 0; c < dof; c++) { 4523 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4524 } 4525 } 4526 } 4527 oldOff += dof; 4528 } 4529 } 4530 } 4531 else { 4532 PetscInt oldOff = 0; 4533 for (p = 0; p < numPoints; p++) { 4534 PetscInt cStart = newPointOffsets[0][p]; 4535 PetscInt b = points[2 * p]; 4536 PetscInt c, r, k; 4537 PetscInt dof; 4538 4539 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4540 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4541 PetscInt nCols = newPointOffsets[0][p+1]-cStart; 4542 const PetscScalar *mat = pointMat[0] + pointMatOffsets[0][p]; 4543 4544 for (r = 0; r < numIndices; r++) { 4545 for (c = 0; c < nCols; c++) { 4546 for (k = 0; k < dof; k++) { 4547 tmpValues[r * newNumIndices + cStart + c] += mat[k * nCols + c] * values[r * numIndices + oldOff + k]; 4548 } 4549 } 4550 } 4551 } 4552 else { 4553 /* copy this column as is */ 4554 for (r = 0; r < numIndices; r++) { 4555 for (c = 0; c < dof; c++) { 4556 tmpValues[r * newNumIndices + cStart + c] = values[r * numIndices + oldOff + c]; 4557 } 4558 } 4559 } 4560 oldOff += dof; 4561 } 4562 } 4563 4564 ierr = PetscMemzero(newValues,newNumIndices*newNumIndices*sizeof(*newValues));CHKERRQ(ierr); 4565 /* multiply constraints transpose on the left */ 4566 if (numFields) { 4567 for (f = 0; f < numFields; f++) { 4568 PetscInt oldOff = offsets[f]; 4569 4570 for (p = 0; p < numPoints; p++) { 4571 PetscInt rStart = newPointOffsets[f][p]; 4572 PetscInt b = points[2 * p]; 4573 PetscInt c, r, k; 4574 PetscInt dof; 4575 4576 ierr = PetscSectionGetFieldDof(section,b,f,&dof);CHKERRQ(ierr); 4577 if (pointMatOffsets[f][p] < pointMatOffsets[f][p + 1]) { 4578 PetscInt nRows = newPointOffsets[f][p+1]-rStart; 4579 const PetscScalar *PETSC_RESTRICT mat = pointMat[f] + pointMatOffsets[f][p]; 4580 4581 for (r = 0; r < nRows; r++) { 4582 for (c = 0; c < newNumIndices; c++) { 4583 for (k = 0; k < dof; k++) { 4584 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4585 } 4586 } 4587 } 4588 } 4589 else { 4590 /* copy this row as is */ 4591 for (r = 0; r < dof; r++) { 4592 for (c = 0; c < newNumIndices; c++) { 4593 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4594 } 4595 } 4596 } 4597 oldOff += dof; 4598 } 4599 } 4600 } 4601 else { 4602 PetscInt oldOff = 0; 4603 4604 for (p = 0; p < numPoints; p++) { 4605 PetscInt rStart = newPointOffsets[0][p]; 4606 PetscInt b = points[2 * p]; 4607 PetscInt c, r, k; 4608 PetscInt dof; 4609 4610 ierr = PetscSectionGetDof(section,b,&dof);CHKERRQ(ierr); 4611 if (pointMatOffsets[0][p] < pointMatOffsets[0][p + 1]) { 4612 PetscInt nRows = newPointOffsets[0][p+1]-rStart; 4613 const PetscScalar *PETSC_RESTRICT mat = pointMat[0] + pointMatOffsets[0][p]; 4614 4615 for (r = 0; r < nRows; r++) { 4616 for (c = 0; c < newNumIndices; c++) { 4617 for (k = 0; k < dof; k++) { 4618 newValues[(rStart + r) * newNumIndices + c] += mat[k * nRows + r] * tmpValues[(oldOff + k) * newNumIndices + c]; 4619 } 4620 } 4621 } 4622 } 4623 else { 4624 /* copy this row as is */ 4625 for (r = 0; r < dof; c++) { 4626 for (c = 0; c < newNumIndices; c++) { 4627 newValues[(rStart + r) * newNumIndices + c] = tmpValues[(oldOff + r) * newNumIndices + c]; 4628 } 4629 } 4630 } 4631 oldOff += dof; 4632 } 4633 } 4634 4635 /* clean up */ 4636 ierr = DMRestoreWorkArray(dm,maxDof,PETSC_INT,&indices);CHKERRQ(ierr); 4637 ierr = DMRestoreWorkArray(dm,maxAnchor*maxDof,PETSC_INT,&newIndices);CHKERRQ(ierr); 4638 if (numFields) { 4639 for (f = 0; f < numFields; f++) { 4640 ierr = DMRestoreWorkArray(dm,pointMatOffsets[f][numPoints],PETSC_SCALAR,&pointMat[f]);CHKERRQ(ierr); 4641 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[f]);CHKERRQ(ierr); 4642 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[f]);CHKERRQ(ierr); 4643 } 4644 } 4645 else { 4646 ierr = DMRestoreWorkArray(dm,pointMatOffsets[0][numPoints],PETSC_SCALAR,&pointMat[0]);CHKERRQ(ierr); 4647 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&pointMatOffsets[0]);CHKERRQ(ierr); 4648 ierr = DMRestoreWorkArray(dm,numPoints+1,PETSC_INT,&newPointOffsets[0]);CHKERRQ(ierr); 4649 } 4650 ierr = DMRestoreWorkArray(dm,newNumIndices*numIndices,PETSC_SCALAR,&tmpValues);CHKERRQ(ierr); 4651 ierr = ISRestoreIndices(aIS,&anchors);CHKERRQ(ierr); 4652 4653 /* output */ 4654 *outNumPoints = newNumPoints; 4655 *outNumIndices = newNumIndices; 4656 *outPoints = newPoints; 4657 *outValues = newValues; 4658 for (f = 0; f < numFields; f++) { 4659 offsets[f] = newOffsets[f]; 4660 } 4661 PetscFunctionReturn(0); 4662 } 4663 4664 #undef __FUNCT__ 4665 #define __FUNCT__ "DMPlexGetClosureIndices" 4666 PetscErrorCode DMPlexGetClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4667 { 4668 PetscSection clSection; 4669 IS clPoints; 4670 const PetscInt *clp; 4671 PetscInt *points = NULL, *pointsNew; 4672 PetscInt numPoints, numPointsNew; 4673 PetscInt offsets[32]; 4674 PetscInt Nf, Nind, NindNew, off, globalOff, f, p; 4675 PetscErrorCode ierr; 4676 4677 PetscFunctionBegin; 4678 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4679 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4680 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4681 if (numIndices) PetscValidPointer(numIndices, 4); 4682 PetscValidPointer(indices, 5); 4683 ierr = PetscSectionGetNumFields(section, &Nf);CHKERRQ(ierr); 4684 if (Nf > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", Nf); 4685 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4686 /* Get points in closure */ 4687 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4688 if (!clPoints) { 4689 PetscInt pStart, pEnd, q; 4690 4691 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4692 /* Compress out points not in the section */ 4693 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4694 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4695 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4696 points[q*2] = points[p]; 4697 points[q*2+1] = points[p+1]; 4698 ++q; 4699 } 4700 } 4701 numPoints = q; 4702 } else { 4703 PetscInt dof, off; 4704 4705 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4706 numPoints = dof/2; 4707 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4708 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4709 points = (PetscInt *) &clp[off]; 4710 } 4711 /* Get number of indices and indices per field */ 4712 for (p = 0, Nind = 0; p < numPoints*2; p += 2) { 4713 PetscInt dof, fdof; 4714 4715 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4716 for (f = 0; f < Nf; ++f) { 4717 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4718 offsets[f+1] += fdof; 4719 } 4720 Nind += dof; 4721 } 4722 for (f = 1; f < Nf; ++f) offsets[f+1] += offsets[f]; 4723 if (Nf && offsets[Nf] != Nind) SETERRQ2(PetscObjectComm((PetscObject) dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[Nf], Nind); 4724 /* Correct for hanging node constraints */ 4725 { 4726 ierr = DMPlexAnchorsModifyMat(dm, section, numPoints, Nind, points, NULL, &numPointsNew, &NindNew, &pointsNew, NULL, offsets);CHKERRQ(ierr); 4727 if (numPointsNew) { 4728 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4729 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4730 numPoints = numPointsNew; 4731 Nind = NindNew; 4732 points = pointsNew; 4733 } 4734 } 4735 /* Calculate indices */ 4736 ierr = DMGetWorkArray(dm, Nind, PETSC_INT, indices);CHKERRQ(ierr); 4737 if (Nf) { 4738 for (p = 0; p < numPoints*2; p += 2) { 4739 PetscInt o = points[p+1]; 4740 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4741 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, *indices); 4742 } 4743 } else { 4744 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4745 PetscInt o = points[p+1]; 4746 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4747 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, *indices); 4748 } 4749 } 4750 /* Cleanup points */ 4751 if (numPointsNew) { 4752 ierr = DMRestoreWorkArray(dm, 2*numPointsNew, PETSC_INT, &pointsNew);CHKERRQ(ierr); 4753 } else { 4754 if (!clPoints) {ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr);} 4755 else {ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr);} 4756 } 4757 if (numIndices) *numIndices = Nind; 4758 PetscFunctionReturn(0); 4759 } 4760 4761 #undef __FUNCT__ 4762 #define __FUNCT__ "DMPlexRestoreClosureIndices" 4763 PetscErrorCode DMPlexRestoreClosureIndices(DM dm, PetscSection section, PetscSection globalSection, PetscInt point, PetscInt *numIndices, PetscInt **indices) 4764 { 4765 PetscErrorCode ierr; 4766 4767 PetscFunctionBegin; 4768 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4769 PetscValidPointer(indices, 5); 4770 ierr = DMRestoreWorkArray(dm, 0, PETSC_INT, indices);CHKERRQ(ierr); 4771 PetscFunctionReturn(0); 4772 } 4773 4774 #undef __FUNCT__ 4775 #define __FUNCT__ "DMPlexMatSetClosure" 4776 /*@C 4777 DMPlexMatSetClosure - Set an array of the values on the closure of 'point' 4778 4779 Not collective 4780 4781 Input Parameters: 4782 + dm - The DM 4783 . section - The section describing the layout in v, or NULL to use the default section 4784 . globalSection - The section describing the layout in v, or NULL to use the default global section 4785 . A - The matrix 4786 . point - The sieve point in the DM 4787 . values - The array of values 4788 - mode - The insert mode, where INSERT_ALL_VALUES and ADD_ALL_VALUES also overwrite boundary conditions 4789 4790 Fortran Notes: 4791 This routine is only available in Fortran 90, and you must include petsc.h90 in your code. 4792 4793 Level: intermediate 4794 4795 .seealso DMPlexVecGetClosure(), DMPlexVecSetClosure() 4796 @*/ 4797 PetscErrorCode DMPlexMatSetClosure(DM dm, PetscSection section, PetscSection globalSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4798 { 4799 DM_Plex *mesh = (DM_Plex*) dm->data; 4800 PetscSection clSection; 4801 IS clPoints; 4802 PetscInt *points = NULL, *newPoints; 4803 const PetscInt *clp; 4804 PetscInt *indices; 4805 PetscInt offsets[32]; 4806 PetscInt numFields, numPoints, newNumPoints, numIndices, newNumIndices, dof, off, globalOff, pStart, pEnd, p, q, f; 4807 PetscScalar *newValues; 4808 PetscErrorCode ierr; 4809 4810 PetscFunctionBegin; 4811 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 4812 if (!section) {ierr = DMGetDefaultSection(dm, §ion);CHKERRQ(ierr);} 4813 PetscValidHeaderSpecific(section, PETSC_SECTION_CLASSID, 2); 4814 if (!globalSection) {ierr = DMGetDefaultGlobalSection(dm, &globalSection);CHKERRQ(ierr);} 4815 PetscValidHeaderSpecific(globalSection, PETSC_SECTION_CLASSID, 3); 4816 PetscValidHeaderSpecific(A, MAT_CLASSID, 4); 4817 ierr = PetscSectionGetNumFields(section, &numFields);CHKERRQ(ierr); 4818 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4819 ierr = PetscMemzero(offsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4820 ierr = PetscSectionGetClosureIndex(section, (PetscObject) dm, &clSection, &clPoints);CHKERRQ(ierr); 4821 if (!clPoints) { 4822 ierr = DMPlexGetTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4823 /* Compress out points not in the section */ 4824 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 4825 for (p = 0, q = 0; p < numPoints*2; p += 2) { 4826 if ((points[p] >= pStart) && (points[p] < pEnd)) { 4827 points[q*2] = points[p]; 4828 points[q*2+1] = points[p+1]; 4829 ++q; 4830 } 4831 } 4832 numPoints = q; 4833 } else { 4834 PetscInt dof, off; 4835 4836 ierr = PetscSectionGetDof(clSection, point, &dof);CHKERRQ(ierr); 4837 numPoints = dof/2; 4838 ierr = PetscSectionGetOffset(clSection, point, &off);CHKERRQ(ierr); 4839 ierr = ISGetIndices(clPoints, &clp);CHKERRQ(ierr); 4840 points = (PetscInt *) &clp[off]; 4841 } 4842 for (p = 0, numIndices = 0; p < numPoints*2; p += 2) { 4843 PetscInt fdof; 4844 4845 ierr = PetscSectionGetDof(section, points[p], &dof);CHKERRQ(ierr); 4846 for (f = 0; f < numFields; ++f) { 4847 ierr = PetscSectionGetFieldDof(section, points[p], f, &fdof);CHKERRQ(ierr); 4848 offsets[f+1] += fdof; 4849 } 4850 numIndices += dof; 4851 } 4852 for (f = 1; f < numFields; ++f) offsets[f+1] += offsets[f]; 4853 4854 if (numFields && offsets[numFields] != numIndices) SETERRQ2(PetscObjectComm((PetscObject)dm), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", offsets[numFields], numIndices); 4855 ierr = DMPlexAnchorsModifyMat(dm,section,numPoints,numIndices,points,values,&newNumPoints,&newNumIndices,&newPoints,&newValues,offsets);CHKERRQ(ierr); 4856 if (newNumPoints) { 4857 if (!clPoints) { 4858 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4859 } else { 4860 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4861 } 4862 numPoints = newNumPoints; 4863 numIndices = newNumIndices; 4864 points = newPoints; 4865 values = newValues; 4866 } 4867 ierr = DMGetWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4868 if (numFields) { 4869 for (p = 0; p < numPoints*2; p += 2) { 4870 PetscInt o = points[p+1]; 4871 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4872 indicesPointFields_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, offsets, PETSC_FALSE, o, indices); 4873 } 4874 } else { 4875 for (p = 0, off = 0; p < numPoints*2; p += 2) { 4876 PetscInt o = points[p+1]; 4877 ierr = PetscSectionGetOffset(globalSection, points[p], &globalOff);CHKERRQ(ierr); 4878 indicesPoint_private(section, points[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, indices); 4879 } 4880 } 4881 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr);} 4882 ierr = MatSetValues(A, numIndices, indices, numIndices, indices, values, mode); 4883 if (mesh->printFEM > 1) { 4884 PetscInt i; 4885 ierr = PetscPrintf(PETSC_COMM_SELF, " Indices:");CHKERRQ(ierr); 4886 for (i = 0; i < numIndices; ++i) {ierr = PetscPrintf(PETSC_COMM_SELF, " %d", indices[i]);CHKERRQ(ierr);} 4887 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 4888 } 4889 if (ierr) { 4890 PetscMPIInt rank; 4891 PetscErrorCode ierr2; 4892 4893 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 4894 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 4895 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numIndices, indices, 0, NULL, values);CHKERRQ(ierr2); 4896 ierr2 = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr2); 4897 CHKERRQ(ierr); 4898 } 4899 if (newNumPoints) { 4900 ierr = DMRestoreWorkArray(dm,newNumIndices*newNumIndices,PETSC_SCALAR,&newValues);CHKERRQ(ierr); 4901 ierr = DMRestoreWorkArray(dm,2*newNumPoints,PETSC_INT,&newPoints);CHKERRQ(ierr); 4902 } 4903 else { 4904 if (!clPoints) { 4905 ierr = DMPlexRestoreTransitiveClosure(dm, point, PETSC_TRUE, &numPoints, &points);CHKERRQ(ierr); 4906 } else { 4907 ierr = ISRestoreIndices(clPoints, &clp);CHKERRQ(ierr); 4908 } 4909 } 4910 ierr = DMRestoreWorkArray(dm, numIndices, PETSC_INT, &indices);CHKERRQ(ierr); 4911 PetscFunctionReturn(0); 4912 } 4913 4914 #undef __FUNCT__ 4915 #define __FUNCT__ "DMPlexMatSetClosureRefined" 4916 PetscErrorCode DMPlexMatSetClosureRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, Mat A, PetscInt point, const PetscScalar values[], InsertMode mode) 4917 { 4918 DM_Plex *mesh = (DM_Plex*) dmf->data; 4919 PetscInt *fpoints = NULL, *ftotpoints = NULL; 4920 PetscInt *cpoints = NULL; 4921 PetscInt *findices, *cindices; 4922 PetscInt foffsets[32], coffsets[32]; 4923 CellRefiner cellRefiner; 4924 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 4925 PetscErrorCode ierr; 4926 4927 PetscFunctionBegin; 4928 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 4929 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 4930 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 4931 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 4932 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 4933 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 4934 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 4935 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 4936 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 4937 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 4938 PetscValidHeaderSpecific(A, MAT_CLASSID, 7); 4939 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 4940 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 4941 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4942 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 4943 /* Column indices */ 4944 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 4945 maxFPoints = numCPoints; 4946 /* Compress out points not in the section */ 4947 /* TODO: Squeeze out points with 0 dof as well */ 4948 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 4949 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 4950 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 4951 cpoints[q*2] = cpoints[p]; 4952 cpoints[q*2+1] = cpoints[p+1]; 4953 ++q; 4954 } 4955 } 4956 numCPoints = q; 4957 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 4958 PetscInt fdof; 4959 4960 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 4961 if (!dof) continue; 4962 for (f = 0; f < numFields; ++f) { 4963 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 4964 coffsets[f+1] += fdof; 4965 } 4966 numCIndices += dof; 4967 } 4968 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 4969 /* Row indices */ 4970 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 4971 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 4972 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 4973 for (r = 0, q = 0; r < numSubcells; ++r) { 4974 /* TODO Map from coarse to fine cells */ 4975 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4976 /* Compress out points not in the section */ 4977 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 4978 for (p = 0; p < numFPoints*2; p += 2) { 4979 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 4980 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 4981 if (!dof) continue; 4982 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 4983 if (s < q) continue; 4984 ftotpoints[q*2] = fpoints[p]; 4985 ftotpoints[q*2+1] = fpoints[p+1]; 4986 ++q; 4987 } 4988 } 4989 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 4990 } 4991 numFPoints = q; 4992 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 4993 PetscInt fdof; 4994 4995 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 4996 if (!dof) continue; 4997 for (f = 0; f < numFields; ++f) { 4998 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 4999 foffsets[f+1] += fdof; 5000 } 5001 numFIndices += dof; 5002 } 5003 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5004 5005 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5006 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5007 ierr = DMGetWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5008 ierr = DMGetWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5009 if (numFields) { 5010 for (p = 0; p < numFPoints*2; p += 2) { 5011 PetscInt o = ftotpoints[p+1]; 5012 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5013 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5014 } 5015 for (p = 0; p < numCPoints*2; p += 2) { 5016 PetscInt o = cpoints[p+1]; 5017 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5018 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5019 } 5020 } else { 5021 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5022 PetscInt o = ftotpoints[p+1]; 5023 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5024 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5025 } 5026 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5027 PetscInt o = cpoints[p+1]; 5028 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5029 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5030 } 5031 } 5032 if (mesh->printSetValues) {ierr = DMPlexPrintMatSetValues(PETSC_VIEWER_STDOUT_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr);} 5033 ierr = MatSetValues(A, numFIndices, findices, numCIndices, cindices, values, mode); 5034 if (ierr) { 5035 PetscMPIInt rank; 5036 PetscErrorCode ierr2; 5037 5038 ierr2 = MPI_Comm_rank(PetscObjectComm((PetscObject)A), &rank);CHKERRQ(ierr2); 5039 ierr2 = (*PetscErrorPrintf)("[%d]ERROR in DMPlexMatSetClosure\n", rank);CHKERRQ(ierr2); 5040 ierr2 = DMPlexPrintMatSetValues(PETSC_VIEWER_STDERR_SELF, A, point, numFIndices, findices, numCIndices, cindices, values);CHKERRQ(ierr2); 5041 ierr2 = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr2); 5042 ierr2 = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr2); 5043 CHKERRQ(ierr); 5044 } 5045 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5046 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5047 ierr = DMRestoreWorkArray(dmf, numFIndices, PETSC_INT, &findices);CHKERRQ(ierr); 5048 ierr = DMRestoreWorkArray(dmc, numCIndices, PETSC_INT, &cindices);CHKERRQ(ierr); 5049 PetscFunctionReturn(0); 5050 } 5051 5052 #undef __FUNCT__ 5053 #define __FUNCT__ "DMPlexMatGetClosureIndicesRefined" 5054 PetscErrorCode DMPlexMatGetClosureIndicesRefined(DM dmf, PetscSection fsection, PetscSection globalFSection, DM dmc, PetscSection csection, PetscSection globalCSection, PetscInt point, PetscInt cindices[], PetscInt findices[]) 5055 { 5056 PetscInt *fpoints = NULL, *ftotpoints = NULL; 5057 PetscInt *cpoints = NULL; 5058 PetscInt foffsets[32], coffsets[32]; 5059 CellRefiner cellRefiner; 5060 PetscInt numFields, numSubcells, maxFPoints, numFPoints, numCPoints, numFIndices, numCIndices, dof, off, globalOff, pStart, pEnd, p, q, r, s, f; 5061 PetscErrorCode ierr; 5062 5063 PetscFunctionBegin; 5064 PetscValidHeaderSpecific(dmf, DM_CLASSID, 1); 5065 PetscValidHeaderSpecific(dmc, DM_CLASSID, 4); 5066 if (!fsection) {ierr = DMGetDefaultSection(dmf, &fsection);CHKERRQ(ierr);} 5067 PetscValidHeaderSpecific(fsection, PETSC_SECTION_CLASSID, 2); 5068 if (!csection) {ierr = DMGetDefaultSection(dmc, &csection);CHKERRQ(ierr);} 5069 PetscValidHeaderSpecific(csection, PETSC_SECTION_CLASSID, 5); 5070 if (!globalFSection) {ierr = DMGetDefaultGlobalSection(dmf, &globalFSection);CHKERRQ(ierr);} 5071 PetscValidHeaderSpecific(globalFSection, PETSC_SECTION_CLASSID, 3); 5072 if (!globalCSection) {ierr = DMGetDefaultGlobalSection(dmc, &globalCSection);CHKERRQ(ierr);} 5073 PetscValidHeaderSpecific(globalCSection, PETSC_SECTION_CLASSID, 6); 5074 ierr = PetscSectionGetNumFields(fsection, &numFields);CHKERRQ(ierr); 5075 if (numFields > 31) SETERRQ1(PetscObjectComm((PetscObject)dmf), PETSC_ERR_ARG_OUTOFRANGE, "Number of fields %D limited to 31", numFields); 5076 ierr = PetscMemzero(foffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5077 ierr = PetscMemzero(coffsets, 32 * sizeof(PetscInt));CHKERRQ(ierr); 5078 /* Column indices */ 5079 ierr = DMPlexGetTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5080 maxFPoints = numCPoints; 5081 /* Compress out points not in the section */ 5082 /* TODO: Squeeze out points with 0 dof as well */ 5083 ierr = PetscSectionGetChart(csection, &pStart, &pEnd);CHKERRQ(ierr); 5084 for (p = 0, q = 0; p < numCPoints*2; p += 2) { 5085 if ((cpoints[p] >= pStart) && (cpoints[p] < pEnd)) { 5086 cpoints[q*2] = cpoints[p]; 5087 cpoints[q*2+1] = cpoints[p+1]; 5088 ++q; 5089 } 5090 } 5091 numCPoints = q; 5092 for (p = 0, numCIndices = 0; p < numCPoints*2; p += 2) { 5093 PetscInt fdof; 5094 5095 ierr = PetscSectionGetDof(csection, cpoints[p], &dof);CHKERRQ(ierr); 5096 if (!dof) continue; 5097 for (f = 0; f < numFields; ++f) { 5098 ierr = PetscSectionGetFieldDof(csection, cpoints[p], f, &fdof);CHKERRQ(ierr); 5099 coffsets[f+1] += fdof; 5100 } 5101 numCIndices += dof; 5102 } 5103 for (f = 1; f < numFields; ++f) coffsets[f+1] += coffsets[f]; 5104 /* Row indices */ 5105 ierr = DMPlexGetCellRefiner_Internal(dmc, &cellRefiner);CHKERRQ(ierr); 5106 ierr = CellRefinerGetAffineTransforms_Internal(cellRefiner, &numSubcells, NULL, NULL, NULL);CHKERRQ(ierr); 5107 ierr = DMGetWorkArray(dmf, maxFPoints*2*numSubcells, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5108 for (r = 0, q = 0; r < numSubcells; ++r) { 5109 /* TODO Map from coarse to fine cells */ 5110 ierr = DMPlexGetTransitiveClosure(dmf, point*numSubcells + r, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5111 /* Compress out points not in the section */ 5112 ierr = PetscSectionGetChart(fsection, &pStart, &pEnd);CHKERRQ(ierr); 5113 for (p = 0; p < numFPoints*2; p += 2) { 5114 if ((fpoints[p] >= pStart) && (fpoints[p] < pEnd)) { 5115 ierr = PetscSectionGetDof(fsection, fpoints[p], &dof);CHKERRQ(ierr); 5116 if (!dof) continue; 5117 for (s = 0; s < q; ++s) if (fpoints[p] == ftotpoints[s*2]) break; 5118 if (s < q) continue; 5119 ftotpoints[q*2] = fpoints[p]; 5120 ftotpoints[q*2+1] = fpoints[p+1]; 5121 ++q; 5122 } 5123 } 5124 ierr = DMPlexRestoreTransitiveClosure(dmf, point, PETSC_TRUE, &numFPoints, &fpoints);CHKERRQ(ierr); 5125 } 5126 numFPoints = q; 5127 for (p = 0, numFIndices = 0; p < numFPoints*2; p += 2) { 5128 PetscInt fdof; 5129 5130 ierr = PetscSectionGetDof(fsection, ftotpoints[p], &dof);CHKERRQ(ierr); 5131 if (!dof) continue; 5132 for (f = 0; f < numFields; ++f) { 5133 ierr = PetscSectionGetFieldDof(fsection, ftotpoints[p], f, &fdof);CHKERRQ(ierr); 5134 foffsets[f+1] += fdof; 5135 } 5136 numFIndices += dof; 5137 } 5138 for (f = 1; f < numFields; ++f) foffsets[f+1] += foffsets[f]; 5139 5140 if (numFields && foffsets[numFields] != numFIndices) SETERRQ2(PetscObjectComm((PetscObject)dmf), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", foffsets[numFields], numFIndices); 5141 if (numFields && coffsets[numFields] != numCIndices) SETERRQ2(PetscObjectComm((PetscObject)dmc), PETSC_ERR_PLIB, "Invalid size for closure %d should be %d", coffsets[numFields], numCIndices); 5142 if (numFields) { 5143 for (p = 0; p < numFPoints*2; p += 2) { 5144 PetscInt o = ftotpoints[p+1]; 5145 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5146 indicesPointFields_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, foffsets, PETSC_FALSE, o, findices); 5147 } 5148 for (p = 0; p < numCPoints*2; p += 2) { 5149 PetscInt o = cpoints[p+1]; 5150 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5151 indicesPointFields_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, coffsets, PETSC_FALSE, o, cindices); 5152 } 5153 } else { 5154 for (p = 0, off = 0; p < numFPoints*2; p += 2) { 5155 PetscInt o = ftotpoints[p+1]; 5156 ierr = PetscSectionGetOffset(globalFSection, ftotpoints[p], &globalOff);CHKERRQ(ierr); 5157 indicesPoint_private(fsection, ftotpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, findices); 5158 } 5159 for (p = 0, off = 0; p < numCPoints*2; p += 2) { 5160 PetscInt o = cpoints[p+1]; 5161 ierr = PetscSectionGetOffset(globalCSection, cpoints[p], &globalOff);CHKERRQ(ierr); 5162 indicesPoint_private(csection, cpoints[p], globalOff < 0 ? -(globalOff+1) : globalOff, &off, PETSC_FALSE, o, cindices); 5163 } 5164 } 5165 ierr = DMRestoreWorkArray(dmf, numCPoints*2*4, PETSC_INT, &ftotpoints);CHKERRQ(ierr); 5166 ierr = DMPlexRestoreTransitiveClosure(dmc, point, PETSC_TRUE, &numCPoints, &cpoints);CHKERRQ(ierr); 5167 PetscFunctionReturn(0); 5168 } 5169 5170 #undef __FUNCT__ 5171 #define __FUNCT__ "DMPlexGetHybridBounds" 5172 /*@ 5173 DMPlexGetHybridBounds - Get the first mesh point of each dimension which is a hybrid 5174 5175 Input Parameter: 5176 . dm - The DMPlex object 5177 5178 Output Parameters: 5179 + cMax - The first hybrid cell 5180 . fMax - The first hybrid face 5181 . eMax - The first hybrid edge 5182 - vMax - The first hybrid vertex 5183 5184 Level: developer 5185 5186 .seealso DMPlexCreateHybridMesh(), DMPlexSetHybridBounds() 5187 @*/ 5188 PetscErrorCode DMPlexGetHybridBounds(DM dm, PetscInt *cMax, PetscInt *fMax, PetscInt *eMax, PetscInt *vMax) 5189 { 5190 DM_Plex *mesh = (DM_Plex*) dm->data; 5191 PetscInt dim; 5192 PetscErrorCode ierr; 5193 5194 PetscFunctionBegin; 5195 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5196 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5197 if (cMax) *cMax = mesh->hybridPointMax[dim]; 5198 if (fMax) *fMax = mesh->hybridPointMax[dim-1]; 5199 if (eMax) *eMax = mesh->hybridPointMax[1]; 5200 if (vMax) *vMax = mesh->hybridPointMax[0]; 5201 PetscFunctionReturn(0); 5202 } 5203 5204 #undef __FUNCT__ 5205 #define __FUNCT__ "DMPlexSetHybridBounds" 5206 /*@ 5207 DMPlexSetHybridBounds - Set the first mesh point of each dimension which is a hybrid 5208 5209 Input Parameters: 5210 . dm - The DMPlex object 5211 . cMax - The first hybrid cell 5212 . fMax - The first hybrid face 5213 . eMax - The first hybrid edge 5214 - vMax - The first hybrid vertex 5215 5216 Level: developer 5217 5218 .seealso DMPlexCreateHybridMesh(), DMPlexGetHybridBounds() 5219 @*/ 5220 PetscErrorCode DMPlexSetHybridBounds(DM dm, PetscInt cMax, PetscInt fMax, PetscInt eMax, PetscInt vMax) 5221 { 5222 DM_Plex *mesh = (DM_Plex*) dm->data; 5223 PetscInt dim; 5224 PetscErrorCode ierr; 5225 5226 PetscFunctionBegin; 5227 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5228 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5229 if (cMax >= 0) mesh->hybridPointMax[dim] = cMax; 5230 if (fMax >= 0) mesh->hybridPointMax[dim-1] = fMax; 5231 if (eMax >= 0) mesh->hybridPointMax[1] = eMax; 5232 if (vMax >= 0) mesh->hybridPointMax[0] = vMax; 5233 PetscFunctionReturn(0); 5234 } 5235 5236 #undef __FUNCT__ 5237 #define __FUNCT__ "DMPlexGetVTKCellHeight" 5238 PetscErrorCode DMPlexGetVTKCellHeight(DM dm, PetscInt *cellHeight) 5239 { 5240 DM_Plex *mesh = (DM_Plex*) dm->data; 5241 5242 PetscFunctionBegin; 5243 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5244 PetscValidPointer(cellHeight, 2); 5245 *cellHeight = mesh->vtkCellHeight; 5246 PetscFunctionReturn(0); 5247 } 5248 5249 #undef __FUNCT__ 5250 #define __FUNCT__ "DMPlexSetVTKCellHeight" 5251 PetscErrorCode DMPlexSetVTKCellHeight(DM dm, PetscInt cellHeight) 5252 { 5253 DM_Plex *mesh = (DM_Plex*) dm->data; 5254 5255 PetscFunctionBegin; 5256 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5257 mesh->vtkCellHeight = cellHeight; 5258 PetscFunctionReturn(0); 5259 } 5260 5261 #undef __FUNCT__ 5262 #define __FUNCT__ "DMPlexCreateNumbering_Private" 5263 /* We can easily have a form that takes an IS instead */ 5264 static PetscErrorCode DMPlexCreateNumbering_Private(DM dm, PetscInt pStart, PetscInt pEnd, PetscInt shift, PetscInt *globalSize, PetscSF sf, IS *numbering) 5265 { 5266 PetscSection section, globalSection; 5267 PetscInt *numbers, p; 5268 PetscErrorCode ierr; 5269 5270 PetscFunctionBegin; 5271 ierr = PetscSectionCreate(PetscObjectComm((PetscObject)dm), §ion);CHKERRQ(ierr); 5272 ierr = PetscSectionSetChart(section, pStart, pEnd);CHKERRQ(ierr); 5273 for (p = pStart; p < pEnd; ++p) { 5274 ierr = PetscSectionSetDof(section, p, 1);CHKERRQ(ierr); 5275 } 5276 ierr = PetscSectionSetUp(section);CHKERRQ(ierr); 5277 ierr = PetscSectionCreateGlobalSection(section, sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 5278 ierr = PetscMalloc1(pEnd - pStart, &numbers);CHKERRQ(ierr); 5279 for (p = pStart; p < pEnd; ++p) { 5280 ierr = PetscSectionGetOffset(globalSection, p, &numbers[p-pStart]);CHKERRQ(ierr); 5281 if (numbers[p-pStart] < 0) numbers[p-pStart] -= shift; 5282 else numbers[p-pStart] += shift; 5283 } 5284 ierr = ISCreateGeneral(PetscObjectComm((PetscObject) dm), pEnd - pStart, numbers, PETSC_OWN_POINTER, numbering);CHKERRQ(ierr); 5285 if (globalSize) { 5286 PetscLayout layout; 5287 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject) dm), globalSection, &layout);CHKERRQ(ierr); 5288 ierr = PetscLayoutGetSize(layout, globalSize);CHKERRQ(ierr); 5289 ierr = PetscLayoutDestroy(&layout);CHKERRQ(ierr); 5290 } 5291 ierr = PetscSectionDestroy(§ion);CHKERRQ(ierr); 5292 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 5293 PetscFunctionReturn(0); 5294 } 5295 5296 #undef __FUNCT__ 5297 #define __FUNCT__ "DMPlexGetCellNumbering" 5298 PetscErrorCode DMPlexGetCellNumbering(DM dm, IS *globalCellNumbers) 5299 { 5300 DM_Plex *mesh = (DM_Plex*) dm->data; 5301 PetscInt cellHeight, cStart, cEnd, cMax; 5302 PetscErrorCode ierr; 5303 5304 PetscFunctionBegin; 5305 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5306 if (!mesh->globalCellNumbers) { 5307 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 5308 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5309 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5310 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 5311 ierr = DMPlexCreateNumbering_Private(dm, cStart, cEnd, 0, NULL, dm->sf, &mesh->globalCellNumbers);CHKERRQ(ierr); 5312 } 5313 *globalCellNumbers = mesh->globalCellNumbers; 5314 PetscFunctionReturn(0); 5315 } 5316 5317 #undef __FUNCT__ 5318 #define __FUNCT__ "DMPlexGetVertexNumbering" 5319 PetscErrorCode DMPlexGetVertexNumbering(DM dm, IS *globalVertexNumbers) 5320 { 5321 DM_Plex *mesh = (DM_Plex*) dm->data; 5322 PetscInt vStart, vEnd, vMax; 5323 PetscErrorCode ierr; 5324 5325 PetscFunctionBegin; 5326 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5327 if (!mesh->globalVertexNumbers) { 5328 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5329 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 5330 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 5331 ierr = DMPlexCreateNumbering_Private(dm, vStart, vEnd, 0, NULL, dm->sf, &mesh->globalVertexNumbers);CHKERRQ(ierr); 5332 } 5333 *globalVertexNumbers = mesh->globalVertexNumbers; 5334 PetscFunctionReturn(0); 5335 } 5336 5337 #undef __FUNCT__ 5338 #define __FUNCT__ "DMPlexCreatePointNumbering" 5339 PetscErrorCode DMPlexCreatePointNumbering(DM dm, IS *globalPointNumbers) 5340 { 5341 IS nums[4]; 5342 PetscInt depths[4]; 5343 PetscInt depth, d, shift = 0; 5344 PetscErrorCode ierr; 5345 5346 PetscFunctionBegin; 5347 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5348 ierr = DMPlexGetDepth(dm, &depth);CHKERRQ(ierr); 5349 /* For unstratified meshes use dim instead of depth */ 5350 if (depth < 0) {ierr = DMGetDimension(dm, &depth);CHKERRQ(ierr);} 5351 depths[0] = depth; depths[1] = 0; 5352 for (d = 2; d <= depth; ++d) depths[d] = depth-d+1; 5353 for (d = 0; d <= depth; ++d) { 5354 PetscInt pStart, pEnd, gsize; 5355 5356 ierr = DMPlexGetDepthStratum(dm, depths[d], &pStart, &pEnd);CHKERRQ(ierr); 5357 ierr = DMPlexCreateNumbering_Private(dm, pStart, pEnd, shift, &gsize, dm->sf, &nums[d]);CHKERRQ(ierr); 5358 shift += gsize; 5359 } 5360 ierr = ISConcatenate(PetscObjectComm((PetscObject) dm), depth+1, nums, globalPointNumbers);CHKERRQ(ierr); 5361 for (d = 0; d <= depth; ++d) {ierr = ISDestroy(&nums[d]);CHKERRQ(ierr);} 5362 PetscFunctionReturn(0); 5363 } 5364 5365 5366 #undef __FUNCT__ 5367 #define __FUNCT__ "PetscSectionCreateGlobalSectionLabel" 5368 /*@C 5369 PetscSectionCreateGlobalSectionLabel - Create a section describing the global field layout using 5370 the local section and an SF describing the section point overlap. 5371 5372 Input Parameters: 5373 + s - The PetscSection for the local field layout 5374 . sf - The SF describing parallel layout of the section points 5375 . includeConstraints - By default this is PETSC_FALSE, meaning that the global field vector will not possess constrained dofs 5376 . label - The label specifying the points 5377 - labelValue - The label stratum specifying the points 5378 5379 Output Parameter: 5380 . gsection - The PetscSection for the global field layout 5381 5382 Note: This gives negative sizes and offsets to points not owned by this process 5383 5384 Level: developer 5385 5386 .seealso: PetscSectionCreate() 5387 @*/ 5388 PetscErrorCode PetscSectionCreateGlobalSectionLabel(PetscSection s, PetscSF sf, PetscBool includeConstraints, DMLabel label, PetscInt labelValue, PetscSection *gsection) 5389 { 5390 PetscInt *neg = NULL, *tmpOff = NULL; 5391 PetscInt pStart, pEnd, p, dof, cdof, off, globalOff = 0, nroots; 5392 PetscErrorCode ierr; 5393 5394 PetscFunctionBegin; 5395 ierr = PetscSectionCreate(PetscObjectComm((PetscObject) s), gsection);CHKERRQ(ierr); 5396 ierr = PetscSectionGetChart(s, &pStart, &pEnd);CHKERRQ(ierr); 5397 ierr = PetscSectionSetChart(*gsection, pStart, pEnd);CHKERRQ(ierr); 5398 ierr = PetscSFGetGraph(sf, &nroots, NULL, NULL, NULL);CHKERRQ(ierr); 5399 if (nroots >= 0) { 5400 if (nroots < pEnd-pStart) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "PetscSF nroots %d < %d section size", nroots, pEnd-pStart); 5401 ierr = PetscCalloc1(nroots, &neg);CHKERRQ(ierr); 5402 if (nroots > pEnd-pStart) { 5403 ierr = PetscCalloc1(nroots, &tmpOff);CHKERRQ(ierr); 5404 } else { 5405 tmpOff = &(*gsection)->atlasDof[-pStart]; 5406 } 5407 } 5408 /* Mark ghost points with negative dof */ 5409 for (p = pStart; p < pEnd; ++p) { 5410 PetscInt value; 5411 5412 ierr = DMLabelGetValue(label, p, &value);CHKERRQ(ierr); 5413 if (value != labelValue) continue; 5414 ierr = PetscSectionGetDof(s, p, &dof);CHKERRQ(ierr); 5415 ierr = PetscSectionSetDof(*gsection, p, dof);CHKERRQ(ierr); 5416 ierr = PetscSectionGetConstraintDof(s, p, &cdof);CHKERRQ(ierr); 5417 if (!includeConstraints && cdof > 0) {ierr = PetscSectionSetConstraintDof(*gsection, p, cdof);CHKERRQ(ierr);} 5418 if (neg) neg[p] = -(dof+1); 5419 } 5420 ierr = PetscSectionSetUpBC(*gsection);CHKERRQ(ierr); 5421 if (nroots >= 0) { 5422 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5423 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5424 if (nroots > pEnd-pStart) { 5425 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasDof[p-pStart] = tmpOff[p];} 5426 } 5427 } 5428 /* Calculate new sizes, get proccess offset, and calculate point offsets */ 5429 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5430 cdof = (!includeConstraints && s->bc) ? s->bc->atlasDof[p] : 0; 5431 (*gsection)->atlasOff[p] = off; 5432 off += (*gsection)->atlasDof[p] > 0 ? (*gsection)->atlasDof[p]-cdof : 0; 5433 } 5434 ierr = MPI_Scan(&off, &globalOff, 1, MPIU_INT, MPI_SUM, PetscObjectComm((PetscObject) s));CHKERRQ(ierr); 5435 globalOff -= off; 5436 for (p = 0, off = 0; p < pEnd-pStart; ++p) { 5437 (*gsection)->atlasOff[p] += globalOff; 5438 if (neg) neg[p] = -((*gsection)->atlasOff[p]+1); 5439 } 5440 /* Put in negative offsets for ghost points */ 5441 if (nroots >= 0) { 5442 ierr = PetscSFBcastBegin(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5443 ierr = PetscSFBcastEnd(sf, MPIU_INT, neg, tmpOff);CHKERRQ(ierr); 5444 if (nroots > pEnd-pStart) { 5445 for (p = pStart; p < pEnd; ++p) {if (tmpOff[p] < 0) (*gsection)->atlasOff[p-pStart] = tmpOff[p];} 5446 } 5447 } 5448 if (nroots >= 0 && nroots > pEnd-pStart) {ierr = PetscFree(tmpOff);CHKERRQ(ierr);} 5449 ierr = PetscFree(neg);CHKERRQ(ierr); 5450 PetscFunctionReturn(0); 5451 } 5452 5453 #undef __FUNCT__ 5454 #define __FUNCT__ "DMPlexCheckSymmetry" 5455 /*@ 5456 DMPlexCheckSymmetry - Check that the adjacency information in the mesh is symmetric. 5457 5458 Input Parameters: 5459 + dm - The DMPlex object 5460 5461 Note: This is a useful diagnostic when creating meshes programmatically. 5462 5463 Level: developer 5464 5465 .seealso: DMCreate(), DMCheckSkeleton(), DMCheckFaces() 5466 @*/ 5467 PetscErrorCode DMPlexCheckSymmetry(DM dm) 5468 { 5469 PetscSection coneSection, supportSection; 5470 const PetscInt *cone, *support; 5471 PetscInt coneSize, c, supportSize, s; 5472 PetscInt pStart, pEnd, p, csize, ssize; 5473 PetscErrorCode ierr; 5474 5475 PetscFunctionBegin; 5476 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5477 ierr = DMPlexGetConeSection(dm, &coneSection);CHKERRQ(ierr); 5478 ierr = DMPlexGetSupportSection(dm, &supportSection);CHKERRQ(ierr); 5479 /* Check that point p is found in the support of its cone points, and vice versa */ 5480 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 5481 for (p = pStart; p < pEnd; ++p) { 5482 ierr = DMPlexGetConeSize(dm, p, &coneSize);CHKERRQ(ierr); 5483 ierr = DMPlexGetCone(dm, p, &cone);CHKERRQ(ierr); 5484 for (c = 0; c < coneSize; ++c) { 5485 PetscBool dup = PETSC_FALSE; 5486 PetscInt d; 5487 for (d = c-1; d >= 0; --d) { 5488 if (cone[c] == cone[d]) {dup = PETSC_TRUE; break;} 5489 } 5490 ierr = DMPlexGetSupportSize(dm, cone[c], &supportSize);CHKERRQ(ierr); 5491 ierr = DMPlexGetSupport(dm, cone[c], &support);CHKERRQ(ierr); 5492 for (s = 0; s < supportSize; ++s) { 5493 if (support[s] == p) break; 5494 } 5495 if ((s >= supportSize) || (dup && (support[s+1] != p))) { 5496 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", p);CHKERRQ(ierr); 5497 for (s = 0; s < coneSize; ++s) { 5498 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[s]);CHKERRQ(ierr); 5499 } 5500 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5501 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", cone[c]);CHKERRQ(ierr); 5502 for (s = 0; s < supportSize; ++s) { 5503 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[s]);CHKERRQ(ierr); 5504 } 5505 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5506 if (dup) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not repeatedly found in support of repeated cone point %d", p, cone[c]); 5507 else SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in support of cone point %d", p, cone[c]); 5508 } 5509 } 5510 ierr = DMPlexGetSupportSize(dm, p, &supportSize);CHKERRQ(ierr); 5511 ierr = DMPlexGetSupport(dm, p, &support);CHKERRQ(ierr); 5512 for (s = 0; s < supportSize; ++s) { 5513 ierr = DMPlexGetConeSize(dm, support[s], &coneSize);CHKERRQ(ierr); 5514 ierr = DMPlexGetCone(dm, support[s], &cone);CHKERRQ(ierr); 5515 for (c = 0; c < coneSize; ++c) { 5516 if (cone[c] == p) break; 5517 } 5518 if (c >= coneSize) { 5519 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d support: ", p);CHKERRQ(ierr); 5520 for (c = 0; c < supportSize; ++c) { 5521 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", support[c]);CHKERRQ(ierr); 5522 } 5523 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5524 ierr = PetscPrintf(PETSC_COMM_SELF, "p: %d cone: ", support[s]);CHKERRQ(ierr); 5525 for (c = 0; c < coneSize; ++c) { 5526 ierr = PetscPrintf(PETSC_COMM_SELF, "%d, ", cone[c]);CHKERRQ(ierr); 5527 } 5528 ierr = PetscPrintf(PETSC_COMM_SELF, "\n");CHKERRQ(ierr); 5529 SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_PLIB, "Point %d not found in cone of support point %d", p, support[s]); 5530 } 5531 } 5532 } 5533 ierr = PetscSectionGetStorageSize(coneSection, &csize);CHKERRQ(ierr); 5534 ierr = PetscSectionGetStorageSize(supportSection, &ssize);CHKERRQ(ierr); 5535 if (csize != ssize) SETERRQ2(PETSC_COMM_SELF, PETSC_ERR_ARG_SIZ, "Total cone size %d != Total support size %d", csize, ssize); 5536 PetscFunctionReturn(0); 5537 } 5538 5539 #undef __FUNCT__ 5540 #define __FUNCT__ "DMPlexCheckSkeleton" 5541 /*@ 5542 DMPlexCheckSkeleton - Check that each cell has the correct number of vertices 5543 5544 Input Parameters: 5545 + dm - The DMPlex object 5546 . isSimplex - Are the cells simplices or tensor products 5547 - cellHeight - Normally 0 5548 5549 Note: This is a useful diagnostic when creating meshes programmatically. 5550 5551 Level: developer 5552 5553 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckFaces() 5554 @*/ 5555 PetscErrorCode DMPlexCheckSkeleton(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5556 { 5557 PetscInt dim, numCorners, numHybridCorners, vStart, vEnd, cStart, cEnd, cMax, c; 5558 PetscErrorCode ierr; 5559 5560 PetscFunctionBegin; 5561 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5562 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5563 switch (dim) { 5564 case 1: numCorners = isSimplex ? 2 : 2; numHybridCorners = isSimplex ? 2 : 2; break; 5565 case 2: numCorners = isSimplex ? 3 : 4; numHybridCorners = isSimplex ? 4 : 4; break; 5566 case 3: numCorners = isSimplex ? 4 : 8; numHybridCorners = isSimplex ? 6 : 8; break; 5567 default: 5568 SETERRQ1(PetscObjectComm((PetscObject) dm), PETSC_ERR_ARG_OUTOFRANGE, "Cannot handle meshes of dimension %d", dim); 5569 } 5570 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5571 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 5572 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 5573 cMax = cMax >= 0 ? cMax : cEnd; 5574 for (c = cStart; c < cMax; ++c) { 5575 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5576 5577 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5578 for (cl = 0; cl < closureSize*2; cl += 2) { 5579 const PetscInt p = closure[cl]; 5580 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5581 } 5582 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5583 if (coneSize != numCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d vertices != %d", c, coneSize, numCorners); 5584 } 5585 for (c = cMax; c < cEnd; ++c) { 5586 PetscInt *closure = NULL, closureSize, cl, coneSize = 0; 5587 5588 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5589 for (cl = 0; cl < closureSize*2; cl += 2) { 5590 const PetscInt p = closure[cl]; 5591 if ((p >= vStart) && (p < vEnd)) ++coneSize; 5592 } 5593 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5594 if (coneSize > numHybridCorners) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Hybrid cell %d has %d vertices > %d", c, coneSize, numHybridCorners); 5595 } 5596 PetscFunctionReturn(0); 5597 } 5598 5599 #undef __FUNCT__ 5600 #define __FUNCT__ "DMPlexCheckFaces" 5601 /*@ 5602 DMPlexCheckFaces - Check that the faces of each cell give a vertex order this is consistent with what we expect from the cell type 5603 5604 Input Parameters: 5605 + dm - The DMPlex object 5606 . isSimplex - Are the cells simplices or tensor products 5607 - cellHeight - Normally 0 5608 5609 Note: This is a useful diagnostic when creating meshes programmatically. 5610 5611 Level: developer 5612 5613 .seealso: DMCreate(), DMCheckSymmetry(), DMCheckSkeleton() 5614 @*/ 5615 PetscErrorCode DMPlexCheckFaces(DM dm, PetscBool isSimplex, PetscInt cellHeight) 5616 { 5617 PetscInt pMax[4]; 5618 PetscInt dim, vStart, vEnd, cStart, cEnd, c, h; 5619 PetscErrorCode ierr; 5620 5621 PetscFunctionBegin; 5622 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 5623 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 5624 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 5625 ierr = DMPlexGetHybridBounds(dm, &pMax[dim], &pMax[dim-1], &pMax[1], &pMax[0]);CHKERRQ(ierr); 5626 for (h = cellHeight; h < dim; ++h) { 5627 ierr = DMPlexGetHeightStratum(dm, h, &cStart, &cEnd);CHKERRQ(ierr); 5628 for (c = cStart; c < cEnd; ++c) { 5629 const PetscInt *cone, *ornt, *faces; 5630 PetscInt numFaces, faceSize, coneSize,f; 5631 PetscInt *closure = NULL, closureSize, cl, numCorners = 0; 5632 5633 if (pMax[dim-h] >= 0 && c >= pMax[dim-h]) continue; 5634 ierr = DMPlexGetConeSize(dm, c, &coneSize);CHKERRQ(ierr); 5635 ierr = DMPlexGetCone(dm, c, &cone);CHKERRQ(ierr); 5636 ierr = DMPlexGetConeOrientation(dm, c, &ornt);CHKERRQ(ierr); 5637 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5638 for (cl = 0; cl < closureSize*2; cl += 2) { 5639 const PetscInt p = closure[cl]; 5640 if ((p >= vStart) && (p < vEnd)) closure[numCorners++] = p; 5641 } 5642 ierr = DMPlexGetRawFaces_Internal(dm, dim-h, numCorners, closure, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5643 if (coneSize != numFaces) SETERRQ3(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Cell %d has %d faces but should have %d", c, coneSize, numFaces); 5644 for (f = 0; f < numFaces; ++f) { 5645 PetscInt *fclosure = NULL, fclosureSize, cl, fnumCorners = 0, v; 5646 5647 ierr = DMPlexGetTransitiveClosure_Internal(dm, cone[f], ornt[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5648 for (cl = 0; cl < fclosureSize*2; cl += 2) { 5649 const PetscInt p = fclosure[cl]; 5650 if ((p >= vStart) && (p < vEnd)) fclosure[fnumCorners++] = p; 5651 } 5652 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); 5653 for (v = 0; v < fnumCorners; ++v) { 5654 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]); 5655 } 5656 ierr = DMPlexRestoreTransitiveClosure(dm, cone[f], PETSC_TRUE, &fclosureSize, &fclosure);CHKERRQ(ierr); 5657 } 5658 ierr = DMPlexRestoreFaces_Internal(dm, dim, c, &numFaces, &faceSize, &faces);CHKERRQ(ierr); 5659 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 5660 } 5661 } 5662 PetscFunctionReturn(0); 5663 } 5664 5665 #undef __FUNCT__ 5666 #define __FUNCT__ "DMCreateInterpolation_Plex" 5667 /* Pointwise interpolation 5668 Just code FEM for now 5669 u^f = I u^c 5670 sum_k u^f_k phi^f_k = I sum_j u^c_j phi^c_j 5671 u^f_i = sum_j psi^f_i I phi^c_j u^c_j 5672 I_{ij} = psi^f_i phi^c_j 5673 */ 5674 PetscErrorCode DMCreateInterpolation_Plex(DM dmCoarse, DM dmFine, Mat *interpolation, Vec *scaling) 5675 { 5676 PetscSection gsc, gsf; 5677 PetscInt m, n; 5678 void *ctx; 5679 DM cdm; 5680 PetscBool regular; 5681 PetscErrorCode ierr; 5682 5683 PetscFunctionBegin; 5684 ierr = DMGetDefaultGlobalSection(dmFine, &gsf);CHKERRQ(ierr); 5685 ierr = PetscSectionGetConstrainedStorageSize(gsf, &m);CHKERRQ(ierr); 5686 ierr = DMGetDefaultGlobalSection(dmCoarse, &gsc);CHKERRQ(ierr); 5687 ierr = PetscSectionGetConstrainedStorageSize(gsc, &n);CHKERRQ(ierr); 5688 5689 ierr = MatCreate(PetscObjectComm((PetscObject) dmCoarse), interpolation);CHKERRQ(ierr); 5690 ierr = MatSetSizes(*interpolation, m, n, PETSC_DETERMINE, PETSC_DETERMINE);CHKERRQ(ierr); 5691 ierr = MatSetType(*interpolation, dmCoarse->mattype);CHKERRQ(ierr); 5692 ierr = DMGetApplicationContext(dmFine, &ctx);CHKERRQ(ierr); 5693 5694 ierr = DMPlexGetCoarseDM(dmFine, &cdm);CHKERRQ(ierr); 5695 ierr = DMPlexGetRegularRefinement(dmFine, ®ular);CHKERRQ(ierr); 5696 if (regular && cdm == dmCoarse) {ierr = DMPlexComputeInterpolatorNested(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5697 else {ierr = DMPlexComputeInterpolatorGeneral(dmCoarse, dmFine, *interpolation, ctx);CHKERRQ(ierr);} 5698 ierr = MatViewFromOptions(*interpolation, NULL, "-interp_mat_view");CHKERRQ(ierr); 5699 /* Use naive scaling */ 5700 ierr = DMCreateInterpolationScale(dmCoarse, dmFine, *interpolation, scaling);CHKERRQ(ierr); 5701 PetscFunctionReturn(0); 5702 } 5703 5704 #undef __FUNCT__ 5705 #define __FUNCT__ "DMCreateInjection_Plex" 5706 PetscErrorCode DMCreateInjection_Plex(DM dmCoarse, DM dmFine, Mat *mat) 5707 { 5708 PetscErrorCode ierr; 5709 VecScatter ctx; 5710 5711 PetscFunctionBegin; 5712 ierr = DMPlexComputeInjectorFEM(dmCoarse, dmFine, &ctx, NULL);CHKERRQ(ierr); 5713 ierr = MatCreateScatter(PetscObjectComm((PetscObject)ctx), ctx, mat);CHKERRQ(ierr); 5714 ierr = VecScatterDestroy(&ctx);CHKERRQ(ierr); 5715 PetscFunctionReturn(0); 5716 } 5717 5718 #undef __FUNCT__ 5719 #define __FUNCT__ "DMCreateDefaultSection_Plex" 5720 PetscErrorCode DMCreateDefaultSection_Plex(DM dm) 5721 { 5722 PetscSection section; 5723 IS *bcPoints, *bcComps; 5724 PetscBool *isFE; 5725 PetscInt *bcFields, *numComp, *numDof; 5726 PetscInt depth, dim, numBd, numBC = 0, numFields, bd, bc = 0, f; 5727 PetscInt cStart, cEnd, cEndInterior; 5728 PetscErrorCode ierr; 5729 5730 PetscFunctionBegin; 5731 ierr = DMGetNumFields(dm, &numFields);CHKERRQ(ierr); 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