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