1 #define PETSCDM_DLL 2 #include <petsc-private/dmpleximpl.h> /*I "petscdmplex.h" I*/ 3 #include <../src/sys/classes/viewer/impls/vtk/vtkvimpl.h> 4 5 #undef __FUNCT__ 6 #define __FUNCT__ "DMPlexVTKGetCellType" 7 PetscErrorCode DMPlexVTKGetCellType(DM dm, PetscInt dim, PetscInt corners, PetscInt *cellType) 8 { 9 PetscFunctionBegin; 10 *cellType = -1; 11 switch (dim) { 12 case 0: 13 switch (corners) { 14 case 1: 15 *cellType = 1; /* VTK_VERTEX */ 16 break; 17 default: 18 break; 19 } 20 break; 21 case 1: 22 switch (corners) { 23 case 2: 24 *cellType = 3; /* VTK_LINE */ 25 break; 26 case 3: 27 *cellType = 21; /* VTK_QUADRATIC_EDGE */ 28 break; 29 default: 30 break; 31 } 32 break; 33 case 2: 34 switch (corners) { 35 case 3: 36 *cellType = 5; /* VTK_TRIANGLE */ 37 break; 38 case 4: 39 *cellType = 9; /* VTK_QUAD */ 40 break; 41 case 6: 42 *cellType = 22; /* VTK_QUADRATIC_TRIANGLE */ 43 break; 44 case 9: 45 *cellType = 23; /* VTK_QUADRATIC_QUAD */ 46 break; 47 default: 48 break; 49 } 50 break; 51 case 3: 52 switch (corners) { 53 case 4: 54 *cellType = 10; /* VTK_TETRA */ 55 break; 56 case 8: 57 *cellType = 12; /* VTK_HEXAHEDRON */ 58 break; 59 case 10: 60 *cellType = 24; /* VTK_QUADRATIC_TETRA */ 61 break; 62 case 27: 63 *cellType = 29; /* VTK_QUADRATIC_HEXAHEDRON */ 64 break; 65 default: 66 break; 67 } 68 } 69 PetscFunctionReturn(0); 70 } 71 72 #undef __FUNCT__ 73 #define __FUNCT__ "DMPlexVTKWriteCells_ASCII" 74 PetscErrorCode DMPlexVTKWriteCells_ASCII(DM dm, FILE *fp, PetscInt *totalCells) 75 { 76 MPI_Comm comm; 77 IS globalVertexNumbers; 78 const PetscInt *gvertex; 79 PetscInt dim; 80 PetscInt numCorners = 0, totCorners = 0, maxCorners, *corners; 81 PetscInt numCells = 0, totCells = 0, maxCells, cellHeight; 82 PetscInt numLabelCells, cMax, cStart, cEnd, c, vStart, vEnd, v; 83 PetscMPIInt numProcs, rank, proc, tag; 84 PetscBool hasLabel; 85 PetscErrorCode ierr; 86 87 PetscFunctionBegin; 88 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 89 ierr = PetscCommGetNewTag(comm, &tag);CHKERRQ(ierr); 90 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 91 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 92 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 93 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 94 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 95 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 96 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, NULL);CHKERRQ(ierr); 97 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 98 ierr = DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);CHKERRQ(ierr); 99 100 hasLabel = numLabelCells > 0 ? PETSC_TRUE : PETSC_FALSE; 101 for (c = cStart; c < cEnd; ++c) { 102 PetscInt *closure = NULL; 103 PetscInt closureSize; 104 105 if (hasLabel) { 106 PetscInt value; 107 108 ierr = DMPlexGetLabelValue(dm, "vtk", c, &value);CHKERRQ(ierr); 109 if (value != 1) continue; 110 } 111 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 112 for (v = 0; v < closureSize*2; v += 2) { 113 if ((closure[v] >= vStart) && (closure[v] < vEnd)) ++numCorners; 114 } 115 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 116 ++numCells; 117 } 118 maxCells = numCells; 119 ierr = MPI_Reduce(&numCells, &totCells, 1, MPIU_INT, MPI_SUM, 0, comm);CHKERRQ(ierr); 120 ierr = MPI_Reduce(&numCells, &maxCells, 1, MPIU_INT, MPI_MAX, 0, comm);CHKERRQ(ierr); 121 ierr = MPI_Reduce(&numCorners, &totCorners, 1, MPIU_INT, MPI_SUM, 0, comm);CHKERRQ(ierr); 122 ierr = MPI_Reduce(&numCorners, &maxCorners, 1, MPIU_INT, MPI_MAX, 0, comm);CHKERRQ(ierr); 123 ierr = DMPlexGetVertexNumbering(dm, &globalVertexNumbers);CHKERRQ(ierr); 124 ierr = ISGetIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); 125 ierr = PetscMalloc(maxCells * sizeof(PetscInt), &corners);CHKERRQ(ierr); 126 ierr = PetscFPrintf(comm, fp, "CELLS %d %d\n", totCells, totCorners+totCells);CHKERRQ(ierr); 127 if (!rank) { 128 PetscInt *remoteVertices; 129 130 for (c = cStart, numCells = 0; c < cEnd; ++c) { 131 PetscInt *closure = NULL; 132 PetscInt closureSize, nC = 0, tmp; 133 134 if (hasLabel) { 135 PetscInt value; 136 137 ierr = DMPlexGetLabelValue(dm, "vtk", c, &value);CHKERRQ(ierr); 138 if (value != 1) continue; 139 } 140 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 141 for (v = 0; v < closureSize*2; v += 2) { 142 if ((closure[v] >= vStart) && (closure[v] < vEnd)) { 143 const PetscInt gv = gvertex[closure[v] - vStart]; 144 closure[nC++] = gv < 0 ? -(gv+1) : gv; 145 } 146 } 147 corners[numCells++] = nC; 148 ierr = PetscFPrintf(comm, fp, "%d ", nC);CHKERRQ(ierr); 149 ierr = DMPlexInvertCell(dim, nC, closure);CHKERRQ(ierr); 150 for (v = 0; v < nC; ++v) { 151 ierr = PetscFPrintf(comm, fp, " %d", closure[v]);CHKERRQ(ierr); 152 } 153 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 154 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 155 } 156 if (numProcs > 1) {ierr = PetscMalloc((maxCorners+maxCells) * sizeof(PetscInt), &remoteVertices);CHKERRQ(ierr);} 157 for (proc = 1; proc < numProcs; ++proc) { 158 MPI_Status status; 159 160 ierr = MPI_Recv(&numCorners, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 161 ierr = MPI_Recv(remoteVertices, numCorners, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 162 for (c = 0; c < numCorners;) { 163 PetscInt nC = remoteVertices[c++]; 164 165 ierr = PetscFPrintf(comm, fp, "%d ", nC);CHKERRQ(ierr); 166 for (v = 0; v < nC; ++v, ++c) { 167 ierr = PetscFPrintf(comm, fp, " %d", remoteVertices[c]);CHKERRQ(ierr); 168 } 169 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 170 } 171 } 172 if (numProcs > 1) {ierr = PetscFree(remoteVertices);CHKERRQ(ierr);} 173 } else { 174 PetscInt *localVertices, numSend = numCells+numCorners, k = 0; 175 176 ierr = PetscMalloc(numSend * sizeof(PetscInt), &localVertices);CHKERRQ(ierr); 177 for (c = cStart, numCells = 0; c < cEnd; ++c) { 178 PetscInt *closure = NULL; 179 PetscInt closureSize, nC = 0; 180 181 if (hasLabel) { 182 PetscInt value; 183 184 ierr = DMPlexGetLabelValue(dm, "vtk", c, &value);CHKERRQ(ierr); 185 if (value != 1) continue; 186 } 187 ierr = DMPlexGetTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 188 for (v = 0; v < closureSize*2; v += 2) { 189 if ((closure[v] >= vStart) && (closure[v] < vEnd)) { 190 const PetscInt gv = gvertex[closure[v] - vStart]; 191 closure[nC++] = gv < 0 ? -(gv+1) : gv; 192 } 193 } 194 corners[numCells++] = nC; 195 localVertices[k++] = nC; 196 for (v = 0; v < nC; ++v, ++k) { 197 localVertices[k] = closure[v]; 198 } 199 ierr = DMPlexRestoreTransitiveClosure(dm, c, PETSC_TRUE, &closureSize, &closure);CHKERRQ(ierr); 200 } 201 if (k != numSend) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_PLIB, "Invalid number of vertices to send %d should be %d", k, numSend); 202 ierr = MPI_Send(&numSend, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 203 ierr = MPI_Send(localVertices, numSend, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 204 ierr = PetscFree(localVertices);CHKERRQ(ierr); 205 } 206 ierr = ISRestoreIndices(globalVertexNumbers, &gvertex);CHKERRQ(ierr); 207 ierr = PetscFPrintf(comm, fp, "CELL_TYPES %d\n", totCells);CHKERRQ(ierr); 208 if (!rank) { 209 PetscInt cellType; 210 211 for (c = 0; c < numCells; ++c) { 212 ierr = DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);CHKERRQ(ierr); 213 ierr = PetscFPrintf(comm, fp, "%d\n", cellType);CHKERRQ(ierr); 214 } 215 for (proc = 1; proc < numProcs; ++proc) { 216 MPI_Status status; 217 218 ierr = MPI_Recv(&numCells, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 219 ierr = MPI_Recv(corners, numCells, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 220 for (c = 0; c < numCells; ++c) { 221 ierr = DMPlexVTKGetCellType(dm, dim, corners[c], &cellType);CHKERRQ(ierr); 222 ierr = PetscFPrintf(comm, fp, "%d\n", cellType);CHKERRQ(ierr); 223 } 224 } 225 } else { 226 ierr = MPI_Send(&numCells, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 227 ierr = MPI_Send(corners, numCells, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 228 } 229 ierr = PetscFree(corners);CHKERRQ(ierr); 230 *totalCells = totCells; 231 PetscFunctionReturn(0); 232 } 233 234 #undef __FUNCT__ 235 #define __FUNCT__ "DMPlexVTKWriteSection_ASCII" 236 PetscErrorCode DMPlexVTKWriteSection_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec v, FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale) 237 { 238 MPI_Comm comm; 239 const MPI_Datatype mpiType = MPIU_SCALAR; 240 PetscScalar *array; 241 PetscInt numDof = 0, maxDof; 242 PetscInt numLabelCells, cellHeight, cMax, cStart, cEnd, numLabelVertices, vMax, vStart, vEnd, pStart, pEnd, p; 243 PetscMPIInt numProcs, rank, proc, tag; 244 PetscBool hasLabel; 245 PetscErrorCode ierr; 246 247 PetscFunctionBegin; 248 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 249 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 250 PetscValidHeaderSpecific(v,VEC_CLASSID,4); 251 if (precision < 0) precision = 6; 252 ierr = PetscCommGetNewTag(comm, &tag);CHKERRQ(ierr); 253 ierr = MPI_Comm_size(comm, &numProcs);CHKERRQ(ierr); 254 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 255 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 256 /* VTK only wants the values at cells or vertices */ 257 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 258 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 259 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 260 ierr = DMPlexGetHybridBounds(dm, &cMax, NULL, NULL, &vMax);CHKERRQ(ierr); 261 if (cMax >= 0) cEnd = PetscMin(cEnd, cMax); 262 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 263 pStart = PetscMax(PetscMin(cStart, vStart), pStart); 264 pEnd = PetscMin(PetscMax(cEnd, vEnd), pEnd); 265 ierr = DMPlexGetStratumSize(dm, "vtk", 1, &numLabelCells);CHKERRQ(ierr); 266 ierr = DMPlexGetStratumSize(dm, "vtk", 2, &numLabelVertices);CHKERRQ(ierr); 267 hasLabel = numLabelCells > 0 || numLabelVertices > 0 ? PETSC_TRUE : PETSC_FALSE; 268 for (p = pStart; p < pEnd; ++p) { 269 /* Reject points not either cells or vertices */ 270 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 271 if (hasLabel) { 272 PetscInt value; 273 274 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 275 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 276 ierr = DMPlexGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 277 if (value != 1) continue; 278 } 279 } 280 ierr = PetscSectionGetDof(section, p, &numDof);CHKERRQ(ierr); 281 if (numDof) break; 282 } 283 ierr = MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 284 enforceDof = PetscMax(enforceDof, maxDof); 285 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 286 if (!rank) { 287 char formatString[8]; 288 289 ierr = PetscSNPrintf(formatString, 8, "%%.%de", precision);CHKERRQ(ierr); 290 for (p = pStart; p < pEnd; ++p) { 291 /* Here we lose a way to filter points by keeping them out of the Numbering */ 292 PetscInt dof, off, goff, d; 293 294 /* Reject points not either cells or vertices */ 295 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 296 if (hasLabel) { 297 PetscInt value; 298 299 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 300 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 301 ierr = DMPlexGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 302 if (value != 1) continue; 303 } 304 } 305 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 306 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 307 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 308 if (dof && goff >= 0) { 309 for (d = 0; d < dof; d++) { 310 if (d > 0) { 311 ierr = PetscFPrintf(comm, fp, " ");CHKERRQ(ierr); 312 } 313 ierr = PetscFPrintf(comm, fp, formatString, PetscRealPart(array[off+d])*scale);CHKERRQ(ierr); 314 } 315 for (d = dof; d < enforceDof; d++) { 316 ierr = PetscFPrintf(comm, fp, " 0.0");CHKERRQ(ierr); 317 } 318 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 319 } 320 } 321 for (proc = 1; proc < numProcs; ++proc) { 322 PetscScalar *remoteValues; 323 PetscInt size, d; 324 MPI_Status status; 325 326 ierr = MPI_Recv(&size, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 327 ierr = PetscMalloc(size * sizeof(PetscScalar), &remoteValues);CHKERRQ(ierr); 328 ierr = MPI_Recv(remoteValues, size, mpiType, proc, tag, comm, &status);CHKERRQ(ierr); 329 for (p = 0; p < size/maxDof; ++p) { 330 for (d = 0; d < maxDof; ++d) { 331 if (d > 0) { 332 ierr = PetscFPrintf(comm, fp, " ");CHKERRQ(ierr); 333 } 334 ierr = PetscFPrintf(comm, fp, formatString, PetscRealPart(remoteValues[p*maxDof+d])*scale);CHKERRQ(ierr); 335 } 336 for (d = maxDof; d < enforceDof; ++d) { 337 ierr = PetscFPrintf(comm, fp, " 0.0");CHKERRQ(ierr); 338 } 339 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 340 } 341 ierr = PetscFree(remoteValues);CHKERRQ(ierr); 342 } 343 } else { 344 PetscScalar *localValues; 345 PetscInt size, k = 0; 346 347 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 348 ierr = PetscMalloc(size * sizeof(PetscScalar), &localValues);CHKERRQ(ierr); 349 for (p = pStart; p < pEnd; ++p) { 350 PetscInt dof, off, goff, d; 351 352 /* Reject points not either cells or vertices */ 353 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 354 if (hasLabel) { 355 PetscInt value; 356 357 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 358 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 359 ierr = DMPlexGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 360 if (value != 1) continue; 361 } 362 } 363 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 364 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 365 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 366 if (goff >= 0) { 367 for (d = 0; d < dof; ++d) { 368 localValues[k++] = array[off+d]; 369 } 370 } 371 } 372 ierr = MPI_Send(&k, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 373 ierr = MPI_Send(localValues, k, mpiType, 0, tag, comm);CHKERRQ(ierr); 374 ierr = PetscFree(localValues);CHKERRQ(ierr); 375 } 376 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 377 PetscFunctionReturn(0); 378 } 379 380 #undef __FUNCT__ 381 #define __FUNCT__ "DMPlexVTKWriteField_ASCII" 382 PetscErrorCode DMPlexVTKWriteField_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec field, const char name[], FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale) 383 { 384 MPI_Comm comm; 385 PetscInt numDof = 0, maxDof; 386 PetscInt pStart, pEnd, p; 387 PetscErrorCode ierr; 388 389 PetscFunctionBegin; 390 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 391 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 392 for (p = pStart; p < pEnd; ++p) { 393 ierr = PetscSectionGetDof(section, p, &numDof);CHKERRQ(ierr); 394 if (numDof) break; 395 } 396 numDof = PetscMax(numDof, enforceDof); 397 ierr = MPI_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 398 if (!name) name = "Unknown"; 399 if (maxDof == 3) { 400 ierr = PetscFPrintf(comm, fp, "VECTORS %s double\n", name);CHKERRQ(ierr); 401 } else { 402 ierr = PetscFPrintf(comm, fp, "SCALARS %s double %d\n", name, maxDof);CHKERRQ(ierr); 403 ierr = PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");CHKERRQ(ierr); 404 } 405 ierr = DMPlexVTKWriteSection_ASCII(dm, section, globalSection, field, fp, enforceDof, precision, scale);CHKERRQ(ierr); 406 PetscFunctionReturn(0); 407 } 408 409 #undef __FUNCT__ 410 #define __FUNCT__ "DMPlexVTKWriteAll_ASCII" 411 static PetscErrorCode DMPlexVTKWriteAll_ASCII(DM dm, PetscViewer viewer) 412 { 413 MPI_Comm comm; 414 PetscViewer_VTK *vtk = (PetscViewer_VTK*) viewer->data; 415 FILE *fp; 416 PetscViewerVTKObjectLink link; 417 PetscSection coordSection, globalCoordSection; 418 PetscLayout vLayout; 419 Vec coordinates; 420 PetscReal lengthScale; 421 PetscInt vMax, totVertices, totCells; 422 PetscBool hasPoint = PETSC_FALSE, hasCell = PETSC_FALSE; 423 PetscErrorCode ierr; 424 425 PetscFunctionBegin; 426 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 427 ierr = PetscFOpen(comm, vtk->filename, "wb", &fp);CHKERRQ(ierr); 428 ierr = PetscFPrintf(comm, fp, "# vtk DataFile Version 2.0\n");CHKERRQ(ierr); 429 ierr = PetscFPrintf(comm, fp, "Simplicial Mesh Example\n");CHKERRQ(ierr); 430 ierr = PetscFPrintf(comm, fp, "ASCII\n");CHKERRQ(ierr); 431 ierr = PetscFPrintf(comm, fp, "DATASET UNSTRUCTURED_GRID\n");CHKERRQ(ierr); 432 /* Vertices */ 433 ierr = DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);CHKERRQ(ierr); 434 ierr = DMPlexGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 435 ierr = PetscSectionCreateGlobalSection(coordSection, dm->sf, PETSC_FALSE, &globalCoordSection);CHKERRQ(ierr); 436 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 437 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 438 if (vMax >= 0) { 439 PetscInt pStart, pEnd, p, localSize = 0; 440 441 ierr = PetscSectionGetChart(globalCoordSection, &pStart, &pEnd);CHKERRQ(ierr); 442 pEnd = PetscMin(pEnd, vMax); 443 for (p = pStart; p < pEnd; ++p) { 444 PetscInt dof; 445 446 ierr = PetscSectionGetDof(globalCoordSection, p, &dof);CHKERRQ(ierr); 447 if (dof > 0) ++localSize; 448 } 449 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &vLayout);CHKERRQ(ierr); 450 ierr = PetscLayoutSetLocalSize(vLayout, localSize);CHKERRQ(ierr); 451 ierr = PetscLayoutSetBlockSize(vLayout, 1);CHKERRQ(ierr); 452 ierr = PetscLayoutSetUp(vLayout);CHKERRQ(ierr); 453 } else { 454 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalCoordSection, &vLayout);CHKERRQ(ierr); 455 } 456 ierr = PetscLayoutGetSize(vLayout, &totVertices);CHKERRQ(ierr); 457 ierr = PetscFPrintf(comm, fp, "POINTS %d double\n", totVertices);CHKERRQ(ierr); 458 ierr = DMPlexVTKWriteSection_ASCII(dm, coordSection, globalCoordSection, coordinates, fp, 3, PETSC_DETERMINE, lengthScale);CHKERRQ(ierr); 459 /* Cells */ 460 ierr = DMPlexVTKWriteCells_ASCII(dm, fp, &totCells);CHKERRQ(ierr); 461 /* Vertex fields */ 462 for (link = vtk->link; link; link = link->next) { 463 if ((link->ft == PETSC_VTK_POINT_FIELD) || (link->ft == PETSC_VTK_POINT_VECTOR_FIELD)) hasPoint = PETSC_TRUE; 464 if ((link->ft == PETSC_VTK_CELL_FIELD) || (link->ft == PETSC_VTK_CELL_VECTOR_FIELD)) hasCell = PETSC_TRUE; 465 } 466 if (hasPoint) { 467 ierr = PetscFPrintf(comm, fp, "POINT_DATA %d\n", totVertices);CHKERRQ(ierr); 468 for (link = vtk->link; link; link = link->next) { 469 Vec X = (Vec) link->vec; 470 DM dmX; 471 PetscSection section, globalSection, newSection = NULL; 472 const char *name; 473 PetscInt enforceDof = PETSC_DETERMINE; 474 475 if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue; 476 if (link->ft == PETSC_VTK_POINT_VECTOR_FIELD) enforceDof = 3; 477 ierr = PetscObjectGetName(link->vec, &name);CHKERRQ(ierr); 478 ierr = VecGetDM(X, &dmX);CHKERRQ(ierr); 479 if (dmX) { 480 DMLabel subpointMap, subpointMapX; 481 PetscInt dim, dimX, pStart, pEnd, qStart, qEnd; 482 483 ierr = DMGetDefaultSection(dmX, §ion);CHKERRQ(ierr); 484 /* Here is where we check whether dmX is a submesh of dm */ 485 ierr = DMPlexGetDimension(dm, &dim);CHKERRQ(ierr); 486 ierr = DMPlexGetDimension(dmX, &dimX);CHKERRQ(ierr); 487 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 488 ierr = DMPlexGetChart(dmX, &qStart, &qEnd);CHKERRQ(ierr); 489 ierr = DMPlexGetSubpointMap(dm, &subpointMap);CHKERRQ(ierr); 490 ierr = DMPlexGetSubpointMap(dmX, &subpointMapX);CHKERRQ(ierr); 491 if (((dim != dimX) || ((pEnd-pStart) < (qEnd-qStart))) && subpointMap && !subpointMapX) { 492 const PetscInt *ind; 493 IS subpointIS; 494 PetscInt n, q; 495 496 ierr = PetscPrintf(PETSC_COMM_SELF, "Making translation PetscSection\n");CHKERRQ(ierr); 497 ierr = PetscSectionGetChart(section, &qStart, &qEnd);CHKERRQ(ierr); 498 ierr = DMPlexCreateSubpointIS(dm, &subpointIS);CHKERRQ(ierr); 499 ierr = ISGetLocalSize(subpointIS, &n);CHKERRQ(ierr); 500 ierr = ISGetIndices(subpointIS, &ind);CHKERRQ(ierr); 501 ierr = PetscSectionCreate(comm, &newSection);CHKERRQ(ierr); 502 ierr = PetscSectionSetChart(newSection, pStart, pEnd);CHKERRQ(ierr); 503 for (q = qStart; q < qEnd; ++q) { 504 PetscInt dof, off, p; 505 506 ierr = PetscSectionGetDof(section, q, &dof);CHKERRQ(ierr); 507 if (dof) { 508 ierr = PetscFindInt(q, n, ind, &p);CHKERRQ(ierr); 509 if (p >= pStart) { 510 ierr = PetscSectionSetDof(newSection, p, dof);CHKERRQ(ierr); 511 ierr = PetscSectionGetOffset(section, q, &off);CHKERRQ(ierr); 512 ierr = PetscSectionSetOffset(newSection, p, off);CHKERRQ(ierr); 513 } 514 } 515 } 516 ierr = ISRestoreIndices(subpointIS, &ind);CHKERRQ(ierr); 517 ierr = ISDestroy(&subpointIS);CHKERRQ(ierr); 518 /* No need to setup section */ 519 section = newSection; 520 } 521 } else { 522 ierr = PetscObjectQuery(link->vec, "section", (PetscObject*) §ion);CHKERRQ(ierr); 523 if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name); 524 } 525 if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name); 526 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 527 ierr = DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);CHKERRQ(ierr); 528 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 529 if (newSection) {ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);} 530 } 531 } 532 /* Cell Fields */ 533 if (hasCell) { 534 ierr = PetscFPrintf(comm, fp, "CELL_DATA %d\n", totCells);CHKERRQ(ierr); 535 for (link = vtk->link; link; link = link->next) { 536 Vec X = (Vec) link->vec; 537 DM dmX; 538 PetscSection section, globalSection; 539 const char *name; 540 PetscInt enforceDof = PETSC_DETERMINE; 541 542 if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue; 543 if (link->ft == PETSC_VTK_CELL_VECTOR_FIELD) enforceDof = 3; 544 ierr = PetscObjectGetName(link->vec, &name);CHKERRQ(ierr); 545 ierr = VecGetDM(X, &dmX);CHKERRQ(ierr); 546 if (dmX) { 547 ierr = DMGetDefaultSection(dmX, §ion);CHKERRQ(ierr); 548 } else { 549 PetscContainer c; 550 551 ierr = PetscObjectQuery(link->vec, "section", (PetscObject*) &c);CHKERRQ(ierr); 552 if (!c) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name); 553 ierr = PetscContainerGetPointer(c, (void**) §ion);CHKERRQ(ierr); 554 } 555 if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it", name); 556 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 557 ierr = DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, name, fp, enforceDof, PETSC_DETERMINE, 1.0);CHKERRQ(ierr); 558 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 559 } 560 } 561 /* Cleanup */ 562 ierr = PetscSectionDestroy(&globalCoordSection);CHKERRQ(ierr); 563 ierr = PetscLayoutDestroy(&vLayout);CHKERRQ(ierr); 564 ierr = PetscFClose(comm, fp);CHKERRQ(ierr); 565 PetscFunctionReturn(0); 566 } 567 568 #undef __FUNCT__ 569 #define __FUNCT__ "DMPlexVTKWriteAll" 570 /*@C 571 DMPlexVTKWriteAll - Write a file containing all the fields that have been provided to the viewer 572 573 Collective 574 575 Input Arguments: 576 + odm - The DMPlex specifying the mesh, passed as a PetscObject 577 - viewer - viewer of type VTK 578 579 Level: developer 580 581 Note: 582 This function is a callback used by the VTK viewer to actually write the file. 583 The reason for this odd model is that the VTK file format does not provide any way to write one field at a time. 584 Instead, metadata for the entire file needs to be available up-front before you can start writing the file. 585 586 .seealso: PETSCVIEWERVTK 587 @*/ 588 PetscErrorCode DMPlexVTKWriteAll(PetscObject odm, PetscViewer viewer) 589 { 590 DM dm = (DM) odm; 591 PetscBool isvtk; 592 PetscErrorCode ierr; 593 594 PetscFunctionBegin; 595 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 596 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 597 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 598 if (!isvtk) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 599 switch (viewer->format) { 600 case PETSC_VIEWER_ASCII_VTK: 601 ierr = DMPlexVTKWriteAll_ASCII(dm, viewer);CHKERRQ(ierr); 602 break; 603 case PETSC_VIEWER_VTK_VTU: 604 ierr = DMPlexVTKWriteAll_VTU(dm, viewer);CHKERRQ(ierr); 605 break; 606 default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 607 } 608 PetscFunctionReturn(0); 609 } 610