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;

 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: }

 19: static PetscErrorCode PetscViewerView_CGNS(PetscViewer v, PetscViewer viewer)
 20: {
 21:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)v->data;

 23:   PetscFunctionBegin;
 24:   if (cgv->filename) PetscCall(PetscViewerASCIIPrintf(viewer, "Filename: %s\n", cgv->filename));
 25:   PetscFunctionReturn(PETSC_SUCCESS);
 26: }

 28: static PetscErrorCode PetscViewerFileClose_CGNS(PetscViewer viewer)
 29: {
 30:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

 32:   PetscFunctionBegin;
 33:   if (cgv->output_times) {
 34:     size_t     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, &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 (size_t i = 0; i < size; i++) PetscCall(PetscSNPrintf(&solnames[i * width], width + 1, "FlowSolution%-20zu", 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 (size_t 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));

 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: }

 72: PetscErrorCode PetscViewerCGNSFileOpen_Internal(PetscViewer viewer, PetscInt sequence_number)
 73: {
 74:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

 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: }

105: PetscErrorCode PetscViewerCGNSCheckBatch_Internal(PetscViewer viewer)
106: {
107:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;
108:   size_t            num_steps;

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 >= cgv->batch_size) PetscCall(PetscViewerFileClose_CGNS(viewer));
114:   PetscFunctionReturn(PETSC_SUCCESS);
115: }

117: static PetscErrorCode PetscViewerDestroy_CGNS(PetscViewer viewer)
118: {
119:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

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: }

131: static PetscErrorCode PetscViewerFileSetMode_CGNS(PetscViewer viewer, PetscFileMode type)
132: {
133:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

135:   PetscFunctionBegin;
136:   cgv->btype = type;
137:   PetscFunctionReturn(PETSC_SUCCESS);
138: }

140: static PetscErrorCode PetscViewerFileGetMode_CGNS(PetscViewer viewer, PetscFileMode *type)
141: {
142:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

144:   PetscFunctionBegin;
145:   *type = cgv->btype;
146:   PetscFunctionReturn(PETSC_SUCCESS);
147: }

149: static PetscErrorCode PetscViewerFileSetName_CGNS(PetscViewer viewer, const char *filename)
150: {
151:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;
152:   char             *has_pattern;

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: }

169: static PetscErrorCode PetscViewerFileGetName_CGNS(PetscViewer viewer, const char **filename)
170: {
171:   PetscViewer_CGNS *cgv = (PetscViewer_CGNS *)viewer->data;

173:   PetscFunctionBegin;
174:   *filename = cgv->filename;
175:   PetscFunctionReturn(PETSC_SUCCESS);
176: }

178: /*MC
179:    PETSCVIEWERCGNS - A viewer for CGNS files

181:   Level: beginner

183:   Options Database Key:
184: . -viewer_cgns_batch_size SIZE - set max number of output sequence times to write per batch

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.

191: .seealso: [](sec_viewers), `PetscViewer`, `PetscViewerCreate()`, `VecView()`, `DMView()`, `PetscViewerFileSetName()`, `PetscViewerFileSetMode()`, `TSSetFromOptions()`
192: M*/

194: PETSC_EXTERN PetscErrorCode PetscViewerCreate_CGNS(PetscViewer v)
195: {
196:   PetscViewer_CGNS *cgv;

198:   PetscFunctionBegin;
199:   PetscCall(PetscNew(&cgv));

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;

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: }