1 2 #include <petsc-private/viewerimpl.h> /*I "petscsys.h" I*/ 3 4 #define QUEUESTRINGSIZE 1024 5 6 typedef struct _PrintfQueue *PrintfQueue; 7 struct _PrintfQueue { 8 char string[QUEUESTRINGSIZE]; 9 PrintfQueue next; 10 }; 11 12 typedef struct { 13 FILE *fd; 14 PetscFileMode mode; /* The mode in which to open the file */ 15 char *filename; 16 PetscBool vecSeen; /* The flag indicating whether any vector has been viewed so far */ 17 PrintfQueue queue, queueBase; 18 int queueLength; 19 } PetscViewer_VU; 20 21 #undef __FUNCT__ 22 #define __FUNCT__ "PetscViewerFileClose_VU" 23 static PetscErrorCode PetscViewerFileClose_VU(PetscViewer viewer) 24 { 25 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 26 PetscErrorCode ierr; 27 28 PetscFunctionBegin; 29 if (vu->vecSeen) { 30 ierr = PetscViewerVUPrintDeferred(viewer, "};\n\n");CHKERRQ(ierr); 31 } 32 ierr = PetscViewerVUFlushDeferred(viewer);CHKERRQ(ierr); 33 ierr = PetscFClose(PetscObjectComm((PetscObject)viewer), vu->fd);CHKERRQ(ierr); 34 vu->fd = NULL; 35 ierr = PetscFree(vu->filename);CHKERRQ(ierr); 36 PetscFunctionReturn(0); 37 } 38 39 #undef __FUNCT__ 40 #define __FUNCT__ "PetscViewerDestroy_VU" 41 PetscErrorCode PetscViewerDestroy_VU(PetscViewer viewer) 42 { 43 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 44 PetscErrorCode ierr; 45 46 PetscFunctionBegin; 47 ierr = PetscViewerFileClose_VU(viewer);CHKERRQ(ierr); 48 ierr = PetscFree(vu);CHKERRQ(ierr); 49 PetscFunctionReturn(0); 50 } 51 52 #undef __FUNCT__ 53 #define __FUNCT__ "PetscViewerFlush_VU" 54 PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer) 55 { 56 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 57 PetscMPIInt rank; 58 int err; 59 PetscErrorCode ierr; 60 61 PetscFunctionBegin; 62 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr); 63 if (!rank) { 64 err = fflush(vu->fd); 65 if (err) SETERRQ(PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 66 } 67 PetscFunctionReturn(0); 68 } 69 70 #undef __FUNCT__ 71 #define __FUNCT__ "PetscViewerFileGetName_VU" 72 PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name) 73 { 74 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 75 76 PetscFunctionBegin; 77 *name = vu->filename; 78 PetscFunctionReturn(0); 79 } 80 81 #undef __FUNCT__ 82 #define __FUNCT__ "PetscViewerFileSetName_VU" 83 PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[]) 84 { 85 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 86 char fname[PETSC_MAX_PATH_LEN]; 87 int rank; 88 PetscErrorCode ierr; 89 90 PetscFunctionBegin; 91 if (!name) PetscFunctionReturn(0); 92 ierr = PetscViewerFileClose_VU(viewer);CHKERRQ(ierr); 93 ierr = MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank);CHKERRQ(ierr); 94 if (rank != 0) PetscFunctionReturn(0); 95 ierr = PetscStrallocpy(name, &vu->filename);CHKERRQ(ierr); 96 ierr = PetscFixFilename(name, fname);CHKERRQ(ierr); 97 switch (vu->mode) { 98 case FILE_MODE_READ: 99 vu->fd = fopen(fname, "r"); 100 break; 101 case FILE_MODE_WRITE: 102 vu->fd = fopen(fname, "w"); 103 break; 104 case FILE_MODE_APPEND: 105 vu->fd = fopen(fname, "a"); 106 break; 107 case FILE_MODE_UPDATE: 108 vu->fd = fopen(fname, "r+"); 109 if (!vu->fd) vu->fd = fopen(fname, "w+"); 110 break; 111 case FILE_MODE_APPEND_UPDATE: 112 /* I really want a file which is opened at the end for updating, 113 not a+, which opens at the beginning, but makes writes at the end. 114 */ 115 vu->fd = fopen(fname, "r+"); 116 if (!vu->fd) vu->fd = fopen(fname, "w+"); 117 else { 118 ierr = fseek(vu->fd, 0, SEEK_END);CHKERRQ(ierr); 119 } 120 break; 121 default: 122 SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_ARG_WRONG, "Invalid file mode %d", vu->mode); 123 } 124 125 if (!vu->fd) SETERRQ1(PETSC_COMM_SELF,PETSC_ERR_FILE_OPEN, "Cannot open PetscViewer file: %s", fname); 126 #if defined(PETSC_USE_LOG) 127 PetscLogObjectState((PetscObject) viewer, "File: %s", name); 128 #endif 129 PetscFunctionReturn(0); 130 } 131 132 #undef __FUNCT__ 133 #define __FUNCT__ "PetscViewerCreate_VU" 134 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer) 135 { 136 PetscViewer_VU *vu; 137 PetscErrorCode ierr; 138 139 PetscFunctionBegin; 140 ierr = PetscNewLog(viewer,PetscViewer_VU, &vu);CHKERRQ(ierr); 141 viewer->data = (void*) vu; 142 143 viewer->ops->destroy = PetscViewerDestroy_VU; 144 viewer->ops->flush = PetscViewerFlush_VU; 145 viewer->ops->getsingleton = NULL; 146 viewer->ops->restoresingleton = NULL; 147 viewer->format = PETSC_VIEWER_DEFAULT; 148 viewer->iformat = 0; 149 150 vu->fd = NULL; 151 vu->mode = FILE_MODE_WRITE; 152 vu->filename = NULL; 153 vu->vecSeen = PETSC_FALSE; 154 vu->queue = NULL; 155 vu->queueBase = NULL; 156 vu->queueLength = 0; 157 158 ierr = PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU);CHKERRQ(ierr); 159 ierr = PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU);CHKERRQ(ierr); 160 PetscFunctionReturn(0); 161 } 162 163 #undef __FUNCT__ 164 #define __FUNCT__ "PetscViewerVUGetPointer" 165 /*@C 166 PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer. 167 168 Not Collective 169 170 Input Parameter: 171 . viewer - The PetscViewer 172 173 Output Parameter: 174 . fd - The file pointer 175 176 Level: intermediate 177 178 Concepts: PetscViewer^file pointer 179 Concepts: file pointer^getting from PetscViewer 180 181 .seealso: PetscViewerASCIIGetPointer() 182 @*/ 183 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd) 184 { 185 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 186 187 PetscFunctionBegin; 188 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 189 PetscValidPointer(fd,2); 190 *fd = vu->fd; 191 PetscFunctionReturn(0); 192 } 193 194 #undef __FUNCT__ 195 #define __FUNCT__ "PetscViewerVUSetMode" 196 /*@C 197 PetscViewerVUSetMode - Sets the mode in which to open the file. 198 199 Not Collective 200 201 Input Parameters: 202 + viewer - The PetscViewer 203 - mode - The file mode 204 205 Level: intermediate 206 207 .keywords: Viewer, file, get, pointer 208 .seealso: PetscViewerASCIISetMode() 209 @*/ 210 PetscErrorCode PetscViewerVUSetMode(PetscViewer viewer, PetscFileMode mode) 211 { 212 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 213 214 PetscFunctionBegin; 215 vu->mode = mode; 216 PetscFunctionReturn(0); 217 } 218 219 #undef __FUNCT__ 220 #define __FUNCT__ "PetscViewerVUSetVecSeen" 221 /*@C 222 PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed 223 a vector. This is usually called internally rather than by a user. 224 225 Not Collective 226 227 Input Parameters: 228 + viewer - The PetscViewer 229 - vecSeen - The flag which indicates whether we have viewed a vector 230 231 Level: advanced 232 233 .keywords: Viewer, Vec 234 .seealso: PetscViewerVUGetVecSeen() 235 @*/ 236 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen) 237 { 238 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 239 240 PetscFunctionBegin; 241 vu->vecSeen = vecSeen; 242 PetscFunctionReturn(0); 243 } 244 245 #undef __FUNCT__ 246 #define __FUNCT__ "PetscViewerVUGetVecSeen" 247 /*@C 248 PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed 249 a vector. This is usually called internally rather than by a user. 250 251 Not Collective 252 253 Input Parameter: 254 . viewer - The PetscViewer 255 256 Output Parameter: 257 . vecSeen - The flag which indicates whether we have viewed a vector 258 259 Level: advanced 260 261 .keywords: Viewer, Vec 262 .seealso: PetscViewerVUGetVecSeen() 263 @*/ 264 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen) 265 { 266 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 267 268 PetscFunctionBegin; 269 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 270 PetscValidPointer(vecSeen,2); 271 *vecSeen = vu->vecSeen; 272 PetscFunctionReturn(0); 273 } 274 275 #undef __FUNCT__ 276 #define __FUNCT__ "PetscViewerVUPrintDeferred" 277 /*@C 278 PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file. 279 280 Not Collective 281 282 Input Parameters: 283 + viewer - The PetscViewer 284 - format - The format string 285 286 Level: intermediate 287 288 .keywords: Viewer, print, deferred 289 .seealso: PetscViewerVUFlushDeferred() 290 @*/ 291 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...) 292 { 293 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 294 va_list Argp; 295 size_t fullLength; 296 PrintfQueue next; 297 PetscErrorCode ierr; 298 299 PetscFunctionBegin; 300 ierr = PetscNew(struct _PrintfQueue, &next);CHKERRQ(ierr); 301 if (vu->queue) { 302 vu->queue->next = next; 303 vu->queue = next; 304 vu->queue->next = NULL; 305 } else { 306 vu->queueBase = vu->queue = next; 307 } 308 vu->queueLength++; 309 310 va_start(Argp, format); 311 ierr = PetscMemzero(next->string,QUEUESTRINGSIZE);CHKERRQ(ierr); 312 ierr = PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp);CHKERRQ(ierr); 313 va_end(Argp); 314 PetscFunctionReturn(0); 315 } 316 317 #undef __FUNCT__ 318 #define __FUNCT__ "PetscViewerVUFlushDeferred" 319 /*@C 320 PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file. 321 322 Not Collective 323 324 Input Parameter: 325 + viewer - The PetscViewer 326 327 Level: intermediate 328 329 .keywords: Viewer, flush, deferred 330 .seealso: PetscViewerVUPrintDeferred() 331 @*/ 332 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer) 333 { 334 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 335 PrintfQueue next = vu->queueBase; 336 PrintfQueue previous; 337 int i; 338 PetscErrorCode ierr; 339 340 PetscFunctionBegin; 341 for (i = 0; i < vu->queueLength; i++) { 342 PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string); 343 previous = next; 344 next = next->next; 345 ierr = PetscFree(previous);CHKERRQ(ierr); 346 } 347 vu->queue = NULL; 348 vu->queueLength = 0; 349 PetscFunctionReturn(0); 350 } 351