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