1 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/
2
3 #define QUEUESTRINGSIZE 8192
4
PetscViewerFileClose_ASCII(PetscViewer viewer)5 static PetscErrorCode PetscViewerFileClose_ASCII(PetscViewer viewer)
6 {
7 PetscMPIInt rank;
8 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
9 int err;
10
11 PetscFunctionBegin;
12 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
13 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
14 if (rank == 0 && vascii->fd != stderr && vascii->fd != PETSC_STDOUT) {
15 if (vascii->fd && vascii->closefile) {
16 err = fclose(vascii->fd);
17 PetscCheck(!err, PETSC_COMM_SELF, PETSC_ERR_SYS, "fclose() failed on file");
18 }
19 if (vascii->storecompressed) {
20 char par[PETSC_MAX_PATH_LEN], buf[PETSC_MAX_PATH_LEN];
21 FILE *fp;
22 PetscCall(PetscStrncpy(par, "gzip ", sizeof(par)));
23 PetscCall(PetscStrlcat(par, vascii->filename, sizeof(par)));
24 #if defined(PETSC_HAVE_POPEN)
25 PetscCall(PetscPOpen(PETSC_COMM_SELF, NULL, par, "r", &fp));
26 PetscCheck(!fgets(buf, 1024, fp), PETSC_COMM_SELF, PETSC_ERR_LIB, "Error from compression command %s %s", par, buf);
27 PetscCall(PetscPClose(PETSC_COMM_SELF, fp));
28 #else
29 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_SUP_SYS, "Cannot run external programs on this machine");
30 #endif
31 }
32 }
33 PetscCall(PetscFree(vascii->filename));
34 PetscFunctionReturn(PETSC_SUCCESS);
35 }
36
PetscViewerDestroy_ASCII(PetscViewer viewer)37 static PetscErrorCode PetscViewerDestroy_ASCII(PetscViewer viewer)
38 {
39 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
40 PetscViewerLink *vlink;
41 PetscMPIInt iflg;
42
43 PetscFunctionBegin;
44 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
45 PetscCall(PetscViewerFileClose_ASCII(viewer));
46 PetscCall(PetscFree(vascii));
47
48 /* remove the viewer from the list in the MPI Communicator */
49 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, NULL));
50
51 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, (void **)&vlink, &iflg));
52 if (iflg) {
53 if (vlink && vlink->viewer == viewer) {
54 if (vlink->next) {
55 PetscCallMPI(MPI_Comm_set_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval, vlink->next));
56 } else {
57 PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_keyval));
58 }
59 PetscCall(PetscFree(vlink));
60 } else {
61 while (vlink && vlink->next) {
62 if (vlink->next->viewer == viewer) {
63 PetscViewerLink *nv = vlink->next;
64 vlink->next = vlink->next->next;
65 PetscCall(PetscFree(nv));
66 }
67 vlink = vlink->next;
68 }
69 }
70 }
71
72 if (Petsc_Viewer_Stdout_keyval != MPI_KEYVAL_INVALID) {
73 PetscViewer aviewer;
74 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval, (void **)&aviewer, &iflg));
75 if (iflg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stdout_keyval));
76 }
77 if (Petsc_Viewer_Stderr_keyval != MPI_KEYVAL_INVALID) {
78 PetscViewer aviewer;
79 PetscCallMPI(MPI_Comm_get_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval, (void **)&aviewer, &iflg));
80 if (iflg && aviewer == viewer) PetscCallMPI(MPI_Comm_delete_attr(PetscObjectComm((PetscObject)viewer), Petsc_Viewer_Stderr_keyval));
81 }
82 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL));
83 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL));
84 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL));
85 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL));
86 PetscFunctionReturn(PETSC_SUCCESS);
87 }
88
PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)89 static PetscErrorCode PetscViewerDestroy_ASCII_SubViewer(PetscViewer viewer)
90 {
91 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
92
93 PetscFunctionBegin;
94 PetscCall(PetscViewerRestoreSubViewer(vascii->bviewer, 0, &viewer));
95 PetscFunctionReturn(PETSC_SUCCESS);
96 }
97
98 /*@C
99 PetscViewerASCIIGetPointer - Extracts the file pointer from an ASCII `PetscViewer`.
100
101 Not Collective, depending on the viewer the value may be meaningless except for process 0 of the viewer; No Fortran Support
102
103 Input Parameter:
104 . viewer - `PetscViewer` context, obtained from `PetscViewerASCIIOpen()`
105
106 Output Parameter:
107 . fd - file pointer
108
109 Level: intermediate
110
111 Note:
112 For the standard `PETSCVIEWERASCII` the value is valid only on MPI rank 0 of the viewer
113
114 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscViewerASCIIOpen()`, `PetscViewerDestroy()`, `PetscViewerSetType()`,
115 `PetscViewerCreate()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`
116 @*/
PetscViewerASCIIGetPointer(PetscViewer viewer,FILE ** fd)117 PetscErrorCode PetscViewerASCIIGetPointer(PetscViewer viewer, FILE **fd)
118 {
119 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
120
121 PetscFunctionBegin;
122 PetscCheck(!vascii->fileunit, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot request file pointer for viewers that use Fortran files");
123 *fd = vascii->fd;
124 PetscFunctionReturn(PETSC_SUCCESS);
125 }
126
PetscViewerFileGetMode_ASCII(PetscViewer viewer,PetscFileMode * mode)127 static PetscErrorCode PetscViewerFileGetMode_ASCII(PetscViewer viewer, PetscFileMode *mode)
128 {
129 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
130
131 PetscFunctionBegin;
132 *mode = vascii->mode;
133 PetscFunctionReturn(PETSC_SUCCESS);
134 }
135
PetscViewerFileSetMode_ASCII(PetscViewer viewer,PetscFileMode mode)136 static PetscErrorCode PetscViewerFileSetMode_ASCII(PetscViewer viewer, PetscFileMode mode)
137 {
138 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
139
140 PetscFunctionBegin;
141 vascii->mode = mode;
142 PetscFunctionReturn(PETSC_SUCCESS);
143 }
144
145 /*
146 If petsc_history is on, then all Petsc*Printf() results are saved
147 if the appropriate (usually .petschistory) file.
148 */
149 PETSC_INTERN FILE *petsc_history;
150
151 /*@
152 PetscViewerASCIISetTab - Causes `PetscViewer` to tab in a number of times before printing
153
154 Not Collective, but only first processor in set has any effect; No Fortran Support
155
156 Input Parameters:
157 + viewer - obtained with `PetscViewerASCIIOpen()`
158 - tabs - number of tabs
159
160 Level: developer
161
162 Note:
163 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
164
165 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
166 `PetscViewerASCIIGetTab()`,
167 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
168 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
169 `PetscViewerASCIIPushTab()`
170 @*/
PetscViewerASCIISetTab(PetscViewer viewer,PetscInt tabs)171 PetscErrorCode PetscViewerASCIISetTab(PetscViewer viewer, PetscInt tabs)
172 {
173 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
174 PetscBool isascii;
175
176 PetscFunctionBegin;
177 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
178 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
179 if (isascii) ascii->tab = tabs;
180 PetscFunctionReturn(PETSC_SUCCESS);
181 }
182
183 /*@
184 PetscViewerASCIIGetTab - Return the number of tabs used by `PetscViewer`.
185
186 Not Collective, meaningful on first processor only; No Fortran Support
187
188 Input Parameter:
189 . viewer - obtained with `PetscViewerASCIIOpen()`
190
191 Output Parameter:
192 . tabs - number of tabs
193
194 Level: developer
195
196 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
197 `PetscViewerASCIISetTab()`,
198 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
199 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
200 @*/
PetscViewerASCIIGetTab(PetscViewer viewer,PetscInt * tabs)201 PetscErrorCode PetscViewerASCIIGetTab(PetscViewer viewer, PetscInt *tabs)
202 {
203 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
204 PetscBool isascii;
205
206 PetscFunctionBegin;
207 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
208 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
209 if (isascii && tabs) *tabs = ascii->tab;
210 PetscFunctionReturn(PETSC_SUCCESS);
211 }
212
213 /*@
214 PetscViewerASCIIAddTab - Add to the number of times a `PETSCVIEWERASCII` viewer tabs before printing
215
216 Not Collective, but only first processor in set has any effect; No Fortran Support
217
218 Input Parameters:
219 + viewer - obtained with `PetscViewerASCIIOpen()`
220 - tabs - number of tabs
221
222 Level: developer
223
224 Note:
225 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
226
227 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
228 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
229 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushTab()`
230 @*/
PetscViewerASCIIAddTab(PetscViewer viewer,PetscInt tabs)231 PetscErrorCode PetscViewerASCIIAddTab(PetscViewer viewer, PetscInt tabs)
232 {
233 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
234 PetscBool isascii;
235
236 PetscFunctionBegin;
237 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
238 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
239 if (isascii) ascii->tab += tabs;
240 PetscFunctionReturn(PETSC_SUCCESS);
241 }
242
243 /*@
244 PetscViewerASCIISubtractTab - Subtracts from the number of times a `PETSCVIEWERASCII` viewer tabs before printing
245
246 Not Collective, but only first processor in set has any effect; No Fortran Support
247
248 Input Parameters:
249 + viewer - obtained with `PetscViewerASCIIOpen()`
250 - tabs - number of tabs
251
252 Level: developer
253
254 Note:
255 `PetscViewerASCIIPushTab()` and `PetscViewerASCIIPopTab()` are the preferred usage
256
257 .seealso: [](sec_viewers), `PETSCVIEWERASCII`, `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
258 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
259 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`,
260 `PetscViewerASCIIPushTab()`
261 @*/
PetscViewerASCIISubtractTab(PetscViewer viewer,PetscInt tabs)262 PetscErrorCode PetscViewerASCIISubtractTab(PetscViewer viewer, PetscInt tabs)
263 {
264 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
265 PetscBool isascii;
266
267 PetscFunctionBegin;
268 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
269 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
270 if (isascii) ascii->tab -= tabs;
271 PetscFunctionReturn(PETSC_SUCCESS);
272 }
273
274 /*@
275 PetscViewerASCIIPushSynchronized - Allows calls to `PetscViewerASCIISynchronizedPrintf()` for this viewer
276
277 Collective
278
279 Input Parameter:
280 . viewer - obtained with `PetscViewerASCIIOpen()`
281
282 Level: intermediate
283
284 Note:
285 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
286
287 .seealso: [](sec_viewers), `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
288 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
289 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
290 @*/
PetscViewerASCIIPushSynchronized(PetscViewer viewer)291 PetscErrorCode PetscViewerASCIIPushSynchronized(PetscViewer viewer)
292 {
293 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
294 PetscBool isascii;
295
296 PetscFunctionBegin;
297 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
298 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
299 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
300 if (isascii) ascii->allowsynchronized++;
301 PetscFunctionReturn(PETSC_SUCCESS);
302 }
303
304 /*@
305 PetscViewerASCIIPopSynchronized - Undoes most recent `PetscViewerASCIIPushSynchronized()` for this viewer
306
307 Collective
308
309 Input Parameter:
310 . viewer - obtained with `PetscViewerASCIIOpen()`
311
312 Level: intermediate
313
314 Note:
315 See documentation of `PetscViewerASCIISynchronizedPrintf()` for more details how the synchronized output should be done properly.
316
317 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerFlush()`,
318 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
319 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
320 @*/
PetscViewerASCIIPopSynchronized(PetscViewer viewer)321 PetscErrorCode PetscViewerASCIIPopSynchronized(PetscViewer viewer)
322 {
323 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
324 PetscBool isascii;
325
326 PetscFunctionBegin;
327 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
328 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
329 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
330 if (isascii) {
331 ascii->allowsynchronized--;
332 PetscCheck(ascii->allowsynchronized >= 0, PETSC_COMM_SELF, PETSC_ERR_PLIB, "Called more times than PetscViewerASCIIPushSynchronized()");
333 }
334 PetscFunctionReturn(PETSC_SUCCESS);
335 }
336
337 /*@
338 PetscViewerASCIIPushTab - Adds one more tab to the amount that `PetscViewerASCIIPrintf()`
339 lines are tabbed.
340
341 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
342
343 Input Parameter:
344 . viewer - obtained with `PetscViewerASCIIOpen()`
345
346 Level: developer
347
348 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
349 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
350 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
351 @*/
PetscViewerASCIIPushTab(PetscViewer viewer)352 PetscErrorCode PetscViewerASCIIPushTab(PetscViewer viewer)
353 {
354 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
355 PetscBool isascii;
356
357 PetscFunctionBegin;
358 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
359 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
360 if (isascii) ascii->tab++;
361 PetscFunctionReturn(PETSC_SUCCESS);
362 }
363
364 /*@
365 PetscViewerASCIIPopTab - Removes one tab from the amount that `PetscViewerASCIIPrintf()` lines are tabbed that was provided by
366 `PetscViewerASCIIPushTab()`
367
368 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
369
370 Input Parameter:
371 . viewer - obtained with `PetscViewerASCIIOpen()`
372
373 Level: developer
374
375 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
376 `PetscViewerASCIIPushTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
377 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
378 @*/
PetscViewerASCIIPopTab(PetscViewer viewer)379 PetscErrorCode PetscViewerASCIIPopTab(PetscViewer viewer)
380 {
381 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
382 PetscBool isascii;
383
384 PetscFunctionBegin;
385 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
386 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
387 if (isascii) {
388 PetscCheck(ascii->tab > 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "More tabs popped than pushed");
389 ascii->tab--;
390 }
391 PetscFunctionReturn(PETSC_SUCCESS);
392 }
393
394 /*@
395 PetscViewerASCIIUseTabs - Turns on or off the use of tabs with the `PETSCVIEWERASCII` `PetscViewer`
396
397 Not Collective, but only first MPI rank in the viewer has any effect; No Fortran Support
398
399 Input Parameters:
400 + viewer - obtained with `PetscViewerASCIIOpen()`
401 - flg - `PETSC_TRUE` or `PETSC_FALSE`
402
403 Level: developer
404
405 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`,
406 `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`, `PetscViewerASCIIPushTab()`, `PetscViewerASCIIOpen()`,
407 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`
408 @*/
PetscViewerASCIIUseTabs(PetscViewer viewer,PetscBool flg)409 PetscErrorCode PetscViewerASCIIUseTabs(PetscViewer viewer, PetscBool flg)
410 {
411 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
412 PetscBool isascii;
413
414 PetscFunctionBegin;
415 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
416 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
417 if (isascii) {
418 if (flg) ascii->tab = ascii->tab_store;
419 else {
420 ascii->tab_store = ascii->tab;
421 ascii->tab = 0;
422 }
423 }
424 PetscFunctionReturn(PETSC_SUCCESS);
425 }
426
427 #if defined(PETSC_USE_FORTRAN_BINDINGS)
428
429 #if defined(PETSC_HAVE_FORTRAN_CAPS)
430 #define petscviewerasciiopenwithfileunit_ PETSCVIEWERASCIIOPENWITHFILEUNIT
431 #define petscviewerasciisetfileunit_ PETSCVIEWERASCIISETFILEUNIT
432 #define petscviewerasciistdoutsetfileunit_ PETSCVIEWERASCIISTDOUTSETFILEUNIT
433 #define petscfortranprinttofileunit_ PETSCFORTRANPRINTTOFILEUNIT
434 #elif !defined(PETSC_HAVE_FORTRAN_UNDERSCORE)
435 #define petscviewerasciiopenwithfileunit_ petscviewerasciiopenwithfileunit
436 #define petscviewerasciisetfileunit_ petscviewerasciisetfileunit
437 #define petscviewerasciistdoutsetfileunit_ petscviewerasciistdoutsetfileunit
438 #define petscfortranprinttofileunit_ petscfortranprinttofileunit
439 #endif
440
441 #if defined(__cplusplus)
442 extern "C" void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
443 #else
444 extern void petscfortranprinttofileunit_(int *, const char *, PetscErrorCode *, PETSC_FORTRAN_CHARLEN_T);
445 #endif
446
447 #define PETSCDEFAULTBUFFERSIZE 8 * 1024
448
449 static int PETSC_VIEWER_ASCII_STDOUT_fileunit = 0;
450
451 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
452 /*MC
453 PetscViewerASCIIStdoutSetFileUnit - sets `PETSC_VIEWER_STDOUT_()` to write to a Fortran IO unit
454
455 Synopsis:
456 #include <petscviewer.h>
457 void PetscViewerASCIIStdoutSetFileUnit(PetscInt unit, PetscErrorCode ierr)
458
459 Input Parameter:
460 . unit - the unit number
461
462 Output Parameter:
463 . ierr - the error code
464
465 Level: intermediate
466
467 Notes:
468 Can be called before `PetscInitialize()`
469
470 Immediately changes the output for all `PETSC_VIEWER_STDOUT_()` viewers
471
472 This may not work currently with some viewers that (improperly) use the `fd` directly instead of `PetscViewerASCIIPrintf()`
473
474 With this option, for example, `-log_options` results will be saved to the Fortran file
475
476 Any process may call this but only the unit passed on the first process is used
477
478 Fortran Note:
479 Only for Fortran
480
481 Developer Note:
482 `PetscViewerASCIIWORLDSetFilename()` and `PetscViewerASCIIWORLDSetFILE()` could be added
483
484 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`,
485 `PETSC_VIEWER_STDOUT_()`, `PetscViewerASCIIGetStdout()`
486 M*/
petscviewerasciistdoutsetfileunit_(int * unit,PetscErrorCode * ierr)487 PETSC_EXTERN void petscviewerasciistdoutsetfileunit_(int *unit, PetscErrorCode *ierr)
488 {
489 #if defined(PETSC_USE_FORTRAN_BINDINGS)
490 PETSC_VIEWER_ASCII_STDOUT_fileunit = *unit;
491 #endif
492 }
493
494 #include <petsc/private/ftnimpl.h>
495
496 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
497 /*MC
498 PetscViewerASCIISetFileUnit - sets the `PETSCVIEWERASCII` `PetscViewer` to write to a Fortran IO unit
499
500 Synopsis:
501 #include <petscviewer.h>
502 void PetscViewerASCIISetFileUnit(PetscViewer viewer, PetscInt unit, PetscErrorCode ierr)
503
504 Input Parameters:
505 + viewer - the viewer
506 - unit - the unit number
507
508 Output Parameter:
509 . ierr - the error code
510
511 Level: intermediate
512
513 Note:
514 `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
515
516 Fortran Notes:
517 Only for Fortran, use `PetscViewerASCIISetFILE()` for C
518
519 .seealso: `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFileUnit()`, `PetscViewerASCIIStdoutSetFileUnit()`
520 M*/
petscviewerasciisetfileunit_(PetscViewer * viewer,int * unit,PetscErrorCode * ierr)521 PETSC_EXTERN void petscviewerasciisetfileunit_(PetscViewer *viewer, int *unit, PetscErrorCode *ierr)
522 {
523 PetscViewer_ASCII *vascii;
524 PetscViewer v;
525
526 PetscPatchDefaultViewers_Fortran(viewer, v);
527 vascii = (PetscViewer_ASCII *)v->data;
528 if (vascii->mode == FILE_MODE_READ) {
529 *ierr = PETSC_ERR_ARG_WRONGSTATE;
530 return;
531 }
532 vascii->fileunit = *unit;
533 }
534
535 // PetscClangLinter pragma disable: -fdoc-synopsis-macro-explicit-synopsis-valid-header
536 /*MC
537 PetscViewerASCIIOpenWithFileUnit - opens a `PETSCVIEWERASCII` to write to a Fortran IO unit
538
539 Synopsis:
540 #include <petscviewer.h>
541 void PetscViewerASCIIOpenWithFileUnit((MPI_Fint comm, integer unit, PetscViewer viewer, PetscErrorCode ierr)
542
543 Input Parameters:
544 + comm - the `MPI_Comm` to share the viewer
545 - unit - the unit number
546
547 Output Parameters:
548 + viewer - the viewer
549 - ierr - the error code
550
551 Level: intermediate
552
553 Note:
554 `PetscViewerDestroy()` does not close the unit for this `PetscViewer`
555
556 Fortran Notes:
557 Only for Fortran, use `PetscViewerASCIIOpenWithFILE()` for C
558
559 .seealso: `PetscViewerASCIISetFileUnit()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII`, `PetscViewerASCIIOpenWithFILE()`
560 M*/
petscviewerasciiopenwithfileunit_(MPI_Fint * comm,int * unit,PetscViewer * viewer,PetscErrorCode * ierr)561 PETSC_EXTERN void petscviewerasciiopenwithfileunit_(MPI_Fint *comm, int *unit, PetscViewer *viewer, PetscErrorCode *ierr)
562 {
563 *ierr = PetscViewerCreate(MPI_Comm_f2c(*(MPI_Fint *)&*comm), viewer);
564 if (*ierr) return;
565 *ierr = PetscViewerSetType(*viewer, PETSCVIEWERASCII);
566 if (*ierr) return;
567 *ierr = PetscViewerFileSetMode(*viewer, FILE_MODE_WRITE);
568 if (*ierr) return;
569 petscviewerasciisetfileunit_(viewer, unit, ierr);
570 }
571
PetscVFPrintfFortran(int unit,const char format[],va_list Argp)572 static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
573 {
574 PetscErrorCode ierr;
575 char str[PETSCDEFAULTBUFFERSIZE];
576 size_t len;
577
578 PetscFunctionBegin;
579 PetscCall(PetscVSNPrintf(str, sizeof(str), format, NULL, Argp));
580 PetscCall(PetscStrlen(str, &len));
581 petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
582 PetscFunctionReturn(PETSC_SUCCESS);
583 }
584
PetscFPrintfFortran(int unit,const char str[])585 static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
586 {
587 PetscErrorCode ierr;
588 size_t len;
589
590 PetscFunctionBegin;
591 PetscCall(PetscStrlen(str, &len));
592 petscfortranprinttofileunit_(&unit, str, &ierr, (int)len);
593 PetscFunctionReturn(PETSC_SUCCESS);
594 }
595
596 #else
597
598 /* these will never be used; but are needed to link with */
PetscVFPrintfFortran(int unit,const char format[],va_list Argp)599 static PetscErrorCode PetscVFPrintfFortran(int unit, const char format[], va_list Argp)
600 {
601 PetscFunctionBegin;
602 PetscFunctionReturn(PETSC_SUCCESS);
603 }
604
PetscFPrintfFortran(int unit,const char str[])605 static PetscErrorCode PetscFPrintfFortran(int unit, const char str[])
606 {
607 PetscFunctionBegin;
608 PetscFunctionReturn(PETSC_SUCCESS);
609 }
610 #endif
611
612 /*@
613 PetscViewerASCIIGetStdout - Creates a `PETSCVIEWERASCII` `PetscViewer` shared by all processes
614 in a communicator that prints to `stdout`. Error returning version of `PETSC_VIEWER_STDOUT_()`
615
616 Collective
617
618 Input Parameter:
619 . comm - the MPI communicator to share the `PetscViewer`
620
621 Output Parameter:
622 . viewer - the viewer
623
624 Level: beginner
625
626 Note:
627 Use `PetscViewerDestroy()` to destroy it
628
629 Developer Note:
630 This should be used in all PETSc source code instead of `PETSC_VIEWER_STDOUT_()` since it allows error checking
631
632 .seealso: [](sec_viewers), `PetscViewerASCIIGetStderr()`, `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`,
633 `PETSC_VIEWER_STDOUT_SELF`
634 @*/
PetscViewerASCIIGetStdout(MPI_Comm comm,PetscViewer * viewer)635 PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer)
636 {
637 PetscMPIInt iflg;
638 MPI_Comm ncomm;
639
640 PetscFunctionBegin;
641 PetscAssertPointer(viewer, 2);
642 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout));
643 PetscCall(PetscCommDuplicate(comm, &ncomm, NULL));
644 if (Petsc_Viewer_Stdout_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stdout_keyval, NULL));
645 PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, &iflg));
646 if (!iflg) { /* PetscViewer not yet created */
647 #if defined(PETSC_USE_FORTRAN_BINDINGS)
648 PetscCallMPI(MPI_Bcast(&PETSC_VIEWER_ASCII_STDOUT_fileunit, 1, MPI_INT, 0, comm));
649 if (PETSC_VIEWER_ASCII_STDOUT_fileunit) {
650 PetscErrorCode ierr;
651 MPI_Fint fcomm = MPI_Comm_c2f(ncomm);
652
653 petscviewerasciiopenwithfileunit_(&fcomm, &PETSC_VIEWER_ASCII_STDOUT_fileunit, viewer, &ierr);
654 } else
655 #endif
656 {
657 PetscViewerFormat format;
658 PetscBool set;
659
660 PetscCall(PetscViewerCreate(ncomm, viewer));
661 PetscCall(PetscViewerSetType(*viewer, PETSCVIEWERASCII));
662 PetscCall(PetscOptionsGetEnum(NULL, NULL, "-petsc_viewer_stdout_format", PetscViewerFormats, (PetscEnum *)&format, &set));
663 if (set) PetscCall(PetscViewerPushFormat(*viewer, format));
664 PetscCall(PetscViewerFileSetName(*viewer, "stdout"));
665 }
666 PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer));
667 PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer));
668 }
669 PetscCall(PetscCommDestroy(&ncomm));
670 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout));
671 #if defined(PETSC_USE_FORTRAN_BINDINGS)
672 ((PetscViewer_ASCII *)(*viewer)->data)->fileunit = PETSC_VIEWER_ASCII_STDOUT_fileunit;
673 #endif
674 PetscFunctionReturn(PETSC_SUCCESS);
675 }
676
677 /*@C
678 PetscViewerASCIIPrintf - Prints to a file, only from the first
679 processor in the `PetscViewer` of type `PETSCVIEWERASCII`
680
681 Not Collective, but only the first MPI rank in the viewer has any effect
682
683 Input Parameters:
684 + viewer - obtained with `PetscViewerASCIIOpen()`
685 - format - the usual printf() format string
686
687 Level: developer
688
689 Fortran Note:
690 The call sequence is `PetscViewerASCIIPrintf`(`PetscViewer`, character(*), int ierr).
691 That is, you can only pass a single character string from Fortran.
692
693 .seealso: [](sec_viewers), `PetscPrintf()`, `PetscSynchronizedPrintf()`, `PetscViewerASCIIOpen()`,
694 `PetscViewerASCIIPushTab()`, `PetscViewerASCIIPopTab()`, `PetscViewerASCIISynchronizedPrintf()`,
695 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`, `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPushSynchronized()`
696 @*/
PetscViewerASCIIPrintf(PetscViewer viewer,const char format[],...)697 PetscErrorCode PetscViewerASCIIPrintf(PetscViewer viewer, const char format[], ...)
698 {
699 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
700 PetscMPIInt rank;
701 PetscInt tab = 0, intab = ascii->tab;
702 FILE *fd = ascii->fd;
703 PetscBool isascii;
704
705 PetscFunctionBegin;
706 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
707 PetscCheck(!ascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
708 PetscAssertPointer(format, 2);
709 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
710 PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
711 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
712 if (rank) PetscFunctionReturn(PETSC_SUCCESS);
713
714 if (ascii->bviewer) { /* pass string up to parent viewer */
715 char *string;
716 va_list Argp;
717 size_t fullLength;
718
719 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
720 for (; tab < ascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
721 va_start(Argp, format);
722 PetscCall(PetscVSNPrintf(string + 2 * intab, QUEUESTRINGSIZE - 2 * intab, format, &fullLength, Argp));
723 va_end(Argp);
724 PetscCall(PetscViewerASCIISynchronizedPrintf(ascii->bviewer, "%s", string));
725 PetscCall(PetscFree(string));
726 } else { /* write directly to file */
727 va_list Argp;
728
729 tab = intab;
730 while (tab--) {
731 if (!ascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fd, " "));
732 else PetscCall(PetscFPrintfFortran(ascii->fileunit, " "));
733 }
734
735 va_start(Argp, format);
736 if (!ascii->fileunit) PetscCall((*PetscVFPrintf)(fd, format, Argp));
737 else PetscCall(PetscVFPrintfFortran(ascii->fileunit, format, Argp));
738 va_end(Argp);
739 PetscCall(PetscFFlush(fd));
740 }
741 PetscFunctionReturn(PETSC_SUCCESS);
742 }
743
744 /*@
745 PetscViewerFileSetName - Sets the name of the file the `PetscViewer` should use.
746
747 Collective
748
749 Input Parameters:
750 + viewer - the `PetscViewer`; for example, of type `PETSCVIEWERASCII` or `PETSCVIEWERBINARY`
751 - name - the name of the file it should use
752
753 Level: advanced
754
755 Note:
756 This will have no effect on viewers that are not related to files
757
758 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerDestroy()`,
759 `PetscViewerASCIIGetPointer()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIISynchronizedPrintf()`
760 @*/
PetscViewerFileSetName(PetscViewer viewer,const char name[])761 PetscErrorCode PetscViewerFileSetName(PetscViewer viewer, const char name[])
762 {
763 char filename[PETSC_MAX_PATH_LEN];
764
765 PetscFunctionBegin;
766 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
767 PetscAssertPointer(name, 2);
768 PetscCall(PetscStrreplace(PetscObjectComm((PetscObject)viewer), name, filename, sizeof(filename)));
769 PetscTryMethod(viewer, "PetscViewerFileSetName_C", (PetscViewer, const char[]), (viewer, filename));
770 PetscFunctionReturn(PETSC_SUCCESS);
771 }
772
773 /*@C
774 PetscViewerFileGetName - Gets the name of the file the `PetscViewer` is using
775
776 Not Collective
777
778 Input Parameter:
779 . viewer - the `PetscViewer`
780
781 Output Parameter:
782 . name - the name of the file it is using
783
784 Level: advanced
785
786 Note:
787 This will have no effect on viewers that are not related to files
788
789 .seealso: [](sec_viewers), `PetscViewerCreate()`, `PetscViewerSetType()`, `PetscViewerASCIIOpen()`, `PetscViewerBinaryOpen()`, `PetscViewerFileSetName()`
790 @*/
PetscViewerFileGetName(PetscViewer viewer,const char * name[])791 PetscErrorCode PetscViewerFileGetName(PetscViewer viewer, const char *name[])
792 {
793 PetscFunctionBegin;
794 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
795 PetscAssertPointer(name, 2);
796 PetscUseMethod(viewer, "PetscViewerFileGetName_C", (PetscViewer, const char **), (viewer, name));
797 PetscFunctionReturn(PETSC_SUCCESS);
798 }
799
PetscViewerFileGetName_ASCII(PetscViewer viewer,const char ** name)800 static PetscErrorCode PetscViewerFileGetName_ASCII(PetscViewer viewer, const char **name)
801 {
802 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
803
804 PetscFunctionBegin;
805 *name = vascii->filename;
806 PetscFunctionReturn(PETSC_SUCCESS);
807 }
808
809 #include <errno.h>
PetscViewerFileSetName_ASCII(PetscViewer viewer,const char name[])810 static PetscErrorCode PetscViewerFileSetName_ASCII(PetscViewer viewer, const char name[])
811 {
812 size_t len;
813 char fname[PETSC_MAX_PATH_LEN], *gz = NULL;
814 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
815 PetscBool isstderr, isstdout;
816 PetscMPIInt rank;
817
818 PetscFunctionBegin;
819 PetscCall(PetscViewerFileClose_ASCII(viewer));
820 if (!name) PetscFunctionReturn(PETSC_SUCCESS);
821 PetscCall(PetscStrallocpy(name, &vascii->filename));
822
823 /* Is this file to be compressed */
824 vascii->storecompressed = PETSC_FALSE;
825
826 PetscCall(PetscStrstr(vascii->filename, ".gz", &gz));
827 if (gz) {
828 PetscCall(PetscStrlen(gz, &len));
829 if (len == 3) {
830 PetscCheck(vascii->mode == FILE_MODE_WRITE, PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Cannot open ASCII PetscViewer file that is compressed; uncompress it manually first");
831 *gz = 0;
832 vascii->storecompressed = PETSC_TRUE;
833 }
834 }
835 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
836 if (rank == 0) {
837 PetscCall(PetscStrcmp(name, "stderr", &isstderr));
838 PetscCall(PetscStrcmp(name, "stdout", &isstdout));
839 /* empty filename means stdout */
840 if (name[0] == 0) isstdout = PETSC_TRUE;
841 if (isstderr) vascii->fd = PETSC_STDERR;
842 else if (isstdout) vascii->fd = PETSC_STDOUT;
843 else {
844 PetscCall(PetscFixFilename(name, fname));
845 switch (vascii->mode) {
846 case FILE_MODE_READ:
847 vascii->fd = fopen(fname, "r");
848 break;
849 case FILE_MODE_WRITE:
850 vascii->fd = fopen(fname, "w");
851 break;
852 case FILE_MODE_APPEND:
853 vascii->fd = fopen(fname, "a");
854 break;
855 case FILE_MODE_UPDATE:
856 vascii->fd = fopen(fname, "r+");
857 if (!vascii->fd) vascii->fd = fopen(fname, "w+");
858 break;
859 case FILE_MODE_APPEND_UPDATE:
860 /* I really want a file which is opened at the end for updating,
861 not a+, which opens at the beginning, but makes writes at the end.
862 */
863 vascii->fd = fopen(fname, "r+");
864 if (!vascii->fd) vascii->fd = fopen(fname, "w+");
865 else {
866 int ret = fseek(vascii->fd, 0, SEEK_END);
867 PetscCheck(!ret, PETSC_COMM_SELF, PETSC_ERR_LIB, "fseek() failed with error code %d", ret);
868 }
869 break;
870 default:
871 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[vascii->mode]);
872 }
873 PetscCheck(vascii->fd, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s due to \"%s\"", fname, strerror(errno));
874 }
875 }
876 PetscCall(PetscLogObjectState((PetscObject)viewer, "File: %s", name));
877 PetscFunctionReturn(PETSC_SUCCESS);
878 }
879
PetscViewerGetSubViewer_ASCII(PetscViewer viewer,MPI_Comm subcomm,PetscViewer * outviewer)880 static PetscErrorCode PetscViewerGetSubViewer_ASCII(PetscViewer viewer, MPI_Comm subcomm, PetscViewer *outviewer)
881 {
882 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data, *ovascii;
883
884 PetscFunctionBegin;
885 PetscCheck(!vascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer already obtained from PetscViewer and not restored");
886 PetscCall(PetscViewerASCIIPushSynchronized(viewer));
887 /*
888 The following line is a bug; it does another PetscViewerASCIIPushSynchronized() on viewer, but if it is removed the code won't work
889 because it relies on this behavior in other places. In particular this line causes the synchronized flush to occur when the viewer is destroyed
890 (since the count never gets to zero) in some examples this displays information that otherwise would be lost
891
892 This code also means another call to PetscViewerASCIIPopSynchronized() must be made after the PetscViewerRestoreSubViewer(), see, for example,
893 PCView_GASM().
894 */
895 PetscCall(PetscViewerASCIIPushSynchronized(viewer));
896 PetscCall(PetscViewerFlush(viewer));
897 PetscCall(PetscViewerCreate(subcomm, outviewer));
898 PetscCall(PetscViewerSetType(*outviewer, PETSCVIEWERASCII));
899 PetscCall(PetscViewerASCIIPushSynchronized(*outviewer));
900 ovascii = (PetscViewer_ASCII *)(*outviewer)->data;
901 ovascii->fd = vascii->fd;
902 ovascii->fileunit = vascii->fileunit;
903 ovascii->closefile = PETSC_FALSE;
904
905 vascii->sviewer = *outviewer;
906 (*outviewer)->format = viewer->format;
907 ((PetscViewer_ASCII *)((*outviewer)->data))->bviewer = viewer;
908 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII_SubViewer;
909 PetscFunctionReturn(PETSC_SUCCESS);
910 }
911
PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer,MPI_Comm comm,PetscViewer * outviewer)912 static PetscErrorCode PetscViewerRestoreSubViewer_ASCII(PetscViewer viewer, MPI_Comm comm, PetscViewer *outviewer)
913 {
914 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)viewer->data;
915
916 PetscFunctionBegin;
917 PetscCheck(ascii->sviewer, PETSC_COMM_SELF, PETSC_ERR_ORDER, "SubViewer never obtained from PetscViewer");
918 PetscCheck(ascii->sviewer == *outviewer, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "This PetscViewer did not generate this SubViewer");
919
920 PetscCall(PetscViewerASCIIPopSynchronized(*outviewer));
921 ascii->sviewer = NULL;
922 (*outviewer)->ops->destroy = PetscViewerDestroy_ASCII;
923 PetscCall(PetscViewerDestroy(outviewer));
924 PetscCall(PetscViewerFlush(viewer));
925 PetscCall(PetscViewerASCIIPopSynchronized(viewer));
926 PetscFunctionReturn(PETSC_SUCCESS);
927 }
928
PetscViewerView_ASCII(PetscViewer v,PetscViewer viewer)929 static PetscErrorCode PetscViewerView_ASCII(PetscViewer v, PetscViewer viewer)
930 {
931 PetscViewer_ASCII *ascii = (PetscViewer_ASCII *)v->data;
932
933 PetscFunctionBegin;
934 if (ascii->fileunit) PetscCall(PetscViewerASCIIPrintf(viewer, "Fortran FILE UNIT: %d\n", ascii->fileunit));
935 else if (ascii->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", ascii->filename));
936 PetscFunctionReturn(PETSC_SUCCESS);
937 }
938
PetscViewerFlush_ASCII(PetscViewer viewer)939 static PetscErrorCode PetscViewerFlush_ASCII(PetscViewer viewer)
940 {
941 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
942 MPI_Comm comm;
943 PetscMPIInt rank, size;
944 FILE *fd = vascii->fd;
945
946 PetscFunctionBegin;
947 PetscCheck(!vascii->sviewer, PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_WRONGSTATE, "Cannot call with outstanding call to PetscViewerRestoreSubViewer()");
948 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
949 PetscCallMPI(MPI_Comm_rank(comm, &rank));
950 PetscCallMPI(MPI_Comm_size(comm, &size));
951
952 if (!vascii->bviewer && rank == 0 && (vascii->mode != FILE_MODE_READ)) PetscCall(PetscFFlush(vascii->fd));
953
954 if (vascii->allowsynchronized) {
955 PetscMPIInt tag, i, j, n = 0, dummy = 0;
956 char *message;
957 MPI_Status status;
958
959 PetscCall(PetscCommDuplicate(comm, &comm, &tag));
960
961 /* First processor waits for messages from all other processors */
962 if (rank == 0) {
963 /* flush my own messages that I may have queued up */
964 PrintfQueue next = vascii->petsc_printfqueuebase, previous;
965 for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
966 if (!vascii->bviewer) {
967 if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", next->string));
968 else PetscCall(PetscFPrintfFortran(vascii->fileunit, next->string));
969 } else {
970 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", next->string));
971 }
972 previous = next;
973 next = next->next;
974 PetscCall(PetscFree(previous->string));
975 PetscCall(PetscFree(previous));
976 }
977 vascii->petsc_printfqueue = NULL;
978 vascii->petsc_printfqueuelength = 0;
979 for (i = 1; i < size; i++) {
980 /* to prevent a flood of messages to process zero, request each message separately */
981 PetscCallMPI(MPI_Send(&dummy, 1, MPI_INT, i, tag, comm));
982 PetscCallMPI(MPI_Recv(&n, 1, MPI_INT, i, tag, comm, &status));
983 for (j = 0; j < n; j++) {
984 size_t size;
985
986 PetscCallMPI(MPI_Recv(&size, 1, MPIU_SIZE_T, i, tag, comm, &status));
987 PetscCall(PetscMalloc1(size, &message));
988 PetscCallMPI(MPI_Recv(message, (PetscMPIInt)size, MPI_CHAR, i, tag, comm, &status));
989 if (!vascii->bviewer) {
990 if (!vascii->fileunit) PetscCall(PetscFPrintf(comm, fd, "%s", message));
991 else PetscCall(PetscFPrintfFortran(vascii->fileunit, message));
992 } else {
993 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", message));
994 }
995 PetscCall(PetscFree(message));
996 }
997 }
998 } else { /* other processors send queue to processor 0 */
999 PrintfQueue next = vascii->petsc_printfqueuebase, previous;
1000
1001 PetscCallMPI(MPI_Recv(&dummy, 1, MPI_INT, 0, tag, comm, &status));
1002 PetscCallMPI(MPI_Send(&vascii->petsc_printfqueuelength, 1, MPI_INT, 0, tag, comm));
1003 for (i = 0; i < vascii->petsc_printfqueuelength; i++) {
1004 PetscCallMPI(MPI_Send(&next->size, 1, MPIU_SIZE_T, 0, tag, comm));
1005 PetscCallMPI(MPI_Send(next->string, (PetscMPIInt)next->size, MPI_CHAR, 0, tag, comm));
1006 previous = next;
1007 next = next->next;
1008 PetscCall(PetscFree(previous->string));
1009 PetscCall(PetscFree(previous));
1010 }
1011 vascii->petsc_printfqueue = NULL;
1012 vascii->petsc_printfqueuelength = 0;
1013 }
1014 PetscCall(PetscCommDestroy(&comm));
1015 }
1016 PetscFunctionReturn(PETSC_SUCCESS);
1017 }
1018
1019 /*MC
1020 PETSCVIEWERASCII - A viewer that prints to `stdout`, `stderr`, or an ASCII file
1021
1022 Level: beginner
1023
1024 .seealso: [](sec_viewers), `PETSC_VIEWER_STDOUT_()`, `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDOUT_WORLD`, `PetscViewerCreate()`, `PetscViewerASCIIOpen()`,
1025 `PetscViewerMatlabOpen()`, `VecView()`, `DMView()`, `PetscViewerMatlabPutArray()`, `PETSCVIEWERBINARY`, `PETSCVIEWERMATLAB`,
1026 `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `PetscViewerFormat`, `PetscViewerType`, `PetscViewerSetType()`
1027 M*/
PetscViewerCreate_ASCII(PetscViewer viewer)1028 PETSC_EXTERN PetscErrorCode PetscViewerCreate_ASCII(PetscViewer viewer)
1029 {
1030 PetscViewer_ASCII *vascii;
1031
1032 PetscFunctionBegin;
1033 PetscCall(PetscNew(&vascii));
1034 viewer->data = (void *)vascii;
1035
1036 viewer->ops->destroy = PetscViewerDestroy_ASCII;
1037 viewer->ops->flush = PetscViewerFlush_ASCII;
1038 viewer->ops->getsubviewer = PetscViewerGetSubViewer_ASCII;
1039 viewer->ops->restoresubviewer = PetscViewerRestoreSubViewer_ASCII;
1040 viewer->ops->view = PetscViewerView_ASCII;
1041 viewer->ops->read = PetscViewerASCIIRead;
1042
1043 /* defaults to stdout unless set with PetscViewerFileSetName() */
1044 vascii->fd = PETSC_STDOUT;
1045 vascii->mode = FILE_MODE_WRITE;
1046 vascii->bviewer = NULL;
1047 vascii->subviewer = NULL;
1048 vascii->sviewer = NULL;
1049 vascii->tab = 0;
1050 vascii->tab_store = 0;
1051 vascii->filename = NULL;
1052 vascii->closefile = PETSC_TRUE;
1053
1054 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_ASCII));
1055 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_ASCII));
1056 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_ASCII));
1057 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_ASCII));
1058 PetscFunctionReturn(PETSC_SUCCESS);
1059 }
1060
1061 /*@C
1062 PetscViewerASCIISynchronizedPrintf - Prints synchronized output to the specified `PETSCVIEWERASCII` file from
1063 several processors. Output of the first processor is followed by that of the
1064 second, etc.
1065
1066 Not Collective, must call collective `PetscViewerFlush()` to get the results flushed
1067
1068 Input Parameters:
1069 + viewer - the `PETSCVIEWERASCII` `PetscViewer`
1070 - format - the usual printf() format string
1071
1072 Level: intermediate
1073
1074 Notes:
1075 You must have previously called `PetscViewerASCIIPushSynchronized()` to allow this routine to be called.
1076 Then you can do multiple independent calls to this routine.
1077
1078 The actual synchronized print is then done using `PetscViewerFlush()`.
1079 `PetscViewerASCIIPopSynchronized()` should be then called if we are already done with the synchronized output
1080 to conclude the "synchronized session".
1081
1082 So the typical calling sequence looks like
1083 .vb
1084 PetscViewerASCIIPushSynchronized(viewer);
1085 PetscViewerASCIISynchronizedPrintf(viewer, ...);
1086 PetscViewerASCIISynchronizedPrintf(viewer, ...);
1087 ...
1088 PetscViewerFlush(viewer);
1089 PetscViewerASCIISynchronizedPrintf(viewer, ...);
1090 PetscViewerASCIISynchronizedPrintf(viewer, ...);
1091 ...
1092 PetscViewerFlush(viewer);
1093 PetscViewerASCIIPopSynchronized(viewer);
1094 .ve
1095
1096 Fortran Note:
1097 The call sequence is `PetscViewerASCIISynchronizedPrintf`(`PetscViewer`, `character(*)`, `PetscErrorCode` ierr)
1098 That is, you can only pass a single character string from Fortran.
1099
1100 .seealso: [](sec_viewers), `PetscViewerASCIIPushSynchronized()`, `PetscViewerFlush()`, `PetscViewerASCIIPopSynchronized()`,
1101 `PetscSynchronizedPrintf()`, `PetscViewerASCIIPrintf()`, `PetscViewerASCIIOpen()`,
1102 `PetscViewerCreate()`, `PetscViewerDestroy()`, `PetscViewerSetType()`
1103 @*/
PetscViewerASCIISynchronizedPrintf(PetscViewer viewer,const char format[],...)1104 PetscErrorCode PetscViewerASCIISynchronizedPrintf(PetscViewer viewer, const char format[], ...)
1105 {
1106 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1107 PetscMPIInt rank;
1108 PetscInt tab = 0;
1109 MPI_Comm comm;
1110 PetscBool isascii;
1111
1112 PetscFunctionBegin;
1113 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1114 PetscAssertPointer(format, 2);
1115 PetscCall(PetscObjectTypeCompare((PetscObject)viewer, PETSCVIEWERASCII, &isascii));
1116 PetscCheck(isascii, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Not ASCII PetscViewer");
1117 PetscCheck(vascii->allowsynchronized, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONGSTATE, "First call PetscViewerASCIIPushSynchronized() to allow this call");
1118
1119 PetscCall(PetscObjectGetComm((PetscObject)viewer, &comm));
1120 PetscCallMPI(MPI_Comm_rank(comm, &rank));
1121
1122 if (vascii->bviewer) {
1123 char *string;
1124 va_list Argp;
1125 size_t fullLength;
1126
1127 PetscCall(PetscCalloc1(QUEUESTRINGSIZE, &string));
1128 for (; tab < vascii->tab; tab++) string[2 * tab] = string[2 * tab + 1] = ' ';
1129 va_start(Argp, format);
1130 PetscCall(PetscVSNPrintf(string + 2 * tab, QUEUESTRINGSIZE - 2 * tab, format, &fullLength, Argp));
1131 va_end(Argp);
1132 PetscCall(PetscViewerASCIISynchronizedPrintf(vascii->bviewer, "%s", string));
1133 PetscCall(PetscFree(string));
1134 } else if (rank == 0) { /* First processor prints immediately to fp */
1135 va_list Argp;
1136 FILE *fp = vascii->fd;
1137
1138 tab = vascii->tab;
1139 while (tab--) {
1140 if (!vascii->fileunit) PetscCall(PetscFPrintf(PETSC_COMM_SELF, fp, " "));
1141 else PetscCall(PetscFPrintfFortran(vascii->fileunit, " "));
1142 }
1143
1144 va_start(Argp, format);
1145 if (!vascii->fileunit) PetscCall((*PetscVFPrintf)(fp, format, Argp));
1146 else PetscCall(PetscVFPrintfFortran(vascii->fileunit, format, Argp));
1147 va_end(Argp);
1148 PetscCall(PetscFFlush(fp));
1149 if (petsc_history) {
1150 va_start(Argp, format);
1151 PetscCall((*PetscVFPrintf)(petsc_history, format, Argp));
1152 va_end(Argp);
1153 PetscCall(PetscFFlush(petsc_history));
1154 }
1155 } else { /* other processors add to queue */
1156 char *string;
1157 va_list Argp;
1158 size_t fullLength;
1159 PrintfQueue next;
1160
1161 PetscCall(PetscNew(&next));
1162 if (vascii->petsc_printfqueue) {
1163 vascii->petsc_printfqueue->next = next;
1164 vascii->petsc_printfqueue = next;
1165 } else {
1166 vascii->petsc_printfqueuebase = vascii->petsc_printfqueue = next;
1167 }
1168 vascii->petsc_printfqueuelength++;
1169 next->size = QUEUESTRINGSIZE;
1170 PetscCall(PetscCalloc1(next->size, &next->string));
1171 string = next->string;
1172
1173 tab = vascii->tab;
1174 tab *= 2;
1175 while (tab--) *string++ = ' ';
1176 va_start(Argp, format);
1177 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, &fullLength, Argp));
1178 va_end(Argp);
1179 if (fullLength > next->size - 2 * vascii->tab) {
1180 PetscCall(PetscFree(next->string));
1181 next->size = fullLength + 2 * vascii->tab;
1182 PetscCall(PetscCalloc1(next->size, &next->string));
1183 string = next->string;
1184 tab = 2 * vascii->tab;
1185 while (tab--) *string++ = ' ';
1186 va_start(Argp, format);
1187 PetscCall(PetscVSNPrintf(string, next->size - 2 * vascii->tab, format, NULL, Argp));
1188 va_end(Argp);
1189 }
1190 }
1191 PetscFunctionReturn(PETSC_SUCCESS);
1192 }
1193
1194 /*@C
1195 PetscViewerASCIIRead - Reads from a `PETSCVIEWERASCII` file
1196
1197 Only MPI rank 0 in the `PetscViewer` may call this
1198
1199 Input Parameters:
1200 + viewer - the `PETSCVIEWERASCII` viewer
1201 . data - location to write the data, treated as an array of type indicated by `datatype`
1202 . num - number of items of data to read
1203 - dtype - type of data to read
1204
1205 Output Parameter:
1206 . count - number of items of data actually read, or `NULL`
1207
1208 Level: beginner
1209
1210 .seealso: [](sec_viewers), `PetscViewerASCIIOpen()`, `PetscViewerPushFormat()`, `PetscViewerDestroy()`, `PetscViewerCreate()`, `PetscViewerFileSetMode()`, `PetscViewerFileSetName()`
1211 `VecView()`, `MatView()`, `VecLoad()`, `MatLoad()`, `PetscViewerBinaryGetDescriptor()`,
1212 `PetscViewerBinaryGetInfoPointer()`, `PetscFileMode`, `PetscViewer`, `PetscViewerBinaryRead()`
1213 @*/
PetscViewerASCIIRead(PetscViewer viewer,void * data,PetscInt num,PetscInt * count,PetscDataType dtype)1214 PetscErrorCode PetscViewerASCIIRead(PetscViewer viewer, void *data, PetscInt num, PetscInt *count, PetscDataType dtype)
1215 {
1216 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data;
1217 FILE *fd = vascii->fd;
1218 PetscInt i;
1219 int ret = 0;
1220 PetscMPIInt rank;
1221
1222 PetscFunctionBegin;
1223 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1);
1224 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank));
1225 PetscCheck(rank == 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Can only be called from process 0 in the PetscViewer");
1226 for (i = 0; i < num; i++) {
1227 if (dtype == PETSC_CHAR) ret = fscanf(fd, "%c", &(((char *)data)[i]));
1228 else if (dtype == PETSC_STRING) ret = fscanf(fd, "%s", &(((char *)data)[i]));
1229 else if (dtype == PETSC_INT) ret = fscanf(fd, "%" PetscInt_FMT, &(((PetscInt *)data)[i]));
1230 else if (dtype == PETSC_ENUM) ret = fscanf(fd, "%d", &(((int *)data)[i]));
1231 else if (dtype == PETSC_INT64) ret = fscanf(fd, "%" PetscInt64_FMT, &(((PetscInt64 *)data)[i]));
1232 else if (dtype == PETSC_LONG) ret = fscanf(fd, "%ld", &(((long *)data)[i]));
1233 else if (dtype == PETSC_COUNT) ret = fscanf(fd, "%" PetscCount_FMT, &(((PetscCount *)data)[i]));
1234 else if (dtype == PETSC_FLOAT) ret = fscanf(fd, "%f", &(((float *)data)[i]));
1235 else if (dtype == PETSC_DOUBLE) ret = fscanf(fd, "%lg", &(((double *)data)[i]));
1236 #if defined(PETSC_USE_REAL___FLOAT128)
1237 else if (dtype == PETSC___FLOAT128) {
1238 double tmp;
1239 ret = fscanf(fd, "%lg", &tmp);
1240 ((__float128 *)data)[i] = tmp;
1241 }
1242 #endif
1243 else
1244 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Data type %d not supported", (int)dtype);
1245 PetscCheck(ret, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Conversion error for data type %d", (int)dtype);
1246 if (ret < 0) break; /* Proxy for EOF, need to check for it in configure */
1247 }
1248 if (count) *count = i;
1249 else PetscCheck(ret >= 0, PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG, "Insufficient data, read only %" PetscInt_FMT " < %" PetscInt_FMT " items", i, num);
1250 PetscFunctionReturn(PETSC_SUCCESS);
1251 }
1252