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