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_SCALAR_INT) 59 newformat[j++] = 'd'; 60 #elif !defined(PETSC_USE_SCALAR_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_VSNPRINTF_CHAR) 102 *fullLength = vsnprintf(str,len,newformat,(char *)Argp); 103 #elif defined(PETSC_HAVE_VSNPRINTF) 104 *fullLength = vsnprintf(str,len,newformat,Argp); 105 #elif defined(PETSC_HAVE__VSNPRINTF) 106 *fullLength = _vsnprintf(str,len,newformat,Argp); 107 #else 108 #error "vsnprintf not found" 109 #endif 110 if (oldLength >= 8*1024) { 111 ierr = PetscFree(newformat);CHKERRQ(ierr); 112 } 113 return 0; 114 } 115 116 #undef __FUNCT__ 117 #define __FUNCT__ "PetscZopeLog" 118 PetscErrorCode PETSC_DLLEXPORT PetscZopeLog(const char *format,va_list Argp) 119 { 120 /* no malloc since may be called by error handler */ 121 char newformat[8*1024]; 122 char log[8*1024]; 123 char logstart[] = " <<<log>>>"; 124 size_t len; 125 size_t formatlen; 126 127 PetscFormatConvert(format,newformat,8*1024); 128 PetscStrlen(logstart, &len); 129 PetscMemcpy(log, logstart, len); 130 PetscStrlen(newformat, &formatlen); 131 PetscMemcpy(&(log[len]), newformat, formatlen); 132 if (PETSC_ZOPEFD){ 133 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 134 vfprintf(PETSC_ZOPEFD,log,(char *)Argp); 135 #else 136 vfprintf(PETSC_ZOPEFD,log,Argp); 137 #endif 138 fflush(PETSC_ZOPEFD); 139 } 140 return 0; 141 } 142 143 #undef __FUNCT__ 144 #define __FUNCT__ "PetscVFPrintf" 145 /* 146 All PETSc standard out and error messages are sent through this function; so, in theory, this can 147 can be replaced with something that does not simply write to a file. 148 149 Note: For error messages this may be called by a process, for regular standard out it is 150 called only by process 0 of a given communicator 151 152 No error handling because may be called by error handler 153 */ 154 PetscErrorCode PETSC_DLLEXPORT PetscVFPrintfDefault(FILE *fd,const char *format,va_list Argp) 155 { 156 /* no malloc since may be called by error handler (assume no long messages in errors) */ 157 char *newformat; 158 char formatbuf[8*1024]; 159 size_t oldLength; 160 161 PetscStrlen(format, &oldLength); 162 if (oldLength < 8*1024) { 163 newformat = formatbuf; 164 } else { 165 (void)PetscMalloc((oldLength+1) * sizeof(char), &newformat); 166 } 167 PetscFormatConvert(format,newformat,oldLength+1); 168 if (PETSC_ZOPEFD && 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_COMM_SELF,PETSC_ERR_SUP_SYS,"Zope not supported due to missing va_copy()"); 176 #endif 177 178 #if defined(PETSC_HAVE_VA_COPY) || defined(PETSC_HAVE___VA_COPY) 179 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 180 vfprintf(PETSC_ZOPEFD,newformat,(char *)s); 181 #else 182 vfprintf(PETSC_ZOPEFD,newformat,s); 183 #endif 184 fflush(PETSC_ZOPEFD); 185 #endif 186 } 187 188 #if defined(PETSC_HAVE_VFPRINTF_CHAR) 189 vfprintf(fd,newformat,(char *)Argp); 190 #else 191 vfprintf(fd,newformat,Argp); 192 #endif 193 fflush(fd); 194 if (oldLength >= 8*1024) { 195 if (PetscFree(newformat)) {}; 196 } 197 return 0; 198 } 199 200 #undef __FUNCT__ 201 #define __FUNCT__ "PetscSNPrintf" 202 /*@C 203 PetscSNPrintf - Prints to a string of given length 204 205 Not Collective 206 207 Input Parameters: 208 + str - the string to print to 209 . len - the length of str 210 . format - the usual printf() format string 211 - any arguments 212 213 Level: intermediate 214 215 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), PetscVSNPrintf(), 216 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 217 @*/ 218 PetscErrorCode PETSC_DLLEXPORT PetscSNPrintf(char *str,size_t len,const char format[],...) 219 { 220 PetscErrorCode ierr; 221 int fullLength; 222 va_list Argp; 223 224 PetscFunctionBegin; 225 va_start(Argp,format); 226 ierr = PetscVSNPrintf(str,len,format,&fullLength,Argp);CHKERRQ(ierr); 227 PetscFunctionReturn(0); 228 } 229 230 /* ----------------------------------------------------------------------- */ 231 232 PrintfQueue queue = 0,queuebase = 0; 233 int queuelength = 0; 234 FILE *queuefile = PETSC_NULL; 235 236 #undef __FUNCT__ 237 #define __FUNCT__ "PetscSynchronizedPrintf" 238 /*@C 239 PetscSynchronizedPrintf - Prints synchronized output from several processors. 240 Output of the first processor is followed by that of the second, etc. 241 242 Not Collective 243 244 Input Parameters: 245 + comm - the communicator 246 - format - the usual printf() format string 247 248 Level: intermediate 249 250 Notes: 251 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 252 from all the processors to be printed. 253 254 Fortran Note: 255 The call sequence is PetscSynchronizedPrintf(MPI_Comm, character(*), PetscErrorCode ierr) from Fortran. 256 That is, you can only pass a single character string from Fortran. 257 258 .seealso: PetscSynchronizedFlush(), PetscSynchronizedFPrintf(), PetscFPrintf(), 259 PetscPrintf(), PetscViewerASCIIPrintf(), PetscViewerASCIISynchronizedPrintf() 260 @*/ 261 PetscErrorCode PETSC_DLLEXPORT PetscSynchronizedPrintf(MPI_Comm comm,const char format[],...) 262 { 263 PetscErrorCode ierr; 264 PetscMPIInt rank; 265 266 PetscFunctionBegin; 267 ierr = MPI_Comm_rank(comm,&rank);CHKERRQ(ierr); 268 269 /* First processor prints immediately to stdout */ 270 if (!rank) { 271 va_list Argp; 272 va_start(Argp,format); 273 ierr = (*PetscVFPrintf)(PETSC_STDOUT,format,Argp);CHKERRQ(ierr); 274 if (petsc_history) { 275 ierr = (*PetscVFPrintf)(petsc_history,format,Argp);CHKERRQ(ierr); 276 } 277 va_end(Argp); 278 } else { /* other processors add to local queue */ 279 va_list Argp; 280 PrintfQueue next; 281 int fullLength = 8191; 282 283 ierr = PetscNew(struct _PrintfQueue,&next);CHKERRQ(ierr); 284 if (queue) {queue->next = next; queue = next; queue->next = 0;} 285 else {queuebase = queue = next;} 286 queuelength++; 287 next->size = -1; 288 while(fullLength >= next->size) { 289 next->size = fullLength+1; 290 ierr = PetscMalloc(next->size * sizeof(char), &next->string);CHKERRQ(ierr); 291 va_start(Argp,format); 292 ierr = PetscMemzero(next->string,next->size);CHKERRQ(ierr); 293 ierr = PetscVSNPrintf(next->string,next->size,format, &fullLength,Argp);CHKERRQ(ierr); 294 va_end(Argp); 295 } 296 } 297 298 PetscFunctionReturn(0); 299 } 300 301 #undef __FUNCT__ 302 #define __FUNCT__ "PetscSynchronizedFPrintf" 303 /*@C 304 PetscSynchronizedFPrintf - Prints synchronized output to the specified file from 305 several processors. Output of the first processor is followed by that of the 306 second, etc. 307 308 Not Collective 309 310 Input Parameters: 311 + comm - the communicator 312 . fd - the file pointer 313 - format - the usual printf() format string 314 315 Level: intermediate 316 317 Notes: 318 REQUIRES a intervening call to PetscSynchronizedFlush() for the information 319 from all the processors to be printed. 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(MPI_Comm, 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_COMM_SELF,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