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 172d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisInfoDestroy_Private(void *ptr) 173d71ae5a4SJacob Faibussowitsch { 1748135c375SStefano Zampini PetscViewerGLVisInfo info = (PetscViewerGLVisInfo)ptr; 1758135c375SStefano Zampini 176c0bc9656SStefano Zampini PetscFunctionBegin; 1779566063dSJacob Faibussowitsch PetscCall(PetscFree(info->fmt)); 1789566063dSJacob Faibussowitsch PetscCall(PetscFree(info)); 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; 1989566063dSJacob Faibussowitsch PetscCall(PetscContainerCreate(PetscObjectComm((PetscObject)window), &container)); 1999566063dSJacob Faibussowitsch PetscCall(PetscContainerSetPointer(container, (void *)info)); 2009566063dSJacob Faibussowitsch PetscCall(PetscContainerSetUserDestroy(container, PetscViewerGLVisInfoDestroy_Private)); 2019566063dSJacob Faibussowitsch PetscCall(PetscObjectCompose((PetscObject)window, "_glvis_info_container", (PetscObject)container)); 2029566063dSJacob Faibussowitsch PetscCall(PetscContainerDestroy(&container)); 20377eacf09SStefano Zampini } else { 2049566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(container, (void **)&info)); 20577eacf09SStefano Zampini } 2069566063dSJacob Faibussowitsch PetscCall(PetscFree(info->fmt)); 2079566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(socket->fmt, &info->fmt)); 2083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2098135c375SStefano Zampini } 2108135c375SStefano Zampini 211d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerGLVisGetNewWindow_Private(PetscViewer viewer, PetscViewer *view) 212d71ae5a4SJacob Faibussowitsch { 2138135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 2148135c375SStefano Zampini PetscViewer window = NULL; 2158135c375SStefano Zampini PetscBool ldis, dis; 2168135c375SStefano Zampini 2178135c375SStefano Zampini PetscFunctionBegin; 2182da53a5bSBarry Smith PetscCall(PetscViewerASCIISocketOpen(PETSC_COMM_SELF, socket->name, socket->port, &window)); 219da81f932SPierre Jolivet /* if we could not establish a connection, we disable the socket viewer on all MPI ranks */ 2202da53a5bSBarry Smith ldis = !viewer ? PETSC_TRUE : PETSC_FALSE; 2211c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&ldis, &dis, 1, MPIU_BOOL, MPI_LOR, PetscObjectComm((PetscObject)viewer))); 2228135c375SStefano Zampini if (dis) { 2238135c375SStefano Zampini socket->status = PETSCVIEWERGLVIS_DISABLED; 2249566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&window)); 2258135c375SStefano Zampini } 2268135c375SStefano Zampini *view = window; 2273ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2288135c375SStefano Zampini } 2298135c375SStefano Zampini 23034e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisPause_Internal(PetscViewer viewer) 231d71ae5a4SJacob Faibussowitsch { 2328135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 2338135c375SStefano Zampini 2348135c375SStefano Zampini PetscFunctionBegin; 23548a46eb9SPierre Jolivet if (socket->type == PETSC_VIEWER_GLVIS_SOCKET && socket->pause > 0) PetscCall(PetscSleep(socket->pause)); 2363ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2378135c375SStefano Zampini } 2388135c375SStefano Zampini 2398135c375SStefano Zampini /* DM specific support */ 24034e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisSetDM_Internal(PetscViewer viewer, PetscObject dm) 241d71ae5a4SJacob Faibussowitsch { 2428135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 2438135c375SStefano Zampini 2448135c375SStefano Zampini PetscFunctionBegin; 245cc73adaaSBarry Smith PetscCheck(!socket->dm || socket->dm == dm, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot change DM associated with the GLVis viewer"); 2468135c375SStefano Zampini if (!socket->dm) { 2478135c375SStefano Zampini PetscErrorCode (*setupwithdm)(PetscObject, PetscViewer) = NULL; 2488135c375SStefano Zampini 2499566063dSJacob Faibussowitsch PetscCall(PetscObjectQueryFunction(dm, "DMSetUpGLVisViewer_C", &setupwithdm)); 2508135c375SStefano Zampini if (setupwithdm) { 2519566063dSJacob Faibussowitsch PetscCall((*setupwithdm)(dm, viewer)); 25298921bdaSJacob Faibussowitsch } else SETERRQ(PetscObjectComm(dm), PETSC_ERR_SUP, "No support for DM type %s", dm->type_name); 2539566063dSJacob Faibussowitsch PetscCall(PetscObjectReference(dm)); 2548135c375SStefano Zampini socket->dm = dm; 2558135c375SStefano Zampini } 2563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2578135c375SStefano Zampini } 2588135c375SStefano Zampini 25934e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDMWindow_Internal(PetscViewer viewer, PetscViewer *view) 260d71ae5a4SJacob Faibussowitsch { 2618135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 2628135c375SStefano Zampini 2638135c375SStefano Zampini PetscFunctionBegin; 2644f572ea9SToby Isaac PetscAssertPointer(view, 2); 2658135c375SStefano Zampini if (!socket->meshwindow) { 2668135c375SStefano Zampini if (socket->type == PETSC_VIEWER_GLVIS_SOCKET) { 2679566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->meshwindow)); 2688135c375SStefano Zampini } else { 26904b79de6SStefano Zampini size_t len; 27004b79de6SStefano Zampini PetscBool isstdout; 27104b79de6SStefano Zampini 2729566063dSJacob Faibussowitsch PetscCall(PetscStrlen(socket->name, &len)); 2739566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout)); 27404b79de6SStefano Zampini if (!socket->name || !len || isstdout) { 2759566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->meshwindow)); 27604b79de6SStefano Zampini } else { 2778135c375SStefano Zampini PetscMPIInt rank; 2788135c375SStefano Zampini char filename[PETSC_MAX_PATH_LEN]; 2799566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 2809566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-mesh.%06d", socket->name, rank)); 2819566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->meshwindow)); 2828135c375SStefano Zampini } 28304b79de6SStefano Zampini } 2841baa6e33SBarry Smith if (socket->meshwindow) PetscCall(PetscViewerPushFormat(socket->meshwindow, PETSC_VIEWER_ASCII_GLVIS)); 2858135c375SStefano Zampini } 2861baa6e33SBarry Smith if (socket->meshwindow) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, socket->meshwindow)); 2878135c375SStefano Zampini *view = socket->meshwindow; 2883ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2898135c375SStefano Zampini } 2908135c375SStefano Zampini 29134e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreDMWindow_Internal(PetscViewer viewer, PetscViewer *view) 292d71ae5a4SJacob Faibussowitsch { 2930286d493SLisandro Dalcin PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 2940286d493SLisandro Dalcin 2950286d493SLisandro Dalcin PetscFunctionBegin; 2964f572ea9SToby Isaac PetscAssertPointer(view, 2); 297cc73adaaSBarry Smith PetscCheck(!*view || *view == socket->meshwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetDMWindow()"); 2980286d493SLisandro Dalcin if (*view) { 2999566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(*view)); 3009566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)viewer)); 3010286d493SLisandro Dalcin } 3020286d493SLisandro Dalcin if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */ 3039566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&socket->meshwindow)); 3040286d493SLisandro Dalcin } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */ 3050286d493SLisandro Dalcin socket->meshwindow = NULL; 3060286d493SLisandro Dalcin } 3070286d493SLisandro Dalcin *view = NULL; 3083ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3090286d493SLisandro Dalcin } 3100286d493SLisandro Dalcin 31134e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetType_Internal(PetscViewer viewer, PetscViewerGLVisType *type) 312d71ae5a4SJacob Faibussowitsch { 3138135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 3148135c375SStefano Zampini 3158135c375SStefano Zampini PetscFunctionBegin; 3164f572ea9SToby Isaac PetscAssertPointer(type, 2); 3178135c375SStefano Zampini *type = socket->type; 3183ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3198135c375SStefano Zampini } 3208135c375SStefano Zampini 3218135c375SStefano Zampini /* This function is only relevant in the SOCKET_GLIVS case. The status is computed the first time it is requested, as GLVis currently has issues when connecting the first time through the socket */ 32234e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetStatus_Internal(PetscViewer viewer, PetscViewerGLVisStatus *sockstatus) 323d71ae5a4SJacob Faibussowitsch { 3248135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 3258135c375SStefano Zampini 3268135c375SStefano Zampini PetscFunctionBegin; 3274f572ea9SToby Isaac PetscAssertPointer(sockstatus, 2); 3288135c375SStefano Zampini if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { 3298135c375SStefano Zampini socket->status = PETSCVIEWERGLVIS_DISCONNECTED; 3308135c375SStefano Zampini } else if (socket->status == PETSCVIEWERGLVIS_DISCONNECTED && socket->nwindow) { 3318135c375SStefano Zampini PetscInt i; 3328135c375SStefano Zampini PetscBool lconn, conn; 3338135c375SStefano Zampini 3348135c375SStefano Zampini for (i = 0, lconn = PETSC_TRUE; i < socket->nwindow; i++) 3359371c9d4SSatish Balay if (!socket->window[i]) lconn = PETSC_FALSE; 3368135c375SStefano Zampini 3371c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&lconn, &conn, 1, MPIU_BOOL, MPI_LAND, PetscObjectComm((PetscObject)viewer))); 3388135c375SStefano Zampini if (conn) socket->status = PETSCVIEWERGLVIS_CONNECTED; 3398135c375SStefano Zampini } 3408135c375SStefano Zampini *sockstatus = socket->status; 3413ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3428135c375SStefano Zampini } 3438135c375SStefano Zampini 34434e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetDM_Internal(PetscViewer viewer, PetscObject *dm) 345d71ae5a4SJacob Faibussowitsch { 3468135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 3478135c375SStefano Zampini 3488135c375SStefano Zampini PetscFunctionBegin; 3498135c375SStefano Zampini *dm = socket->dm; 3503ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3518135c375SStefano Zampini } 3528135c375SStefano Zampini 35334e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetFields_Internal(PetscViewer viewer, PetscInt *nfield, const char **fec[], PetscInt *spacedim[], PetscErrorCode (**g2lfield)(PetscObject, PetscInt, PetscObject[], void *), PetscObject *Ufield[], void **userctx) 354d71ae5a4SJacob Faibussowitsch { 3558135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 3568135c375SStefano Zampini 3578135c375SStefano Zampini PetscFunctionBegin; 3588135c375SStefano Zampini if (nfield) *nfield = socket->nwindow; 3598135c375SStefano Zampini if (fec) *fec = (const char **)socket->fec_type; 3604cac2994SStefano Zampini if (spacedim) *spacedim = socket->spacedim; 3618135c375SStefano Zampini if (g2lfield) *g2lfield = socket->g2lfield; 3628135c375SStefano Zampini if (Ufield) *Ufield = socket->Ufield; 3638135c375SStefano Zampini if (userctx) *userctx = socket->userctx; 3643ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3658135c375SStefano Zampini } 3668135c375SStefano Zampini 3678135c375SStefano Zampini /* accessor routines for the viewer windows: 3688135c375SStefano Zampini PETSC_VIEWER_GLVIS_DUMP : it returns a new viewer every time 3698135c375SStefano Zampini PETSC_VIEWER_GLVIS_SOCKET : it returns the socket, and creates it if not yet done. 3708135c375SStefano Zampini */ 37134e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisGetWindow_Internal(PetscViewer viewer, PetscInt wid, PetscViewer *view) 372d71ae5a4SJacob Faibussowitsch { 3738135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 3748135c375SStefano Zampini PetscViewerGLVisStatus status; 3758135c375SStefano Zampini 3768135c375SStefano Zampini PetscFunctionBegin; 3778135c375SStefano Zampini PetscValidLogicalCollectiveInt(viewer, wid, 2); 3784f572ea9SToby Isaac PetscAssertPointer(view, 3); 3792c71b3e2SJacob Faibussowitsch PetscCheck(wid >= 0 && (wid <= socket->nwindow - 1), PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Cannot get window id %" PetscInt_FMT ": allowed range [0,%" PetscInt_FMT ")", wid, socket->nwindow - 1); 3808135c375SStefano Zampini status = socket->status; 3812c71b3e2SJacob Faibussowitsch if (socket->type == PETSC_VIEWER_GLVIS_DUMP) PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "Window %" PetscInt_FMT " is already in use", wid); 3828135c375SStefano Zampini switch (status) { 3838135c375SStefano Zampini case PETSCVIEWERGLVIS_DISCONNECTED: 3842c71b3e2SJacob Faibussowitsch PetscCheck(!socket->window[wid], PETSC_COMM_SELF, PETSC_ERR_USER, "This should not happen"); 385f7d195e4SLawrence Mitchell if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { 38604b79de6SStefano Zampini size_t len; 38704b79de6SStefano Zampini PetscBool isstdout; 38804b79de6SStefano Zampini 3899566063dSJacob Faibussowitsch PetscCall(PetscStrlen(socket->name, &len)); 3909566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(socket->name, "stdout", &isstdout)); 39104b79de6SStefano Zampini if (!socket->name || !len || isstdout) { 3929566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, "stdout", &socket->window[wid])); 39304b79de6SStefano Zampini } else { 3948135c375SStefano Zampini PetscMPIInt rank; 3958135c375SStefano Zampini char filename[PETSC_MAX_PATH_LEN]; 3968135c375SStefano Zampini 3979566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 3989566063dSJacob Faibussowitsch PetscCall(PetscSNPrintf(filename, PETSC_MAX_PATH_LEN, "%s-%s-%" PetscInt_FMT ".%06d", socket->name, socket->windowtitle[wid], socket->snapid, rank)); 3999566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpen(PETSC_COMM_SELF, filename, &socket->window[wid])); 40004b79de6SStefano Zampini } 4018135c375SStefano Zampini } else { 4029566063dSJacob Faibussowitsch PetscCall(PetscViewerGLVisGetNewWindow_Private(viewer, &socket->window[wid])); 4038135c375SStefano Zampini } 40448a46eb9SPierre Jolivet if (socket->window[wid]) PetscCall(PetscViewerPushFormat(socket->window[wid], PETSC_VIEWER_ASCII_GLVIS)); 4058135c375SStefano Zampini *view = socket->window[wid]; 4068135c375SStefano Zampini break; 407d71ae5a4SJacob Faibussowitsch case PETSCVIEWERGLVIS_CONNECTED: 408d71ae5a4SJacob Faibussowitsch *view = socket->window[wid]; 409d71ae5a4SJacob Faibussowitsch break; 410d71ae5a4SJacob Faibussowitsch case PETSCVIEWERGLVIS_DISABLED: 411d71ae5a4SJacob Faibussowitsch *view = NULL; 412d71ae5a4SJacob Faibussowitsch break; 413d71ae5a4SJacob Faibussowitsch default: 414d71ae5a4SJacob Faibussowitsch SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unhandled socket status %d", (int)status); 4158135c375SStefano Zampini } 4161baa6e33SBarry Smith if (*view) PetscCall(PetscViewerGLVisAttachInfo_Private(viewer, *view)); 4173ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4188135c375SStefano Zampini } 4198135c375SStefano Zampini 4208135c375SStefano Zampini /* Restore the window viewer 4218135c375SStefano Zampini PETSC_VIEWER_GLVIS_DUMP : destroys the temporary created ASCII viewer used for dumping 4228135c375SStefano Zampini PETSC_VIEWER_GLVIS_SOCKET: - if the returned window viewer is not NULL, just zeros the pointer. 4238135c375SStefano Zampini - it the returned window viewer is NULL, assumes something went wrong 4248135c375SStefano Zampini with the socket (i.e. SIGPIPE when a user closes the popup window) 4258135c375SStefano Zampini and that the caller already handled it (see VecView_GLVis). 4268135c375SStefano Zampini */ 42734e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisRestoreWindow_Internal(PetscViewer viewer, PetscInt wid, PetscViewer *view) 428d71ae5a4SJacob Faibussowitsch { 4298135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 4308135c375SStefano Zampini 4318135c375SStefano Zampini PetscFunctionBegin; 43263bd7f81SStefano Zampini PetscValidHeaderSpecificType(viewer, PETSC_VIEWER_CLASSID, 1, PETSCVIEWERGLVIS); 4338135c375SStefano Zampini PetscValidLogicalCollectiveInt(viewer, wid, 2); 4344f572ea9SToby Isaac PetscAssertPointer(view, 3); 435cc73adaaSBarry Smith PetscCheck(wid >= 0 && wid < socket->nwindow, PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Cannot restore window id %" PetscInt_FMT ": allowed range [0,%" PetscInt_FMT ")", wid, socket->nwindow); 436cc73adaaSBarry Smith PetscCheck(!*view || *view == socket->window[wid], PetscObjectComm((PetscObject)viewer), PETSC_ERR_USER, "Viewer was not obtained from PetscViewerGLVisGetWindow()"); 4378135c375SStefano Zampini if (*view) { 4389566063dSJacob Faibussowitsch PetscCall(PetscViewerFlush(*view)); 4399566063dSJacob Faibussowitsch PetscCall(PetscBarrier((PetscObject)viewer)); 4408135c375SStefano Zampini } 4418135c375SStefano Zampini if (socket->type == PETSC_VIEWER_GLVIS_DUMP) { /* destroy the viewer, as it is associated with a single time step */ 4429566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&socket->window[wid])); 4438135c375SStefano Zampini } else if (!*view) { /* something went wrong (SIGPIPE) so we just zero the private pointer */ 4448135c375SStefano Zampini socket->window[wid] = NULL; 4458135c375SStefano Zampini } 4468135c375SStefano Zampini *view = NULL; 4473ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4488135c375SStefano Zampini } 4498135c375SStefano Zampini 4508135c375SStefano Zampini /* default window appearance in the PETSC_VIEWER_GLVIS_SOCKET case */ 45134e79e72SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisInitWindow_Internal(PetscViewer viewer, PetscBool mesh, PetscInt dim, const char *name) 452d71ae5a4SJacob Faibussowitsch { 4538135c375SStefano Zampini PetscViewerGLVisInfo info; 4548135c375SStefano Zampini PetscContainer container; 4558135c375SStefano Zampini 4568135c375SStefano Zampini PetscFunctionBegin; 4579566063dSJacob Faibussowitsch PetscCall(PetscObjectQuery((PetscObject)viewer, "_glvis_info_container", (PetscObject *)&container)); 45828b400f6SJacob Faibussowitsch PetscCheck(container, PETSC_COMM_SELF, PETSC_ERR_USER, "Viewer was not obtained from PetscGLVisViewerGetNewWindow_Private"); 4599566063dSJacob Faibussowitsch PetscCall(PetscContainerGetPointer(container, (void **)&info)); 4603ba16761SJacob Faibussowitsch if (info->init) PetscFunctionReturn(PETSC_SUCCESS); 461fe28a402SLisandro Dalcin 462fe28a402SLisandro Dalcin /* Configure window */ 46348a46eb9SPierre Jolivet if (info->size[0] > 0) PetscCall(PetscViewerASCIIPrintf(viewer, "window_size %" PetscInt_FMT " %" PetscInt_FMT "\n", info->size[0], info->size[1])); 46448a46eb9SPierre Jolivet if (name) PetscCall(PetscViewerASCIIPrintf(viewer, "window_title '%s'\n", name)); 465fe28a402SLisandro Dalcin 466fe28a402SLisandro Dalcin /* Configure default view */ 4678135c375SStefano Zampini if (mesh) { 4688135c375SStefano Zampini switch (dim) { 4698135c375SStefano Zampini case 1: 4709566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */ 4718135c375SStefano Zampini break; 4728135c375SStefano Zampini case 2: 4739566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "keys m\n")); /* show mesh */ 4748135c375SStefano Zampini break; 475d71ae5a4SJacob Faibussowitsch case 3: /* TODO: decide default view in 3D */ 476d71ae5a4SJacob Faibussowitsch break; 4778135c375SStefano Zampini } 4788135c375SStefano Zampini } else { 4799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "keys cm\n")); /* show colorbar and mesh */ 4808135c375SStefano Zampini switch (dim) { 4818135c375SStefano Zampini case 1: 4829566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "keys RRjl\n")); /* set to 1D (side view), turn off perspective and light */ 4838135c375SStefano Zampini break; 4848135c375SStefano Zampini case 2: 4859566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "keys Rjl\n")); /* set to 2D (top view), turn off perspective and light */ 4868135c375SStefano Zampini break; 487d71ae5a4SJacob Faibussowitsch case 3: 488d71ae5a4SJacob Faibussowitsch break; 4898135c375SStefano Zampini } 4909566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIPrintf(viewer, "autoscale value\n")); /* update value-range; keep mesh-extents fixed */ 49173365f8bSLisandro Dalcin } 492fe28a402SLisandro Dalcin 493fe28a402SLisandro Dalcin { /* Additional keys and commands */ 494fe28a402SLisandro Dalcin char keys[256] = "", cmds[2 * PETSC_MAX_PATH_LEN] = ""; 495fe28a402SLisandro Dalcin PetscOptions opt = ((PetscObject)viewer)->options; 496fe28a402SLisandro Dalcin const char *pre = ((PetscObject)viewer)->prefix; 497fe28a402SLisandro Dalcin 4989566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(opt, pre, "-glvis_keys", keys, sizeof(keys), NULL)); 4999566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetString(opt, pre, "-glvis_exec", cmds, sizeof(cmds), NULL)); 5009566063dSJacob Faibussowitsch if (keys[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "keys %s\n", keys)); 5019566063dSJacob Faibussowitsch if (cmds[0]) PetscCall(PetscViewerASCIIPrintf(viewer, "%s\n", cmds)); 5028135c375SStefano Zampini } 503fe28a402SLisandro Dalcin 504fe28a402SLisandro Dalcin /* Pause visualization */ 50548a46eb9SPierre Jolivet if (!mesh && info->pause == -1) PetscCall(PetscViewerASCIIPrintf(viewer, "autopause 1\n")); 50648a46eb9SPierre Jolivet if (!mesh && info->pause == 0) PetscCall(PetscViewerASCIIPrintf(viewer, "pause\n")); 507fe28a402SLisandro Dalcin 5088135c375SStefano Zampini info->init = PETSC_TRUE; 5093ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5108135c375SStefano Zampini } 5118135c375SStefano Zampini 512d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_GLVis(PetscViewer viewer) 513d71ae5a4SJacob Faibussowitsch { 5148135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 5158135c375SStefano Zampini PetscInt i; 5168135c375SStefano Zampini 5178135c375SStefano Zampini PetscFunctionBegin; 5188135c375SStefano Zampini for (i = 0; i < socket->nwindow; i++) { 5199566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&socket->window[i])); 5209566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->windowtitle[i])); 5219566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->fec_type[i])); 5229566063dSJacob Faibussowitsch PetscCall(PetscObjectDestroy(&socket->Ufield[i])); 5238135c375SStefano Zampini } 5249566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->name)); 5259566063dSJacob Faibussowitsch PetscCall(PetscFree5(socket->window, socket->windowtitle, socket->fec_type, socket->spacedim, socket->Ufield)); 5269566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->fmt)); 5279566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(&socket->meshwindow)); 5289566063dSJacob Faibussowitsch PetscCall(PetscObjectDestroy(&socket->dm)); 5299566063dSJacob Faibussowitsch if (socket->destroyctx && socket->userctx) PetscCall((*socket->destroyctx)(socket->userctx)); 5308135c375SStefano Zampini 5319566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", NULL)); 5329566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", NULL)); 5339566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", NULL)); 5349566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL)); 5359566063dSJacob Faibussowitsch PetscCall(PetscFree(socket)); 5368135c375SStefano Zampini viewer->data = NULL; 5373ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5388135c375SStefano Zampini } 5398135c375SStefano Zampini 540d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetFromOptions_GLVis(PetscViewer v, PetscOptionItems *PetscOptionsObject) 541d71ae5a4SJacob Faibussowitsch { 5428135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)v->data; 54373365f8bSLisandro Dalcin PetscInt nsizes = 2, prec = PETSC_DECIDE; 54473365f8bSLisandro Dalcin PetscBool set; 5458135c375SStefano Zampini 5468135c375SStefano Zampini PetscFunctionBegin; 547d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "GLVis PetscViewer Options"); 5489566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-glvis_precision", "Number of digits for floating point values", "PetscViewerGLVisSetPrecision", prec, &prec, &set)); 5499566063dSJacob Faibussowitsch if (set) PetscCall(PetscViewerGLVisSetPrecision(v, prec)); 5509566063dSJacob Faibussowitsch PetscCall(PetscOptionsIntArray("-glvis_size", "Window sizes", NULL, socket->windowsizes, &nsizes, &set)); 55173365f8bSLisandro Dalcin if (set && (nsizes == 1 || socket->windowsizes[1] < 0)) socket->windowsizes[1] = socket->windowsizes[0]; 5529566063dSJacob Faibussowitsch PetscCall(PetscOptionsReal("-glvis_pause", "-1 to pause after each visualization, otherwise sleeps for given seconds", NULL, socket->pause, &socket->pause, NULL)); 553bcee047aSJacob Faibussowitsch PetscCall(PetscOptionsName("-glvis_keys", "Additional keys to configure visualization", NULL, &set)); 554bcee047aSJacob Faibussowitsch PetscCall(PetscOptionsName("-glvis_exec", "Additional commands to configure visualization", NULL, &set)); 555d0609cedSBarry Smith PetscOptionsHeadEnd(); 5563ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5578135c375SStefano Zampini } 5588135c375SStefano Zampini 559d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerFileSetName_GLVis(PetscViewer viewer, const char name[]) 560d71ae5a4SJacob Faibussowitsch { 561bbcf679cSJacob Faibussowitsch char *sport = NULL; 5628135c375SStefano Zampini PetscViewerGLVis socket = (PetscViewerGLVis)viewer->data; 5638135c375SStefano Zampini 5648135c375SStefano Zampini PetscFunctionBegin; 5658135c375SStefano Zampini socket->type = PETSC_VIEWER_GLVIS_DUMP; 5668135c375SStefano Zampini /* we accept localhost^port */ 5679566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->name)); 5689566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &socket->name)); 5699566063dSJacob Faibussowitsch PetscCall(PetscStrchr(socket->name, '^', &sport)); 5708135c375SStefano Zampini if (sport) { 5718135c375SStefano Zampini PetscInt port = 19916; 5728135c375SStefano Zampini size_t len; 5735f80ce2aSJacob Faibussowitsch PetscErrorCode ierr; 5748135c375SStefano Zampini 5758135c375SStefano Zampini *sport++ = 0; 5769566063dSJacob Faibussowitsch PetscCall(PetscStrlen(sport, &len)); 5775f80ce2aSJacob Faibussowitsch ierr = PetscOptionsStringToInt(sport, &port); 5785f80ce2aSJacob Faibussowitsch if (PetscUnlikely(ierr)) { 5798135c375SStefano Zampini socket->port = 19916; 5805f80ce2aSJacob Faibussowitsch } else { 5815f80ce2aSJacob Faibussowitsch socket->port = (port != PETSC_DECIDE && port != PETSC_DEFAULT) ? port : 19916; 5828135c375SStefano Zampini } 5838135c375SStefano Zampini socket->type = PETSC_VIEWER_GLVIS_SOCKET; 5848135c375SStefano Zampini } 5853ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 5868135c375SStefano Zampini } 5878135c375SStefano Zampini 588cc4c1da9SBarry Smith /*@ 589811af0c4SBarry Smith PetscViewerGLVisOpen - Opens a `PETSCVIEWERGLVIS` `PetscViewer` 5908135c375SStefano Zampini 591d1f92df0SBarry Smith Collective; No Fortran Support 5928135c375SStefano Zampini 5938135c375SStefano Zampini Input Parameters: 5948135c375SStefano Zampini + comm - the MPI communicator 595811af0c4SBarry Smith . type - the viewer type: `PETSC_VIEWER_GLVIS_SOCKET` for real-time visualization or `PETSC_VIEWER_GLVIS_DUMP` for dumping to a file 5968135c375SStefano Zampini . name - either the hostname where the GLVis server is running or the base filename for dumping the data for subsequent visualizations 597811af0c4SBarry Smith - port - socket port where the GLVis server is listening. Not referenced when type is `PETSC_VIEWER_GLVIS_DUMP` 5988135c375SStefano Zampini 5992fe279fdSBarry Smith Output Parameter: 6002fe279fdSBarry Smith . viewer - the `PetscViewer` object 6018135c375SStefano Zampini 60273365f8bSLisandro Dalcin Options Database Keys: 603fe28a402SLisandro Dalcin + -glvis_precision <precision> - Sets number of digits for floating point values 604fe28a402SLisandro Dalcin . -glvis_size <width,height> - Sets the window size (in pixels) 60573365f8bSLisandro Dalcin . -glvis_pause <pause> - Sets time (in seconds) that the program pauses after each visualization 606fe28a402SLisandro Dalcin (0 is default, -1 implies every visualization) 607fe28a402SLisandro Dalcin . -glvis_keys - Additional keys to configure visualization 608fe28a402SLisandro Dalcin - -glvis_exec - Additional commands to configure visualization 60973365f8bSLisandro Dalcin 6108135c375SStefano Zampini Level: beginner 6118135c375SStefano Zampini 612d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERGLVIS`, `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerGLVisType` 61373365f8bSLisandro Dalcin @*/ 614d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerGLVisOpen(MPI_Comm comm, PetscViewerGLVisType type, const char name[], PetscInt port, PetscViewer *viewer) 615d71ae5a4SJacob Faibussowitsch { 6168135c375SStefano Zampini PetscViewerGLVis socket; 6178135c375SStefano Zampini 6188135c375SStefano Zampini PetscFunctionBegin; 6199566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, viewer)); 6209566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERGLVIS)); 6218135c375SStefano Zampini 6228135c375SStefano Zampini socket = (PetscViewerGLVis)((*viewer)->data); 623a7bda6aaSStefano Zampini socket->type = type; 624a7bda6aaSStefano Zampini if (type == PETSC_VIEWER_GLVIS_DUMP || name) { 6259566063dSJacob Faibussowitsch PetscCall(PetscFree(socket->name)); 6269566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(name, &socket->name)); 627a7bda6aaSStefano Zampini } 628a7bda6aaSStefano Zampini socket->port = (!port || port == PETSC_DETERMINE || port == PETSC_DECIDE) ? 19916 : port; 6298135c375SStefano Zampini 6309566063dSJacob Faibussowitsch PetscCall(PetscViewerSetFromOptions(*viewer)); 6313ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 6328135c375SStefano Zampini } 6338135c375SStefano Zampini 634d1f92df0SBarry Smith /*@C 635811af0c4SBarry Smith PETSC_VIEWER_GLVIS_ - Creates a `PETSCVIEWERGLVIS` `PetscViewer` shared by all processors in a communicator. 6368135c375SStefano Zampini 637d1f92df0SBarry Smith Collective; No Fortran Support 6388135c375SStefano Zampini 6398135c375SStefano Zampini Input Parameter: 640811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERGLVIS` `PetscViewer` 6418135c375SStefano Zampini 6428135c375SStefano Zampini Environmental variables: 643d1f92df0SBarry Smith + `PETSC_VIEWER_GLVIS_FILENAME` - output filename (if specified dump to disk, and takes precedence on `PETSC_VIEWER_GLVIS_HOSTNAME`) 644d1f92df0SBarry Smith . `PETSC_VIEWER_GLVIS_HOSTNAME` - machine where the GLVis server is listening (defaults to localhost) 645d1f92df0SBarry Smith - `PETSC_VIEWER_GLVIS_PORT` - port opened by the GLVis server (defaults to 19916) 646d1f92df0SBarry Smith 647d1f92df0SBarry Smith Level: intermediate 6488135c375SStefano Zampini 649811af0c4SBarry Smith Note: 650811af0c4SBarry Smith Unlike almost all other PETSc routines, `PETSC_VIEWER_GLVIS_()` does not return 651811af0c4SBarry Smith an error code. It is usually used in the form 652*648c30bcSBarry Smith .vb 653*648c30bcSBarry Smith XXXView(XXX object, PETSC_VIEWER_GLVIS_(comm)); 654*648c30bcSBarry Smith .ve 655*648c30bcSBarry Smith 656*648c30bcSBarry Smith Developer Note: 657*648c30bcSBarry Smith How come this viewer is not stashed as an attribute in the MPI communicator? 6588135c375SStefano Zampini 659d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERGLVIS`, `PetscViewer`, `PetscViewerGLVISOpen()`, `PetscViewerGLVisType`, `PetscViewerCreate()`, `PetscViewerDestroy()` 660d1f92df0SBarry Smith @*/ 661d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_GLVIS_(MPI_Comm comm) 662d71ae5a4SJacob Faibussowitsch { 6638135c375SStefano Zampini PetscBool flg; 6648135c375SStefano Zampini PetscViewer viewer; 6658135c375SStefano Zampini PetscViewerGLVisType type; 6668135c375SStefano Zampini char fname[PETSC_MAX_PATH_LEN], sport[16]; 6678135c375SStefano Zampini PetscInt port = 19916; /* default for GLVis */ 6688135c375SStefano Zampini 6698135c375SStefano Zampini PetscFunctionBegin; 670*648c30bcSBarry Smith PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_FILENAME", fname, PETSC_MAX_PATH_LEN, &flg)); 6718135c375SStefano Zampini if (!flg) { 6728135c375SStefano Zampini type = PETSC_VIEWER_GLVIS_SOCKET; 673*648c30bcSBarry Smith PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_HOSTNAME", fname, PETSC_MAX_PATH_LEN, &flg)); 674*648c30bcSBarry Smith if (!flg) { PetscCallNull(PetscStrncpy(fname, "localhost", sizeof(fname))); } 675*648c30bcSBarry Smith PetscCallNull(PetscOptionsGetenv(comm, "PETSC_VIEWER_GLVIS_PORT", sport, 16, &flg)); 676*648c30bcSBarry Smith if (flg) { PetscCallNull(PetscOptionsStringToInt(sport, &port)); } 6778135c375SStefano Zampini } else { 6788135c375SStefano Zampini type = PETSC_VIEWER_GLVIS_DUMP; 6798135c375SStefano Zampini } 680*648c30bcSBarry Smith PetscCallNull(PetscViewerGLVisOpen(comm, type, fname, port, &viewer)); 681*648c30bcSBarry Smith PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer)); 6828135c375SStefano Zampini PetscFunctionReturn(viewer); 6838135c375SStefano Zampini } 6848135c375SStefano Zampini 685d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_GLVis(PetscViewer viewer) 686d71ae5a4SJacob Faibussowitsch { 6878135c375SStefano Zampini PetscViewerGLVis socket; 6888135c375SStefano Zampini 6898135c375SStefano Zampini PetscFunctionBegin; 6904dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&socket)); 6918135c375SStefano Zampini 6928135c375SStefano Zampini /* defaults to socket viewer */ 6939566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy("localhost", &socket->name)); 6948135c375SStefano Zampini socket->port = 19916; /* GLVis default listening port */ 6958135c375SStefano Zampini socket->type = PETSC_VIEWER_GLVIS_SOCKET; 6968135c375SStefano Zampini socket->pause = 0; /* just pause the first time */ 6978135c375SStefano Zampini 69873365f8bSLisandro Dalcin socket->windowsizes[0] = 600; 69973365f8bSLisandro Dalcin socket->windowsizes[1] = 600; 70073365f8bSLisandro Dalcin 70177eacf09SStefano Zampini /* defaults to full precision */ 7029566063dSJacob Faibussowitsch PetscCall(PetscStrallocpy(" %g", &socket->fmt)); 70377eacf09SStefano Zampini 7048135c375SStefano Zampini viewer->data = (void *)socket; 7058135c375SStefano Zampini viewer->ops->destroy = PetscViewerDestroy_GLVis; 7068135c375SStefano Zampini viewer->ops->setfromoptions = PetscViewerSetFromOptions_GLVis; 7078135c375SStefano Zampini 7089566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetPrecision_C", PetscViewerGLVisSetPrecision_GLVis)); 7099566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetSnapId_C", PetscViewerGLVisSetSnapId_GLVis)); 7109566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerGLVisSetFields_C", PetscViewerGLVisSetFields_GLVis)); 7119566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_GLVis)); 7123ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7138135c375SStefano Zampini } 7148135c375SStefano Zampini 7158135c375SStefano Zampini /* this is a private implementation of a SOCKET with ASCII data format 7168135c375SStefano Zampini GLVis does not currently handle binary socket streams */ 7178135c375SStefano Zampini #if defined(PETSC_HAVE_UNISTD_H) 7188135c375SStefano Zampini #include <unistd.h> 7198135c375SStefano Zampini #endif 7208135c375SStefano Zampini 7216524c165SJacob Faibussowitsch #ifndef PETSC_HAVE_WINDOWS_H 7228135c375SStefano Zampini static PetscErrorCode (*PetscViewerDestroy_ASCII)(PetscViewer); 7238135c375SStefano Zampini 724d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_ASCII_Socket(PetscViewer viewer) 725d71ae5a4SJacob Faibussowitsch { 7268135c375SStefano Zampini FILE *stream; 727d0609cedSBarry Smith 7288135c375SStefano Zampini PetscFunctionBegin; 7299566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetPointer(viewer, &stream)); 7308135c375SStefano Zampini if (stream) { 73140fde1d9SLisandro Dalcin int retv = fclose(stream); 73240fde1d9SLisandro Dalcin PetscCheck(!retv, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on stream"); 7338135c375SStefano Zampini } 7349566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy_ASCII(viewer)); 7353ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7368135c375SStefano Zampini } 73727e89126SStefano Zampini #endif 73811a4995dSStefano Zampini 7392da53a5bSBarry Smith /* 7402da53a5bSBarry Smith This attempts to return a NULL viewer if it is unable to open a socket connection. 7412da53a5bSBarry Smith 7422da53a5bSBarry Smith The code below involving PetscUnlikely(ierr) is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc. 7432da53a5bSBarry Smith 7442da53a5bSBarry Smith The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain failure conditions but instead either return a special value 7452da53a5bSBarry Smith of fd to indicate it was impossible to open the socket, or add another return argument to it indicating the socket was not opened. 7462da53a5bSBarry Smith */ 747d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerASCIISocketOpen(MPI_Comm comm, const char *hostname, PetscInt port, PetscViewer *viewer) 748d71ae5a4SJacob Faibussowitsch { 749150de0cbSStefano Zampini #if defined(PETSC_HAVE_WINDOWS_H) 75027e89126SStefano Zampini PetscFunctionBegin; 75127e89126SStefano Zampini SETERRQ(comm, PETSC_ERR_SUP, "Not implemented for Windows"); 75227e89126SStefano Zampini #else 7538135c375SStefano Zampini FILE *stream = NULL; 754178bdba8SJose E. Roman int fd = 0; 7558135c375SStefano Zampini PetscErrorCode ierr; 7568135c375SStefano Zampini 7578135c375SStefano Zampini PetscFunctionBegin; 7584f572ea9SToby Isaac PetscAssertPointer(hostname, 2); 7594f572ea9SToby Isaac PetscAssertPointer(viewer, 4); 760c891a504SStefano Zampini #if defined(PETSC_USE_SOCKET_VIEWER) 7618135c375SStefano Zampini ierr = PetscOpenSocket(hostname, port, &fd); 762c891a504SStefano Zampini #else 763c891a504SStefano Zampini SETERRQ(comm, PETSC_ERR_SUP, "Missing Socket viewer"); 764c891a504SStefano Zampini #endif 7652da53a5bSBarry Smith /* 7662da53a5bSBarry Smith The following code is illegal in PETSc, one can NEVER attempt to recover once an error is initiated in PETSc. 7672da53a5bSBarry Smith The correct approach is to refactor PetscOpenSocket() to not initiate an error under certain conditions but instead either return a special value 7682da53a5bSBarry 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. 7692da53a5bSBarry Smith */ 7703ca90d2dSJacob Faibussowitsch if (PetscUnlikely(ierr)) { 7719d3446b2SPierre Jolivet PetscCall(PetscInfo(NULL, "Cannot connect to socket on %s:%" PetscInt_FMT ". Socket visualization is disabled\n", hostname, port)); 7728135c375SStefano Zampini *viewer = NULL; 7733ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7748135c375SStefano Zampini } else { 7759d3446b2SPierre Jolivet PetscCall(PetscInfo(NULL, "Successfully connect to socket on %s:%" PetscInt_FMT ". Socket visualization is enabled\n", hostname, port)); 7768135c375SStefano Zampini } 7778135c375SStefano Zampini stream = fdopen(fd, "w"); /* Not possible on Windows */ 77828b400f6SJacob Faibussowitsch PetscCheck(stream, PETSC_COMM_SELF, PETSC_ERR_SYS, "Cannot open stream from socket %s:%" PetscInt_FMT, hostname, port); 7799566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIOpenWithFILE(PETSC_COMM_SELF, stream, viewer)); 7808135c375SStefano Zampini PetscViewerDestroy_ASCII = (*viewer)->ops->destroy; 7818135c375SStefano Zampini (*viewer)->ops->destroy = PetscViewerDestroy_ASCII_Socket; 78227e89126SStefano Zampini #endif 7833ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 7848135c375SStefano Zampini } 7850286d493SLisandro Dalcin 7860286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIGPIPE) 7870286d493SLisandro Dalcin 7880286d493SLisandro Dalcin #include <signal.h> 7890286d493SLisandro Dalcin 7900286d493SLisandro Dalcin #if defined(PETSC_HAVE_WINDOWS_H) 7910286d493SLisandro Dalcin #define PETSC_DEVNULL "NUL" 7920286d493SLisandro Dalcin #else 7930286d493SLisandro Dalcin #define PETSC_DEVNULL "/dev/null" 7940286d493SLisandro Dalcin #endif 7950286d493SLisandro Dalcin 7960286d493SLisandro Dalcin static volatile PetscBool PetscGLVisBrokenPipe = PETSC_FALSE; 7970286d493SLisandro Dalcin 7980286d493SLisandro Dalcin static void (*PetscGLVisSigHandler_save)(int) = NULL; 7990286d493SLisandro Dalcin 800d71ae5a4SJacob Faibussowitsch static void PetscGLVisSigHandler_SIGPIPE(PETSC_UNUSED int sig) 801d71ae5a4SJacob Faibussowitsch { 8020286d493SLisandro Dalcin PetscGLVisBrokenPipe = PETSC_TRUE; 8030286d493SLisandro Dalcin #if !defined(PETSC_MISSING_SIG_IGN) 8040286d493SLisandro Dalcin signal(SIGPIPE, SIG_IGN); 8050286d493SLisandro Dalcin #endif 8060286d493SLisandro Dalcin } 8070286d493SLisandro Dalcin 808d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) 809d71ae5a4SJacob Faibussowitsch { 8100286d493SLisandro Dalcin PetscFunctionBegin; 81128b400f6SJacob Faibussowitsch PetscCheck(!PetscGLVisSigHandler_save, comm, PETSC_ERR_PLIB, "Nested call to %s()", PETSC_FUNCTION_NAME); 8120286d493SLisandro Dalcin PetscGLVisBrokenPipe = PETSC_FALSE; 8130286d493SLisandro Dalcin PetscGLVisSigHandler_save = signal(SIGPIPE, PetscGLVisSigHandler_SIGPIPE); 8143ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8150286d493SLisandro Dalcin } 8160286d493SLisandro Dalcin 817d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(MPI_Comm comm, PetscViewer *win) 818d71ae5a4SJacob Faibussowitsch { 8190286d493SLisandro Dalcin PetscBool flag, brokenpipe; 8200286d493SLisandro Dalcin 8210286d493SLisandro Dalcin PetscFunctionBegin; 8220286d493SLisandro Dalcin flag = PetscGLVisBrokenPipe; 8231c2dc1cbSBarry Smith PetscCall(MPIU_Allreduce(&flag, &brokenpipe, 1, MPIU_BOOL, MPI_LOR, comm)); 8240286d493SLisandro Dalcin if (brokenpipe) { 8250286d493SLisandro Dalcin FILE *sock, *null = fopen(PETSC_DEVNULL, "w"); 8269566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIIGetPointer(*win, &sock)); 8279566063dSJacob Faibussowitsch PetscCall(PetscViewerASCIISetFILE(*win, null)); 8289566063dSJacob Faibussowitsch PetscCall(PetscViewerDestroy(win)); 8290286d493SLisandro Dalcin if (sock) (void)fclose(sock); 8300286d493SLisandro Dalcin } 8310286d493SLisandro Dalcin (void)signal(SIGPIPE, PetscGLVisSigHandler_save); 8320286d493SLisandro Dalcin PetscGLVisSigHandler_save = NULL; 8330286d493SLisandro Dalcin PetscGLVisBrokenPipe = PETSC_FALSE; 8343ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8350286d493SLisandro Dalcin } 8360286d493SLisandro Dalcin 8370286d493SLisandro Dalcin #else 8380286d493SLisandro Dalcin 839d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveBegin(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) 840d71ae5a4SJacob Faibussowitsch { 8410286d493SLisandro Dalcin PetscFunctionBegin; 8423ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8430286d493SLisandro Dalcin } 8440286d493SLisandro Dalcin 845d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscGLVisCollectiveEnd(PETSC_UNUSED MPI_Comm comm, PETSC_UNUSED PetscViewer *win) 846d71ae5a4SJacob Faibussowitsch { 8470286d493SLisandro Dalcin PetscFunctionBegin; 8483ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 8490286d493SLisandro Dalcin } 8500286d493SLisandro Dalcin 8510286d493SLisandro Dalcin #endif 852