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