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 #if defined(PETSC_USE_REAL_DOUBLE) || defined(PETSC_USE_REAL___FLOAT128) 275 typedef double PetscVTKReal; 276 #elif defined(PETSC_USE_REAL_SINGLE) || defined(PETSC_USE_REAL___FP16) 277 typedef float PetscVTKReal; 278 #else 279 typedef PetscReal PetscVTKReal; 280 #endif 281 282 static PetscErrorCode DMPlexVTKWriteSection_ASCII(DM dm, PetscSection section, PetscSection globalSection, Vec v, FILE *fp, PetscInt enforceDof, PetscInt precision, PetscReal scale, PetscInt imag) 283 { 284 MPI_Comm comm; 285 const MPI_Datatype mpiType = MPIU_SCALAR; 286 PetscScalar *array; 287 PetscInt numDof = 0, maxDof; 288 PetscInt numLabelCells, cellHeight, cStart, cEnd, numLabelVertices, vMax, vStart, vEnd, pStart, pEnd, p; 289 PetscMPIInt size, rank, proc, tag; 290 PetscBool hasLabel; 291 PetscErrorCode ierr; 292 293 PetscFunctionBegin; 294 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 295 PetscValidHeaderSpecific(dm,DM_CLASSID,1); 296 PetscValidHeaderSpecific(v,VEC_CLASSID,4); 297 if (precision < 0) precision = 6; 298 ierr = PetscCommGetNewTag(comm, &tag);CHKERRQ(ierr); 299 ierr = MPI_Comm_size(comm, &size);CHKERRQ(ierr); 300 ierr = MPI_Comm_rank(comm, &rank);CHKERRQ(ierr); 301 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 302 /* VTK only wants the values at cells or vertices */ 303 ierr = DMPlexGetVTKCellHeight(dm, &cellHeight);CHKERRQ(ierr); 304 ierr = DMPlexGetHeightStratum(dm, cellHeight, &cStart, &cEnd);CHKERRQ(ierr); 305 ierr = DMPlexGetDepthStratum(dm, 0, &vStart, &vEnd);CHKERRQ(ierr); 306 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 307 if (vMax >= 0) vEnd = PetscMin(vEnd, vMax); 308 pStart = PetscMax(PetscMin(cStart, vStart), pStart); 309 pEnd = PetscMin(PetscMax(cEnd, vEnd), pEnd); 310 ierr = DMGetStratumSize(dm, "vtk", 1, &numLabelCells);CHKERRQ(ierr); 311 ierr = DMGetStratumSize(dm, "vtk", 2, &numLabelVertices);CHKERRQ(ierr); 312 hasLabel = numLabelCells > 0 || numLabelVertices > 0 ? PETSC_TRUE : PETSC_FALSE; 313 for (p = pStart; p < pEnd; ++p) { 314 /* Reject points not either cells or vertices */ 315 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 316 if (hasLabel) { 317 PetscInt value; 318 319 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 320 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 321 ierr = DMGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 322 if (value != 1) continue; 323 } 324 } 325 ierr = PetscSectionGetDof(section, p, &numDof);CHKERRQ(ierr); 326 if (numDof) break; 327 } 328 ierr = MPIU_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, comm);CHKERRQ(ierr); 329 enforceDof = PetscMax(enforceDof, maxDof); 330 ierr = VecGetArray(v, &array);CHKERRQ(ierr); 331 if (!rank) { 332 PetscVTKReal dval; 333 PetscScalar val; 334 char formatString[8]; 335 336 ierr = PetscSNPrintf(formatString, 8, "%%.%de", precision);CHKERRQ(ierr); 337 for (p = pStart; p < pEnd; ++p) { 338 /* Here we lose a way to filter points by keeping them out of the Numbering */ 339 PetscInt dof, off, goff, d; 340 341 /* Reject points not either cells or vertices */ 342 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 343 if (hasLabel) { 344 PetscInt value; 345 346 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 347 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 348 ierr = DMGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 349 if (value != 1) continue; 350 } 351 } 352 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 353 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 354 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 355 if (dof && goff >= 0) { 356 for (d = 0; d < dof; d++) { 357 if (d > 0) { 358 ierr = PetscFPrintf(comm, fp, " ");CHKERRQ(ierr); 359 } 360 val = array[off+d]; 361 dval = (PetscVTKReal) ((imag ? PetscImaginaryPart(val) : PetscRealPart(val)) * scale); 362 ierr = PetscFPrintf(comm, fp, formatString, dval);CHKERRQ(ierr); 363 } 364 for (d = dof; d < enforceDof; d++) { 365 ierr = PetscFPrintf(comm, fp, " 0.0");CHKERRQ(ierr); 366 } 367 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 368 } 369 } 370 for (proc = 1; proc < size; ++proc) { 371 PetscScalar *remoteValues; 372 PetscInt size = 0, d; 373 MPI_Status status; 374 375 ierr = MPI_Recv(&size, 1, MPIU_INT, proc, tag, comm, &status);CHKERRQ(ierr); 376 ierr = PetscMalloc1(size, &remoteValues);CHKERRQ(ierr); 377 ierr = MPI_Recv(remoteValues, size, mpiType, proc, tag, comm, &status);CHKERRQ(ierr); 378 for (p = 0; p < size/maxDof; ++p) { 379 for (d = 0; d < maxDof; ++d) { 380 if (d > 0) { 381 ierr = PetscFPrintf(comm, fp, " ");CHKERRQ(ierr); 382 } 383 val = remoteValues[p*maxDof+d]; 384 dval = (PetscVTKReal) ((imag ? PetscImaginaryPart(val) : PetscRealPart(val)) * scale); 385 ierr = PetscFPrintf(comm, fp, formatString, dval);CHKERRQ(ierr); 386 } 387 for (d = maxDof; d < enforceDof; ++d) { 388 ierr = PetscFPrintf(comm, fp, " 0.0");CHKERRQ(ierr); 389 } 390 ierr = PetscFPrintf(comm, fp, "\n");CHKERRQ(ierr); 391 } 392 ierr = PetscFree(remoteValues);CHKERRQ(ierr); 393 } 394 } else { 395 PetscScalar *localValues; 396 PetscInt size, k = 0; 397 398 ierr = PetscSectionGetStorageSize(section, &size);CHKERRQ(ierr); 399 ierr = PetscMalloc1(size, &localValues);CHKERRQ(ierr); 400 for (p = pStart; p < pEnd; ++p) { 401 PetscInt dof, off, goff, d; 402 403 /* Reject points not either cells or vertices */ 404 if (((p < cStart) || (p >= cEnd)) && ((p < vStart) || (p >= vEnd))) continue; 405 if (hasLabel) { 406 PetscInt value; 407 408 if (((p >= cStart) && (p < cEnd) && numLabelCells) || 409 ((p >= vStart) && (p < vEnd) && numLabelVertices)) { 410 ierr = DMGetLabelValue(dm, "vtk", p, &value);CHKERRQ(ierr); 411 if (value != 1) continue; 412 } 413 } 414 ierr = PetscSectionGetDof(section, p, &dof);CHKERRQ(ierr); 415 ierr = PetscSectionGetOffset(section, p, &off);CHKERRQ(ierr); 416 ierr = PetscSectionGetOffset(globalSection, p, &goff);CHKERRQ(ierr); 417 if (goff >= 0) { 418 for (d = 0; d < dof; ++d) { 419 localValues[k++] = array[off+d]; 420 } 421 } 422 } 423 ierr = MPI_Send(&k, 1, MPIU_INT, 0, tag, comm);CHKERRQ(ierr); 424 ierr = MPI_Send(localValues, k, mpiType, 0, tag, comm);CHKERRQ(ierr); 425 ierr = PetscFree(localValues);CHKERRQ(ierr); 426 } 427 ierr = VecRestoreArray(v, &array);CHKERRQ(ierr); 428 PetscFunctionReturn(0); 429 } 430 431 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) 432 { 433 MPI_Comm comm; 434 PetscInt numDof = 0, maxDof; 435 PetscInt pStart, pEnd, p; 436 PetscErrorCode ierr; 437 438 PetscFunctionBegin; 439 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 440 ierr = PetscSectionGetChart(section, &pStart, &pEnd);CHKERRQ(ierr); 441 for (p = pStart; p < pEnd; ++p) { 442 ierr = PetscSectionGetDof(section, p, &numDof);CHKERRQ(ierr); 443 if (numDof) break; 444 } 445 numDof = PetscMax(numDof, enforceDof); 446 ierr = MPIU_Allreduce(&numDof, &maxDof, 1, MPIU_INT, MPI_MAX, PetscObjectComm((PetscObject)dm));CHKERRQ(ierr); 447 if (!name) name = "Unknown"; 448 if (maxDof == 3) { 449 if (nameComplex) { 450 ierr = PetscFPrintf(comm, fp, "VECTORS %s.%s double\n", name, imag ? "Im" : "Re");CHKERRQ(ierr); 451 } else { 452 ierr = PetscFPrintf(comm, fp, "VECTORS %s double\n", name);CHKERRQ(ierr); 453 } 454 } else { 455 if (nameComplex) { 456 ierr = PetscFPrintf(comm, fp, "SCALARS %s.%s double %D\n", name, imag ? "Im" : "Re", maxDof);CHKERRQ(ierr); 457 } else { 458 ierr = PetscFPrintf(comm, fp, "SCALARS %s double %D\n", name, maxDof);CHKERRQ(ierr); 459 } 460 ierr = PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");CHKERRQ(ierr); 461 } 462 ierr = DMPlexVTKWriteSection_ASCII(dm, section, globalSection, field, fp, enforceDof, precision, scale, imag);CHKERRQ(ierr); 463 PetscFunctionReturn(0); 464 } 465 466 static PetscErrorCode DMPlexVTKWriteAll_ASCII(DM dm, PetscViewer viewer) 467 { 468 MPI_Comm comm; 469 PetscViewer_VTK *vtk = (PetscViewer_VTK*) viewer->data; 470 FILE *fp; 471 PetscViewerVTKObjectLink link; 472 PetscSection coordSection, globalCoordSection; 473 PetscLayout vLayout; 474 Vec coordinates; 475 PetscReal lengthScale; 476 PetscInt vMax, totVertices, totCells = 0, loops_per_scalar, l; 477 PetscBool hasPoint = PETSC_FALSE, hasCell = PETSC_FALSE, writePartition = PETSC_FALSE, localized, writeComplex; 478 PetscErrorCode ierr; 479 480 PetscFunctionBegin; 481 #if defined(PETSC_USE_COMPLEX) 482 loops_per_scalar = 2; 483 writeComplex = PETSC_TRUE; 484 #else 485 loops_per_scalar = 1; 486 writeComplex = PETSC_FALSE; 487 #endif 488 ierr = DMGetCoordinatesLocalized(dm,&localized);CHKERRQ(ierr); 489 if (localized) SETERRQ(PetscObjectComm((PetscObject)dm),PETSC_ERR_SUP,"VTK output with localized coordinates not yet supported"); 490 ierr = PetscObjectGetComm((PetscObject)dm,&comm);CHKERRQ(ierr); 491 ierr = PetscFOpen(comm, vtk->filename, "wb", &fp);CHKERRQ(ierr); 492 ierr = PetscFPrintf(comm, fp, "# vtk DataFile Version 2.0\n");CHKERRQ(ierr); 493 ierr = PetscFPrintf(comm, fp, "Simplicial Mesh Example\n");CHKERRQ(ierr); 494 ierr = PetscFPrintf(comm, fp, "ASCII\n");CHKERRQ(ierr); 495 ierr = PetscFPrintf(comm, fp, "DATASET UNSTRUCTURED_GRID\n");CHKERRQ(ierr); 496 /* Vertices */ 497 ierr = DMPlexGetScale(dm, PETSC_UNIT_LENGTH, &lengthScale);CHKERRQ(ierr); 498 ierr = DMGetCoordinateSection(dm, &coordSection);CHKERRQ(ierr); 499 ierr = PetscSectionCreateGlobalSection(coordSection, dm->sf, PETSC_FALSE, PETSC_FALSE, &globalCoordSection);CHKERRQ(ierr); 500 ierr = DMGetCoordinatesLocal(dm, &coordinates);CHKERRQ(ierr); 501 ierr = DMPlexGetHybridBounds(dm, NULL, NULL, NULL, &vMax);CHKERRQ(ierr); 502 if (vMax >= 0) { 503 PetscInt pStart, pEnd, p, localSize = 0; 504 505 ierr = PetscSectionGetChart(globalCoordSection, &pStart, &pEnd);CHKERRQ(ierr); 506 pEnd = PetscMin(pEnd, vMax); 507 for (p = pStart; p < pEnd; ++p) { 508 PetscInt dof; 509 510 ierr = PetscSectionGetDof(globalCoordSection, p, &dof);CHKERRQ(ierr); 511 if (dof > 0) ++localSize; 512 } 513 ierr = PetscLayoutCreate(PetscObjectComm((PetscObject)dm), &vLayout);CHKERRQ(ierr); 514 ierr = PetscLayoutSetLocalSize(vLayout, localSize);CHKERRQ(ierr); 515 ierr = PetscLayoutSetBlockSize(vLayout, 1);CHKERRQ(ierr); 516 ierr = PetscLayoutSetUp(vLayout);CHKERRQ(ierr); 517 } else { 518 ierr = PetscSectionGetPointLayout(PetscObjectComm((PetscObject)dm), globalCoordSection, &vLayout);CHKERRQ(ierr); 519 } 520 ierr = PetscLayoutGetSize(vLayout, &totVertices);CHKERRQ(ierr); 521 ierr = PetscFPrintf(comm, fp, "POINTS %D double\n", totVertices);CHKERRQ(ierr); 522 ierr = DMPlexVTKWriteSection_ASCII(dm, coordSection, globalCoordSection, coordinates, fp, 3, PETSC_DETERMINE, lengthScale, 0);CHKERRQ(ierr); 523 /* Cells */ 524 ierr = DMPlexVTKWriteCells_ASCII(dm, fp, &totCells);CHKERRQ(ierr); 525 /* Vertex fields */ 526 for (link = vtk->link; link; link = link->next) { 527 if ((link->ft == PETSC_VTK_POINT_FIELD) || (link->ft == PETSC_VTK_POINT_VECTOR_FIELD)) hasPoint = PETSC_TRUE; 528 if ((link->ft == PETSC_VTK_CELL_FIELD) || (link->ft == PETSC_VTK_CELL_VECTOR_FIELD)) hasCell = PETSC_TRUE; 529 } 530 if (hasPoint) { 531 ierr = PetscFPrintf(comm, fp, "POINT_DATA %D\n", totVertices);CHKERRQ(ierr); 532 for (link = vtk->link; link; link = link->next) { 533 Vec X = (Vec) link->vec; 534 PetscSection section = NULL, globalSection, newSection = NULL; 535 char namebuf[256]; 536 const char *name; 537 PetscInt enforceDof = PETSC_DETERMINE; 538 539 if ((link->ft != PETSC_VTK_POINT_FIELD) && (link->ft != PETSC_VTK_POINT_VECTOR_FIELD)) continue; 540 if (link->ft == PETSC_VTK_POINT_VECTOR_FIELD) enforceDof = 3; 541 ierr = PetscObjectGetName(link->vec, &name);CHKERRQ(ierr); 542 ierr = PetscObjectQuery(link->vec, "section", (PetscObject*) §ion);CHKERRQ(ierr); 543 if (!section) { 544 DM dmX; 545 546 ierr = VecGetDM(X, &dmX);CHKERRQ(ierr); 547 if (dmX) { 548 DMLabel subpointMap, subpointMapX; 549 PetscInt dim, dimX, pStart, pEnd, qStart, qEnd; 550 551 ierr = DMGetLocalSection(dmX, §ion);CHKERRQ(ierr); 552 /* Here is where we check whether dmX is a submesh of dm */ 553 ierr = DMGetDimension(dm, &dim);CHKERRQ(ierr); 554 ierr = DMGetDimension(dmX, &dimX);CHKERRQ(ierr); 555 ierr = DMPlexGetChart(dm, &pStart, &pEnd);CHKERRQ(ierr); 556 ierr = DMPlexGetChart(dmX, &qStart, &qEnd);CHKERRQ(ierr); 557 ierr = DMPlexGetSubpointMap(dm, &subpointMap);CHKERRQ(ierr); 558 ierr = DMPlexGetSubpointMap(dmX, &subpointMapX);CHKERRQ(ierr); 559 if (((dim != dimX) || ((pEnd-pStart) < (qEnd-qStart))) && subpointMap && !subpointMapX) { 560 const PetscInt *ind = NULL; 561 IS subpointIS; 562 PetscInt n = 0, q; 563 564 ierr = PetscSectionGetChart(section, &qStart, &qEnd);CHKERRQ(ierr); 565 ierr = DMPlexCreateSubpointIS(dm, &subpointIS);CHKERRQ(ierr); 566 if (subpointIS) { 567 ierr = ISGetLocalSize(subpointIS, &n);CHKERRQ(ierr); 568 ierr = ISGetIndices(subpointIS, &ind);CHKERRQ(ierr); 569 } 570 ierr = PetscSectionCreate(comm, &newSection);CHKERRQ(ierr); 571 ierr = PetscSectionSetChart(newSection, pStart, pEnd);CHKERRQ(ierr); 572 for (q = qStart; q < qEnd; ++q) { 573 PetscInt dof, off, p; 574 575 ierr = PetscSectionGetDof(section, q, &dof);CHKERRQ(ierr); 576 if (dof) { 577 ierr = PetscFindInt(q, n, ind, &p);CHKERRQ(ierr); 578 if (p >= pStart) { 579 ierr = PetscSectionSetDof(newSection, p, dof);CHKERRQ(ierr); 580 ierr = PetscSectionGetOffset(section, q, &off);CHKERRQ(ierr); 581 ierr = PetscSectionSetOffset(newSection, p, off);CHKERRQ(ierr); 582 } 583 } 584 } 585 if (subpointIS) { 586 ierr = ISRestoreIndices(subpointIS, &ind);CHKERRQ(ierr); 587 ierr = ISDestroy(&subpointIS);CHKERRQ(ierr); 588 } 589 /* No need to setup section */ 590 section = newSection; 591 } 592 } 593 } 594 if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it and could not create one from VecGetDM()", name); 595 if (link->field >= 0) { 596 const char *fieldname; 597 598 ierr = PetscSectionGetFieldName(section, link->field, &fieldname);CHKERRQ(ierr); 599 ierr = PetscSectionGetField(section, link->field, §ion);CHKERRQ(ierr); 600 if (fieldname) { 601 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s%s", name, fieldname);CHKERRQ(ierr); 602 } else { 603 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s%D", name, link->field);CHKERRQ(ierr); 604 } 605 } else { 606 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s", name);CHKERRQ(ierr); 607 } 608 ierr = PetscViewerVTKSanitizeName_Internal(namebuf, sizeof(namebuf));CHKERRQ(ierr); 609 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 610 for (l = 0; l < loops_per_scalar; l++) { 611 ierr = DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, namebuf, fp, enforceDof, PETSC_DETERMINE, 1.0, writeComplex, l);CHKERRQ(ierr); 612 } 613 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 614 if (newSection) {ierr = PetscSectionDestroy(&newSection);CHKERRQ(ierr);} 615 } 616 } 617 /* Cell Fields */ 618 ierr = PetscOptionsGetBool(((PetscObject) dm)->options,((PetscObject) dm)->prefix, "-dm_view_partition", &writePartition, NULL);CHKERRQ(ierr); 619 if (hasCell || writePartition) { 620 ierr = PetscFPrintf(comm, fp, "CELL_DATA %D\n", totCells);CHKERRQ(ierr); 621 for (link = vtk->link; link; link = link->next) { 622 Vec X = (Vec) link->vec; 623 PetscSection section = NULL, globalSection; 624 const char *name = ""; 625 char namebuf[256]; 626 PetscInt enforceDof = PETSC_DETERMINE; 627 628 if ((link->ft != PETSC_VTK_CELL_FIELD) && (link->ft != PETSC_VTK_CELL_VECTOR_FIELD)) continue; 629 if (link->ft == PETSC_VTK_CELL_VECTOR_FIELD) enforceDof = 3; 630 ierr = PetscObjectGetName(link->vec, &name);CHKERRQ(ierr); 631 ierr = PetscObjectQuery(link->vec, "section", (PetscObject*) §ion);CHKERRQ(ierr); 632 if (!section) { 633 DM dmX; 634 635 ierr = VecGetDM(X, &dmX);CHKERRQ(ierr); 636 if (dmX) { 637 ierr = DMGetLocalSection(dmX, §ion);CHKERRQ(ierr); 638 } 639 } 640 if (!section) SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_WRONG, "Vector %s had no PetscSection composed with it and could not create one from VecGetDM()", name); 641 if (link->field >= 0) { 642 const char *fieldname; 643 644 ierr = PetscSectionGetFieldName(section, link->field, &fieldname);CHKERRQ(ierr); 645 ierr = PetscSectionGetField(section, link->field, §ion);CHKERRQ(ierr); 646 if (fieldname) { 647 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s%s", name, fieldname);CHKERRQ(ierr); 648 } else { 649 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s%D", name, link->field);CHKERRQ(ierr); 650 } 651 } else { 652 ierr = PetscSNPrintf(namebuf, sizeof(namebuf), "%s", name);CHKERRQ(ierr); 653 } 654 ierr = PetscViewerVTKSanitizeName_Internal(namebuf, sizeof(namebuf));CHKERRQ(ierr); 655 ierr = PetscSectionCreateGlobalSection(section, dm->sf, PETSC_FALSE, PETSC_FALSE, &globalSection);CHKERRQ(ierr); 656 for (l = 0; l < loops_per_scalar; l++) { 657 ierr = DMPlexVTKWriteField_ASCII(dm, section, globalSection, X, namebuf, fp, enforceDof, PETSC_DETERMINE, 1.0, writeComplex, l);CHKERRQ(ierr); 658 } 659 ierr = PetscSectionDestroy(&globalSection);CHKERRQ(ierr); 660 } 661 if (writePartition) { 662 ierr = PetscFPrintf(comm, fp, "SCALARS partition int 1\n");CHKERRQ(ierr); 663 ierr = PetscFPrintf(comm, fp, "LOOKUP_TABLE default\n");CHKERRQ(ierr); 664 ierr = DMPlexVTKWritePartition_ASCII(dm, fp);CHKERRQ(ierr); 665 } 666 } 667 /* Cleanup */ 668 ierr = PetscSectionDestroy(&globalCoordSection);CHKERRQ(ierr); 669 ierr = PetscLayoutDestroy(&vLayout);CHKERRQ(ierr); 670 ierr = PetscFClose(comm, fp);CHKERRQ(ierr); 671 PetscFunctionReturn(0); 672 } 673 674 /*@C 675 DMPlexVTKWriteAll - Write a file containing all the fields that have been provided to the viewer 676 677 Collective 678 679 Input Arguments: 680 + odm - The DMPlex specifying the mesh, passed as a PetscObject 681 - viewer - viewer of type VTK 682 683 Level: developer 684 685 Note: 686 This function is a callback used by the VTK viewer to actually write the file. 687 The reason for this odd model is that the VTK file format does not provide any way to write one field at a time. 688 Instead, metadata for the entire file needs to be available up-front before you can start writing the file. 689 690 .seealso: PETSCVIEWERVTK 691 @*/ 692 PetscErrorCode DMPlexVTKWriteAll(PetscObject odm, PetscViewer viewer) 693 { 694 DM dm = (DM) odm; 695 PetscBool isvtk; 696 PetscErrorCode ierr; 697 698 PetscFunctionBegin; 699 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 700 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 701 ierr = PetscObjectTypeCompare((PetscObject) viewer, PETSCVIEWERVTK, &isvtk);CHKERRQ(ierr); 702 if (!isvtk) SETERRQ1(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Cannot use viewer type %s", ((PetscObject)viewer)->type_name); 703 switch (viewer->format) { 704 case PETSC_VIEWER_ASCII_VTK: 705 ierr = DMPlexVTKWriteAll_ASCII(dm, viewer);CHKERRQ(ierr); 706 break; 707 case PETSC_VIEWER_VTK_VTU: 708 ierr = DMPlexVTKWriteAll_VTU(dm, viewer);CHKERRQ(ierr); 709 break; 710 default: SETERRQ1(PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "No support for format '%s'", PetscViewerFormats[viewer->format]); 711 } 712 PetscFunctionReturn(0); 713 } 714