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