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 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetName_C",NULL)); 44 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetName_C",NULL)); 45 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileSetMode_C",NULL)); 46 PetscCall(PetscObjectComposeFunction((PetscObject)viewer,"PetscViewerFileGetMode_C",NULL)); 47 PetscFunctionReturn(0); 48 } 49 50 PetscErrorCode PetscViewerFlush_VU(PetscViewer viewer) 51 { 52 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 53 PetscMPIInt rank; 54 int err; 55 56 PetscFunctionBegin; 57 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 58 if (rank == 0) { 59 err = fflush(vu->fd); 60 PetscCheck(!err,PETSC_COMM_SELF,PETSC_ERR_SYS,"fflush() failed on file"); 61 } 62 PetscFunctionReturn(0); 63 } 64 65 static PetscErrorCode PetscViewerFileSetMode_VU(PetscViewer viewer, PetscFileMode mode) 66 { 67 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 68 69 PetscFunctionBegin; 70 vu->mode = mode; 71 PetscFunctionReturn(0); 72 } 73 74 static PetscErrorCode PetscViewerFileGetMode_VU(PetscViewer viewer, PetscFileMode *type) 75 { 76 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 77 78 PetscFunctionBegin; 79 *type = vu->mode; 80 PetscFunctionReturn(0); 81 } 82 83 static PetscErrorCode PetscViewerFileGetName_VU(PetscViewer viewer, const char **name) 84 { 85 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 86 87 PetscFunctionBegin; 88 *name = vu->filename; 89 PetscFunctionReturn(0); 90 } 91 92 static PetscErrorCode PetscViewerFileSetName_VU(PetscViewer viewer, const char name[]) 93 { 94 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 95 char fname[PETSC_MAX_PATH_LEN]; 96 int rank; 97 98 PetscFunctionBegin; 99 if (!name) PetscFunctionReturn(0); 100 PetscCall(PetscViewerFileClose_VU(viewer)); 101 PetscCallMPI(MPI_Comm_rank(PetscObjectComm((PetscObject)viewer), &rank)); 102 if (rank != 0) PetscFunctionReturn(0); 103 PetscCall(PetscStrallocpy(name, &vu->filename)); 104 PetscCall(PetscFixFilename(name, fname)); 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 PetscCall(fseek(vu->fd, 0, SEEK_END)); 127 } 128 break; 129 default: 130 SETERRQ(PetscObjectComm((PetscObject)viewer),PETSC_ERR_SUP, "Unsupported file mode %s",PetscFileModes[vu->mode]); 131 } 132 133 PetscCheck(vu->fd,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 144 PetscFunctionBegin; 145 PetscCall(PetscNewLog(viewer,&vu)); 146 viewer->data = (void*) vu; 147 148 viewer->ops->destroy = PetscViewerDestroy_VU; 149 viewer->ops->flush = PetscViewerFlush_VU; 150 viewer->ops->getsubviewer = NULL; 151 viewer->ops->restoresubviewer = NULL; 152 153 vu->fd = NULL; 154 vu->mode = FILE_MODE_WRITE; 155 vu->filename = NULL; 156 vu->vecSeen = PETSC_FALSE; 157 vu->queue = NULL; 158 vu->queueBase = NULL; 159 vu->queueLength = 0; 160 161 PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetName_C",PetscViewerFileSetName_VU)); 162 PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetName_C",PetscViewerFileGetName_VU)); 163 PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileSetMode_C",PetscViewerFileSetMode_VU)); 164 PetscCall(PetscObjectComposeFunction((PetscObject) viewer,"PetscViewerFileGetMode_C",PetscViewerFileGetMode_VU)); 165 PetscFunctionReturn(0); 166 } 167 168 /*@C 169 PetscViewerVUGetPointer - Extracts the file pointer from a VU PetscViewer. 170 171 Not Collective 172 173 Input Parameter: 174 . viewer - The PetscViewer 175 176 Output Parameter: 177 . fd - The file pointer 178 179 Level: intermediate 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 /*@C 195 PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed 196 a vector. This is usually called internally rather than by a user. 197 198 Not Collective 199 200 Input Parameters: 201 + viewer - The PetscViewer 202 - vecSeen - The flag which indicates whether we have viewed a vector 203 204 Level: advanced 205 206 .seealso: `PetscViewerVUGetVecSeen()` 207 @*/ 208 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen) 209 { 210 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 211 212 PetscFunctionBegin; 213 vu->vecSeen = vecSeen; 214 PetscFunctionReturn(0); 215 } 216 217 /*@C 218 PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed 219 a vector. This is usually called internally rather than by a user. 220 221 Not Collective 222 223 Input Parameter: 224 . viewer - The PetscViewer 225 226 Output Parameter: 227 . vecSeen - The flag which indicates whether we have viewed a vector 228 229 Level: advanced 230 231 .seealso: `PetscViewerVUGetVecSeen()` 232 @*/ 233 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen) 234 { 235 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 236 237 PetscFunctionBegin; 238 PetscValidHeaderSpecific(viewer,PETSC_VIEWER_CLASSID,1); 239 PetscValidBoolPointer(vecSeen,2); 240 *vecSeen = vu->vecSeen; 241 PetscFunctionReturn(0); 242 } 243 244 /*@C 245 PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file. 246 247 Not Collective 248 249 Input Parameters: 250 + viewer - The PetscViewer 251 - format - The format string 252 253 Level: intermediate 254 255 .seealso: `PetscViewerVUFlushDeferred()` 256 @*/ 257 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...) 258 { 259 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 260 va_list Argp; 261 size_t fullLength; 262 PrintfQueue next; 263 264 PetscFunctionBegin; 265 PetscCall(PetscNew(&next)); 266 if (vu->queue) { 267 vu->queue->next = next; 268 vu->queue = next; 269 vu->queue->next = NULL; 270 } else { 271 vu->queueBase = vu->queue = next; 272 } 273 vu->queueLength++; 274 275 va_start(Argp, format); 276 PetscCall(PetscArrayzero(next->string,QUEUESTRINGSIZE)); 277 PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE,format,&fullLength, Argp)); 278 va_end(Argp); 279 PetscFunctionReturn(0); 280 } 281 282 /*@C 283 PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file. 284 285 Not Collective 286 287 Input Parameter: 288 . viewer - The PetscViewer 289 290 Level: intermediate 291 292 .seealso: `PetscViewerVUPrintDeferred()` 293 @*/ 294 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer) 295 { 296 PetscViewer_VU *vu = (PetscViewer_VU*) viewer->data; 297 PrintfQueue next = vu->queueBase; 298 PrintfQueue previous; 299 int i; 300 301 PetscFunctionBegin; 302 for (i = 0; i < vu->queueLength; i++) { 303 PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string); 304 previous = next; 305 next = next->next; 306 PetscCall(PetscFree(previous)); 307 } 308 vu->queue = NULL; 309 vu->queueLength = 0; 310 PetscFunctionReturn(0); 311 } 312