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