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