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