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