xref: /petsc/src/sys/classes/viewer/impls/glvis/glvis.c (revision c3339decea92175325d9368fa13196bcd0e0e58b)
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 @*/
46d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisSetPrecision(PetscViewer viewer, PetscInt prec)
47d71ae5a4SJacob Faibussowitsch {
4877eacf09SStefano Zampini   PetscFunctionBegin;
4977eacf09SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
50cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGLVisSetPrecision_C", (PetscViewer, PetscInt), (viewer, prec));
5177eacf09SStefano Zampini   PetscFunctionReturn(0);
5277eacf09SStefano Zampini }
5377eacf09SStefano Zampini 
54d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisSetPrecision_GLVis(PetscViewer viewer, PetscInt prec)
55d71ae5a4SJacob Faibussowitsch {
5677eacf09SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5777eacf09SStefano Zampini 
5877eacf09SStefano Zampini   PetscFunctionBegin;
599566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->fmt));
6077eacf09SStefano Zampini   if (prec > 0) {
619566063dSJacob Faibussowitsch     PetscCall(PetscMalloc1(16, &socket->fmt));
629566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(socket->fmt, 16, " %%.%" PetscInt_FMT "e", prec));
6377eacf09SStefano Zampini   } else {
649566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(" %g", &socket->fmt));
6577eacf09SStefano Zampini   }
6677eacf09SStefano Zampini   PetscFunctionReturn(0);
6777eacf09SStefano Zampini }
6877eacf09SStefano Zampini 
6977eacf09SStefano Zampini /*@
70811af0c4SBarry Smith      PetscViewerGLVisSetSnapId - Set the snapshot id. Only relevant when the `PetscViewerGLVisType` is `PETSC_VIEWER_GLVIS_DUMP`
718135c375SStefano Zampini 
72*c3339decSBarry Smith   Logically Collective
738135c375SStefano Zampini 
748135c375SStefano Zampini   Input Parameters:
75811af0c4SBarry Smith +  viewer - the `PetscViewer` of type `PETSCVIEWERGLVIS`
768135c375SStefano Zampini -  id     - the current snapshot id in a time-dependent simulation
778135c375SStefano Zampini 
788135c375SStefano Zampini   Level: beginner
798135c375SStefano Zampini 
80811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerGLVisOpen()`, `PetscViewerGLVisSetFields()`, `PetscViewerCreate()`, `PetscViewerSetType()`
818135c375SStefano Zampini @*/
82d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisSetSnapId(PetscViewer viewer, PetscInt id)
83d71ae5a4SJacob Faibussowitsch {
848135c375SStefano Zampini   PetscFunctionBegin;
858135c375SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
868135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, id, 2);
87cac4c232SBarry Smith   PetscTryMethod(viewer, "PetscViewerGLVisSetSnapId_C", (PetscViewer, PetscInt), (viewer, id));
888135c375SStefano Zampini   PetscFunctionReturn(0);
898135c375SStefano Zampini }
908135c375SStefano Zampini 
91d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisSetSnapId_GLVis(PetscViewer viewer, PetscInt id)
92d71ae5a4SJacob Faibussowitsch {
938135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
948135c375SStefano Zampini 
958135c375SStefano Zampini   PetscFunctionBegin;
9677eacf09SStefano Zampini   socket->snapid = id;
978135c375SStefano Zampini   PetscFunctionReturn(0);
988135c375SStefano Zampini }
998135c375SStefano Zampini 
1004cac2994SStefano Zampini /*@C
1014cac2994SStefano Zampini      PetscViewerGLVisSetFields - Sets the required information to visualize different fields from a vector.
1028135c375SStefano Zampini 
103*c3339decSBarry Smith   Logically Collective
1048135c375SStefano Zampini 
1058135c375SStefano Zampini   Input Parameters:
106811af0c4SBarry Smith +  viewer     - the `PetscViewer` of type `PETSCVIEWERGLVIS`
1078135c375SStefano Zampini .  nf         - number of fields to be visualized
1088135c375SStefano Zampini .  fec_type   - the type of finite element to be used to visualize the data (see FiniteElementCollection::Name() in MFEM)
1094cac2994SStefano Zampini .  dim        - array of space dimension for field vectors (used to initialize the scene)
1108135c375SStefano Zampini .  g2lfields  - User routine to compute the local field vectors to be visualized; PetscObject is used in place of Vec on the prototype
1114cac2994SStefano Zampini .  Vfield     - array of work vectors, one for each field
1128135c375SStefano Zampini .  ctx        - User context to store the relevant data to apply g2lfields
1138135c375SStefano Zampini -  destroyctx - Destroy function for userctx
1148135c375SStefano Zampini 
11595452b02SPatrick Sanan   Notes:
11695452b02SPatrick Sanan     g2lfields is called on the vector V to be visualized in order to extract the relevant dofs to be put in Vfield[], as
1178135c375SStefano Zampini .vb
1184cac2994SStefano Zampini   g2lfields((PetscObject)V,nfields,(PetscObject*)Vfield[],ctx).
1198135c375SStefano Zampini .ve
120811af0c4SBarry Smith 
1214cac2994SStefano Zampini   For vector spaces, the block size of Vfield[i] represents the vector dimension. It misses the Fortran bindings.
1224cac2994SStefano Zampini   The names of the Vfield vectors will be displayed in the window title.
1238135c375SStefano Zampini 
1248135c375SStefano Zampini   Level: intermediate
1258135c375SStefano Zampini 
126811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerGLVisOpen()`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscObjectSetName()`
1274cac2994SStefano Zampini @*/
128d71ae5a4SJacob Faibussowitsch 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 *))
129d71ae5a4SJacob Faibussowitsch {
1308135c375SStefano Zampini   PetscFunctionBegin;
1318135c375SStefano Zampini   PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1328135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, nf, 2);
13328b400f6SJacob Faibussowitsch   PetscCheck(fec_type, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "You need to provide the FiniteElementCollection names for the fields");
1344cac2994SStefano Zampini   PetscValidPointer(fec_type, 3);
135dadcf809SJacob Faibussowitsch   PetscValidIntPointer(dim, 4);
1364cac2994SStefano Zampini   PetscValidPointer(Vfield, 6);
137cac4c232SBarry 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));
1388135c375SStefano Zampini   PetscFunctionReturn(0);
1398135c375SStefano Zampini }
1408135c375SStefano Zampini 
141d71ae5a4SJacob Faibussowitsch 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 *))
142d71ae5a4SJacob Faibussowitsch {
1438135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
1448135c375SStefano Zampini   PetscInt         i;
1458135c375SStefano Zampini 
1468135c375SStefano Zampini   PetscFunctionBegin;
147cc73adaaSBarry 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);
1488135c375SStefano Zampini   if (!socket->nwindow) {
1498135c375SStefano Zampini     socket->nwindow = nfields;
1508135c375SStefano Zampini 
1519566063dSJacob Faibussowitsch     PetscCall(PetscCalloc5(nfields, &socket->window, nfields, &socket->windowtitle, nfields, &socket->fec_type, nfields, &socket->spacedim, nfields, &socket->Ufield));
1528135c375SStefano Zampini     for (i = 0; i < nfields; i++) {
1534cac2994SStefano Zampini       const char *name;
1548135c375SStefano Zampini 
1559566063dSJacob Faibussowitsch       PetscCall(PetscObjectGetName(Vfield[i], &name));
1569566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(name, &socket->windowtitle[i]));
1579566063dSJacob Faibussowitsch       PetscCall(PetscStrallocpy(fec_type[i], &socket->fec_type[i]));
1589566063dSJacob Faibussowitsch       PetscCall(PetscObjectReference(Vfield[i]));
1594cac2994SStefano Zampini       socket->Ufield[i]   = Vfield[i];
1604cac2994SStefano Zampini       socket->spacedim[i] = dim[i];
1618135c375SStefano Zampini     }
1628135c375SStefano Zampini   }
1638135c375SStefano Zampini   /* number of fields are not allowed to vary */
16408401ef6SPierre Jolivet   PetscCheck(nfields == socket->nwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot visualize %" PetscInt_FMT " fields using %" PetscInt_FMT " socket windows", nfields, socket->nwindow);
1658135c375SStefano Zampini   socket->g2lfield = g2l;
1669566063dSJacob Faibussowitsch   if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx));
1678135c375SStefano Zampini   socket->userctx    = ctx;
1688135c375SStefano Zampini   socket->destroyctx = destroyctx;
1698135c375SStefano Zampini   PetscFunctionReturn(0);
1708135c375SStefano Zampini }
1718135c375SStefano Zampini 
172d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisInfoDestroy_Private(void *ptr)
173d71ae5a4SJacob Faibussowitsch {
1748135c375SStefano Zampini   PetscViewerGLVisInfo info = (PetscViewerGLVisInfo)ptr;
1758135c375SStefano Zampini 
176c0bc9656SStefano Zampini   PetscFunctionBegin;
1779566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
1789566063dSJacob Faibussowitsch   PetscCall(PetscFree(info));
1798135c375SStefano Zampini   PetscFunctionReturn(0);
1808135c375SStefano Zampini }
1818135c375SStefano Zampini 
1828135c375SStefano Zampini /* we can decide to prevent specific processes from using the viewer */
183d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisAttachInfo_Private(PetscViewer viewer, PetscViewer window)
184d71ae5a4SJacob Faibussowitsch {
1858135c375SStefano Zampini   PetscViewerGLVis     socket = (PetscViewerGLVis)viewer->data;
1868135c375SStefano Zampini   PetscContainer       container;
1878135c375SStefano Zampini   PetscViewerGLVisInfo info;
1888135c375SStefano Zampini 
189c0bc9656SStefano Zampini   PetscFunctionBegin;
1909566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)window, "_glvis_info_container", (PetscObject *)&container));
19177eacf09SStefano Zampini   if (!container) {
1929566063dSJacob Faibussowitsch     PetscCall(PetscNew(&info));
1938135c375SStefano Zampini     info->enabled = PETSC_TRUE;
1948135c375SStefano Zampini     info->init    = PETSC_FALSE;
19573365f8bSLisandro Dalcin     info->size[0] = socket->windowsizes[0];
19673365f8bSLisandro Dalcin     info->size[1] = socket->windowsizes[1];
1978135c375SStefano Zampini     info->pause   = socket->pause;
1989566063dSJacob Faibussowitsch     PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)window), &container));
1999566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetPointer(container, (void *)info));
2009566063dSJacob Faibussowitsch     PetscCall(PetscContainerSetUserDestroy(container, PetscViewerGLVisInfoDestroy_Private));
2019566063dSJacob Faibussowitsch     PetscCall(PetscObjectCompose((PetscObject)window, "_glvis_info_container", (PetscObject)container));
2029566063dSJacob Faibussowitsch     PetscCall(PetscContainerDestroy(&container));
20377eacf09SStefano Zampini   } else {
2049566063dSJacob Faibussowitsch     PetscCall(PetscContainerGetPointer(container, (void **)&info));
20577eacf09SStefano Zampini   }
2069566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
2079566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(socket->fmt, &info->fmt));
2088135c375SStefano Zampini   PetscFunctionReturn(0);
2098135c375SStefano Zampini }
2108135c375SStefano Zampini 
211d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisGetNewWindow_Private(PetscViewer viewer, PetscViewer *view)
212d71ae5a4SJacob Faibussowitsch {
2138135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2148135c375SStefano Zampini   PetscViewer      window = NULL;
2158135c375SStefano Zampini   PetscBool        ldis, dis;
2168135c375SStefano Zampini 
2178135c375SStefano Zampini   PetscFunctionBegin;
2182da53a5bSBarry Smith   PetscCall(PetscViewerASCIISocketOpen(PETSC_COMM_SELF, socket->name, socket->port, &window));
2192da53a5bSBarry Smith   /* if we could not estabilish a connection, we disable the socket viewer on all MPI ranks */
2202da53a5bSBarry Smith   ldis = !viewer ? PETSC_TRUE : PETSC_FALSE;
2211c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&ldis, &dis, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)viewer)));
2228135c375SStefano Zampini   if (dis) {
2238135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISABLED;
2249566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&window));
2258135c375SStefano Zampini   }
2268135c375SStefano Zampini   *view = window;
2278135c375SStefano Zampini   PetscFunctionReturn(0);
2288135c375SStefano Zampini }
2298135c375SStefano Zampini 
230d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisPause_Private(PetscViewer viewer)
231d71ae5a4SJacob Faibussowitsch {
2328135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2338135c375SStefano Zampini 
2348135c375SStefano Zampini   PetscFunctionBegin;
23548a46eb9SPierre Jolivet   if (socket->type == PETSC_VIEWER_GLVIS_SOCKET && socket->pause > 0) PetscCall(PetscSleep(socket->pause));
2368135c375SStefano Zampini   PetscFunctionReturn(0);
2378135c375SStefano Zampini }
2388135c375SStefano Zampini 
2398135c375SStefano Zampini /* DM specific support */
240d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisSetDM_Private(PetscViewer viewer, PetscObject dm)
241d71ae5a4SJacob Faibussowitsch {
2428135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2438135c375SStefano Zampini 
2448135c375SStefano Zampini   PetscFunctionBegin;
245cc73adaaSBarry Smith   PetscCheck(!socket->dm || socket->dm == dm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot change DM associated with the GLVis viewer");
2468135c375SStefano Zampini   if (!socket->dm) {
2478135c375SStefano Zampini     PetscErrorCode (*setupwithdm)(PetscObject, PetscViewer) = NULL;
2488135c375SStefano Zampini 
2499566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction(dm, "DMSetUpGLVisViewer_C", &setupwithdm));
2508135c375SStefano Zampini     if (setupwithdm) {
2519566063dSJacob Faibussowitsch       PetscCall((*setupwithdm)(dm, viewer));
25298921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm(dm), PETSC_ERR_SUP, "No support for DM type %s", dm->type_name);
2539566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference(dm));
2548135c375SStefano Zampini     socket->dm = dm;
2558135c375SStefano Zampini   }
2568135c375SStefano Zampini   PetscFunctionReturn(0);
2578135c375SStefano Zampini }
2588135c375SStefano Zampini 
259d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDMWindow_Private(PetscViewer viewer, PetscViewer *view)
260d71ae5a4SJacob Faibussowitsch {
2618135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2628135c375SStefano Zampini 
2638135c375SStefano Zampini   PetscFunctionBegin;
2640286d493SLisandro Dalcin   PetscValidPointer(view, 2);
2658135c375SStefano Zampini   if (!socket->meshwindow) {
2668135c375SStefano Zampini     if (socket->type == PETSC_VIEWER_GLVIS_SOCKET) {
2679566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->meshwindow));
2688135c375SStefano Zampini     } else {
26904b79de6SStefano Zampini       size_t    len;
27004b79de6SStefano Zampini       PetscBool isstdout;
27104b79de6SStefano Zampini 
2729566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
2739566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
27404b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
2759566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->meshwindow));
27604b79de6SStefano Zampini       } else {
2778135c375SStefano Zampini         PetscMPIInt rank;
2788135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
2799566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
2809566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-mesh.%06d", socket->name, rank));
2819566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->meshwindow));
2828135c375SStefano Zampini       }
28304b79de6SStefano Zampini     }
2841baa6e33SBarry Smith     if (socket->meshwindow) PetscCall(PetscViewerPushFormat(socket->meshwindow, PETSC_VIEWER_ASCII_GLVIS));
2858135c375SStefano Zampini   }
2861baa6e33SBarry Smith   if (socket->meshwindow) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, socket->meshwindow));
2878135c375SStefano Zampini   *view = socket->meshwindow;
2888135c375SStefano Zampini   PetscFunctionReturn(0);
2898135c375SStefano Zampini }
2908135c375SStefano Zampini 
291d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreDMWindow_Private(PetscViewer viewer, PetscViewer *view)
292d71ae5a4SJacob Faibussowitsch {
2930286d493SLisandro Dalcin   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2940286d493SLisandro Dalcin 
2950286d493SLisandro Dalcin   PetscFunctionBegin;
2960286d493SLisandro Dalcin   PetscValidPointer(view, 2);
297cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->meshwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetDMWindow()");
2980286d493SLisandro Dalcin   if (*view) {
2999566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
3009566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
3010286d493SLisandro Dalcin   }
3020286d493SLisandro Dalcin   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
3039566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->meshwindow));
3040286d493SLisandro Dalcin   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
3050286d493SLisandro Dalcin     socket->meshwindow = NULL;
3060286d493SLisandro Dalcin   }
3070286d493SLisandro Dalcin   *view = NULL;
3080286d493SLisandro Dalcin   PetscFunctionReturn(0);
3090286d493SLisandro Dalcin }
3100286d493SLisandro Dalcin 
311d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetType_Private(PetscViewer viewer, PetscViewerGLVisType *type)
312d71ae5a4SJacob Faibussowitsch {
3138135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3148135c375SStefano Zampini 
3158135c375SStefano Zampini   PetscFunctionBegin;
3168135c375SStefano Zampini   PetscValidPointer(type, 2);
3178135c375SStefano Zampini   *type = socket->type;
3188135c375SStefano Zampini   PetscFunctionReturn(0);
3198135c375SStefano Zampini }
3208135c375SStefano Zampini 
3218135c375SStefano 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 */
322d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetStatus_Private(PetscViewer viewer, PetscViewerGLVisStatus *sockstatus)
323d71ae5a4SJacob Faibussowitsch {
3248135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3258135c375SStefano Zampini 
3268135c375SStefano Zampini   PetscFunctionBegin;
3278135c375SStefano Zampini   PetscValidPointer(sockstatus, 2);
3288135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
3298135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISCONNECTED;
3308135c375SStefano Zampini   } else if (socket->status == PETSCVIEWERGLVIS_DISCONNECTED && socket->nwindow) {
3318135c375SStefano Zampini     PetscInt  i;
3328135c375SStefano Zampini     PetscBool lconn, conn;
3338135c375SStefano Zampini 
3348135c375SStefano Zampini     for (i = 0, lconn = PETSC_TRUE; i < socket->nwindow; i++)
3359371c9d4SSatish Balay       if (!socket->window[i]) lconn = PETSC_FALSE;
3368135c375SStefano Zampini 
3371c2dc1cbSBarry Smith     PetscCall(MPIU_Allreduce(&lconn, &conn, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)viewer)));
3388135c375SStefano Zampini     if (conn) socket->status = PETSCVIEWERGLVIS_CONNECTED;
3398135c375SStefano Zampini   }
3408135c375SStefano Zampini   *sockstatus = socket->status;
3418135c375SStefano Zampini   PetscFunctionReturn(0);
3428135c375SStefano Zampini }
3438135c375SStefano Zampini 
344d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDM_Private(PetscViewer viewer, PetscObject *dm)
345d71ae5a4SJacob Faibussowitsch {
3468135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3478135c375SStefano Zampini 
3488135c375SStefano Zampini   PetscFunctionBegin;
3498135c375SStefano Zampini   *dm = socket->dm;
3508135c375SStefano Zampini   PetscFunctionReturn(0);
3518135c375SStefano Zampini }
3528135c375SStefano Zampini 
353d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetFields_Private(PetscViewer viewer, PetscInt *nfield, const char **fec[], PetscInt *spacedim[], PetscErrorCode (**g2lfield)(PetscObject, PetscInt, PetscObject[], void *), PetscObject *Ufield[], void **userctx)
354d71ae5a4SJacob Faibussowitsch {
3558135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3568135c375SStefano Zampini 
3578135c375SStefano Zampini   PetscFunctionBegin;
3588135c375SStefano Zampini   if (nfield) *nfield = socket->nwindow;
3598135c375SStefano Zampini   if (fec) *fec = (const char **)socket->fec_type;
3604cac2994SStefano Zampini   if (spacedim) *spacedim = socket->spacedim;
3618135c375SStefano Zampini   if (g2lfield) *g2lfield = socket->g2lfield;
3628135c375SStefano Zampini   if (Ufield) *Ufield = socket->Ufield;
3638135c375SStefano Zampini   if (userctx) *userctx = socket->userctx;
3648135c375SStefano Zampini   PetscFunctionReturn(0);
3658135c375SStefano Zampini }
3668135c375SStefano Zampini 
3678135c375SStefano Zampini /* accessor routines for the viewer windows:
3688135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP   : it returns a new viewer every time
3698135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET : it returns the socket, and creates it if not yet done.
3708135c375SStefano Zampini */
371d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetWindow_Private(PetscViewer viewer, PetscInt wid, PetscViewer *view)
372d71ae5a4SJacob Faibussowitsch {
3738135c375SStefano Zampini   PetscViewerGLVis       socket = (PetscViewerGLVis)viewer->data;
3748135c375SStefano Zampini   PetscViewerGLVisStatus status;
3758135c375SStefano Zampini 
3768135c375SStefano Zampini   PetscFunctionBegin;
3778135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
3788135c375SStefano Zampini   PetscValidPointer(view, 3);
3792c71b3e2SJacob 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);
3808135c375SStefano Zampini   status = socket->status;
3812c71b3e2SJacob 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);
3828135c375SStefano Zampini   switch (status) {
3838135c375SStefano Zampini   case PETSCVIEWERGLVIS_DISCONNECTED:
3842c71b3e2SJacob Faibussowitsch     PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "This should not happen");
385f7d195e4SLawrence Mitchell     if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
38604b79de6SStefano Zampini       size_t    len;
38704b79de6SStefano Zampini       PetscBool isstdout;
38804b79de6SStefano Zampini 
3899566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
3909566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
39104b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
3929566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->window[wid]));
39304b79de6SStefano Zampini       } else {
3948135c375SStefano Zampini         PetscMPIInt rank;
3958135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
3968135c375SStefano Zampini 
3979566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3989566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-%s-%" PetscInt_FMT ".%06d", socket->name, socket->windowtitle[wid], socket->snapid, rank));
3999566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->window[wid]));
40004b79de6SStefano Zampini       }
4018135c375SStefano Zampini     } else {
4029566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->window[wid]));
4038135c375SStefano Zampini     }
40448a46eb9SPierre Jolivet     if (socket->window[wid]) PetscCall(PetscViewerPushFormat(socket->window[wid], PETSC_VIEWER_ASCII_GLVIS));
4058135c375SStefano Zampini     *view = socket->window[wid];
4068135c375SStefano Zampini     break;
407d71ae5a4SJacob Faibussowitsch   case PETSCVIEWERGLVIS_CONNECTED:
408d71ae5a4SJacob Faibussowitsch     *view = socket->window[wid];
409d71ae5a4SJacob Faibussowitsch     break;
410d71ae5a4SJacob Faibussowitsch   case PETSCVIEWERGLVIS_DISABLED:
411d71ae5a4SJacob Faibussowitsch     *view = NULL;
412d71ae5a4SJacob Faibussowitsch     break;
413d71ae5a4SJacob Faibussowitsch   default:
414d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unhandled socket status %d", (int)status);
4158135c375SStefano Zampini   }
4161baa6e33SBarry Smith   if (*view) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, *view));
4178135c375SStefano Zampini   PetscFunctionReturn(0);
4188135c375SStefano Zampini }
4198135c375SStefano Zampini 
4208135c375SStefano Zampini /* Restore the window viewer
4218135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP  : destroys the temporary created ASCII viewer used for dumping
4228135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET: - if the returned window viewer is not NULL, just zeros the pointer.
4238135c375SStefano Zampini                  - it the returned window viewer is NULL, assumes something went wrong
4248135c375SStefano Zampini                    with the socket (i.e. SIGPIPE when a user closes the popup window)
4258135c375SStefano Zampini                    and that the caller already handled it (see VecView_GLVis).
4268135c375SStefano Zampini */
427d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreWindow_Private(PetscViewer viewer, PetscInt wid, PetscViewer *view)
428d71ae5a4SJacob Faibussowitsch {
4298135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
4308135c375SStefano Zampini 
4318135c375SStefano Zampini   PetscFunctionBegin;
43263bd7f81SStefano Zampini   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERGLVIS);
4338135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
4348135c375SStefano Zampini   PetscValidPointer(view, 3);
435cc73adaaSBarry 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);
436cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->window[wid], PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetWindow()");
4378135c375SStefano Zampini   if (*view) {
4389566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
4399566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
4408135c375SStefano Zampini   }
4418135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
4429566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[wid]));
4438135c375SStefano Zampini   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
4448135c375SStefano Zampini     socket->window[wid] = NULL;
4458135c375SStefano Zampini   }
4468135c375SStefano Zampini   *view = NULL;
4478135c375SStefano Zampini   PetscFunctionReturn(0);
4488135c375SStefano Zampini }
4498135c375SStefano Zampini 
4508135c375SStefano Zampini /* default window appearance in the PETSC_VIEWER_GLVIS_SOCKET case */
451d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisInitWindow_Private(PetscViewer viewer, PetscBool mesh, PetscInt dim, const char *name)
452d71ae5a4SJacob Faibussowitsch {
4538135c375SStefano Zampini   PetscViewerGLVisInfo info;
4548135c375SStefano Zampini   PetscContainer       container;
4558135c375SStefano Zampini 
4568135c375SStefano Zampini   PetscFunctionBegin;
4579566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)viewer, "_glvis_info_container", (PetscObject *)&container));
45828b400f6SJacob Faibussowitsch   PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_USER, "Viewer was not obtained from PetscGLVisViewerGetNewWindow_Private");
4599566063dSJacob Faibussowitsch   PetscCall(PetscContainerGetPointer(container, (void **)&info));
460fe28a402SLisandro Dalcin   if (info->init) PetscFunctionReturn(0);
461fe28a402SLisandro Dalcin 
462fe28a402SLisandro Dalcin   /* Configure window */
46348a46eb9SPierre Jolivet   if (info->size[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "window_size %" PetscInt_FMT " %" PetscInt_FMT "\n", info->size[0], info->size[1]));
46448a46eb9SPierre Jolivet   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "window_title '%s'\n", name));
465fe28a402SLisandro Dalcin 
466fe28a402SLisandro Dalcin   /* Configure default view */
4678135c375SStefano Zampini   if (mesh) {
4688135c375SStefano Zampini     switch (dim) {
4698135c375SStefano Zampini     case 1:
4709566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4718135c375SStefano Zampini       break;
4728135c375SStefano Zampini     case 2:
4739566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4748135c375SStefano Zampini       break;
475d71ae5a4SJacob Faibussowitsch     case 3: /* TODO: decide default view in 3D */
476d71ae5a4SJacob Faibussowitsch       break;
4778135c375SStefano Zampini     }
4788135c375SStefano Zampini   } else {
4799566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "keys cm\n")); /* show colorbar and mesh */
4808135c375SStefano Zampini     switch (dim) {
4818135c375SStefano Zampini     case 1:
4829566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys RRjl\n")); /* set to 1D (side view), turn off perspective and light */
4838135c375SStefano Zampini       break;
4848135c375SStefano Zampini     case 2:
4859566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys Rjl\n")); /* set to 2D (top view), turn off perspective and light */
4868135c375SStefano Zampini       break;
487d71ae5a4SJacob Faibussowitsch     case 3:
488d71ae5a4SJacob Faibussowitsch       break;
4898135c375SStefano Zampini     }
4909566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "autoscale value\n")); /* update value-range; keep mesh-extents fixed */
49173365f8bSLisandro Dalcin   }
492fe28a402SLisandro Dalcin 
493fe28a402SLisandro Dalcin   { /* Additional keys and commands */
494fe28a402SLisandro Dalcin     char         keys[256] = "", cmds[2 * PETSC_MAX_PATH_LEN] = "";
495fe28a402SLisandro Dalcin     PetscOptions opt = ((PetscObject)viewer)->options;
496fe28a402SLisandro Dalcin     const char  *pre = ((PetscObject)viewer)->prefix;
497fe28a402SLisandro Dalcin 
4989566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_keys", keys, sizeof(keys), NULL));
4999566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_exec", cmds, sizeof(cmds), NULL));
5009566063dSJacob Faibussowitsch     if (keys[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "keys %s\n", keys));
5019566063dSJacob Faibussowitsch     if (cmds[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", cmds));
5028135c375SStefano Zampini   }
503fe28a402SLisandro Dalcin 
504fe28a402SLisandro Dalcin   /* Pause visualization */
50548a46eb9SPierre Jolivet   if (!mesh && info->pause == -1) PetscCall(PetscViewerASCIIPrintf(viewer, "autopause 1\n"));
50648a46eb9SPierre Jolivet   if (!mesh && info->pause == 0) PetscCall(PetscViewerASCIIPrintf(viewer, "pause\n"));
507fe28a402SLisandro Dalcin 
5088135c375SStefano Zampini   info->init = PETSC_TRUE;
5098135c375SStefano Zampini   PetscFunctionReturn(0);
5108135c375SStefano Zampini }
5118135c375SStefano Zampini 
512d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_GLVis(PetscViewer viewer)
513d71ae5a4SJacob Faibussowitsch {
5148135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5158135c375SStefano Zampini   PetscInt         i;
5168135c375SStefano Zampini 
5178135c375SStefano Zampini   PetscFunctionBegin;
5188135c375SStefano Zampini   for (i = 0; i < socket->nwindow; i++) {
5199566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[i]));
5209566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->windowtitle[i]));
5219566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->fec_type[i]));
5229566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&socket->Ufield[i]));
5238135c375SStefano Zampini   }
5249566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
5259566063dSJacob Faibussowitsch   PetscCall(PetscFree5(socket->window, socket->windowtitle, socket->fec_type, socket->spacedim, socket->Ufield));
5269566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->fmt));
5279566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&socket->meshwindow));
5289566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&socket->dm));
5299566063dSJacob Faibussowitsch   if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx));
5308135c375SStefano Zampini 
5319566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", NULL));
5329566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", NULL));
5339566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", NULL));
5349566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
5359566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket));
5368135c375SStefano Zampini   viewer->data = NULL;
5378135c375SStefano Zampini   PetscFunctionReturn(0);
5388135c375SStefano Zampini }
5398135c375SStefano Zampini 
540d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetFromOptions_GLVis(PetscViewer v, PetscOptionItems *PetscOptionsObject)
541d71ae5a4SJacob Faibussowitsch {
5428135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)v->data;
54373365f8bSLisandro Dalcin   PetscInt         nsizes = 2, prec = PETSC_DECIDE;
54473365f8bSLisandro Dalcin   PetscBool        set;
5458135c375SStefano Zampini 
5468135c375SStefano Zampini   PetscFunctionBegin;
547d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "GLVis PetscViewer Options");
5489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-glvis_precision", "Number of digits for floating point values", "PetscViewerGLVisSetPrecision", prec, &prec, &set));
5499566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerGLVisSetPrecision(v, prec));
5509566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-glvis_size", "Window sizes", NULL, socket->windowsizes, &nsizes, &set));
55173365f8bSLisandro Dalcin   if (set && (nsizes == 1 || socket->windowsizes[1] < 0)) socket->windowsizes[1] = socket->windowsizes[0];
5529566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-glvis_pause", "-1 to pause after each visualization, otherwise sleeps for given seconds", NULL, socket->pause, &socket->pause, NULL));
5539566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_keys", "Additional keys to configure visualization", NULL, NULL));
5549566063dSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_exec", "Additional commands to configure visualization", NULL, NULL));
555d0609cedSBarry Smith   PetscOptionsHeadEnd();
5568135c375SStefano Zampini   PetscFunctionReturn(0);
5578135c375SStefano Zampini }
5588135c375SStefano Zampini 
559d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_GLVis(PetscViewer viewer, const char name[])
560d71ae5a4SJacob Faibussowitsch {
5618135c375SStefano Zampini   char            *sport;
5628135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5638135c375SStefano Zampini 
5648135c375SStefano Zampini   PetscFunctionBegin;
5658135c375SStefano Zampini   socket->type = PETSC_VIEWER_GLVIS_DUMP;
5668135c375SStefano Zampini   /* we accept localhost^port */
5679566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
5689566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &socket->name));
5699566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(socket->name, '^', &sport));
5708135c375SStefano Zampini   if (sport) {
5718135c375SStefano Zampini     PetscInt       port = 19916;
5728135c375SStefano Zampini     size_t         len;
5735f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
5748135c375SStefano Zampini 
5758135c375SStefano Zampini     *sport++ = 0;
5769566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(sport, &len));
5775f80ce2aSJacob Faibussowitsch     ierr = PetscOptionsStringToInt(sport, &port);
5785f80ce2aSJacob Faibussowitsch     if (PetscUnlikely(ierr)) {
5798135c375SStefano Zampini       socket->port = 19916;
5805f80ce2aSJacob Faibussowitsch     } else {
5815f80ce2aSJacob Faibussowitsch       socket->port = (port != PETSC_DECIDE && port != PETSC_DEFAULT) ? port : 19916;
5828135c375SStefano Zampini     }
5838135c375SStefano Zampini     socket->type = PETSC_VIEWER_GLVIS_SOCKET;
5848135c375SStefano Zampini   }
5858135c375SStefano Zampini   PetscFunctionReturn(0);
5868135c375SStefano Zampini }
5878135c375SStefano Zampini 
58873365f8bSLisandro Dalcin /*@C
589811af0c4SBarry Smith   PetscViewerGLVisOpen - Opens a `PETSCVIEWERGLVIS` `PetscViewer`
5908135c375SStefano Zampini 
591d083f849SBarry Smith   Collective
5928135c375SStefano Zampini 
5938135c375SStefano Zampini   Input Parameters:
5948135c375SStefano Zampini +  comm      - the MPI communicator
595811af0c4SBarry Smith .  type      - the viewer type: `PETSC_VIEWER_GLVIS_SOCKET` for real-time visualization or `PETSC_VIEWER_GLVIS_DUMP` for dumping to a file
5968135c375SStefano Zampini .  name      - either the hostname where the GLVis server is running or the base filename for dumping the data for subsequent visualizations
597811af0c4SBarry Smith -  port      - socket port where the GLVis server is listening. Not referenced when type is `PETSC_VIEWER_GLVIS_DUMP`
5988135c375SStefano Zampini 
5998135c375SStefano Zampini   Output Parameters:
600811af0c4SBarry Smith -  viewer    - the `PetscViewer` object
6018135c375SStefano Zampini 
60273365f8bSLisandro Dalcin   Options Database Keys:
603fe28a402SLisandro Dalcin +  -glvis_precision <precision> - Sets number of digits for floating point values
604fe28a402SLisandro Dalcin .  -glvis_size <width,height> - Sets the window size (in pixels)
60573365f8bSLisandro Dalcin .  -glvis_pause <pause> - Sets time (in seconds) that the program pauses after each visualization
606fe28a402SLisandro Dalcin        (0 is default, -1 implies every visualization)
607fe28a402SLisandro Dalcin .  -glvis_keys - Additional keys to configure visualization
608fe28a402SLisandro Dalcin -  -glvis_exec - Additional commands to configure visualization
60973365f8bSLisandro Dalcin 
610811af0c4SBarry Smith   Fortran Note:
611811af0c4SBarry Smith   Missing Fortran binding
6128135c375SStefano Zampini 
6138135c375SStefano Zampini   Level: beginner
6148135c375SStefano Zampini 
615811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerGLVisType`
61673365f8bSLisandro Dalcin @*/
617d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisOpen(MPI_Comm comm, PetscViewerGLVisType type, const char name[], PetscInt port, PetscViewer *viewer)
618d71ae5a4SJacob Faibussowitsch {
6198135c375SStefano Zampini   PetscViewerGLVis socket;
6208135c375SStefano Zampini 
6218135c375SStefano Zampini   PetscFunctionBegin;
6229566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, viewer));
6239566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERGLVIS));
6248135c375SStefano Zampini 
6258135c375SStefano Zampini   socket       = (PetscViewerGLVis)((*viewer)->data);
626a7bda6aaSStefano Zampini   socket->type = type;
627a7bda6aaSStefano Zampini   if (type == PETSC_VIEWER_GLVIS_DUMP || name) {
6289566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->name));
6299566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &socket->name));
630a7bda6aaSStefano Zampini   }
631a7bda6aaSStefano Zampini   socket->port = (!port || port == PETSC_DETERMINE || port == PETSC_DECIDE) ? 19916 : port;
6328135c375SStefano Zampini 
6339566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*viewer));
6348135c375SStefano Zampini   PetscFunctionReturn(0);
6358135c375SStefano Zampini }
6368135c375SStefano Zampini 
6378135c375SStefano Zampini /*
638811af0c4SBarry Smith   PETSC_VIEWER_GLVIS_ - Creates a `PETSCVIEWERGLVIS` `PetscViewer` shared by all processors in a communicator.
6398135c375SStefano Zampini 
640d083f849SBarry Smith   Collective
6418135c375SStefano Zampini 
6428135c375SStefano Zampini   Input Parameter:
643811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERGLVIS` `PetscViewer`
6448135c375SStefano Zampini 
6458135c375SStefano Zampini   Level: intermediate
6468135c375SStefano Zampini 
6478135c375SStefano Zampini   Environmental variables:
648811af0c4SBarry Smith + `PETSC_VIEWER_GLVIS_FILENAME` : output filename (if specified dump to disk, and takes precedence on `PETSC_VIEWER_GLVIS_HOSTNAME`)
649811af0c4SBarry Smith . `PETSC_VIEWER_GLVIS_HOSTNAME` : machine where the GLVis server is listening (defaults to localhost)
650811af0c4SBarry Smith - `PETSC_VIEWER_GLVIS_PORT`     : port opened by the GLVis server (defaults to 19916)
6518135c375SStefano Zampini 
652811af0c4SBarry Smith   Note:
653811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_GLVIS_()` does not return
654811af0c4SBarry Smith   an error code.  It is usually used in the form
6558135c375SStefano Zampini $       XXXView(XXX object, PETSC_VIEWER_GLVIS_(comm));
6568135c375SStefano Zampini 
657811af0c4SBarry Smith   Fortran Note:
658811af0c4SBarry Smith   Missing Fortran bindings
659811af0c4SBarry Smith 
660811af0c4SBarry Smith .seealso: `PETSCVIEWERGLVIS`, `PetscViewer`, `PetscViewerGLVISOpen()`, `PetscViewerGLVisType`, `PetscViewerCreate()`, `PetscViewerDestroy()`
6618135c375SStefano Zampini */
662d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_GLVIS_(MPI_Comm comm)
663d71ae5a4SJacob Faibussowitsch {
6648135c375SStefano Zampini   PetscErrorCode       ierr;
6658135c375SStefano Zampini   PetscBool            flg;
6668135c375SStefano Zampini   PetscViewer          viewer;
6678135c375SStefano Zampini   PetscViewerGLVisType type;
6688135c375SStefano Zampini   char                 fname[PETSC_MAX_PATH_LEN], sport[16];
6698135c375SStefano Zampini   PetscInt             port = 19916; /* default for GLVis */
6708135c375SStefano Zampini 
6718135c375SStefano Zampini   PetscFunctionBegin;
6729d7c699cSSatish Balay   ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg);
6739371c9d4SSatish Balay   if (ierr) {
6749371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6759371c9d4SSatish Balay     PetscFunctionReturn(NULL);
6769371c9d4SSatish Balay   }
6778135c375SStefano Zampini   if (!flg) {
6788135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_SOCKET;
6798135c375SStefano Zampini     ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_HOSTNAME", fname, PETSC_MAX_PATH_LEN, &flg);
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     if (!flg) {
6858135c375SStefano Zampini       ierr = PetscStrcpy(fname, "localhost");
6869371c9d4SSatish Balay       if (ierr) {
6879371c9d4SSatish Balay         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6889371c9d4SSatish Balay         PetscFunctionReturn(NULL);
6899371c9d4SSatish Balay       }
6908135c375SStefano Zampini     }
6919d7c699cSSatish Balay     ierr = PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_PORT", sport, 16, &flg);
6929371c9d4SSatish Balay     if (ierr) {
6939371c9d4SSatish Balay       PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
6949371c9d4SSatish Balay       PetscFunctionReturn(NULL);
6959371c9d4SSatish Balay     }
6968135c375SStefano Zampini     if (flg) {
6978135c375SStefano Zampini       ierr = PetscOptionsStringToInt(sport, &port);
6989371c9d4SSatish Balay       if (ierr) {
6999371c9d4SSatish Balay         PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
7009371c9d4SSatish Balay         PetscFunctionReturn(NULL);
7019371c9d4SSatish Balay       }
7028135c375SStefano Zampini     }
7038135c375SStefano Zampini   } else {
7048135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_DUMP;
7058135c375SStefano Zampini   }
7068135c375SStefano Zampini   ierr = PetscViewerGLVisOpen(comm, type, fname, port, &viewer);
7079371c9d4SSatish Balay   if (ierr) {
7089371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
7099371c9d4SSatish Balay     PetscFunctionReturn(NULL);
7109371c9d4SSatish Balay   }
7118135c375SStefano Zampini   ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
7129371c9d4SSatish Balay   if (ierr) {
7139371c9d4SSatish Balay     PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_GLVIS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " ");
7149371c9d4SSatish Balay     PetscFunctionReturn(NULL);
7159371c9d4SSatish Balay   }
7168135c375SStefano Zampini   PetscFunctionReturn(viewer);
7178135c375SStefano Zampini }
7188135c375SStefano Zampini 
719d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_GLVis(PetscViewer viewer)
720d71ae5a4SJacob Faibussowitsch {
7218135c375SStefano Zampini   PetscViewerGLVis socket;
7228135c375SStefano Zampini 
7238135c375SStefano Zampini   PetscFunctionBegin;
7244dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&socket));
7258135c375SStefano Zampini 
7268135c375SStefano Zampini   /* defaults to socket viewer */
7279566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("localhost", &socket->name));
7288135c375SStefano Zampini   socket->port  = 19916; /* GLVis default listening port */
7298135c375SStefano Zampini   socket->type  = PETSC_VIEWER_GLVIS_SOCKET;
7308135c375SStefano Zampini   socket->pause = 0; /* just pause the first time */
7318135c375SStefano Zampini 
73273365f8bSLisandro Dalcin   socket->windowsizes[0] = 600;
73373365f8bSLisandro Dalcin   socket->windowsizes[1] = 600;
73473365f8bSLisandro Dalcin 
73577eacf09SStefano Zampini   /* defaults to full precision */
7369566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(" %g", &socket->fmt));
73777eacf09SStefano Zampini 
7388135c375SStefano Zampini   viewer->data                = (void *)socket;
7398135c375SStefano Zampini   viewer->ops->destroy        = PetscViewerDestroy_GLVis;
7408135c375SStefano Zampini   viewer->ops->setfromoptions = PetscViewerSetFromOptions_GLVis;
7418135c375SStefano Zampini 
7429566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", PetscViewerGLVisSetPrecision_GLVis));
7439566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", PetscViewerGLVisSetSnapId_GLVis));
7449566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", PetscViewerGLVisSetFields_GLVis));
7459566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_GLVis));
7468135c375SStefano Zampini   PetscFunctionReturn(0);
7478135c375SStefano Zampini }
7488135c375SStefano Zampini 
7498135c375SStefano Zampini /* this is a private implementation of a SOCKET with ASCII data format
7508135c375SStefano Zampini    GLVis does not currently handle binary socket streams */
7518135c375SStefano Zampini #if defined(PETSC_HAVE_UNISTD_H)
7528135c375SStefano Zampini   #include <unistd.h>
7538135c375SStefano Zampini #endif
7548135c375SStefano Zampini 
7556524c165SJacob Faibussowitsch #ifndef PETSC_HAVE_WINDOWS_H
7568135c375SStefano Zampini static PetscErrorCode (*PetscViewerDestroy_ASCII)(PetscViewer);
7578135c375SStefano Zampini 
758d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII_Socket(PetscViewer viewer)
759d71ae5a4SJacob Faibussowitsch {
7608135c375SStefano Zampini   FILE *stream;
761d0609cedSBarry Smith 
7628135c375SStefano Zampini   PetscFunctionBegin;
7639566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetPointer(viewer, &stream));
7648135c375SStefano Zampini   if (stream) {
76540fde1d9SLisandro Dalcin     int retv = fclose(stream);
76640fde1d9SLisandro Dalcin     PetscCheck(!retv, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on stream");
7678135c375SStefano Zampini   }
7689566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy_ASCII(viewer));
7698135c375SStefano Zampini   PetscFunctionReturn(0);
7708135c375SStefano Zampini }
77127e89126SStefano Zampini #endif
77211a4995dSStefano Zampini 
7732da53a5bSBarry Smith /*
7742da53a5bSBarry Smith     This attempts to return a NULL viewer if it is unable to open a socket connection.
7752da53a5bSBarry Smith 
7762da53a5bSBarry Smith      The code below involving PetscUnlikely(ierr) is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
7772da53a5bSBarry Smith 
7782da53a5bSBarry Smith      The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain failure conditions but instead either return a special value
7792da53a5bSBarry 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.
7802da53a5bSBarry Smith */
781d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm comm, const char *hostname, PetscInt port, PetscViewer *viewer)
782d71ae5a4SJacob Faibussowitsch {
783150de0cbSStefano Zampini #if defined(PETSC_HAVE_WINDOWS_H)
78427e89126SStefano Zampini   PetscFunctionBegin;
78527e89126SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Not implemented for Windows");
78627e89126SStefano Zampini #else
7878135c375SStefano Zampini   FILE          *stream = NULL;
788178bdba8SJose E. Roman   int            fd     = 0;
7898135c375SStefano Zampini   PetscErrorCode ierr;
7908135c375SStefano Zampini 
7918135c375SStefano Zampini   PetscFunctionBegin;
792dadcf809SJacob Faibussowitsch   PetscValidCharPointer(hostname, 2);
7938135c375SStefano Zampini   PetscValidPointer(viewer, 4);
794c891a504SStefano Zampini   #if defined(PETSC_USE_SOCKET_VIEWER)
7958135c375SStefano Zampini   ierr = PetscOpenSocket(hostname, port, &fd);
796c891a504SStefano Zampini   #else
797c891a504SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Missing Socket viewer");
798c891a504SStefano Zampini   #endif
7992da53a5bSBarry Smith   /*
8002da53a5bSBarry Smith      The following code is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
8012da53a5bSBarry Smith         The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain conditions but instead either return a special value
8022da53a5bSBarry 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.
8032da53a5bSBarry Smith    */
8043ca90d2dSJacob Faibussowitsch   if (PetscUnlikely(ierr)) {
8058135c375SStefano Zampini     char err[1024];
8068135c375SStefano Zampini 
8079566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(err, 1024, "Cannot connect to socket on %s:%" PetscInt_FMT ". Socket visualization is disabled\n", hostname, port));
8089566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "%s", err));
8098135c375SStefano Zampini     *viewer = NULL;
8102da53a5bSBarry Smith     PetscFunctionReturn(0);
8118135c375SStefano Zampini   } else {
8128135c375SStefano Zampini     char msg[1024];
8138135c375SStefano Zampini 
8149566063dSJacob Faibussowitsch     PetscCall(PetscSNPrintf(msg, 1024, "Successfully connect to socket on %s:%" PetscInt_FMT ". Socket visualization is enabled\n", hostname, port));
8159566063dSJacob Faibussowitsch     PetscCall(PetscInfo(NULL, "%s", msg));
8168135c375SStefano Zampini   }
8178135c375SStefano Zampini   stream = fdopen(fd, "w"); /* Not possible on Windows */
81828b400f6SJacob Faibussowitsch   PetscCheck(stream, PETSC_COMM_SELF, PETSC_ERR_SYS, "Cannot open stream from socket %s:%" PetscInt_FMT, hostname, port);
8199566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIOpenWithFILE(PETSC_COMM_SELF, stream, viewer));
8208135c375SStefano Zampini   PetscViewerDestroy_ASCII = (*viewer)->ops->destroy;
8218135c375SStefano Zampini   (*viewer)->ops->destroy  = PetscViewerDestroy_ASCII_Socket;
82227e89126SStefano Zampini #endif
8238135c375SStefano Zampini   PetscFunctionReturn(0);
8248135c375SStefano Zampini }
8250286d493SLisandro Dalcin 
8260286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIGPIPE)
8270286d493SLisandro Dalcin 
8280286d493SLisandro Dalcin   #include <signal.h>
8290286d493SLisandro Dalcin 
8300286d493SLisandro Dalcin   #if defined(PETSC_HAVE_WINDOWS_H)
8310286d493SLisandro Dalcin     #define PETSC_DEVNULL "NUL"
8320286d493SLisandro Dalcin   #else
8330286d493SLisandro Dalcin     #define PETSC_DEVNULL "/dev/null"
8340286d493SLisandro Dalcin   #endif
8350286d493SLisandro Dalcin 
8360286d493SLisandro Dalcin static volatile PetscBool PetscGLVisBrokenPipe = PETSC_FALSE;
8370286d493SLisandro Dalcin 
8380286d493SLisandro Dalcin static void (*PetscGLVisSigHandler_save)(int) = NULL;
8390286d493SLisandro Dalcin 
840d71ae5a4SJacob Faibussowitsch static void PetscGLVisSigHandler_SIGPIPE(PETSC_UNUSED int sig)
841d71ae5a4SJacob Faibussowitsch {
8420286d493SLisandro Dalcin   PetscGLVisBrokenPipe = PETSC_TRUE;
8430286d493SLisandro Dalcin   #if !defined(PETSC_MISSING_SIG_IGN)
8440286d493SLisandro Dalcin   signal(SIGPIPE, SIG_IGN);
8450286d493SLisandro Dalcin   #endif
8460286d493SLisandro Dalcin }
8470286d493SLisandro Dalcin 
848d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
849d71ae5a4SJacob Faibussowitsch {
8500286d493SLisandro Dalcin   PetscFunctionBegin;
85128b400f6SJacob Faibussowitsch   PetscCheck(!PetscGLVisSigHandler_save, comm, PETSC_ERR_PLIB, "Nested call to %s()", PETSC_FUNCTION_NAME);
8520286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8530286d493SLisandro Dalcin   PetscGLVisSigHandler_save = signal(SIGPIPE, PetscGLVisSigHandler_SIGPIPE);
8540286d493SLisandro Dalcin   PetscFunctionReturn(0);
8550286d493SLisandro Dalcin }
8560286d493SLisandro Dalcin 
857d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(MPI_Comm comm, PetscViewer *win)
858d71ae5a4SJacob Faibussowitsch {
8590286d493SLisandro Dalcin   PetscBool flag, brokenpipe;
8600286d493SLisandro Dalcin 
8610286d493SLisandro Dalcin   PetscFunctionBegin;
8620286d493SLisandro Dalcin   flag = PetscGLVisBrokenPipe;
8631c2dc1cbSBarry Smith   PetscCall(MPIU_Allreduce(&flag, &brokenpipe, 1, MPIU_BOOL, MPI_LOR, comm));
8640286d493SLisandro Dalcin   if (brokenpipe) {
8650286d493SLisandro Dalcin     FILE *sock, *null = fopen(PETSC_DEVNULL, "w");
8669566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIGetPointer(*win, &sock));
8679566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISetFILE(*win, null));
8689566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(win));
8690286d493SLisandro Dalcin     if (sock) (void)fclose(sock);
8700286d493SLisandro Dalcin   }
8710286d493SLisandro Dalcin   (void)signal(SIGPIPE, PetscGLVisSigHandler_save);
8720286d493SLisandro Dalcin   PetscGLVisSigHandler_save = NULL;
8730286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8740286d493SLisandro Dalcin   PetscFunctionReturn(0);
8750286d493SLisandro Dalcin }
8760286d493SLisandro Dalcin 
8770286d493SLisandro Dalcin #else
8780286d493SLisandro Dalcin 
879d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
880d71ae5a4SJacob Faibussowitsch {
8810286d493SLisandro Dalcin   PetscFunctionBegin;
8820286d493SLisandro Dalcin   PetscFunctionReturn(0);
8830286d493SLisandro Dalcin }
8840286d493SLisandro Dalcin 
885d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
886d71ae5a4SJacob Faibussowitsch {
8870286d493SLisandro Dalcin   PetscFunctionBegin;
8880286d493SLisandro Dalcin   PetscFunctionReturn(0);
8890286d493SLisandro Dalcin }
8900286d493SLisandro Dalcin 
8910286d493SLisandro Dalcin #endif
892