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