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