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