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