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