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