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 PETSC_EXTERN PetscMPIInt MPIAPI Petsc_DelViewer(MPI_Comm comm, PetscMPIInt keyval, void *attr_val, void *extra_state) 185 { 186 PetscFunctionBegin; 187 PetscCallMPI(PetscInfo(NULL, "Removing viewer data attribute in an MPI_Comm %ld\n", (long)comm)); 188 PetscFunctionReturn(MPI_SUCCESS); 189 } 190 191 /*@C 192 PetscViewerASCIIOpen - Opens an ASCII file for writing as a `PETSCVIEWERASCII` `PetscViewer`. 193 194 Collective 195 196 Input Parameters: 197 + comm - the communicator 198 - name - the file name 199 200 Output Parameter: 201 . lab - the `PetscViewer` to use with the specified file 202 203 Level: beginner 204 205 Notes: 206 To open a ASCII file as a viewer for reading one must use the sequence 207 .vb 208 PetscViewerCreate(comm,&lab); 209 PetscViewerSetType(lab,PETSCVIEWERASCII); 210 PetscViewerFileSetMode(lab,FILE_MODE_READ); 211 PetscViewerFileSetName(lab,name); 212 .ve 213 214 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`. 215 216 The MPI communicator used here must match that used by the object one is viewing. For example if the 217 Mat was created with a `PETSC_COMM_WORLD`, then the Viewer must be created with `PETSC_COMM_WORLD` 218 219 As shown below, `PetscViewerASCIIOpen()` is useful in conjunction with 220 `MatView()` and `VecView()` 221 .vb 222 PetscViewerASCIIOpen(PETSC_COMM_WORLD,"mat.output",&viewer); 223 MatView(matrix,viewer); 224 .ve 225 226 .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIRead()`, `PETSCVIEWERASCII` 227 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 228 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, 229 @*/ 230 PetscErrorCode PetscViewerASCIIOpen(MPI_Comm comm, const char name[], PetscViewer *lab) 231 { 232 PetscViewerLink *vlink, *nv; 233 PetscBool flg, eq; 234 size_t len; 235 236 PetscFunctionBegin; 237 PetscCall(PetscStrlen(name, &len)); 238 if (!len) { 239 PetscCall(PetscViewerASCIIGetStdout(comm, lab)); 240 PetscCall(PetscObjectReference((PetscObject)*lab)); 241 PetscFunctionReturn(PETSC_SUCCESS); 242 } 243 PetscCall(PetscSpinlockLock(&PetscViewerASCIISpinLockOpen)); 244 if (Petsc_Viewer_keyval == MPI_KEYVAL_INVALID) PetscCallMPI(MPI_Comm_create_keyval(MPI_COMM_NULL_COPY_FN, Petsc_DelViewer, &Petsc_Viewer_keyval, (void *)0)); 245 /* 246 It would be better to move this code to PetscFileSetName() but since it must return a preexiting communicator 247 we cannot do that, since PetscFileSetName() takes a communicator that already exists. 248 249 Plus if the original communicator that created the file has since been close this will not detect the old 250 communictor and hence will overwrite the old data. It may be better to simply remove all this code 251 */ 252 /* make sure communicator is a PETSc communicator */ 253 PetscCall(PetscCommDuplicate(comm, &comm, NULL)); 254 /* has file already been opened into a viewer */ 255 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 256 if (flg) { 257 while (vlink) { 258 PetscCall(PetscStrcmp(name, ((PetscViewer_ASCII *)(vlink->viewer->data))->filename, &eq)); 259 if (eq) { 260 PetscCall(PetscObjectReference((PetscObject)vlink->viewer)); 261 *lab = vlink->viewer; 262 PetscCall(PetscCommDestroy(&comm)); 263 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 264 PetscFunctionReturn(PETSC_SUCCESS); 265 } 266 vlink = vlink->next; 267 } 268 } 269 PetscCall(PetscViewerCreate(comm, lab)); 270 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 271 if (name) PetscCall(PetscViewerFileSetName(*lab, name)); 272 /* save viewer into communicator if needed later */ 273 PetscCall(PetscNew(&nv)); 274 nv->viewer = *lab; 275 if (!flg) { 276 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 277 } else { 278 PetscCallMPI(MPI_Comm_get_attr(comm, Petsc_Viewer_keyval, (void **)&vlink, (PetscMPIInt *)&flg)); 279 if (vlink) { 280 while (vlink->next) vlink = vlink->next; 281 vlink->next = nv; 282 } else { 283 PetscCallMPI(MPI_Comm_set_attr(comm, Petsc_Viewer_keyval, nv)); 284 } 285 } 286 PetscCall(PetscCommDestroy(&comm)); 287 PetscCall(PetscSpinlockUnlock(&PetscViewerASCIISpinLockOpen)); 288 PetscFunctionReturn(PETSC_SUCCESS); 289 } 290 291 /*@C 292 PetscViewerASCIIOpenWithFILE - Given an open file creates an `PETSCVIEWERASCII` viewer that prints to it. 293 294 Collective 295 296 Input Parameters: 297 + comm - the communicator 298 - fd - the `FILE` pointer 299 300 Output Parameter: 301 . lab - the `PetscViewer` to use with the specified file 302 303 Level: beginner 304 305 Notes: 306 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the fd will NOT be closed. 307 308 If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`), 309 then only the first processor in the group uses the file. All other 310 processors send their data to the first processor to print. 311 312 Fortran Notes: 313 Use `PetscViewerASCIIOpenWithFileUnit()` 314 315 .seealso: [](sec_viewers), `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIIOpenWithFileUnit()`, 316 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 317 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIISetFILE()`, `PETSCVIEWERASCII` 318 @*/ 319 PetscErrorCode PetscViewerASCIIOpenWithFILE(MPI_Comm comm, FILE *fd, PetscViewer *lab) 320 { 321 PetscFunctionBegin; 322 PetscCall(PetscViewerCreate(comm, lab)); 323 PetscCall(PetscViewerSetType(*lab, PETSCVIEWERASCII)); 324 PetscCall(PetscViewerASCIISetFILE(*lab, fd)); 325 PetscFunctionReturn(PETSC_SUCCESS); 326 } 327 328 /*@C 329 PetscViewerASCIISetFILE - Given an open file sets the `PETSCVIEWERASCII` viewer to use the file for output 330 331 Not Collective 332 333 Input Parameters: 334 + viewer - the `PetscViewer` to use with the specified file 335 - fd - the `FILE` pointer 336 337 Level: beginner 338 339 Notes: 340 This `PetscViewer` can be destroyed with `PetscViewerDestroy()`, but the `fd` will NOT be closed. 341 342 If a multiprocessor communicator is used (such as `PETSC_COMM_WORLD`), 343 then only the first processor in the group uses the file. All other 344 processors send their data to the first processor to print. 345 346 Fortran Notes: 347 Use `PetscViewerASCIISetFileUnit()` 348 349 .seealso: `MatView()`, `VecView()`, `PetscViewerDestroy()`, `PetscViewerBinaryOpen()`, `PetscViewerASCIISetFileUnit()`, 350 `PetscViewerASCIIGetPointer()`, `PetscViewerPushFormat()`, `PETSC_VIEWER_STDOUT_`, `PETSC_VIEWER_STDERR_`, 351 `PETSC_VIEWER_STDOUT_WORLD`, `PETSC_VIEWER_STDOUT_SELF`, `PetscViewerASCIIOpen()`, `PetscViewerASCIIOpenWithFILE()`, `PETSCVIEWERASCII` 352 @*/ 353 PetscErrorCode PetscViewerASCIISetFILE(PetscViewer viewer, FILE *fd) 354 { 355 PetscViewer_ASCII *vascii = (PetscViewer_ASCII *)viewer->data; 356 357 PetscFunctionBegin; 358 vascii->fd = fd; 359 vascii->closefile = PETSC_FALSE; 360 PetscFunctionReturn(PETSC_SUCCESS); 361 } 362