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