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