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