xref: /petsc/src/sys/classes/viewer/impls/glvis/glvis.c (revision 4dfa11a44d5adf2389f1d3acbc8f3c1116dc6c3a)
10039db0dSBarry Smith #define PETSC_DESIRE_FEATURE_TEST_MACROS /* for fdopen() */
2347361c3SStefano Zampini 
38135c375SStefano Zampini #include <petsc/private/viewerimpl.h> /*I   "petscviewer.h" I*/
48135c375SStefano Zampini #include <petsc/private/petscimpl.h>  /*I   "petscsys.h"    I*/
58135c375SStefano Zampini #include <petsc/private/glvisviewerimpl.h>
68135c375SStefano Zampini 
78135c375SStefano Zampini /* we may eventually make this function public */
88135c375SStefano Zampini static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm, const char *, PetscInt, PetscViewer *);
98135c375SStefano Zampini 
108135c375SStefano Zampini struct _n_PetscViewerGLVis {
118135c375SStefano Zampini   PetscViewerGLVisStatus status;
128135c375SStefano Zampini   PetscViewerGLVisType   type;       /* either PETSC_VIEWER_GLVIS_DUMP or PETSC_VIEWER_GLVIS_SOCKET */
138135c375SStefano Zampini   char                  *name;       /* prefix for filename, or hostname, depending on the type */
148135c375SStefano Zampini   PetscInt               port;       /* used just for the socket case */
158135c375SStefano Zampini   PetscReal              pause;      /* if positive, calls PetscSleep(pause) after each VecView_GLVis call */
168135c375SStefano Zampini   PetscViewer            meshwindow; /* used just by the ASCII dumping */
178135c375SStefano Zampini   PetscObject            dm;         /* DM as passed by PetscViewerGLVisSetDM_Private(): should contain discretization info */
188135c375SStefano Zampini   PetscInt               nwindow;    /* number of windows/fields to be visualized */
198135c375SStefano Zampini   PetscViewer           *window;
208135c375SStefano Zampini   char                 **windowtitle;
2173365f8bSLisandro Dalcin   PetscInt               windowsizes[2];
228135c375SStefano Zampini   char                 **fec_type;                                          /* type of elements to be used for visualization, see FiniteElementCollection::Name() */
238135c375SStefano Zampini   PetscErrorCode (*g2lfield)(PetscObject, PetscInt, PetscObject[], void *); /* global to local operation for generating dofs to be visualized */
244cac2994SStefano Zampini   PetscInt    *spacedim;                                                    /* geometrical space dimension (just used to initialize the scene) */
258135c375SStefano Zampini   PetscObject *Ufield;                                                      /* work vectors for visualization */
268135c375SStefano Zampini   PetscInt     snapid;                                                      /* snapshot id, use PetscViewerGLVisSetSnapId to change this value*/
278135c375SStefano Zampini   void        *userctx;                                                     /* User context, used by g2lfield */
288135c375SStefano Zampini   PetscErrorCode (*destroyctx)(void *);                                     /* destroy routine for userctx */
2977eacf09SStefano Zampini   char *fmt;                                                                /* format string for FP values */
308135c375SStefano Zampini };
318135c375SStefano Zampini typedef struct _n_PetscViewerGLVis *PetscViewerGLVis;
328135c375SStefano Zampini 
338135c375SStefano Zampini /*@
34811af0c4SBarry Smith      PetscViewerGLVisSetPrecision - Set the number of digits for floating point values to be displayed
3577eacf09SStefano Zampini 
3677eacf09SStefano Zampini   Not Collective
3777eacf09SStefano Zampini 
3877eacf09SStefano Zampini   Input Parameters:
39811af0c4SBarry Smith +  viewer - the `PetscViewer` of type `PETSCVIEWERGLVIS`
4077eacf09SStefano Zampini -  prec   - the number of digits required
4177eacf09SStefano Zampini 
4277eacf09SStefano Zampini   Level: beginner
4377eacf09SStefano Zampini 
44811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerGLVisOpen()`, `PetscViewerGLVisSetFields()`, `PetscViewerCreate()`, `PetscViewerSetType()`
4577eacf09SStefano Zampini @*/
469371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisSetPrecision(PetscViewer viewer, PetscInt prec) {
4777eacf09SStefano Zampini   PetscFunctionBegin;
4877eacf09SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
49cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGLVisSetPrecision_C", (PetscViewer, PetscInt), (viewer, prec));
5077eacf09SStefano Zampini   PetscFunctionReturn(0);
5177eacf09SStefano Zampini }
5277eacf09SStefano Zampini 
539371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisSetPrecision_GLVis(PetscViewer viewer, PetscInt prec) {
5477eacf09SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5577eacf09SStefano Zampini 
5677eacf09SStefano Zampini   PetscFunctionBegin;
579566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->fmt));
5877eacf09SStefano Zampini   if (prec > 0) {
599566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(16, &socket->fmt));
609566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(socket->fmt, 16, " %%.%" PetscInt_FMT "e", prec));
6177eacf09SStefano Zampini   } else {
629566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(" %g", &socket->fmt));
6377eacf09SStefano Zampini   }
6477eacf09SStefano Zampini   PetscFunctionReturn(0);
6577eacf09SStefano Zampini }
6677eacf09SStefano Zampini 
6777eacf09SStefano Zampini /*@
68811af0c4SBarry Smith      PetscViewerGLVisSetSnapId - Set the snapshot id. Only relevant when the `PetscViewerGLVisType` is `PETSC_VIEWER_GLVIS_DUMP`
698135c375SStefano Zampini 
70811af0c4SBarry Smith   Logically Collective on viewer
718135c375SStefano Zampini 
728135c375SStefano Zampini   Input Parameters:
73811af0c4SBarry Smith +  viewer - the `PetscViewer` of type `PETSCVIEWERGLVIS`
748135c375SStefano Zampini -  id     - the current snapshot id in a time-dependent simulation
758135c375SStefano Zampini 
768135c375SStefano Zampini   Level: beginner
778135c375SStefano Zampini 
78811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerGLVisOpen()`, `PetscViewerGLVisSetFields()`, `PetscViewerCreate()`, `PetscViewerSetType()`
798135c375SStefano Zampini @*/
809371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisSetSnapId(PetscViewer viewer, PetscInt id) {
818135c375SStefano Zampini   PetscFunctionBegin;
828135c375SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
838135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, id, 2);
84cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGLVisSetSnapId_C", (PetscViewer, PetscInt), (viewer, id));
858135c375SStefano Zampini   PetscFunctionReturn(0);
868135c375SStefano Zampini }
878135c375SStefano Zampini 
889371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisSetSnapId_GLVis(PetscViewer viewer, PetscInt id) {
898135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
908135c375SStefano Zampini 
918135c375SStefano Zampini   PetscFunctionBegin;
9277eacf09SStefano Zampini   socket->snapid = id;
938135c375SStefano Zampini   PetscFunctionReturn(0);
948135c375SStefano Zampini }
958135c375SStefano Zampini 
964cac2994SStefano Zampini /*@C
974cac2994SStefano Zampini      PetscViewerGLVisSetFields - Sets the required information to visualize different fields from a vector.
988135c375SStefano Zampini 
99811af0c4SBarry Smith   Logically Collective on viewer
1008135c375SStefano Zampini 
1018135c375SStefano Zampini   Input Parameters:
102811af0c4SBarry Smith +  viewer     - the `PetscViewer` of type `PETSCVIEWERGLVIS`
1038135c375SStefano Zampini .  nf         - number of fields to be visualized
1048135c375SStefano Zampini .  fec_type   - the type of finite element to be used to visualize the data (see FiniteElementCollection::Name() in MFEM)
1054cac2994SStefano Zampini .  dim        - array of space dimension for field vectors (used to initialize the scene)
1068135c375SStefano Zampini .  g2lfields  - User routine to compute the local field vectors to be visualized; PetscObject is used in place of Vec on the prototype
1074cac2994SStefano Zampini .  Vfield     - array of work vectors, one for each field
1088135c375SStefano Zampini .  ctx        - User context to store the relevant data to apply g2lfields
1098135c375SStefano Zampini -  destroyctx - Destroy function for userctx
1108135c375SStefano Zampini 
11195452b02SPatrick Sanan   Notes:
11295452b02SPatrick Sanan     g2lfields is called on the vector V to be visualized in order to extract the relevant dofs to be put in Vfield[], as
1138135c375SStefano Zampini .vb
1144cac2994SStefano Zampini   g2lfields((PetscObject)V,nfields,(PetscObject*)Vfield[],ctx).
1158135c375SStefano Zampini .ve
116811af0c4SBarry Smith 
1174cac2994SStefano Zampini   For vector spaces, the block size of Vfield[i] represents the vector dimension. It misses the Fortran bindings.
1184cac2994SStefano Zampini   The names of the Vfield vectors will be displayed in the window title.
1198135c375SStefano Zampini 
1208135c375SStefano Zampini   Level: intermediate
1218135c375SStefano Zampini 
122811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerGLVisOpen()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscObjectSetName()`
1234cac2994SStefano Zampini @*/
1249371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisSetFields(PetscViewer viewer, PetscInt nf, const char *fec_type[], PetscInt dim[], PetscErrorCode (*g2l)(PetscObject, PetscInt, PetscObject[], void *), PetscObject Vfield[], void *ctx, PetscErrorCode (*destroyctx)(void *)) {
1258135c375SStefano Zampini   PetscFunctionBegin;
1268135c375SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1278135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, nf, 2);
12828b400f6SJacob Faibussowitsch   PetscCheck(fec_type, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "You need to provide the FiniteElementCollection names for the fields");
1294cac2994SStefano Zampini   PetscValidPointer(fec_type, 3);
130dadcf809SJacob Faibussowitsch   PetscValidIntPointer(dim, 4);
1314cac2994SStefano Zampini   PetscValidPointer(Vfield, 6);
132cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGLVisSetFields_C", (PetscViewer, PetscInt, const char *[], PetscInt[], PetscErrorCode (*)(PetscObject, PetscInt, PetscObject[], void *), PetscObject[], void *, PetscErrorCode (*)(void *)), (viewer, nf, fec_type, dim, g2l, Vfield, ctx, destroyctx));
1338135c375SStefano Zampini   PetscFunctionReturn(0);
1348135c375SStefano Zampini }
1358135c375SStefano Zampini 
1369371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisSetFields_GLVis(PetscViewer viewer, PetscInt nfields, const char *fec_type[], PetscInt dim[], PetscErrorCode (*g2l)(PetscObject, PetscInt, PetscObject[], void *), PetscObject Vfield[], void *ctx, PetscErrorCode (*destroyctx)(void *)) {
1378135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
1388135c375SStefano Zampini   PetscInt         i;
1398135c375SStefano Zampini 
1408135c375SStefano Zampini   PetscFunctionBegin;
141cc73adaaSBarry Smith   PetscCheck(!socket->nwindow || socket->nwindow == nfields, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Cannot set number of fields %" PetscInt_FMT " with number of windows %" PetscInt_FMT, nfields, socket->nwindow);
1428135c375SStefano Zampini   if (!socket->nwindow) {
1438135c375SStefano Zampini     socket->nwindow = nfields;
1448135c375SStefano Zampini 
1459566063dSJacob Faibussowitsch     PetscCall(PetscCalloc5(nfields, &socket->window, nfields, &socket->windowtitle, nfields, &socket->fec_type, nfields, &socket->spacedim, nfields, &socket->Ufield));
1468135c375SStefano Zampini     for (i = 0; i < nfields; i++) {
1474cac2994SStefano Zampini       const char *name;
1488135c375SStefano Zampini 
1499566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName(Vfield[i], &name));
1509566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(name, &socket->windowtitle[i]));
1519566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(fec_type[i], &socket->fec_type[i]));
1529566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(Vfield[i]));
1534cac2994SStefano Zampini       socket->Ufield[i]   = Vfield[i];
1544cac2994SStefano Zampini       socket->spacedim[i] = dim[i];
1558135c375SStefano Zampini     }
1568135c375SStefano Zampini   }
1578135c375SStefano Zampini   /* number of fields are not allowed to vary */
15808401ef6SPierre Jolivet   PetscCheck(nfields == socket->nwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot visualize %" PetscInt_FMT " fields using %" PetscInt_FMT " socket windows", nfields, socket->nwindow);
1598135c375SStefano Zampini   socket->g2lfield = g2l;
1609566063dSJacob Faibussowitsch   if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx));
1618135c375SStefano Zampini   socket->userctx    = ctx;
1628135c375SStefano Zampini   socket->destroyctx = destroyctx;
1638135c375SStefano Zampini   PetscFunctionReturn(0);
1648135c375SStefano Zampini }
1658135c375SStefano Zampini 
1669371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisInfoDestroy_Private(void *ptr) {
1678135c375SStefano Zampini   PetscViewerGLVisInfo info = (PetscViewerGLVisInfo)ptr;
1688135c375SStefano Zampini 
169c0bc9656SStefano Zampini   PetscFunctionBegin;
1709566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
1719566063dSJacob Faibussowitsch   PetscCall(PetscFree(info));
1728135c375SStefano Zampini   PetscFunctionReturn(0);
1738135c375SStefano Zampini }
1748135c375SStefano Zampini 
1758135c375SStefano Zampini /* we can decide to prevent specific processes from using the viewer */
1769371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisAttachInfo_Private(PetscViewer viewer, PetscViewer window) {
1778135c375SStefano Zampini   PetscViewerGLVis     socket = (PetscViewerGLVis)viewer->data;
1788135c375SStefano Zampini   PetscContainer       container;
1798135c375SStefano Zampini   PetscViewerGLVisInfo info;
1808135c375SStefano Zampini 
181c0bc9656SStefano Zampini   PetscFunctionBegin;
1829566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)window, "_glvis_info_container", (PetscObject *)&container));
18377eacf09SStefano Zampini   if (!container) {
1849566063dSJacob Faibussowitsch     PetscCall(PetscNew(&info));
1858135c375SStefano Zampini     info->enabled = PETSC_TRUE;
1868135c375SStefano Zampini     info->init    = PETSC_FALSE;
18773365f8bSLisandro Dalcin     info->size[0] = socket->windowsizes[0];
18873365f8bSLisandro Dalcin     info->size[1] = socket->windowsizes[1];
1898135c375SStefano Zampini     info->pause   = socket->pause;
1909566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)window), &container));
1919566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(container, (void *)info));
1929566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(container, PetscViewerGLVisInfoDestroy_Private));
1939566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)window, "_glvis_info_container", (PetscObject)container));
1949566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&container));
19577eacf09SStefano Zampini   } else {
1969566063dSJacob Faibussowitsch     PetscCall(PetscContainerGetPointer(container, (void **)&info));
19777eacf09SStefano Zampini   }
1989566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
1999566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(socket->fmt, &info->fmt));
2008135c375SStefano Zampini   PetscFunctionReturn(0);
2018135c375SStefano Zampini }
2028135c375SStefano Zampini 
2039371c9d4SSatish Balay static PetscErrorCode PetscViewerGLVisGetNewWindow_Private(PetscViewer viewer, PetscViewer *view) {
2048135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2058135c375SStefano Zampini   PetscViewer      window = NULL;
2068135c375SStefano Zampini   PetscBool        ldis, dis;
2078135c375SStefano Zampini 
2088135c375SStefano Zampini   PetscFunctionBegin;
2092da53a5bSBarry Smith   PetscCall(PetscViewerASCIISocketOpen(PETSC_COMM_SELF, socket->name, socket->port, &window));
2102da53a5bSBarry Smith   /* if we could not estabilish a connection, we disable the socket viewer on all MPI ranks */
2112da53a5bSBarry Smith   ldis = !viewer ? PETSC_TRUE : PETSC_FALSE;
2121c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&ldis, &dis, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)viewer)));
2138135c375SStefano Zampini   if (dis) {
2148135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISABLED;
2159566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&window));
2168135c375SStefano Zampini   }
2178135c375SStefano Zampini   *view = window;
2188135c375SStefano Zampini   PetscFunctionReturn(0);
2198135c375SStefano Zampini }
2208135c375SStefano Zampini 
2219371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisPause_Private(PetscViewer viewer) {
2228135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2238135c375SStefano Zampini 
2248135c375SStefano Zampini   PetscFunctionBegin;
22548a46eb9SPierre Jolivet   if (socket->type == PETSC_VIEWER_GLVIS_SOCKET && socket->pause > 0) PetscCall(PetscSleep(socket->pause));
2268135c375SStefano Zampini   PetscFunctionReturn(0);
2278135c375SStefano Zampini }
2288135c375SStefano Zampini 
2298135c375SStefano Zampini /* DM specific support */
2309371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisSetDM_Private(PetscViewer viewer, PetscObject dm) {
2318135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2328135c375SStefano Zampini 
2338135c375SStefano Zampini   PetscFunctionBegin;
234cc73adaaSBarry Smith   PetscCheck(!socket->dm || socket->dm == dm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot change DM associated with the GLVis viewer");
2358135c375SStefano Zampini   if (!socket->dm) {
2368135c375SStefano Zampini     PetscErrorCode (*setupwithdm)(PetscObject, PetscViewer) = NULL;
2378135c375SStefano Zampini 
2389566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction(dm, "DMSetUpGLVisViewer_C", &setupwithdm));
2398135c375SStefano Zampini     if (setupwithdm) {
2409566063dSJacob Faibussowitsch       PetscCall((*setupwithdm)(dm, viewer));
24198921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm(dm), PETSC_ERR_SUP, "No support for DM type %s", dm->type_name);
2429566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference(dm));
2438135c375SStefano Zampini     socket->dm = dm;
2448135c375SStefano Zampini   }
2458135c375SStefano Zampini   PetscFunctionReturn(0);
2468135c375SStefano Zampini }
2478135c375SStefano Zampini 
2489371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetDMWindow_Private(PetscViewer viewer, PetscViewer *view) {
2498135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2508135c375SStefano Zampini 
2518135c375SStefano Zampini   PetscFunctionBegin;
2520286d493SLisandro Dalcin   PetscValidPointer(view, 2);
2538135c375SStefano Zampini   if (!socket->meshwindow) {
2548135c375SStefano Zampini     if (socket->type == PETSC_VIEWER_GLVIS_SOCKET) {
2559566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->meshwindow));
2568135c375SStefano Zampini     } else {
25704b79de6SStefano Zampini       size_t    len;
25804b79de6SStefano Zampini       PetscBool isstdout;
25904b79de6SStefano Zampini 
2609566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
2619566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
26204b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
2639566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->meshwindow));
26404b79de6SStefano Zampini       } else {
2658135c375SStefano Zampini         PetscMPIInt rank;
2668135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
2679566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
2689566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-mesh.%06d", socket->name, rank));
2699566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->meshwindow));
2708135c375SStefano Zampini       }
27104b79de6SStefano Zampini     }
2721baa6e33SBarry Smith     if (socket->meshwindow) PetscCall(PetscViewerPushFormat(socket->meshwindow, PETSC_VIEWER_ASCII_GLVIS));
2738135c375SStefano Zampini   }
2741baa6e33SBarry Smith   if (socket->meshwindow) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, socket->meshwindow));
2758135c375SStefano Zampini   *view = socket->meshwindow;
2768135c375SStefano Zampini   PetscFunctionReturn(0);
2778135c375SStefano Zampini }
2788135c375SStefano Zampini 
2799371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisRestoreDMWindow_Private(PetscViewer viewer, PetscViewer *view) {
2800286d493SLisandro Dalcin   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2810286d493SLisandro Dalcin 
2820286d493SLisandro Dalcin   PetscFunctionBegin;
2830286d493SLisandro Dalcin   PetscValidPointer(view, 2);
284cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->meshwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetDMWindow()");
2850286d493SLisandro Dalcin   if (*view) {
2869566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
2879566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
2880286d493SLisandro Dalcin   }
2890286d493SLisandro Dalcin   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
2909566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->meshwindow));
2910286d493SLisandro Dalcin   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
2920286d493SLisandro Dalcin     socket->meshwindow = NULL;
2930286d493SLisandro Dalcin   }
2940286d493SLisandro Dalcin   *view = NULL;
2950286d493SLisandro Dalcin   PetscFunctionReturn(0);
2960286d493SLisandro Dalcin }
2970286d493SLisandro Dalcin 
2989371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetType_Private(PetscViewer viewer, PetscViewerGLVisType *type) {
2998135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3008135c375SStefano Zampini 
3018135c375SStefano Zampini   PetscFunctionBegin;
3028135c375SStefano Zampini   PetscValidPointer(type, 2);
3038135c375SStefano Zampini   *type = socket->type;
3048135c375SStefano Zampini   PetscFunctionReturn(0);
3058135c375SStefano Zampini }
3068135c375SStefano Zampini 
3078135c375SStefano Zampini /* This function is only relevant in the SOCKET_GLIVS case. The status is computed the first time it is requested, as GLVis currently has issues when connecting the first time through the socket */
3089371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetStatus_Private(PetscViewer viewer, PetscViewerGLVisStatus *sockstatus) {
3098135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3108135c375SStefano Zampini 
3118135c375SStefano Zampini   PetscFunctionBegin;
3128135c375SStefano Zampini   PetscValidPointer(sockstatus, 2);
3138135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
3148135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISCONNECTED;
3158135c375SStefano Zampini   } else if (socket->status == PETSCVIEWERGLVIS_DISCONNECTED && socket->nwindow) {
3168135c375SStefano Zampini     PetscInt  i;
3178135c375SStefano Zampini     PetscBool lconn, conn;
3188135c375SStefano Zampini 
3198135c375SStefano Zampini     for (i = 0, lconn = PETSC_TRUE; i < socket->nwindow; i++)
3209371c9d4SSatish Balay       if (!socket->window[i]) lconn = PETSC_FALSE;
3218135c375SStefano Zampini 
3221c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&lconn, &conn, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)viewer)));
3238135c375SStefano Zampini     if (conn) socket->status = PETSCVIEWERGLVIS_CONNECTED;
3248135c375SStefano Zampini   }
3258135c375SStefano Zampini   *sockstatus = socket->status;
3268135c375SStefano Zampini   PetscFunctionReturn(0);
3278135c375SStefano Zampini }
3288135c375SStefano Zampini 
3299371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetDM_Private(PetscViewer viewer, PetscObject *dm) {
3308135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3318135c375SStefano Zampini 
3328135c375SStefano Zampini   PetscFunctionBegin;
3338135c375SStefano Zampini   *dm = socket->dm;
3348135c375SStefano Zampini   PetscFunctionReturn(0);
3358135c375SStefano Zampini }
3368135c375SStefano Zampini 
3379371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetFields_Private(PetscViewer viewer, PetscInt *nfield, const char **fec[], PetscInt *spacedim[], PetscErrorCode (**g2lfield)(PetscObject, PetscInt, PetscObject[], void *), PetscObject *Ufield[], void **userctx) {
3388135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3398135c375SStefano Zampini 
3408135c375SStefano Zampini   PetscFunctionBegin;
3418135c375SStefano Zampini   if (nfield) *nfield = socket->nwindow;
3428135c375SStefano Zampini   if (fec) *fec = (const char **)socket->fec_type;
3434cac2994SStefano Zampini   if (spacedim) *spacedim = socket->spacedim;
3448135c375SStefano Zampini   if (g2lfield) *g2lfield = socket->g2lfield;
3458135c375SStefano Zampini   if (Ufield) *Ufield = socket->Ufield;
3468135c375SStefano Zampini   if (userctx) *userctx = socket->userctx;
3478135c375SStefano Zampini   PetscFunctionReturn(0);
3488135c375SStefano Zampini }
3498135c375SStefano Zampini 
3508135c375SStefano Zampini /* accessor routines for the viewer windows:
3518135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP   : it returns a new viewer every time
3528135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET : it returns the socket, and creates it if not yet done.
3538135c375SStefano Zampini */
3549371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisGetWindow_Private(PetscViewer viewer, PetscInt wid, PetscViewer *view) {
3558135c375SStefano Zampini   PetscViewerGLVis       socket = (PetscViewerGLVis)viewer->data;
3568135c375SStefano Zampini   PetscViewerGLVisStatus status;
3578135c375SStefano Zampini 
3588135c375SStefano Zampini   PetscFunctionBegin;
3598135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
3608135c375SStefano Zampini   PetscValidPointer(view, 3);
3612c71b3e2SJacob Faibussowitsch   PetscCheck(wid >= 0 && (wid <= socket->nwindow - 1), PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Cannot get window id %" PetscInt_FMT ": allowed range [0,%" PetscInt_FMT ")", wid, socket->nwindow - 1);
3628135c375SStefano Zampini   status = socket->status;
3632c71b3e2SJacob Faibussowitsch   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "Window %" PetscInt_FMT " is already in use", wid);
3648135c375SStefano Zampini   switch (status) {
3658135c375SStefano Zampini   case PETSCVIEWERGLVIS_DISCONNECTED:
3662c71b3e2SJacob Faibussowitsch     PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "This should not happen");
367f7d195e4SLawrence Mitchell     if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
36804b79de6SStefano Zampini       size_t    len;
36904b79de6SStefano Zampini       PetscBool isstdout;
37004b79de6SStefano Zampini 
3719566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
3729566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
37304b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
3749566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->window[wid]));
37504b79de6SStefano Zampini       } else {
3768135c375SStefano Zampini         PetscMPIInt rank;
3778135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
3788135c375SStefano Zampini 
3799566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3809566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-%s-%" PetscInt_FMT ".%06d", socket->name, socket->windowtitle[wid], socket->snapid, rank));
3819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->window[wid]));
38204b79de6SStefano Zampini       }
3838135c375SStefano Zampini     } else {
3849566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->window[wid]));
3858135c375SStefano Zampini     }
38648a46eb9SPierre Jolivet     if (socket->window[wid]) PetscCall(PetscViewerPushFormat(socket->window[wid], PETSC_VIEWER_ASCII_GLVIS));
3878135c375SStefano Zampini     *view = socket->window[wid];
3888135c375SStefano Zampini     break;
3899371c9d4SSatish Balay   case PETSCVIEWERGLVIS_CONNECTED: *view = socket->window[wid]; break;
3909371c9d4SSatish Balay   case PETSCVIEWERGLVIS_DISABLED: *view = NULL; break;
3919371c9d4SSatish Balay   default: SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unhandled socket status %d", (int)status);
3928135c375SStefano Zampini   }
3931baa6e33SBarry Smith   if (*view) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, *view));
3948135c375SStefano Zampini   PetscFunctionReturn(0);
3958135c375SStefano Zampini }
3968135c375SStefano Zampini 
3978135c375SStefano Zampini /* Restore the window viewer
3988135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP  : destroys the temporary created ASCII viewer used for dumping
3998135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET: - if the returned window viewer is not NULL, just zeros the pointer.
4008135c375SStefano Zampini                  - it the returned window viewer is NULL, assumes something went wrong
4018135c375SStefano Zampini                    with the socket (i.e. SIGPIPE when a user closes the popup window)
4028135c375SStefano Zampini                    and that the caller already handled it (see VecView_GLVis).
4038135c375SStefano Zampini */
4049371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisRestoreWindow_Private(PetscViewer viewer, PetscInt wid, PetscViewer *view) {
4058135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
4068135c375SStefano Zampini 
4078135c375SStefano Zampini   PetscFunctionBegin;
40863bd7f81SStefano Zampini   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERGLVIS);
4098135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
4108135c375SStefano Zampini   PetscValidPointer(view, 3);
411cc73adaaSBarry Smith   PetscCheck(wid >= 0 && wid < socket->nwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Cannot restore window id %" PetscInt_FMT ": allowed range [0,%" PetscInt_FMT ")", wid, socket->nwindow);
412cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->window[wid], PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetWindow()");
4138135c375SStefano Zampini   if (*view) {
4149566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
4159566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
4168135c375SStefano Zampini   }
4178135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
4189566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[wid]));
4198135c375SStefano Zampini   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
4208135c375SStefano Zampini     socket->window[wid] = NULL;
4218135c375SStefano Zampini   }
4228135c375SStefano Zampini   *view = NULL;
4238135c375SStefano Zampini   PetscFunctionReturn(0);
4248135c375SStefano Zampini }
4258135c375SStefano Zampini 
4268135c375SStefano Zampini /* default window appearance in the PETSC_VIEWER_GLVIS_SOCKET case */
4279371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisInitWindow_Private(PetscViewer viewer, PetscBool mesh, PetscInt dim, const char *name) {
4288135c375SStefano Zampini   PetscViewerGLVisInfo info;
4298135c375SStefano Zampini   PetscContainer       container;
4308135c375SStefano Zampini 
4318135c375SStefano Zampini   PetscFunctionBegin;
4329566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)viewer, "_glvis_info_container", (PetscObject *)&container));
43328b400f6SJacob Faibussowitsch   PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_USER, "Viewer was not obtained from PetscGLVisViewerGetNewWindow_Private");
4349566063dSJacob Faibussowitsch   PetscCall(PetscContainerGetPointer(container, (void **)&info));
435fe28a402SLisandro Dalcin   if (info->init) PetscFunctionReturn(0);
436fe28a402SLisandro Dalcin 
437fe28a402SLisandro Dalcin   /* Configure window */
43848a46eb9SPierre Jolivet   if (info->size[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "window_size %" PetscInt_FMT " %" PetscInt_FMT "\n", info->size[0], info->size[1]));
43948a46eb9SPierre Jolivet   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "window_title '%s'\n", name));
440fe28a402SLisandro Dalcin 
441fe28a402SLisandro Dalcin   /* Configure default view */
4428135c375SStefano Zampini   if (mesh) {
4438135c375SStefano Zampini     switch (dim) {
4448135c375SStefano Zampini     case 1:
4459566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4468135c375SStefano Zampini       break;
4478135c375SStefano Zampini     case 2:
4489566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4498135c375SStefano Zampini       break;
4509371c9d4SSatish Balay     case 3: /* TODO: decide default view in 3D */ break;
4518135c375SStefano Zampini     }
4528135c375SStefano Zampini   } else {
4539566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "keys cm\n")); /* show colorbar and mesh */
4548135c375SStefano Zampini     switch (dim) {
4558135c375SStefano Zampini     case 1:
4569566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys RRjl\n")); /* set to 1D (side view), turn off perspective and light */
4578135c375SStefano Zampini       break;
4588135c375SStefano Zampini     case 2:
4599566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys Rjl\n")); /* set to 2D (top view), turn off perspective and light */
4608135c375SStefano Zampini       break;
4619371c9d4SSatish Balay     case 3: break;
4628135c375SStefano Zampini     }
4639566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "autoscale value\n")); /* update value-range; keep mesh-extents fixed */
46473365f8bSLisandro Dalcin   }
465fe28a402SLisandro Dalcin 
466fe28a402SLisandro Dalcin   { /* Additional keys and commands */
467fe28a402SLisandro Dalcin     char         keys[256] = "", cmds[2 * PETSC_MAX_PATH_LEN] = "";
468fe28a402SLisandro Dalcin     PetscOptions opt = ((PetscObject)viewer)->options;
469fe28a402SLisandro Dalcin     const char  *pre = ((PetscObject)viewer)->prefix;
470fe28a402SLisandro Dalcin 
4719566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_keys", keys, sizeof(keys), NULL));
4729566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_exec", cmds, sizeof(cmds), NULL));
4739566063dSJacob Faibussowitsch     if (keys[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "keys %s\n", keys));
4749566063dSJacob Faibussowitsch     if (cmds[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", cmds));
4758135c375SStefano Zampini   }
476fe28a402SLisandro Dalcin 
477fe28a402SLisandro Dalcin   /* Pause visualization */
47848a46eb9SPierre Jolivet   if (!mesh && info->pause == -1) PetscCall(PetscViewerASCIIPrintf(viewer, "autopause 1\n"));
47948a46eb9SPierre Jolivet   if (!mesh && info->pause == 0) PetscCall(PetscViewerASCIIPrintf(viewer, "pause\n"));
480fe28a402SLisandro Dalcin 
4818135c375SStefano Zampini   info->init = PETSC_TRUE;
4828135c375SStefano Zampini   PetscFunctionReturn(0);
4838135c375SStefano Zampini }
4848135c375SStefano Zampini 
4859371c9d4SSatish Balay static PetscErrorCode PetscViewerDestroy_GLVis(PetscViewer viewer) {
4868135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
4878135c375SStefano Zampini   PetscInt         i;
4888135c375SStefano Zampini 
4898135c375SStefano Zampini   PetscFunctionBegin;
4908135c375SStefano Zampini   for (i = 0; i < socket->nwindow; i++) {
4919566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[i]));
4929566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->windowtitle[i]));
4939566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->fec_type[i]));
4949566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&socket->Ufield[i]));
4958135c375SStefano Zampini   }
4969566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
4979566063dSJacob Faibussowitsch   PetscCall(PetscFree5(socket->window, socket->windowtitle, socket->fec_type, socket->spacedim, socket->Ufield));
4989566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->fmt));
4999566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&socket->meshwindow));
5009566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&socket->dm));
5019566063dSJacob Faibussowitsch   if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx));
5028135c375SStefano Zampini 
5039566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", NULL));
5049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", NULL));
5059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", NULL));
5069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
5079566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket));
5088135c375SStefano Zampini   viewer->data = NULL;
5098135c375SStefano Zampini   PetscFunctionReturn(0);
5108135c375SStefano Zampini }
5118135c375SStefano Zampini 
5129371c9d4SSatish Balay static PetscErrorCode PetscViewerSetFromOptions_GLVis(PetscViewer v, PetscOptionItems *PetscOptionsObject) {
5138135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)v->data;
51473365f8bSLisandro Dalcin   PetscInt         nsizes = 2, prec = PETSC_DECIDE;
51573365f8bSLisandro Dalcin   PetscBool        set;
5168135c375SStefano Zampini 
5178135c375SStefano Zampini   PetscFunctionBegin;
518d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "GLVis PetscViewer Options");
5199566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-glvis_precision", "Number of digits for floating point values", "PetscViewerGLVisSetPrecision", prec, &prec, &set));
5209566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerGLVisSetPrecision(v, prec));
5219566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-glvis_size", "Window sizes", NULL, socket->windowsizes, &nsizes, &set));
52273365f8bSLisandro Dalcin   if (set && (nsizes == 1 || socket->windowsizes[1] < 0)) socket->windowsizes[1] = socket->windowsizes[0];
5239566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-glvis_pause", "-1 to pause after each visualization, otherwise sleeps for given seconds", NULL, socket->pause, &socket->pause, NULL));
5249566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_keys", "Additional keys to configure visualization", NULL, NULL));
5259566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_exec", "Additional commands to configure visualization", NULL, NULL));
526d0609cedSBarry Smith   PetscOptionsHeadEnd();
5278135c375SStefano Zampini   PetscFunctionReturn(0);
5288135c375SStefano Zampini }
5298135c375SStefano Zampini 
5309371c9d4SSatish Balay static PetscErrorCode PetscViewerFileSetName_GLVis(PetscViewer viewer, const char name[]) {
5318135c375SStefano Zampini   char            *sport;
5328135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5338135c375SStefano Zampini 
5348135c375SStefano Zampini   PetscFunctionBegin;
5358135c375SStefano Zampini   socket->type = PETSC_VIEWER_GLVIS_DUMP;
5368135c375SStefano Zampini   /* we accept localhost^port */
5379566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
5389566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &socket->name));
5399566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(socket->name, '^', &sport));
5408135c375SStefano Zampini   if (sport) {
5418135c375SStefano Zampini     PetscInt       port = 19916;
5428135c375SStefano Zampini     size_t         len;
5435f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
5448135c375SStefano Zampini 
5458135c375SStefano Zampini     *sport++ = 0;
5469566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(sport, &len));
5475f80ce2aSJacob Faibussowitsch     ierr = PetscOptionsStringToInt(sport, &port);
5485f80ce2aSJacob Faibussowitsch     if (PetscUnlikely(ierr)) {
5498135c375SStefano Zampini       socket->port = 19916;
5505f80ce2aSJacob Faibussowitsch     } else {
5515f80ce2aSJacob Faibussowitsch       socket->port = (port != PETSC_DECIDE && port != PETSC_DEFAULT) ? port : 19916;
5528135c375SStefano Zampini     }
5538135c375SStefano Zampini     socket->type = PETSC_VIEWER_GLVIS_SOCKET;
5548135c375SStefano Zampini   }
5558135c375SStefano Zampini   PetscFunctionReturn(0);
5568135c375SStefano Zampini }
5578135c375SStefano Zampini 
55873365f8bSLisandro Dalcin /*@C
559811af0c4SBarry Smith   PetscViewerGLVisOpen - Opens a `PETSCVIEWERGLVIS` `PetscViewer`
5608135c375SStefano Zampini 
561d083f849SBarry Smith   Collective
5628135c375SStefano Zampini 
5638135c375SStefano Zampini   Input Parameters:
5648135c375SStefano Zampini +  comm      - the MPI communicator
565811af0c4SBarry Smith .  type      - the viewer type: `PETSC_VIEWER_GLVIS_SOCKET` for real-time visualization or `PETSC_VIEWER_GLVIS_DUMP` for dumping to a file
5668135c375SStefano Zampini .  name      - either the hostname where the GLVis server is running or the base filename for dumping the data for subsequent visualizations
567811af0c4SBarry Smith -  port      - socket port where the GLVis server is listening. Not referenced when type is `PETSC_VIEWER_GLVIS_DUMP`
5688135c375SStefano Zampini 
5698135c375SStefano Zampini   Output Parameters:
570811af0c4SBarry Smith -  viewer    - the `PetscViewer` object
5718135c375SStefano Zampini 
57273365f8bSLisandro Dalcin   Options Database Keys:
573fe28a402SLisandro Dalcin +  -glvis_precision <precision> - Sets number of digits for floating point values
574fe28a402SLisandro Dalcin .  -glvis_size <width,height> - Sets the window size (in pixels)
57573365f8bSLisandro Dalcin .  -glvis_pause <pause> - Sets time (in seconds) that the program pauses after each visualization
576fe28a402SLisandro Dalcin        (0 is default, -1 implies every visualization)
577fe28a402SLisandro Dalcin .  -glvis_keys - Additional keys to configure visualization
578fe28a402SLisandro Dalcin -  -glvis_exec - Additional commands to configure visualization
57973365f8bSLisandro Dalcin 
580811af0c4SBarry Smith   Fortran Note:
581811af0c4SBarry Smith   Missing Fortran binding
5828135c375SStefano Zampini 
5838135c375SStefano Zampini   Level: beginner
5848135c375SStefano Zampini 
585811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerGLVisType`
58673365f8bSLisandro Dalcin @*/
5879371c9d4SSatish Balay PetscErrorCode PetscViewerGLVisOpen(MPI_Comm comm, PetscViewerGLVisType type, const char name[], PetscInt port, PetscViewer *viewer) {
5888135c375SStefano Zampini   PetscViewerGLVis socket;
5898135c375SStefano Zampini 
5908135c375SStefano Zampini   PetscFunctionBegin;
5919566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, viewer));
5929566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERGLVIS));
5938135c375SStefano Zampini 
5948135c375SStefano Zampini   socket       = (PetscViewerGLVis)((*viewer)->data);
595a7bda6aaSStefano Zampini   socket->type = type;
596a7bda6aaSStefano Zampini   if (type == PETSC_VIEWER_GLVIS_DUMP || name) {
5979566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->name));
5989566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &socket->name));
599a7bda6aaSStefano Zampini   }
600a7bda6aaSStefano Zampini   socket->port = (!port || port == PETSC_DETERMINE || port == PETSC_DECIDE) ? 19916 : port;
6018135c375SStefano Zampini 
6029566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*viewer));
6038135c375SStefano Zampini   PetscFunctionReturn(0);
6048135c375SStefano Zampini }
6058135c375SStefano Zampini 
6068135c375SStefano Zampini /*
607811af0c4SBarry Smith   PETSC_VIEWER_GLVIS_ - Creates a `PETSCVIEWERGLVIS` `PetscViewer` shared by all processors in a communicator.
6088135c375SStefano Zampini 
609d083f849SBarry Smith   Collective
6108135c375SStefano Zampini 
6118135c375SStefano Zampini   Input Parameter:
612811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERGLVIS` `PetscViewer`
6138135c375SStefano Zampini 
6148135c375SStefano Zampini   Level: intermediate
6158135c375SStefano Zampini 
6168135c375SStefano Zampini   Environmental variables:
617811af0c4SBarry Smith + `PETSC_VIEWER_GLVIS_FILENAME` : output filename (if specified dump to disk, and takes precedence on `PETSC_VIEWER_GLVIS_HOSTNAME`)
618811af0c4SBarry Smith . `PETSC_VIEWER_GLVIS_HOSTNAME` : machine where the GLVis server is listening (defaults to localhost)
619811af0c4SBarry Smith - `PETSC_VIEWER_GLVIS_PORT`     : port opened by the GLVis server (defaults to 19916)
6208135c375SStefano Zampini 
621811af0c4SBarry Smith   Note:
622811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_GLVIS_()` does not return
623811af0c4SBarry Smith   an error code.  It is usually used in the form
6248135c375SStefano Zampini $       XXXView(XXX object, PETSC_VIEWER_GLVIS_(comm));
6258135c375SStefano Zampini 
626811af0c4SBarry Smith   Fortran Note:
627811af0c4SBarry Smith   Missing Fortran bindings
628811af0c4SBarry Smith 
629811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewer`, `PetscViewerGLVISOpen()`, `PetscViewerGLVisType`, `PetscViewerCreate()`, `PetscViewerDestroy()`
6308135c375SStefano Zampini */
6319371c9d4SSatish Balay PetscViewer PETSC_VIEWER_GLVIS_(MPI_Comm comm) {
6328135c375SStefano Zampini   PetscErrorCode       ierr;
6338135c375SStefano Zampini   PetscBool            flg;
6348135c375SStefano Zampini   PetscViewer          viewer;
6358135c375SStefano Zampini   PetscViewerGLVisType type;
6368135c375SStefano Zampini   char                 fname[PETSC_MAX_PATH_LEN], sport[16];
6378135c375SStefano Zampini   PetscInt             port = 19916; /* default for GLVis */
6388135c375SStefano Zampini 
6398135c375SStefano Zampini   PetscFunctionBegin;
6409d7c699cSSatish Balay   ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
6419371c9d4SSatish Balay   if (ierr) {
6429371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6439371c9d4SSatish Balay     PetscFunctionReturn(NULL);
6449371c9d4SSatish Balay   }
6458135c375SStefano Zampini   if (!flg) {
6468135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_SOCKET;
6478135c375SStefano Zampini     ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_HOSTNAME", fname, PETSC_MAX_PATH_LEN, &flg);
6489371c9d4SSatish Balay     if (ierr) {
6499371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6509371c9d4SSatish Balay       PetscFunctionReturn(NULL);
6519371c9d4SSatish Balay     }
6528135c375SStefano Zampini     if (!flg) {
6538135c375SStefano Zampini       ierr = PetscStrcpy(fname, "localhost");
6549371c9d4SSatish Balay       if (ierr) {
6559371c9d4SSatish Balay         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6569371c9d4SSatish Balay         PetscFunctionReturn(NULL);
6579371c9d4SSatish Balay       }
6588135c375SStefano Zampini     }
6599d7c699cSSatish Balay     ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_PORT", sport, 16, &flg);
6609371c9d4SSatish Balay     if (ierr) {
6619371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6629371c9d4SSatish Balay       PetscFunctionReturn(NULL);
6639371c9d4SSatish Balay     }
6648135c375SStefano Zampini     if (flg) {
6658135c375SStefano Zampini       ierr = PetscOptionsStringToInt(sport, &port);
6669371c9d4SSatish Balay       if (ierr) {
6679371c9d4SSatish Balay         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6689371c9d4SSatish Balay         PetscFunctionReturn(NULL);
6699371c9d4SSatish Balay       }
6708135c375SStefano Zampini     }
6718135c375SStefano Zampini   } else {
6728135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_DUMP;
6738135c375SStefano Zampini   }
6748135c375SStefano Zampini   ierr = PetscViewerGLVisOpen(comm, type, fname, port, &viewer);
6759371c9d4SSatish Balay   if (ierr) {
6769371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6779371c9d4SSatish Balay     PetscFunctionReturn(NULL);
6789371c9d4SSatish Balay   }
6798135c375SStefano Zampini   ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
6809371c9d4SSatish Balay   if (ierr) {
6819371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6829371c9d4SSatish Balay     PetscFunctionReturn(NULL);
6839371c9d4SSatish Balay   }
6848135c375SStefano Zampini   PetscFunctionReturn(viewer);
6858135c375SStefano Zampini }
6868135c375SStefano Zampini 
6879371c9d4SSatish Balay PETSC_EXTERN PetscErrorCode PetscViewerCreate_GLVis(PetscViewer viewer) {
6888135c375SStefano Zampini   PetscViewerGLVis socket;
6898135c375SStefano Zampini 
6908135c375SStefano Zampini   PetscFunctionBegin;
691*4dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&socket));
6928135c375SStefano Zampini 
6938135c375SStefano Zampini   /* defaults to socket viewer */
6949566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("localhost", &socket->name));
6958135c375SStefano Zampini   socket->port  = 19916; /* GLVis default listening port */
6968135c375SStefano Zampini   socket->type  = PETSC_VIEWER_GLVIS_SOCKET;
6978135c375SStefano Zampini   socket->pause = 0; /* just pause the first time */
6988135c375SStefano Zampini 
69973365f8bSLisandro Dalcin   socket->windowsizes[0] = 600;
70073365f8bSLisandro Dalcin   socket->windowsizes[1] = 600;
70173365f8bSLisandro Dalcin 
70277eacf09SStefano Zampini   /* defaults to full precision */
7039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(" %g", &socket->fmt));
70477eacf09SStefano Zampini 
7058135c375SStefano Zampini   viewer->data                = (void *)socket;
7068135c375SStefano Zampini   viewer->ops->destroy        = PetscViewerDestroy_GLVis;
7078135c375SStefano Zampini   viewer->ops->setfromoptions = PetscViewerSetFromOptions_GLVis;
7088135c375SStefano Zampini 
7099566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", PetscViewerGLVisSetPrecision_GLVis));
7109566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", PetscViewerGLVisSetSnapId_GLVis));
7119566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", PetscViewerGLVisSetFields_GLVis));
7129566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_GLVis));
7138135c375SStefano Zampini   PetscFunctionReturn(0);
7148135c375SStefano Zampini }
7158135c375SStefano Zampini 
7168135c375SStefano Zampini /* this is a private implementation of a SOCKET with ASCII data format
7178135c375SStefano Zampini    GLVis does not currently handle binary socket streams */
7188135c375SStefano Zampini #if defined(PETSC_HAVE_UNISTD_H)
7198135c375SStefano Zampini #include <unistd.h>
7208135c375SStefano Zampini #endif
7218135c375SStefano Zampini 
722150de0cbSStefano Zampini #if !defined(PETSC_HAVE_WINDOWS_H)
7238135c375SStefano Zampini static PetscErrorCode (*PetscViewerDestroy_ASCII)(PetscViewer);
7248135c375SStefano Zampini 
7259371c9d4SSatish Balay static PetscErrorCode PetscViewerDestroy_ASCII_Socket(PetscViewer viewer) {
7268135c375SStefano Zampini   FILE *stream;
727d0609cedSBarry Smith 
7288135c375SStefano Zampini   PetscFunctionBegin;
7299566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetPointer(viewer, &stream));
7308135c375SStefano Zampini   if (stream) {
73140fde1d9SLisandro Dalcin     int retv = fclose(stream);
73240fde1d9SLisandro Dalcin     PetscCheck(!retv, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on stream");
7338135c375SStefano Zampini   }
7349566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy_ASCII(viewer));
7358135c375SStefano Zampini   PetscFunctionReturn(0);
7368135c375SStefano Zampini }
73727e89126SStefano Zampini #endif
73811a4995dSStefano Zampini 
7392da53a5bSBarry Smith /*
7402da53a5bSBarry Smith     This attempts to return a NULL viewer if it is unable to open a socket connection.
7412da53a5bSBarry Smith 
7422da53a5bSBarry Smith      The code below involving PetscUnlikely(ierr) is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
7432da53a5bSBarry Smith 
7442da53a5bSBarry Smith      The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain failure conditions but instead either return a special value
7452da53a5bSBarry Smith      of fd to indicate it was impossible to open the socket, or add another return argument to it indicating the socket was not opened.
7462da53a5bSBarry Smith */
7479371c9d4SSatish Balay static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm comm, const char *hostname, PetscInt port, PetscViewer *viewer) {
748150de0cbSStefano Zampini #if defined(PETSC_HAVE_WINDOWS_H)
74927e89126SStefano Zampini   PetscFunctionBegin;
75027e89126SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Not implemented for Windows");
75127e89126SStefano Zampini #else
7528135c375SStefano Zampini   FILE          *stream = NULL;
753178bdba8SJose E. Roman   int            fd     = 0;
7548135c375SStefano Zampini   PetscErrorCode ierr;
7558135c375SStefano Zampini 
7568135c375SStefano Zampini   PetscFunctionBegin;
757dadcf809SJacob Faibussowitsch   PetscValidCharPointer(hostname, 2);
7588135c375SStefano Zampini   PetscValidPointer(viewer, 4);
759c891a504SStefano Zampini #if defined(PETSC_USE_SOCKET_VIEWER)
7608135c375SStefano Zampini   ierr = PetscOpenSocket(hostname, port, &fd);
761c891a504SStefano Zampini #else
762c891a504SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Missing Socket viewer");
763c891a504SStefano Zampini #endif
7642da53a5bSBarry Smith   /*
7652da53a5bSBarry Smith      The following code is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
7662da53a5bSBarry Smith         The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain conditions but instead either return a special value
7672da53a5bSBarry Smith      of fd to indicate it was impossible to open the socket, or add another return argument to it indicating the socket was not opened.
7682da53a5bSBarry Smith    */
7693ca90d2dSJacob Faibussowitsch   if (PetscUnlikely(ierr)) {
7708135c375SStefano Zampini     char err[1024];
7718135c375SStefano Zampini 
7729566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(err, 1024, "Cannot connect to socket on %s:%" PetscInt_FMT ". Socket visualization is disabled\n", hostname, port));
7739566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "%s", err));
7748135c375SStefano Zampini     *viewer = NULL;
7752da53a5bSBarry Smith     PetscFunctionReturn(0);
7768135c375SStefano Zampini   } else {
7778135c375SStefano Zampini     char msg[1024];
7788135c375SStefano Zampini 
7799566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(msg, 1024, "Successfully connect to socket on %s:%" PetscInt_FMT ". Socket visualization is enabled\n", hostname, port));
7809566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "%s", msg));
7818135c375SStefano Zampini   }
7828135c375SStefano Zampini   stream = fdopen(fd, "w"); /* Not possible on Windows */
78328b400f6SJacob Faibussowitsch   PetscCheck(stream, PETSC_COMM_SELF, PETSC_ERR_SYS, "Cannot open stream from socket %s:%" PetscInt_FMT, hostname, port);
7849566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIOpenWithFILE(PETSC_COMM_SELF, stream, viewer));
7858135c375SStefano Zampini   PetscViewerDestroy_ASCII = (*viewer)->ops->destroy;
7868135c375SStefano Zampini   (*viewer)->ops->destroy  = PetscViewerDestroy_ASCII_Socket;
78727e89126SStefano Zampini #endif
7888135c375SStefano Zampini   PetscFunctionReturn(0);
7898135c375SStefano Zampini }
7900286d493SLisandro Dalcin 
7910286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIGPIPE)
7920286d493SLisandro Dalcin 
7930286d493SLisandro Dalcin #include <signal.h>
7940286d493SLisandro Dalcin 
7950286d493SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H)
7960286d493SLisandro Dalcin #define PETSC_DEVNULL "NUL"
7970286d493SLisandro Dalcin #else
7980286d493SLisandro Dalcin #define PETSC_DEVNULL "/dev/null"
7990286d493SLisandro Dalcin #endif
8000286d493SLisandro Dalcin 
8010286d493SLisandro Dalcin static volatile PetscBool PetscGLVisBrokenPipe = PETSC_FALSE;
8020286d493SLisandro Dalcin 
8030286d493SLisandro Dalcin static void (*PetscGLVisSigHandler_save)(int) = NULL;
8040286d493SLisandro Dalcin 
8059371c9d4SSatish Balay static void PetscGLVisSigHandler_SIGPIPE(PETSC_UNUSED int sig) {
8060286d493SLisandro Dalcin   PetscGLVisBrokenPipe = PETSC_TRUE;
8070286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIG_IGN)
8080286d493SLisandro Dalcin   signal(SIGPIPE, SIG_IGN);
8090286d493SLisandro Dalcin #endif
8100286d493SLisandro Dalcin }
8110286d493SLisandro Dalcin 
8129371c9d4SSatish Balay PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) {
8130286d493SLisandro Dalcin   PetscFunctionBegin;
81428b400f6SJacob Faibussowitsch   PetscCheck(!PetscGLVisSigHandler_save, comm, PETSC_ERR_PLIB, "Nested call to %s()", PETSC_FUNCTION_NAME);
8150286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8160286d493SLisandro Dalcin   PetscGLVisSigHandler_save = signal(SIGPIPE, PetscGLVisSigHandler_SIGPIPE);
8170286d493SLisandro Dalcin   PetscFunctionReturn(0);
8180286d493SLisandro Dalcin }
8190286d493SLisandro Dalcin 
8209371c9d4SSatish Balay PetscErrorCode PetscGLVisCollectiveEnd(MPI_Comm comm, PetscViewer *win) {
8210286d493SLisandro Dalcin   PetscBool flag, brokenpipe;
8220286d493SLisandro Dalcin 
8230286d493SLisandro Dalcin   PetscFunctionBegin;
8240286d493SLisandro Dalcin   flag = PetscGLVisBrokenPipe;
8251c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&flag, &brokenpipe, 1, MPIU_BOOL, MPI_LOR, comm));
8260286d493SLisandro Dalcin   if (brokenpipe) {
8270286d493SLisandro Dalcin     FILE *sock, *null = fopen(PETSC_DEVNULL, "w");
8289566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIGetPointer(*win, &sock));
8299566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISetFILE(*win, null));
8309566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(win));
8310286d493SLisandro Dalcin     if (sock) (void)fclose(sock);
8320286d493SLisandro Dalcin   }
8330286d493SLisandro Dalcin   (void)signal(SIGPIPE, PetscGLVisSigHandler_save);
8340286d493SLisandro Dalcin   PetscGLVisSigHandler_save = NULL;
8350286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8360286d493SLisandro Dalcin   PetscFunctionReturn(0);
8370286d493SLisandro Dalcin }
8380286d493SLisandro Dalcin 
8390286d493SLisandro Dalcin #else
8400286d493SLisandro Dalcin 
8419371c9d4SSatish Balay PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) {
8420286d493SLisandro Dalcin   PetscFunctionBegin;
8430286d493SLisandro Dalcin   PetscFunctionReturn(0);
8440286d493SLisandro Dalcin }
8450286d493SLisandro Dalcin 
8469371c9d4SSatish Balay PetscErrorCode PetscGLVisCollectiveEnd(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) {
8470286d493SLisandro Dalcin   PetscFunctionBegin;
8480286d493SLisandro Dalcin   PetscFunctionReturn(0);
8490286d493SLisandro Dalcin }
8500286d493SLisandro Dalcin 
8510286d493SLisandro Dalcin #endif
852