1 2 #include <../src/sys/classes/viewer/impls/ascii/asciiimpl.h> /*I "petscviewer.h" I*/ 3 4 /* ---------------------------------------------------------------------*/ 5 6 /* 7 The variable Petsc_Viewer_Stdout_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 PetscMPIInt Petsc_Viewer_Stdout_keyval = MPI_KEYVAL_INVALID; 11 12 /*@ 13 PetscViewerASCIIGetStdout - Creates a ASCII PetscViewer shared by all processors 14 in a communicator. Error returning version of PETSC_VIEWER_STDOUT_() 15 16 Collective 17 18 Input Parameter: 19 . comm - the MPI communicator to share the PetscViewer 20 21 Level: beginner 22 23 Notes: 24 This should be used in all PETSc source code instead of PETSC_VIEWER_STDOUT_() 25 26 .seealso: `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`, 27 `PETSC_VIEWER_STDOUT_SELF` 28 29 @*/ 30 PetscErrorCode PetscViewerASCIIGetStdout(MPI_Comm comm, PetscViewer *viewer) { 31 PetscBool flg; 32 MPI_Comm ncomm; 33 34 PetscFunctionBegin; 35 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStdout)); 36 PetscCall(PetscCommDuplicate(comm, &ncomm, NULL)); 37 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)); } 38 PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void **)viewer, (PetscMPIInt *)&flg)); 39 if (!flg) { /* PetscViewer not yet created */ 40 PetscCall(PetscViewerASCIIOpen(ncomm, "stdout", viewer)); 41 PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer)); 42 PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stdout_keyval, (void *)*viewer)); 43 } 44 PetscCall(PetscCommDestroy(&ncomm)); 45 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStdout)); 46 PetscFunctionReturn(0); 47 } 48 49 /*@C 50 PETSC_VIEWER_STDOUT_ - Creates a ASCII PetscViewer shared by all processors 51 in a communicator. 52 53 Collective 54 55 Input Parameter: 56 . comm - the MPI communicator to share the PetscViewer 57 58 Level: beginner 59 60 Notes: 61 Unlike almost all other PETSc routines, this does not return 62 an error code. Usually used in the form 63 $ XXXView(XXX object,PETSC_VIEWER_STDOUT_(comm)); 64 65 .seealso: `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDOUT_WORLD`, 66 `PETSC_VIEWER_STDOUT_SELF` 67 68 @*/ 69 PetscViewer PETSC_VIEWER_STDOUT_(MPI_Comm comm) { 70 PetscErrorCode ierr; 71 PetscViewer viewer; 72 73 PetscFunctionBegin; 74 ierr = PetscViewerASCIIGetStdout(comm, &viewer); 75 if (ierr) { 76 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDOUT_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 77 PetscFunctionReturn(NULL); 78 } 79 PetscFunctionReturn(viewer); 80 } 81 82 /* ---------------------------------------------------------------------*/ 83 84 /* 85 The variable Petsc_Viewer_Stderr_keyval is used to indicate an MPI attribute that 86 is attached to a communicator, in this case the attribute is a PetscViewer. 87 */ 88 PetscMPIInt Petsc_Viewer_Stderr_keyval = MPI_KEYVAL_INVALID; 89 90 /*@ 91 PetscViewerASCIIGetStderr - Creates a ASCII PetscViewer shared by all processors 92 in a communicator. Error returning version of PETSC_VIEWER_STDERR_() 93 94 Collective 95 96 Input Parameter: 97 . comm - the MPI communicator to share the PetscViewer 98 99 Level: beginner 100 101 Notes: 102 This should be used in all PETSc source code instead of PETSC_VIEWER_STDERR_() 103 104 .seealso: `PETSC_VIEWER_DRAW_()`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDERR_`, `PETSC_VIEWER_STDERR_WORLD`, 105 `PETSC_VIEWER_STDERR_SELF` 106 107 @*/ 108 PetscErrorCode PetscViewerASCIIGetStderr(MPI_Comm comm, PetscViewer *viewer) { 109 PetscBool flg; 110 MPI_Comm ncomm; 111 112 PetscFunctionBegin; 113 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockStderr)); 114 PetscCall(PetscCommDuplicate(comm, &ncomm, NULL)); 115 if (Petsc_Viewer_Stderr_keyval == MPI_KEYVAL_INVALID) { PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, MPI_COMM_NULL_DELETE_FN, &Petsc_Viewer_Stderr_keyval, NULL)); } 116 PetscCallMPI(MPI_Comm_get_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void **)viewer, (PetscMPIInt *)&flg)); 117 if (!flg) { /* PetscViewer not yet created */ 118 PetscCall(PetscViewerASCIIOpen(ncomm, "stderr", viewer)); 119 PetscCall(PetscObjectRegisterDestroy((PetscObject)*viewer)); 120 PetscCallMPI(MPI_Comm_set_attr(ncomm, Petsc_Viewer_Stderr_keyval, (void *)*viewer)); 121 } 122 PetscCall(PetscCommDestroy(&ncomm)); 123 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockStderr)); 124 PetscFunctionReturn(0); 125 } 126 127 /*@C 128 PETSC_VIEWER_STDERR_ - Creates a ASCII PetscViewer shared by all processors 129 in a communicator. 130 131 Collective 132 133 Input Parameter: 134 . comm - the MPI communicator to share the PetscViewer 135 136 Level: beginner 137 138 Note: 139 Unlike almost all other PETSc routines, this does not return 140 an error code. Usually used in the form 141 $ XXXView(XXX object,PETSC_VIEWER_STDERR_(comm)); 142 143 .seealso: `PETSC_VIEWER_DRAW_`, `PetscViewerASCIIOpen()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDOUT_WORLD`, 144 `PETSC_VIEWER_STDOUT_SELF`, `PETSC_VIEWER_STDERR_WORLD`, `PETSC_VIEWER_STDERR_SELF` 145 @*/ 146 PetscViewer PETSC_VIEWER_STDERR_(MPI_Comm comm) { 147 PetscErrorCode ierr; 148 PetscViewer viewer; 149 150 PetscFunctionBegin; 151 ierr = PetscViewerASCIIGetStderr(comm, &viewer); 152 if (ierr) { 153 PetscError(PETSC_COMM_SELF, __LINE__, "PETSC_VIEWER_STDERR_", __FILE__, PETSC_ERR_PLIB, PETSC_ERROR_INITIAL, " "); 154 PetscFunctionReturn(NULL); 155 } 156 PetscFunctionReturn(viewer); 157 } 158 159 PetscMPIInt Petsc_Viewer_keyval = MPI_KEYVAL_INVALID; 160 /* 161 Called with MPI_Comm_free() is called on a communicator that has a viewer as an attribute. The viewer is not actually destroyed because that is managed by 162 PetscObjectDestroyRegisterAll(). PetscViewerASCIIGetStdout() registers the viewer with PetscObjectDestroyRegister() to be destroyed when PetscFinalize() is called. 163 164 This is called by MPI, not by users. 165 166 */ 167 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state) { 168 PetscFunctionBegin; 169 PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %ld\n", (long)comm)); 170 PetscFunctionReturn(MPI_SUCCESS); 171 } 172 173 /*@C 174 PetscViewerASCIIOpen - Opens an ASCII file for writing as a PetscViewer. 175 176 Collective 177 178 Input Parameters: 179 + comm - the communicator 180 - name - the file name 181 182 Output Parameter: 183 . lab - the PetscViewer to use with the specified file 184 185 Level: beginner 186 187 Notes: 188 To open a ASCII file as a viewer for reading one must use the sequence 189 $ PetscViewerCreate(comm,&lab); 190 $ PetscViewerSetType(lab,PETSCVIEWERASCII); 191 $ PetscViewerFileSetMode(lab,FILE_MODE_READ); 192 $ PetscViewerFileSetName(lab,name); 193 194 This PetscViewer can be destroyed with PetscViewerDestroy(). 195 196 The MPI communicator used here must match that used by the object one is viewing. For example if the 197 Mat was created with a PETSC_COMM_WORLD, then the Viewer must be created with PETSC_COMM_WORLD 198 199 As shown below, PetscViewerASCIIOpen() is useful in conjunction with 200 MatView() and VecView() 201 .vb 202 PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer); 203 MatView(matrix,viewer); 204 .ve 205 206 .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()` 207 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 208 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, 209 @*/ 210 PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab) { 211 PetscViewerLink *vlink, *nv; 212 PetscBool flg, eq; 213 size_t len; 214 215 PetscFunctionBegin; 216 PetscCall(PetscStrlen(name, &len)); 217 if (!len) { 218 PetscCall(PetscViewerASCIIGetStdout(comm, lab)); 219 PetscCall(PetscObjectReference((PetscObject)*lab)); 220 PetscFunctionReturn(0); 221 } 222 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen)); 223 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) { PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); } 224 /* 225 It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator 226 we cannot do that, since PetscFileSetName() takes a communicator that already exists. 227 228 Plus if the original communicator that created the file has since been close this will not detect the old 229 communictor and hence will overwrite the old data. It may be better to simply remove all this code 230 */ 231 /* make sure communicator is a PETSc communicator */ 232 PetscCall(PetscCommDuplicate(comm, &comm, NULL)); 233 /* has file already been opened into a viewer */ 234 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 235 if (flg) { 236 while (vlink) { 237 PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)(vlink->viewer->data))->filename, &eq)); 238 if (eq) { 239 PetscCall(PetscObjectReference((PetscObject)vlink->viewer)); 240 *lab = vlink->viewer; 241 PetscCall(PetscCommDestroy(&comm)); 242 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 243 PetscFunctionReturn(0); 244 } 245 vlink = vlink->next; 246 } 247 } 248 PetscCall(PetscViewerCreate(comm, lab)); 249 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 250 if (name) PetscCall(PetscViewerFileSetName(*lab, name)); 251 /* save viewer into communicator if needed later */ 252 PetscCall(PetscNew(&nv)); 253 nv->viewer = *lab; 254 if (!flg) { 255 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 256 } else { 257 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 258 if (vlink) { 259 while (vlink->next) vlink = vlink->next; 260 vlink->next = nv; 261 } else { 262 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 263 } 264 } 265 PetscCall(PetscCommDestroy(&comm)); 266 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 267 PetscFunctionReturn(0); 268 } 269 270 /*@C 271 PetscViewerASCIIOpenWithFILE - Given an open file creates an ASCII viewer that prints to it. 272 273 Collective 274 275 Input Parameters: 276 + comm - the communicator 277 - fd - the FILE pointer 278 279 Output Parameter: 280 . lab - the PetscViewer to use with the specified file 281 282 Level: beginner 283 284 Notes: 285 This PetscViewer can be destroyed with PetscViewerDestroy(), but the fd will NOT be closed. 286 287 If a multiprocessor communicator is used (such as PETSC_COMM_WORLD), 288 then only the first processor in the group uses the file. All other 289 processors send their data to the first processor to print. 290 291 .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, 292 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 293 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()` 294 @*/ 295 PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab) { 296 PetscFunctionBegin; 297 PetscCall(PetscViewerCreate(comm, lab)); 298 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 299 PetscCall(PetscViewerASCIISetFILE(*lab, fd)); 300 PetscFunctionReturn(0); 301 } 302 303 PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd) { 304 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 305 306 PetscFunctionBegin; 307 vascii->fd = fd; 308 vascii->closefile = PETSC_FALSE; 309 PetscFunctionReturn(0); 310 } 311