Actual source code: dupl.c
petsc-3.13.6 2020-09-29
2: #include <petsc/private/viewerimpl.h>
4: /*@C
5: PetscViewerGetSubViewer - Creates a new PetscViewer (same type as the old)
6: that lives on a subcommunicator
8: Collective on PetscViewer
10: Input Parameter:
11: . viewer - the PetscViewer to be reproduced
13: Output Parameter:
14: . outviewer - new PetscViewer
16: Level: advanced
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().
24: Call PetscViewerRestoreSubViewer() to destroy this PetscViewer, NOT PetscViewerDestroy()
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.
30: Between the calls to PetscViewerGetSubViewer() and PetscViewerRestoreSubViewer() the original
31: viewer should not be used
33: PETSCVIEWERDRAW and PETSCVIEWERBINARY only support returning a singleton viewer on rank 0,
34: all other ranks will return a NULL viewer
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.
41: It would be nice if the call to PetscViewerFlush() was not required and was handled by
42: PetscViewerRestoreSubViewer()
44: .seealso: PetscViewerSocketOpen(), PetscViewerASCIIOpen(), PetscViewerDrawOpen(), PetscViewerRestoreSubViewer()
45: @*/
46: PetscErrorCode PetscViewerGetSubViewer(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
47: {
49: PetscMPIInt size;
54: MPI_Comm_size(PetscObjectComm((PetscObject)viewer),&size);
55: if (size == 1) {
56: PetscObjectReference((PetscObject)viewer);
57: *outviewer = viewer;
58: } else if (viewer->ops->getsubviewer) {
59: (*viewer->ops->getsubviewer)(viewer,comm,outviewer);
60: } else SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_SUP,"Cannot get SubViewer PetscViewer for type %s",((PetscObject)viewer)->type_name);
61: return(0);
62: }
64: /*@C
65: PetscViewerRestoreSubViewer - Restores a new PetscViewer obtained with PetscViewerGetSubViewer().
67: Collective on PetscViewer
69: Input Parameters:
70: + viewer - the PetscViewer that was reproduced
71: - outviewer - new PetscViewer
73: Level: advanced
75: Notes:
76: Call PetscViewerGetSubViewer() to get this PetscViewer, NOT PetscViewerCreate()
78: .seealso: PetscViewerSocketOpen(), PetscViewerASCIIOpen(), PetscViewerDrawOpen(), PetscViewerGetSubViewer()
79: @*/
80: PetscErrorCode PetscViewerRestoreSubViewer(PetscViewer viewer,MPI_Comm comm,PetscViewer *outviewer)
81: {
83: PetscMPIInt size;
88: MPI_Comm_size(PetscObjectComm((PetscObject)viewer),&size);
89: if (size == 1) {
90: PetscObjectDereference((PetscObject)viewer);
91: if (outviewer) *outviewer = NULL;
92: } else if (viewer->ops->restoresubviewer) {
93: (*viewer->ops->restoresubviewer)(viewer,comm,outviewer);
94: }
95: return(0);
96: }