1 2 #include <petsc/private/viewerimpl.h> 3 #include <petscviewersaws.h> 4 #include <petscsys.h> 5 6 /* 7 The variable Petsc_Viewer_SAWs_keyval is used to indicate an MPI attribute that 8 is attached to a communicator, in this case the attribute is a PetscViewer. 9 */ 10 static PetscMPIInt Petsc_Viewer_SAWs_keyval = MPI_KEYVAL_INVALID; 11 12 /*@C 13 PETSC_VIEWER_SAWS_ - Creates an SAWs `PetscViewer` shared by all processors in a communicator. 14 15 Collective 16 17 Input Parameters: 18 . comm - the MPI communicator to share the `PetscViewer` 19 20 Level: developer 21 22 Note: 23 Unlike almost all other PETSc routines, `PETSC_VIEWER_SAWS_()` does not return 24 an error code. The resulting `PetscViewer` is usually used in the form 25 $ XXXView(XXX object,PETSC_VIEWER_SAWS_(comm)); 26 27 .seealso: `PetscViewer`, `PETSC_VIEWER_SAWS_WORLD`, `PETSC_VIEWER_SAWS_SELF` 28 @*/ 29 PetscViewer PETSC_VIEWER_SAWS_(MPI_Comm comm) { 30 PetscErrorCode ierr; 31 PetscMPIInt flag; 32 PetscViewer viewer; 33 MPI_Comm ncomm; 34 35 PetscFunctionBegin; 36 ierr = PetscCommDuplicate(comm, &ncomm, NULL); 37 if (ierr) { 38 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 39 PetscFunctionReturn(0); 40 } 41 if (Petsc_Viewer_SAWs_keyval == MPI_KEYVAL_INVALID) { 42 ierr = MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_SAWs_keyval, 0); 43 if (ierr) { 44 PetscError(ncomm, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, 1, PETSC_ERROR_INITIAL, " "); 45 PetscFunctionReturn(NULL); 46 } 47 } 48 ierr = MPI_Comm_get_attr(ncomm, Petsc_Viewer_SAWs_keyval, (void **)&viewer, &flag); 49 if (ierr) { 50 PetscError(ncomm, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, 1, PETSC_ERROR_INITIAL, " "); 51 PetscFunctionReturn(NULL); 52 } 53 if (!flag) { /* PetscViewer not yet created */ 54 ierr = PetscViewerSAWsOpen(comm, &viewer); 55 if (ierr) { 56 PetscError(ncomm, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, 1, PETSC_ERROR_REPEAT, " "); 57 PetscFunctionReturn(NULL); 58 } 59 ierr = PetscObjectRegisterDestroy((PetscObject)viewer); 60 if (ierr) { 61 PetscError(ncomm, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, 1, PETSC_ERROR_REPEAT, " "); 62 PetscFunctionReturn(NULL); 63 } 64 ierr = MPI_Comm_set_attr(ncomm, Petsc_Viewer_SAWs_keyval, (void *)viewer); 65 if (ierr) { 66 PetscError(ncomm, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, 1, PETSC_ERROR_INITIAL, " "); 67 PetscFunctionReturn(NULL); 68 } 69 } 70 ierr = PetscCommDestroy(&ncomm); 71 if (ierr) { 72 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_SAWS_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_REPEAT, " "); 73 PetscFunctionReturn(NULL); 74 } 75 PetscFunctionReturn(viewer); 76 } 77 78 /* 79 If there is a PetscViewer associated with this communicator, it is destroyed. 80 */ 81 PetscErrorCode PetscViewer_SAWS_Destroy(MPI_Comm comm) { 82 PetscMPIInt flag; 83 PetscViewer viewer; 84 85 PetscFunctionBegin; 86 if (Petsc_Viewer_SAWs_keyval == MPI_KEYVAL_INVALID) PetscFunctionReturn(0); 87 88 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_SAWs_keyval, (void **)&viewer, &flag)); 89 if (flag) { 90 PetscCall(PetscViewerDestroy(&viewer)); 91 PetscCallMPI(MPI_Comm_delete_attr(comm, Petsc_Viewer_SAWs_keyval)); 92 } 93 PetscFunctionReturn(0); 94 } 95 96 static PetscErrorCode PetscViewerDestroy_SAWs(PetscViewer viewer) { 97 PetscFunctionBegin; 98 /* 99 Make sure that we mark that the stack is no longer published 100 */ 101 if (PetscObjectComm((PetscObject)viewer) == PETSC_COMM_WORLD) PetscCall(PetscStackSAWsViewOff()); 102 PetscFunctionReturn(0); 103 } 104 105 PETSC_EXTERN PetscErrorCode PetscViewerCreate_SAWs(PetscViewer v) { 106 PetscFunctionBegin; 107 v->ops->destroy = PetscViewerDestroy_SAWs; 108 PetscFunctionReturn(0); 109 } 110