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