Actual source code: mprint.c
1: /*
2: Utilities routines to add simple ASCII IO capability.
3: */
4: #include <../src/sys/fileio/mprint.h>
5: #include <errno.h>
6: /*
7: If petsc_history is on, then all Petsc*Printf() results are saved
8: if the appropriate (usually .petschistory) file.
9: */
10: PETSC_INTERN 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 = NULL;
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 = NULL;
24: /*@C
25: PetscFormatConvertGetSize - Gets the length of a string needed to hold data converted with `PetscFormatConvert()` based on the format
27: No Fortran Support
29: Input Parameter:
30: . format - the PETSc format string
32: Output Parameter:
33: . size - the needed length of the new format
35: Level: developer
37: .seealso: `PetscFormatConvert()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
38: @*/
39: PetscErrorCode PetscFormatConvertGetSize(const char *format, size_t *size)
40: {
41: size_t sz = 0;
42: PetscInt i = 0;
44: PetscFunctionBegin;
45: PetscAssertPointer(format, 1);
46: PetscAssertPointer(size, 2);
47: while (format[i]) {
48: if (format[i] == '%') {
49: if (format[i + 1] == '%') {
50: i += 2;
51: sz += 2;
52: continue;
53: }
54: /* Find the letter */
55: while (format[i] && (format[i] <= '9')) {
56: ++i;
57: ++sz;
58: }
59: switch (format[i]) {
60: #if PetscDefined(USE_64BIT_INDICES)
61: case 'D':
62: sz += 2;
63: break;
64: #endif
65: case 'g':
66: sz += 4;
67: default:
68: break;
69: }
70: }
71: ++i;
72: ++sz;
73: }
74: *size = sz + 1; /* space for NULL character */
75: PetscFunctionReturn(PETSC_SUCCESS);
76: }
78: /*@C
79: PetscFormatConvert - converts %g to [|%g|] so that `PetscVSNPrintf()` can ensure all %g formatted numbers have a decimal point when printed.
81: No Fortran Support
83: Input Parameter:
84: . format - the PETSc format string
86: Output Parameter:
87: . newformat - the formatted string
89: Level: developer
91: Note:
92: The decimal point is then used by the `petscdiff` script so that differences in floating
93: point number output is ignored in the test harness.
95: Deprecated usage also converts the `%D` to `%d` for 32-bit PETSc indices and to `%lld` for
96: 64-bit PETSc indices. This feature is no longer used in PETSc code instead use %"
97: PetscInt_FMT " in the format string.
99: .seealso: `PetscFormatConvertGetSize()`, `PetscVSNPrintf()`, `PetscVFPrintf()`
100: @*/
101: PetscErrorCode PetscFormatConvert(const char *format, char *newformat)
102: {
103: PetscInt i = 0, j = 0;
105: PetscFunctionBegin;
106: while (format[i]) {
107: if (format[i] == '%' && format[i + 1] == '%') {
108: newformat[j++] = format[i++];
109: newformat[j++] = format[i++];
110: } else if (format[i] == '%') {
111: if (format[i + 1] == 'g') {
112: newformat[j++] = '[';
113: newformat[j++] = '|';
114: }
115: /* Find the letter */
116: for (; format[i] && format[i] <= '9'; i++) newformat[j++] = format[i];
117: switch (format[i]) {
118: case 'D':
119: #if !defined(PETSC_USE_64BIT_INDICES)
120: newformat[j++] = 'd';
121: #else
122: newformat[j++] = 'l';
123: newformat[j++] = 'l';
124: newformat[j++] = 'd';
125: #endif
126: break;
127: case 'g':
128: newformat[j++] = format[i];
129: if (format[i - 1] == '%') {
130: newformat[j++] = '|';
131: newformat[j++] = ']';
132: }
133: break;
134: case 'G':
135: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%G format is no longer supported, use %%g and cast the argument to double");
136: case 'F':
137: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP, "%%F format is no longer supported, use %%f and cast the argument to double");
138: default:
139: newformat[j++] = format[i];
140: break;
141: }
142: i++;
143: } else newformat[j++] = format[i++];
144: }
145: newformat[j] = 0;
146: PetscFunctionReturn(PETSC_SUCCESS);
147: }
149: #define PETSCDEFAULTBUFFERSIZE 8 * 1024
151: /*@C
152: PetscVSNPrintf - The PETSc version of `vsnprintf()`. Ensures that all `%g` formatted arguments' output contains the decimal point (which
153: is used by the test harness)
155: Input Parameters:
156: + str - location to put result
157: . len - the length of `str`
158: . format - the PETSc format string
159: - Argp - the variable argument list to format
161: Output Parameter:
162: . fullLength - the amount of space in `str` actually used.
164: Level: developer
166: Developer Notes:
167: This function may be called from an error handler, if an error occurs when it is called by the error handler than likely
168: a recursion will occur resulting in a crash of the program.
170: If the length of the format string `format` is on the order of `PETSCDEFAULTBUFFERSIZE` (8 * 1024 bytes) or larger, this function will call `PetscMalloc()`
172: .seealso: `PetscFormatConvert()`, `PetscFormatConvertGetSize()`, `PetscErrorPrintf()`, `PetscVPrintf()`
173: @*/
174: PetscErrorCode PetscVSNPrintf(char *str, size_t len, const char *format, size_t *fullLength, va_list Argp)
175: {
176: char *newformat = NULL;
177: char formatbuf[PETSCDEFAULTBUFFERSIZE];
178: size_t newLength;
179: int flen;
181: PetscFunctionBegin;
182: PetscCall(PetscFormatConvertGetSize(format, &newLength));
183: if (newLength < sizeof(formatbuf)) {
184: newformat = formatbuf;
185: newLength = sizeof(formatbuf) - 1;
186: } else {
187: PetscCall(PetscMalloc1(newLength, &newformat));
188: }
189: PetscCall(PetscFormatConvert(format, newformat));
190: #if defined(PETSC_HAVE_VSNPRINTF)
191: flen = vsnprintf(str, len, newformat, Argp);
192: #else
193: #error "vsnprintf not found"
194: #endif
195: if (newLength > sizeof(formatbuf) - 1) PetscCall(PetscFree(newformat));
196: {
197: PetscBool foundedot;
198: size_t cnt = 0, ncnt = 0, leng;
199: PetscCall(PetscStrlen(str, &leng));
200: if (leng > 4) {
201: for (cnt = 0; cnt < leng - 4; cnt++) {
202: if (str[cnt] == '[' && str[cnt + 1] == '|') {
203: flen -= 4;
204: cnt++;
205: cnt++;
206: foundedot = PETSC_FALSE;
207: for (; cnt < leng - 1; cnt++) {
208: if (str[cnt] == '|' && str[cnt + 1] == ']') {
209: cnt++;
210: if (!foundedot) str[ncnt++] = '.';
211: ncnt--;
212: break;
213: } else {
214: if (str[cnt] == 'e' || str[cnt] == '.') foundedot = PETSC_TRUE;
215: str[ncnt++] = str[cnt];
216: }
217: }
218: } else {
219: str[ncnt] = str[cnt];
220: }
221: ncnt++;
222: }
223: while (cnt < leng) {
224: str[ncnt] = str[cnt];
225: ncnt++;
226: cnt++;
227: }
228: str[ncnt] = 0;
229: }
230: }
231: #if defined(PETSC_HAVE_WINDOWS_H) && !defined(PETSC_HAVE__SET_OUTPUT_FORMAT)
232: /* older Windows OS always produces e-+0np for floating point output; remove the extra 0 */
233: {
234: size_t cnt = 0, ncnt = 0, leng;
235: PetscCall(PetscStrlen(str, &leng));
236: if (leng > 5) {
237: for (cnt = 0; cnt < leng - 4; cnt++) {
238: if (str[cnt] == 'e' && (str[cnt + 1] == '-' || str[cnt + 1] == '+') && str[cnt + 2] == '0' && str[cnt + 3] >= '0' && str[cnt + 3] <= '9' && str[cnt + 4] >= '0' && str[cnt + 4] <= '9') {
239: str[ncnt] = str[cnt];
240: ncnt++;
241: cnt++;
242: str[ncnt] = str[cnt];
243: ncnt++;
244: cnt++;
245: cnt++;
246: str[ncnt] = str[cnt];
247: } else {
248: str[ncnt] = str[cnt];
249: }
250: ncnt++;
251: }
252: while (cnt < leng) {
253: str[ncnt] = str[cnt];
254: ncnt++;
255: cnt++;
256: }
257: str[ncnt] = 0;
258: }
259: }
260: #endif
261: if (fullLength) *fullLength = 1 + (size_t)flen;
262: PetscFunctionReturn(PETSC_SUCCESS);
263: }
265: /*@C
266: PetscFFlush - Flush a file stream
268: Input Parameter:
269: . fd - The file stream handle
271: Level: intermediate
273: Notes:
274: For output streams (and for update streams on which the last operation was output), writes
275: any unwritten data from the stream's buffer to the associated output device.
277: For input streams (and for update streams on which the last operation was input), the
278: behavior is undefined.
280: If `fd` is `NULL`, all open output streams are flushed, including ones not directly
281: accessible to the program.
283: .seealso: `PetscPrintf()`, `PetscFPrintf()`, `PetscVFPrintf()`, `PetscVSNPrintf()`
284: @*/
285: PetscErrorCode PetscFFlush(FILE *fd)
286: {
287: PetscFunctionBegin;
288: if (fd) PetscAssertPointer(fd, 1);
289: // could also use PetscCallExternal() here, but since we can get additional error explanation
290: // from strerror() we opted for a manual check
291: PetscCheck(0 == fflush(fd), PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "Error in fflush() due to \"%s\"", strerror(errno));
292: PetscFunctionReturn(PETSC_SUCCESS);
293: }
295: /*@C
296: PetscVFPrintfDefault - All PETSc standard out and error messages are sent through this function; so, in theory, this can
297: can be replaced with something that does not simply write to a file.
299: Input Parameters:
300: + fd - the file descriptor to write to
301: . format - the format string to write with
302: - Argp - the variable argument list of items to format and write
304: Level: developer
306: Note:
307: For error messages this may be called by any MPI process, for regular standard out it is
308: called only by MPI rank 0 of a given communicator
310: Example Usage:
311: To use, write your own function for example,
312: .vb
313: PetscErrorCode mypetscvfprintf(FILE *fd, const char format[], va_list Argp)
314: {
315: PetscErrorCode ierr;
317: PetscFunctionBegin;
318: if (fd != stdout && fd != stderr) { handle regular files
319: CHKERR(PetscVFPrintfDefault(fd,format,Argp));
320: } else {
321: char buff[BIG];
322: size_t length;
323: PetscCall(PetscVSNPrintf(buff,BIG,format,&length,Argp));
324: now send buff to whatever stream or whatever you want
325: }
326: PetscFunctionReturn(PETSC_SUCCESS);
327: }
328: .ve
329: then before the call to `PetscInitialize()` do the assignment `PetscVFPrintf = mypetscvfprintf`;
331: Developer Notes:
332: This could be called by an error handler, if that happens then a recursion of the error handler may occur
333: and a resulting crash
335: .seealso: `PetscVSNPrintf()`, `PetscErrorPrintf()`, `PetscFFlush()`
336: @*/
337: PetscErrorCode PetscVFPrintfDefault(FILE *fd, const char *format, va_list Argp)
338: {
339: char str[PETSCDEFAULTBUFFERSIZE];
340: char *buff = str;
341: size_t fullLength;
342: #if defined(PETSC_HAVE_VA_COPY)
343: va_list Argpcopy;
344: #endif
346: PetscFunctionBegin;
347: #if defined(PETSC_HAVE_VA_COPY)
348: va_copy(Argpcopy, Argp);
349: #endif
350: PetscCall(PetscVSNPrintf(str, sizeof(str), format, &fullLength, Argp));
351: if (fullLength > sizeof(str)) {
352: PetscCall(PetscMalloc1(fullLength, &buff));
353: #if defined(PETSC_HAVE_VA_COPY)
354: PetscCall(PetscVSNPrintf(buff, fullLength, format, NULL, Argpcopy));
355: #else
356: SETERRQ(PETSC_COMM_SELF, PETSC_ERR_LIB, "C89 does not support va_copy() hence cannot print long strings with PETSc printing routines");
357: #endif
358: }
359: #if defined(PETSC_HAVE_VA_COPY)
360: va_end(Argpcopy);
361: #endif
362: {
363: const int err = fprintf(fd, "%s", buff);
364: // cannot use PetscCallExternal() for fprintf since the return value is "number of
365: // characters transmitted to the output stream" on success
366: PetscCheck(err >= 0, PETSC_COMM_SELF, PETSC_ERR_FILE_WRITE, "fprintf() returned error code %d", err);
367: }
368: PetscCall(PetscFFlush(fd));
369: if (buff != str) PetscCall(PetscFree(buff));
370: PetscFunctionReturn(PETSC_SUCCESS);
371: }
373: /*@C
374: PetscSNPrintf - Prints to a string of given length
376: Not Collective
378: Input Parameters:
379: + len - the length of `str`
380: - format - the usual `printf()` format string
382: Output Parameter:
383: . str - the resulting string
385: Level: intermediate
387: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
388: `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
389: `PetscVFPrintf()`, `PetscFFlush()`
390: @*/
391: PetscErrorCode PetscSNPrintf(char *str, size_t len, const char format[], ...)
392: {
393: size_t fullLength;
394: va_list Argp;
396: PetscFunctionBegin;
397: va_start(Argp, format);
398: PetscCall(PetscVSNPrintf(str, len, format, &fullLength, Argp));
399: va_end(Argp);
400: PetscFunctionReturn(PETSC_SUCCESS);
401: }
403: /*@C
404: PetscSNPrintfCount - Prints to a string of given length, returns count of characters printed
406: Not Collective
408: Input Parameters:
409: + len - the length of `str`
410: . format - the usual `printf()` format string
411: - ... - args to format
413: Output Parameters:
414: + str - the resulting string
415: - countused - number of characters printed
417: Level: intermediate
419: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`, `PetscVSNPrintf()`,
420: `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscSNPrintf()`, `PetscVFPrintf()`
421: @*/
422: PetscErrorCode PetscSNPrintfCount(char *str, size_t len, const char format[], size_t *countused, ...)
423: {
424: va_list Argp;
426: PetscFunctionBegin;
427: va_start(Argp, countused);
428: PetscCall(PetscVSNPrintf(str, len, format, countused, Argp));
429: va_end(Argp);
430: PetscFunctionReturn(PETSC_SUCCESS);
431: }
433: PrintfQueue petsc_printfqueue = NULL, petsc_printfqueuebase = NULL;
434: int petsc_printfqueuelength = 0;
436: static inline PetscErrorCode PetscVFPrintf_Private(MPI_Comm comm, FILE *fd, const char format[], va_list Argp)
437: {
438: const PetscBool tee = (PetscBool)(petsc_history && (fd != petsc_history));
439: PetscMPIInt rank;
440: va_list cpy;
442: PetscFunctionBegin;
443: PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
444: PetscCallMPI(MPI_Comm_rank(comm, &rank));
445: if (PetscLikely(rank != 0)) PetscFunctionReturn(PETSC_SUCCESS);
446: // must do this before we possibly consume Argp
447: if (tee) va_copy(cpy, Argp);
448: PetscCall((*PetscVFPrintf)(fd, format, Argp));
449: if (tee) {
450: PetscCall((*PetscVFPrintf)(petsc_history, format, cpy));
451: va_end(cpy);
452: }
453: PetscFunctionReturn(PETSC_SUCCESS);
454: }
456: static inline PetscErrorCode PetscSynchronizedFPrintf_Private(MPI_Comm comm, FILE *fp, const char format[], va_list Argp)
457: {
458: PetscMPIInt rank;
459: va_list cpy;
461: PetscFunctionBegin;
462: PetscCheck(comm != MPI_COMM_NULL, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called with MPI_COMM_NULL, likely PetscObjectComm() failed");
463: PetscCallMPI(MPI_Comm_rank(comm, &rank));
464: /* First processor prints immediately to fp */
465: if (rank == 0) {
466: va_copy(cpy, Argp);
467: PetscCall(PetscVFPrintf_Private(comm, fp, format, cpy));
468: va_end(cpy);
469: } else { /* other processors add to local queue */
470: PrintfQueue next;
471: size_t fullLength = PETSCDEFAULTBUFFERSIZE;
473: PetscCall(PetscNew(&next));
474: if (petsc_printfqueue) {
475: petsc_printfqueue->next = next;
476: petsc_printfqueue = next;
477: petsc_printfqueue->next = NULL;
478: } else petsc_printfqueuebase = petsc_printfqueue = next;
479: petsc_printfqueuelength++;
480: next->size = 0;
481: next->string = NULL;
482: while (fullLength >= next->size) {
483: next->size = fullLength + 1;
484: PetscCall(PetscFree(next->string));
485: PetscCall(PetscMalloc1(next->size, &next->string));
486: PetscCall(PetscArrayzero(next->string, next->size));
487: va_copy(cpy, Argp);
488: PetscCall(PetscVSNPrintf(next->string, next->size, format, &fullLength, cpy));
489: va_end(cpy);
490: }
491: }
492: PetscFunctionReturn(PETSC_SUCCESS);
493: }
495: /*@C
496: PetscSynchronizedPrintf - Prints synchronized output from multiple MPI processes.
497: Output of the first processor is followed by that of the second, etc.
499: Not Collective
501: Input Parameters:
502: + comm - the MPI communicator
503: - format - the usual `printf()` format string
505: Level: intermediate
507: Note:
508: REQUIRES a call to `PetscSynchronizedFlush()` by all the processes after the completion of the calls to `PetscSynchronizedPrintf()` for the information
509: from all the processors to be printed.
511: Fortran Notes:
512: The call sequence is `PetscSynchronizedPrintf`(`MPI_Comm`, `character`(*), `PetscErrorCode` ierr).
513: That is, you can only pass a single character string from Fortran.
515: .seealso: `PetscSynchronizedFlush()`, `PetscSynchronizedFPrintf()`, `PetscFPrintf()`,
516: `PetscPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`,
517: `PetscFFlush()`
518: @*/
519: PetscErrorCode PetscSynchronizedPrintf(MPI_Comm comm, const char format[], ...)
520: {
521: va_list Argp;
523: PetscFunctionBegin;
524: va_start(Argp, format);
525: PetscCall(PetscSynchronizedFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
526: va_end(Argp);
527: PetscFunctionReturn(PETSC_SUCCESS);
528: }
530: /*@C
531: PetscSynchronizedFPrintf - Prints synchronized output to the specified file from
532: several MPI processes. Output of the first process is followed by that of the
533: second, etc.
535: Not Collective
537: Input Parameters:
538: + comm - the MPI communicator
539: . fp - the file pointer
540: - format - the usual `printf()` format string
542: Level: intermediate
544: Note:
545: REQUIRES a intervening call to `PetscSynchronizedFlush()` for the information
546: from all the processors to be printed.
548: .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFPrintf()`,
549: `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
550: `PetscFFlush()`
551: @*/
552: PetscErrorCode PetscSynchronizedFPrintf(MPI_Comm comm, FILE *fp, const char format[], ...)
553: {
554: va_list Argp;
556: PetscFunctionBegin;
557: va_start(Argp, format);
558: PetscCall(PetscSynchronizedFPrintf_Private(comm, fp, format, Argp));
559: va_end(Argp);
560: PetscFunctionReturn(PETSC_SUCCESS);
561: }
563: /*@C
564: PetscSynchronizedFlush - Flushes to the screen output from all processors
565: involved in previous `PetscSynchronizedPrintf()`/`PetscSynchronizedFPrintf()` calls.
567: Collective
569: Input Parameters:
570: + comm - the MPI communicator
571: - fd - the file pointer (valid on MPI rank 0 of the communicator)
573: Level: intermediate
575: Note:
576: If `PetscSynchronizedPrintf()` and/or `PetscSynchronizedFPrintf()` are called with
577: different MPI communicators there must be an intervening call to `PetscSynchronizedFlush()` between the calls with different MPI communicators.
579: Fortran Notes:
580: Pass `PETSC_STDOUT` if the flush is for standard out; otherwise pass a value obtained from `PetscFOpen()`
582: .seealso: `PetscSynchronizedPrintf()`, `PetscFPrintf()`, `PetscPrintf()`, `PetscViewerASCIIPrintf()`,
583: `PetscViewerASCIISynchronizedPrintf()`
584: @*/
585: PetscErrorCode PetscSynchronizedFlush(MPI_Comm comm, FILE *fd)
586: {
587: PetscMPIInt rank, size, tag, i, j, n = 0, dummy = 0;
588: char *message;
589: MPI_Status status;
591: PetscFunctionBegin;
592: PetscCall(PetscCommDuplicate(comm, &comm, &tag));
593: PetscCallMPI(MPI_Comm_rank(comm, &rank));
594: PetscCallMPI(MPI_Comm_size(comm, &size));
596: /* First processor waits for messages from all other processors */
597: if (rank == 0) {
598: if (!fd) fd = PETSC_STDOUT;
599: for (i = 1; i < size; i++) {
600: /* to prevent a flood of messages to process zero, request each message separately */
601: PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
602: PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
603: for (j = 0; j < n; j++) {
604: PetscMPIInt size = 0;
606: PetscCallMPI(MPI_Recv(&size, 1, MPI_INT, i, tag, comm, &status));
607: PetscCall(PetscMalloc1(size, &message));
608: PetscCallMPI(MPI_Recv(message, size, MPI_CHAR, i, tag, comm, &status));
609: PetscCall(PetscFPrintf(comm, fd, "%s", message));
610: PetscCall(PetscFree(message));
611: }
612: }
613: } else { /* other processors send queue to processor 0 */
614: PrintfQueue next = petsc_printfqueuebase, previous;
616: PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
617: PetscCallMPI(MPI_Send(&petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
618: for (i = 0; i < petsc_printfqueuelength; i++) {
619: PetscCallMPI(MPI_Send(&next->size, 1, MPI_INT, 0, tag, comm));
620: PetscCallMPI(MPI_Send(next->string, next->size, MPI_CHAR, 0, tag, comm));
621: previous = next;
622: next = next->next;
623: PetscCall(PetscFree(previous->string));
624: PetscCall(PetscFree(previous));
625: }
626: petsc_printfqueue = NULL;
627: petsc_printfqueuelength = 0;
628: }
629: PetscCall(PetscCommDestroy(&comm));
630: PetscFunctionReturn(PETSC_SUCCESS);
631: }
633: /*@C
634: PetscFPrintf - Prints to a file, only from the first
635: MPI process in the communicator.
637: Not Collective; No Fortran Support
639: Input Parameters:
640: + comm - the MPI communicator
641: . fd - the file pointer
642: - format - the usual `printf()` format string
644: Level: intermediate
646: Developer Notes:
647: This maybe, and is, called from PETSc error handlers and `PetscMallocValidate()` hence it does not use `PetscCallMPI()` which
648: could recursively restart the malloc validation.
650: .seealso: `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
651: `PetscViewerASCIISynchronizedPrintf()`, `PetscSynchronizedFlush()`, `PetscFFlush()`
652: @*/
653: PetscErrorCode PetscFPrintf(MPI_Comm comm, FILE *fd, const char format[], ...)
654: {
655: va_list Argp;
657: PetscFunctionBegin;
658: va_start(Argp, format);
659: PetscCall(PetscVFPrintf_Private(comm, fd, format, Argp));
660: va_end(Argp);
661: PetscFunctionReturn(PETSC_SUCCESS);
662: }
664: /*@C
665: PetscPrintf - Prints to standard out, only from the first
666: MPI process in the communicator. Calls from other processes are ignored.
668: Not Collective
670: Input Parameters:
671: + comm - the communicator
672: - format - the usual `printf()` format string
674: Level: intermediate
676: Note:
677: Deprecated information: `PetscPrintf()` supports some format specifiers that are unique to PETSc.
678: See the manual page for `PetscFormatConvert()` for details.
680: Fortran Notes:
681: The call sequence is `PetscPrintf`(MPI_Comm, character(*), `PetscErrorCode` ierr) from Fortran.
682: That is, you can only pass a single character string from Fortran.
684: .seealso: `PetscFPrintf()`, `PetscSynchronizedPrintf()`, `PetscFormatConvert()`, `PetscFFlush()`
685: @*/
686: PetscErrorCode PetscPrintf(MPI_Comm comm, const char format[], ...)
687: {
688: va_list Argp;
690: PetscFunctionBegin;
691: va_start(Argp, format);
692: PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
693: va_end(Argp);
694: PetscFunctionReturn(PETSC_SUCCESS);
695: }
697: PetscErrorCode PetscHelpPrintfDefault(MPI_Comm comm, const char format[], ...)
698: {
699: va_list Argp;
701: PetscFunctionBegin;
702: va_start(Argp, format);
703: PetscCall(PetscVFPrintf_Private(comm, PETSC_STDOUT, format, Argp));
704: va_end(Argp);
705: PetscFunctionReturn(PETSC_SUCCESS);
706: }
708: /*@C
709: PetscSynchronizedFGets - Multiple MPI processes all get the same line from a file.
711: Collective
713: Input Parameters:
714: + comm - the MPI communicator
715: . fp - the file pointer
716: - len - the length of `string`
718: Output Parameter:
719: . string - the line read from the file, at end of file `string`[0] == 0
721: Level: intermediate
723: .seealso: `PetscSynchronizedPrintf()`, `PetscSynchronizedFlush()`,
724: `PetscFOpen()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPrintf()`
725: @*/
726: PetscErrorCode PetscSynchronizedFGets(MPI_Comm comm, FILE *fp, size_t len, char string[])
727: {
728: PetscMPIInt rank;
730: PetscFunctionBegin;
731: PetscCallMPI(MPI_Comm_rank(comm, &rank));
732: if (rank == 0) {
733: if (!fgets(string, len, fp)) {
734: string[0] = 0;
735: PetscCheck(feof(fp), PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "Error reading from file due to \"%s\"", strerror(errno));
736: }
737: }
738: PetscCallMPI(MPI_Bcast(string, len, MPI_BYTE, 0, comm));
739: PetscFunctionReturn(PETSC_SUCCESS);
740: }
742: PetscErrorCode PetscFormatRealArray(char buf[], size_t len, const char *fmt, PetscInt n, const PetscReal x[])
743: {
744: PetscInt i;
745: size_t left, count;
746: char *p;
748: PetscFunctionBegin;
749: for (i = 0, p = buf, left = len; i < n; i++) {
750: PetscCall(PetscSNPrintfCount(p, left, fmt, &count, (double)x[i]));
751: PetscCheck(count < left, PETSC_COMM_SELF, PETSC_ERR_ARG_OUTOFRANGE, "Insufficient space in buffer");
752: left -= count;
753: p += count - 1;
754: *p++ = ' ';
755: }
756: p[i ? 0 : -1] = 0;
757: PetscFunctionReturn(PETSC_SUCCESS);
758: }