xref: /petsc/src/sys/classes/viewer/interface/dupl.c (revision 4e278199b78715991f5c71ebbd945c1489263e6c)
1 
2 #include <petsc/private/viewerimpl.h>  /*I "petscviewer.h" I*/
3 
4 /*@C
5    PetscViewerGetSubViewer - Creates a new PetscViewer (same type as the old)
6     that lives on a subcommunicator
7 
8     Collective on PetscViewer
9 
10    Input Parameter:
11 .  viewer - the PetscViewer to be reproduced
12 
13    Output Parameter:
14 .  outviewer - new PetscViewer
15 
16    Level: advanced
17 
18    Notes:
19     The output of the subviewers is synchronized against the original viewer. For example, if a
20     viewer on two MPI ranks is decomposed into two subviewers, the output from the first viewer is
21     all printed before the output from the second viewer. You must call PetscViewerFlush() after
22     the call to PetscViewerRestoreSubViewer().
23 
24     Call PetscViewerRestoreSubViewer() to destroy this PetscViewer, NOT PetscViewerDestroy()
25 
26      This is most commonly used to view a sequential object that is part of a
27     parallel object. For example block Jacobi PC view could use this to obtain a
28     PetscViewer that is used with the sequential KSP on one block of the preconditioner.
29 
30     Between the calls to PetscViewerGetSubViewer() and PetscViewerRestoreSubViewer() the original
31     viewer should not be used
32 
33     PETSCVIEWERDRAW and PETSCVIEWERBINARY only support returning a singleton viewer on rank 0,
34     all other ranks will return a NULL viewer
35 
36   Developer Notes:
37     There is currently incomplete error checking that the user does not use the original viewer between the
38     the calls to PetscViewerGetSubViewer() and PetscViewerRestoreSubViewer(). If the user does there
39     could be errors in the viewing that go undetected or crash the code.
40 
41     It would be nice if the call to PetscViewerFlush() was not required and was handled by
42     PetscViewerRestoreSubViewer()
43 
44 .seealso: PetscViewerSocketOpen(), PetscViewerASCIIOpen(), PetscViewerDrawOpen(), PetscViewerRestoreSubViewer()
45 @*/
46 PetscErrorCode  PetscViewerGetSubViewer(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
47 {
48   PetscErrorCode ierr;
49 
50   PetscFunctionBegin;
51   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
52   PetscValidPointer(outviewer,3);
53   if (viewer->ops->getsubviewer) {
54     ierr = (*viewer->ops->getsubviewer)(viewer,comm,outviewer);CHKERRQ(ierr);
55   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get SubViewer PetscViewer for type %s",((PetscObject)viewer)->type_name);
56   PetscFunctionReturn(0);
57 }
58 
59 /*@C
60    PetscViewerRestoreSubViewer - Restores a new PetscViewer obtained with PetscViewerGetSubViewer().
61 
62     Collective on PetscViewer
63 
64    Input Parameters:
65 +  viewer - the PetscViewer that was reproduced
66 -  outviewer - new PetscViewer
67 
68    Level: advanced
69 
70    Notes:
71     Call PetscViewerGetSubViewer() to get this PetscViewer, NOT PetscViewerCreate()
72 
73 .seealso: PetscViewerSocketOpen(), PetscViewerASCIIOpen(), PetscViewerDrawOpen(), PetscViewerGetSubViewer()
74 @*/
75 PetscErrorCode  PetscViewerRestoreSubViewer(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
76 {
77   PetscErrorCode ierr;
78 
79   PetscFunctionBegin;
80   PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1);
81 
82   if (viewer->ops->restoresubviewer) {
83     ierr = (*viewer->ops->restoresubviewer)(viewer,comm,outviewer);CHKERRQ(ierr);
84   } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot restore SubViewer PetscViewer for type %s",((PetscObject)viewer)->type_name);
85   PetscFunctionReturn(0);
86 }
87