1 #include <petsc/private/viewercgnsimpl.h> /*I "petscviewer.h" I*/ 2 #if defined(PETSC_HDF5_HAVE_PARALLEL) 3 #include <pcgnslib.h> 4 #else 5 #include <cgnslib.h> 6 #endif 7 8 static PetscErrorCode PetscViewerSetFromOptions_CGNS(PetscViewer v, PetscOptionItems *PetscOptionsObject) 9 { 10 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)v->data; 11 12 PetscFunctionBegin; 13 PetscOptionsHeadBegin(PetscOptionsObject, "CGNS Viewer Options"); 14 PetscCall(PetscOptionsInt("-viewer_cgns_batch_size", "Max number of steps to store in single file when using a template cgns:name-\%d.cgns", "", cgv->batch_size, &cgv->batch_size, NULL)); 15 PetscOptionsHeadEnd(); 16 PetscFunctionReturn(PETSC_SUCCESS); 17 } 18 19 static PetscErrorCode PetscViewerView_CGNS(PetscViewer v, PetscViewer viewer) 20 { 21 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)v->data; 22 23 PetscFunctionBegin; 24 if (cgv->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", cgv->filename)); 25 PetscFunctionReturn(PETSC_SUCCESS); 26 } 27 28 static PetscErrorCode PetscViewerFileClose_CGNS(PetscViewer viewer) 29 { 30 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 31 32 PetscFunctionBegin; 33 if (cgv->output_times) { 34 PetscCount size, width = 32, *steps; 35 char *solnames; 36 PetscReal *times; 37 cgsize_t num_times; 38 PetscCall(PetscSegBufferGetSize(cgv->output_times, &size)); 39 PetscCall(PetscSegBufferExtractInPlace(cgv->output_times, ×)); 40 num_times = size; 41 PetscCallCGNS(cg_biter_write(cgv->file_num, cgv->base, "TimeIterValues", num_times)); 42 PetscCallCGNS(cg_goto(cgv->file_num, cgv->base, "BaseIterativeData_t", 1, NULL)); 43 PetscCallCGNS(cg_array_write("TimeValues", CGNS_ENUMV(RealDouble), 1, &num_times, times)); 44 PetscCall(PetscSegBufferDestroy(&cgv->output_times)); 45 PetscCallCGNS(cg_ziter_write(cgv->file_num, cgv->base, cgv->zone, "ZoneIterativeData")); 46 PetscCallCGNS(cg_goto(cgv->file_num, cgv->base, "Zone_t", cgv->zone, "ZoneIterativeData_t", 1, NULL)); 47 PetscCall(PetscMalloc(size * width + 1, &solnames)); 48 PetscCall(PetscSegBufferExtractInPlace(cgv->output_steps, &steps)); 49 for (PetscCount i = 0; i < size; i++) PetscCall(PetscSNPrintf(&solnames[i * width], width + 1, "FlowSolution%-20zu", (size_t)steps[i])); 50 PetscCall(PetscSegBufferDestroy(&cgv->output_steps)); 51 cgsize_t shape[2] = {(cgsize_t)width, (cgsize_t)size}; 52 PetscCallCGNS(cg_array_write("FlowSolutionPointers", CGNS_ENUMV(Character), 2, shape, solnames)); 53 // The VTK reader looks for names like FlowSolution*Pointers. 54 for (PetscCount i = 0; i < size; i++) PetscCall(PetscSNPrintf(&solnames[i * width], width + 1, "%-32s", "CellInfo")); 55 PetscCallCGNS(cg_array_write("FlowSolutionCellInfoPointers", CGNS_ENUMV(Character), 2, shape, solnames)); 56 PetscCall(PetscFree(solnames)); 57 58 PetscCallCGNS(cg_simulation_type_write(cgv->file_num, cgv->base, CGNS_ENUMV(TimeAccurate))); 59 } 60 PetscCall(PetscFree(cgv->filename)); 61 #if defined(PETSC_HDF5_HAVE_PARALLEL) 62 if (cgv->file_num) PetscCallCGNS(cgp_close(cgv->file_num)); 63 #else 64 if (cgv->file_num) PetscCallCGNS(cg_close(cgv->file_num)); 65 #endif 66 cgv->file_num = 0; 67 PetscCall(PetscFree(cgv->node_l2g)); 68 PetscCall(PetscFree(cgv->nodal_field)); 69 PetscFunctionReturn(PETSC_SUCCESS); 70 } 71 72 PetscErrorCode PetscViewerCGNSFileOpen_Internal(PetscViewer viewer, PetscInt sequence_number) 73 { 74 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 75 76 PetscFunctionBegin; 77 PetscCheck((cgv->filename == NULL) ^ (sequence_number < 0), PetscObjectComm((PetscObject)viewer), PETSC_ERR_ARG_INCOMP, "Expect either a template filename or non-negative sequence number"); 78 if (!cgv->filename) { 79 char filename_numbered[PETSC_MAX_PATH_LEN]; 80 // Cast sequence_number so %d can be used also when PetscInt is 64-bit. We could upgrade the format string if users 81 // run more than 2B time steps. 82 PetscCall(PetscSNPrintf(filename_numbered, sizeof filename_numbered, cgv->filename_template, (int)sequence_number)); 83 PetscCall(PetscStrallocpy(filename_numbered, &cgv->filename)); 84 } 85 switch (cgv->btype) { 86 case FILE_MODE_READ: 87 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "FILE_MODE_READ not yet implemented"); 88 break; 89 case FILE_MODE_WRITE: 90 #if defined(PETSC_HDF5_HAVE_PARALLEL) 91 PetscCallCGNS(cgp_mpi_comm(PetscObjectComm((PetscObject)viewer))); 92 PetscCallCGNS(cgp_open(cgv->filename, CG_MODE_WRITE, &cgv->file_num)); 93 #else 94 PetscCallCGNS(cg_open(filename, CG_MODE_WRITE, &cgv->file_num)); 95 #endif 96 break; 97 case FILE_MODE_UNDEFINED: 98 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_ORDER, "Must call PetscViewerFileSetMode() before PetscViewerFileSetName()"); 99 default: 100 SETERRQ(PetscObjectComm((PetscObject)viewer), PETSC_ERR_SUP, "Unsupported file mode %s", PetscFileModes[cgv->btype]); 101 } 102 PetscFunctionReturn(PETSC_SUCCESS); 103 } 104 105 PetscErrorCode PetscViewerCGNSCheckBatch_Internal(PetscViewer viewer) 106 { 107 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 108 PetscCount num_steps; 109 110 PetscFunctionBegin; 111 if (!cgv->filename_template) PetscFunctionReturn(PETSC_SUCCESS); // Batches are closed when viewer is destroyed 112 PetscCall(PetscSegBufferGetSize(cgv->output_times, &num_steps)); 113 if (num_steps >= (PetscCount)cgv->batch_size) PetscCall(PetscViewerFileClose_CGNS(viewer)); 114 PetscFunctionReturn(PETSC_SUCCESS); 115 } 116 117 static PetscErrorCode PetscViewerDestroy_CGNS(PetscViewer viewer) 118 { 119 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 120 121 PetscFunctionBegin; 122 PetscCall(PetscViewerFileClose_CGNS(viewer)); 123 PetscCall(PetscFree(cgv)); 124 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetName_C", NULL)); 125 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetName_C", NULL)); 126 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileSetMode_C", NULL)); 127 PetscCall(PetscObjectComposeFunction((PetscObject)viewer, "PetscViewerFileGetMode_C", NULL)); 128 PetscFunctionReturn(PETSC_SUCCESS); 129 } 130 131 static PetscErrorCode PetscViewerFileSetMode_CGNS(PetscViewer viewer, PetscFileMode type) 132 { 133 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 134 135 PetscFunctionBegin; 136 cgv->btype = type; 137 PetscFunctionReturn(PETSC_SUCCESS); 138 } 139 140 static PetscErrorCode PetscViewerFileGetMode_CGNS(PetscViewer viewer, PetscFileMode *type) 141 { 142 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 143 144 PetscFunctionBegin; 145 *type = cgv->btype; 146 PetscFunctionReturn(PETSC_SUCCESS); 147 } 148 149 static PetscErrorCode PetscViewerFileSetName_CGNS(PetscViewer viewer, const char *filename) 150 { 151 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 152 char *has_pattern; 153 154 PetscFunctionBegin; 155 if (cgv->file_num) PetscCallCGNS(cg_close(cgv->file_num)); 156 PetscCall(PetscFree(cgv->filename)); 157 PetscCall(PetscFree(cgv->filename_template)); 158 PetscCall(PetscStrchr(filename, '%', &has_pattern)); 159 if (has_pattern) { 160 PetscCall(PetscStrallocpy(filename, &cgv->filename_template)); 161 // Templated file names open lazily, once we know DMGetOutputSequenceNumber() 162 } else { 163 PetscCall(PetscStrallocpy(filename, &cgv->filename)); 164 PetscCall(PetscViewerCGNSFileOpen_Internal(viewer, -1)); 165 } 166 PetscFunctionReturn(PETSC_SUCCESS); 167 } 168 169 static PetscErrorCode PetscViewerFileGetName_CGNS(PetscViewer viewer, const char **filename) 170 { 171 PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data; 172 173 PetscFunctionBegin; 174 *filename = cgv->filename; 175 PetscFunctionReturn(PETSC_SUCCESS); 176 } 177 178 /*MC 179 PETSCVIEWERCGNS - A viewer for CGNS files 180 181 Level: beginner 182 183 Options Database Key: 184 . -viewer_cgns_batch_size SIZE - set max number of output sequence times to write per batch 185 186 Note: 187 If the filename contains an integer format character, the CGNS viewer will created a batched output sequence. For 188 example, one could use `-ts_monitor_solution cgns:flow-%d.cgns`. This is desirable if one wants to limit file sizes or 189 if the job might crash/be killed by a resource manager before exiting cleanly. 190 191 .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `VecView()`, `DMView()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `TSSetFromOptions()` 192 M*/ 193 194 PETSC_EXTERN PetscErrorCode PetscViewerCreate_CGNS(PetscViewer v) 195 { 196 PetscViewer_CGNS *cgv; 197 198 PetscFunctionBegin; 199 PetscCall(PetscNew(&cgv)); 200 201 v->data = cgv; 202 v->ops->destroy = PetscViewerDestroy_CGNS; 203 v->ops->setfromoptions = PetscViewerSetFromOptions_CGNS; 204 v->ops->view = PetscViewerView_CGNS; 205 cgv->btype = FILE_MODE_UNDEFINED; 206 cgv->filename = NULL; 207 cgv->batch_size = 20; 208 209 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetName_C", PetscViewerFileSetName_CGNS)); 210 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetName_C", PetscViewerFileGetName_CGNS)); 211 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileSetMode_C", PetscViewerFileSetMode_CGNS)); 212 PetscCall(PetscObjectComposeFunction((PetscObject)v, "PetscViewerFileGetMode_C", PetscViewerFileGetMode_CGNS)); 213 PetscFunctionReturn(PETSC_SUCCESS); 214 } 215