Actual source code: networkview.c
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>
15: #include <petscdraw.h>
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;
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));
33: PetscCall(DMGetCoordinateDim(dmcoords, &i));
34: PetscCheck(i == 2, PETSC_COMM_WORLD, PETSC_ERR_SUP, "dim %" PetscInt_FMT " != 2 is not supported yet", i);
36: // Get the coordinate vector from dm
37: PetscCall(DMGetCoordinatesLocal(dm, &allVertexCoords));
39: // Get the MPI communicator and this process' rank
40: PetscCall(PetscObjectGetComm((PetscObject)dmcoords, &comm));
41: PetscCallMPI(MPI_Comm_rank(comm, &rank));
43: // Start synchronized printing
44: PetscCall(PetscViewerASCIIPushSynchronized(viewer));
46: // Write the header
47: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, "Type,Rank,ID,X,Y,Z,Name,Color\n"));
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));
55: // Write out each vertex
56: for (i = 0; i < nvertices; i++) {
57: vertex = vertices[i];
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));
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: }
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));
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: }
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
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));
118: // Clear the file name buffer so all communicated bytes are well-defined
119: PetscCall(PetscMemzero(filename, sizeof(filename)));
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));
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
132: /* Process Options */
133: optionShowRanks = network->vieweroptions.showallranks;
134: showNoNodes = network->vieweroptions.shownovertices;
135: showNoNumbering = network->vieweroptions.shownonumbering;
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();
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: }
182: // Broadcast the filename to all other MPI ranks
183: PetscCallMPI(MPI_Bcast(filename, PETSC_MAX_PATH_LEN, MPI_BYTE, 0, comm));
185: PetscCall(PetscViewerASCIIOpen(comm, filename, &csvViewer));
186: PetscCall(PetscViewerPushFormat(csvViewer, PETSC_VIEWER_ASCII_CSV));
188: // Use the CSV viewer to write out the local network
189: PetscCall(DMView_Network_CSV(dm, csvViewer));
191: // Close the viewer
192: PetscCall(PetscViewerDestroy(&csvViewer));
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)));
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: }
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)));
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 '
253: PetscCall(PetscArrayzero(proccall, sizeof(proccall)));
254: PetscCall(PetscSNPrintf(proccall, sizeof(proccall), "%s %s %s %s", PETSC_PYTHON_EXE, scriptFile, options, filename));
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: }
274: PetscErrorCode DMView_Network(DM dm, PetscViewer viewer)
275: {
276: PetscBool iascii, isdraw;
277: PetscViewerFormat format;
279: PetscFunctionBegin;
282: PetscCall(PetscViewerGetFormat(viewer, &format));
284: PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERDRAW, &isdraw));
285: if (isdraw) {
286: PetscCall(DMView_Network_Matplotlib(dm, viewer));
287: PetscFunctionReturn(PETSC_SUCCESS);
288: }
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;
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: }
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: }
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));
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: }
328: /* Shared vertices */
329: PetscCall(DMNetworkGetSharedVertices(dm, NULL, &vtx));
330: if (nsv) {
331: PetscInt gidx;
332: PetscBool ghost;
333: const PetscInt *sv = NULL;
335: PetscCall(PetscViewerASCIISynchronizedPrintf(viewer, " SharedVertices:\n"));
336: for (i = 0; i < nsv; i++) {
337: PetscCall(DMNetworkIsGhostVertex(dm, vtx[i], &ghost));
338: if (ghost) continue;
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: }
351: /*@
352: DMNetworkViewSetShowRanks - Sets viewing the `DMETNWORK` on each rank individually.
354: Logically Collective
356: Input Parameter:
357: . dm - the `DMNETWORK` object
359: Output Parameter:
360: . showranks - `PETSC_TRUE` if viewing each rank's sub network individually
362: Level: beginner
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;
370: PetscFunctionBegin;
372: network->vieweroptions.showallranks = showranks;
373: PetscFunctionReturn(PETSC_SUCCESS);
374: }
376: /*@
377: DMNetworkViewSetShowGlobal - Set viewing the global network.
379: Logically Collective
381: Input Parameter:
382: . dm - the `DMNETWORK` object
384: Output Parameter:
385: . showglobal - `PETSC_TRUE` if viewing the global network
387: Level: beginner
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;
395: PetscFunctionBegin;
397: network->vieweroptions.dontshowglobal = (PetscBool)(!showglobal);
398: PetscFunctionReturn(PETSC_SUCCESS);
399: }
401: /*@
402: DMNetworkViewSetShowVertices - Sets whether to display the vertices in viewing routines.
404: Logically Collective
406: Input Parameter:
407: . dm - the `DMNETWORK` object
409: Output Parameter:
410: . showvertices - `PETSC_TRUE` if visualizing the vertices
412: Level: beginner
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;
420: PetscFunctionBegin;
422: network->vieweroptions.shownovertices = (PetscBool)(!showvertices);
423: PetscFunctionReturn(PETSC_SUCCESS);
424: }
426: /*@
427: DMNetworkViewSetShowNumbering - Set displaying the numbering of edges and vertices in viewing routines.
429: Logically Collective
431: Input Parameter:
432: . dm - the `DMNETWORK` object
434: Output Parameter:
435: . shownumbering - `PETSC_TRUE` if displaying the numbering of edges and vertices
437: Level: beginner
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;
445: PetscFunctionBegin;
447: network->vieweroptions.shownonumbering = (PetscBool)(!shownumbering);
448: PetscFunctionReturn(PETSC_SUCCESS);
449: }
451: /*@
452: DMNetworkViewSetViewRanks - View the `DMNETWORK` on each of the specified ranks individually.
454: Collective
456: Input Parameter:
457: . dm - the `DMNETWORK` object
459: Output Parameter:
460: . viewranks - set of ranks to view the `DMNETWORK` on individually
462: Level: beginner
464: Note:
465: `DMNetwork` takes ownership of the input viewranks `IS`, it should be destroyed by the caller.
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;
473: PetscFunctionBegin;
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: }