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 Used to output to Zope 25 */ 26 FILE *PETSC_ZOPEFD = 0; 27 28 /* 29 Return the maximum expected new size of the format 30 */ 31 #define PETSC_MAX_LENGTH_FORMAT(l) (l+l/8) 32 33 #undef __FUNCT__ 34 #define __FUNCT__ "PetscFormatConvert" 35 /*@C 36 PetscFormatConvert - Takes a PETSc format string and converts it to a reqular C format string 37 38 Input Parameters: 39 + format - the PETSc format string 40 . newformat - the location to put the standard C format string values 41 - size - the length of newformat 42 43 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 44 45 Level: developer 46 47 @*/ 48 PetscErrorCode PetscFormatConvert(const char *format,char *newformat,size_t size) 49 { 50 PetscInt i = 0,j = 0; 51 52 PetscFunctionBegin; 53 while (format[i] && j < (PetscInt)size-1) { 54 if (format[i] == '%' && format[i+1] != '%') { 55 /* Find the letter */ 56 for ( ; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i]; 57 switch (format[i]) { 58 case 'D': 59 #if !defined(PETSC_USE_64BIT_INDICES) 60 newformat[j++] = 'd'; 61 #else 62 newformat[j++] = 'l'; 63 newformat[j++] = 'l'; 64 newformat[j++] = 'd'; 65 #endif 66 break; 67 case 'G': 68 #if defined(PETSC_USE_REAL_DOUBLE) || defined(PETSC_USE_REAL_SINGLE) 69 newformat[j++] = 'g'; 70 #elif defined(PETSC_USE_REAL___FLOAT128) 71 newformat[j++] = 'Q'; 72 newformat[j++] = 'g'; 73 #endif 74 break; 75 case 'F': 76 #if defined(PETSC_USE_REAL_DOUBLE) || defined(PETSC_USE_REAL_SINGLE) 77 newformat[j++] = 'f'; 78 #elif defined(PETSC_USE_REAL_LONG_DOUBLE) 79 newformat[j++] = 'L'; 80 newformat[j++] = 'f'; 81 #elif defined(PETSC_USE_REAL___FLOAT128) 82 newformat[j++] = 'Q'; 83 newformat[j++] = 'f'; 84 #endif 85 break; 86 default: 87 newformat[j++] = format[i]; 88 break; 89 } 90 i++; 91 } else { 92 newformat[j++] = format[i++]; 93 } 94 } 95 newformat[j] = 0; 96 PetscFunctionReturn(0); 97 } 98 99 #undef __FUNCT__ 100 #define __FUNCT__ "PetscVSNPrintf" 101 /*@C 102 PetscVSNPrintf - The PETSc version of vsnprintf(). Converts a PETSc format string into a standard C format string and then puts all the 103 function arguments into a string using the format statement. 104 105 Input Parameters: 106 + str - location to put result 107 . len - the amount of space in str 108 + format - the PETSc format string 109 - fullLength - the amount of space in str actually used. 110 111 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 112 a recursion will occur and possible crash. 113 114 Level: developer 115 116 @*/ 117 PetscErrorCode PetscVSNPrintf(char *str,size_t len,const char *format,size_t *fullLength,va_list Argp) 118 { 119 char *newformat; 120 char formatbuf[8*1024]; 121 size_t oldLength,length; 122 int fullLengthInt; 123 PetscErrorCode ierr; 124 125 PetscFunctionBegin; 126 ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr); 127 if (oldLength < 8*1024) { 128 newformat = formatbuf; 129 oldLength = 8*1024-1; 130 } else { 131 oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength); 132 ierr = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr); 133 } 134 PetscFormatConvert(format,newformat,oldLength); 135 ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr); 136 #if 0 137 if (length > len) { 138 newformat[len] = '\0'; 139 } 140 #endif 141 #if defined(PETSC_HAVE_VSNPRINTF_CHAR) 142 fullLengthInt = vsnprintf(str,len,newformat,(char *)Argp); 143 #elif defined(PETSC_HAVE_VSNPRINTF) 144 fullLengthInt = vsnprintf(str,len,newformat,Argp); 145 #elif defined(PETSC_HAVE__VSNPRINTF) 146 fullLengthInt = _vsnprintf(str,len,newformat,Argp); 147 #else 148 #error "vsnprintf not found" 149 #endif 150 if (fullLengthInt < 0) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"vsnprintf() failed"); 151 if (fullLength) *fullLength = (size_t)fullLengthInt; 152 if (oldLength >= 8*1024) { 153 ierr = PetscFree(newformat);CHKERRQ(ierr); 154 } 155 PetscFunctionReturn(0); 156 } 157 158 #undef __FUNCT__ 159 #define __FUNCT__ "PetscZopeLog" 160 PetscErrorCode PetscZopeLog(const char *format,va_list Argp) 161 { 162 /* no malloc since may be called by error handler */ 163 char newformat[8*1024]; 164 char log[8*1024]; 165 char logstart[] = " <<<log>>>"; 166 size_t len,formatlen; 167 168 PetscFormatConvert(format,newformat,8*1024); 169 PetscStrlen(logstart, &len); 170 PetscMemcpy(log, logstart, len); 171 PetscStrlen(newformat, &formatlen); 172 PetscMemcpy(&(log[len]), newformat, formatlen); 173 if (PETSC_ZOPEFD){ 174 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 175 vfprintf(PETSC_ZOPEFD,log,(char *)Argp); 176 #else 177 vfprintf(PETSC_ZOPEFD,log,Argp); 178 #endif 179 fflush(PETSC_ZOPEFD); 180 } 181 return 0; 182 } 183 184 #undef __FUNCT__ 185 #define __FUNCT__ "PetscVFPrintfDefault" 186 /*@C 187 PetscVFPrintf - All PETSc standard out and error messages are sent through this function; so, in theory, this can 188 can be replaced with something that does not simply write to a file. 189 190 To use, write your own function for example, 191 $PetscErrorCode mypetscvfprintf(FILE *fd,const char format[],va_list Argp) 192 ${ 193 $ PetscErrorCode ierr; 194 $ 195 $ PetscFunctionBegin; 196 $ if (fd != stdout && fd != stderr) { handle regular files 197 $ ierr = PetscVFPrintfDefault(fd,format,Argp); CHKERR(ierr); 198 $ } else { 199 $ char buff[BIG]; 200 $ size_t length; 201 $ ierr = PetscVSNPrintf(buff,BIG,format,&length,Argp);CHKERRQ(ierr); 202 $ now send buff to whatever stream or whatever you want 203 $ } 204 $ PetscFunctionReturn(0); 205 $} 206 then before the call to PetscInitialize() do the assignment 207 $ PetscVFPrintf = mypetscvfprintf; 208 209 Notes: For error messages this may be called by any process, for regular standard out it is 210 called only by process 0 of a given communicator 211 212 Developer Notes: this could be called by an error handler, if that happens then a recursion of the error handler may occur 213 and a crash 214 215 Level: developer 216 217 .seealso: PetscVSNPrintf(), PetscErrorPrintf() 218 219 @*/ 220 PetscErrorCode PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 221 { 222 char *newformat; 223 char formatbuf[8*1024]; 224 size_t oldLength; 225 PetscErrorCode ierr; 226 227 PetscFunctionBegin; 228 ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr); 229 if (oldLength < 8*1024) { 230 newformat = formatbuf; 231 oldLength = 8*1024-1; 232 } else { 233 oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength); 234 ierr = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr); 235 } 236 ierr = PetscFormatConvert(format,newformat,oldLength);CHKERRQ(ierr); 237 238 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 239 vfprintf(fd,newformat,(char *)Argp); 240 #else 241 vfprintf(fd,newformat,Argp); 242 #endif 243 fflush(fd); 244 if (oldLength >= 8*1024) { 245 ierr = PetscFree(newformat);CHKERRQ(ierr); 246 } 247 PetscFunctionReturn(0); 248 } 249 250 #undef __FUNCT__ 251 #define __FUNCT__ "PetscSNPrintf" 252 /*@C 253 PetscSNPrintf - Prints to a string of given length 254 255 Not Collective 256 257 Input Parameters: 258 + str - the string to print to 259 . len - the length of str 260 . format - the usual printf() format string 261 - any arguments 262 263 Level: intermediate 264 265 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 266 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 267 @*/ 268 PetscErrorCode PetscSNPrintf(char *str,size_t len,const char format[],...) 269 { 270 PetscErrorCode ierr; 271 size_t fullLength; 272 va_list Argp; 273 274 PetscFunctionBegin; 275 va_start(Argp,format); 276 ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr); 277 PetscFunctionReturn(0); 278 } 279 280 #undef __FUNCT__ 281 #define __FUNCT__ "PetscSNPrintfCount" 282 /*@C 283 PetscSNPrintfCount - Prints to a string of given length, returns count 284 285 Not Collective 286 287 Input Parameters: 288 + str - the string to print to 289 . len - the length of str 290 . format - the usual printf() format string 291 . countused - number of characters used 292 - any arguments 293 294 Level: intermediate 295 296 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 297 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf(), PetscSNPrintf() 298 @*/ 299 PetscErrorCode PetscSNPrintfCount(char *str,size_t len,const char format[],size_t *countused,...) 300 { 301 PetscErrorCode ierr; 302 va_list Argp; 303 304 PetscFunctionBegin; 305 va_start(Argp,countused); 306 ierr = PetscVSNPrintf(str,len,format,countused,Argp);CHKERRQ(ierr); 307 PetscFunctionReturn(0); 308 } 309 310 /* ----------------------------------------------------------------------- */ 311 312 PrintfQueue queue = 0,queuebase = 0; 313 int queuelength = 0; 314 FILE *queuefile = PETSC_NULL; 315 316 #undef __FUNCT__ 317 #define __FUNCT__ "PetscSynchronizedPrintf" 318 /*@C 319 PetscSynchronizedPrintf - Prints synchronized output from several processors. 320 Output of the first processor is followed by that of the second, etc. 321 322 Not Collective 323 324 Input Parameters: 325 + comm - the communicator 326 - format - the usual printf() format string 327 328 Level: intermediate 329 330 Notes: 331 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 332 from all the processors to be printed. 333 334 Fortran Note: 335 The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 336 That is, you can only pass a single character string from Fortran. 337 338 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 339 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 340 @*/ 341 PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 342 { 343 PetscErrorCode ierr; 344 PetscMPIInt rank; 345 346 PetscFunctionBegin; 347 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 348 349 /* First processor prints immediately to stdout */ 350 if (!rank) { 351 va_list Argp; 352 va_start(Argp,format); 353 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 354 if (petsc_history) { 355 va_start(Argp,format); 356 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 357 } 358 va_end(Argp); 359 } else { /* other processors add to local queue */ 360 va_list Argp; 361 PrintfQueue next; 362 size_t fullLength = 8191; 363 364 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 365 if (queue) {queue->next = next; queue = next; queue->next = 0;} 366 else {queuebase = queue = next;} 367 queuelength++; 368 next->size = -1; 369 while((PetscInt)fullLength >= next->size) { 370 next->size = fullLength+1; 371 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 372 va_start(Argp,format); 373 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 374 ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr); 375 va_end(Argp); 376 } 377 } 378 379 PetscFunctionReturn(0); 380 } 381 382 #undef __FUNCT__ 383 #define __FUNCT__ "PetscSynchronizedFPrintf" 384 /*@C 385 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 386 several processors. Output of the first processor is followed by that of the 387 second, etc. 388 389 Not Collective 390 391 Input Parameters: 392 + comm - the communicator 393 . fd - the file pointer 394 - format - the usual printf() format string 395 396 Level: intermediate 397 398 Notes: 399 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 400 from all the processors to be printed. 401 402 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 403 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 404 405 @*/ 406 PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...) 407 { 408 PetscErrorCode ierr; 409 PetscMPIInt rank; 410 411 PetscFunctionBegin; 412 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 413 414 /* First processor prints immediately to fp */ 415 if (!rank) { 416 va_list Argp; 417 va_start(Argp,format); 418 ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr); 419 queuefile = fp; 420 if (petsc_history && (fp !=petsc_history)) { 421 va_start(Argp,format); 422 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 423 } 424 va_end(Argp); 425 } else { /* other processors add to local queue */ 426 va_list Argp; 427 PrintfQueue next; 428 size_t fullLength = 8191; 429 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 430 if (queue) {queue->next = next; queue = next; queue->next = 0;} 431 else {queuebase = queue = next;} 432 queuelength++; 433 next->size = -1; 434 while((PetscInt)fullLength >= next->size) { 435 next->size = fullLength+1; 436 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 437 va_start(Argp,format); 438 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 439 ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr); 440 va_end(Argp); 441 } 442 } 443 PetscFunctionReturn(0); 444 } 445 446 #undef __FUNCT__ 447 #define __FUNCT__ "PetscSynchronizedFlush" 448 /*@ 449 PetscSynchronizedFlush - Flushes to the screen output from all processors 450 involved in previous PetscSynchronizedPrintf() calls. 451 452 Collective on MPI_Comm 453 454 Input Parameters: 455 . comm - the communicator 456 457 Level: intermediate 458 459 Notes: 460 Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with 461 different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush(). 462 463 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 464 PetscViewerASCIISynchronizedPrintf() 465 @*/ 466 PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm) 467 { 468 PetscErrorCode ierr; 469 PetscMPIInt rank,size,tag,i,j,n,dummy = 0; 470 char *message; 471 MPI_Status status; 472 FILE *fd; 473 474 PetscFunctionBegin; 475 ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); 476 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 477 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 478 479 /* First processor waits for messages from all other processors */ 480 if (!rank) { 481 if (queuefile) { 482 fd = queuefile; 483 } else { 484 fd = PETSC_STDOUT; 485 } 486 for (i=1; i<size; i++) { 487 /* to prevent a flood of messages to process zero, request each message separately */ 488 ierr = MPI_Send(&dummy,1,MPI_INT,i,tag,comm);CHKERRQ(ierr); 489 ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 490 for (j=0; j<n; j++) { 491 PetscMPIInt size; 492 493 ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 494 ierr = PetscMalloc(size * sizeof(char), &message);CHKERRQ(ierr); 495 ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr); 496 ierr = PetscFPrintf(comm,fd,"%s",message); 497 ierr = PetscFree(message);CHKERRQ(ierr); 498 } 499 } 500 queuefile = PETSC_NULL; 501 } else { /* other processors send queue to processor 0 */ 502 PrintfQueue next = queuebase,previous; 503 504 ierr = MPI_Recv(&dummy,1,MPI_INT,0,tag,comm,&status);CHKERRQ(ierr); 505 ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 506 for (i=0; i<queuelength; i++) { 507 ierr = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 508 ierr = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); 509 previous = next; 510 next = next->next; 511 ierr = PetscFree(previous->string);CHKERRQ(ierr); 512 ierr = PetscFree(previous);CHKERRQ(ierr); 513 } 514 queue = 0; 515 queuelength = 0; 516 } 517 ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 518 PetscFunctionReturn(0); 519 } 520 521 /* ---------------------------------------------------------------------------------------*/ 522 523 #undef __FUNCT__ 524 #define __FUNCT__ "PetscFPrintf" 525 /*@C 526 PetscFPrintf - Prints to a file, only from the first 527 processor in the communicator. 528 529 Not Collective 530 531 Input Parameters: 532 + comm - the communicator 533 . fd - the file pointer 534 - format - the usual printf() format string 535 536 Level: intermediate 537 538 Fortran Note: 539 This routine is not supported in Fortran. 540 541 Concepts: printing^in parallel 542 Concepts: printf^in parallel 543 544 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 545 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 546 @*/ 547 PetscErrorCode PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 548 { 549 PetscErrorCode ierr; 550 PetscMPIInt rank; 551 552 PetscFunctionBegin; 553 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 554 if (!rank) { 555 va_list Argp; 556 va_start(Argp,format); 557 ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr); 558 if (petsc_history && (fd !=petsc_history)) { 559 va_start(Argp,format); 560 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 561 } 562 va_end(Argp); 563 } 564 PetscFunctionReturn(0); 565 } 566 567 #undef __FUNCT__ 568 #define __FUNCT__ "PetscPrintf" 569 /*@C 570 PetscPrintf - Prints to standard out, only from the first 571 processor in the communicator. Calls from other processes are ignored. 572 573 Not Collective 574 575 Input Parameters: 576 + comm - the communicator 577 - format - the usual printf() format string 578 579 Level: intermediate 580 581 Fortran Note: 582 The call sequence is PetscPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 583 That is, you can only pass a single character string from Fortran. 584 585 Concepts: printing^in parallel 586 Concepts: printf^in parallel 587 588 .seealso: PetscFPrintf(), PetscSynchronizedPrintf() 589 @*/ 590 PetscErrorCode PetscPrintf(MPI_Comm comm,const char format[],...) 591 { 592 PetscErrorCode ierr; 593 PetscMPIInt rank; 594 595 PetscFunctionBegin; 596 if (!comm) comm = PETSC_COMM_WORLD; 597 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 598 if (!rank) { 599 va_list Argp; 600 va_start(Argp,format); 601 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 602 if (petsc_history) { 603 va_start(Argp,format); 604 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 605 } 606 va_end(Argp); 607 } 608 PetscFunctionReturn(0); 609 } 610 611 /* ---------------------------------------------------------------------------------------*/ 612 #undef __FUNCT__ 613 #define __FUNCT__ "PetscHelpPrintfDefault" 614 /*@C 615 PetscHelpPrintf - All PETSc help messages are passing through this function. You can change how help messages are printed by 616 replacinng it with something that does not simply write to a stdout. 617 618 To use, write your own function for example, 619 $PetscErrorCode mypetschelpprintf(MPI_Comm comm,const char format[],....) 620 ${ 621 $ PetscFunctionReturn(0); 622 $} 623 then before the call to PetscInitialize() do the assignment 624 $ PetscHelpPrintf = mypetschelpprintf; 625 626 Note: the default routine used is called PetscHelpPrintfDefault(). 627 628 Level: developer 629 630 .seealso: PetscVSNPrintf(), PetscVFPrintf(), PetscErrorPrintf() 631 @*/ 632 PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 633 { 634 PetscErrorCode ierr; 635 PetscMPIInt rank; 636 637 PetscFunctionBegin; 638 if (!comm) comm = PETSC_COMM_WORLD; 639 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 640 if (!rank) { 641 va_list Argp; 642 va_start(Argp,format); 643 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 644 if (petsc_history) { 645 va_start(Argp,format); 646 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 647 } 648 va_end(Argp); 649 } 650 PetscFunctionReturn(0); 651 } 652 653 /* ---------------------------------------------------------------------------------------*/ 654 655 656 #undef __FUNCT__ 657 #define __FUNCT__ "PetscSynchronizedFGets" 658 /*@C 659 PetscSynchronizedFGets - Several processors all get the same line from a file. 660 661 Collective on MPI_Comm 662 663 Input Parameters: 664 + comm - the communicator 665 . fd - the file pointer 666 - len - the length of the output buffer 667 668 Output Parameter: 669 . string - the line read from the file 670 671 Level: intermediate 672 673 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 674 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 675 676 @*/ 677 PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[]) 678 { 679 PetscErrorCode ierr; 680 PetscMPIInt rank; 681 682 PetscFunctionBegin; 683 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 684 685 if (!rank) { 686 char *ptr = fgets(string, len, fp); 687 688 if (!ptr) { 689 if (feof(fp)) { 690 len = 0; 691 } else SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno); 692 } 693 } 694 ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); 695 PetscFunctionReturn(0); 696 } 697 698 #if defined(PETSC_HAVE_MATLAB_ENGINE) 699 #include <mex.h> 700 #undef __FUNCT__ 701 #define __FUNCT__ "PetscVFPrintf_Matlab" 702 PetscErrorCode PetscVFPrintf_Matlab(FILE *fd,const char format[],va_list Argp) 703 { 704 PetscErrorCode ierr; 705 706 PetscFunctionBegin; 707 if (fd != stdout && fd != stderr) { /* handle regular files */ 708 ierr = PetscVFPrintfDefault(fd,format,Argp); CHKERRQ(ierr); 709 } else { 710 size_t len=8*1024,length; 711 char buf[len]; 712 713 ierr = PetscVSNPrintf(buf,len,format,&length,Argp);CHKERRQ(ierr); 714 mexPrintf("%s",buf); 715 } 716 PetscFunctionReturn(0); 717 } 718 #endif 719 720 #undef __FUNCT__ 721 #define __FUNCT__ "PetscFormatStrip" 722 /*@C 723 PetscFormatStrip - Takes a PETSc format string and removes all numerical modifiers to % operations 724 725 Input Parameters: 726 . format - the PETSc format string 727 728 Level: developer 729 730 @*/ 731 PetscErrorCode PetscFormatStrip(char *format) 732 { 733 size_t loc1 = 0, loc2 = 0; 734 735 PetscFunctionBegin; 736 while (format[loc2]){ 737 if (format[loc2] == '%') { 738 format[loc1++] = format[loc2++]; 739 while (format[loc2] && ((format[loc2] >= '0' && format[loc2] <= '9') || format[loc2] == '.')) loc2++; 740 } 741 format[loc1++] = format[loc2++]; 742 } 743 PetscFunctionReturn(0); 744 } 745 746 static PetscToken OriginalRun = 0; 747 748 #undef __FUNCT__ 749 #define __FUNCT__ "PetscVFPrintfRegressDestroy" 750 static PetscErrorCode PetscVFPrintfRegressDestroy(void) 751 { 752 PetscErrorCode ierr; 753 754 PetscFunctionBegin; 755 ierr = PetscTokenDestroy(&OriginalRun);CHKERRQ(ierr); 756 PetscFunctionReturn(0); 757 } 758 759 #undef __FUNCT__ 760 #define __FUNCT__ "PetscVFPrintfRegressSetUp" 761 /*@C 762 PetscVFPrintfRegressSetUp - Reads in file of previous results of run to compare with current run using PetscVFPrintfRegress 763 764 Level: developer 765 766 .seealso: PetscVSNPrintf(), PetscErrorPrintf(), PetscVFPrintfRegress() 767 768 @*/ 769 PetscErrorCode PetscVFPrintfRegressSetUp(MPI_Comm comm,const char *filename) 770 { 771 PetscErrorCode ierr; 772 FILE *fp; 773 char buffer[1024],*big; 774 size_t cnt = 0,len; 775 char *ptr; 776 PetscMPIInt rank; 777 778 PetscFunctionBegin; 779 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 780 if (!rank) { 781 ierr = PetscFOpen(comm,filename,"r",&fp);CHKERRQ(ierr); 782 783 ptr = fgets(buffer, 1024, fp); 784 while (ptr) { 785 ierr = PetscStrlen(ptr,&len);CHKERRQ(ierr); 786 cnt += len; 787 ptr = fgets(buffer, 1024, fp); 788 } 789 if (!feof(fp)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno); 790 ierr = PetscFClose(comm,fp);CHKERRQ(ierr); 791 ierr = PetscMalloc(cnt*sizeof(char),&big);CHKERRQ(ierr); 792 big[0] = 0; 793 ierr = PetscFOpen(comm,filename,"r",&fp);CHKERRQ(ierr); 794 ptr = fgets(buffer, 1024, fp); 795 while (ptr) { 796 ierr = PetscStrcat(big,ptr);CHKERRQ(ierr); 797 ptr = fgets(buffer, 1024, fp); 798 } 799 if (!feof(fp)) SETERRQ1(PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file: %d", errno); 800 ierr = PetscFClose(comm,fp);CHKERRQ(ierr); 801 ierr = PetscTokenCreate(big,'\n',&OriginalRun);CHKERRQ(ierr); 802 ierr = PetscFree(big);CHKERRQ(ierr); 803 PetscVFPrintf = PetscVFPrintfRegress; 804 ierr = PetscRegisterFinalize(PetscVFPrintfRegressDestroy);CHKERRQ(ierr); 805 } 806 PetscFunctionReturn(0); 807 } 808 809 810 #undef __FUNCT__ 811 #define __FUNCT__ "PetscVFPrintfRegress" 812 /*@C 813 PetscVFPrintfRegress - Special version of PetscVFPrintf() to help make clean PETSc regression tests 814 815 Level: developer 816 817 Developer Notes: 818 Since this routine knows exactly the data-types and formats of each of the arguments it could in theory do an appropriate 819 diff for each argument, rather than using a string diff on the entire result. 820 821 So we should somehow loop over all the parts of the format string check that the string part matches and the arguments match 822 within a reasonable tolerance. 823 824 .seealso: PetscVSNPrintf(), PetscErrorPrintf() 825 826 @*/ 827 PetscErrorCode PetscVFPrintfRegress(FILE *fd,const char *format,va_list Argp) 828 { 829 char *newformat,*nformat,*oresult; 830 char formatbuf[8*1024],testbuf[8*1024]; 831 size_t oldLength; 832 PetscErrorCode ierr; 833 char *result; 834 PetscBool same; 835 size_t len; 836 int found; 837 va_list cArgp; 838 839 PetscFunctionBegin; 840 va_copy(cArgp,Argp); 841 ierr = PetscTokenFind(OriginalRun,&result);CHKERRQ(ierr); 842 if (!result) { 843 printf("Fewer lines in original, than in regression test\n"); 844 exit(0); 845 } 846 847 ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr); 848 if (oldLength < 8*1024) { 849 newformat = formatbuf; 850 oldLength = 8*1024-1; 851 } else { 852 oldLength = PETSC_MAX_LENGTH_FORMAT(oldLength); 853 ierr = PetscMalloc(oldLength * sizeof(char), &newformat);CHKERRQ(ierr); 854 } 855 ierr = PetscFormatConvert(format,newformat,oldLength);CHKERRQ(ierr); 856 ierr = PetscVSNPrintf(testbuf,8*1024,newformat,&len,Argp);CHKERRQ(ierr); 857 testbuf[len-1] = 0; /* remove \n at end of line */ 858 ierr = PetscStrcmp(result,testbuf,&same);CHKERRQ(ierr); 859 if (!same) { 860 char *sub; 861 same = PETSC_TRUE; 862 ierr = PetscFormatStrip(newformat);CHKERRQ(ierr); 863 nformat = newformat; 864 oresult = result; 865 866 ierr = PetscStrstr(nformat,"%",&sub);CHKERRQ(ierr); 867 while (sub) { 868 sub++; 869 if (*sub == 'g' || *sub == 'f') { 870 float val; 871 double nval; 872 char tsub = sub[1]; 873 sub++; *sub = 0; 874 found = sscanf(oresult,nformat,&val); 875 if (!found) { 876 printf("Old::%s\nNew::%s\n",result,testbuf); 877 printf("Different because not scan:%s: from :%s:\n",nformat,oresult); 878 same = PETSC_FALSE; 879 break; 880 } 881 nval = va_arg(cArgp,double); 882 if (PetscAbs((nval - val)/(nval + val)) > .1) { 883 printf("Old::%s\nNew::%s\n",result,testbuf); 884 printf("Different because float values %g to far from %g\n",val,nval); 885 same = PETSC_FALSE; 886 break; 887 } 888 *sub = tsub; 889 while (*nformat == *oresult) {nformat++; oresult++;} 890 while (*oresult == ' ') oresult++; 891 while ((*oresult >= '0' && *oresult <= '9') || *oresult == '.' || *oresult == '-' || *oresult == 'e') oresult++; 892 } else if (*sub == 'd') { 893 int val,nval; 894 char tsub = sub[1]; 895 sub++; *sub = 0; 896 found = sscanf(oresult,nformat,&val); 897 if (!found) { 898 printf("Old::%s\nNew::%s\n",result,testbuf); 899 printf("Different because not scan:%s: from :%s:\n",nformat,oresult); 900 same = PETSC_FALSE; 901 break; 902 } 903 nval = va_arg(cArgp,int); 904 if (val != nval) { 905 printf("Old::%s\nNew::%s\n",result,testbuf); 906 printf("Different because integer value %d != %d\n",val,nval); 907 same = PETSC_FALSE; 908 break; 909 } 910 *sub = tsub; 911 while (*nformat == *oresult) {nformat++; oresult++;} 912 while (*oresult == ' ') oresult++; 913 while ((*oresult >= '0' && *oresult <= '9') || *oresult == '-') oresult++; 914 } 915 nformat = sub; 916 ierr = PetscStrstr(nformat,"%",&sub);CHKERRQ(ierr); 917 } 918 } 919 920 if (oldLength >= 8*1024) { 921 ierr = PetscFree(newformat);CHKERRQ(ierr); 922 } 923 PetscFunctionReturn(0); 924 } 925