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