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