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