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 /*MC 357 PETSCVIEWERSOCKET - A viewer that writes to a Unix socket 358 359 360 .seealso: PetscViewerSocketOpen(), PetscViewerDrawOpen(), PETSC_VIEWER_DRAW_(),PETSC_VIEWER_DRAW_SELF, PETSC_VIEWER_DRAW_WORLD, 361 PetscViewerCreate(), PetscViewerASCIIOpen(), PetscViewerBinaryOpen(), PETSCVIEWERBINARY, PETSCVIEWERDRAW, 362 PetscViewerMatlabOpen(), VecView(), DMView(), PetscViewerMatlabPutArray(), PETSCVIEWERASCII, PETSCVIEWERMATLAB, 363 PetscViewerFileSetName(), PetscViewerFileSetMode(), PetscViewerFormat, PetscViewerType, PetscViewerSetType() 364 365 M*/ 366 367 #undef __FUNCT__ 368 #define __FUNCT__ "PetscViewerCreate_Socket" 369 PETSC_EXTERN PetscErrorCode PetscViewerCreate_Socket(PetscViewer v) 370 { 371 PetscViewer_Socket *vmatlab; 372 PetscErrorCode ierr; 373 374 PetscFunctionBegin; 375 ierr = PetscNewLog(v,&vmatlab);CHKERRQ(ierr); 376 vmatlab->port = 0; 377 v->data = (void*)vmatlab; 378 v->ops->destroy = PetscViewerDestroy_Socket; 379 v->ops->flush = 0; 380 v->ops->setfromoptions = PetscViewerSetFromOptions_Socket; 381 382 /* lie and say this is a binary viewer; then all the XXXView_Binary() methods will work correctly on it */ 383 ierr = PetscObjectChangeTypeName((PetscObject)v,PETSCVIEWERBINARY);CHKERRQ(ierr); 384 PetscFunctionReturn(0); 385 } 386 387 #undef __FUNCT__ 388 #define __FUNCT__ "PetscViewerSocketSetConnection" 389 /*@C 390 PetscViewerSocketSetConnection - Sets the machine and port that a PETSc socket 391 viewer is to use 392 393 Logically Collective on PetscViewer 394 395 Input Parameters: 396 + v - viewer to connect 397 . machine - host to connect to, use NULL for the local machine,use "server" to passively wait for 398 a connection from elsewhere 399 - port - the port on the machine one is connecting to, use PETSC_DEFAULT for default 400 401 Level: advanced 402 403 .seealso: PetscViewerSocketOpen() 404 @*/ 405 PetscErrorCode PetscViewerSocketSetConnection(PetscViewer v,const char machine[],int port) 406 { 407 PetscErrorCode ierr; 408 PetscMPIInt rank; 409 char mach[256]; 410 PetscBool tflg; 411 PetscViewer_Socket *vmatlab = (PetscViewer_Socket*)v->data; 412 413 PetscFunctionBegin; 414 /* PetscValidLogicalCollectiveInt(v,port,3); not a PetscInt */ 415 if (port <= 0) { 416 char portn[16]; 417 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_PORT",portn,16,&tflg);CHKERRQ(ierr); 418 if (tflg) { 419 PetscInt pport; 420 ierr = PetscOptionsStringToInt(portn,&pport);CHKERRQ(ierr); 421 port = (int)pport; 422 } else port = PETSCSOCKETDEFAULTPORT; 423 } 424 if (!machine) { 425 ierr = PetscOptionsGetenv(PetscObjectComm((PetscObject)v),"PETSC_VIEWER_SOCKET_MACHINE",mach,256,&tflg);CHKERRQ(ierr); 426 if (!tflg) { 427 ierr = PetscGetHostName(mach,256);CHKERRQ(ierr); 428 } 429 } else { 430 ierr = PetscStrncpy(mach,machine,256);CHKERRQ(ierr); 431 } 432 433 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)v),&rank);CHKERRQ(ierr); 434 if (!rank) { 435 ierr = PetscStrcmp(mach,"server",&tflg);CHKERRQ(ierr); 436 if (tflg) { 437 int listenport; 438 ierr = PetscInfo1(v,"Waiting for connection from socket process on port %D\n",port);CHKERRQ(ierr); 439 ierr = PetscSocketEstablish(port,&listenport);CHKERRQ(ierr); 440 ierr = PetscSocketListen(listenport,&vmatlab->port);CHKERRQ(ierr); 441 close(listenport); 442 } else { 443 ierr = PetscInfo2(v,"Connecting to socket process on port %D machine %s\n",port,mach);CHKERRQ(ierr); 444 ierr = PetscOpenSocket(mach,port,&vmatlab->port);CHKERRQ(ierr); 445 } 446 } 447 PetscFunctionReturn(0); 448 } 449 450 /* ---------------------------------------------------------------------*/ 451 /* 452 The variable Petsc_Viewer_Socket_keyval is used to indicate an MPI attribute that 453 is attached to a communicator, in this case the attribute is a PetscViewer. 454 */ 455 static PetscMPIInt Petsc_Viewer_Socket_keyval = MPI_KEYVAL_INVALID; 456 457 458 #undef __FUNCT__ 459 #define __FUNCT__ "PETSC_VIEWER_SOCKET_" 460 /*@C 461 PETSC_VIEWER_SOCKET_ - Creates a socket viewer shared by all processors in a communicator. 462 463 Collective on MPI_Comm 464 465 Input Parameter: 466 . comm - the MPI communicator to share the socket PetscViewer 467 468 Level: intermediate 469 470 Options Database Keys: 471 For use with the default PETSC_VIEWER_SOCKET_WORLD or if 472 NULL is passed for machine or PETSC_DEFAULT is passed for port 473 $ -viewer_socket_machine <machine> 474 $ -viewer_socket_port <port> 475 476 Environmental variables: 477 + PETSC_VIEWER_SOCKET_PORT portnumber 478 - PETSC_VIEWER_SOCKET_MACHINE machine name 479 480 Notes: 481 Unlike almost all other PETSc routines, PetscViewer_SOCKET_ does not return 482 an error code. The socket PetscViewer is usually used in the form 483 $ XXXView(XXX object,PETSC_VIEWER_SOCKET_(comm)); 484 485 Currently the only socket client available is MATLAB. See 486 src/dm/examples/tests/ex12.c and ex12.m for an example of usage. 487 488 Connects to a waiting socket and stays connected until PetscViewerDestroy() is called. 489 490 Use this for communicating with an interactive MATLAB session, see PETSC_VIEWER_MATLAB_() for writing output to a 491 .mat file. Use PetscMatlabEngineCreate() or PETSC_MATLAB_ENGINE_(), PETSC_MATLAB_ENGINE_SELF, or PETSC_MATLAB_ENGINE_WORLD 492 for communicating with a MATLAB Engine 493 494 .seealso: PETSC_VIEWER_SOCKET_WORLD, PETSC_VIEWER_SOCKET_SELF, PetscViewerSocketOpen(), PetscViewerCreate(), 495 PetscViewerSocketSetConnection(), PetscViewerDestroy(), PETSC_VIEWER_SOCKET_(), PetscViewerBinaryWrite(), PetscViewerBinaryRead(), 496 PetscViewerBinaryWriteStringArray(), PetscViewerBinaryGetDescriptor(), PETSC_VIEWER_MATLAB_() 497 @*/ 498 PetscViewer PETSC_VIEWER_SOCKET_(MPI_Comm comm) 499 { 500 PetscErrorCode ierr; 501 PetscBool flg; 502 PetscViewer viewer; 503 MPI_Comm ncomm; 504 505 PetscFunctionBegin; 506 ierr = PetscCommDuplicate(comm,&ncomm,NULL);if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 507 if (Petsc_Viewer_Socket_keyval == MPI_KEYVAL_INVALID) { 508 ierr = MPI_Keyval_create(MPI_NULL_COPY_FN,MPI_NULL_DELETE_FN,&Petsc_Viewer_Socket_keyval,0); 509 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 510 } 511 ierr = MPI_Attr_get(ncomm,Petsc_Viewer_Socket_keyval,(void**)&viewer,(int*)&flg); 512 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 513 if (!flg) { /* PetscViewer not yet created */ 514 ierr = PetscViewerSocketOpen(ncomm,0,0,&viewer); 515 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 516 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 517 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 518 ierr = MPI_Attr_put(ncomm,Petsc_Viewer_Socket_keyval,(void*)viewer); 519 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 520 } 521 ierr = PetscCommDestroy(&ncomm); 522 if (ierr) {PetscError(PETSC_COMM_SELF,__LINE__,"PETSC_VIEWER_SOCKET_",__FILE__,PETSC_ERR_PLIB,PETSC_ERROR_INITIAL," ");PetscFunctionReturn(0);} 523 PetscFunctionReturn(viewer); 524 } 525 526