1 #define PETSC_DLL 2 /* 3 Utilites routines to add simple ASCII IO capability. 4 */ 5 #include "src/sys/fileio/mprint.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 #undef __FUNCT__ 29 #define __FUNCT__ "PetscFormatConvert" 30 PetscErrorCode PETSC_DLLEXPORT PetscFormatConvert(const char *format,char *newformat,PetscInt size) 31 { 32 PetscInt i = 0,j = 0; 33 34 while (format[i] && i < size-1) { 35 if (format[i] == '%' && format[i+1] == 'D') { 36 newformat[j++] = '%'; 37 #if !defined(PETSC_USE_64BIT_INDICES) 38 newformat[j++] = 'd'; 39 #else 40 newformat[j++] = 'l'; 41 newformat[j++] = 'l'; 42 newformat[j++] = 'd'; 43 #endif 44 i += 2; 45 } else if (format[i] == '%' && format[i+1] >= '1' && format[i+1] <= '9' && format[i+2] == 'D') { 46 newformat[j++] = '%'; 47 newformat[j++] = format[i+1]; 48 #if !defined(PETSC_USE_64BIT_INDICES) 49 newformat[j++] = 'd'; 50 #else 51 newformat[j++] = 'l'; 52 newformat[j++] = 'l'; 53 newformat[j++] = 'd'; 54 #endif 55 i += 3; 56 } else if (format[i] == '%' && format[i+1] == 'G') { 57 newformat[j++] = '%'; 58 #if defined(PETSC_USE_INT) 59 newformat[j++] = 'd'; 60 #elif !defined(PETSC_USE_LONG_DOUBLE) 61 newformat[j++] = 'g'; 62 #else 63 newformat[j++] = 'L'; 64 newformat[j++] = 'g'; 65 #endif 66 i += 2; 67 }else { 68 newformat[j++] = format[i++]; 69 } 70 } 71 newformat[j] = 0; 72 return 0; 73 } 74 75 #undef __FUNCT__ 76 #define __FUNCT__ "PetscVSNPrintf" 77 /* 78 No error handling because may be called by error handler 79 */ 80 PetscErrorCode PETSC_DLLEXPORT PetscVSNPrintf(char *str,size_t len,const char *format,int *fullLength,va_list Argp) 81 { 82 /* no malloc since may be called by error handler */ 83 char *newformat; 84 char formatbuf[8*1024]; 85 size_t oldLength,length; 86 PetscErrorCode ierr; 87 88 ierr = PetscStrlen(format, &oldLength);CHKERRQ(ierr); 89 if (oldLength < 8*1024) { 90 newformat = formatbuf; 91 } else { 92 ierr = PetscMalloc((oldLength+1) * sizeof(char), &newformat);CHKERRQ(ierr); 93 } 94 PetscFormatConvert(format,newformat,oldLength+1); 95 ierr = PetscStrlen(newformat, &length);CHKERRQ(ierr); 96 #if 0 97 if (length > len) { 98 newformat[len] = '\0'; 99 } 100 #endif 101 #if defined(PETSC_HAVE_VPRINTF_CHAR) 102 *fullLength = vsnprintf(str,len,newformat,(char *)Argp); 103 #elif defined(PETSC_HAVE__VSNPRINTF) 104 *fullLength = _vsnprintf(str,len,newformat,Argp); 105 #else 106 *fullLength = vsnprintf(str,len,newformat,Argp); 107 #endif 108 if (oldLength >= 8*1024) { 109 ierr = PetscFree(newformat);CHKERRQ(ierr); 110 } 111 return 0; 112 } 113 114 #undef __FUNCT__ 115 #define __FUNCT__ "PetscZopeLog" 116 117 PetscErrorCode PETSC_DLLEXPORT PetscZopeLog(const char *format,va_list Argp){ 118 /* no malloc since may be called by error handler */ 119 char newformat[8*1024]; 120 char log[8*1024]; 121 122 extern FILE * PETSC_ZOPEFD; 123 char logstart[] = " <<<log>>>"; 124 size_t len; 125 size_t formatlen; 126 PetscFormatConvert(format,newformat,8*1024); 127 PetscStrlen(logstart, &len); 128 PetscMemcpy(log, logstart, len); 129 PetscStrlen(newformat, &formatlen); 130 PetscMemcpy(&(log[len]), newformat, formatlen); 131 if(PETSC_ZOPEFD != NULL){ 132 #if defined(PETSC_HAVE_VPRINTF_CHAR) 133 vfprintf(PETSC_ZOPEFD,log,(char *)Argp); 134 #else 135 vfprintf(PETSC_ZOPEFD,log,Argp); 136 fflush(PETSC_ZOPEFD); 137 #endif 138 } 139 return 0; 140 } 141 142 #undef __FUNCT__ 143 #define __FUNCT__ "PetscVFPrintf" 144 /* 145 All PETSc standard out and error messages are sent through this function; so, in theory, this can 146 can be replaced with something that does not simply write to a file. 147 148 Note: For error messages this may be called by a process, for regular standard out it is 149 called only by process 0 of a given communicator 150 151 No error handling because may be called by error handler 152 */ 153 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 154 { 155 /* no malloc since may be called by error handler (assume no long messages in errors) */ 156 char *newformat; 157 char formatbuf[8*1024]; 158 size_t oldLength; 159 extern FILE *PETSC_ZOPEFD; 160 161 PetscStrlen(format, &oldLength); 162 if (oldLength < 8*1024) { 163 newformat = formatbuf; 164 } else { 165 PetscMalloc((oldLength+1) * sizeof(char), &newformat); 166 } 167 PetscFormatConvert(format,newformat,oldLength+1); 168 if(PETSC_ZOPEFD != NULL && PETSC_ZOPEFD != PETSC_STDOUT){ 169 va_list s; 170 #if defined(PETSC_HAVE_VA_COPY) 171 va_copy(s, Argp); 172 #elif defined(PETSC_HAVE___VA_COPY) 173 __va_copy(s, Argp); 174 #else 175 SETERRQ(PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()"); 176 #endif 177 178 #if defined(PETSC_HAVE_VPRINTF_CHAR) 179 vfprintf(PETSC_ZOPEFD,newformat,(char *)s); 180 #else 181 vfprintf(PETSC_ZOPEFD,newformat,s); 182 fflush(PETSC_ZOPEFD); 183 #endif 184 } 185 186 #if defined(PETSC_HAVE_VPRINTF_CHAR) 187 vfprintf(fd,newformat,(char *)Argp); 188 #else 189 vfprintf(fd,newformat,Argp); 190 fflush(fd); 191 #endif 192 if (oldLength >= 8*1024) { 193 if (PetscFree(newformat)) {}; 194 } 195 return 0; 196 } 197 198 #undef __FUNCT__ 199 #define __FUNCT__ "PetscSNPrintf" 200 /*@C 201 PetscSNPrintf - Prints to a string of given length 202 203 Not Collective 204 205 Input Parameters: 206 + str - the string to print to 207 . len - the length of str 208 . format - the usual printf() format string 209 - any arguments 210 211 Level: intermediate 212 213 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 214 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 215 @*/ 216 PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...) 217 { 218 PetscErrorCode ierr; 219 int fullLength; 220 va_list Argp; 221 222 PetscFunctionBegin; 223 va_start(Argp,format); 224 ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr); 225 PetscFunctionReturn(0); 226 } 227 228 /* ----------------------------------------------------------------------- */ 229 230 PrintfQueue queue = 0,queuebase = 0; 231 int queuelength = 0; 232 FILE *queuefile = PETSC_NULL; 233 234 #undef __FUNCT__ 235 #define __FUNCT__ "PetscSynchronizedPrintf" 236 /*@C 237 PetscSynchronizedPrintf - Prints synchronized output from several processors. 238 Output of the first processor is followed by that of the second, etc. 239 240 Not Collective 241 242 Input Parameters: 243 + comm - the communicator 244 - format - the usual printf() format string 245 246 Level: intermediate 247 248 Notes: 249 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 250 from all the processors to be printed. 251 252 Fortran Note: 253 The call sequence is PetscSynchronizedPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. 254 That is, you can only pass a single character string from Fortran. 255 256 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 257 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 258 @*/ 259 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 260 { 261 PetscErrorCode ierr; 262 PetscMPIInt rank; 263 264 PetscFunctionBegin; 265 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 266 267 /* First processor prints immediately to stdout */ 268 if (!rank) { 269 va_list Argp; 270 va_start(Argp,format); 271 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 272 if (petsc_history) { 273 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 274 } 275 va_end(Argp); 276 } else { /* other processors add to local queue */ 277 va_list Argp; 278 PrintfQueue next; 279 int fullLength = 8191; 280 281 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 282 if (queue) {queue->next = next; queue = next; queue->next = 0;} 283 else {queuebase = queue = next;} 284 queuelength++; 285 next->size = -1; 286 while(fullLength >= next->size) { 287 next->size = fullLength+1; 288 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 289 va_start(Argp,format); 290 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 291 ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr); 292 va_end(Argp); 293 } 294 } 295 296 PetscFunctionReturn(0); 297 } 298 299 #undef __FUNCT__ 300 #define __FUNCT__ "PetscSynchronizedFPrintf" 301 /*@C 302 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 303 several processors. Output of the first processor is followed by that of the 304 second, etc. 305 306 Not Collective 307 308 Input Parameters: 309 + comm - the communicator 310 . fd - the file pointer 311 - format - the usual printf() format string 312 313 Level: intermediate 314 315 Notes: 316 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 317 from all the processors to be printed. 318 319 Contributed by: Matthew Knepley 320 321 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), PetscFPrintf(), 322 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 323 324 @*/ 325 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFPrintf(MPI_Comm comm,FILE* fp,const char format[],...) 326 { 327 PetscErrorCode ierr; 328 PetscMPIInt rank; 329 330 PetscFunctionBegin; 331 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 332 333 /* First processor prints immediately to fp */ 334 if (!rank) { 335 va_list Argp; 336 va_start(Argp,format); 337 ierr = (*PetscVFPrintf)(fp,format,Argp);CHKERRQ(ierr); 338 queuefile = fp; 339 if (petsc_history) { 340 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 341 } 342 va_end(Argp); 343 } else { /* other processors add to local queue */ 344 va_list Argp; 345 PrintfQueue next; 346 int fullLength = 8191; 347 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 348 if (queue) {queue->next = next; queue = next; queue->next = 0;} 349 else {queuebase = queue = next;} 350 queuelength++; 351 next->size = -1; 352 while(fullLength >= next->size) { 353 next->size = fullLength+1; 354 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 355 va_start(Argp,format); 356 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 357 ierr = PetscVSNPrintf(next->string,next->size,format,&fullLength,Argp);CHKERRQ(ierr); 358 va_end(Argp); 359 } 360 } 361 PetscFunctionReturn(0); 362 } 363 364 #undef __FUNCT__ 365 #define __FUNCT__ "PetscSynchronizedFlush" 366 /*@ 367 PetscSynchronizedFlush - Flushes to the screen output from all processors 368 involved in previous PetscSynchronizedPrintf() calls. 369 370 Collective on MPI_Comm 371 372 Input Parameters: 373 . comm - the communicator 374 375 Level: intermediate 376 377 Notes: 378 Usage of PetscSynchronizedPrintf() and PetscSynchronizedFPrintf() with 379 different MPI communicators REQUIRES an intervening call to PetscSynchronizedFlush(). 380 381 .seealso: PetscSynchronizedPrintf(), PetscFPrintf(), PetscPrintf(), PetscViewerASCIIPrintf(), 382 PetscViewerASCIISynchronizedPrintf() 383 @*/ 384 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFlush(MPI_Comm comm) 385 { 386 PetscErrorCode ierr; 387 PetscMPIInt rank,size,tag,i,j,n; 388 char *message; 389 MPI_Status status; 390 FILE *fd; 391 392 PetscFunctionBegin; 393 ierr = PetscCommDuplicate(comm,&comm,&tag);CHKERRQ(ierr); 394 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 395 ierr = MPI_Comm_size(comm,&size);CHKERRQ(ierr); 396 397 /* First processor waits for messages from all other processors */ 398 if (!rank) { 399 if (queuefile) { 400 fd = queuefile; 401 } else { 402 fd = PETSC_STDOUT; 403 } 404 for (i=1; i<size; i++) { 405 ierr = MPI_Recv(&n,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 406 for (j=0; j<n; j++) { 407 int size; 408 409 ierr = MPI_Recv(&size,1,MPI_INT,i,tag,comm,&status);CHKERRQ(ierr); 410 ierr = PetscMalloc(size * sizeof(char), &message);CHKERRQ(ierr); 411 ierr = MPI_Recv(message,size,MPI_CHAR,i,tag,comm,&status);CHKERRQ(ierr); 412 ierr = PetscFPrintf(comm,fd,"%s",message); 413 ierr = PetscFree(message);CHKERRQ(ierr); 414 } 415 } 416 queuefile = PETSC_NULL; 417 } else { /* other processors send queue to processor 0 */ 418 PrintfQueue next = queuebase,previous; 419 420 ierr = MPI_Send(&queuelength,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 421 for (i=0; i<queuelength; i++) { 422 ierr = MPI_Send(&next->size,1,MPI_INT,0,tag,comm);CHKERRQ(ierr); 423 ierr = MPI_Send(next->string,next->size,MPI_CHAR,0,tag,comm);CHKERRQ(ierr); 424 previous = next; 425 next = next->next; 426 ierr = PetscFree(previous->string);CHKERRQ(ierr); 427 ierr = PetscFree(previous);CHKERRQ(ierr); 428 } 429 queue = 0; 430 queuelength = 0; 431 } 432 ierr = PetscCommDestroy(&comm);CHKERRQ(ierr); 433 PetscFunctionReturn(0); 434 } 435 436 /* ---------------------------------------------------------------------------------------*/ 437 438 #undef __FUNCT__ 439 #define __FUNCT__ "PetscFPrintf" 440 /*@C 441 PetscFPrintf - Prints to a file, only from the first 442 processor in the communicator. 443 444 Not Collective 445 446 Input Parameters: 447 + comm - the communicator 448 . fd - the file pointer 449 - format - the usual printf() format string 450 451 Level: intermediate 452 453 Fortran Note: 454 This routine is not supported in Fortran. 455 456 Concepts: printing^in parallel 457 Concepts: printf^in parallel 458 459 .seealso: PetscPrintf(), PetscSynchronizedPrintf(), PetscViewerASCIIPrintf(), 460 PetscViewerASCIISynchronizedPrintf(), PetscSynchronizedFlush() 461 @*/ 462 PetscErrorCode PETSC_DLLEXPORT PetscFPrintf(MPI_Comm comm,FILE* fd,const char format[],...) 463 { 464 PetscErrorCode ierr; 465 PetscMPIInt rank; 466 467 PetscFunctionBegin; 468 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 469 if (!rank) { 470 va_list Argp; 471 va_start(Argp,format); 472 ierr = (*PetscVFPrintf)(fd,format,Argp);CHKERRQ(ierr); 473 if (petsc_history) { 474 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 475 } 476 va_end(Argp); 477 } 478 PetscFunctionReturn(0); 479 } 480 481 #undef __FUNCT__ 482 #define __FUNCT__ "PetscPrintf" 483 /*@C 484 PetscPrintf - Prints to standard out, only from the first 485 processor in the communicator. 486 487 Not Collective 488 489 Input Parameters: 490 + comm - the communicator 491 - format - the usual printf() format string 492 493 Level: intermediate 494 495 Fortran Note: 496 The call sequence is PetscPrintf(PetscViewer, character(*), PetscErrorCode ierr) from Fortran. 497 That is, you can only pass a single character string from Fortran. 498 499 Notes: %A is replace with %g unless the value is < 1.e-12 when it is 500 replaced with < 1.e-12 501 502 Concepts: printing^in parallel 503 Concepts: printf^in parallel 504 505 .seealso: PetscFPrintf(), PetscSynchronizedPrintf() 506 @*/ 507 PetscErrorCode PETSC_DLLEXPORT PetscPrintf(MPI_Comm comm,const char format[],...) 508 { 509 PetscErrorCode ierr; 510 PetscMPIInt rank; 511 size_t len; 512 char *nformat,*sub1,*sub2; 513 PetscReal value; 514 515 PetscFunctionBegin; 516 if (!comm) comm = PETSC_COMM_WORLD; 517 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 518 if (!rank) { 519 va_list Argp; 520 va_start(Argp,format); 521 522 ierr = PetscStrstr(format,"%A",&sub1);CHKERRQ(ierr); 523 if (sub1) { 524 ierr = PetscStrstr(format,"%",&sub2);CHKERRQ(ierr); 525 if (sub1 != sub2) SETERRQ(PETSC_ERR_ARG_WRONG,"%%A format must be first in format string"); 526 ierr = PetscStrlen(format,&len);CHKERRQ(ierr); 527 ierr = PetscMalloc((len+16)*sizeof(char),&nformat);CHKERRQ(ierr); 528 ierr = PetscStrcpy(nformat,format);CHKERRQ(ierr); 529 ierr = PetscStrstr(nformat,"%",&sub2);CHKERRQ(ierr); 530 sub2[0] = 0; 531 value = (double)va_arg(Argp,double); 532 if (PetscAbsReal(value) < 1.e-12) { 533 ierr = PetscStrcat(nformat,"< 1.e-12");CHKERRQ(ierr); 534 } else { 535 ierr = PetscStrcat(nformat,"%g");CHKERRQ(ierr); 536 va_end(Argp); 537 va_start(Argp,format); 538 } 539 ierr = PetscStrcat(nformat,sub1+2);CHKERRQ(ierr); 540 } else { 541 nformat = (char*)format; 542 } 543 ierr = (*PetscVFPrintf)(PETSC_STDOUT,nformat,Argp);CHKERRQ(ierr); 544 if (petsc_history) { 545 ierr = (*PetscVFPrintf)(petsc_history,nformat,Argp);CHKERRQ(ierr); 546 } 547 va_end(Argp); 548 if (sub1) {ierr = PetscFree(nformat);CHKERRQ(ierr);} 549 } 550 PetscFunctionReturn(0); 551 } 552 553 /* ---------------------------------------------------------------------------------------*/ 554 #undef __FUNCT__ 555 #define __FUNCT__ "PetscHelpPrintfDefault" 556 PetscErrorCode PETSC_DLLEXPORT PetscHelpPrintfDefault(MPI_Comm comm,const char format[],...) 557 { 558 PetscErrorCode ierr; 559 PetscMPIInt rank; 560 561 PetscFunctionBegin; 562 if (!comm) comm = PETSC_COMM_WORLD; 563 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 564 if (!rank) { 565 va_list Argp; 566 va_start(Argp,format); 567 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 568 if (petsc_history) { 569 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 570 } 571 va_end(Argp); 572 } 573 PetscFunctionReturn(0); 574 } 575 576 /* ---------------------------------------------------------------------------------------*/ 577 578 579 #undef __FUNCT__ 580 #define __FUNCT__ "PetscSynchronizedFGets" 581 /*@C 582 PetscSynchronizedFGets - Several processors all get the same line from a file. 583 584 Collective on MPI_Comm 585 586 Input Parameters: 587 + comm - the communicator 588 . fd - the file pointer 589 - len - the length of the output buffer 590 591 Output Parameter: 592 . string - the line read from the file 593 594 Level: intermediate 595 596 .seealso: PetscSynchronizedPrintf(), PetscSynchronizedFlush(), 597 PetscFOpen(), PetscViewerASCIISynchronizedPrintf(), PetscViewerASCIIPrintf() 598 599 @*/ 600 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedFGets(MPI_Comm comm,FILE* fp,size_t len,char string[]) 601 { 602 PetscErrorCode ierr; 603 PetscMPIInt rank; 604 605 PetscFunctionBegin; 606 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 607 608 if (!rank) { 609 fgets(string,len,fp); 610 } 611 ierr = MPI_Bcast(string,len,MPI_BYTE,0,comm);CHKERRQ(ierr); 612 PetscFunctionReturn(0); 613 } 614