1cc4c1da9SBarry Smith #include <petscsys.h> /*I "petscviewer.h" I*/
25c6c1daeSBarry Smith
35c6c1daeSBarry Smith #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS)
45c6c1daeSBarry Smith /* Some systems have inconsistent include files that use but do not
55c6c1daeSBarry Smith ensure that the following definitions are made */
65c6c1daeSBarry Smith typedef unsigned char u_char;
75c6c1daeSBarry Smith typedef unsigned short u_short;
85c6c1daeSBarry Smith typedef unsigned short ushort;
95c6c1daeSBarry Smith typedef unsigned int u_int;
105c6c1daeSBarry Smith typedef unsigned long u_long;
115c6c1daeSBarry Smith #endif
125c6c1daeSBarry Smith
135c6c1daeSBarry Smith #include <errno.h>
145c6c1daeSBarry Smith #include <ctype.h>
155c6c1daeSBarry Smith #if defined(PETSC_HAVE_MACHINE_ENDIAN_H)
165c6c1daeSBarry Smith #include <machine/endian.h>
175c6c1daeSBarry Smith #endif
185c6c1daeSBarry Smith #if defined(PETSC_HAVE_UNISTD_H)
195c6c1daeSBarry Smith #include <unistd.h>
205c6c1daeSBarry Smith #endif
215c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_SOCKET_H)
225c6c1daeSBarry Smith #include <sys/socket.h>
235c6c1daeSBarry Smith #endif
245c6c1daeSBarry Smith #if defined(PETSC_HAVE_SYS_WAIT_H)
255c6c1daeSBarry Smith #include <sys/wait.h>
265c6c1daeSBarry Smith #endif
275c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETINET_IN_H)
285c6c1daeSBarry Smith #include <netinet/in.h>
295c6c1daeSBarry Smith #endif
305c6c1daeSBarry Smith #if defined(PETSC_HAVE_NETDB_H)
315c6c1daeSBarry Smith #include <netdb.h>
325c6c1daeSBarry Smith #endif
335c6c1daeSBarry Smith #if defined(PETSC_HAVE_FCNTL_H)
345c6c1daeSBarry Smith #include <fcntl.h>
355c6c1daeSBarry Smith #endif
365c6c1daeSBarry Smith #if defined(PETSC_HAVE_IO_H)
375c6c1daeSBarry Smith #include <io.h>
385c6c1daeSBarry Smith #endif
395c6c1daeSBarry Smith #if defined(PETSC_HAVE_WINSOCK2_H)
405c6c1daeSBarry Smith #include <Winsock2.h>
415c6c1daeSBarry Smith #endif
425c6c1daeSBarry Smith #include <sys/stat.h>
435c6c1daeSBarry Smith #include <../src/sys/classes/viewer/impls/socket/socket.h>
445c6c1daeSBarry Smith
455c6c1daeSBarry Smith #if defined(PETSC_NEED_CLOSE_PROTO)
468cc058d9SJed Brown PETSC_EXTERN int close(int);
475c6c1daeSBarry Smith #endif
485c6c1daeSBarry Smith #if defined(PETSC_NEED_SOCKET_PROTO)
498cc058d9SJed Brown PETSC_EXTERN int socket(int, int, int);
505c6c1daeSBarry Smith #endif
515c6c1daeSBarry Smith #if defined(PETSC_NEED_SLEEP_PROTO)
528cc058d9SJed Brown PETSC_EXTERN int sleep(unsigned);
535c6c1daeSBarry Smith #endif
545c6c1daeSBarry Smith #if defined(PETSC_NEED_CONNECT_PROTO)
558cc058d9SJed Brown PETSC_EXTERN int connect(int, struct sockaddr *, int);
565c6c1daeSBarry Smith #endif
575c6c1daeSBarry Smith
PetscViewerDestroy_Socket(PetscViewer viewer)58d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer)
59d71ae5a4SJacob Faibussowitsch {
605c6c1daeSBarry Smith PetscViewer_Socket *vmatlab = (PetscViewer_Socket *)viewer->data;
615c6c1daeSBarry Smith
625c6c1daeSBarry Smith PetscFunctionBegin;
635c6c1daeSBarry Smith if (vmatlab->port) {
643ba16761SJacob Faibussowitsch int ierr;
653ba16761SJacob Faibussowitsch
665c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
675c6c1daeSBarry Smith ierr = closesocket(vmatlab->port);
685c6c1daeSBarry Smith #else
695c6c1daeSBarry Smith ierr = close(vmatlab->port);
705c6c1daeSBarry Smith #endif
7128b400f6SJacob Faibussowitsch PetscCheck(!ierr, PETSC_COMM_SELF, PETSC_ERR_SYS, "System error closing socket");
725c6c1daeSBarry Smith }
739566063dSJacob Faibussowitsch PetscCall(PetscFree(vmatlab));
742e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinarySetSkipHeader_C", NULL));
752e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetSkipHeader_C", NULL));
762e956fe4SStefano Zampini PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerBinaryGetFlowControl_C", NULL));
773ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
785c6c1daeSBarry Smith }
795c6c1daeSBarry Smith
80cc4c1da9SBarry Smith /*@
81aec76313SJacob Faibussowitsch PetscOpenSocket - handles connected to an open port where someone is waiting.
825c6c1daeSBarry Smith
834683183fSBarry Smith Input Parameters:
84aec76313SJacob Faibussowitsch + hostname - for example www.mcs.anl.gov
854683183fSBarry Smith - portnum - for example 80
864683183fSBarry Smith
8701d2d390SJose E. Roman Output Parameter:
884683183fSBarry Smith . t - the socket number
894683183fSBarry Smith
9095452b02SPatrick Sanan Notes:
9195452b02SPatrick Sanan Use close() to close the socket connection
924683183fSBarry Smith
93811af0c4SBarry Smith Use read() or `PetscHTTPRequest()` to read from the socket
944683183fSBarry Smith
954683183fSBarry Smith Level: advanced
964683183fSBarry Smith
97db781477SPatrick Sanan .seealso: `PetscSocketListen()`, `PetscSocketEstablish()`, `PetscHTTPRequest()`, `PetscHTTPSConnect()`
984683183fSBarry Smith @*/
PetscOpenSocket(const char hostname[],int portnum,int * t)99d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscOpenSocket(const char hostname[], int portnum, int *t)
100d71ae5a4SJacob Faibussowitsch {
1015c6c1daeSBarry Smith struct sockaddr_in sa;
1025c6c1daeSBarry Smith struct hostent *hp;
1035c6c1daeSBarry Smith int s = 0;
1045c6c1daeSBarry Smith PetscBool flg = PETSC_TRUE;
1054a285bdaSBarry Smith static int refcnt = 0;
1065c6c1daeSBarry Smith
1075c6c1daeSBarry Smith PetscFunctionBegin;
1085c6c1daeSBarry Smith if (!(hp = gethostbyname(hostname))) {
1095c6c1daeSBarry Smith perror("SEND: error gethostbyname: ");
11098921bdaSJacob Faibussowitsch SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error open connection to %s", hostname);
1115c6c1daeSBarry Smith }
1129566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&sa, sizeof(sa)));
1139566063dSJacob Faibussowitsch PetscCall(PetscMemcpy(&sa.sin_addr, hp->h_addr_list[0], hp->h_length));
1145c6c1daeSBarry Smith
1156497c311SBarry Smith sa.sin_family = (unsigned char)hp->h_addrtype;
1165c6c1daeSBarry Smith sa.sin_port = htons((u_short)portnum);
1175c6c1daeSBarry Smith while (flg) {
1185c6c1daeSBarry Smith if ((s = socket(hp->h_addrtype, SOCK_STREAM, 0)) < 0) {
1199371c9d4SSatish Balay perror("SEND: error socket");
1209371c9d4SSatish Balay SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
1215c6c1daeSBarry Smith }
1225c6c1daeSBarry Smith if (connect(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
1235c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
1245c6c1daeSBarry Smith ierr = WSAGetLastError();
125a297a907SKarl Rupp if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n");
126a297a907SKarl Rupp else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
127a297a907SKarl Rupp else if (ierr == WSAEISCONN) {
1285c6c1daeSBarry Smith (*PetscErrorPrintf)("SEND: socket already connected\n");
1295c6c1daeSBarry Smith Sleep((unsigned)1);
1305c6c1daeSBarry Smith } else if (ierr == WSAECONNREFUSED) {
1315c6c1daeSBarry Smith /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */
1325c6c1daeSBarry Smith Sleep((unsigned)1);
1335c6c1daeSBarry Smith } else {
1349371c9d4SSatish Balay perror(NULL);
1359371c9d4SSatish Balay SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
1365c6c1daeSBarry Smith }
1375c6c1daeSBarry Smith #else
1383ba16761SJacob Faibussowitsch if (errno == EADDRINUSE) {
1393ba16761SJacob Faibussowitsch PetscErrorCode ierr = (*PetscErrorPrintf)("SEND: address is in use\n");
1403ba16761SJacob Faibussowitsch (void)ierr;
1413ba16761SJacob Faibussowitsch } else if (errno == EALREADY) {
1423ba16761SJacob Faibussowitsch PetscErrorCode ierr = (*PetscErrorPrintf)("SEND: socket is non-blocking \n");
1433ba16761SJacob Faibussowitsch (void)ierr;
1443ba16761SJacob Faibussowitsch } else if (errno == EISCONN) {
1453ba16761SJacob Faibussowitsch PetscErrorCode ierr = (*PetscErrorPrintf)("SEND: socket already connected\n");
1463ba16761SJacob Faibussowitsch (void)ierr;
1475c6c1daeSBarry Smith sleep((unsigned)1);
1485c6c1daeSBarry Smith } else if (errno == ECONNREFUSED) {
1494a285bdaSBarry Smith refcnt++;
15008401ef6SPierre Jolivet PetscCheck(refcnt <= 5, PETSC_COMM_SELF, PETSC_ERR_SYS, "Connection refused by remote host %s port %d", hostname, portnum);
1519566063dSJacob Faibussowitsch PetscCall(PetscInfo(NULL, "Connection refused in attaching socket, trying again\n"));
1525c6c1daeSBarry Smith sleep((unsigned)1);
1535c6c1daeSBarry Smith } else {
1549371c9d4SSatish Balay perror(NULL);
1559371c9d4SSatish Balay SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "system error");
1565c6c1daeSBarry Smith }
1575c6c1daeSBarry Smith #endif
1585c6c1daeSBarry Smith flg = PETSC_TRUE;
1595c6c1daeSBarry Smith #if defined(PETSC_HAVE_CLOSESOCKET)
1605c6c1daeSBarry Smith closesocket(s);
1615c6c1daeSBarry Smith #else
1625c6c1daeSBarry Smith close(s);
1635c6c1daeSBarry Smith #endif
164a297a907SKarl Rupp } else flg = PETSC_FALSE;
1655c6c1daeSBarry Smith }
1665c6c1daeSBarry Smith *t = s;
1673ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
1685c6c1daeSBarry Smith }
1695c6c1daeSBarry Smith
17010450e9eSJacob Faibussowitsch /*
1715c6c1daeSBarry Smith PetscSocketEstablish - starts a listener on a socket
1725c6c1daeSBarry Smith
1732fe279fdSBarry Smith Input Parameter:
1744683183fSBarry Smith . portnumber - the port to wait at
1754683183fSBarry Smith
1762fe279fdSBarry Smith Output Parameter:
177811af0c4SBarry Smith . ss - the socket to be used with `PetscSocketListen()`
1784683183fSBarry Smith
1794683183fSBarry Smith Level: advanced
1804683183fSBarry Smith
181db781477SPatrick Sanan .seealso: `PetscSocketListen()`, `PetscOpenSocket()`
18210450e9eSJacob Faibussowitsch */
PetscSocketEstablish(int portnum,int * ss)18310450e9eSJacob Faibussowitsch static PetscErrorCode PetscSocketEstablish(int portnum, int *ss)
184d71ae5a4SJacob Faibussowitsch {
185d1ea7ff4SJose E. Roman char myname[PETSC_MAX_OPTION_NAME];
1865c6c1daeSBarry Smith int s;
1875c6c1daeSBarry Smith struct sockaddr_in sa;
1885c6c1daeSBarry Smith struct hostent *hp;
1895c6c1daeSBarry Smith
1905c6c1daeSBarry Smith PetscFunctionBegin;
1919566063dSJacob Faibussowitsch PetscCall(PetscGetHostName(myname, sizeof(myname)));
1925c6c1daeSBarry Smith
1939566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&sa, sizeof(struct sockaddr_in)));
1945c6c1daeSBarry Smith
1955c6c1daeSBarry Smith hp = gethostbyname(myname);
19628b400f6SJacob Faibussowitsch PetscCheck(hp, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to get hostent information from system");
1975c6c1daeSBarry Smith
1986497c311SBarry Smith sa.sin_family = (unsigned char)hp->h_addrtype;
1995c6c1daeSBarry Smith sa.sin_port = htons((u_short)portnum);
2005c6c1daeSBarry Smith
201cc73adaaSBarry Smith PetscCheck((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Error running socket() command");
2025c6c1daeSBarry Smith #if defined(PETSC_HAVE_SO_REUSEADDR)
2035c6c1daeSBarry Smith {
2045c6c1daeSBarry Smith int optval = 1; /* Turn on the option */
2053ba16761SJacob Faibussowitsch int ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval));
2063ba16761SJacob Faibussowitsch PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "setsockopt() failed with error code %d", ret);
2075c6c1daeSBarry Smith }
2085c6c1daeSBarry Smith #endif
2095c6c1daeSBarry Smith
2105c6c1daeSBarry Smith while (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) {
2115c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR)
2125c6c1daeSBarry Smith ierr = WSAGetLastError();
2135c6c1daeSBarry Smith if (ierr != WSAEADDRINUSE) {
2145c6c1daeSBarry Smith #else
2155c6c1daeSBarry Smith if (errno != EADDRINUSE) {
2165c6c1daeSBarry Smith #endif
2175c6c1daeSBarry Smith close(s);
2185c6c1daeSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "Error from bind()");
2195c6c1daeSBarry Smith }
2205c6c1daeSBarry Smith }
2215c6c1daeSBarry Smith listen(s, 0);
2225c6c1daeSBarry Smith *ss = s;
2233ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2245c6c1daeSBarry Smith }
2255c6c1daeSBarry Smith
22610450e9eSJacob Faibussowitsch /*
227811af0c4SBarry Smith PetscSocketListen - Listens at a socket created with `PetscSocketEstablish()`
2284683183fSBarry Smith
2294683183fSBarry Smith Input Parameter:
230811af0c4SBarry Smith . listenport - obtained with `PetscSocketEstablish()`
2314683183fSBarry Smith
2324683183fSBarry Smith Output Parameter:
2334683183fSBarry Smith . t - pass this to read() to read what is passed to this connection
2344683183fSBarry Smith
2354683183fSBarry Smith Level: advanced
2365c6c1daeSBarry Smith
237db781477SPatrick Sanan .seealso: `PetscSocketEstablish()`
23810450e9eSJacob Faibussowitsch */
23910450e9eSJacob Faibussowitsch static PetscErrorCode PetscSocketListen(int listenport, int *t)
240d71ae5a4SJacob Faibussowitsch {
2415c6c1daeSBarry Smith struct sockaddr_in isa;
2425c6c1daeSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T)
2435c6c1daeSBarry Smith size_t i;
2445c6c1daeSBarry Smith #else
2455c6c1daeSBarry Smith int i;
2465c6c1daeSBarry Smith #endif
2475c6c1daeSBarry Smith
2485c6c1daeSBarry Smith PetscFunctionBegin;
2495c6c1daeSBarry Smith /* wait for someone to try to connect */
2505c6c1daeSBarry Smith i = sizeof(struct sockaddr_in);
251cc73adaaSBarry Smith PetscCheck((*t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "error from accept()");
2523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
2535c6c1daeSBarry Smith }
2545c6c1daeSBarry Smith
25510450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'"
25610450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown
257cc4c1da9SBarry Smith /*@
258a30fc760SBarry Smith PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server.
2595c6c1daeSBarry Smith
260d083f849SBarry Smith Collective
2615c6c1daeSBarry Smith
2625c6c1daeSBarry Smith Input Parameters:
2635c6c1daeSBarry Smith + comm - the MPI communicator
2643f423023SBarry Smith . machine - the machine the server is running on, use `NULL` for the local machine, use "server" to passively wait for
2655c6c1daeSBarry Smith a connection from elsewhere
266811af0c4SBarry Smith - port - the port to connect to, use `PETSC_DEFAULT` for the default
2675c6c1daeSBarry Smith
2685c6c1daeSBarry Smith Output Parameter:
2695c6c1daeSBarry Smith . lab - a context to use when communicating with the server
2705c6c1daeSBarry Smith
271811af0c4SBarry Smith Options Database Keys:
272811af0c4SBarry Smith For use with `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`,
273811af0c4SBarry Smith `PETSC_VIEWER_SOCKET_()` or if
2743f423023SBarry Smith `NULL` is passed for machine or PETSC_DEFAULT is passed for port
2753f423023SBarry Smith + -viewer_socket_machine <machine> - the machine where the socket is available
276f332b1cbSPierre Jolivet - -viewer_socket_port <port> - the socket to connect to
277811af0c4SBarry Smith
278811af0c4SBarry Smith Environmental variables:
2793f423023SBarry Smith + `PETSC_VIEWER_SOCKET_MACHINE` - machine name
2803f423023SBarry Smith - `PETSC_VIEWER_SOCKET_PORT` - portnumber
281811af0c4SBarry Smith
2825c6c1daeSBarry Smith Level: intermediate
2835c6c1daeSBarry Smith
2845c6c1daeSBarry Smith Notes:
2855c6c1daeSBarry Smith Most users should employ the following commands to access the
286811af0c4SBarry Smith MATLAB `PetscViewer`
2873f423023SBarry Smith .vb
2883f423023SBarry Smith
2893f423023SBarry Smith PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer)
2903f423023SBarry Smith MatView(Mat matrix,PetscViewer viewer)
2913f423023SBarry Smith .ve
2923f423023SBarry Smith or
2933f423023SBarry Smith .vb
2943f423023SBarry Smith PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer)
2953f423023SBarry Smith VecView(Vec vector,PetscViewer viewer)
2963f423023SBarry Smith .ve
2975c6c1daeSBarry Smith
298750b007cSBarry Smith Currently the only socket client available is MATLAB, PETSc must be configured with --with-matlab for this client. See
299c4762a1bSJed Brown src/dm/tests/ex12.c and ex12.m for an example of usage.
3005c6c1daeSBarry Smith
30195452b02SPatrick Sanan The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket
302811af0c4SBarry Smith use `PetscViewerBinaryRead()`, `PetscViewerBinaryWrite()`, `PetscViewerBinarWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`.
303a30fc760SBarry Smith
304811af0c4SBarry Smith Use this for communicating with an interactive MATLAB session, see `PETSC_VIEWER_MATLAB_()` for writing output to a
305811af0c4SBarry Smith .mat file. Use `PetscMatlabEngineCreate()` or `PETSC_MATLAB_ENGINE_()`, `PETSC_MATLAB_ENGINE_SELF`, or `PETSC_MATLAB_ENGINE_WORLD`
306a30fc760SBarry Smith for communicating with a MATLAB Engine
3075c6c1daeSBarry Smith
308d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSCVIEWERSOCKET`, `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerSetType()`,
309db781477SPatrick Sanan `PetscViewerSocketSetConnection()`, `PETSC_VIEWER_SOCKET_`, `PETSC_VIEWER_SOCKET_WORLD`,
310db781477SPatrick Sanan `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteStringArray()`,
311db781477SPatrick Sanan `PetscBinaryViewerGetDescriptor()`, `PetscMatlabEngineCreate()`
3125c6c1daeSBarry Smith @*/
313d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm, const char machine[], int port, PetscViewer *lab)
314d71ae5a4SJacob Faibussowitsch {
3155c6c1daeSBarry Smith PetscFunctionBegin;
3169566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, lab));
3179566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSOCKET));
3189566063dSJacob Faibussowitsch PetscCall(PetscViewerSocketSetConnection(*lab, machine, port));
3193ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3205c6c1daeSBarry Smith }
3215c6c1daeSBarry Smith
322ce78bad3SBarry Smith static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v, PetscOptionItems PetscOptionsObject)
323d71ae5a4SJacob Faibussowitsch {
3245c6c1daeSBarry Smith PetscInt def = -1;
3255c6c1daeSBarry Smith char sdef[256];
3265c6c1daeSBarry Smith PetscBool tflg;
3275c6c1daeSBarry Smith
3285c6c1daeSBarry Smith PetscFunctionBegin;
3295c6c1daeSBarry Smith /*
3305c6c1daeSBarry Smith These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they
3315c6c1daeSBarry Smith are listed here for the GUI to display
3325c6c1daeSBarry Smith */
333d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Socket PetscViewer Options");
3349566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", sdef, 16, &tflg));
335ac530a7eSPierre Jolivet if (tflg) PetscCall(PetscOptionsStringToInt(sdef, &def));
336ac530a7eSPierre Jolivet else def = PETSCSOCKETDEFAULTPORT;
3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-viewer_socket_port", "Port number to use for socket", "PetscViewerSocketSetConnection", def, NULL, NULL));
3385c6c1daeSBarry Smith
3399566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-viewer_socket_machine", "Machine to use for socket", "PetscViewerSocketSetConnection", sdef, NULL, sizeof(sdef), NULL));
3409566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", sdef, sizeof(sdef), &tflg));
34148a46eb9SPierre Jolivet if (!tflg) PetscCall(PetscGetHostName(sdef, sizeof(sdef)));
342d0609cedSBarry Smith PetscOptionsHeadEnd();
3433ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3445c6c1daeSBarry Smith }
3455c6c1daeSBarry Smith
346d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer, PetscBool *skip)
347d71ae5a4SJacob Faibussowitsch {
3484c9f2355SSatish Balay PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data;
3494c9f2355SSatish Balay
3504c9f2355SSatish Balay PetscFunctionBegin;
3514c9f2355SSatish Balay *skip = vsocket->skipheader;
3523ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3534c9f2355SSatish Balay }
3544c9f2355SSatish Balay
355d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer, PetscBool skip)
356d71ae5a4SJacob Faibussowitsch {
3574c9f2355SSatish Balay PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data;
3584c9f2355SSatish Balay
3594c9f2355SSatish Balay PetscFunctionBegin;
3604c9f2355SSatish Balay vsocket->skipheader = skip;
3613ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3624c9f2355SSatish Balay }
3634c9f2355SSatish Balay
36476667918SBarry Smith PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer, PetscInt *);
3654c9f2355SSatish Balay
3668556b5ebSBarry Smith /*MC
3678556b5ebSBarry Smith PETSCVIEWERSOCKET - A viewer that writes to a Unix socket
3688556b5ebSBarry Smith
369811af0c4SBarry Smith Level: beginner
370811af0c4SBarry Smith
371d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWERBINARY`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`,
372db781477SPatrick Sanan `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`,
373db781477SPatrick Sanan `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`,
374db781477SPatrick Sanan `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
3758556b5ebSBarry Smith M*/
3768556b5ebSBarry Smith
377d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v)
378d71ae5a4SJacob Faibussowitsch {
3795c6c1daeSBarry Smith PetscViewer_Socket *vmatlab;
3805c6c1daeSBarry Smith
3815c6c1daeSBarry Smith PetscFunctionBegin;
3824dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&vmatlab));
3835c6c1daeSBarry Smith vmatlab->port = 0;
38476667918SBarry Smith vmatlab->flowcontrol = 256; /* same default as in PetscViewerCreate_Binary() */
3855c6c1daeSBarry Smith v->data = (void *)vmatlab;
3865c6c1daeSBarry Smith v->ops->destroy = PetscViewerDestroy_Socket;
38702c9f0b5SLisandro Dalcin v->ops->flush = NULL;
3885c6c1daeSBarry Smith v->ops->setfromoptions = PetscViewerSetFromOptions_Socket;
3895c6c1daeSBarry Smith
3905c6c1daeSBarry Smith /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */
3919566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)v, PETSCVIEWERBINARY));
3929566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Socket));
3939566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Socket));
39476667918SBarry Smith PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary));
3953ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
3965c6c1daeSBarry Smith }
3975c6c1daeSBarry Smith
3985d83a8b1SBarry Smith /*@
3995c6c1daeSBarry Smith PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket
4005c6c1daeSBarry Smith viewer is to use
4015c6c1daeSBarry Smith
402c3339decSBarry Smith Logically Collective
4035c6c1daeSBarry Smith
4045c6c1daeSBarry Smith Input Parameters:
4055c6c1daeSBarry Smith + v - viewer to connect
4063f423023SBarry Smith . machine - host to connect to, use `NULL` for the local machine,use "server" to passively wait for
4075c6c1daeSBarry Smith a connection from elsewhere
408811af0c4SBarry Smith - port - the port on the machine one is connecting to, use `PETSC_DEFAULT` for default
4095c6c1daeSBarry Smith
4105c6c1daeSBarry Smith Level: advanced
4115c6c1daeSBarry Smith
412d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PetscViewerSocketOpen()`
4135c6c1daeSBarry Smith @*/
414d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v, const char machine[], int port)
415d71ae5a4SJacob Faibussowitsch {
4165c6c1daeSBarry Smith PetscMPIInt rank;
4175c6c1daeSBarry Smith char mach[256];
4185c6c1daeSBarry Smith PetscBool tflg;
4193ca90d2dSJacob Faibussowitsch PetscViewer_Socket *vmatlab;
4205c6c1daeSBarry Smith
4215c6c1daeSBarry Smith PetscFunctionBegin;
4223ca90d2dSJacob Faibussowitsch PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1);
4234f572ea9SToby Isaac if (machine) PetscAssertPointer(machine, 2);
4243ca90d2dSJacob Faibussowitsch vmatlab = (PetscViewer_Socket *)v->data;
4255c6c1daeSBarry Smith /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */
4265c6c1daeSBarry Smith if (port <= 0) {
4275c6c1daeSBarry Smith char portn[16];
4289566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", portn, 16, &tflg));
4295c6c1daeSBarry Smith if (tflg) {
4305c6c1daeSBarry Smith PetscInt pport;
4319566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringToInt(portn, &pport));
432835f2295SStefano Zampini PetscCall(PetscMPIIntCast(pport, &port));
433a297a907SKarl Rupp } else port = PETSCSOCKETDEFAULTPORT;
4345c6c1daeSBarry Smith }
4355c6c1daeSBarry Smith if (!machine) {
4369566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", mach, sizeof(mach), &tflg));
43748a46eb9SPierre Jolivet if (!tflg) PetscCall(PetscGetHostName(mach, sizeof(mach)));
4385c6c1daeSBarry Smith } else {
4399566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mach, machine, sizeof(mach)));
4405c6c1daeSBarry Smith }
4415c6c1daeSBarry Smith
4429566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank));
443dd400576SPatrick Sanan if (rank == 0) {
4449566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mach, "server", &tflg));
4455c6c1daeSBarry Smith if (tflg) {
44610450e9eSJacob Faibussowitsch int listenport = 0;
44710450e9eSJacob Faibussowitsch
4489566063dSJacob Faibussowitsch PetscCall(PetscInfo(v, "Waiting for connection from socket process on port %d\n", port));
4499566063dSJacob Faibussowitsch PetscCall(PetscSocketEstablish(port, &listenport));
4509566063dSJacob Faibussowitsch PetscCall(PetscSocketListen(listenport, &vmatlab->port));
4515c6c1daeSBarry Smith close(listenport);
4525c6c1daeSBarry Smith } else {
4539566063dSJacob Faibussowitsch PetscCall(PetscInfo(v, "Connecting to socket process on port %d machine %s\n", port, mach));
4549566063dSJacob Faibussowitsch PetscCall(PetscOpenSocket(mach, port, &vmatlab->port));
4555c6c1daeSBarry Smith }
4565c6c1daeSBarry Smith }
4573ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS);
4585c6c1daeSBarry Smith }
4595c6c1daeSBarry Smith
4605c6c1daeSBarry Smith /*
4615c6c1daeSBarry Smith The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that
4625c6c1daeSBarry Smith is attached to a communicator, in this case the attribute is a PetscViewer.
4635c6c1daeSBarry Smith */
464d4c7638eSBarry Smith PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID;
4655c6c1daeSBarry Smith
4665c6c1daeSBarry Smith /*@C
4675c6c1daeSBarry Smith PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator.
4685c6c1daeSBarry Smith
469d083f849SBarry Smith Collective
4705c6c1daeSBarry Smith
4715c6c1daeSBarry Smith Input Parameter:
472811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERSOCKET` `PetscViewer`
4735c6c1daeSBarry Smith
4745c6c1daeSBarry Smith Level: intermediate
4755c6c1daeSBarry Smith
4765c6c1daeSBarry Smith Options Database Keys:
477811af0c4SBarry Smith For use with the default `PETSC_VIEWER_SOCKET_WORLD` or if
4783f423023SBarry Smith `NULL` is passed for machine or `PETSC_DEFAULT` is passed for port
479d1f92df0SBarry Smith + -viewer_socket_machine <machine> - machine to connect to
480d1f92df0SBarry Smith - -viewer_socket_port <port> - port to connect to
4815c6c1daeSBarry Smith
4825c6c1daeSBarry Smith Environmental variables:
483811af0c4SBarry Smith + `PETSC_VIEWER_SOCKET_PORT` - portnumber
484811af0c4SBarry Smith - `PETSC_VIEWER_SOCKET_MACHINE` - machine name
4855c6c1daeSBarry Smith
4865c6c1daeSBarry Smith Notes:
48734fa283eSBarry Smith This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it
48834fa283eSBarry Smith
489811af0c4SBarry Smith Unlike almost all other PETSc routines, `PETSC_VIEWER_SOCKET_()` does not return
490a3b724e8SBarry Smith an error code, it returns `NULL` if it fails. The `PETSCVIEWERSOCKET` `PetscViewer` is usually used in the form `XXXView(XXX object, PETSC_VIEWER_SOCKET_(comm))`
4915c6c1daeSBarry Smith
4925c6c1daeSBarry Smith Currently the only socket client available is MATLAB. See
493c4762a1bSJed Brown src/dm/tests/ex12.c and ex12.m for an example of usage.
4945c6c1daeSBarry Smith
495811af0c4SBarry Smith Connects to a waiting socket and stays connected until `PetscViewerDestroy()` is called.
4965c6c1daeSBarry Smith
497811af0c4SBarry Smith Use this for communicating with an interactive MATLAB session, see `PETSC_VIEWER_MATLAB_()` for writing output to a
498811af0c4SBarry Smith .mat file. Use `PetscMatlabEngineCreate()` or `PETSC_MATLAB_ENGINE_()`, `PETSC_MATLAB_ENGINE_SELF`, or `PETSC_MATLAB_ENGINE_WORLD`
499a30fc760SBarry Smith for communicating with a MATLAB Engine
5005c6c1daeSBarry Smith
501d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerSocketOpen()`, `PetscViewerCreate()`,
502db781477SPatrick Sanan `PetscViewerSocketSetConnection()`, `PetscViewerDestroy()`, `PETSC_VIEWER_SOCKET_()`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`,
503db781477SPatrick Sanan `PetscViewerBinaryWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`, `PETSC_VIEWER_MATLAB_()`
5045c6c1daeSBarry Smith @*/
505d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm)
506d71ae5a4SJacob Faibussowitsch {
507*b8b5be36SMartin Diehl PetscMPIInt iflg;
5085c6c1daeSBarry Smith PetscViewer viewer;
5095c6c1daeSBarry Smith MPI_Comm ncomm;
5105c6c1daeSBarry Smith
5115c6c1daeSBarry Smith PetscFunctionBegin;
512648c30bcSBarry Smith PetscCallNull(PetscCommDuplicate(comm, &ncomm, NULL));
513dd460d27SBarry Smith if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) PetscCallMPINull(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Socket_keyval, NULL));
514*b8b5be36SMartin Diehl PetscCallMPINull(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Socket_keyval, (void **)&viewer, &iflg));
515*b8b5be36SMartin Diehl if (!iflg) { /* PetscViewer not yet created */
516648c30bcSBarry Smith PetscCallNull(PetscViewerSocketOpen(ncomm, NULL, 0, &viewer));
517648c30bcSBarry Smith PetscCallNull(PetscObjectRegisterDestroy((PetscObject)viewer));
518648c30bcSBarry Smith PetscCallMPINull(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Socket_keyval, (void *)viewer));
5199371c9d4SSatish Balay }
520648c30bcSBarry Smith PetscCallNull(PetscCommDestroy(&ncomm));
5215c6c1daeSBarry Smith PetscFunctionReturn(viewer);
5225c6c1daeSBarry Smith }
523