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