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