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