1 /* 2 Utilites routines to add simple ASCII IO capability. 3 */ 4 #include <../src/sys/fileio/mprint.h> 5 #include <errno.h> 6 /* 7 If petsc_history is on, then all Petsc*Printf() results are saved 8 if the appropriate (usually .petschistory) file. 9 */ 10 extern FILE *petsc_history; 11 /* 12 Allows one to overwrite where standard out is sent. For example 13 PETSC_STDOUT = fopen("/dev/ttyXX","w") will cause all standard out 14 writes to go to terminal XX; assuming you have write permission there 15 */ 16 FILE *PETSC_STDOUT = 0; 17 /* 18 Allows one to overwrite where standard error is sent. For example 19 PETSC_STDERR = fopen("/dev/ttyXX","w") will cause all standard error 20 writes to go to terminal XX; assuming you have write permission there 21 */ 22 FILE *PETSC_STDERR = 0; 23 24 /*@C 25 PetscFormatConvertGetSize - Gets the length of a string needed to hold format converted with PetscFormatConvert() 26 27 Input Parameter: 28 . format - the PETSc format string 29 30 Output Parameter: 31 . size - the needed length of the new format 32 33 Level: developer 34 35 .seealso: PetscFormatConvert(), PetscVSNPrintf(), PetscVFPrintf() 36 37 @*/ 38 PetscErrorCode PetscFormatConvertGetSize(const char *format,size_t *size) 39 { 40 PetscInt i = 0; 41 42 PetscFunctionBegin; 43 *size = 0; 44 while (format[i]) { 45 if (format[i] == '%' && format[i+1] == '%') { 46 i++; i++; *size += 2; 47 } else if (format[i] == '%') { 48 /* Find the letter */ 49 for (; format[i] && format[i] <= '9'; i++,(*size += 1)); 50 switch (format[i]) { 51 case 'D': 52 #if defined(PETSC_USE_64BIT_INDICES) 53 *size += 2; 54 #endif 55 break; 56 case 'g': 57 *size += 4; 58 break; 59 default: 60 break; 61 } 62 *size += 1; 63 i++; 64 } else { 65 i++; 66 *size += 1; 67 } 68 } 69 *size += 1; /* space for NULL character */ 70 PetscFunctionReturn(0); 71 } 72 73 /*@C 74 PetscFormatConvert - Takes a PETSc format string and converts the %D to %d for 32 bit PETSc indices and %lld for 64 bit PETSc indices. Also 75 converts %g to [|%g|] so that PetscVSNPrintf() can easily insure all %g formatted numbers have a decimal point when printed. 76 77 Input Parameters: 78 + format - the PETSc format string 79 . newformat - the location to put the new format 80 - size - the length of newformat, you can use PetscFormatConvertGetSize() to compute the needed size 81 82 Note: this exists so we can have the same code when PetscInt is either int or long long int 83 84 Level: developer 85 86 .seealso: PetscFormatConvertGetSize(), PetscVSNPrintf(), PetscVFPrintf() 87 88 @*/ 89 PetscErrorCode PetscFormatConvert(const char *format,char *newformat) 90 { 91 PetscInt i = 0, j = 0; 92 93 PetscFunctionBegin; 94 while (format[i]) { 95 if (format[i] == '%' && format[i+1] == '%') { 96 newformat[j++] = format[i++]; 97 newformat[j++] = format[i++]; 98 } else if (format[i] == '%') { 99 if (format[i+1] == 'g') { 100 newformat[j++] = '['; 101 newformat[j++] = '|'; 102 } 103 /* Find the letter */ 104 for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i]; 105 switch (format[i]) { 106 case 'D': 107 #if !defined(PETSC_USE_64BIT_INDICES) 108 newformat[j++] = 'd'; 109 #else 110 newformat[j++] = 'l'; 111 newformat[j++] = 'l'; 112 newformat[j++] = 'd'; 113 #endif 114 break; 115 case 'g': 116 newformat[j++] = format[i]; 117 if (format[i-1] == '%') { 118 newformat[j++] = '|'; 119 newformat[j++] = ']'; 120 } 121 break; 122 case 'G': 123 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%G format is no longer supported, use %%g and cast the argument to double"); 124 break; 125 case 'F': 126 SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SUP,"%%F format is no longer supported, use %%f and cast the argument to double"); 127 break; 128 default: 129 newformat[j++] = format[i]; 130 break; 131 } 132 i++; 133 } else newformat[j++] = format[i++]; 134 } 135 newformat[j] = 0; 136 PetscFunctionReturn(0); 137 } 138 139 #define PETSCVSNPRINTFDEFAULTFORMATBUFFERSIZE 8*1024 140 141 /*@C 142 PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the 143 function arguments into a string using the format statement. 144 145 Input Parameters: 146 + str - location to put result 147 . len - the amount of space in str 148 + format - the PETSc format string 149 - fullLength - the amount of space in str actually used. 150 151 Developer Notes: this function may be called from an error handler, if an error occurs when it is called by the error handler than likely 152 a recursion will occur and possible crash. 153 154 Level: developer 155 156 .seealso: PetscVSNPrintf(), PetscErrorPrintf(), PetscVPrintf() 157 158 @*/ 159 PetscErrorCode PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp) 160 { 161 char *newformat = NULL; 162 char formatbuf[PETSCVSNPRINTFDEFAULTFORMATBUFFERSIZE]; 163 size_t newLength; 164 PetscErrorCode ierr; 165 166 PetscFunctionBegin; 167 ierr = PetscFormatConvertGetSize(format,&newLength);CHKERRQ(ierr); 168 if (newLength < PETSCVSNPRINTFDEFAULTFORMATBUFFERSIZE) { 169 newformat = formatbuf; 170 newLength = PETSCVSNPRINTFDEFAULTFORMATBUFFERSIZE-1; 171 } else { 172 ierr = PetscMalloc1(newLength, &newformat);CHKERRQ(ierr); 173 } 174 ierr = PetscFormatConvert(format,newformat);CHKERRQ(ierr); 175 #if defined(PETSC_HAVE_VSNPRINTF_CHAR) 176 (void) vsnprintf(str,len,newformat,(char*)Argp); 177 #elif defined(PETSC_HAVE_VSNPRINTF) 178 (void) vsnprintf(str,len,newformat,Argp); 179 #elif defined(PETSC_HAVE__VSNPRINTF) 180 (void) _vsnprintf(str,len,newformat,Argp); 181 #else 182 #error "vsnprintf not found" 183 #endif 184 if (newLength > PETSCVSNPRINTFDEFAULTFORMATBUFFERSIZE-1) { 185 ierr = PetscFree(newformat);CHKERRQ(ierr); 186 } 187 { 188 PetscBool foundedot; 189 size_t cnt = 0,ncnt = 0,leng; 190 ierr = PetscStrlen(str,&leng);CHKERRQ(ierr); 191 if (leng > 4) { 192 for (cnt=0; cnt<leng-4; cnt++) { 193 if (str[cnt] == '[' && str[cnt+1] == '|'){ 194 cnt++; cnt++; 195 foundedot = PETSC_FALSE; 196 for (; cnt<leng-1; cnt++) { 197 if (str[cnt] == '|' && str[cnt+1] == ']'){ 198 cnt++; 199 if (!foundedot) str[ncnt++] = '.'; 200 ncnt--; 201 break; 202 } else { 203 if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE; 204 str[ncnt++] = str[cnt]; 205 } 206 } 207 } else { 208 str[ncnt] = str[cnt]; 209 } 210 ncnt++; 211 } 212 while (cnt < leng) { 213 str[ncnt] = str[cnt]; ncnt++; cnt++; 214 } 215 str[ncnt] = 0; 216 } 217 } 218 #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT) 219 /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */ 220 { 221 size_t cnt = 0,ncnt = 0,leng; 222 ierr = PetscStrlen(str,&leng);CHKERRQ(ierr); 223 if (leng > 5) { 224 for (cnt=0; cnt<leng-4; cnt++) { 225 if (str[cnt] == 'e' && (str[cnt+1] == '-' || str[cnt+1] == '+') && str[cnt+2] == '0' && str[cnt+3] >= '0' && str[cnt+3] <= '9' && str[cnt+4] >= '0' && str[cnt+4] <= '9') { 226 str[ncnt] = str[cnt]; ncnt++; cnt++; 227 str[ncnt] = str[cnt]; ncnt++; cnt++; cnt++; 228 str[ncnt] = str[cnt]; 229 } else { 230 str[ncnt] = str[cnt]; 231 } 232 ncnt++; 233 } 234 while (cnt < leng) { 235 str[ncnt] = str[cnt]; ncnt++; cnt++; 236 } 237 str[ncnt] = 0; 238 } 239 } 240 #endif 241 if (fullLength) { 242 ierr = PetscStrlen(str,fullLength);CHKERRQ(ierr); 243 } 244 PetscFunctionReturn(0); 245 } 246 247 /*@C 248 PetscVFPrintf - All PETSc standard out and error messages are sent through this function; so, in theory, this can 249 can be replaced with something that does not simply write to a file. 250 251 To use, write your own function for example, 252 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp) 253 ${ 254 $ PetscErrorCode ierr; 255 $ 256 $ PetscFunctionBegin; 257 $ if (fd != stdout && fd != stderr) { handle regular files 258 $ ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERR(ierr); 259 $ } else { 260 $ char buff[BIG]; 261 $ size_t length; 262 $ ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr); 263 $ now send buff to whatever stream or whatever you want 264 $ } 265 $ PetscFunctionReturn(0); 266 $} 267 then before the call to PetscInitialize() do the assignment 268 $ PetscVFPrintf = mypetscvfprintf; 269 270 Notes: For error messages this may be called by any process, for regular standard out it is 271 called only by process 0 of a given communicator 272 273 Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur 274 and a crash 275 276 Level: developer 277 278 .seealso: PetscVSNPrintf(), PetscErrorPrintf() 279 280 @*/ 281 PetscErrorCode PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 282 { 283 char str[8*1024]; 284 PetscErrorCode ierr; 285 286 PetscFunctionBegin; 287 ierr = PetscVSNPrintf(str,sizeof(str),format,NULL,Argp);CHKERRQ(ierr); 288 fprintf(fd,"%s",str);CHKERRQ(ierr); 289 fflush(fd); 290 PetscFunctionReturn(0); 291 } 292 293 /*@C 294 PetscSNPrintf - Prints to a string of given length 295 296 Not Collective 297 298 Input Parameters: 299 + str - the string to print to 300 . len - the length of str 301 . format - the usual printf() format string 302 - any arguments 303 304 Level: intermediate 305 306 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 307 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscVFPrintf() 308 @*/ 309 PetscErrorCode PetscSNPrintf(char *str,size_t len,const char format[],...) 310 { 311 PetscErrorCode ierr; 312 size_t fullLength; 313 va_list Argp; 314 315 PetscFunctionBegin; 316 va_start(Argp,format); 317 ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr); 318 PetscFunctionReturn(0); 319 } 320 321 /*@C 322 PetscSNPrintfCount - Prints to a string of given length, returns count 323 324 Not Collective 325 326 Input Parameters: 327 + str - the string to print to 328 . len - the length of str 329 . format - the usual printf() format string 330 . countused - number of characters used 331 - any arguments 332 333 Level: intermediate 334 335 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 336 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf(), PetscVFPrintf() 337 @*/ 338 PetscErrorCode PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...) 339 { 340 PetscErrorCode ierr; 341 va_list Argp; 342 343 PetscFunctionBegin; 344 va_start(Argp,countused); 345 ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr); 346 PetscFunctionReturn(0); 347 } 348 349 /* ----------------------------------------------------------------------- */ 350 351 PrintfQueue petsc_printfqueue = 0,petsc_printfqueuebase = 0; 352 int petsc_printfqueuelength = 0; 353 354 /*@C 355 PetscSynchronizedPrintf - Prints synchronized output from several processors. 356 Output of the first processor is followed by that of the second, etc. 357 358 Not Collective 359 360 Input Parameters: 361 + comm - the communicator 362 - format - the usual printf() format string 363 364 Level: intermediate 365 366 Notes: 367 REQUIRES a call to PetscSynchronizedFlush() by all the processes after the completion of the calls to PetscSynchronizedPrintf() for the information 368 from all the processors to be printed. 369 370 Fortran Note: 371 The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 372 That is, you can only pass a single character string from Fortran. 373 374 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 375 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 376 @*/ 377 PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 378 { 379 PetscErrorCode ierr; 380 PetscMPIInt rank; 381 382 PetscFunctionBegin; 383 if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 384 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 385 386 /* First processor prints immediately to stdout */ 387 if (!rank) { 388 va_list Argp; 389 va_start(Argp,format); 390 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 391 if (petsc_history) { 392 va_start(Argp,format); 393 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 394 } 395 va_end(Argp); 396 } else { /* other processors add to local queue */ 397 va_list Argp; 398 PrintfQueue next; 399 size_t fullLength = 8191; 400 401 ierr = PetscNew(&next);CHKERRQ(ierr); 402 if (petsc_printfqueue) { 403 petsc_printfqueue->next = next; 404 petsc_printfqueue = next; 405 petsc_printfqueue->next = 0; 406 } else petsc_printfqueuebase = petsc_printfqueue = next; 407 petsc_printfqueuelength++; 408 next->size = -1; 409 while ((PetscInt)fullLength >= next->size) { 410 next->size = fullLength+1; 411 412 ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr); 413 va_start(Argp,format); 414 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 415 ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr); 416 va_end(Argp); 417 } 418 } 419 PetscFunctionReturn(0); 420 } 421 422 /*@C 423 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 424 several processors. Output of the first processor is followed by that of the 425 second, etc. 426 427 Not Collective 428 429 Input Parameters: 430 + comm - the communicator 431 . fd - the file pointer 432 - format - the usual printf() format string 433 434 Level: intermediate 435 436 Notes: 437 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 438 from all the processors to be printed. 439 440 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 441 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 442 443 @*/ 444 PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm,FILE *fp,const char format[],...) 445 { 446 PetscErrorCode ierr; 447 PetscMPIInt rank; 448 449 PetscFunctionBegin; 450 if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 451 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 452 453 /* First processor prints immediately to fp */ 454 if (!rank) { 455 va_list Argp; 456 va_start(Argp,format); 457 ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr); 458 if (petsc_history && (fp !=petsc_history)) { 459 va_start(Argp,format); 460 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 461 } 462 va_end(Argp); 463 } else { /* other processors add to local queue */ 464 va_list Argp; 465 PrintfQueue next; 466 size_t fullLength = 8191; 467 ierr = PetscNew(&next);CHKERRQ(ierr); 468 if (petsc_printfqueue) { 469 petsc_printfqueue->next = next; 470 petsc_printfqueue = next; 471 petsc_printfqueue->next = 0; 472 } else petsc_printfqueuebase = petsc_printfqueue = next; 473 petsc_printfqueuelength++; 474 next->size = -1; 475 while ((PetscInt)fullLength >= next->size) { 476 next->size = fullLength+1; 477 ierr = PetscMalloc1(next->size, &next->string);CHKERRQ(ierr); 478 va_start(Argp,format); 479 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 480 ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr); 481 va_end(Argp); 482 } 483 } 484 PetscFunctionReturn(0); 485 } 486 487 /*@C 488 PetscSynchronizedFlush - Flushes to the screen output from all processors 489 involved in previous PetscSynchronizedPrintf()/PetscSynchronizedFPrintf() calls. 490 491 Collective on MPI_Comm 492 493 Input Parameters: 494 + comm - the communicator 495 - fd - the file pointer (valid on process 0 of the communicator) 496 497 Level: intermediate 498 499 Notes: 500 If PetscSynchronizedPrintf() and/or PetscSynchronizedFPrintf() are called with 501 different MPI communicators there must be an intervening call to PetscSynchronizedFlush() between the calls with different MPI communicators. 502 503 From Fortran pass PETSC_STDOUT if the flush is for standard out; otherwise pass a value obtained from PetscFOpen() 504 505 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 506 PetscViewerASCIISynchronizedPrintf() 507 @*/ 508 PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm,FILE *fd) 509 { 510 PetscErrorCode ierr; 511 PetscMPIInt rank,size,tag,i,j,n = 0,dummy = 0; 512 char *message; 513 MPI_Status status; 514 515 PetscFunctionBegin; 516 ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); 517 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 518 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 519 520 /* First processor waits for messages from all other processors */ 521 if (!rank) { 522 if (!fd) fd = PETSC_STDOUT; 523 for (i=1; i<size; i++) { 524 /* to prevent a flood of messages to process zero, request each message separately */ 525 ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr); 526 ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 527 for (j=0; j<n; j++) { 528 PetscMPIInt size = 0; 529 530 ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 531 ierr = PetscMalloc1(size, &message);CHKERRQ(ierr); 532 ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr); 533 ierr = PetscFPrintf(comm,fd,"%s",message);CHKERRQ(ierr); 534 ierr = PetscFree(message);CHKERRQ(ierr); 535 } 536 } 537 } else { /* other processors send queue to processor 0 */ 538 PrintfQueue next = petsc_printfqueuebase,previous; 539 540 ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr); 541 ierr = MPI_Send(&petsc_printfqueuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 542 for (i=0; i<petsc_printfqueuelength; i++) { 543 ierr = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 544 ierr = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); 545 previous = next; 546 next = next->next; 547 ierr = PetscFree(previous->string);CHKERRQ(ierr); 548 ierr = PetscFree(previous);CHKERRQ(ierr); 549 } 550 petsc_printfqueue = 0; 551 petsc_printfqueuelength = 0; 552 } 553 ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 554 PetscFunctionReturn(0); 555 } 556 557 /* ---------------------------------------------------------------------------------------*/ 558 559 /*@C 560 PetscFPrintf - Prints to a file, only from the first 561 processor in the communicator. 562 563 Not Collective 564 565 Input Parameters: 566 + comm - the communicator 567 . fd - the file pointer 568 - format - the usual printf() format string 569 570 Level: intermediate 571 572 Fortran Note: 573 This routine is not supported in Fortran. 574 575 Concepts: printing^in parallel 576 Concepts: printf^in parallel 577 578 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 579 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 580 @*/ 581 PetscErrorCode PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 582 { 583 PetscErrorCode ierr; 584 PetscMPIInt rank; 585 586 PetscFunctionBegin; 587 if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 588 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 589 if (!rank) { 590 va_list Argp; 591 va_start(Argp,format); 592 ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr); 593 if (petsc_history && (fd !=petsc_history)) { 594 va_start(Argp,format); 595 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 596 } 597 va_end(Argp); 598 } 599 PetscFunctionReturn(0); 600 } 601 602 /*@C 603 PetscPrintf - Prints to standard out, only from the first 604 processor in the communicator. Calls from other processes are ignored. 605 606 Not Collective 607 608 Input Parameters: 609 + comm - the communicator 610 - format - the usual printf() format string 611 612 Level: intermediate 613 614 Fortran Note: 615 The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 616 That is, you can only pass a single character string from Fortran. 617 618 Concepts: printing^in parallel 619 Concepts: printf^in parallel 620 621 .seealso: PetscFPrintf(), PetscSynchronizedPrintf() 622 @*/ 623 PetscErrorCode PetscPrintf(MPI_Comm comm,const char format[],...) 624 { 625 PetscErrorCode ierr; 626 PetscMPIInt rank; 627 628 PetscFunctionBegin; 629 if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 630 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 631 if (!rank) { 632 va_list Argp; 633 va_start(Argp,format); 634 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 635 if (petsc_history) { 636 va_start(Argp,format); 637 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 638 } 639 va_end(Argp); 640 } 641 PetscFunctionReturn(0); 642 } 643 644 /* ---------------------------------------------------------------------------------------*/ 645 /*@C 646 PetscHelpPrintf - All PETSc help messages are passing through this function. You can change how help messages are printed by 647 replacinng it with something that does not simply write to a stdout. 648 649 To use, write your own function for example, 650 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....) 651 ${ 652 $ PetscFunctionReturn(0); 653 $} 654 then before the call to PetscInitialize() do the assignment 655 $ PetscHelpPrintf = mypetschelpprintf; 656 657 Note: the default routine used is called PetscHelpPrintfDefault(). 658 659 Level: developer 660 661 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf() 662 @*/ 663 PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 664 { 665 PetscErrorCode ierr; 666 PetscMPIInt rank; 667 668 PetscFunctionBegin; 669 if (comm == MPI_COMM_NULL) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_PLIB,"Called with MPI_COMM_NULL, likely PetscObjectComm() failed"); 670 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 671 if (!rank) { 672 va_list Argp; 673 va_start(Argp,format); 674 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 675 if (petsc_history) { 676 va_start(Argp,format); 677 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 678 } 679 va_end(Argp); 680 } 681 PetscFunctionReturn(0); 682 } 683 684 /* ---------------------------------------------------------------------------------------*/ 685 686 687 /*@C 688 PetscSynchronizedFGets - Several processors all get the same line from a file. 689 690 Collective on MPI_Comm 691 692 Input Parameters: 693 + comm - the communicator 694 . fd - the file pointer 695 - len - the length of the output buffer 696 697 Output Parameter: 698 . string - the line read from the file, at end of file string[0] == 0 699 700 Level: intermediate 701 702 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 703 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 704 705 @*/ 706 PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm,FILE *fp,size_t len,char string[]) 707 { 708 PetscErrorCode ierr; 709 PetscMPIInt rank; 710 711 PetscFunctionBegin; 712 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 713 714 if (!rank) { 715 char *ptr = fgets(string, len, fp); 716 717 if (!ptr) { 718 string[0] = 0; 719 if (!feof(fp)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno); 720 } 721 } 722 ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); 723 PetscFunctionReturn(0); 724 } 725 726 #if defined(PETSC_HAVE_CLOSURES) 727 int (^SwiftClosure)(const char*) = 0; 728 729 PetscErrorCode PetscVFPrintfToString(FILE *fd,const char format[],va_list Argp) 730 { 731 PetscErrorCode ierr; 732 733 PetscFunctionBegin; 734 if (fd != stdout && fd != stderr) { /* handle regular files */ 735 ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr); 736 } else { 737 size_t len=8*1024,length; 738 char buf[len]; 739 740 ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr); 741 ierr = SwiftClosure(buf);CHKERRQ(ierr); 742 } 743 PetscFunctionReturn(0); 744 } 745 746 /* 747 Provide a Swift function that processes all the PETSc calls to PetscVFPrintf() 748 */ 749 PetscErrorCode PetscVFPrintfSetClosure(int (^closure)(const char*)) 750 { 751 PetscVFPrintf = PetscVFPrintfToString; 752 SwiftClosure = closure; 753 return 0; 754 } 755 #endif 756 757 #if defined(PETSC_HAVE_MATLAB_ENGINE) 758 #include <mex.h> 759 PetscErrorCode PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp) 760 { 761 PetscErrorCode ierr; 762 763 PetscFunctionBegin; 764 if (fd != stdout && fd != stderr) { /* handle regular files */ 765 ierr = PetscVFPrintfDefault(fd,format,Argp);CHKERRQ(ierr); 766 } else { 767 size_t len=8*1024,length; 768 char buf[len]; 769 770 ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr); 771 mexPrintf("%s",buf); 772 } 773 PetscFunctionReturn(0); 774 } 775 #endif 776 777 /*@C 778 PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations 779 780 Input Parameters: 781 . format - the PETSc format string 782 783 Level: developer 784 785 @*/ 786 PetscErrorCode PetscFormatStrip(char *format) 787 { 788 size_t loc1 = 0, loc2 = 0; 789 790 PetscFunctionBegin; 791 while (format[loc2]) { 792 if (format[loc2] == '%') { 793 format[loc1++] = format[loc2++]; 794 while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++; 795 } 796 format[loc1++] = format[loc2++]; 797 } 798 PetscFunctionReturn(0); 799 } 800 801