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