15c6c1daeSBarry Smith #include <petscsys.h> 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 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 804683183fSBarry Smith /*@C 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 @*/ 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 1155c6c1daeSBarry Smith sa.sin_family = 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 */ 18310450e9eSJacob Faibussowitsch static PetscErrorCode PetscSocketEstablish(int portnum, int *ss) 184d71ae5a4SJacob Faibussowitsch { 185589a23caSBarry Smith static size_t MAXHOSTNAME = 100; 1865c6c1daeSBarry Smith char myname[MAXHOSTNAME + 1]; 1875c6c1daeSBarry Smith int s; 1885c6c1daeSBarry Smith struct sockaddr_in sa; 1895c6c1daeSBarry Smith struct hostent *hp; 1905c6c1daeSBarry Smith 1915c6c1daeSBarry Smith PetscFunctionBegin; 1929566063dSJacob Faibussowitsch PetscCall(PetscGetHostName(myname, sizeof(myname))); 1935c6c1daeSBarry Smith 1949566063dSJacob Faibussowitsch PetscCall(PetscMemzero(&sa, sizeof(struct sockaddr_in))); 1955c6c1daeSBarry Smith 1965c6c1daeSBarry Smith hp = gethostbyname(myname); 19728b400f6SJacob Faibussowitsch PetscCheck(hp, PETSC_COMM_SELF, PETSC_ERR_SYS, "Unable to get hostent information from system"); 1985c6c1daeSBarry Smith 1995c6c1daeSBarry Smith sa.sin_family = hp->h_addrtype; 2005c6c1daeSBarry Smith sa.sin_port = htons((u_short)portnum); 2015c6c1daeSBarry Smith 202cc73adaaSBarry Smith PetscCheck((s = socket(AF_INET, SOCK_STREAM, 0)) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "Error running socket() command"); 2035c6c1daeSBarry Smith #if defined(PETSC_HAVE_SO_REUSEADDR) 2045c6c1daeSBarry Smith { 2055c6c1daeSBarry Smith int optval = 1; /* Turn on the option */ 2063ba16761SJacob Faibussowitsch int ret = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *)&optval, sizeof(optval)); 2073ba16761SJacob Faibussowitsch PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "setsockopt() failed with error code %d", ret); 2085c6c1daeSBarry Smith } 2095c6c1daeSBarry Smith #endif 2105c6c1daeSBarry Smith 2115c6c1daeSBarry Smith while (bind(s, (struct sockaddr *)&sa, sizeof(sa)) < 0) { 2125c6c1daeSBarry Smith #if defined(PETSC_HAVE_WSAGETLASTERROR) 2135c6c1daeSBarry Smith ierr = WSAGetLastError(); 2145c6c1daeSBarry Smith if (ierr != WSAEADDRINUSE) { 2155c6c1daeSBarry Smith #else 2165c6c1daeSBarry Smith if (errno != EADDRINUSE) { 2175c6c1daeSBarry Smith #endif 2185c6c1daeSBarry Smith close(s); 2195c6c1daeSBarry Smith SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SYS, "Error from bind()"); 2205c6c1daeSBarry Smith } 2215c6c1daeSBarry Smith } 2225c6c1daeSBarry Smith listen(s, 0); 2235c6c1daeSBarry Smith *ss = s; 2243ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2255c6c1daeSBarry Smith } 2265c6c1daeSBarry Smith 22710450e9eSJacob Faibussowitsch /* 228811af0c4SBarry Smith PetscSocketListen - Listens at a socket created with `PetscSocketEstablish()` 2294683183fSBarry Smith 2304683183fSBarry Smith Input Parameter: 231811af0c4SBarry Smith . listenport - obtained with `PetscSocketEstablish()` 2324683183fSBarry Smith 2334683183fSBarry Smith Output Parameter: 2344683183fSBarry Smith . t - pass this to read() to read what is passed to this connection 2354683183fSBarry Smith 2364683183fSBarry Smith Level: advanced 2375c6c1daeSBarry Smith 238db781477SPatrick Sanan .seealso: `PetscSocketEstablish()` 23910450e9eSJacob Faibussowitsch */ 24010450e9eSJacob Faibussowitsch static PetscErrorCode PetscSocketListen(int listenport, int *t) 241d71ae5a4SJacob Faibussowitsch { 2425c6c1daeSBarry Smith struct sockaddr_in isa; 2435c6c1daeSBarry Smith #if defined(PETSC_HAVE_ACCEPT_SIZE_T) 2445c6c1daeSBarry Smith size_t i; 2455c6c1daeSBarry Smith #else 2465c6c1daeSBarry Smith int i; 2475c6c1daeSBarry Smith #endif 2485c6c1daeSBarry Smith 2495c6c1daeSBarry Smith PetscFunctionBegin; 2505c6c1daeSBarry Smith /* wait for someone to try to connect */ 2515c6c1daeSBarry Smith i = sizeof(struct sockaddr_in); 252cc73adaaSBarry Smith PetscCheck((*t = accept(listenport, (struct sockaddr *)&isa, (socklen_t *)&i)) >= 0, PETSC_COMM_SELF, PETSC_ERR_SYS, "error from accept()"); 2533ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 2545c6c1daeSBarry Smith } 2555c6c1daeSBarry Smith 25610450e9eSJacob Faibussowitsch // "Unknown section 'Environmental Variables'" 25710450e9eSJacob Faibussowitsch // PetscClangLinter pragma disable: -fdoc-section-header-unknown 2585c6c1daeSBarry Smith /*@C 259a30fc760SBarry Smith PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server. 2605c6c1daeSBarry Smith 261d083f849SBarry Smith Collective 2625c6c1daeSBarry Smith 2635c6c1daeSBarry Smith Input Parameters: 2645c6c1daeSBarry Smith + comm - the MPI communicator 2653f423023SBarry Smith . machine - the machine the server is running on, use `NULL` for the local machine, use "server" to passively wait for 2665c6c1daeSBarry Smith a connection from elsewhere 267811af0c4SBarry Smith - port - the port to connect to, use `PETSC_DEFAULT` for the default 2685c6c1daeSBarry Smith 2695c6c1daeSBarry Smith Output Parameter: 2705c6c1daeSBarry Smith . lab - a context to use when communicating with the server 2715c6c1daeSBarry Smith 272811af0c4SBarry Smith Options Database Keys: 273811af0c4SBarry Smith For use with `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`, 274811af0c4SBarry Smith `PETSC_VIEWER_SOCKET_()` or if 2753f423023SBarry Smith `NULL` is passed for machine or PETSC_DEFAULT is passed for port 2763f423023SBarry Smith + -viewer_socket_machine <machine> - the machine where the socket is available 277*f332b1cbSPierre Jolivet - -viewer_socket_port <port> - the socket to connect to 278811af0c4SBarry Smith 279811af0c4SBarry Smith Environmental variables: 2803f423023SBarry Smith + `PETSC_VIEWER_SOCKET_MACHINE` - machine name 2813f423023SBarry Smith - `PETSC_VIEWER_SOCKET_PORT` - portnumber 282811af0c4SBarry Smith 2835c6c1daeSBarry Smith Level: intermediate 2845c6c1daeSBarry Smith 2855c6c1daeSBarry Smith Notes: 2865c6c1daeSBarry Smith Most users should employ the following commands to access the 287811af0c4SBarry Smith MATLAB `PetscViewer` 2883f423023SBarry Smith .vb 2893f423023SBarry Smith 2903f423023SBarry Smith PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer) 2913f423023SBarry Smith MatView(Mat matrix,PetscViewer viewer) 2923f423023SBarry Smith .ve 2933f423023SBarry Smith or 2943f423023SBarry Smith .vb 2953f423023SBarry Smith PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer) 2963f423023SBarry Smith VecView(Vec vector,PetscViewer viewer) 2973f423023SBarry Smith .ve 2985c6c1daeSBarry Smith 299750b007cSBarry Smith Currently the only socket client available is MATLAB, PETSc must be configured with --with-matlab for this client. See 300c4762a1bSJed Brown src/dm/tests/ex12.c and ex12.m for an example of usage. 3015c6c1daeSBarry Smith 30295452b02SPatrick Sanan The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket 303811af0c4SBarry Smith use `PetscViewerBinaryRead()`, `PetscViewerBinaryWrite()`, `PetscViewerBinarWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`. 304a30fc760SBarry Smith 305811af0c4SBarry Smith Use this for communicating with an interactive MATLAB session, see `PETSC_VIEWER_MATLAB_()` for writing output to a 306811af0c4SBarry Smith .mat file. Use `PetscMatlabEngineCreate()` or `PETSC_MATLAB_ENGINE_()`, `PETSC_MATLAB_ENGINE_SELF`, or `PETSC_MATLAB_ENGINE_WORLD` 307a30fc760SBarry Smith for communicating with a MATLAB Engine 3085c6c1daeSBarry Smith 309d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERBINARY`, `PETSCVIEWERSOCKET`, `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerSetType()`, 310db781477SPatrick Sanan `PetscViewerSocketSetConnection()`, `PETSC_VIEWER_SOCKET_`, `PETSC_VIEWER_SOCKET_WORLD`, 311db781477SPatrick Sanan `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`, `PetscViewerBinaryWriteStringArray()`, 312db781477SPatrick Sanan `PetscBinaryViewerGetDescriptor()`, `PetscMatlabEngineCreate()` 3135c6c1daeSBarry Smith @*/ 314d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm, const char machine[], int port, PetscViewer *lab) 315d71ae5a4SJacob Faibussowitsch { 3165c6c1daeSBarry Smith PetscFunctionBegin; 3179566063dSJacob Faibussowitsch PetscCall(PetscViewerCreate(comm, lab)); 3189566063dSJacob Faibussowitsch PetscCall(PetscViewerSetType(*lab, PETSCVIEWERSOCKET)); 3199566063dSJacob Faibussowitsch PetscCall(PetscViewerSocketSetConnection(*lab, machine, port)); 3203ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3215c6c1daeSBarry Smith } 3225c6c1daeSBarry Smith 323d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscViewer v, PetscOptionItems *PetscOptionsObject) 324d71ae5a4SJacob Faibussowitsch { 3255c6c1daeSBarry Smith PetscInt def = -1; 3265c6c1daeSBarry Smith char sdef[256]; 3275c6c1daeSBarry Smith PetscBool tflg; 3285c6c1daeSBarry Smith 3295c6c1daeSBarry Smith PetscFunctionBegin; 3305c6c1daeSBarry Smith /* 3315c6c1daeSBarry Smith These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they 3325c6c1daeSBarry Smith are listed here for the GUI to display 3335c6c1daeSBarry Smith */ 334d0609cedSBarry Smith PetscOptionsHeadBegin(PetscOptionsObject, "Socket PetscViewer Options"); 3359566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", sdef, 16, &tflg)); 3365c6c1daeSBarry Smith if (tflg) { 3379566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringToInt(sdef, &def)); 338a297a907SKarl Rupp } else def = PETSCSOCKETDEFAULTPORT; 3399566063dSJacob Faibussowitsch PetscCall(PetscOptionsInt("-viewer_socket_port", "Port number to use for socket", "PetscViewerSocketSetConnection", def, NULL, NULL)); 3405c6c1daeSBarry Smith 3419566063dSJacob Faibussowitsch PetscCall(PetscOptionsString("-viewer_socket_machine", "Machine to use for socket", "PetscViewerSocketSetConnection", sdef, NULL, sizeof(sdef), NULL)); 3429566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", sdef, sizeof(sdef), &tflg)); 34348a46eb9SPierre Jolivet if (!tflg) PetscCall(PetscGetHostName(sdef, sizeof(sdef))); 344d0609cedSBarry Smith PetscOptionsHeadEnd(); 3453ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3465c6c1daeSBarry Smith } 3475c6c1daeSBarry Smith 348d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer, PetscBool *skip) 349d71ae5a4SJacob Faibussowitsch { 3504c9f2355SSatish Balay PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data; 3514c9f2355SSatish Balay 3524c9f2355SSatish Balay PetscFunctionBegin; 3534c9f2355SSatish Balay *skip = vsocket->skipheader; 3543ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3554c9f2355SSatish Balay } 3564c9f2355SSatish Balay 357d71ae5a4SJacob Faibussowitsch static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer, PetscBool skip) 358d71ae5a4SJacob Faibussowitsch { 3594c9f2355SSatish Balay PetscViewer_Socket *vsocket = (PetscViewer_Socket *)viewer->data; 3604c9f2355SSatish Balay 3614c9f2355SSatish Balay PetscFunctionBegin; 3624c9f2355SSatish Balay vsocket->skipheader = skip; 3633ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3644c9f2355SSatish Balay } 3654c9f2355SSatish Balay 36676667918SBarry Smith PETSC_INTERN PetscErrorCode PetscViewerBinaryGetFlowControl_Binary(PetscViewer, PetscInt *); 3674c9f2355SSatish Balay 3688556b5ebSBarry Smith /*MC 3698556b5ebSBarry Smith PETSCVIEWERSOCKET - A viewer that writes to a Unix socket 3708556b5ebSBarry Smith 371811af0c4SBarry Smith Level: beginner 372811af0c4SBarry Smith 373d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSC_VIEWERBINARY`, `PetscViewerSocketOpen()`, `PetscViewerDrawOpen()`, `PETSC_VIEWER_DRAW_()`, `PETSC_VIEWER_DRAW_SELF`, `PETSC_VIEWER_DRAW_WORLD`, 374db781477SPatrick Sanan `PetscViewerCreate()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PETSCVIEWERBINARY`, `PETSCVIEWERDRAW`, 375db781477SPatrick Sanan `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERASCII`, `PETSCVIEWERMATLAB`, 376db781477SPatrick Sanan `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()` 3778556b5ebSBarry Smith M*/ 3788556b5ebSBarry Smith 379d71ae5a4SJacob Faibussowitsch PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v) 380d71ae5a4SJacob Faibussowitsch { 3815c6c1daeSBarry Smith PetscViewer_Socket *vmatlab; 3825c6c1daeSBarry Smith 3835c6c1daeSBarry Smith PetscFunctionBegin; 3844dfa11a4SJacob Faibussowitsch PetscCall(PetscNew(&vmatlab)); 3855c6c1daeSBarry Smith vmatlab->port = 0; 38676667918SBarry Smith vmatlab->flowcontrol = 256; /* same default as in PetscViewerCreate_Binary() */ 3875c6c1daeSBarry Smith v->data = (void *)vmatlab; 3885c6c1daeSBarry Smith v->ops->destroy = PetscViewerDestroy_Socket; 38902c9f0b5SLisandro Dalcin v->ops->flush = NULL; 3905c6c1daeSBarry Smith v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; 3915c6c1daeSBarry Smith 3925c6c1daeSBarry Smith /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ 3939566063dSJacob Faibussowitsch PetscCall(PetscObjectChangeTypeName((PetscObject)v, PETSCVIEWERBINARY)); 3949566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinarySetSkipHeader_C", PetscViewerBinarySetSkipHeader_Socket)); 3959566063dSJacob Faibussowitsch PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetSkipHeader_C", PetscViewerBinaryGetSkipHeader_Socket)); 39676667918SBarry Smith PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerBinaryGetFlowControl_C", PetscViewerBinaryGetFlowControl_Binary)); 3974c9f2355SSatish Balay 3983ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 3995c6c1daeSBarry Smith } 4005c6c1daeSBarry Smith 4015c6c1daeSBarry Smith /*@C 4025c6c1daeSBarry Smith PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 4035c6c1daeSBarry Smith viewer is to use 4045c6c1daeSBarry Smith 405c3339decSBarry Smith Logically Collective 4065c6c1daeSBarry Smith 4075c6c1daeSBarry Smith Input Parameters: 4085c6c1daeSBarry Smith + v - viewer to connect 4093f423023SBarry Smith . machine - host to connect to, use `NULL` for the local machine,use "server" to passively wait for 4105c6c1daeSBarry Smith a connection from elsewhere 411811af0c4SBarry Smith - port - the port on the machine one is connecting to, use `PETSC_DEFAULT` for default 4125c6c1daeSBarry Smith 4135c6c1daeSBarry Smith Level: advanced 4145c6c1daeSBarry Smith 415d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PetscViewerSocketOpen()` 4165c6c1daeSBarry Smith @*/ 417d71ae5a4SJacob Faibussowitsch PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v, const char machine[], int port) 418d71ae5a4SJacob Faibussowitsch { 4195c6c1daeSBarry Smith PetscMPIInt rank; 4205c6c1daeSBarry Smith char mach[256]; 4215c6c1daeSBarry Smith PetscBool tflg; 4223ca90d2dSJacob Faibussowitsch PetscViewer_Socket *vmatlab; 4235c6c1daeSBarry Smith 4245c6c1daeSBarry Smith PetscFunctionBegin; 4253ca90d2dSJacob Faibussowitsch PetscValidHeaderSpecific(v, PETSC_VIEWER_CLASSID, 1); 4264f572ea9SToby Isaac if (machine) PetscAssertPointer(machine, 2); 4273ca90d2dSJacob Faibussowitsch vmatlab = (PetscViewer_Socket *)v->data; 4285c6c1daeSBarry Smith /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */ 4295c6c1daeSBarry Smith if (port <= 0) { 4305c6c1daeSBarry Smith char portn[16]; 4319566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_PORT", portn, 16, &tflg)); 4325c6c1daeSBarry Smith if (tflg) { 4335c6c1daeSBarry Smith PetscInt pport; 4349566063dSJacob Faibussowitsch PetscCall(PetscOptionsStringToInt(portn, &pport)); 4355c6c1daeSBarry Smith port = (int)pport; 436a297a907SKarl Rupp } else port = PETSCSOCKETDEFAULTPORT; 4375c6c1daeSBarry Smith } 4385c6c1daeSBarry Smith if (!machine) { 4399566063dSJacob Faibussowitsch PetscCall(PetscOptionsGetenv(PetscObjectComm((PetscObject)v), "PETSC_VIEWER_SOCKET_MACHINE", mach, sizeof(mach), &tflg)); 44048a46eb9SPierre Jolivet if (!tflg) PetscCall(PetscGetHostName(mach, sizeof(mach))); 4415c6c1daeSBarry Smith } else { 4429566063dSJacob Faibussowitsch PetscCall(PetscStrncpy(mach, machine, sizeof(mach))); 4435c6c1daeSBarry Smith } 4445c6c1daeSBarry Smith 4459566063dSJacob Faibussowitsch PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)v), &rank)); 446dd400576SPatrick Sanan if (rank == 0) { 4479566063dSJacob Faibussowitsch PetscCall(PetscStrcmp(mach, "server", &tflg)); 4485c6c1daeSBarry Smith if (tflg) { 44910450e9eSJacob Faibussowitsch int listenport = 0; 45010450e9eSJacob Faibussowitsch 4519566063dSJacob Faibussowitsch PetscCall(PetscInfo(v, "Waiting for connection from socket process on port %d\n", port)); 4529566063dSJacob Faibussowitsch PetscCall(PetscSocketEstablish(port, &listenport)); 4539566063dSJacob Faibussowitsch PetscCall(PetscSocketListen(listenport, &vmatlab->port)); 4545c6c1daeSBarry Smith close(listenport); 4555c6c1daeSBarry Smith } else { 4569566063dSJacob Faibussowitsch PetscCall(PetscInfo(v, "Connecting to socket process on port %d machine %s\n", port, mach)); 4579566063dSJacob Faibussowitsch PetscCall(PetscOpenSocket(mach, port, &vmatlab->port)); 4585c6c1daeSBarry Smith } 4595c6c1daeSBarry Smith } 4603ba16761SJacob Faibussowitsch PetscFunctionReturn(PETSC_SUCCESS); 4615c6c1daeSBarry Smith } 4625c6c1daeSBarry Smith 4635c6c1daeSBarry Smith /* 4645c6c1daeSBarry Smith The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that 4655c6c1daeSBarry Smith is attached to a communicator, in this case the attribute is a PetscViewer. 4665c6c1daeSBarry Smith */ 467d4c7638eSBarry Smith PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; 4685c6c1daeSBarry Smith 4695c6c1daeSBarry Smith /*@C 4705c6c1daeSBarry Smith PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 4715c6c1daeSBarry Smith 472d083f849SBarry Smith Collective 4735c6c1daeSBarry Smith 4745c6c1daeSBarry Smith Input Parameter: 475811af0c4SBarry Smith . comm - the MPI communicator to share the `PETSCVIEWERSOCKET` `PetscViewer` 4765c6c1daeSBarry Smith 4775c6c1daeSBarry Smith Level: intermediate 4785c6c1daeSBarry Smith 4795c6c1daeSBarry Smith Options Database Keys: 480811af0c4SBarry Smith For use with the default `PETSC_VIEWER_SOCKET_WORLD` or if 4813f423023SBarry Smith `NULL` is passed for machine or `PETSC_DEFAULT` is passed for port 482d1f92df0SBarry Smith + -viewer_socket_machine <machine> - machine to connect to 483d1f92df0SBarry Smith - -viewer_socket_port <port> - port to connect to 4845c6c1daeSBarry Smith 4855c6c1daeSBarry Smith Environmental variables: 486811af0c4SBarry Smith + `PETSC_VIEWER_SOCKET_PORT` - portnumber 487811af0c4SBarry Smith - `PETSC_VIEWER_SOCKET_MACHINE` - machine name 4885c6c1daeSBarry Smith 4895c6c1daeSBarry Smith Notes: 49034fa283eSBarry Smith This object is destroyed in `PetscFinalize()`, `PetscViewerDestroy()` should never be called on it 49134fa283eSBarry Smith 492811af0c4SBarry Smith Unlike almost all other PETSc routines, `PETSC_VIEWER_SOCKET_()` does not return 493811af0c4SBarry Smith an error code, it returns NULL if it fails. The `PETSCVIEWERSOCKET` `PetscViewer` is usually used in the form 4945c6c1daeSBarry Smith $ XXXView(XXX object, PETSC_VIEWER_SOCKET_(comm)); 4955c6c1daeSBarry Smith 4965c6c1daeSBarry Smith Currently the only socket client available is MATLAB. See 497c4762a1bSJed Brown src/dm/tests/ex12.c and ex12.m for an example of usage. 4985c6c1daeSBarry Smith 499811af0c4SBarry Smith Connects to a waiting socket and stays connected until `PetscViewerDestroy()` is called. 5005c6c1daeSBarry Smith 501811af0c4SBarry Smith Use this for communicating with an interactive MATLAB session, see `PETSC_VIEWER_MATLAB_()` for writing output to a 502811af0c4SBarry Smith .mat file. Use `PetscMatlabEngineCreate()` or `PETSC_MATLAB_ENGINE_()`, `PETSC_MATLAB_ENGINE_SELF`, or `PETSC_MATLAB_ENGINE_WORLD` 503a30fc760SBarry Smith for communicating with a MATLAB Engine 5045c6c1daeSBarry Smith 505d1f92df0SBarry Smith .seealso: [](sec_viewers), `PETSCVIEWERMATLAB`, `PETSCVIEWERSOCKET`, `PETSC_VIEWER_SOCKET_WORLD`, `PETSC_VIEWER_SOCKET_SELF`, `PetscViewerSocketOpen()`, `PetscViewerCreate()`, 506db781477SPatrick Sanan `PetscViewerSocketSetConnection()`, `PetscViewerDestroy()`, `PETSC_VIEWER_SOCKET_()`, `PetscViewerBinaryWrite()`, `PetscViewerBinaryRead()`, 507db781477SPatrick Sanan `PetscViewerBinaryWriteStringArray()`, `PetscViewerBinaryGetDescriptor()`, `PETSC_VIEWER_MATLAB_()` 5085c6c1daeSBarry Smith @*/ 509d71ae5a4SJacob Faibussowitsch PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm) 510d71ae5a4SJacob Faibussowitsch { 5115c6c1daeSBarry Smith PetscErrorCode ierr; 5123ba16761SJacob Faibussowitsch PetscMPIInt mpi_ierr; 5135c6c1daeSBarry Smith PetscBool flg; 5145c6c1daeSBarry Smith PetscViewer viewer; 5155c6c1daeSBarry Smith MPI_Comm ncomm; 5165c6c1daeSBarry Smith 5175c6c1daeSBarry Smith PetscFunctionBegin; 5189371c9d4SSatish Balay ierr = PetscCommDuplicate(comm, &ncomm, NULL); 5199371c9d4SSatish Balay if (ierr) { 5203ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 5219371c9d4SSatish Balay PetscFunctionReturn(NULL); 5229371c9d4SSatish Balay } 5235c6c1daeSBarry Smith if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { 5243ba16761SJacob Faibussowitsch mpi_ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Socket_keyval, NULL); 5253ba16761SJacob Faibussowitsch if (mpi_ierr) { 5263ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 5279371c9d4SSatish Balay PetscFunctionReturn(NULL); 5289371c9d4SSatish Balay } 5295c6c1daeSBarry Smith } 5303ba16761SJacob Faibussowitsch mpi_ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_Socket_keyval, (void **)&viewer, (int *)&flg); 5313ba16761SJacob Faibussowitsch if (mpi_ierr) { 5323ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 5339371c9d4SSatish Balay PetscFunctionReturn(NULL); 5349371c9d4SSatish Balay } 5355c6c1daeSBarry Smith if (!flg) { /* PetscViewer not yet created */ 53602c9f0b5SLisandro Dalcin ierr = PetscViewerSocketOpen(ncomm, NULL, 0, &viewer); 53734fa283eSBarry Smith ((PetscObject)viewer)->persistent = PETSC_TRUE; 5389371c9d4SSatish Balay if (ierr) { 5393ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 5409371c9d4SSatish Balay PetscFunctionReturn(NULL); 5419371c9d4SSatish Balay } 5425c6c1daeSBarry Smith ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 5439371c9d4SSatish Balay if (ierr) { 5443ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 5459371c9d4SSatish Balay PetscFunctionReturn(NULL); 5469371c9d4SSatish Balay } 5473ba16761SJacob Faibussowitsch mpi_ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_Socket_keyval, (void *)viewer); 5483ba16761SJacob Faibussowitsch if (mpi_ierr) { 5493ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 5509371c9d4SSatish Balay PetscFunctionReturn(NULL); 5519371c9d4SSatish Balay } 5525c6c1daeSBarry Smith } 5535c6c1daeSBarry Smith ierr = PetscCommDestroy(&ncomm); 5549371c9d4SSatish Balay if (ierr) { 5553ba16761SJacob Faibussowitsch ierr = PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SOCKET_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 5569371c9d4SSatish Balay PetscFunctionReturn(NULL); 5579371c9d4SSatish Balay } 5585c6c1daeSBarry Smith PetscFunctionReturn(viewer); 5595c6c1daeSBarry Smith } 560