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