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