xref: /petsc/src/sys/classes/viewer/impls/glvis/glvis.c (revision 49abdd8a111d9c2ef7fc48ade253ef64e07f9b37)
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 
44d1f92df0SBarry Smith .seealso: [](sec_viewers), `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));
513ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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   }
663ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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 
72c3339decSBarry 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 
80d1f92df0SBarry Smith .seealso: [](sec_viewers), `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));
883ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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;
973ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
988135c375SStefano Zampini }
998135c375SStefano Zampini 
1004cac2994SStefano Zampini /*@C
1014cac2994SStefano Zampini   PetscViewerGLVisSetFields - Sets the required information to visualize different fields from a vector.
1028135c375SStefano Zampini 
103c3339decSBarry 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)
110aec76313SJacob Faibussowitsch . g2l        - 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 
1153f423023SBarry Smith   Level: intermediate
1163f423023SBarry Smith 
11795452b02SPatrick Sanan   Notes:
1183f423023SBarry Smith   `g2lfields` is called on the vector V to be visualized in order to extract the relevant dofs to be put in `Vfield`, as
1198135c375SStefano Zampini .vb
1204cac2994SStefano Zampini   g2lfields((PetscObject)V,nfields,(PetscObject*)Vfield[],ctx).
1218135c375SStefano Zampini .ve
122811af0c4SBarry Smith 
1233f423023SBarry Smith   For vector spaces, the block size of `Vfield`[i] represents the vector dimension.
1243f423023SBarry Smith   The names of the `Vfield` vectors will be displayed in the window title.
1258135c375SStefano Zampini 
126d1f92df0SBarry Smith .seealso: [](sec_viewers), `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");
1344f572ea9SToby Isaac   PetscAssertPointer(fec_type, 3);
1354f572ea9SToby Isaac   PetscAssertPointer(dim, 4);
1364f572ea9SToby Isaac   PetscAssertPointer(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));
1383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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;
1693ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
1708135c375SStefano Zampini }
1718135c375SStefano Zampini 
172*49abdd8aSBarry Smith static PetscErrorCode PetscViewerGLVisInfoDestroy_Private(void **ptr)
173d71ae5a4SJacob Faibussowitsch {
174*49abdd8aSBarry Smith   PetscViewerGLVisInfo info = (PetscViewerGLVisInfo)*ptr;
1758135c375SStefano Zampini 
176c0bc9656SStefano Zampini   PetscFunctionBegin;
1779566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
1789566063dSJacob Faibussowitsch   PetscCall(PetscFree(info));
1793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
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;
19803e76207SPierre Jolivet     PetscCall(PetscObjectContainerCompose((PetscObject)window, "_glvis_info_container", info, PetscViewerGLVisInfoDestroy_Private));
19977eacf09SStefano Zampini   } else {
2009566063dSJacob Faibussowitsch     PetscCall(PetscContainerGetPointer(container, (void **)&info));
20177eacf09SStefano Zampini   }
2029566063dSJacob Faibussowitsch   PetscCall(PetscFree(info->fmt));
2039566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(socket->fmt, &info->fmt));
2043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2058135c375SStefano Zampini }
2068135c375SStefano Zampini 
207d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisGetNewWindow_Private(PetscViewer viewer, PetscViewer *view)
208d71ae5a4SJacob Faibussowitsch {
2098135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2108135c375SStefano Zampini   PetscViewer      window = NULL;
2118135c375SStefano Zampini   PetscBool        ldis, dis;
2128135c375SStefano Zampini 
2138135c375SStefano Zampini   PetscFunctionBegin;
2142da53a5bSBarry Smith   PetscCall(PetscViewerASCIISocketOpen(PETSC_COMM_SELF, socket->name, socket->port, &window));
215da81f932SPierre Jolivet   /* if we could not establish a connection, we disable the socket viewer on all MPI ranks */
2162da53a5bSBarry Smith   ldis = !viewer ? PETSC_TRUE : PETSC_FALSE;
217462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&ldis, &dis, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)viewer)));
2188135c375SStefano Zampini   if (dis) {
2198135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISABLED;
2209566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&window));
2218135c375SStefano Zampini   }
2228135c375SStefano Zampini   *view = window;
2233ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2248135c375SStefano Zampini }
2258135c375SStefano Zampini 
22634e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisPause_Internal(PetscViewer viewer)
227d71ae5a4SJacob Faibussowitsch {
2288135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2298135c375SStefano Zampini 
2308135c375SStefano Zampini   PetscFunctionBegin;
23148a46eb9SPierre Jolivet   if (socket->type == PETSC_VIEWER_GLVIS_SOCKET && socket->pause > 0) PetscCall(PetscSleep(socket->pause));
2323ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2338135c375SStefano Zampini }
2348135c375SStefano Zampini 
2358135c375SStefano Zampini /* DM specific support */
23634e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisSetDM_Internal(PetscViewer viewer, PetscObject dm)
237d71ae5a4SJacob Faibussowitsch {
2388135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2398135c375SStefano Zampini 
2408135c375SStefano Zampini   PetscFunctionBegin;
241cc73adaaSBarry Smith   PetscCheck(!socket->dm || socket->dm == dm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot change DM associated with the GLVis viewer");
2428135c375SStefano Zampini   if (!socket->dm) {
2438135c375SStefano Zampini     PetscErrorCode (*setupwithdm)(PetscObject, PetscViewer) = NULL;
2448135c375SStefano Zampini 
2459566063dSJacob Faibussowitsch     PetscCall(PetscObjectQueryFunction(dm, "DMSetUpGLVisViewer_C", &setupwithdm));
2468135c375SStefano Zampini     if (setupwithdm) {
2479566063dSJacob Faibussowitsch       PetscCall((*setupwithdm)(dm, viewer));
24898921bdaSJacob Faibussowitsch     } else SETERRQ(PetscObjectComm(dm), PETSC_ERR_SUP, "No support for DM type %s", dm->type_name);
2499566063dSJacob Faibussowitsch     PetscCall(PetscObjectReference(dm));
2508135c375SStefano Zampini     socket->dm = dm;
2518135c375SStefano Zampini   }
2523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2538135c375SStefano Zampini }
2548135c375SStefano Zampini 
25534e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDMWindow_Internal(PetscViewer viewer, PetscViewer *view)
256d71ae5a4SJacob Faibussowitsch {
2578135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2588135c375SStefano Zampini 
2598135c375SStefano Zampini   PetscFunctionBegin;
2604f572ea9SToby Isaac   PetscAssertPointer(view, 2);
2618135c375SStefano Zampini   if (!socket->meshwindow) {
2628135c375SStefano Zampini     if (socket->type == PETSC_VIEWER_GLVIS_SOCKET) {
2639566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->meshwindow));
2648135c375SStefano Zampini     } else {
26504b79de6SStefano Zampini       size_t    len;
26604b79de6SStefano Zampini       PetscBool isstdout;
26704b79de6SStefano Zampini 
2689566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
2699566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
27004b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
2719566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->meshwindow));
27204b79de6SStefano Zampini       } else {
2738135c375SStefano Zampini         PetscMPIInt rank;
2748135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
2759566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
2769566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-mesh.%06d", socket->name, rank));
2779566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->meshwindow));
2788135c375SStefano Zampini       }
27904b79de6SStefano Zampini     }
2801baa6e33SBarry Smith     if (socket->meshwindow) PetscCall(PetscViewerPushFormat(socket->meshwindow, PETSC_VIEWER_ASCII_GLVIS));
2818135c375SStefano Zampini   }
2821baa6e33SBarry Smith   if (socket->meshwindow) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, socket->meshwindow));
2838135c375SStefano Zampini   *view = socket->meshwindow;
2843ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
2858135c375SStefano Zampini }
2868135c375SStefano Zampini 
28734e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreDMWindow_Internal(PetscViewer viewer, PetscViewer *view)
288d71ae5a4SJacob Faibussowitsch {
2890286d493SLisandro Dalcin   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2900286d493SLisandro Dalcin 
2910286d493SLisandro Dalcin   PetscFunctionBegin;
2924f572ea9SToby Isaac   PetscAssertPointer(view, 2);
293cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->meshwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetDMWindow()");
2940286d493SLisandro Dalcin   if (*view) {
2959566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
2969566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
2970286d493SLisandro Dalcin   }
2980286d493SLisandro Dalcin   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
2999566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->meshwindow));
3000286d493SLisandro Dalcin   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
3010286d493SLisandro Dalcin     socket->meshwindow = NULL;
3020286d493SLisandro Dalcin   }
3030286d493SLisandro Dalcin   *view = NULL;
3043ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3050286d493SLisandro Dalcin }
3060286d493SLisandro Dalcin 
30734e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetType_Internal(PetscViewer viewer, PetscViewerGLVisType *type)
308d71ae5a4SJacob Faibussowitsch {
3098135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3108135c375SStefano Zampini 
3118135c375SStefano Zampini   PetscFunctionBegin;
3124f572ea9SToby Isaac   PetscAssertPointer(type, 2);
3138135c375SStefano Zampini   *type = socket->type;
3143ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3158135c375SStefano Zampini }
3168135c375SStefano Zampini 
3178135c375SStefano 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 */
31834e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetStatus_Internal(PetscViewer viewer, PetscViewerGLVisStatus *sockstatus)
319d71ae5a4SJacob Faibussowitsch {
3208135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3218135c375SStefano Zampini 
3228135c375SStefano Zampini   PetscFunctionBegin;
3234f572ea9SToby Isaac   PetscAssertPointer(sockstatus, 2);
3248135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
3258135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISCONNECTED;
3268135c375SStefano Zampini   } else if (socket->status == PETSCVIEWERGLVIS_DISCONNECTED && socket->nwindow) {
3278135c375SStefano Zampini     PetscInt  i;
3288135c375SStefano Zampini     PetscBool lconn, conn;
3298135c375SStefano Zampini 
3308135c375SStefano Zampini     for (i = 0, lconn = PETSC_TRUE; i < socket->nwindow; i++)
3319371c9d4SSatish Balay       if (!socket->window[i]) lconn = PETSC_FALSE;
3328135c375SStefano Zampini 
333462c564dSBarry Smith     PetscCallMPI(MPIU_Allreduce(&lconn, &conn, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)viewer)));
3348135c375SStefano Zampini     if (conn) socket->status = PETSCVIEWERGLVIS_CONNECTED;
3358135c375SStefano Zampini   }
3368135c375SStefano Zampini   *sockstatus = socket->status;
3373ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3388135c375SStefano Zampini }
3398135c375SStefano Zampini 
34034e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDM_Internal(PetscViewer viewer, PetscObject *dm)
341d71ae5a4SJacob Faibussowitsch {
3428135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3438135c375SStefano Zampini 
3448135c375SStefano Zampini   PetscFunctionBegin;
3458135c375SStefano Zampini   *dm = socket->dm;
3463ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3478135c375SStefano Zampini }
3488135c375SStefano Zampini 
34934e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetFields_Internal(PetscViewer viewer, PetscInt *nfield, const char **fec[], PetscInt *spacedim[], PetscErrorCode (**g2lfield)(PetscObject, PetscInt, PetscObject[], void *), PetscObject *Ufield[], void **userctx)
350d71ae5a4SJacob Faibussowitsch {
3518135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3528135c375SStefano Zampini 
3538135c375SStefano Zampini   PetscFunctionBegin;
3548135c375SStefano Zampini   if (nfield) *nfield = socket->nwindow;
3558135c375SStefano Zampini   if (fec) *fec = (const char **)socket->fec_type;
3564cac2994SStefano Zampini   if (spacedim) *spacedim = socket->spacedim;
3578135c375SStefano Zampini   if (g2lfield) *g2lfield = socket->g2lfield;
3588135c375SStefano Zampini   if (Ufield) *Ufield = socket->Ufield;
3598135c375SStefano Zampini   if (userctx) *userctx = socket->userctx;
3603ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
3618135c375SStefano Zampini }
3628135c375SStefano Zampini 
3638135c375SStefano Zampini /* accessor routines for the viewer windows:
3648135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP   : it returns a new viewer every time
3658135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET : it returns the socket, and creates it if not yet done.
3668135c375SStefano Zampini */
36734e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetWindow_Internal(PetscViewer viewer, PetscInt wid, PetscViewer *view)
368d71ae5a4SJacob Faibussowitsch {
3698135c375SStefano Zampini   PetscViewerGLVis       socket = (PetscViewerGLVis)viewer->data;
3708135c375SStefano Zampini   PetscViewerGLVisStatus status;
3718135c375SStefano Zampini 
3728135c375SStefano Zampini   PetscFunctionBegin;
3738135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
3744f572ea9SToby Isaac   PetscAssertPointer(view, 3);
3752c71b3e2SJacob 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);
3768135c375SStefano Zampini   status = socket->status;
3772c71b3e2SJacob 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);
3788135c375SStefano Zampini   switch (status) {
3798135c375SStefano Zampini   case PETSCVIEWERGLVIS_DISCONNECTED:
3802c71b3e2SJacob Faibussowitsch     PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "This should not happen");
381f7d195e4SLawrence Mitchell     if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
38204b79de6SStefano Zampini       size_t    len;
38304b79de6SStefano Zampini       PetscBool isstdout;
38404b79de6SStefano Zampini 
3859566063dSJacob Faibussowitsch       PetscCall(PetscStrlen(socket->name, &len));
3869566063dSJacob Faibussowitsch       PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout));
38704b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
3889566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->window[wid]));
38904b79de6SStefano Zampini       } else {
3908135c375SStefano Zampini         PetscMPIInt rank;
3918135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
3928135c375SStefano Zampini 
3939566063dSJacob Faibussowitsch         PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
3949566063dSJacob Faibussowitsch         PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-%s-%" PetscInt_FMT ".%06d", socket->name, socket->windowtitle[wid], socket->snapid, rank));
3959566063dSJacob Faibussowitsch         PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->window[wid]));
39604b79de6SStefano Zampini       }
3978135c375SStefano Zampini     } else {
3989566063dSJacob Faibussowitsch       PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->window[wid]));
3998135c375SStefano Zampini     }
40048a46eb9SPierre Jolivet     if (socket->window[wid]) PetscCall(PetscViewerPushFormat(socket->window[wid], PETSC_VIEWER_ASCII_GLVIS));
4018135c375SStefano Zampini     *view = socket->window[wid];
4028135c375SStefano Zampini     break;
403d71ae5a4SJacob Faibussowitsch   case PETSCVIEWERGLVIS_CONNECTED:
404d71ae5a4SJacob Faibussowitsch     *view = socket->window[wid];
405d71ae5a4SJacob Faibussowitsch     break;
406d71ae5a4SJacob Faibussowitsch   case PETSCVIEWERGLVIS_DISABLED:
407d71ae5a4SJacob Faibussowitsch     *view = NULL;
408d71ae5a4SJacob Faibussowitsch     break;
409d71ae5a4SJacob Faibussowitsch   default:
410d71ae5a4SJacob Faibussowitsch     SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unhandled socket status %d", (int)status);
4118135c375SStefano Zampini   }
4121baa6e33SBarry Smith   if (*view) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, *view));
4133ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4148135c375SStefano Zampini }
4158135c375SStefano Zampini 
4168135c375SStefano Zampini /* Restore the window viewer
4178135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP  : destroys the temporary created ASCII viewer used for dumping
4188135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET: - if the returned window viewer is not NULL, just zeros the pointer.
4198135c375SStefano Zampini                  - it the returned window viewer is NULL, assumes something went wrong
4208135c375SStefano Zampini                    with the socket (i.e. SIGPIPE when a user closes the popup window)
4218135c375SStefano Zampini                    and that the caller already handled it (see VecView_GLVis).
4228135c375SStefano Zampini */
42334e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreWindow_Internal(PetscViewer viewer, PetscInt wid, PetscViewer *view)
424d71ae5a4SJacob Faibussowitsch {
4258135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
4268135c375SStefano Zampini 
4278135c375SStefano Zampini   PetscFunctionBegin;
42863bd7f81SStefano Zampini   PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERGLVIS);
4298135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer, wid, 2);
4304f572ea9SToby Isaac   PetscAssertPointer(view, 3);
431cc73adaaSBarry 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);
432cc73adaaSBarry Smith   PetscCheck(!*view || *view == socket->window[wid], PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetWindow()");
4338135c375SStefano Zampini   if (*view) {
4349566063dSJacob Faibussowitsch     PetscCall(PetscViewerFlush(*view));
4359566063dSJacob Faibussowitsch     PetscCall(PetscBarrier((PetscObject)viewer));
4368135c375SStefano Zampini   }
4378135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
4389566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[wid]));
4398135c375SStefano Zampini   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
4408135c375SStefano Zampini     socket->window[wid] = NULL;
4418135c375SStefano Zampini   }
4428135c375SStefano Zampini   *view = NULL;
4433ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
4448135c375SStefano Zampini }
4458135c375SStefano Zampini 
4468135c375SStefano Zampini /* default window appearance in the PETSC_VIEWER_GLVIS_SOCKET case */
44734e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisInitWindow_Internal(PetscViewer viewer, PetscBool mesh, PetscInt dim, const char *name)
448d71ae5a4SJacob Faibussowitsch {
4498135c375SStefano Zampini   PetscViewerGLVisInfo info;
4508135c375SStefano Zampini   PetscContainer       container;
4518135c375SStefano Zampini 
4528135c375SStefano Zampini   PetscFunctionBegin;
4539566063dSJacob Faibussowitsch   PetscCall(PetscObjectQuery((PetscObject)viewer, "_glvis_info_container", (PetscObject *)&container));
45428b400f6SJacob Faibussowitsch   PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_USER, "Viewer was not obtained from PetscGLVisViewerGetNewWindow_Private");
4559566063dSJacob Faibussowitsch   PetscCall(PetscContainerGetPointer(container, (void **)&info));
4563ba16761SJacob Faibussowitsch   if (info->init) PetscFunctionReturn(PETSC_SUCCESS);
457fe28a402SLisandro Dalcin 
458fe28a402SLisandro Dalcin   /* Configure window */
45948a46eb9SPierre Jolivet   if (info->size[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "window_size %" PetscInt_FMT " %" PetscInt_FMT "\n", info->size[0], info->size[1]));
46048a46eb9SPierre Jolivet   if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "window_title '%s'\n", name));
461fe28a402SLisandro Dalcin 
462fe28a402SLisandro Dalcin   /* Configure default view */
4638135c375SStefano Zampini   if (mesh) {
4648135c375SStefano Zampini     switch (dim) {
4658135c375SStefano Zampini     case 1:
4669566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4678135c375SStefano Zampini       break;
4688135c375SStefano Zampini     case 2:
4699566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */
4708135c375SStefano Zampini       break;
471d71ae5a4SJacob Faibussowitsch     case 3: /* TODO: decide default view in 3D */
472d71ae5a4SJacob Faibussowitsch       break;
4738135c375SStefano Zampini     }
4748135c375SStefano Zampini   } else {
4759566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "keys cm\n")); /* show colorbar and mesh */
4768135c375SStefano Zampini     switch (dim) {
4778135c375SStefano Zampini     case 1:
4789566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys RRjl\n")); /* set to 1D (side view), turn off perspective and light */
4798135c375SStefano Zampini       break;
4808135c375SStefano Zampini     case 2:
4819566063dSJacob Faibussowitsch       PetscCall(PetscViewerASCIIPrintf(viewer, "keys Rjl\n")); /* set to 2D (top view), turn off perspective and light */
4828135c375SStefano Zampini       break;
483d71ae5a4SJacob Faibussowitsch     case 3:
484d71ae5a4SJacob Faibussowitsch       break;
4858135c375SStefano Zampini     }
4869566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIPrintf(viewer, "autoscale value\n")); /* update value-range; keep mesh-extents fixed */
48773365f8bSLisandro Dalcin   }
488fe28a402SLisandro Dalcin 
489fe28a402SLisandro Dalcin   { /* Additional keys and commands */
490fe28a402SLisandro Dalcin     char         keys[256] = "", cmds[2 * PETSC_MAX_PATH_LEN] = "";
491fe28a402SLisandro Dalcin     PetscOptions opt = ((PetscObject)viewer)->options;
492fe28a402SLisandro Dalcin     const char  *pre = ((PetscObject)viewer)->prefix;
493fe28a402SLisandro Dalcin 
4949566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_keys", keys, sizeof(keys), NULL));
4959566063dSJacob Faibussowitsch     PetscCall(PetscOptionsGetString(opt, pre, "-glvis_exec", cmds, sizeof(cmds), NULL));
4969566063dSJacob Faibussowitsch     if (keys[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "keys %s\n", keys));
4979566063dSJacob Faibussowitsch     if (cmds[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", cmds));
4988135c375SStefano Zampini   }
499fe28a402SLisandro Dalcin 
500fe28a402SLisandro Dalcin   /* Pause visualization */
50148a46eb9SPierre Jolivet   if (!mesh && info->pause == -1) PetscCall(PetscViewerASCIIPrintf(viewer, "autopause 1\n"));
50248a46eb9SPierre Jolivet   if (!mesh && info->pause == 0) PetscCall(PetscViewerASCIIPrintf(viewer, "pause\n"));
503fe28a402SLisandro Dalcin 
5048135c375SStefano Zampini   info->init = PETSC_TRUE;
5053ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5068135c375SStefano Zampini }
5078135c375SStefano Zampini 
508d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_GLVis(PetscViewer viewer)
509d71ae5a4SJacob Faibussowitsch {
5108135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5118135c375SStefano Zampini   PetscInt         i;
5128135c375SStefano Zampini 
5138135c375SStefano Zampini   PetscFunctionBegin;
5148135c375SStefano Zampini   for (i = 0; i < socket->nwindow; i++) {
5159566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(&socket->window[i]));
5169566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->windowtitle[i]));
5179566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->fec_type[i]));
5189566063dSJacob Faibussowitsch     PetscCall(PetscObjectDestroy(&socket->Ufield[i]));
5198135c375SStefano Zampini   }
5209566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
5219566063dSJacob Faibussowitsch   PetscCall(PetscFree5(socket->window, socket->windowtitle, socket->fec_type, socket->spacedim, socket->Ufield));
5229566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->fmt));
5239566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy(&socket->meshwindow));
5249566063dSJacob Faibussowitsch   PetscCall(PetscObjectDestroy(&socket->dm));
5259566063dSJacob Faibussowitsch   if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx));
5268135c375SStefano Zampini 
5279566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", NULL));
5289566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", NULL));
5299566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", NULL));
5309566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
5319566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket));
5328135c375SStefano Zampini   viewer->data = NULL;
5333ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5348135c375SStefano Zampini }
5358135c375SStefano Zampini 
536d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetFromOptions_GLVis(PetscViewer v, PetscOptionItems *PetscOptionsObject)
537d71ae5a4SJacob Faibussowitsch {
5388135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)v->data;
53973365f8bSLisandro Dalcin   PetscInt         nsizes = 2, prec = PETSC_DECIDE;
54073365f8bSLisandro Dalcin   PetscBool        set;
5418135c375SStefano Zampini 
5428135c375SStefano Zampini   PetscFunctionBegin;
543d0609cedSBarry Smith   PetscOptionsHeadBegin(PetscOptionsObject, "GLVis PetscViewer Options");
5449566063dSJacob Faibussowitsch   PetscCall(PetscOptionsInt("-glvis_precision", "Number of digits for floating point values", "PetscViewerGLVisSetPrecision", prec, &prec, &set));
5459566063dSJacob Faibussowitsch   if (set) PetscCall(PetscViewerGLVisSetPrecision(v, prec));
5469566063dSJacob Faibussowitsch   PetscCall(PetscOptionsIntArray("-glvis_size", "Window sizes", NULL, socket->windowsizes, &nsizes, &set));
54773365f8bSLisandro Dalcin   if (set && (nsizes == 1 || socket->windowsizes[1] < 0)) socket->windowsizes[1] = socket->windowsizes[0];
5489566063dSJacob Faibussowitsch   PetscCall(PetscOptionsReal("-glvis_pause", "-1 to pause after each visualization, otherwise sleeps for given seconds", NULL, socket->pause, &socket->pause, NULL));
549bcee047aSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_keys", "Additional keys to configure visualization", NULL, &set));
550bcee047aSJacob Faibussowitsch   PetscCall(PetscOptionsName("-glvis_exec", "Additional commands to configure visualization", NULL, &set));
551d0609cedSBarry Smith   PetscOptionsHeadEnd();
5523ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5538135c375SStefano Zampini }
5548135c375SStefano Zampini 
555d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_GLVis(PetscViewer viewer, const char name[])
556d71ae5a4SJacob Faibussowitsch {
557bbcf679cSJacob Faibussowitsch   char            *sport  = NULL;
5588135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5598135c375SStefano Zampini 
5608135c375SStefano Zampini   PetscFunctionBegin;
5618135c375SStefano Zampini   socket->type = PETSC_VIEWER_GLVIS_DUMP;
5628135c375SStefano Zampini   /* we accept localhost^port */
5639566063dSJacob Faibussowitsch   PetscCall(PetscFree(socket->name));
5649566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(name, &socket->name));
5659566063dSJacob Faibussowitsch   PetscCall(PetscStrchr(socket->name, '^', &sport));
5668135c375SStefano Zampini   if (sport) {
5678135c375SStefano Zampini     PetscInt       port = 19916;
5688135c375SStefano Zampini     size_t         len;
5695f80ce2aSJacob Faibussowitsch     PetscErrorCode ierr;
5708135c375SStefano Zampini 
5718135c375SStefano Zampini     *sport++ = 0;
5729566063dSJacob Faibussowitsch     PetscCall(PetscStrlen(sport, &len));
5735f80ce2aSJacob Faibussowitsch     ierr = PetscOptionsStringToInt(sport, &port);
5745f80ce2aSJacob Faibussowitsch     if (PetscUnlikely(ierr)) {
5758135c375SStefano Zampini       socket->port = 19916;
5765f80ce2aSJacob Faibussowitsch     } else {
5775f80ce2aSJacob Faibussowitsch       socket->port = (port != PETSC_DECIDE && port != PETSC_DEFAULT) ? port : 19916;
5788135c375SStefano Zampini     }
5798135c375SStefano Zampini     socket->type = PETSC_VIEWER_GLVIS_SOCKET;
5808135c375SStefano Zampini   }
5813ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
5828135c375SStefano Zampini }
5838135c375SStefano Zampini 
584cc4c1da9SBarry Smith /*@
585811af0c4SBarry Smith   PetscViewerGLVisOpen - Opens a `PETSCVIEWERGLVIS` `PetscViewer`
5868135c375SStefano Zampini 
587d1f92df0SBarry Smith   Collective; No Fortran Support
5888135c375SStefano Zampini 
5898135c375SStefano Zampini   Input Parameters:
5908135c375SStefano Zampini + comm - the MPI communicator
591811af0c4SBarry Smith . type - the viewer type: `PETSC_VIEWER_GLVIS_SOCKET` for real-time visualization or `PETSC_VIEWER_GLVIS_DUMP` for dumping to a file
5928135c375SStefano Zampini . name - either the hostname where the GLVis server is running or the base filename for dumping the data for subsequent visualizations
593811af0c4SBarry Smith - port - socket port where the GLVis server is listening. Not referenced when type is `PETSC_VIEWER_GLVIS_DUMP`
5948135c375SStefano Zampini 
5952fe279fdSBarry Smith   Output Parameter:
5962fe279fdSBarry Smith . viewer - the `PetscViewer` object
5978135c375SStefano Zampini 
59873365f8bSLisandro Dalcin   Options Database Keys:
599fe28a402SLisandro Dalcin + -glvis_precision <precision> - Sets number of digits for floating point values
600fe28a402SLisandro Dalcin . -glvis_size <width,height>   - Sets the window size (in pixels)
60173365f8bSLisandro Dalcin . -glvis_pause <pause>         - Sets time (in seconds) that the program pauses after each visualization
602fe28a402SLisandro Dalcin                                  (0 is default, -1 implies every visualization)
603fe28a402SLisandro Dalcin . -glvis_keys                  - Additional keys to configure visualization
604fe28a402SLisandro Dalcin - -glvis_exec                  - Additional commands to configure visualization
60573365f8bSLisandro Dalcin 
6068135c375SStefano Zampini   Level: beginner
6078135c375SStefano Zampini 
608d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERGLVIS`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerGLVisType`
60973365f8bSLisandro Dalcin @*/
610d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisOpen(MPI_Comm comm, PetscViewerGLVisType type, const char name[], PetscInt port, PetscViewer *viewer)
611d71ae5a4SJacob Faibussowitsch {
6128135c375SStefano Zampini   PetscViewerGLVis socket;
6138135c375SStefano Zampini 
6148135c375SStefano Zampini   PetscFunctionBegin;
6159566063dSJacob Faibussowitsch   PetscCall(PetscViewerCreate(comm, viewer));
6169566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERGLVIS));
6178135c375SStefano Zampini 
6188135c375SStefano Zampini   socket       = (PetscViewerGLVis)((*viewer)->data);
619a7bda6aaSStefano Zampini   socket->type = type;
620a7bda6aaSStefano Zampini   if (type == PETSC_VIEWER_GLVIS_DUMP || name) {
6219566063dSJacob Faibussowitsch     PetscCall(PetscFree(socket->name));
6229566063dSJacob Faibussowitsch     PetscCall(PetscStrallocpy(name, &socket->name));
623a7bda6aaSStefano Zampini   }
624a7bda6aaSStefano Zampini   socket->port = (!port || port == PETSC_DETERMINE || port == PETSC_DECIDE) ? 19916 : port;
6258135c375SStefano Zampini 
6269566063dSJacob Faibussowitsch   PetscCall(PetscViewerSetFromOptions(*viewer));
6273ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
6288135c375SStefano Zampini }
6298135c375SStefano Zampini 
630d1f92df0SBarry Smith /*@C
631811af0c4SBarry Smith   PETSC_VIEWER_GLVIS_ - Creates a `PETSCVIEWERGLVIS` `PetscViewer` shared by all processors in a communicator.
6328135c375SStefano Zampini 
633d1f92df0SBarry Smith   Collective; No Fortran Support
6348135c375SStefano Zampini 
6358135c375SStefano Zampini   Input Parameter:
636811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERGLVIS` `PetscViewer`
6378135c375SStefano Zampini 
6388135c375SStefano Zampini   Environmental variables:
639d1f92df0SBarry Smith + `PETSC_VIEWER_GLVIS_FILENAME` - output filename (if specified dump to disk, and takes precedence on `PETSC_VIEWER_GLVIS_HOSTNAME`)
640d1f92df0SBarry Smith . `PETSC_VIEWER_GLVIS_HOSTNAME` - machine where the GLVis server is listening (defaults to localhost)
641d1f92df0SBarry Smith - `PETSC_VIEWER_GLVIS_PORT`     - port opened by the GLVis server (defaults to 19916)
642d1f92df0SBarry Smith 
643d1f92df0SBarry Smith   Level: intermediate
6448135c375SStefano Zampini 
645811af0c4SBarry Smith   Note:
646811af0c4SBarry Smith   Unlike almost all other PETSc routines, `PETSC_VIEWER_GLVIS_()` does not return
647811af0c4SBarry Smith   an error code.  It is usually used in the form
648648c30bcSBarry Smith .vb
649648c30bcSBarry Smith        XXXView(XXX object, PETSC_VIEWER_GLVIS_(comm));
650648c30bcSBarry Smith .ve
651648c30bcSBarry Smith 
652648c30bcSBarry Smith   Developer Note:
653648c30bcSBarry Smith   How come this viewer is not stashed as an attribute in the MPI communicator?
6548135c375SStefano Zampini 
655d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERGLVIS`, `PetscViewer`, `PetscViewerGLVISOpen()`, `PetscViewerGLVisType`, `PetscViewerCreate()`, `PetscViewerDestroy()`
656d1f92df0SBarry Smith @*/
657d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_GLVIS_(MPI_Comm comm)
658d71ae5a4SJacob Faibussowitsch {
6598135c375SStefano Zampini   PetscBool            flg;
6608135c375SStefano Zampini   PetscViewer          viewer;
6618135c375SStefano Zampini   PetscViewerGLVisType type;
6628135c375SStefano Zampini   char                 fname[PETSC_MAX_PATH_LEN], sport[16];
6638135c375SStefano Zampini   PetscInt             port = 19916; /* default for GLVis */
6648135c375SStefano Zampini 
6658135c375SStefano Zampini   PetscFunctionBegin;
666648c30bcSBarry Smith   PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg));
6678135c375SStefano Zampini   if (!flg) {
6688135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_SOCKET;
669648c30bcSBarry Smith     PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_HOSTNAME", fname, PETSC_MAX_PATH_LEN, &flg));
670648c30bcSBarry Smith     if (!flg) { PetscCallNull(PetscStrncpy(fname, "localhost", sizeof(fname))); }
671648c30bcSBarry Smith     PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_PORT", sport, 16, &flg));
672648c30bcSBarry Smith     if (flg) { PetscCallNull(PetscOptionsStringToInt(sport, &port)); }
6738135c375SStefano Zampini   } else {
6748135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_DUMP;
6758135c375SStefano Zampini   }
676648c30bcSBarry Smith   PetscCallNull(PetscViewerGLVisOpen(comm, type, fname, port, &viewer));
677648c30bcSBarry Smith   PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
6788135c375SStefano Zampini   PetscFunctionReturn(viewer);
6798135c375SStefano Zampini }
6808135c375SStefano Zampini 
681d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_GLVis(PetscViewer viewer)
682d71ae5a4SJacob Faibussowitsch {
6838135c375SStefano Zampini   PetscViewerGLVis socket;
6848135c375SStefano Zampini 
6858135c375SStefano Zampini   PetscFunctionBegin;
6864dfa11a4SJacob Faibussowitsch   PetscCall(PetscNew(&socket));
6878135c375SStefano Zampini 
6888135c375SStefano Zampini   /* defaults to socket viewer */
6899566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy("localhost", &socket->name));
6908135c375SStefano Zampini   socket->port  = 19916; /* GLVis default listening port */
6918135c375SStefano Zampini   socket->type  = PETSC_VIEWER_GLVIS_SOCKET;
6928135c375SStefano Zampini   socket->pause = 0; /* just pause the first time */
6938135c375SStefano Zampini 
69473365f8bSLisandro Dalcin   socket->windowsizes[0] = 600;
69573365f8bSLisandro Dalcin   socket->windowsizes[1] = 600;
69673365f8bSLisandro Dalcin 
69777eacf09SStefano Zampini   /* defaults to full precision */
6989566063dSJacob Faibussowitsch   PetscCall(PetscStrallocpy(" %g", &socket->fmt));
69977eacf09SStefano Zampini 
7008135c375SStefano Zampini   viewer->data                = (void *)socket;
7018135c375SStefano Zampini   viewer->ops->destroy        = PetscViewerDestroy_GLVis;
7028135c375SStefano Zampini   viewer->ops->setfromoptions = PetscViewerSetFromOptions_GLVis;
7038135c375SStefano Zampini 
7049566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", PetscViewerGLVisSetPrecision_GLVis));
7059566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", PetscViewerGLVisSetSnapId_GLVis));
7069566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", PetscViewerGLVisSetFields_GLVis));
7079566063dSJacob Faibussowitsch   PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_GLVis));
7083ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7098135c375SStefano Zampini }
7108135c375SStefano Zampini 
7118135c375SStefano Zampini /* this is a private implementation of a SOCKET with ASCII data format
7128135c375SStefano Zampini    GLVis does not currently handle binary socket streams */
7138135c375SStefano Zampini #if defined(PETSC_HAVE_UNISTD_H)
7148135c375SStefano Zampini   #include <unistd.h>
7158135c375SStefano Zampini #endif
7168135c375SStefano Zampini 
7176524c165SJacob Faibussowitsch #ifndef PETSC_HAVE_WINDOWS_H
7188135c375SStefano Zampini static PetscErrorCode (*PetscViewerDestroy_ASCII)(PetscViewer);
7198135c375SStefano Zampini 
720d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII_Socket(PetscViewer viewer)
721d71ae5a4SJacob Faibussowitsch {
7228135c375SStefano Zampini   FILE *stream;
723d0609cedSBarry Smith 
7248135c375SStefano Zampini   PetscFunctionBegin;
7259566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIGetPointer(viewer, &stream));
7268135c375SStefano Zampini   if (stream) {
72740fde1d9SLisandro Dalcin     int retv = fclose(stream);
72840fde1d9SLisandro Dalcin     PetscCheck(!retv, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on stream");
7298135c375SStefano Zampini   }
7309566063dSJacob Faibussowitsch   PetscCall(PetscViewerDestroy_ASCII(viewer));
7313ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7328135c375SStefano Zampini }
73327e89126SStefano Zampini #endif
73411a4995dSStefano Zampini 
7352da53a5bSBarry Smith /*
7362da53a5bSBarry Smith     This attempts to return a NULL viewer if it is unable to open a socket connection.
7372da53a5bSBarry Smith 
7382da53a5bSBarry Smith      The code below involving PetscUnlikely(ierr) is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
7392da53a5bSBarry Smith 
7402da53a5bSBarry Smith      The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain failure conditions but instead either return a special value
7412da53a5bSBarry 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.
7422da53a5bSBarry Smith */
743d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm comm, const char *hostname, PetscInt port, PetscViewer *viewer)
744d71ae5a4SJacob Faibussowitsch {
745150de0cbSStefano Zampini #if defined(PETSC_HAVE_WINDOWS_H)
74627e89126SStefano Zampini   PetscFunctionBegin;
74727e89126SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Not implemented for Windows");
74827e89126SStefano Zampini #else
7498135c375SStefano Zampini   FILE          *stream = NULL;
750178bdba8SJose E. Roman   int            fd     = 0;
7518135c375SStefano Zampini   PetscErrorCode ierr;
7528135c375SStefano Zampini 
7538135c375SStefano Zampini   PetscFunctionBegin;
7544f572ea9SToby Isaac   PetscAssertPointer(hostname, 2);
7554f572ea9SToby Isaac   PetscAssertPointer(viewer, 4);
756c891a504SStefano Zampini   #if defined(PETSC_USE_SOCKET_VIEWER)
7576497c311SBarry Smith   ierr = PetscOpenSocket(hostname, (int)port, &fd);
758c891a504SStefano Zampini   #else
759c891a504SStefano Zampini   SETERRQ(comm, PETSC_ERR_SUP, "Missing Socket viewer");
760c891a504SStefano Zampini   #endif
7612da53a5bSBarry Smith   /*
7622da53a5bSBarry Smith      The following code is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc.
7632da53a5bSBarry Smith         The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain conditions but instead either return a special value
7642da53a5bSBarry 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.
7652da53a5bSBarry Smith    */
7663ca90d2dSJacob Faibussowitsch   if (PetscUnlikely(ierr)) {
7679d3446b2SPierre Jolivet     PetscCall(PetscInfo(NULL, "Cannot connect to socket on %s:%" PetscInt_FMT ". Socket visualization is disabled\n", hostname, port));
7688135c375SStefano Zampini     *viewer = NULL;
7693ba16761SJacob Faibussowitsch     PetscFunctionReturn(PETSC_SUCCESS);
7708135c375SStefano Zampini   } else {
7719d3446b2SPierre Jolivet     PetscCall(PetscInfo(NULL, "Successfully connect to socket on %s:%" PetscInt_FMT ". Socket visualization is enabled\n", hostname, port));
7728135c375SStefano Zampini   }
7738135c375SStefano Zampini   stream = fdopen(fd, "w"); /* Not possible on Windows */
77428b400f6SJacob Faibussowitsch   PetscCheck(stream, PETSC_COMM_SELF, PETSC_ERR_SYS, "Cannot open stream from socket %s:%" PetscInt_FMT, hostname, port);
7759566063dSJacob Faibussowitsch   PetscCall(PetscViewerASCIIOpenWithFILE(PETSC_COMM_SELF, stream, viewer));
7768135c375SStefano Zampini   PetscViewerDestroy_ASCII = (*viewer)->ops->destroy;
7778135c375SStefano Zampini   (*viewer)->ops->destroy  = PetscViewerDestroy_ASCII_Socket;
77827e89126SStefano Zampini #endif
7793ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
7808135c375SStefano Zampini }
7810286d493SLisandro Dalcin 
7820286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIGPIPE)
7830286d493SLisandro Dalcin 
7840286d493SLisandro Dalcin   #include <signal.h>
7850286d493SLisandro Dalcin 
7860286d493SLisandro Dalcin   #if defined(PETSC_HAVE_WINDOWS_H)
7870286d493SLisandro Dalcin     #define PETSC_DEVNULL "NUL"
7880286d493SLisandro Dalcin   #else
7890286d493SLisandro Dalcin     #define PETSC_DEVNULL "/dev/null"
7900286d493SLisandro Dalcin   #endif
7910286d493SLisandro Dalcin 
7920286d493SLisandro Dalcin static volatile PetscBool PetscGLVisBrokenPipe = PETSC_FALSE;
7930286d493SLisandro Dalcin 
7940286d493SLisandro Dalcin static void (*PetscGLVisSigHandler_save)(int) = NULL;
7950286d493SLisandro Dalcin 
796d71ae5a4SJacob Faibussowitsch static void PetscGLVisSigHandler_SIGPIPE(PETSC_UNUSED int sig)
797d71ae5a4SJacob Faibussowitsch {
7980286d493SLisandro Dalcin   PetscGLVisBrokenPipe = PETSC_TRUE;
7990286d493SLisandro Dalcin   #if !defined(PETSC_MISSING_SIG_IGN)
8000286d493SLisandro Dalcin   signal(SIGPIPE, SIG_IGN);
8010286d493SLisandro Dalcin   #endif
8020286d493SLisandro Dalcin }
8030286d493SLisandro Dalcin 
804d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
805d71ae5a4SJacob Faibussowitsch {
8060286d493SLisandro Dalcin   PetscFunctionBegin;
80728b400f6SJacob Faibussowitsch   PetscCheck(!PetscGLVisSigHandler_save, comm, PETSC_ERR_PLIB, "Nested call to %s()", PETSC_FUNCTION_NAME);
8080286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8090286d493SLisandro Dalcin   PetscGLVisSigHandler_save = signal(SIGPIPE, PetscGLVisSigHandler_SIGPIPE);
8103ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8110286d493SLisandro Dalcin }
8120286d493SLisandro Dalcin 
813d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(MPI_Comm comm, PetscViewer *win)
814d71ae5a4SJacob Faibussowitsch {
8150286d493SLisandro Dalcin   PetscBool flag, brokenpipe;
8160286d493SLisandro Dalcin 
8170286d493SLisandro Dalcin   PetscFunctionBegin;
8180286d493SLisandro Dalcin   flag = PetscGLVisBrokenPipe;
819462c564dSBarry Smith   PetscCallMPI(MPIU_Allreduce(&flag, &brokenpipe, 1, MPIU_BOOL, MPI_LOR, comm));
8200286d493SLisandro Dalcin   if (brokenpipe) {
8210286d493SLisandro Dalcin     FILE *sock, *null = fopen(PETSC_DEVNULL, "w");
8229566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIIGetPointer(*win, &sock));
8239566063dSJacob Faibussowitsch     PetscCall(PetscViewerASCIISetFILE(*win, null));
8249566063dSJacob Faibussowitsch     PetscCall(PetscViewerDestroy(win));
8250286d493SLisandro Dalcin     if (sock) (void)fclose(sock);
8260286d493SLisandro Dalcin   }
8270286d493SLisandro Dalcin   (void)signal(SIGPIPE, PetscGLVisSigHandler_save);
8280286d493SLisandro Dalcin   PetscGLVisSigHandler_save = NULL;
8290286d493SLisandro Dalcin   PetscGLVisBrokenPipe      = PETSC_FALSE;
8303ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8310286d493SLisandro Dalcin }
8320286d493SLisandro Dalcin 
8330286d493SLisandro Dalcin #else
8340286d493SLisandro Dalcin 
835d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
836d71ae5a4SJacob Faibussowitsch {
8370286d493SLisandro Dalcin   PetscFunctionBegin;
8383ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8390286d493SLisandro Dalcin }
8400286d493SLisandro Dalcin 
841d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win)
842d71ae5a4SJacob Faibussowitsch {
8430286d493SLisandro Dalcin   PetscFunctionBegin;
8443ba16761SJacob Faibussowitsch   PetscFunctionReturn(PETSC_SUCCESS);
8450286d493SLisandro Dalcin }
8460286d493SLisandro Dalcin 
8470286d493SLisandro Dalcin #endif
848