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