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