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