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