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