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