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