1 #define PETSC_DLL 2 /* 3 Utilites routines to add simple ASCII IO capability. 4 */ 5 #include "src/sys/fileio/mprint.h" 6 #include "petscconfiginfo.h" 7 /* 8 If petsc_history is on, then all Petsc*Printf() results are saved 9 if the appropriate (usually .petschistory) file. 10 */ 11 extern FILE *petsc_history; 12 /* 13 Allows one to overwrite where standard out is sent. For example 14 PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out 15 writes to go to terminal XX; assuming you have write permission there 16 */ 17 FILE *PETSC_STDOUT = 0; 18 19 #undef __FUNCT__ 20 #define __FUNCT__ "PetscFormatConvert" 21 PetscErrorCode PETSC_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size) 22 { 23 PetscInt i = 0,j = 0; 24 25 while (format[i] && i < size-1) { 26 if (format[i] == '%' && format[i+1] == 'D') { 27 newformat[j++] = '%'; 28 #if defined(PETSC_USE_32BIT_INT) 29 newformat[j++] = 'd'; 30 #else 31 newformat[j++] = 'l'; 32 newformat[j++] = 'l'; 33 newformat[j++] = 'd'; 34 #endif 35 i += 2; 36 } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') { 37 newformat[j++] = '%'; 38 newformat[j++] = format[i+1]; 39 #if defined(PETSC_USE_32BIT_INT) 40 newformat[j++] = 'd'; 41 #else 42 newformat[j++] = 'l'; 43 newformat[j++] = 'l'; 44 newformat[j++] = 'd'; 45 #endif 46 i += 3; 47 } else if (format[i] == '%' && format[i+1] == 'G') { 48 newformat[j++] = '%'; 49 #if !defined(PETSC_USE_LONG_DOUBLE) 50 newformat[j++] = 'g'; 51 #else 52 newformat[j++] = 'L'; 53 newformat[j++] = 'g'; 54 #endif 55 i += 2; 56 }else { 57 newformat[j++] = format[i++]; 58 } 59 } 60 newformat[j] = 0; 61 return 0; 62 } 63 64 #undef __FUNCT__ 65 #define __FUNCT__ "PetscVSNPrintf" 66 /* 67 No error handling because may be called by error handler 68 */ 69 PetscErrorCode PETSC_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,va_list Argp) 70 { 71 /* no malloc since may be called by error handler */ 72 char newformat[8*1024]; 73 size_t length; 74 PetscErrorCode ierr; 75 76 PetscFormatConvert(format,newformat,8*1024); 77 ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr); 78 if (length > len) { 79 newformat[len] = '\0'; 80 } 81 #if defined(PETSC_HAVE_VPRINTF_CHAR) 82 vsprintf(str,newformat,(char *)Argp); 83 #else 84 vsprintf(str,newformat,Argp); 85 #endif 86 return 0; 87 } 88 89 #undef __FUNCT__ 90 #define __FUNCT__ "PetscVFPrintf" 91 /* 92 All PETSc standard out and error messages are sent through this function; so, in theory, this can 93 can be replaced with something that does not simply write to a file. 94 95 Note: For error messages this may be called by a process, for regular standard out it is 96 called only by process 0 of a given communicator 97 98 No error handling because may be called by error handler 99 */ 100 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintf(FILE *fd,const char *format,va_list Argp) 101 { 102 /* no malloc since may be called by error handler */ 103 char newformat[8*1024]; 104 105 PetscFormatConvert(format,newformat,8*1024); 106 #if defined(PETSC_HAVE_VPRINTF_CHAR) 107 vfprintf(fd,newformat,(char *)Argp); 108 #else 109 vfprintf(fd,newformat,Argp); 110 fflush(fd); 111 #endif 112 return 0; 113 } 114 115 /* ----------------------------------------------------------------------- */ 116 117 PrintfQueue queue = 0,queuebase = 0; 118 int queuelength = 0; 119 FILE *queuefile = PETSC_NULL; 120 121 #undef __FUNCT__ 122 #define __FUNCT__ "PetscSynchronizedPrintf" 123 /*@C 124 PetscSynchronizedPrintf - Prints synchronized output from several processors. 125 Output of the first processor is followed by that of the second, etc. 126 127 Not Collective 128 129 Input Parameters: 130 + comm - the communicator 131 - format - the usual printf() format string 132 133 Level: intermediate 134 135 Notes: 136 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 137 from all the processors to be printed. 138 139 Fortran Note: 140 The call sequence is PetscSynchronizedPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. 141 That is, you can only pass a single character string from Fortran. 142 143 The length of the formatted message cannot exceed QUEUESTRINGSIZE characters. 144 145 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 146 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 147 @*/ 148 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 149 { 150 PetscErrorCode ierr; 151 PetscMPIInt rank; 152 153 PetscFunctionBegin; 154 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 155 156 /* First processor prints immediately to stdout */ 157 if (!rank) { 158 va_list Argp; 159 va_start(Argp,format); 160 ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 161 if (petsc_history) { 162 ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr); 163 } 164 va_end(Argp); 165 } else { /* other processors add to local queue */ 166 va_list Argp; 167 PrintfQueue next; 168 169 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 170 if (queue) {queue->next = next; queue = next; queue->next = 0;} 171 else {queuebase = queue = next;} 172 queuelength++; 173 va_start(Argp,format); 174 ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr); 175 ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr); 176 va_end(Argp); 177 } 178 179 PetscFunctionReturn(0); 180 } 181 182 #undef __FUNCT__ 183 #define __FUNCT__ "PetscSynchronizedFPrintf" 184 /*@C 185 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 186 several processors. Output of the first processor is followed by that of the 187 second, etc. 188 189 Not Collective 190 191 Input Parameters: 192 + comm - the communicator 193 . fd - the file pointer 194 - format - the usual printf() format string 195 196 Level: intermediate 197 198 Notes: 199 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 200 from all the processors to be printed. 201 202 The length of the formatted message cannot exceed QUEUESTRINGSIZE characters. 203 204 Contributed by: Matthew Knepley 205 206 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 207 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 208 209 @*/ 210 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...) 211 { 212 PetscErrorCode ierr; 213 PetscMPIInt rank; 214 215 PetscFunctionBegin; 216 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 217 218 /* First processor prints immediately to fp */ 219 if (!rank) { 220 va_list Argp; 221 va_start(Argp,format); 222 ierr = PetscVFPrintf(fp,format,Argp);CHKERRQ(ierr); 223 queuefile = fp; 224 if (petsc_history) { 225 ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr); 226 } 227 va_end(Argp); 228 } else { /* other processors add to local queue */ 229 va_list Argp; 230 PrintfQueue next; 231 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 232 if (queue) {queue->next = next; queue = next; queue->next = 0;} 233 else {queuebase = queue = next;} 234 queuelength++; 235 va_start(Argp,format); 236 ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr); 237 ierr = PetscVSNPrintf(next->string,QUEUESTRINGSIZE,format,Argp);CHKERRQ(ierr); 238 va_end(Argp); 239 } 240 PetscFunctionReturn(0); 241 } 242 243 #undef __FUNCT__ 244 #define __FUNCT__ "PetscSynchronizedFlush" 245 /*@ 246 PetscSynchronizedFlush - Flushes to the screen output from all processors 247 involved in previous PetscSynchronizedPrintf() calls. 248 249 Collective on MPI_Comm 250 251 Input Parameters: 252 . comm - the communicator 253 254 Level: intermediate 255 256 Notes: 257 Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with 258 different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush(). 259 260 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 261 PetscViewerASCIISynchronizedPrintf() 262 @*/ 263 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm) 264 { 265 PetscErrorCode ierr; 266 PetscMPIInt rank,size,tag,i,j,n; 267 char message[QUEUESTRINGSIZE]; 268 MPI_Status status; 269 FILE *fd; 270 271 PetscFunctionBegin; 272 ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); 273 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 274 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 275 276 /* First processor waits for messages from all other processors */ 277 if (!rank) { 278 if (queuefile) { 279 fd = queuefile; 280 } else { 281 fd = PETSC_STDOUT; 282 } 283 for (i=1; i<size; i++) { 284 ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 285 for (j=0; j<n; j++) { 286 ierr = MPI_Recv(message,QUEUESTRINGSIZE,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr); 287 ierr = PetscFPrintf(comm,fd,"%s",message); 288 } 289 } 290 queuefile = PETSC_NULL; 291 } else { /* other processors send queue to processor 0 */ 292 PrintfQueue next = queuebase,previous; 293 294 ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 295 for (i=0; i<queuelength; i++) { 296 ierr = MPI_Send(next->string,QUEUESTRINGSIZE,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); 297 previous = next; 298 next = next->next; 299 ierr = PetscFree(previous);CHKERRQ(ierr); 300 } 301 queue = 0; 302 queuelength = 0; 303 } 304 ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 305 PetscFunctionReturn(0); 306 } 307 308 /* ---------------------------------------------------------------------------------------*/ 309 310 #undef __FUNCT__ 311 #define __FUNCT__ "PetscFPrintf" 312 /*@C 313 PetscFPrintf - Prints to a file, only from the first 314 processor in the communicator. 315 316 Not Collective 317 318 Input Parameters: 319 + comm - the communicator 320 . fd - the file pointer 321 - format - the usual printf() format string 322 323 Level: intermediate 324 325 Fortran Note: 326 This routine is not supported in Fortran. 327 328 Concepts: printing^in parallel 329 Concepts: printf^in parallel 330 331 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 332 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 333 @*/ 334 PetscErrorCode PETSC_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 335 { 336 PetscErrorCode ierr; 337 PetscMPIInt rank; 338 339 PetscFunctionBegin; 340 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 341 if (!rank) { 342 va_list Argp; 343 va_start(Argp,format); 344 ierr = PetscVFPrintf(fd,format,Argp);CHKERRQ(ierr); 345 if (petsc_history) { 346 ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr); 347 } 348 va_end(Argp); 349 } 350 PetscFunctionReturn(0); 351 } 352 353 #undef __FUNCT__ 354 #define __FUNCT__ "PetscPrintf" 355 /*@C 356 PetscPrintf - Prints to standard out, only from the first 357 processor in the communicator. 358 359 Not Collective 360 361 Input Parameters: 362 + comm - the communicator 363 - format - the usual printf() format string 364 365 Level: intermediate 366 367 Fortran Note: 368 The call sequence is PetscPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. 369 That is, you can only pass a single character string from Fortran. 370 371 Notes: %A is replace with %g unless the value is < 1.e-12 when it is 372 replaced with < 1.e-12 373 374 Concepts: printing^in parallel 375 Concepts: printf^in parallel 376 377 .seealso: PetscFPrintf(), PetscSynchronizedPrintf() 378 @*/ 379 PetscErrorCode PETSC_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...) 380 { 381 PetscErrorCode ierr; 382 PetscMPIInt rank; 383 size_t len; 384 char *nformat,*sub1,*sub2; 385 PetscReal value; 386 387 PetscFunctionBegin; 388 if (!comm) comm = PETSC_COMM_WORLD; 389 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 390 if (!rank) { 391 va_list Argp; 392 va_start(Argp,format); 393 394 ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr); 395 if (sub1) { 396 ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr); 397 if (sub1 != sub2) SETERRQ(PETSC_ERR_ARG_WRONG,"%%A format must be first in format string"); 398 ierr = PetscStrlen(format,&len);CHKERRQ(ierr); 399 ierr = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr); 400 ierr = PetscStrcpy(nformat,format);CHKERRQ(ierr); 401 ierr = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr); 402 sub2[0] = 0; 403 value = (double)va_arg(Argp,double); 404 if (PetscAbsReal(value) < 1.e-12) { 405 ierr = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr); 406 } else { 407 ierr = PetscStrcat(nformat,"%g");CHKERRQ(ierr); 408 va_end(Argp); 409 va_start(Argp,format); 410 } 411 ierr = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr); 412 } else { 413 nformat = (char*)format; 414 } 415 ierr = PetscVFPrintf(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr); 416 if (petsc_history) { 417 ierr = PetscVFPrintf(petsc_history,nformat,Argp);CHKERRQ(ierr); 418 } 419 va_end(Argp); 420 if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);} 421 } 422 PetscFunctionReturn(0); 423 } 424 425 /* ---------------------------------------------------------------------------------------*/ 426 #undef __FUNCT__ 427 #define __FUNCT__ "PetscHelpPrintfDefault" 428 PetscErrorCode PETSC_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 429 { 430 PetscErrorCode ierr; 431 PetscMPIInt rank; 432 433 PetscFunctionBegin; 434 if (!comm) comm = PETSC_COMM_WORLD; 435 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 436 if (!rank) { 437 va_list Argp; 438 va_start(Argp,format); 439 ierr = PetscVFPrintf(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 440 if (petsc_history) { 441 ierr = PetscVFPrintf(petsc_history,format,Argp);CHKERRQ(ierr); 442 } 443 va_end(Argp); 444 } 445 PetscFunctionReturn(0); 446 } 447 448 /* ---------------------------------------------------------------------------------------*/ 449 450 static char arch[10],hostname[64],username[16],pname[PETSC_MAX_PATH_LEN],date[64]; 451 static PetscTruth PetscErrorPrintfInitializeCalled = PETSC_FALSE; 452 453 #undef __FUNCT__ 454 #define __FUNCT__ "PetscErrorPrintfInitialize" 455 /* 456 Initializes arch, hostname, username,date so that system calls do NOT need 457 to be made during the error handler. 458 */ 459 PetscErrorCode PETSC_DLLEXPORT PetscErrorPrintfInitialize() 460 { 461 PetscErrorCode ierr; 462 463 PetscFunctionBegin; 464 ierr = PetscGetArchType(arch,10);CHKERRQ(ierr); 465 ierr = PetscGetHostName(hostname,64);CHKERRQ(ierr); 466 ierr = PetscGetUserName(username,16);CHKERRQ(ierr); 467 ierr = PetscGetProgramName(pname,PETSC_MAX_PATH_LEN);CHKERRQ(ierr); 468 ierr = PetscGetDate(date,64);CHKERRQ(ierr); 469 PetscErrorPrintfInitializeCalled = PETSC_TRUE; 470 PetscFunctionReturn(0); 471 } 472 473 474 #undef __FUNCT__ 475 #define __FUNCT__ "PetscErrorPrintfDefault" 476 PetscErrorCode PETSC_DLLEXPORT PetscErrorPrintfDefault(const char format[],...) 477 { 478 va_list Argp; 479 static PetscTruth PetscErrorPrintfCalled = PETSC_FALSE; 480 static PetscTruth InPetscErrorPrintfDefault = PETSC_FALSE; 481 static FILE *fd; 482 char version[256]; 483 PetscErrorCode ierr; 484 485 /* 486 InPetscErrorPrintfDefault is used to prevent the error handler called (potentially) 487 from PetscSleep(), PetscGetArchName(), ... below from printing its own error message. 488 */ 489 490 /* 491 This function does not call PetscFunctionBegin and PetscFunctionReturn() because 492 it may be called by PetscStackView(). 493 494 This function does not do error checking because it is called by the error handlers. 495 */ 496 497 if (!PetscErrorPrintfCalled) { 498 PetscTruth use_stderr; 499 500 PetscErrorPrintfCalled = PETSC_TRUE; 501 InPetscErrorPrintfDefault = PETSC_TRUE; 502 503 PetscOptionsHasName(PETSC_NULL,"-error_output_stderr",&use_stderr); 504 if (use_stderr) { 505 fd = stderr; 506 } else { 507 fd = PETSC_STDOUT; 508 } 509 510 /* 511 On the SGI machines and Cray T3E, if errors are generated "simultaneously" by 512 different processors, the messages are printed all jumbled up; to try to 513 prevent this we have each processor wait based on their rank 514 */ 515 #if defined(PETSC_CAN_SLEEP_AFTER_ERROR) 516 { 517 PetscMPIInt rank; 518 if (PetscGlobalRank > 8) rank = 8; else rank = PetscGlobalRank; 519 PetscSleep(rank); 520 } 521 #endif 522 523 ierr = PetscGetVersion(&version);CHKERRQ(ierr); 524 525 PetscFPrintf(PETSC_COMM_SELF,fd,"------------------------------------------------------------------------\n"); 526 PetscFPrintf(PETSC_COMM_SELF,fd,"%s\n",version); 527 PetscFPrintf(PETSC_COMM_SELF,fd,"See docs/changes/index.html for recent updates.\n"); 528 PetscFPrintf(PETSC_COMM_SELF,fd,"See docs/faq.html for hints about trouble shooting.\n"); 529 PetscFPrintf(PETSC_COMM_SELF,fd,"See docs/index.html for manual pages.\n"); 530 PetscFPrintf(PETSC_COMM_SELF,fd,"------------------------------------------------------------------------\n"); 531 if (PetscErrorPrintfInitializeCalled) { 532 PetscFPrintf(PETSC_COMM_SELF,fd,"%s on a %s named %s by %s %s\n",pname,arch,hostname,username,date); 533 } 534 PetscFPrintf(PETSC_COMM_SELF,fd,"Libraries linked from %s\n",PETSC_LIB_DIR); 535 PetscFPrintf(PETSC_COMM_SELF,fd,"Configure run at %s\n",petscconfigureruntime); 536 PetscFPrintf(PETSC_COMM_SELF,fd,"Configure options %s\n",petscconfigureoptions); 537 PetscFPrintf(PETSC_COMM_SELF,fd,"------------------------------------------------------------------------\n"); 538 InPetscErrorPrintfDefault = PETSC_FALSE; 539 } 540 541 if (!InPetscErrorPrintfDefault) { 542 PetscFPrintf(PETSC_COMM_SELF,fd,"[%d]PETSC ERROR: ",PetscGlobalRank); 543 va_start(Argp,format); 544 PetscVFPrintf(fd,format,Argp); 545 va_end(Argp); 546 } 547 return 0; 548 } 549 550 #undef __FUNCT__ 551 #define __FUNCT__ "PetscSynchronizedFGets" 552 /*@C 553 PetscSynchronizedFGets - Several processors all get the same line from a file. 554 555 Collective on MPI_Comm 556 557 Input Parameters: 558 + comm - the communicator 559 . fd - the file pointer 560 - len - the length of the output buffer 561 562 Output Parameter: 563 . string - the line read from the file 564 565 Level: intermediate 566 567 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 568 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 569 570 @*/ 571 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[]) 572 { 573 PetscErrorCode ierr; 574 PetscMPIInt rank; 575 576 PetscFunctionBegin; 577 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 578 579 if (!rank) { 580 fgets(string,len,fp); 581 } 582 ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); 583 PetscFunctionReturn(0); 584 } 585