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