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