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