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