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 . lab - 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,&lab); 167 PetscViewerSetType(lab,PETSCVIEWERASCII); 168 PetscViewerFileSetMode(lab,FILE_MODE_READ); 169 PetscViewerFileSetName(lab,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 *lab) 189 { 190 PetscViewerLink *vlink, *nv; 191 PetscBool flg, eq; 192 size_t len; 193 194 PetscFunctionBegin; 195 PetscCall(PetscStrlen(name, &len)); 196 if (!len) { 197 PetscCall(PetscViewerASCIIGetStdout(comm, lab)); 198 PetscCall(PetscObjectReference((PetscObject)*lab)); 199 PetscFunctionReturn(PETSC_SUCCESS); 200 } 201 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen)); 202 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); 203 /* 204 It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator 205 we cannot do that, since PetscFileSetName() takes a communicator that already exists. 206 207 Plus if the original communicator that created the file has since been close this will not detect the old 208 communictor and hence will overwrite the old data. It may be better to simply remove all this code 209 */ 210 /* make sure communicator is a PETSc communicator */ 211 PetscCall(PetscCommDuplicate(comm, &comm, NULL)); 212 /* has file already been opened into a viewer */ 213 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 214 if (flg) { 215 while (vlink) { 216 PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)vlink->viewer->data)->filename, &eq)); 217 if (eq) { 218 PetscCall(PetscObjectReference((PetscObject)vlink->viewer)); 219 *lab = vlink->viewer; 220 PetscCall(PetscCommDestroy(&comm)); 221 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 222 PetscFunctionReturn(PETSC_SUCCESS); 223 } 224 vlink = vlink->next; 225 } 226 } 227 PetscCall(PetscViewerCreate(comm, lab)); 228 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 229 if (name) PetscCall(PetscViewerFileSetName(*lab, name)); 230 /* save viewer into communicator if needed later */ 231 PetscCall(PetscNew(&nv)); 232 nv->viewer = *lab; 233 if (!flg) { 234 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 235 } else { 236 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 237 if (vlink) { 238 while (vlink->next) vlink = vlink->next; 239 vlink->next = nv; 240 } else { 241 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 242 } 243 } 244 PetscCall(PetscCommDestroy(&comm)); 245 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 246 PetscFunctionReturn(PETSC_SUCCESS); 247 } 248 249 /*@C 250 PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it. 251 252 Collective 253 254 Input Parameters: 255 + comm - the communicator 256 - fd - the `FILE` pointer 257 258 Output Parameter: 259 . lab - the `PetscViewer` to use with the specified file 260 261 Level: beginner 262 263 Notes: 264 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed. 265 266 If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`), 267 then only the first processor in the group uses the file. All other 268 processors send their data to the first processor to print. 269 270 Fortran Notes: 271 Use `PetscViewerASCIIOpenWithFileUnit()` 272 273 .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`, 274 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 275 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII` 276 @*/ 277 PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab) 278 { 279 PetscFunctionBegin; 280 PetscCall(PetscViewerCreate(comm, lab)); 281 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 282 PetscCall(PetscViewerASCIISetFILE(*lab, fd)); 283 PetscFunctionReturn(PETSC_SUCCESS); 284 } 285 286 /*@C 287 PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output 288 289 Not Collective 290 291 Input Parameters: 292 + viewer - the `PetscViewer` to use with the specified file 293 - fd - the `FILE` pointer 294 295 Level: beginner 296 297 Notes: 298 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed. 299 300 If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`), 301 then only the first processor in the group uses the file. All other 302 processors send their data to the first processor to print. 303 304 Fortran Notes: 305 Use `PetscViewerASCIISetFileUnit()` 306 307 .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`, 308 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 309 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII` 310 @*/ 311 PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd) 312 { 313 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 314 315 PetscFunctionBegin; 316 vascii->fd = fd; 317 vascii->closefile = PETSC_FALSE; 318 PetscFunctionReturn(PETSC_SUCCESS); 319 } 320