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