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