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 /*MC 123 PETSCVIEWERVU - A viewer that prints to a VU file 124 125 Level: beginner 126 127 .seealso: `PetscViewerVUFlushDeferred()`, `PetscViewerVUGetPointer()`, `PetscViewerVUSetVecSeen()`, `PetscViewerVUGetVecSeen()`, 128 `PetscViewerVUPrintDeferred()`, `PetscViewerVUFlushDeferred()` 129 M*/ 130 PETSC_EXTERN PetscErrorCode PetscViewerCreate_VU(PetscViewer viewer) { 131 PetscViewer_VU *vu; 132 133 PetscFunctionBegin; 134 PetscCall(PetscNewLog(viewer, &vu)); 135 viewer->data = (void *)vu; 136 137 viewer->ops->destroy = PetscViewerDestroy_VU; 138 viewer->ops->flush = PetscViewerFlush_VU; 139 viewer->ops->getsubviewer = NULL; 140 viewer->ops->restoresubviewer = NULL; 141 142 vu->fd = NULL; 143 vu->mode = FILE_MODE_WRITE; 144 vu->filename = NULL; 145 vu->vecSeen = PETSC_FALSE; 146 vu->queue = NULL; 147 vu->queueBase = NULL; 148 vu->queueLength = 0; 149 150 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", PetscViewerFileSetName_VU)); 151 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", PetscViewerFileGetName_VU)); 152 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_VU)); 153 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_VU)); 154 PetscFunctionReturn(0); 155 } 156 157 /*@C 158 PetscViewerVUGetPointer - Extracts the file pointer from a `PETSCVIEWERVU` `PetscViewer`. 159 160 Not Collective 161 162 Input Parameter: 163 . viewer - The `PetscViewer` 164 165 Output Parameter: 166 . fd - The file pointer 167 168 Level: intermediate 169 170 .seealso: `PETSCVIEWERVU`, `PetscViewerASCIIGetPointer()` 171 @*/ 172 PetscErrorCode PetscViewerVUGetPointer(PetscViewer viewer, FILE **fd) { 173 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data; 174 175 PetscFunctionBegin; 176 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 177 PetscValidPointer(fd, 2); 178 *fd = vu->fd; 179 PetscFunctionReturn(0); 180 } 181 182 /*@C 183 PetscViewerVUSetVecSeen - Sets the flag which indicates whether we have viewed 184 a vector. This is usually called internally rather than by a user. 185 186 Not Collective 187 188 Input Parameters: 189 + viewer - The `PETSCVIEWERVU` `PetscViewer` 190 - vecSeen - The flag which indicates whether we have viewed a vector 191 192 Level: developer 193 194 .seealso: `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()` 195 @*/ 196 PetscErrorCode PetscViewerVUSetVecSeen(PetscViewer viewer, PetscBool vecSeen) { 197 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data; 198 199 PetscFunctionBegin; 200 vu->vecSeen = vecSeen; 201 PetscFunctionReturn(0); 202 } 203 204 /*@C 205 PetscViewerVUGetVecSeen - Gets the flag which indicates whether we have viewed 206 a vector. This is usually called internally rather than by a user. 207 208 Not Collective 209 210 Input Parameter: 211 . viewer - The `PETSCVIEWERVU` `PetscViewer` 212 213 Output Parameter: 214 . vecSeen - The flag which indicates whether we have viewed a vector 215 216 Level: advanced 217 218 .seealso: `PETSCVIEWERVU`, `PetscViewerVUGetVecSeen()` 219 @*/ 220 PetscErrorCode PetscViewerVUGetVecSeen(PetscViewer viewer, PetscBool *vecSeen) { 221 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data; 222 223 PetscFunctionBegin; 224 PetscValidHeaderSpecific(viewer, PETSC_VIEWER_CLASSID, 1); 225 PetscValidBoolPointer(vecSeen, 2); 226 *vecSeen = vu->vecSeen; 227 PetscFunctionReturn(0); 228 } 229 230 /*@C 231 PetscViewerVUPrintDeferred - Prints to the deferred write cache instead of the file. 232 233 Not Collective 234 235 Input Parameters: 236 + viewer - The `PETSCVIEWERVU` `PetscViewer` 237 - format - The format string 238 239 Level: intermediate 240 241 .seealso: `PETSCVIEWERVU`, `PetscViewerVUFlushDeferred()` 242 @*/ 243 PetscErrorCode PetscViewerVUPrintDeferred(PetscViewer viewer, const char format[], ...) { 244 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data; 245 va_list Argp; 246 size_t fullLength; 247 PrintfQueue next; 248 249 PetscFunctionBegin; 250 PetscCall(PetscNew(&next)); 251 if (vu->queue) { 252 vu->queue->next = next; 253 vu->queue = next; 254 vu->queue->next = NULL; 255 } else { 256 vu->queueBase = vu->queue = next; 257 } 258 vu->queueLength++; 259 260 va_start(Argp, format); 261 PetscCall(PetscArrayzero(next->string, QUEUESTRINGSIZE)); 262 PetscCall(PetscVSNPrintf(next->string, QUEUESTRINGSIZE, format, &fullLength, Argp)); 263 va_end(Argp); 264 PetscFunctionReturn(0); 265 } 266 267 /*@C 268 PetscViewerVUFlushDeferred - Flushes the deferred write cache to the file. 269 270 Not Collective 271 272 Input Parameter: 273 . viewer - The `PETSCVIEWERVU` `PetscViewer` 274 275 Level: intermediate 276 277 .seealso: `PETSCVIEWERVU`, `PetscViewerVUPrintDeferred()` 278 @*/ 279 PetscErrorCode PetscViewerVUFlushDeferred(PetscViewer viewer) { 280 PetscViewer_VU *vu = (PetscViewer_VU *)viewer->data; 281 PrintfQueue next = vu->queueBase; 282 PrintfQueue previous; 283 int i; 284 285 PetscFunctionBegin; 286 for (i = 0; i < vu->queueLength; i++) { 287 PetscFPrintf(PetscObjectComm((PetscObject)viewer), vu->fd, "%s", next->string); 288 previous = next; 289 next = next->next; 290 PetscCall(PetscFree(previous)); 291 } 292 vu->queue = NULL; 293 vu->queueLength = 0; 294 PetscFunctionReturn(0); 295 } 296