1 2 #include <petscsys.h> 3 4 #if defined(PETSC_NEEDS_UTYPE_TYPEDEFS) 5 /* Some systems have inconsistent include files that use but do not 6 ensure that the following definitions are made */ 7 typedef unsigned char u_char; 8 typedef unsigned short u_short; 9 typedef unsigned short ushort; 10 typedef unsigned int u_int; 11 typedef unsigned long u_long; 12 #endif 13 14 #include <errno.h> 15 #include <ctype.h> 16 #if defined(PETSC_HAVE_MACHINE_ENDIAN_H) 17 #include <machine/endian.h> 18 #endif 19 #if defined(PETSC_HAVE_UNISTD_H) 20 #include <unistd.h> 21 #endif 22 #if defined(PETSC_HAVE_SYS_SOCKET_H) 23 #include <sys/socket.h> 24 #endif 25 #if defined(PETSC_HAVE_SYS_WAIT_H) 26 #include <sys/wait.h> 27 #endif 28 #if defined(PETSC_HAVE_NETINET_IN_H) 29 #include <netinet/in.h> 30 #endif 31 #if defined(PETSC_HAVE_NETDB_H) 32 #include <netdb.h> 33 #endif 34 #if defined(PETSC_HAVE_FCNTL_H) 35 #include <fcntl.h> 36 #endif 37 #if defined(PETSC_HAVE_IO_H) 38 #include <io.h> 39 #endif 40 #if defined(PETSC_HAVE_WINSOCK2_H) 41 #include <Winsock2.h> 42 #endif 43 #include <sys/stat.h> 44 #include <../src/sys/classes/viewer/impls/socket/socket.h> 45 46 #if defined(PETSC_NEED_CLOSE_PROTO) 47 PETSC_EXTERN int close(int); 48 #endif 49 #if defined(PETSC_NEED_SOCKET_PROTO) 50 PETSC_EXTERN int socket(int,int,int); 51 #endif 52 #if defined(PETSC_NEED_SLEEP_PROTO) 53 PETSC_EXTERN int sleep(unsigned); 54 #endif 55 #if defined(PETSC_NEED_CONNECT_PROTO) 56 PETSC_EXTERN int connect(int,struct sockaddr*,int); 57 #endif 58 59 /*--------------------------------------------------------------*/ 60 #undef __FUNCT__ 61 #define __FUNCT__ "PetscViewerDestroy_Socket" 62 static PetscErrorCode PetscViewerDestroy_Socket(PetscViewer viewer) 63 { 64 PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)viewer->data; 65 PetscErrorCode ierr; 66 67 PetscFunctionBegin; 68 if (vmatlab->port) { 69 #if defined(PETSC_HAVE_CLOSESOCKET) 70 ierr = closesocket(vmatlab->port); 71 #else 72 ierr = close(vmatlab->port); 73 #endif 74 if (ierr) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"System error closing socket"); 75 } 76 ierr = PetscFree(vmatlab);CHKERRQ(ierr); 77 PetscFunctionReturn(0); 78 } 79 80 /*--------------------------------------------------------------*/ 81 #undef __FUNCT__ 82 #define __FUNCT__ "PetscOpenSocket" 83 /*@C 84 PetscSocketOpen - handles connected to an open port where someone is waiting. 85 86 Input Parameters: 87 + url - for example www.mcs.anl.gov 88 - portnum - for example 80 89 90 Output Paramater: 91 . t - the socket number 92 93 Notes: Use close() to close the socket connection 94 95 Use read() or PetscHTTPRequest() to read from the socket 96 97 Level: advanced 98 99 .seealso: PetscSocketListen(), PetscSocketEstablish(), PetscHTTPRequest(), PetscHTTPSConnect() 100 @*/ 101 PetscErrorCode PetscOpenSocket(const char hostname[],int portnum,int *t) 102 { 103 struct sockaddr_in sa; 104 struct hostent *hp; 105 int s = 0; 106 PetscErrorCode ierr; 107 PetscBool flg = PETSC_TRUE; 108 static int refcnt = 0; 109 110 PetscFunctionBegin; 111 if (!(hp=gethostbyname(hostname))) { 112 perror("SEND: error gethostbyname: "); 113 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error open connection to %s",hostname); 114 } 115 ierr = PetscMemzero(&sa,sizeof(sa));CHKERRQ(ierr); 116 ierr = PetscMemcpy(&sa.sin_addr,hp->h_addr_list[0],hp->h_length);CHKERRQ(ierr); 117 118 sa.sin_family = hp->h_addrtype; 119 sa.sin_port = htons((u_short) portnum); 120 while (flg) { 121 if ((s=socket(hp->h_addrtype,SOCK_STREAM,0)) < 0) { 122 perror("SEND: error socket"); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 123 } 124 if (connect(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) { 125 #if defined(PETSC_HAVE_WSAGETLASTERROR) 126 ierr = WSAGetLastError(); 127 if (ierr == WSAEADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 128 else if (ierr == WSAEALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); 129 else if (ierr == WSAEISCONN) { 130 (*PetscErrorPrintf)("SEND: socket already connected\n"); 131 Sleep((unsigned) 1); 132 } else if (ierr == WSAECONNREFUSED) { 133 /* (*PetscErrorPrintf)("SEND: forcefully rejected\n"); */ 134 Sleep((unsigned) 1); 135 } else { 136 perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 137 } 138 #else 139 if (errno == EADDRINUSE) (*PetscErrorPrintf)("SEND: address is in use\n"); 140 else if (errno == EALREADY) (*PetscErrorPrintf)("SEND: socket is non-blocking \n"); 141 else if (errno == EISCONN) { 142 (*PetscErrorPrintf)("SEND: socket already connected\n"); 143 sleep((unsigned) 1); 144 } else if (errno == ECONNREFUSED) { 145 refcnt++; 146 if (refcnt > 5) SETERRQ2(PETSC_COMM_SELF,PETSC_ERR_SYS,"Connection refused by remote host %s port %d",hostname,portnum); 147 ierr = PetscInfo(0,"Connection refused in attaching socket, trying again\n");CHKERRQ(ierr); 148 sleep((unsigned) 1); 149 } else { 150 perror(NULL); SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"system error"); 151 } 152 #endif 153 flg = PETSC_TRUE; 154 #if defined(PETSC_HAVE_CLOSESOCKET) 155 closesocket(s); 156 #else 157 close(s); 158 #endif 159 } else flg = PETSC_FALSE; 160 } 161 *t = s; 162 PetscFunctionReturn(0); 163 } 164 165 #define MAXHOSTNAME 100 166 #undef __FUNCT__ 167 #define __FUNCT__ "PetscSocketEstablish" 168 /*@C 169 PetscSocketEstablish - starts a listener on a socket 170 171 Input Parameters: 172 . portnumber - the port to wait at 173 174 Output Parameters: 175 . ss - the socket to be used with PetscSocketListen() 176 177 Level: advanced 178 179 .seealso: PetscSocketListen(), PetscOpenSocket() 180 181 @*/ 182 PETSC_INTERN PetscErrorCode PetscSocketEstablish(int portnum,int *ss) 183 { 184 char myname[MAXHOSTNAME+1]; 185 int s; 186 PetscErrorCode ierr; 187 struct sockaddr_in sa; 188 struct hostent *hp; 189 190 PetscFunctionBegin; 191 ierr = PetscGetHostName(myname,MAXHOSTNAME);CHKERRQ(ierr); 192 193 ierr = PetscMemzero(&sa,sizeof(struct sockaddr_in));CHKERRQ(ierr); 194 195 hp = gethostbyname(myname); 196 if (!hp) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Unable to get hostent information from system"); 197 198 sa.sin_family = hp->h_addrtype; 199 sa.sin_port = htons((u_short)portnum); 200 201 if ((s = socket(AF_INET,SOCK_STREAM,0)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error running socket() command"); 202 #if defined(PETSC_HAVE_SO_REUSEADDR) 203 { 204 int optval = 1; /* Turn on the option */ 205 ierr = setsockopt(s,SOL_SOCKET,SO_REUSEADDR,(char*)&optval,sizeof(optval));CHKERRQ(ierr); 206 } 207 #endif 208 209 while (bind(s,(struct sockaddr*)&sa,sizeof(sa)) < 0) { 210 #if defined(PETSC_HAVE_WSAGETLASTERROR) 211 ierr = WSAGetLastError(); 212 if (ierr != WSAEADDRINUSE) { 213 #else 214 if (errno != EADDRINUSE) { 215 #endif 216 close(s); 217 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"Error from bind()"); 218 } 219 } 220 listen(s,0); 221 *ss = s; 222 return(0); 223 } 224 225 #undef __FUNCT__ 226 #define __FUNCT__ "PetscSocketListen" 227 /*@C 228 PetscSocketListen - Listens at a socket created with PetscSocketEstablish() 229 230 Input Parameter: 231 . listenport - obtained with PetscSocketEstablish() 232 233 Output Parameter: 234 . t - pass this to read() to read what is passed to this connection 235 236 Level: advanced 237 238 .seealso: PetscSocketEstablish() 239 @*/ 240 PETSC_INTERN PetscErrorCode PetscSocketListen(int listenport,int *t) 241 { 242 struct sockaddr_in isa; 243 #if defined(PETSC_HAVE_ACCEPT_SIZE_T) 244 size_t i; 245 #else 246 int i; 247 #endif 248 249 PetscFunctionBegin; 250 /* wait for someone to try to connect */ 251 i = sizeof(struct sockaddr_in); 252 if ((*t = accept(listenport,(struct sockaddr*)&isa,(socklen_t*)&i)) < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"error from accept()\n"); 253 PetscFunctionReturn(0); 254 } 255 256 #undef __FUNCT__ 257 #define __FUNCT__ "PetscViewerSocketOpen" 258 /*@C 259 PetscViewerSocketOpen - Opens a connection to a MATLAB or other socket based server. 260 261 Collective on MPI_Comm 262 263 Input Parameters: 264 + comm - the MPI communicator 265 . machine - the machine the server is running on,, use NULL for the local machine, use "server" to passively wait for 266 a connection from elsewhere 267 - port - the port to connect to, use PETSC_DEFAULT for the default 268 269 Output Parameter: 270 . lab - a context to use when communicating with the server 271 272 Level: intermediate 273 274 Notes: 275 Most users should employ the following commands to access the 276 MATLAB PetscViewers 277 $ 278 $ PetscViewerSocketOpen(MPI_Comm comm, char *machine,int port,PetscViewer &viewer) 279 $ MatView(Mat matrix,PetscViewer viewer) 280 $ 281 $ or 282 $ 283 $ PetscViewerSocketOpen(MPI_Comm comm,char *machine,int port,PetscViewer &viewer) 284 $ VecView(Vec vector,PetscViewer viewer) 285 286 Options Database Keys: 287 For use with PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, 288 PETSC_VIEWER_SOCKET_() or if 289 NULL is passed for machine or PETSC_DEFAULT is passed for port 290 $ -viewer_socket_machine <machine> 291 $ -viewer_socket_port <port> 292 293 Environmental variables: 294 + PETSC_VIEWER_SOCKET_PORT portnumber 295 - PETSC_VIEWER_SOCKET_MACHINE machine name 296 297 Currently the only socket client available is MATLAB. See 298 src/dm/examples/tests/ex12.c and ex12.m for an example of usage. 299 300 Notes: The socket viewer is in some sense a subclass of the binary viewer, to read and write to the socket 301 use PetscViewerBinaryRead(), PetscViewerBinaryWrite(), PetscViewerBinarWriteStringArray(), PetscViewerBinaryGetDescriptor(). 302 303 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 304 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 305 for communicating with a MATLAB Engine 306 307 Concepts: MATLAB^sending data 308 Concepts: sockets^sending data 309 310 .seealso: MatView(), VecView(), PetscViewerDestroy(), PetscViewerCreate(), PetscViewerSetType(), 311 PetscViewerSocketSetConnection(), PETSC_VIEWER_SOCKET_, PETSC_VIEWER_SOCKET_WORLD, 312 PETSC_VIEWER_SOCKET_SELF, PetscViewerBinaryWrite(), PetscViewerBinaryRead(), PetscViewerBinaryWriteStringArray(), 313 PetscBinaryViewerGetDescriptor(), PetscMatlabEngineCreate() 314 @*/ 315 PetscErrorCode PetscViewerSocketOpen(MPI_Comm comm,const char machine[],int port,PetscViewer *lab) 316 { 317 PetscErrorCode ierr; 318 319 PetscFunctionBegin; 320 ierr = PetscViewerCreate(comm,lab);CHKERRQ(ierr); 321 ierr = PetscViewerSetType(*lab,PETSCVIEWERSOCKET);CHKERRQ(ierr); 322 ierr = PetscViewerSocketSetConnection(*lab,machine,port);CHKERRQ(ierr); 323 PetscFunctionReturn(0); 324 } 325 326 #undef __FUNCT__ 327 #define __FUNCT__ "PetscViewerSetFromOptions_Socket" 328 static PetscErrorCode PetscViewerSetFromOptions_Socket(PetscOptionItems *PetscOptionsObject,PetscViewer v) 329 { 330 PetscErrorCode ierr; 331 PetscInt def = -1; 332 char sdef[256]; 333 PetscBool tflg; 334 335 PetscFunctionBegin; 336 /* 337 These options are not processed here, they are processed in PetscViewerSocketSetConnection(), they 338 are listed here for the GUI to display 339 */ 340 ierr = PetscOptionsHead(PetscOptionsObject,"Socket PetscViewer Options");CHKERRQ(ierr); 341 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",sdef,16,&tflg);CHKERRQ(ierr); 342 if (tflg) { 343 ierr = PetscOptionsStringToInt(sdef,&def);CHKERRQ(ierr); 344 } else def = PETSCSOCKETDEFAULTPORT; 345 ierr = PetscOptionsInt("-viewer_socket_port","Port number to use for socket","PetscViewerSocketSetConnection",def,0,0);CHKERRQ(ierr); 346 347 ierr = PetscOptionsString("-viewer_socket_machine","Machine to use for socket","PetscViewerSocketSetConnection",sdef,0,0,0);CHKERRQ(ierr); 348 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",sdef,256,&tflg);CHKERRQ(ierr); 349 if (!tflg) { 350 ierr = PetscGetHostName(sdef,256);CHKERRQ(ierr); 351 } 352 ierr = PetscOptionsTail();CHKERRQ(ierr); 353 PetscFunctionReturn(0); 354 } 355 356 #undef __FUNCT__ 357 #define __FUNCT__ "PetscViewerBinaryGetSkipHeader_Socket" 358 static PetscErrorCode PetscViewerBinaryGetSkipHeader_Socket(PetscViewer viewer,PetscBool *skip) 359 { 360 PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data; 361 362 PetscFunctionBegin; 363 *skip = vsocket->skipheader; 364 PetscFunctionReturn(0); 365 } 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "PetscViewerBinarySetSkipHeader_Socket" 369 static PetscErrorCode PetscViewerBinarySetSkipHeader_Socket(PetscViewer viewer,PetscBool skip) 370 { 371 PetscViewer_Socket *vsocket = (PetscViewer_Socket*)viewer->data; 372 373 PetscFunctionBegin; 374 vsocket->skipheader = skip; 375 PetscFunctionReturn(0); 376 } 377 378 #undef __FUNCT__ 379 #define __FUNCT__ "PetscViewerBinaryGetFlowControl_Socket" 380 static PetscErrorCode PetscViewerBinaryGetFlowControl_Socket(PetscViewer viewer,PetscInt *fc) 381 { 382 PetscFunctionBegin; 383 *fc = 0; 384 PetscFunctionReturn(0); 385 } 386 387 /*MC 388 PETSCVIEWERSOCKET - A viewer that writes to a Unix socket 389 390 391 .seealso: PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD, 392 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, 393 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 394 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 395 396 Level: beginner 397 M*/ 398 399 #undef __FUNCT__ 400 #define __FUNCT__ "PetscViewerCreate_Socket" 401 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v) 402 { 403 PetscViewer_Socket *vmatlab; 404 PetscErrorCode ierr; 405 406 PetscFunctionBegin; 407 ierr = PetscNewLog(v,&vmatlab);CHKERRQ(ierr); 408 vmatlab->port = 0; 409 v->data = (void*)vmatlab; 410 v->ops->destroy = PetscViewerDestroy_Socket; 411 v->ops->flush = 0; 412 v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; 413 414 /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ 415 ierr = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr); 416 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinarySetSkipHeader_C",PetscViewerBinarySetSkipHeader_Socket);CHKERRQ(ierr); 417 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetSkipHeader_C",PetscViewerBinaryGetSkipHeader_Socket);CHKERRQ(ierr); 418 ierr = PetscObjectComposeFunction((PetscObject)v,"PetscViewerBinaryGetFlowControl_C",PetscViewerBinaryGetFlowControl_Socket);CHKERRQ(ierr); 419 420 PetscFunctionReturn(0); 421 } 422 423 #undef __FUNCT__ 424 #define __FUNCT__ "PetscViewerSocketSetConnection" 425 /*@C 426 PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 427 viewer is to use 428 429 Logically Collective on PetscViewer 430 431 Input Parameters: 432 + v - viewer to connect 433 . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for 434 a connection from elsewhere 435 - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default 436 437 Level: advanced 438 439 .seealso: PetscViewerSocketOpen() 440 @*/ 441 PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port) 442 { 443 PetscErrorCode ierr; 444 PetscMPIInt rank; 445 char mach[256]; 446 PetscBool tflg; 447 PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data; 448 449 PetscFunctionBegin; 450 /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */ 451 if (port <= 0) { 452 char portn[16]; 453 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr); 454 if (tflg) { 455 PetscInt pport; 456 ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr); 457 port = (int)pport; 458 } else port = PETSCSOCKETDEFAULTPORT; 459 } 460 if (!machine) { 461 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr); 462 if (!tflg) { 463 ierr = PetscGetHostName(mach,256);CHKERRQ(ierr); 464 } 465 } else { 466 ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr); 467 } 468 469 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr); 470 if (!rank) { 471 ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr); 472 if (tflg) { 473 int listenport; 474 ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr); 475 ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr); 476 ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr); 477 close(listenport); 478 } else { 479 ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr); 480 ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr); 481 } 482 } 483 PetscFunctionReturn(0); 484 } 485 486 /* ---------------------------------------------------------------------*/ 487 /* 488 The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that 489 is attached to a communicator, in this case the attribute is a PetscViewer. 490 */ 491 static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; 492 493 494 #undef __FUNCT__ 495 #define __FUNCT__ "PETSC_VIEWER_SOCKET_" 496 /*@C 497 PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 498 499 Collective on MPI_Comm 500 501 Input Parameter: 502 . comm - the MPI communicator to share the socket PetscViewer 503 504 Level: intermediate 505 506 Options Database Keys: 507 For use with the default PETSC_VIEWER_SOCKET_WORLD or if 508 NULL is passed for machine or PETSC_DEFAULT is passed for port 509 $ -viewer_socket_machine <machine> 510 $ -viewer_socket_port <port> 511 512 Environmental variables: 513 + PETSC_VIEWER_SOCKET_PORT portnumber 514 - PETSC_VIEWER_SOCKET_MACHINE machine name 515 516 Notes: 517 Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return 518 an error code. The socket PetscViewer is usually used in the form 519 $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm)); 520 521 Currently the only socket client available is MATLAB. See 522 src/dm/examples/tests/ex12.c and ex12.m for an example of usage. 523 524 Connects to a waiting socket and stays connected until PetscViewerDestroy() is called. 525 526 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 527 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 528 for communicating with a MATLAB Engine 529 530 .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(), 531 PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(), 532 PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_() 533 @*/ 534 PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm) 535 { 536 PetscErrorCode ierr; 537 PetscBool flg; 538 PetscViewer viewer; 539 MPI_Comm ncomm; 540 541 PetscFunctionBegin; 542 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 543 if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { 544 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0); 545 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 546 } 547 ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg); 548 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 549 if (!flg) { /* PetscViewer not yet created */ 550 ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer); 551 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 552 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 553 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 554 ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer); 555 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 556 } 557 ierr = PetscCommDestroy(&ncomm); 558 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 559 PetscFunctionReturn(viewer); 560 } 561 562