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