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