xref: /petsc/src/sys/classes/viewer/impls/glvis/glvis.c (revision a7bda6aa3ba235683bad061d22ca55702fa6889c)
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;
218135c375SStefano Zampini   char                   **fec_type;                                            /* type of elements to be used for visualization, see FiniteElementCollection::Name() */
228135c375SStefano Zampini   PetscErrorCode         (*g2lfield)(PetscObject,PetscInt,PetscObject[],void*); /* global to local operation for generating dofs to be visualized */
234cac2994SStefano Zampini   PetscInt               *spacedim;                                             /* geometrical space dimension (just used to initialize the scene) */
248135c375SStefano Zampini   PetscObject            *Ufield;                                               /* work vectors for visualization */
258135c375SStefano Zampini   PetscInt               snapid;                                                /* snapshot id, use PetscViewerGLVisSetSnapId to change this value*/
268135c375SStefano Zampini   void                   *userctx;                                              /* User context, used by g2lfield */
278135c375SStefano Zampini   PetscErrorCode         (*destroyctx)(void*);                                  /* destroy routine for userctx */
2877eacf09SStefano Zampini   char*                  fmt;                                                   /* format string for FP values */
298135c375SStefano Zampini };
308135c375SStefano Zampini typedef struct _n_PetscViewerGLVis *PetscViewerGLVis;
318135c375SStefano Zampini 
328135c375SStefano Zampini /*@
3377eacf09SStefano Zampini      PetscViewerGLVisSetPrecision - Set the number of digits for floating point values
3477eacf09SStefano Zampini 
3577eacf09SStefano Zampini   Not Collective
3677eacf09SStefano Zampini 
3777eacf09SStefano Zampini   Input Parameters:
3877eacf09SStefano Zampini +  viewer - the PetscViewer
3977eacf09SStefano Zampini -  prec   - the number of digits required
4077eacf09SStefano Zampini 
4177eacf09SStefano Zampini   Level: beginner
4277eacf09SStefano Zampini 
4377eacf09SStefano Zampini .seealso: PetscViewerGLVisOpen(), PetscViewerGLVisSetFields(), PetscViewerCreate(), PetscViewerSetType()
4477eacf09SStefano Zampini @*/
4577eacf09SStefano Zampini PetscErrorCode PetscViewerGLVisSetPrecision(PetscViewer viewer, PetscInt prec)
4677eacf09SStefano Zampini {
4777eacf09SStefano Zampini   PetscErrorCode ierr;
4877eacf09SStefano Zampini 
4977eacf09SStefano Zampini   PetscFunctionBegin;
5077eacf09SStefano Zampini   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
5177eacf09SStefano Zampini   ierr = PetscTryMethod(viewer,"PetscViewerGLVisSetPrecision_C",(PetscViewer,PetscInt),(viewer,prec));CHKERRQ(ierr);
5277eacf09SStefano Zampini   PetscFunctionReturn(0);
5377eacf09SStefano Zampini }
5477eacf09SStefano Zampini 
5577eacf09SStefano Zampini static PetscErrorCode PetscViewerGLVisSetPrecision_GLVis(PetscViewer viewer, PetscInt prec)
5677eacf09SStefano Zampini {
5777eacf09SStefano Zampini   PetscErrorCode   ierr;
5877eacf09SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5977eacf09SStefano Zampini 
6077eacf09SStefano Zampini   PetscFunctionBegin;
6177eacf09SStefano Zampini   ierr = PetscFree(socket->fmt);CHKERRQ(ierr);
6277eacf09SStefano Zampini   if (prec > 0) {
6377eacf09SStefano Zampini     ierr = PetscMalloc1(16,&socket->fmt);CHKERRQ(ierr);
6477eacf09SStefano Zampini     ierr = PetscSNPrintf(socket->fmt,16," %%.%De",prec);CHKERRQ(ierr);
6577eacf09SStefano Zampini   } else {
6677eacf09SStefano Zampini     ierr = PetscStrallocpy(" %g",&socket->fmt);CHKERRQ(ierr);
6777eacf09SStefano Zampini   }
6877eacf09SStefano Zampini   PetscFunctionReturn(0);
6977eacf09SStefano Zampini }
7077eacf09SStefano Zampini 
7177eacf09SStefano Zampini /*@
728135c375SStefano Zampini      PetscViewerGLVisSetSnapId - Set the snapshot id. Only relevant when the viewer is of type PETSC_VIEWER_GLVIS_DUMP
738135c375SStefano Zampini 
748135c375SStefano Zampini   Logically Collective on PetscViewer
758135c375SStefano Zampini 
768135c375SStefano Zampini   Input Parameters:
778135c375SStefano Zampini +  viewer - the PetscViewer
788135c375SStefano Zampini -  id     - the current snapshot id in a time-dependent simulation
798135c375SStefano Zampini 
808135c375SStefano Zampini   Level: beginner
818135c375SStefano Zampini 
8277eacf09SStefano Zampini .seealso: PetscViewerGLVisOpen(), PetscViewerGLVisSetFields(), PetscViewerCreate(), PetscViewerSetType()
838135c375SStefano Zampini @*/
848135c375SStefano Zampini PetscErrorCode PetscViewerGLVisSetSnapId(PetscViewer viewer, PetscInt id)
858135c375SStefano Zampini {
868135c375SStefano Zampini   PetscErrorCode ierr;
878135c375SStefano Zampini 
888135c375SStefano Zampini   PetscFunctionBegin;
898135c375SStefano Zampini   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
908135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer,id,2);
918135c375SStefano Zampini   ierr = PetscTryMethod(viewer,"PetscViewerGLVisSetSnapId_C",(PetscViewer,PetscInt),(viewer,id));CHKERRQ(ierr);
928135c375SStefano Zampini   PetscFunctionReturn(0);
938135c375SStefano Zampini }
948135c375SStefano Zampini 
958135c375SStefano Zampini static PetscErrorCode PetscViewerGLVisSetSnapId_GLVis(PetscViewer viewer, PetscInt id)
968135c375SStefano Zampini {
978135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
988135c375SStefano Zampini 
998135c375SStefano Zampini   PetscFunctionBegin;
10077eacf09SStefano Zampini   socket->snapid = id;
1018135c375SStefano Zampini   PetscFunctionReturn(0);
1028135c375SStefano Zampini }
1038135c375SStefano Zampini 
1044cac2994SStefano Zampini /*@C
1054cac2994SStefano Zampini      PetscViewerGLVisSetFields - Sets the required information to visualize different fields from a vector.
1068135c375SStefano Zampini 
1078135c375SStefano Zampini   Logically Collective on PetscViewer
1088135c375SStefano Zampini 
1098135c375SStefano Zampini   Input Parameters:
1108135c375SStefano Zampini +  viewer     - the PetscViewer
1118135c375SStefano Zampini .  nf         - number of fields to be visualized
1128135c375SStefano Zampini .  fec_type   - the type of finite element to be used to visualize the data (see FiniteElementCollection::Name() in MFEM)
1134cac2994SStefano Zampini .  dim        - array of space dimension for field vectors (used to initialize the scene)
1148135c375SStefano Zampini .  g2lfields  - User routine to compute the local field vectors to be visualized; PetscObject is used in place of Vec on the prototype
1154cac2994SStefano Zampini .  Vfield     - array of work vectors, one for each field
1168135c375SStefano Zampini .  ctx        - User context to store the relevant data to apply g2lfields
1178135c375SStefano Zampini -  destroyctx - Destroy function for userctx
1188135c375SStefano Zampini 
1194cac2994SStefano Zampini   Notes: g2lfields is called on the vector V to be visualized in order to extract the relevant dofs to be put in Vfield[], as
1208135c375SStefano Zampini .vb
1214cac2994SStefano Zampini   g2lfields((PetscObject)V,nfields,(PetscObject*)Vfield[],ctx).
1228135c375SStefano Zampini .ve
1234cac2994SStefano Zampini   For vector spaces, the block size of Vfield[i] represents the vector dimension. It misses the Fortran bindings.
1244cac2994SStefano Zampini   PETSc will take ownership of the work vectors.
1254cac2994SStefano Zampini   The names of the Vfield vectors will be displayed in the window title.
1268135c375SStefano Zampini 
1278135c375SStefano Zampini   Level: intermediate
1288135c375SStefano Zampini 
1294cac2994SStefano Zampini .seealso: PetscViewerGLVisOpen(), PetscViewerCreate(), PetscViewerSetType(), PetscObjectSetName()
1304cac2994SStefano Zampini @*/
1314cac2994SStefano Zampini 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*))
1328135c375SStefano Zampini {
1338135c375SStefano Zampini   PetscErrorCode ierr;
1348135c375SStefano Zampini 
1358135c375SStefano Zampini   PetscFunctionBegin;
1368135c375SStefano Zampini   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
1378135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer,nf,2);
1388135c375SStefano Zampini   if (!fec_type) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"You need to provide the FiniteElementCollection names for the fields");
1394cac2994SStefano Zampini   PetscValidPointer(fec_type,3);
1404cac2994SStefano Zampini   PetscValidPointer(dim,4);
1414cac2994SStefano Zampini   PetscValidPointer(Vfield,6);
1424cac2994SStefano Zampini   ierr = 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));CHKERRQ(ierr);
1438135c375SStefano Zampini   PetscFunctionReturn(0);
1448135c375SStefano Zampini }
1458135c375SStefano Zampini 
1464cac2994SStefano Zampini 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*))
1478135c375SStefano Zampini {
1488135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
1498135c375SStefano Zampini   PetscInt         i;
1508135c375SStefano Zampini   PetscErrorCode   ierr;
1518135c375SStefano Zampini 
1528135c375SStefano Zampini   PetscFunctionBegin;
1538135c375SStefano Zampini   if (socket->nwindow && socket->nwindow != nfields) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_USER,"Cannot set number of fields %D with number of windows %D",nfields,socket->nwindow);
1548135c375SStefano Zampini   if (!socket->nwindow) {
1558135c375SStefano Zampini     socket->nwindow = nfields;
1568135c375SStefano Zampini 
1574cac2994SStefano Zampini     ierr = PetscCalloc5(nfields,&socket->window,nfields,&socket->windowtitle,nfields,&socket->fec_type,nfields,&socket->spacedim,nfields,&socket->Ufield);CHKERRQ(ierr);
1588135c375SStefano Zampini     for (i=0;i<nfields;i++) {
1594cac2994SStefano Zampini       const char     *name;
1608135c375SStefano Zampini 
1614cac2994SStefano Zampini       ierr = PetscObjectGetName(Vfield[i],&name);CHKERRQ(ierr);
1628135c375SStefano Zampini       ierr = PetscStrallocpy(name,&socket->windowtitle[i]);CHKERRQ(ierr);
1638135c375SStefano Zampini       ierr = PetscStrallocpy(fec_type[i],&socket->fec_type[i]);CHKERRQ(ierr);
1644cac2994SStefano Zampini       ierr = PetscObjectReference(Vfield[i]);CHKERRQ(ierr);
1654cac2994SStefano Zampini       socket->Ufield[i] = Vfield[i];
1664cac2994SStefano Zampini       socket->spacedim[i] = dim[i];
1678135c375SStefano Zampini     }
1688135c375SStefano Zampini   }
1698135c375SStefano Zampini   /* number of fields are not allowed to vary */
1708135c375SStefano Zampini   if (nfields != socket->nwindow) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot visualize %D fields using %D socket windows",nfields,socket->nwindow);
1718135c375SStefano Zampini   socket->g2lfield = g2l;
1728135c375SStefano Zampini   if (socket->destroyctx && socket->userctx) { ierr = (*socket->destroyctx)(socket->userctx);CHKERRQ(ierr); }
1738135c375SStefano Zampini   socket->userctx = ctx;
1748135c375SStefano Zampini   socket->destroyctx = destroyctx;
1758135c375SStefano Zampini   PetscFunctionReturn(0);
1768135c375SStefano Zampini }
1778135c375SStefano Zampini 
1788135c375SStefano Zampini static PetscErrorCode PetscViewerGLVisInfoDestroy_Private(void *ptr)
1798135c375SStefano Zampini {
1808135c375SStefano Zampini   PetscViewerGLVisInfo info = (PetscViewerGLVisInfo)ptr;
1818135c375SStefano Zampini   PetscErrorCode       ierr;
1828135c375SStefano Zampini 
183c0bc9656SStefano Zampini   PetscFunctionBegin;
18477eacf09SStefano Zampini   ierr = PetscFree(info->fmt);CHKERRQ(ierr);
1858135c375SStefano Zampini   ierr = PetscFree(info);CHKERRQ(ierr);
1868135c375SStefano Zampini   PetscFunctionReturn(0);
1878135c375SStefano Zampini }
1888135c375SStefano Zampini 
1898135c375SStefano Zampini /* we can decide to prevent specific processes from using the viewer */
1908135c375SStefano Zampini static PetscErrorCode PetscViewerGLVisAttachInfo_Private(PetscViewer viewer, PetscViewer window)
1918135c375SStefano Zampini {
1928135c375SStefano Zampini   PetscViewerGLVis     socket = (PetscViewerGLVis)viewer->data;
1938135c375SStefano Zampini   PetscErrorCode       ierr;
1948135c375SStefano Zampini   PetscContainer       container;
1958135c375SStefano Zampini   PetscViewerGLVisInfo info;
1968135c375SStefano Zampini 
197c0bc9656SStefano Zampini   PetscFunctionBegin;
19877eacf09SStefano Zampini   ierr = PetscObjectQuery((PetscObject)window,"_glvis_info_container",(PetscObject*)&container);CHKERRQ(ierr);
19977eacf09SStefano Zampini   if (!container) {
2008135c375SStefano Zampini     ierr = PetscNew(&info);CHKERRQ(ierr);
2018135c375SStefano Zampini     info->enabled = PETSC_TRUE;
2028135c375SStefano Zampini     info->init    = PETSC_FALSE;
2038135c375SStefano Zampini     info->pause   = socket->pause;
2048135c375SStefano Zampini     ierr = PetscContainerCreate(PetscObjectComm((PetscObject)window),&container);CHKERRQ(ierr);
2058135c375SStefano Zampini     ierr = PetscContainerSetPointer(container,(void*)info);CHKERRQ(ierr);
2068135c375SStefano Zampini     ierr = PetscContainerSetUserDestroy(container,PetscViewerGLVisInfoDestroy_Private);CHKERRQ(ierr);
2078135c375SStefano Zampini     ierr = PetscObjectCompose((PetscObject)window,"_glvis_info_container",(PetscObject)container);CHKERRQ(ierr);
2088135c375SStefano Zampini     ierr = PetscContainerDestroy(&container);CHKERRQ(ierr);
20977eacf09SStefano Zampini   } else {
21077eacf09SStefano Zampini     ierr = PetscContainerGetPointer(container,(void**)&info);CHKERRQ(ierr);
21177eacf09SStefano Zampini   }
21277eacf09SStefano Zampini   ierr = PetscFree(info->fmt);CHKERRQ(ierr);
21377eacf09SStefano Zampini   ierr = PetscStrallocpy(socket->fmt,&info->fmt);CHKERRQ(ierr);
2148135c375SStefano Zampini   PetscFunctionReturn(0);
2158135c375SStefano Zampini }
2168135c375SStefano Zampini 
2178135c375SStefano Zampini static PetscErrorCode PetscViewerGLVisGetNewWindow_Private(PetscViewer viewer,PetscViewer *view)
2188135c375SStefano Zampini {
2198135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2208135c375SStefano Zampini   PetscViewer      window = NULL;
2218135c375SStefano Zampini   PetscBool        ldis,dis;
2228135c375SStefano Zampini   PetscErrorCode   ierr;
2238135c375SStefano Zampini 
2248135c375SStefano Zampini   PetscFunctionBegin;
2258135c375SStefano Zampini   ierr = PetscViewerASCIISocketOpen(PETSC_COMM_SELF,socket->name,socket->port,&window);
2268135c375SStefano Zampini   /* if we could not estabilish a connection the first time,
2278135c375SStefano Zampini      we disable the socket viewer */
2288135c375SStefano Zampini   ldis = ierr ? PETSC_TRUE : PETSC_FALSE;
2298135c375SStefano Zampini   ierr = MPI_Allreduce(&ldis,&dis,1,MPIU_BOOL,MPI_LOR,PetscObjectComm((PetscObject)viewer));CHKERRQ(ierr);
2308135c375SStefano Zampini   if (dis) {
2318135c375SStefano Zampini     socket->status = PETSCVIEWERGLVIS_DISABLED;
2328135c375SStefano Zampini     ierr  = PetscViewerDestroy(&window);CHKERRQ(ierr);
2338135c375SStefano Zampini   }
2348135c375SStefano Zampini   *view = window;
2358135c375SStefano Zampini   PetscFunctionReturn(0);
2368135c375SStefano Zampini }
2378135c375SStefano Zampini 
2388135c375SStefano Zampini PetscErrorCode PetscViewerGLVisPause_Private(PetscViewer viewer)
2398135c375SStefano Zampini {
2408135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2418135c375SStefano Zampini   PetscErrorCode   ierr;
2428135c375SStefano Zampini 
2438135c375SStefano Zampini   PetscFunctionBegin;
2448135c375SStefano Zampini   if (socket->pause > 0) {
2458135c375SStefano Zampini     ierr = PetscSleep(socket->pause);CHKERRQ(ierr);
2468135c375SStefano Zampini   }
2478135c375SStefano Zampini   PetscFunctionReturn(0);
2488135c375SStefano Zampini }
2498135c375SStefano Zampini 
2508135c375SStefano Zampini /* DM specific support */
2518135c375SStefano Zampini PetscErrorCode PetscViewerGLVisSetDM_Private(PetscViewer viewer, PetscObject dm)
2528135c375SStefano Zampini {
2538135c375SStefano Zampini   PetscErrorCode   ierr;
2548135c375SStefano Zampini   PetscViewerGLVis socket  = (PetscViewerGLVis)viewer->data;
2558135c375SStefano Zampini 
2568135c375SStefano Zampini   PetscFunctionBegin;
2578135c375SStefano Zampini   if (socket->dm && socket->dm != dm) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Cannot change DM associated with the GLVis viewer");
2588135c375SStefano Zampini   if (!socket->dm) {
2598135c375SStefano Zampini     PetscErrorCode (*setupwithdm)(PetscObject,PetscViewer) = NULL;
2608135c375SStefano Zampini 
2618135c375SStefano Zampini     ierr = PetscObjectQueryFunction(dm,"DMSetUpGLVisViewer_C",&setupwithdm);CHKERRQ(ierr);
2628135c375SStefano Zampini     if (setupwithdm) {
2638135c375SStefano Zampini       ierr = (*setupwithdm)(dm,viewer);CHKERRQ(ierr);
2648135c375SStefano Zampini     } else SETERRQ1(PetscObjectComm(dm),PETSC_ERR_SUP,"No support for DM type %s",dm->type_name);
2658135c375SStefano Zampini     ierr = PetscObjectReference(dm);CHKERRQ(ierr);
2668135c375SStefano Zampini     socket->dm = dm;
2678135c375SStefano Zampini   }
2688135c375SStefano Zampini   PetscFunctionReturn(0);
2698135c375SStefano Zampini }
2708135c375SStefano Zampini 
2718135c375SStefano Zampini PetscErrorCode PetscViewerGLVisGetDMWindow_Private(PetscViewer viewer,PetscViewer* view)
2728135c375SStefano Zampini {
2738135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
2748135c375SStefano Zampini   PetscErrorCode   ierr;
2758135c375SStefano Zampini 
2768135c375SStefano Zampini   PetscFunctionBegin;
2778135c375SStefano Zampini   if (!socket->meshwindow) {
2788135c375SStefano Zampini     if (socket->type == PETSC_VIEWER_GLVIS_SOCKET) {
2798135c375SStefano Zampini       ierr = PetscViewerGLVisGetNewWindow_Private(viewer,&socket->meshwindow);CHKERRQ(ierr);
2808135c375SStefano Zampini     } else {
28104b79de6SStefano Zampini       size_t    len;
28204b79de6SStefano Zampini       PetscBool isstdout;
28304b79de6SStefano Zampini 
28404b79de6SStefano Zampini       ierr = PetscStrlen(socket->name,&len);CHKERRQ(ierr);
28504b79de6SStefano Zampini       ierr = PetscStrcmp(socket->name,"stdout",&isstdout);CHKERRQ(ierr);
28604b79de6SStefano Zampini       if (!socket->name || !len || isstdout) {
2873f877d7dSStefano Zampini         ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&socket->meshwindow);CHKERRQ(ierr);
28804b79de6SStefano Zampini       } else {
2898135c375SStefano Zampini         PetscMPIInt rank;
2908135c375SStefano Zampini         char        filename[PETSC_MAX_PATH_LEN];
2918135c375SStefano Zampini         ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
2928135c375SStefano Zampini         ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s-mesh.%06d",socket->name,rank);CHKERRQ(ierr);
2938135c375SStefano Zampini         ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&socket->meshwindow);CHKERRQ(ierr);
2948135c375SStefano Zampini       }
29504b79de6SStefano Zampini     }
2968135c375SStefano Zampini     if (socket->meshwindow) {
2978135c375SStefano Zampini       ierr = PetscViewerPushFormat(socket->meshwindow,PETSC_VIEWER_ASCII_GLVIS);CHKERRQ(ierr);
2988135c375SStefano Zampini     }
2998135c375SStefano Zampini   }
30077eacf09SStefano Zampini   if (socket->meshwindow) {
30177eacf09SStefano Zampini     ierr = PetscViewerGLVisAttachInfo_Private(viewer,socket->meshwindow);CHKERRQ(ierr);
30277eacf09SStefano Zampini   }
3038135c375SStefano Zampini   *view = socket->meshwindow;
3048135c375SStefano Zampini   PetscFunctionReturn(0);
3058135c375SStefano Zampini }
3068135c375SStefano Zampini 
3078135c375SStefano Zampini PetscErrorCode PetscViewerGLVisGetType_Private(PetscViewer viewer,PetscViewerGLVisType *type)
3088135c375SStefano Zampini {
3098135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3108135c375SStefano Zampini 
3118135c375SStefano Zampini   PetscFunctionBegin;
3128135c375SStefano Zampini   PetscValidPointer(type,2);
3138135c375SStefano Zampini   *type = socket->type;
3148135c375SStefano Zampini   PetscFunctionReturn(0);
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 */
3188135c375SStefano Zampini PetscErrorCode PetscViewerGLVisGetStatus_Private(PetscViewer viewer, PetscViewerGLVisStatus *sockstatus)
3198135c375SStefano Zampini {
3208135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3218135c375SStefano Zampini 
3228135c375SStefano Zampini   PetscFunctionBegin;
3238135c375SStefano Zampini   PetscValidPointer(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     PetscErrorCode ierr;
3308135c375SStefano Zampini 
3318135c375SStefano Zampini     for (i=0,lconn=PETSC_TRUE;i<socket->nwindow;i++)
3328135c375SStefano Zampini       if (!socket->window[i])
3338135c375SStefano Zampini         lconn = PETSC_FALSE;
3348135c375SStefano Zampini 
3358135c375SStefano Zampini     ierr = MPI_Allreduce(&lconn,&conn,1,MPIU_BOOL,MPI_LAND,PetscObjectComm((PetscObject)viewer));CHKERRQ(ierr);
3368135c375SStefano Zampini     if (conn) socket->status = PETSCVIEWERGLVIS_CONNECTED;
3378135c375SStefano Zampini   }
3388135c375SStefano Zampini   *sockstatus = socket->status;
3398135c375SStefano Zampini   PetscFunctionReturn(0);
3408135c375SStefano Zampini }
3418135c375SStefano Zampini 
3428135c375SStefano Zampini PetscErrorCode PetscViewerGLVisGetDM_Private(PetscViewer viewer, PetscObject* dm)
3438135c375SStefano Zampini {
3448135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3458135c375SStefano Zampini 
3468135c375SStefano Zampini   PetscFunctionBegin;
3478135c375SStefano Zampini   *dm = socket->dm;
3488135c375SStefano Zampini   PetscFunctionReturn(0);
3498135c375SStefano Zampini }
3508135c375SStefano Zampini 
3514cac2994SStefano Zampini PetscErrorCode PetscViewerGLVisGetFields_Private(PetscViewer viewer, PetscInt* nfield, const char **fec[], PetscInt *spacedim[], PetscErrorCode(**g2lfield)(PetscObject,PetscInt,PetscObject[],void*), PetscObject *Ufield[], void **userctx)
3528135c375SStefano Zampini {
3538135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
3548135c375SStefano Zampini 
3558135c375SStefano Zampini   PetscFunctionBegin;
3568135c375SStefano Zampini   if (nfield)   *nfield   = socket->nwindow;
3578135c375SStefano Zampini   if (fec)      *fec      = (const char**)socket->fec_type;
3584cac2994SStefano Zampini   if (spacedim) *spacedim = socket->spacedim;
3598135c375SStefano Zampini   if (g2lfield) *g2lfield = socket->g2lfield;
3608135c375SStefano Zampini   if (Ufield)   *Ufield   = socket->Ufield;
3618135c375SStefano Zampini   if (userctx)  *userctx  = socket->userctx;
3628135c375SStefano Zampini   PetscFunctionReturn(0);
3638135c375SStefano Zampini }
3648135c375SStefano Zampini 
3658135c375SStefano Zampini /* accessor routines for the viewer windows:
3668135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP   : it returns a new viewer every time
3678135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET : it returns the socket, and creates it if not yet done.
3688135c375SStefano Zampini */
3698135c375SStefano Zampini PetscErrorCode PetscViewerGLVisGetWindow_Private(PetscViewer viewer,PetscInt wid,PetscViewer* view)
3708135c375SStefano Zampini {
3718135c375SStefano Zampini   PetscViewerGLVis       socket = (PetscViewerGLVis)viewer->data;
3728135c375SStefano Zampini   PetscViewerGLVisStatus status;
3738135c375SStefano Zampini   PetscErrorCode         ierr;
3748135c375SStefano Zampini 
3758135c375SStefano Zampini   PetscFunctionBegin;
3768135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer,wid,2);
3778135c375SStefano Zampini   PetscValidPointer(view,3);
3788135c375SStefano Zampini   if (wid < 0 || wid > socket->nwindow-1) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_USER,"Cannot get window id %D: allowed range [0,%D)",wid,socket->nwindow-1);
3798135c375SStefano Zampini   status = socket->status;
3808135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP && socket->window[wid]) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_USER,"Window %D is already in use",wid);
3818135c375SStefano Zampini   switch (status) {
3828135c375SStefano Zampini     case PETSCVIEWERGLVIS_DISCONNECTED:
3838135c375SStefano Zampini       if (socket->window[wid]) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"This should not happen");
3848135c375SStefano Zampini       if (socket->type == PETSC_VIEWER_GLVIS_DUMP) {
38504b79de6SStefano Zampini         size_t    len;
38604b79de6SStefano Zampini         PetscBool isstdout;
38704b79de6SStefano Zampini 
38804b79de6SStefano Zampini         ierr = PetscStrlen(socket->name,&len);CHKERRQ(ierr);
38904b79de6SStefano Zampini         ierr = PetscStrcmp(socket->name,"stdout",&isstdout);CHKERRQ(ierr);
39004b79de6SStefano Zampini         if (!socket->name || !len || isstdout) {
3913f877d7dSStefano Zampini           ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,"stdout",&socket->window[wid]);CHKERRQ(ierr);
39204b79de6SStefano Zampini         } else {
3938135c375SStefano Zampini           PetscMPIInt rank;
3948135c375SStefano Zampini           char        filename[PETSC_MAX_PATH_LEN];
3958135c375SStefano Zampini 
3968135c375SStefano Zampini           ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer),&rank);CHKERRQ(ierr);
3978135c375SStefano Zampini           ierr = PetscSNPrintf(filename,PETSC_MAX_PATH_LEN,"%s-%s-%d.%06d",socket->name,socket->windowtitle[wid],socket->snapid,rank);CHKERRQ(ierr);
3988135c375SStefano Zampini           ierr = PetscViewerASCIIOpen(PETSC_COMM_SELF,filename,&socket->window[wid]);CHKERRQ(ierr);
39904b79de6SStefano Zampini         }
4008135c375SStefano Zampini       } else {
4018135c375SStefano Zampini         ierr = PetscViewerGLVisGetNewWindow_Private(viewer,&socket->window[wid]);CHKERRQ(ierr);
4028135c375SStefano Zampini       }
4038135c375SStefano Zampini       if (socket->window[wid]) {
4048135c375SStefano Zampini         ierr = PetscViewerPushFormat(socket->window[wid],PETSC_VIEWER_ASCII_GLVIS);CHKERRQ(ierr);
4058135c375SStefano Zampini       }
4068135c375SStefano Zampini       *view = socket->window[wid];
4078135c375SStefano Zampini       break;
4088135c375SStefano Zampini     case PETSCVIEWERGLVIS_CONNECTED:
4098135c375SStefano Zampini       *view = socket->window[wid];
4108135c375SStefano Zampini       break;
4118135c375SStefano Zampini     case PETSCVIEWERGLVIS_DISABLED:
4128135c375SStefano Zampini       *view = NULL;
4138135c375SStefano Zampini       break;
4148135c375SStefano Zampini     default:
4158135c375SStefano Zampini       SETERRQ1(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP,"Unhandled socket status %d\n",(int)status);
4168135c375SStefano Zampini       break;
4178135c375SStefano Zampini   }
41877eacf09SStefano Zampini   if (*view) {
41977eacf09SStefano Zampini     ierr = PetscViewerGLVisAttachInfo_Private(viewer,*view);CHKERRQ(ierr);
42077eacf09SStefano Zampini   }
4218135c375SStefano Zampini   PetscFunctionReturn(0);
4228135c375SStefano Zampini }
4238135c375SStefano Zampini 
4248135c375SStefano Zampini /* Restore the window viewer
4258135c375SStefano Zampini    PETSC_VIEWER_GLVIS_DUMP  : destroys the temporary created ASCII viewer used for dumping
4268135c375SStefano Zampini    PETSC_VIEWER_GLVIS_SOCKET: - if the returned window viewer is not NULL, just zeros the pointer.
4278135c375SStefano Zampini                  - it the returned window viewer is NULL, assumes something went wrong
4288135c375SStefano Zampini                    with the socket (i.e. SIGPIPE when a user closes the popup window)
4298135c375SStefano Zampini                    and that the caller already handled it (see VecView_GLVis).
4308135c375SStefano Zampini */
4318135c375SStefano Zampini PetscErrorCode PetscViewerGLVisRestoreWindow_Private(PetscViewer viewer,PetscInt wid, PetscViewer* view)
4328135c375SStefano Zampini {
4338135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
4348135c375SStefano Zampini   PetscErrorCode   ierr;
4358135c375SStefano Zampini 
4368135c375SStefano Zampini   PetscFunctionBegin;
4378135c375SStefano Zampini   PetscValidLogicalCollectiveInt(viewer,wid,2);
4388135c375SStefano Zampini   PetscValidPointer(view,3);
4398135c375SStefano Zampini   if (wid < 0 || wid > socket->nwindow-1) SETERRQ2(PetscObjectComm((PetscObject)viewer),PETSC_ERR_USER,"Cannot restore window id %D: allowed range [0,%D)",wid,socket->nwindow);
4408135c375SStefano Zampini   if (*view && *view != socket->window[wid]) SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_USER,"Viewer was not obtained from PetscViewerGLVisGetWindow");
4418135c375SStefano Zampini   if (*view) {
4428135c375SStefano Zampini     ierr = PetscViewerFlush(*view);CHKERRQ(ierr);
4438135c375SStefano Zampini     ierr = PetscBarrier((PetscObject)viewer);CHKERRQ(ierr);
4448135c375SStefano Zampini   }
4458135c375SStefano Zampini   if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */
4468135c375SStefano Zampini     ierr = PetscViewerDestroy(&socket->window[wid]);CHKERRQ(ierr);
4478135c375SStefano Zampini   } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */
4488135c375SStefano Zampini     socket->window[wid] = NULL;
4498135c375SStefano Zampini   }
4508135c375SStefano Zampini   *view = NULL;
4518135c375SStefano Zampini   PetscFunctionReturn(0);
4528135c375SStefano Zampini }
4538135c375SStefano Zampini 
4548135c375SStefano Zampini /* default window appearance in the PETSC_VIEWER_GLVIS_SOCKET case */
4558135c375SStefano Zampini PetscErrorCode PetscViewerGLVisInitWindow_Private(PetscViewer viewer, PetscBool mesh, PetscInt dim, const char *name)
4568135c375SStefano Zampini {
4578135c375SStefano Zampini   PetscErrorCode       ierr;
4588135c375SStefano Zampini   PetscViewerGLVisInfo info;
4598135c375SStefano Zampini   PetscContainer       container;
4608135c375SStefano Zampini 
4618135c375SStefano Zampini   PetscFunctionBegin;
4628135c375SStefano Zampini   ierr = PetscObjectQuery((PetscObject)viewer,"_glvis_info_container",(PetscObject*)&container);CHKERRQ(ierr);
4638135c375SStefano Zampini   if (!container) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_USER,"Viewer was not obtained from PetscGLVisViewerGetNewWindow_Private");
4648135c375SStefano Zampini   ierr = PetscContainerGetPointer(container,(void**)&info);CHKERRQ(ierr);
4658135c375SStefano Zampini   if (info->init) {
4668135c375SStefano Zampini     if (info->pause < 0) {
4678135c375SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"pause\n");CHKERRQ(ierr); /* pause */
4688135c375SStefano Zampini     }
4698135c375SStefano Zampini     PetscFunctionReturn(0);
4708135c375SStefano Zampini   }
4718135c375SStefano Zampini   ierr = PetscViewerASCIIPrintf(viewer,"window_size 800 800\n");CHKERRQ(ierr);
4728135c375SStefano Zampini   if (name) {
4738135c375SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"window_title '%s'\n",name);CHKERRQ(ierr);
4748135c375SStefano Zampini   }
4758135c375SStefano Zampini   if (mesh) {
4768135c375SStefano Zampini     switch (dim) {
4778135c375SStefano Zampini     case 1:
4788135c375SStefano Zampini       break;
4798135c375SStefano Zampini     case 2:
4808135c375SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"keys cmeeppppp\n");CHKERRQ(ierr); /* show colorbar, mesh and ranks */
4818135c375SStefano Zampini       break;
4828135c375SStefano Zampini     case 3: /* TODO: decide default view in 3D */
4838135c375SStefano Zampini       break;
4848135c375SStefano Zampini     }
4858135c375SStefano Zampini   } else {
4868135c375SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"keys cm\n");CHKERRQ(ierr); /* show colorbar and mesh */
4878135c375SStefano Zampini     switch (dim) {
4888135c375SStefano Zampini     case 1:
4898135c375SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"keys RRj\n");CHKERRQ(ierr); /* set to 1D (side view) and turn off perspective */
4908135c375SStefano Zampini       break;
4918135c375SStefano Zampini     case 2:
4928135c375SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"keys Rjl\n");CHKERRQ(ierr); /* set to 2D (top view), turn off perspective and light */
4938135c375SStefano Zampini       break;
4948135c375SStefano Zampini     case 3:
4958135c375SStefano Zampini       break;
4968135c375SStefano Zampini     }
4978135c375SStefano Zampini     ierr = PetscViewerASCIIPrintf(viewer,"autoscale value\n");CHKERRQ(ierr); /* update value-range; keep mesh-extents fixed */
4988135c375SStefano Zampini     if (info->pause == 0) {
4998135c375SStefano Zampini       ierr = PetscViewerASCIIPrintf(viewer,"pause\n");CHKERRQ(ierr); /* pause */
5008135c375SStefano Zampini     }
5018135c375SStefano Zampini   }
5028135c375SStefano Zampini   info->init = PETSC_TRUE;
5038135c375SStefano Zampini   PetscFunctionReturn(0);
5048135c375SStefano Zampini }
5058135c375SStefano Zampini 
5068135c375SStefano Zampini static PetscErrorCode PetscViewerDestroy_GLVis(PetscViewer viewer)
5078135c375SStefano Zampini {
5088135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5098135c375SStefano Zampini   PetscInt         i;
5108135c375SStefano Zampini   PetscErrorCode   ierr;
5118135c375SStefano Zampini 
5128135c375SStefano Zampini   PetscFunctionBegin;
5138135c375SStefano Zampini   for (i=0;i<socket->nwindow;i++) {
5148135c375SStefano Zampini     ierr = PetscViewerDestroy(&socket->window[i]);CHKERRQ(ierr);
5158135c375SStefano Zampini     ierr = PetscFree(socket->windowtitle[i]);CHKERRQ(ierr);
5168135c375SStefano Zampini     ierr = PetscFree(socket->fec_type[i]);CHKERRQ(ierr);
5178135c375SStefano Zampini     ierr = PetscObjectDestroy(&socket->Ufield[i]);CHKERRQ(ierr);
5188135c375SStefano Zampini   }
5198135c375SStefano Zampini   ierr = PetscFree(socket->name);CHKERRQ(ierr);
5204cac2994SStefano Zampini   ierr = PetscFree5(socket->window,socket->windowtitle,socket->fec_type,socket->spacedim,socket->Ufield);CHKERRQ(ierr);
52177eacf09SStefano Zampini   ierr = PetscFree(socket->fmt);CHKERRQ(ierr);
5228135c375SStefano Zampini   ierr = PetscViewerDestroy(&socket->meshwindow);CHKERRQ(ierr);
5238135c375SStefano Zampini   ierr = PetscObjectDestroy(&socket->dm);CHKERRQ(ierr);
5248135c375SStefano Zampini   if (socket->destroyctx && socket->userctx) { ierr = (*socket->destroyctx)(socket->userctx);CHKERRQ(ierr); }
5258135c375SStefano Zampini 
52677eacf09SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetPrecision_C",NULL);CHKERRQ(ierr);
5278135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetSnapId_C",NULL);CHKERRQ(ierr);
5288135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetFields_C",NULL);CHKERRQ(ierr);
5298135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL);CHKERRQ(ierr);
5308135c375SStefano Zampini   ierr = PetscFree(socket);CHKERRQ(ierr);
5318135c375SStefano Zampini   viewer->data = NULL;
5328135c375SStefano Zampini   PetscFunctionReturn(0);
5338135c375SStefano Zampini }
5348135c375SStefano Zampini 
5358135c375SStefano Zampini static PetscErrorCode PetscViewerSetFromOptions_GLVis(PetscOptionItems *PetscOptionsObject,PetscViewer v)
5368135c375SStefano Zampini {
5378135c375SStefano Zampini   PetscErrorCode   ierr;
5388135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)v->data;
5398135c375SStefano Zampini 
5408135c375SStefano Zampini   PetscFunctionBegin;
5418135c375SStefano Zampini   ierr = PetscOptionsHead(PetscOptionsObject,"GLVis PetscViewer Options");CHKERRQ(ierr);
5428135c375SStefano Zampini   ierr = PetscOptionsReal("-viewer_glvis_pause","-1 to pause after each visualization, otherwise sleeps for given seconds",NULL,socket->pause,&socket->pause,NULL);CHKERRQ(ierr);
5438135c375SStefano Zampini   ierr = PetscOptionsTail();CHKERRQ(ierr);
5448135c375SStefano Zampini   PetscFunctionReturn(0);
5458135c375SStefano Zampini }
5468135c375SStefano Zampini 
5478135c375SStefano Zampini static PetscErrorCode PetscViewerSetFileName_GLVis(PetscViewer viewer, const char name[])
5488135c375SStefano Zampini {
5498135c375SStefano Zampini   char             *sport;
5508135c375SStefano Zampini   PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data;
5518135c375SStefano Zampini   PetscErrorCode   ierr;
5528135c375SStefano Zampini 
5538135c375SStefano Zampini   PetscFunctionBegin;
5548135c375SStefano Zampini   socket->type = PETSC_VIEWER_GLVIS_DUMP;
5558135c375SStefano Zampini   /* we accept localhost^port */
5568135c375SStefano Zampini   ierr = PetscFree(socket->name);CHKERRQ(ierr);
5578135c375SStefano Zampini   ierr = PetscStrallocpy(name,&socket->name);CHKERRQ(ierr);
5588135c375SStefano Zampini   ierr = PetscStrchr(socket->name,'^',&sport);CHKERRQ(ierr);
5598135c375SStefano Zampini   if (sport) {
5608135c375SStefano Zampini     PetscInt port = 19916;
5618135c375SStefano Zampini     size_t   len;
5628135c375SStefano Zampini 
5638135c375SStefano Zampini     *sport++ = 0;
5648135c375SStefano Zampini     ierr = PetscStrlen(sport,&len);CHKERRQ(ierr);
5658135c375SStefano Zampini     if (len) ierr = PetscOptionsStringToInt(sport,&port);
5668135c375SStefano Zampini     if (!ierr) {
5678135c375SStefano Zampini       socket->port = (port != PETSC_DECIDE && port != PETSC_DEFAULT) ? port : 19916;
5688135c375SStefano Zampini     } else {
5698135c375SStefano Zampini       socket->port = 19916;
5708135c375SStefano Zampini     }
5718135c375SStefano Zampini     socket->type = PETSC_VIEWER_GLVIS_SOCKET;
5728135c375SStefano Zampini   }
5738135c375SStefano Zampini   PetscFunctionReturn(0);
5748135c375SStefano Zampini }
5758135c375SStefano Zampini 
5768135c375SStefano Zampini /*
5778135c375SStefano Zampini      PetscViewerGLVisOpen - Opens a GLVis type viewer
5788135c375SStefano Zampini 
5798135c375SStefano Zampini   Collective on comm
5808135c375SStefano Zampini 
5818135c375SStefano Zampini   Input Parameters:
5828135c375SStefano Zampini +  comm      - the MPI communicator
5838135c375SStefano Zampini .  type      - the viewer type: PETSC_VIEWER_GLVIS_SOCKET for real-time visualization or PETSC_VIEWER_GLVIS_DUMP for dumping to disk
5848135c375SStefano Zampini .  name      - either the hostname where the GLVis server is running or the base filename for dumping the data for subsequent visualizations
5858135c375SStefano Zampini -  port      - socket port where the GLVis server is listening. Not referenced when type is PETSC_VIEWER_GLVIS_DUMP
5868135c375SStefano Zampini 
5878135c375SStefano Zampini   Output Parameters:
5888135c375SStefano Zampini -  viewer    - the PetscViewer object
5898135c375SStefano Zampini 
5908135c375SStefano Zampini   Notes: misses Fortran binding
5918135c375SStefano Zampini 
5928135c375SStefano Zampini   Level: beginner
5938135c375SStefano Zampini 
5948135c375SStefano Zampini .seealso: PetscViewerCreate(), PetscViewerSetType(), PetscViewerGLVisType
5958135c375SStefano Zampini */
5968135c375SStefano Zampini PETSC_EXTERN PetscErrorCode PetscViewerGLVisOpen(MPI_Comm comm, PetscViewerGLVisType type, const char* name, PetscInt port, PetscViewer* viewer)
5978135c375SStefano Zampini {
5988135c375SStefano Zampini   PetscViewerGLVis socket;
5998135c375SStefano Zampini   PetscErrorCode   ierr;
6008135c375SStefano Zampini 
6018135c375SStefano Zampini   PetscFunctionBegin;
6028135c375SStefano Zampini   ierr = PetscViewerCreate(comm,viewer);CHKERRQ(ierr);
6038135c375SStefano Zampini   ierr = PetscViewerSetType(*viewer,PETSCVIEWERGLVIS);CHKERRQ(ierr);
6048135c375SStefano Zampini 
6058135c375SStefano Zampini   socket       = (PetscViewerGLVis)((*viewer)->data);
606*a7bda6aaSStefano Zampini   socket->type = type;
607*a7bda6aaSStefano Zampini   if (type == PETSC_VIEWER_GLVIS_DUMP || name) {
60851f51421SSatish Balay     ierr = PetscFree(socket->name);CHKERRQ(ierr);
6098135c375SStefano Zampini     ierr = PetscStrallocpy(name,&socket->name);CHKERRQ(ierr);
610*a7bda6aaSStefano Zampini   }
611*a7bda6aaSStefano Zampini   socket->port = (!port || port == PETSC_DETERMINE || port == PETSC_DECIDE) ? 19916 : port;
6128135c375SStefano Zampini 
6138135c375SStefano Zampini   ierr = PetscViewerSetFromOptions(*viewer);CHKERRQ(ierr);
6148135c375SStefano Zampini   PetscFunctionReturn(0);
6158135c375SStefano Zampini }
6168135c375SStefano Zampini 
6178135c375SStefano Zampini /*
6188135c375SStefano Zampini   PETSC_VIEWER_GLVIS_ - Creates an GLVIS PetscViewer shared by all processors in a communicator.
6198135c375SStefano Zampini 
6208135c375SStefano Zampini   Collective on MPI_Comm
6218135c375SStefano Zampini 
6228135c375SStefano Zampini   Input Parameter:
6238135c375SStefano Zampini . comm - the MPI communicator to share the GLVIS PetscViewer
6248135c375SStefano Zampini 
6258135c375SStefano Zampini   Level: intermediate
6268135c375SStefano Zampini 
6278135c375SStefano Zampini   Notes: misses Fortran bindings
6288135c375SStefano Zampini 
6298135c375SStefano Zampini   Environmental variables:
6308135c375SStefano Zampini + PETSC_VIEWER_GLVIS_FILENAME : output filename (if specified dump to disk, and takes precedence on PETSC_VIEWER_GLVIS_HOSTNAME)
6318135c375SStefano Zampini . PETSC_VIEWER_GLVIS_HOSTNAME : machine where the GLVis server is listening (defaults to localhost)
6328135c375SStefano Zampini - PETSC_VIEWER_GLVIS_PORT     : port opened by the GLVis server (defaults to 19916)
6338135c375SStefano Zampini 
6348135c375SStefano Zampini   Notes:
6358135c375SStefano Zampini   Unlike almost all other PETSc routines, PETSC_VIEWER_GLVIS_ does not return
6368135c375SStefano Zampini   an error code.  The GLVIS PetscViewer is usually used in the form
6378135c375SStefano Zampini $       XXXView(XXX object, PETSC_VIEWER_GLVIS_(comm));
6388135c375SStefano Zampini 
6398135c375SStefano Zampini .seealso: PetscViewerGLVISOpen(), PetscViewerGLVisType, PetscViewerCreate(), PetscViewerDestroy()
6408135c375SStefano Zampini */
6418135c375SStefano Zampini PETSC_EXTERN PetscViewer PETSC_VIEWER_GLVIS_(MPI_Comm comm)
6428135c375SStefano Zampini {
6438135c375SStefano Zampini   PetscErrorCode       ierr;
6448135c375SStefano Zampini   PetscBool            flg;
6458135c375SStefano Zampini   PetscViewer          viewer;
6468135c375SStefano Zampini   PetscViewerGLVisType type;
6478135c375SStefano Zampini   char                 fname[PETSC_MAX_PATH_LEN],sport[16];
6488135c375SStefano Zampini   PetscInt             port = 19916; /* default for GLVis */
6498135c375SStefano Zampini 
6508135c375SStefano Zampini   PetscFunctionBegin;
6519d7c699cSSatish Balay   ierr = PetscOptionsGetenv(comm,"PETSC_VIEWER_GLVIS_FILENAME",fname,PETSC_MAX_PATH_LEN,&flg);
6529d7c699cSSatish Balay   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6538135c375SStefano Zampini   if (!flg) {
6548135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_SOCKET;
6558135c375SStefano Zampini     ierr = PetscOptionsGetenv(comm,"PETSC_VIEWER_GLVIS_HOSTNAME",fname,PETSC_MAX_PATH_LEN,&flg);
6568135c375SStefano Zampini     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6578135c375SStefano Zampini     if (!flg) {
6588135c375SStefano Zampini       ierr = PetscStrcpy(fname,"localhost");
6598135c375SStefano Zampini       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6608135c375SStefano Zampini     }
6619d7c699cSSatish Balay     ierr = PetscOptionsGetenv(comm,"PETSC_VIEWER_GLVIS_PORT",sport,16,&flg);
6629d7c699cSSatish Balay     if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6638135c375SStefano Zampini     if (flg) {
6648135c375SStefano Zampini       ierr = PetscOptionsStringToInt(sport,&port);
6658135c375SStefano Zampini       if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6668135c375SStefano Zampini     }
6678135c375SStefano Zampini   } else {
6688135c375SStefano Zampini     type = PETSC_VIEWER_GLVIS_DUMP;
6698135c375SStefano Zampini   }
6708135c375SStefano Zampini   ierr = PetscViewerGLVisOpen(comm,type,fname,port,&viewer);
6718135c375SStefano Zampini   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6728135c375SStefano Zampini   ierr = PetscObjectRegisterDestroy((PetscObject)viewer);
6738135c375SStefano Zampini   if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_GLVIS_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);}
6748135c375SStefano Zampini   PetscFunctionReturn(viewer);
6758135c375SStefano Zampini }
6768135c375SStefano Zampini 
6778135c375SStefano Zampini PETSC_EXTERN PetscErrorCode PetscViewerCreate_GLVis(PetscViewer viewer)
6788135c375SStefano Zampini {
6798135c375SStefano Zampini   PetscViewerGLVis socket;
6808135c375SStefano Zampini   PetscErrorCode   ierr;
6818135c375SStefano Zampini 
6828135c375SStefano Zampini   PetscFunctionBegin;
6838135c375SStefano Zampini   ierr = PetscNewLog(viewer,&socket);CHKERRQ(ierr);
6848135c375SStefano Zampini 
6858135c375SStefano Zampini   /* defaults to socket viewer */
6868135c375SStefano Zampini   ierr = PetscStrallocpy("localhost",&socket->name);CHKERRQ(ierr);
6878135c375SStefano Zampini   socket->port  = 19916; /* GLVis default listening port */
6888135c375SStefano Zampini   socket->type  = PETSC_VIEWER_GLVIS_SOCKET;
6898135c375SStefano Zampini   socket->pause = 0; /* just pause the first time */
6908135c375SStefano Zampini 
69177eacf09SStefano Zampini   /* defaults to full precision */
69277eacf09SStefano Zampini   ierr = PetscStrallocpy(" %g",&socket->fmt);CHKERRQ(ierr);
69377eacf09SStefano Zampini 
6948135c375SStefano Zampini   viewer->data                = (void*)socket;
6958135c375SStefano Zampini   viewer->ops->destroy        = PetscViewerDestroy_GLVis;
6968135c375SStefano Zampini   viewer->ops->setfromoptions = PetscViewerSetFromOptions_GLVis;
6978135c375SStefano Zampini 
69877eacf09SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetPrecision_C",PetscViewerGLVisSetPrecision_GLVis);CHKERRQ(ierr);
6998135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetSnapId_C",PetscViewerGLVisSetSnapId_GLVis);CHKERRQ(ierr);
7008135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerGLVisSetFields_C",PetscViewerGLVisSetFields_GLVis);CHKERRQ(ierr);
7018135c375SStefano Zampini   ierr = PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",PetscViewerSetFileName_GLVis);CHKERRQ(ierr);
7028135c375SStefano Zampini   PetscFunctionReturn(0);
7038135c375SStefano Zampini }
7048135c375SStefano Zampini 
7058135c375SStefano Zampini /* this is a private implementation of a SOCKET with ASCII data format
7068135c375SStefano Zampini    GLVis does not currently handle binary socket streams */
7078135c375SStefano Zampini #if defined(PETSC_HAVE_UNISTD_H)
7088135c375SStefano Zampini #include <unistd.h>
7098135c375SStefano Zampini #endif
7108135c375SStefano Zampini 
711150de0cbSStefano Zampini #if !defined(PETSC_HAVE_WINDOWS_H)
7128135c375SStefano Zampini static PetscErrorCode (*PetscViewerDestroy_ASCII)(PetscViewer);
7138135c375SStefano Zampini 
7148135c375SStefano Zampini static PetscErrorCode PetscViewerDestroy_ASCII_Socket(PetscViewer viewer)
7158135c375SStefano Zampini {
7168135c375SStefano Zampini   FILE *stream;
7178135c375SStefano Zampini   PetscErrorCode ierr = 0;
7188135c375SStefano Zampini   PetscFunctionBegin;
7198135c375SStefano Zampini   ierr = PetscViewerASCIIGetPointer(viewer,&stream);CHKERRQ(ierr);
7208135c375SStefano Zampini   if (stream) {
7218135c375SStefano Zampini     ierr = fclose(stream);
7228135c375SStefano Zampini     if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fclose() failed on stream");
7238135c375SStefano Zampini   }
7248135c375SStefano Zampini   ierr = PetscViewerDestroy_ASCII(viewer);CHKERRQ(ierr);
7258135c375SStefano Zampini   PetscFunctionReturn(0);
7268135c375SStefano Zampini }
72727e89126SStefano Zampini #endif
72811a4995dSStefano Zampini 
7298135c375SStefano Zampini static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm comm,const char* hostname,PetscInt port,PetscViewer* viewer)
7308135c375SStefano Zampini {
731150de0cbSStefano Zampini #if defined(PETSC_HAVE_WINDOWS_H)
73227e89126SStefano Zampini   PetscFunctionBegin;
73327e89126SStefano Zampini   SETERRQ(comm,PETSC_ERR_SUP,"Not implemented for Windows");
73427e89126SStefano Zampini #else
7358135c375SStefano Zampini   FILE           *stream = NULL;
7368135c375SStefano Zampini   int            fd;
7378135c375SStefano Zampini   PetscErrorCode ierr;
7388135c375SStefano Zampini 
7398135c375SStefano Zampini   PetscFunctionBegin;
7408135c375SStefano Zampini   PetscValidPointer(hostname,2);
7418135c375SStefano Zampini   PetscValidPointer(viewer,4);
742c891a504SStefano Zampini #if defined(PETSC_USE_SOCKET_VIEWER)
7438135c375SStefano Zampini   ierr = PetscOpenSocket(hostname,port,&fd);
744c891a504SStefano Zampini #else
745c891a504SStefano Zampini   SETERRQ(comm,PETSC_ERR_SUP,"Missing Socket viewer");
746c891a504SStefano Zampini #endif
7478135c375SStefano Zampini   if (ierr) {
7488135c375SStefano Zampini     PetscInt sierr = ierr;
7498135c375SStefano Zampini     char     err[1024];
7508135c375SStefano Zampini 
7518135c375SStefano Zampini     ierr    = PetscSNPrintf(err,1024,"Cannot connect to socket on %s:%D. Socket visualization is disabled\n",hostname,port);CHKERRQ(ierr);
7528135c375SStefano Zampini     ierr    = PetscInfo(NULL,err);CHKERRQ(ierr);
7538135c375SStefano Zampini     *viewer = NULL;
7548135c375SStefano Zampini     PetscFunctionReturn(sierr);
7558135c375SStefano Zampini   } else {
7568135c375SStefano Zampini     char msg[1024];
7578135c375SStefano Zampini 
7588135c375SStefano Zampini     ierr = PetscSNPrintf(msg,1024,"Successfully connect to socket on %s:%D. Socket visualization is enabled\n",hostname,port);CHKERRQ(ierr);
7598135c375SStefano Zampini     ierr = PetscInfo(NULL,msg);CHKERRQ(ierr);
7608135c375SStefano Zampini   }
7618135c375SStefano Zampini   stream = fdopen(fd,"w"); /* Not possible on Windows */
7628135c375SStefano Zampini   if (!stream) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Cannot open stream from socket %s:%d",hostname,port);
7638135c375SStefano Zampini   ierr = PetscViewerASCIIOpenWithFILE(PETSC_COMM_SELF,stream,viewer);CHKERRQ(ierr);
7648135c375SStefano Zampini   PetscViewerDestroy_ASCII = (*viewer)->ops->destroy;
7658135c375SStefano Zampini   (*viewer)->ops->destroy = PetscViewerDestroy_ASCII_Socket;
76627e89126SStefano Zampini #endif
7678135c375SStefano Zampini   PetscFunctionReturn(0);
7688135c375SStefano Zampini }
769