1 #include <petscconf.h> 2 // We need to define this ahead of any other includes to make sure mkstemp is actually defined 3 #if defined(PETSC_HAVE_MKSTEMP) 4 #if !defined(_XOPEN_SOURCE) 5 #define _XOPEN_SOURCE 600 6 #endif 7 #endif 8 #include "petsc/private/petscimpl.h" 9 #include "petscerror.h" 10 #include "petscis.h" 11 #include "petscstring.h" 12 #include "petscsys.h" 13 #include "petscsystypes.h" 14 #include <petsc/private/dmnetworkimpl.h> /*I "petscdmnetwork.h" I*/ 15 #include <petscdraw.h> 16 17 static PetscErrorCode DMView_Network_CSV(DM dm, PetscViewer viewer) 18 { 19 DM dmcoords; 20 PetscInt nsubnets, i, subnet, nvertices, nedges, vertex, edge, gidx, ncomp; 21 PetscInt vertexOffsets[2], globalEdgeVertices[2]; 22 PetscScalar vertexCoords[2], *color_ptr, color; 23 const PetscInt *vertices, *edges, *edgeVertices; 24 Vec allVertexCoords; 25 PetscMPIInt rank; 26 MPI_Comm comm; 27 28 PetscFunctionBegin; 29 // Get the coordinate information from dmcoords 30 PetscCheck(dm->coordinates[0].dm, PetscObjectComm((PetscObject)dm), PETSC_ERR_ARG_NULL, "CoordinateDM not created"); 31 PetscCall(DMGetCoordinateDM(dm, &dmcoords)); 32 33 PetscCall(DMGetCoordinateDim(dmcoords, &i)); 34 PetscCheck(i == 2, PETSC_COMM_WORLD, PETSC_ERR_SUP, "dim %" PetscInt_FMT " != 2 is not supported yet", i); 35 36 // Get the coordinate vector from dm 37 PetscCall(DMGetCoordinatesLocal(dm, &allVertexCoords)); 38 39 // Get the MPI communicator and this process' rank 40 PetscCall(PetscObjectGetComm((PetscObject)dmcoords, &comm)); 41 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 42 43 // Start synchronized printing 44 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 45 46 // Write the header 47 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Type,Rank,ID,X,Y,Z,Name,Color\n")); 48 49 // Iterate each subnetwork (Note: We need to get the global number of subnets apparently) 50 PetscCall(DMNetworkGetNumSubNetworks(dmcoords, NULL, &nsubnets)); 51 for (subnet = 0; subnet < nsubnets; subnet++) { 52 // Get the subnetwork's vertices and edges 53 PetscCall(DMNetworkGetSubnetwork(dmcoords, subnet, &nvertices, &nedges, &vertices, &edges)); 54 55 // Write out each vertex 56 for (i = 0; i < nvertices; i++) { 57 vertex = vertices[i]; 58 59 // Get the offset into the coordinate vector for the vertex 60 PetscCall(DMNetworkGetLocalVecOffset(dmcoords, vertex, ALL_COMPONENTS, vertexOffsets)); 61 vertexOffsets[1] = vertexOffsets[0] + 1; 62 // Remap vertex to the global value 63 PetscCall(DMNetworkGetGlobalVertexIndex(dmcoords, vertex, &gidx)); 64 // Get the vertex position from the coordinate vector 65 PetscCall(VecGetValues(allVertexCoords, 2, vertexOffsets, vertexCoords)); 66 67 // Get vertex color; TODO: name 68 PetscCall(DMNetworkGetNumComponents(dmcoords, vertex, &ncomp)); 69 PetscCheck(ncomp <= 1, PETSC_COMM_WORLD, PETSC_ERR_SUP, "num of components %" PetscInt_FMT " must be <= 1", ncomp); 70 color = 0.0; 71 if (ncomp == 1) { 72 PetscCall(DMNetworkGetComponent(dmcoords, vertex, 0, NULL, (void **)&color_ptr, NULL)); 73 color = *color_ptr; 74 } 75 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Node,%" PetscInt_FMT ",%" PetscInt_FMT ",%lf,%lf,0,%" PetscInt_FMT ",%lf\n", (PetscInt)rank, gidx, (double)PetscRealPart(vertexCoords[0]), (double)PetscRealPart(vertexCoords[1]), gidx, (double)PetscRealPart(color))); 76 } 77 78 // Write out each edge 79 for (i = 0; i < nedges; i++) { 80 edge = edges[i]; 81 PetscCall(DMNetworkGetConnectedVertices(dmcoords, edge, &edgeVertices)); 82 PetscCall(DMNetworkGetGlobalVertexIndex(dmcoords, edgeVertices[0], &globalEdgeVertices[0])); 83 PetscCall(DMNetworkGetGlobalVertexIndex(dmcoords, edgeVertices[1], &globalEdgeVertices[1])); 84 PetscCall(DMNetworkGetGlobalEdgeIndex(dmcoords, edge, &edge)); 85 86 // TODO: Determine edge color/name 87 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Edge,%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",%" PetscInt_FMT ",0,%" PetscInt_FMT "\n", (PetscInt)rank, edge, globalEdgeVertices[0], globalEdgeVertices[1], edge)); 88 } 89 } 90 // End synchronized printing 91 PetscCall(PetscViewerFlush(viewer)); 92 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 93 PetscFunctionReturn(PETSC_SUCCESS); 94 } 95 96 static PetscErrorCode DMView_Network_Matplotlib(DM dm, PetscViewer viewer) 97 { 98 PetscMPIInt rank, size; 99 MPI_Comm comm; 100 char filename[PETSC_MAX_PATH_LEN + 1], options[512], proccall[PETSC_MAX_PATH_LEN + 512], scriptFile[PETSC_MAX_PATH_LEN + 1], buffer[256], buffer2[256]; 101 PetscViewer csvViewer; 102 FILE *processFile = NULL; 103 PetscBool isnull, optionShowRanks = PETSC_FALSE, optionRankIsSet = PETSC_FALSE, showNoNodes = PETSC_FALSE, showNoNumbering = PETSC_FALSE, optionShowVertices = PETSC_FALSE, optionViewPadding = PETSC_FALSE; 104 PetscDraw draw; 105 DM_Network *network = (DM_Network *)dm->data; 106 PetscReal drawPause, viewPadding = 1.0; 107 PetscInt i; 108 #if defined(PETSC_HAVE_MKSTEMP) 109 PetscBool isSharedTmp; 110 #endif 111 112 PetscFunctionBegin; 113 // Deal with the PetscDraw we are given 114 PetscCall(PetscViewerDrawGetDraw(viewer, 1, &draw)); 115 PetscCall(PetscDrawIsNull(draw, &isnull)); 116 PetscCall(PetscDrawSetVisible(draw, PETSC_FALSE)); 117 118 // Clear the file name buffer so all communicated bytes are well-defined 119 PetscCall(PetscMemzero(filename, sizeof(filename))); 120 121 // Get the MPI communicator and this process' rank 122 PetscCall(PetscObjectGetComm((PetscObject)dm, &comm)); 123 PetscCallMPI(MPI_Comm_rank(comm, &rank)); 124 PetscCallMPI(MPI_Comm_size(comm, &size)); 125 126 #if defined(PETSC_HAVE_MKSTEMP) 127 // Get if the temporary directory is shared 128 // Note: This must be done collectively on every rank, it cannot be done on a single rank 129 PetscCall(PetscSharedTmp(comm, &isSharedTmp)); 130 #endif 131 132 /* Process Options */ 133 optionShowRanks = network->vieweroptions.showallranks; 134 showNoNodes = network->vieweroptions.shownovertices; 135 showNoNumbering = network->vieweroptions.shownonumbering; 136 137 /* 138 TODO: if the option -dmnetwork_view_tmpdir can be moved up here that would be good as well. 139 */ 140 PetscOptionsBegin(PetscObjectComm((PetscObject)dm), ((PetscObject)dm)->prefix, "MatPlotLib PetscViewer DMNetwork Options", "PetscViewer"); 141 PetscCall(PetscOptionsBool("-dmnetwork_view_all_ranks", "View all ranks in the DMNetwork", NULL, optionShowRanks, &optionShowRanks, NULL)); 142 PetscCall(PetscOptionsString("-dmnetwork_view_rank_range", "Set of ranks to view the DMNetwork on", NULL, buffer, buffer, sizeof(buffer), &optionRankIsSet)); 143 PetscCall(PetscOptionsBool("-dmnetwork_view_no_vertices", "Do not view vertices", NULL, showNoNodes, &showNoNodes, NULL)); 144 PetscCall(PetscOptionsBool("-dmnetwork_view_no_numbering", "Do not view edge and vertex numbering", NULL, showNoNumbering, &showNoNumbering, NULL)); 145 PetscCall(PetscOptionsString("-dmnetwork_view_zoomin_vertices", "Focus the view on the given set of vertices", NULL, buffer2, buffer2, sizeof(buffer2), &optionShowVertices)); 146 PetscCall(PetscOptionsReal("-dmnetwork_view_zoomin_vertices_padding", "Set the padding when viewing specific vertices", NULL, viewPadding, &viewPadding, &optionViewPadding)); 147 PetscOptionsEnd(); 148 149 // Generate and broadcast the temporary file name from rank 0 150 if (rank == 0) { 151 #if defined(PETSC_HAVE_TMPNAM_S) 152 // Acquire a temporary file to write to and open an ASCII/CSV viewer 153 PetscCheck(tmpnam_s(filename, sizeof(filename)) == 0, comm, PETSC_ERR_SYS, "Could not acquire temporary file"); 154 #elif defined(PETSC_HAVE_MKSTEMP) 155 PetscBool isTmpOverridden; 156 size_t numChars; 157 // Same thing, but for POSIX systems on which tmpnam is deprecated 158 // Note: Configure may detect mkstemp but it will not be defined if compiling for C99, so check additional defines to see if we can use it 159 // Mkstemp requires us to explicitly specify part of the path, but some systems may not like putting files in /tmp/ so have an option for it 160 PetscCall(PetscOptionsGetString(NULL, NULL, "-dmnetwork_view_tmpdir", filename, sizeof(filename), &isTmpOverridden)); 161 // If not specified by option try using a shared tmp on the system 162 if (!isTmpOverridden) { 163 // Validate that if tmp is not overridden it is at least shared 164 PetscCheck(isSharedTmp, comm, PETSC_ERR_SUP_SYS, "Temporary file directory is not shared between ranks, try using -dmnetwork_view_tmpdir to specify a shared directory"); 165 PetscCall(PetscGetTmp(PETSC_COMM_SELF, filename, sizeof(filename))); 166 } 167 // Make sure the filename ends with a '/' 168 PetscCall(PetscStrlen(filename, &numChars)); 169 if (filename[numChars - 1] != '/') { 170 filename[numChars] = '/'; 171 filename[numChars + 1] = 0; 172 } 173 // Perform the actual temporary file creation 174 PetscCall(PetscStrlcat(filename, "XXXXXX", sizeof(filename))); 175 PetscCheck(mkstemp(filename) != -1, comm, PETSC_ERR_SYS, "Could not acquire temporary file"); 176 #else 177 // Same thing, but for older C versions which don't have the safe form 178 PetscCheck(tmpnam(filename) != NULL, comm, PETSC_ERR_SYS, "Could not acquire temporary file"); 179 #endif 180 } 181 182 // Broadcast the filename to all other MPI ranks 183 PetscCallMPI(MPI_Bcast(filename, PETSC_MAX_PATH_LEN, MPI_BYTE, 0, comm)); 184 185 PetscCall(PetscViewerASCIIOpen(comm, filename, &csvViewer)); 186 PetscCall(PetscViewerPushFormat(csvViewer, PETSC_VIEWER_ASCII_CSV)); 187 188 // Use the CSV viewer to write out the local network 189 PetscCall(DMView_Network_CSV(dm, csvViewer)); 190 191 // Close the viewer 192 PetscCall(PetscViewerDestroy(&csvViewer)); 193 194 // Generate options string 195 PetscCall(PetscMemzero(options, sizeof(options))); 196 // If the draw is null run as a "test execute" ie. do nothing just test that the script was called correctly 197 PetscCall(PetscStrlcat(options, isnull ? " -tx " : " ", sizeof(options))); 198 PetscCall(PetscDrawGetPause(draw, &drawPause)); 199 if (drawPause > 0) { 200 char pausebuffer[64]; 201 PetscCall(PetscSNPrintf(pausebuffer, sizeof(pausebuffer), "%f", (double)drawPause)); 202 PetscCall(PetscStrlcat(options, " -dt ", sizeof(options))); 203 PetscCall(PetscStrlcat(options, pausebuffer, sizeof(options))); 204 } 205 if (optionShowRanks || optionRankIsSet) { 206 // Show all ranks only if the option is set in code or by the user AND not showing specific ranks AND there is more than one process 207 if (optionShowRanks && !optionRankIsSet && size != 1) PetscCall(PetscStrlcat(options, " -dar ", sizeof(options))); 208 // Do not show the global plot if the user requests it OR if one specific rank is requested 209 if (network->vieweroptions.dontshowglobal || optionRankIsSet) PetscCall(PetscStrlcat(options, " -ncp ", sizeof(options))); 210 211 if (optionRankIsSet) { 212 // If a range of ranks to draw is specified append it 213 PetscCall(PetscStrlcat(options, " -drr ", sizeof(options))); 214 PetscCall(PetscStrlcat(options, buffer, sizeof(options))); 215 } else { 216 // Otherwise, use the options provided in code 217 if (network->vieweroptions.viewranks) { 218 const PetscInt *viewranks; 219 PetscInt viewrankssize; 220 char rankbuffer[64]; 221 PetscCall(ISGetTotalIndices(network->vieweroptions.viewranks, &viewranks)); 222 PetscCall(ISGetSize(network->vieweroptions.viewranks, &viewrankssize)); 223 PetscCall(PetscStrlcat(options, " -drr ", sizeof(options))); 224 for (i = 0; i < viewrankssize; i++) { 225 PetscCall(PetscSNPrintf(rankbuffer, sizeof(rankbuffer), "%" PetscInt_FMT, viewranks[i])); 226 PetscCall(PetscStrlcat(options, rankbuffer, sizeof(options))); 227 } 228 PetscCall(ISRestoreTotalIndices(network->vieweroptions.viewranks, &viewranks)); 229 } // if not provided an IS of viewing ranks, skip viewing 230 } 231 } 232 if (optionShowVertices) { 233 // Pass vertices to focus on if defined 234 PetscCall(PetscStrlcat(options, " -vsv ", sizeof(options))); 235 PetscCall(PetscStrlcat(options, buffer2, sizeof(options))); 236 optionViewPadding = PETSC_TRUE; 237 // Pass padding if set 238 if (optionViewPadding) { 239 PetscCall(PetscSNPrintf(buffer2, sizeof(buffer2), "%f", (double)viewPadding)); 240 PetscCall(PetscStrlcat(options, " -vp ", sizeof(options))); 241 PetscCall(PetscStrlcat(options, buffer2, sizeof(options))); 242 } 243 } 244 245 // Check for options for visibility... 246 if (showNoNodes) PetscCall(PetscStrlcat(options, " -nn ", sizeof(options))); 247 if (showNoNumbering) PetscCall(PetscStrlcat(options, " -nnl -nel ", sizeof(options))); 248 249 // Get the value of $PETSC_DIR 250 PetscCall(PetscStrreplace(comm, "${PETSC_DIR}/share/petsc/bin/dmnetwork_view.py", scriptFile, sizeof(scriptFile))); 251 PetscCall(PetscFixFilename(scriptFile, scriptFile)); 252 // Generate the system call for 'python3 $PETSC_DIR/share/petsc/dmnetwork_view.py <options> <file>' 253 PetscCall(PetscArrayzero(proccall, sizeof(proccall))); 254 PetscCall(PetscSNPrintf(proccall, sizeof(proccall), "%s %s %s %s", PETSC_PYTHON_EXE, scriptFile, options, filename)); 255 256 #if defined(PETSC_HAVE_POPEN) 257 // Perform the call to run the python script (Note: while this is called on all ranks POpen will only run on rank 0) 258 PetscCall(PetscPOpen(comm, NULL, proccall, "r", &processFile)); 259 if (processFile != NULL) { 260 while (fgets(buffer, sizeof(buffer), processFile) != NULL) PetscCall(PetscPrintf(comm, "%s", buffer)); 261 } 262 PetscCall(PetscPClose(comm, processFile)); 263 #else 264 // Same thing, but using the standard library for systems that don't have POpen/PClose (only run on rank 0) 265 if (rank == 0) PetscCheck(system(proccall) == 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Failed to call viewer script"); 266 // Barrier so that all ranks wait until the call completes 267 PetscCallMPI(MPI_Barrier(comm)); 268 #endif 269 // Clean up the temporary file we used using rank 0 270 if (rank == 0) PetscCheck(remove(filename) == 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Failed to delete temporary file"); 271 PetscFunctionReturn(PETSC_SUCCESS); 272 } 273 274 PetscErrorCode DMView_Network(DM dm, PetscViewer viewer) 275 { 276 PetscBool iascii, isdraw; 277 PetscViewerFormat format; 278 279 PetscFunctionBegin; 280 PetscValidHeaderSpecific(dm, DM_CLASSID, 1); 281 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 2); 282 PetscCall(PetscViewerGetFormat(viewer, &format)); 283 284 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw)); 285 if (isdraw) { 286 PetscCall(DMView_Network_Matplotlib(dm, viewer)); 287 PetscFunctionReturn(PETSC_SUCCESS); 288 } 289 290 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &iascii)); 291 if (iascii) { 292 const PetscInt *cone, *vtx, *edges; 293 PetscInt vfrom, vto, i, j, nv, ne, nsv, p, nsubnet; 294 DM_Network *network = (DM_Network *)dm->data; 295 PetscMPIInt rank; 296 297 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)dm), &rank)); 298 if (format == PETSC_VIEWER_ASCII_CSV) { 299 PetscCall(DMView_Network_CSV(dm, viewer)); 300 PetscFunctionReturn(PETSC_SUCCESS); 301 } 302 303 nsubnet = network->cloneshared->Nsubnet; /* num of subnetworks */ 304 if (!rank) { 305 PetscCall(PetscPrintf(PETSC_COMM_SELF, " NSubnets: %" PetscInt_FMT "; NEdges: %" PetscInt_FMT "; NVertices: %" PetscInt_FMT "; NSharedVertices: %" PetscInt_FMT ".\n", nsubnet, network->cloneshared->NEdges, network->cloneshared->NVertices, 306 network->cloneshared->Nsvtx)); 307 } 308 309 PetscCall(DMNetworkGetSharedVertices(dm, &nsv, NULL)); 310 PetscCall(PetscViewerASCIIPushSynchronized(viewer)); 311 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " [%d] nEdges: %" PetscInt_FMT "; nVertices: %" PetscInt_FMT "; nSharedVertices: %" PetscInt_FMT "\n", rank, network->cloneshared->nEdges, network->cloneshared->nVertices, nsv)); 312 313 for (i = 0; i < nsubnet; i++) { 314 PetscCall(DMNetworkGetSubnetwork(dm, i, &nv, &ne, &vtx, &edges)); 315 if (ne) { 316 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " Subnet %" PetscInt_FMT ": nEdges %" PetscInt_FMT ", nVertices(include shared vertices) %" PetscInt_FMT "\n", i, ne, nv)); 317 for (j = 0; j < ne; j++) { 318 p = edges[j]; 319 PetscCall(DMNetworkGetConnectedVertices(dm, p, &cone)); 320 PetscCall(DMNetworkGetGlobalVertexIndex(dm, cone[0], &vfrom)); 321 PetscCall(DMNetworkGetGlobalVertexIndex(dm, cone[1], &vto)); 322 PetscCall(DMNetworkGetGlobalEdgeIndex(dm, edges[j], &p)); 323 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " edge %" PetscInt_FMT ": %" PetscInt_FMT " ----> %" PetscInt_FMT "\n", p, vfrom, vto)); 324 } 325 } 326 } 327 328 /* Shared vertices */ 329 PetscCall(DMNetworkGetSharedVertices(dm, NULL, &vtx)); 330 if (nsv) { 331 PetscInt gidx; 332 PetscBool ghost; 333 const PetscInt *sv = NULL; 334 335 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " SharedVertices:\n")); 336 for (i = 0; i < nsv; i++) { 337 PetscCall(DMNetworkIsGhostVertex(dm, vtx[i], &ghost)); 338 if (ghost) continue; 339 340 PetscCall(DMNetworkSharedVertexGetInfo(dm, vtx[i], &gidx, &nv, &sv)); 341 PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " svtx %" PetscInt_FMT ": global index %" PetscInt_FMT ", subnet[%" PetscInt_FMT "].%" PetscInt_FMT " ---->\n", i, gidx, sv[0], sv[1])); 342 for (j = 1; j < nv; j++) PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " ----> subnet[%" PetscInt_FMT "].%" PetscInt_FMT "\n", sv[2 * j], sv[2 * j + 1])); 343 } 344 } 345 PetscCall(PetscViewerFlush(viewer)); 346 PetscCall(PetscViewerASCIIPopSynchronized(viewer)); 347 } else PetscCheck(iascii, PetscObjectComm((PetscObject)dm), PETSC_ERR_SUP, "Viewer type %s not yet supported for DMNetwork writing", ((PetscObject)viewer)->type_name); 348 PetscFunctionReturn(PETSC_SUCCESS); 349 } 350 351 /*@ 352 DMNetworkViewSetShowRanks - Sets viewing the `DMETNWORK` on each rank individually. 353 354 Logically Collective 355 356 Input Parameter: 357 . dm - the `DMNETWORK` object 358 359 Output Parameter: 360 . showranks - `PETSC_TRUE` if viewing each rank's sub network individually 361 362 Level: beginner 363 364 .seealso: `DM`, `DMNETWORK`, `DMNetworkViewSetShowGlobal()`, `DMNetworkViewSetShowVertices()`, `DMNetworkViewSetShowNumbering()`, `DMNetworkViewSetViewRanks()` 365 @*/ 366 PetscErrorCode DMNetworkViewSetShowRanks(DM dm, PetscBool showranks) 367 { 368 DM_Network *network = (DM_Network *)dm->data; 369 370 PetscFunctionBegin; 371 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMNETWORK); 372 network->vieweroptions.showallranks = showranks; 373 PetscFunctionReturn(PETSC_SUCCESS); 374 } 375 376 /*@ 377 DMNetworkViewSetShowGlobal - Set viewing the global network. 378 379 Logically Collective 380 381 Input Parameter: 382 . dm - the `DMNETWORK` object 383 384 Output Parameter: 385 . showglobal - `PETSC_TRUE` if viewing the global network 386 387 Level: beginner 388 389 .seealso: `DM`, `DMNETWORK`, `DMNetworkViewSetShowRanks()`, `DMNetworkViewSetShowVertices()`, `DMNetworkViewSetShowNumbering()`, `DMNetworkViewSetViewRanks()` 390 @*/ 391 PetscErrorCode DMNetworkViewSetShowGlobal(DM dm, PetscBool showglobal) 392 { 393 DM_Network *network = (DM_Network *)dm->data; 394 395 PetscFunctionBegin; 396 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMNETWORK); 397 network->vieweroptions.dontshowglobal = (PetscBool)(!showglobal); 398 PetscFunctionReturn(PETSC_SUCCESS); 399 } 400 401 /*@ 402 DMNetworkViewSetShowVertices - Sets whether to display the vertices in viewing routines. 403 404 Logically Collective 405 406 Input Parameter: 407 . dm - the `DMNETWORK` object 408 409 Output Parameter: 410 . showvertices - `PETSC_TRUE` if visualizing the vertices 411 412 Level: beginner 413 414 .seealso: `DM`, `DMNETWORK`, `DMNetworkViewSetShowRanks()`, `DMNetworkViewSetShowGlobal()`, `DMNetworkViewSetShowNumbering()`, `DMNetworkViewSetViewRanks()` 415 @*/ 416 PetscErrorCode DMNetworkViewSetShowVertices(DM dm, PetscBool showvertices) 417 { 418 DM_Network *network = (DM_Network *)dm->data; 419 420 PetscFunctionBegin; 421 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMNETWORK); 422 network->vieweroptions.shownovertices = (PetscBool)(!showvertices); 423 PetscFunctionReturn(PETSC_SUCCESS); 424 } 425 426 /*@ 427 DMNetworkViewSetShowNumbering - Set displaying the numbering of edges and vertices in viewing routines. 428 429 Logically Collective 430 431 Input Parameter: 432 . dm - the `DMNETWORK` object 433 434 Output Parameter: 435 . shownumbering - `PETSC_TRUE` if displaying the numbering of edges and vertices 436 437 Level: beginner 438 439 .seealso: `DM`, `DMNETWORK`, `DMNetworkViewSetShowRanks()`, `DMNetworkViewSetShowGlobal()`, `DMNetworkViewSetShowVertices()`, `DMNetworkViewSetViewRanks()` 440 @*/ 441 PetscErrorCode DMNetworkViewSetShowNumbering(DM dm, PetscBool shownumbering) 442 { 443 DM_Network *network = (DM_Network *)dm->data; 444 445 PetscFunctionBegin; 446 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMNETWORK); 447 network->vieweroptions.shownonumbering = (PetscBool)(!shownumbering); 448 PetscFunctionReturn(PETSC_SUCCESS); 449 } 450 451 /*@ 452 DMNetworkViewSetViewRanks - View the `DMNETWORK` on each of the specified ranks individually. 453 454 Collective 455 456 Input Parameter: 457 . dm - the `DMNETWORK` object 458 459 Output Parameter: 460 . viewranks - set of ranks to view the `DMNETWORK` on individually 461 462 Level: beginner 463 464 Note: 465 `DMNetwork` takes ownership of the input viewranks `IS`, it should be destroyed by the caller. 466 467 .seealso: `DM`, `DMNETWORK`, `DMNetworkViewSetShowRanks()`, `DMNetworkViewSetShowGlobal()`, `DMNetworkViewSetShowVertices()`, `DMNetworkViewSetShowNumbering()` 468 @*/ 469 PetscErrorCode DMNetworkViewSetViewRanks(DM dm, IS viewranks) 470 { 471 DM_Network *network = (DM_Network *)dm->data; 472 473 PetscFunctionBegin; 474 PetscValidHeaderSpecificType(dm, DM_CLASSID, 1, DMNETWORK); 475 PetscValidHeaderSpecific(viewranks, IS_CLASSID, 2); 476 PetscCheckSameComm(dm, 1, viewranks, 2); 477 PetscCall(ISDestroy(&network->vieweroptions.viewranks)); 478 PetscCall(PetscObjectReference((PetscObject)viewranks)); 479 network->vieweroptions.viewranks = viewranks; 480 PetscFunctionReturn(PETSC_SUCCESS); 481 } 482