16#define __FUNCT__ "SetupPostProcessSwarm"
24 PetscFunctionBeginUser;
26 char *pipeline_copy, *step_token, *step_saveptr;
27 PetscBool finalize_needed = PETSC_FALSE;
29 ierr = DMCreate(PETSC_COMM_WORLD, &user->
post_swarm); CHKERRQ(ierr);
30 ierr = DMSetType(user->
post_swarm, DMSWARM); CHKERRQ(ierr);
31 ierr = DMSetDimension(user->
post_swarm, 3); CHKERRQ(ierr);
32 ierr = DMSwarmSetType(user->
post_swarm, DMSWARM_BASIC); CHKERRQ(ierr);
35 ierr = DMSwarmSetCellDM(user->
post_swarm, user->
da); CHKERRQ(ierr);
48 step_token = strtok_r(pipeline_copy,
";", &step_saveptr);
51 if (strlen(step_token) == 0) { step_token = strtok_r(NULL,
";", &step_saveptr);
continue; }
53 char *keyword = strtok(step_token,
":");
54 char *args_str = strtok(NULL,
"");
56 PetscInt output_field_dimensions = 1;
58 if (strcasecmp(keyword,
"ComputeSpecificKE") == 0) {
59 if (!args_str) SETERRQ(PETSC_COMM_SELF, 1,
"Error (ComputeSpecificKE): Missing arguments.");
60 char *input_field = strtok(args_str,
">");
61 char *output_field = strtok(NULL,
">");
62 output_field_dimensions = 1;
63 if (!input_field) SETERRQ(PETSC_COMM_SELF, 1,
"Error (ComputeSpecificKE): Missing input field in 'in>out' syntax.");
64 if (!output_field) SETERRQ(PETSC_COMM_SELF, 1,
"Error (ComputeSpecificKE): Missing output field in 'in>out' syntax.");
67 if (strlen(input_field) == 0) SETERRQ(PETSC_COMM_SELF, 1,
"Error (ComputeSpecificKE): Empty input field name.");
68 if (strlen(output_field) == 0) SETERRQ(PETSC_COMM_SELF, 1,
"Error (ComputeSpecificKE): Empty output field name.");
71 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Registered particle field '%s' (ComputeSpecificKE input='%s').\n", output_field, input_field);
72 finalize_needed = PETSC_TRUE;
79 step_token = strtok_r(NULL,
";", &step_saveptr);
82 ierr = PetscFree(pipeline_copy); CHKERRQ(ierr);
85 if (finalize_needed) {
88 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"No custom particle fields requested; finalizing an empty post-processing swarm for safe use.\n");
90 ierr = DMSwarmFinalizeFieldRegister(user->
post_swarm); CHKERRQ(ierr);
95 PetscFunctionReturn(0);
100#define __FUNCT__ "EulerianDataProcessingPipeline"
110 char *pipeline_copy, *step_token, *step_saveptr;
112 PetscFunctionBeginUser;
120 PetscFunctionReturn(0);
126 ierr = PetscStrallocpy(pps->
process_pipeline, &pipeline_copy); CHKERRQ(ierr);
129 step_token = strtok_r(pipeline_copy,
";", &step_saveptr);
132 if (strlen(step_token) == 0) {
133 step_token = strtok_r(NULL,
";", &step_saveptr);
137 char *keyword = strtok(step_token,
":");
138 char *args_str = strtok(NULL,
"");
141 step_token = strtok_r(NULL,
";", &step_saveptr);
148 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Executing Transformation: '%s' on args: '%s'\n", keyword, args_str ? args_str :
"None");
151 if (strcasecmp(keyword,
"CellToNodeAverage") == 0) {
152 if (!args_str) SETERRQ(PETSC_COMM_SELF, 1,
"CellToNodeAverage requires arguments in 'in_field>out_field' format.");
153 char *in_field = strtok(args_str,
">");
154 char *out_field = strtok(NULL,
">");
155 if (!in_field || !out_field) SETERRQ(PETSC_COMM_SELF, 1,
"CellToNodeAverage requires 'in>out' syntax (e.g., P>P_nodal).");
156 if(strcmp(in_field,out_field)==0) SETERRQ(PETSC_COMM_SELF, 1,
"CellToNodeAverage input and output fields must be different.");
157 if(user->
simCtx->
np == 0 && (strcmp(out_field,
"Psi_nodal")==0 || strcmp(in_field,
"Psi_nodal")==0)){
158 LOG(
GLOBAL,
LOG_WARNING,
"CellToNodeAverage cannot process 'Psi_nodal' when no particles are present in the simulation.\n");
159 step_token = strtok_r(NULL,
";", &step_saveptr);
165 else if (strcasecmp(keyword,
"ComputeQCriterion") == 0) {
168 else if (strcasecmp(keyword,
"DimensionalizeAllLoadedFields") == 0) {
173 else if (strcasecmp(keyword,
"NormalizeRelativeField") == 0) {
174 if (!args_str) SETERRQ(PETSC_COMM_SELF, 1,
"NormalizePressure requires the pressure field name (e.g., 'P') as an argument.");
183 step_token = strtok_r(NULL,
";", &step_saveptr);
186 ierr = PetscFree(pipeline_copy); CHKERRQ(ierr);
189 PetscFunctionReturn(0);
194#define __FUNCT__ "WriteEulerianFile"
207 PetscFunctionBeginUser;
211 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"No instantaneous fields requested for output at ti=%" PetscInt_FMT
". Skipping.\n", ti);
213 PetscFunctionReturn(0);
222 LOG_ALLOW(
GLOBAL,
LOG_DEBUG,
"Using coords linearization order: fast=i mid=j slow=k (sizes: %" PetscInt_FMT
" x %" PetscInt_FMT
" x %" PetscInt_FMT
")\n",
223 meta.
mx, meta.
my, meta.
mz);
229 char *fields_copy, *field_name;
232 field_name = strtok(fields_copy,
",");
235 if (!*field_name) { field_name = strtok(NULL,
",");
continue; }
239 Vec field_vec = NULL;
240 PetscInt num_components = 0;
242 if (!strcasecmp(field_name,
"P_nodal")) {
243 field_vec = user->
P_nodal; num_components = 1;
244 }
else if (!strcasecmp(field_name,
"Ucat_nodal")) {
245 field_vec = user->
Ucat_nodal; num_components = 3;
246 }
else if (!strcasecmp(field_name,
"Qcrit")) {
247 field_vec = user->
Qcrit; num_components = 1;
248 }
else if (!strcasecmp(field_name,
"Psi_nodal")){
251 field_name = strtok(NULL,
",");
254 field_vec = user->
Psi_nodal; num_components = 1;
257 field_name = strtok(NULL,
",");
397 field_name = strtok(NULL,
",");
400 ierr = PetscFree(fields_copy); CHKERRQ(ierr);
468 ierr = PetscSNPrintf(filename,
sizeof(filename),
"%s_%05" PetscInt_FMT
".vts", pps->
output_prefix, ti); CHKERRQ(ierr);
473 PetscFunctionReturn(0);
478#define __FUNCT__ "FieldStatisticsPipeline"
489 char *windows_copy = NULL;
490 char *window_name = NULL;
491 PetscInt source_step = 0;
492 PetscBool want_vtk = PETSC_FALSE, want_csv = PETSC_FALSE;
494 PetscFunctionBeginUser;
500 "Field-statistics post-processing was requested, but the run's control configures "
501 "no statistics window.");
508 token = strtok(formats,
",");
511 if (!strcasecmp(token,
"vtk")) want_vtk = PETSC_TRUE;
512 else if (!strcasecmp(token,
"csv")) want_csv = PETSC_TRUE;
514 "Unknown field-statistics format '%s'. Known formats are vtk and csv.\n", token);
515 token = strtok(NULL,
",");
531 window_name = strtok(windows_copy,
",");
532 while (window_name) {
533 PetscInt window_index = -1;
537 if (!*window_name) { window_name = strtok(NULL,
",");
continue; }
540 PetscBool matches = PETSC_FALSE;
543 window_name, &matches); CHKERRQ(ierr);
544 if (matches) { window_index = w;
break; }
546 if (window_index < 0) {
547 ierr = PetscFree(windows_copy); CHKERRQ(ierr);
548 SETERRQ(PETSC_COMM_WORLD, PETSC_ERR_ARG_WRONG,
549 "Field-statistics post-processing requested window '%s', which this run does "
550 "not configure.", window_name);
558 "Statistics window '%s' had accumulated no sample by step %" PetscInt_FMT
559 "; nothing to derive yet.\n", window->
definition.
name, source_step);
560 window_name = strtok(NULL,
",");
566 PetscInt derived_count = 0;
567 char filename[PETSC_MAX_PATH_LEN];
576 if (derived_count == 0) {
578 "Outputs '%s' produce no field for window '%s'; it accumulates none of "
579 "the state they need. Skipping.\n",
585 for (PetscInt index = 0; index < derived_count; ++index) {
588 PetscInt components = 0;
592 name,
sizeof(name), &nodal, &components); CHKERRQ(ierr);
597 ierr = PetscSNPrintf(filename,
sizeof(filename),
"%s_statistics_%s_%05" PetscInt_FMT
".vts",
609 window_name = strtok(NULL,
",");
611 ierr = PetscFree(windows_copy); CHKERRQ(ierr);
615 PetscFunctionReturn(0);
619#define __FUNCT__ "ParticleDataProcessingPipeline"
629 char *pipeline_copy, *step_token, *step_saveptr;
631 PetscFunctionBeginUser;
637 PetscFunctionReturn(0);
641 PetscInt n_local_source;
642 ierr = DMSwarmGetLocalSize(user->
swarm, &n_local_source); CHKERRQ(ierr);
645 ierr = DMSwarmSetLocalSizes(user->
post_swarm, n_local_source, -1); CHKERRQ(ierr);
652 step_token = strtok_r(pipeline_copy,
";", &step_saveptr);
655 if (strlen(step_token) == 0) { step_token = strtok_r(NULL,
";", &step_saveptr);
continue; }
657 char *keyword = strtok(step_token,
":");
658 char *args_str = strtok(NULL,
"");
662 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"Executing Particle Transformation: '%s' on args: '%s'\n", keyword, args_str ? args_str :
"None");
664 if (strcasecmp(keyword,
"ComputeSpecificKE") == 0) {
665 if (!args_str) SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"ComputeSpecificKE requires 'input_field>output_field' arguments.");
666 char *velocity_field = strtok(args_str,
">");
667 char *ske_field = strtok(NULL,
">");
668 if (!velocity_field || !ske_field) {
669 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"ComputeSpecificKE requires 'input_field>output_field' arguments.");
672 if (strlen(velocity_field) == 0 || strlen(ske_field) == 0) {
673 SETERRQ(PETSC_COMM_SELF, PETSC_ERR_ARG_WRONG,
"ComputeSpecificKE does not allow empty input/output field names.");
682 step_token = strtok_r(NULL,
";", &step_saveptr);
684 ierr = PetscFree(pipeline_copy); CHKERRQ(ierr);
689 PetscFunctionReturn(0);
693#define __FUNCT__ "GlobalStatisticsPipeline"
701 char *pipeline_copy, *step_token, *step_saveptr;
703 PetscFunctionBeginUser;
709 ierr = DMSwarmGetSize(user->
swarm, &n_global); CHKERRQ(ierr);
715 step_token = strtok_r(pipeline_copy,
";", &step_saveptr);
718 if (strlen(step_token) == 0) {
719 step_token = strtok_r(NULL,
";", &step_saveptr);
continue;
721 char *keyword = strtok(step_token,
":");
724 if (strcasecmp(keyword,
"ComputeMSD") == 0) {
728 "Unknown statistics keyword '%s'. Skipping.\n", keyword);
732 step_token = strtok_r(NULL,
";", &step_saveptr);
734 ierr = PetscFree(pipeline_copy); CHKERRQ(ierr);
738 PetscFunctionReturn(0);
742#define __FUNCT__ "WriteParticleFile"
754 PetscInt n_total_particles_before_subsample;
756 PetscFunctionBeginUser;
762 PetscFunctionReturn(0);
765 ierr = DMSwarmGetSize(user->
swarm, &n_global); CHKERRQ(ierr);
769 PetscFunctionReturn(0);
772 ierr = PetscMemzero(&part_meta,
sizeof(
VTKMetaData)); CHKERRQ(ierr);
780 LOG_ALLOW(
GLOBAL,
LOG_INFO,
"--- Starting VTP Particle File Writing for ti = %" PetscInt_FMT
" (writing %" PetscInt_FMT
" of %" PetscInt_FMT
" particles) ---\n",
781 ti, part_meta.
npoints, n_total_particles_before_subsample);
790 ierr = PetscSNPrintf(filename,
sizeof(filename),
"%s_%05" PetscInt_FMT
".vtp", pps->
particle_output_prefix, ti); CHKERRQ(ierr);
800 ierr = PetscFree(part_meta.
coords); CHKERRQ(ierr);
801 ierr = PetscFree(part_meta.
connectivity); CHKERRQ(ierr);
802 ierr = PetscFree(part_meta.
offsets); CHKERRQ(ierr);
807 PetscFunctionReturn(0);
811#define __FUNCT__ "main"
812#ifndef PICURV_POSTPROCESSOR_NO_MAIN
824 ierr = PetscInitialize(&argc, &argv, (
char *)0,
"Unified Post-Processing Tool"); CHKERRQ(ierr);
828 ierr = PetscPrintf(PETSC_COMM_WORLD,
"Postprocessor MPI processes: %d\n", (
int)simCtx->
size); CHKERRQ(ierr);
849 if(needs_particle_stage) {
855 SETERRQ(PETSC_COMM_SELF,1,
856 "Particle post-processing requested (particle output or particle statistics pipeline) "
857 "but np=0. Please set np>0 during solver run to enable particle post-processing.");
877 if(needs_particle_stage) {
901 if(simCtx->
rank == 0){
903 PetscReal currentTime = (PetscReal)ti*simCtx->
dt;
912 if (simCtx->
rank == 0) {
913 PetscInt endTime = pps->
endTime-1;
915 PetscReal endTimeValue = (PetscReal)pps->
endTime*simCtx->
dt;
917 PetscPrintf(PETSC_COMM_SELF,
"\n");
929 ierr = PetscFinalize();
PetscErrorCode PreCheckAndResizeSwarm(UserCtx *user, PetscInt ti, const char *ext)
Checks particle count in the reference file and resizes the swarm if needed.
PetscErrorCode InitializeParticleSwarm(SimCtx *simCtx)
High-level particle initialization orchestrator for a simulation run.
PetscErrorCode RegisterSwarmField(DM swarm, const char *fieldName, PetscInt fieldDim, PetscDataType dtype)
Registers a swarm field without finalizing registration.
PetscErrorCode ReadSimulationFields(UserCtx *user, PetscInt ti)
Reads binary field data for velocity, pressure, and other required vectors.
void TrimWhitespace(char *str)
Removes leading and trailing ASCII whitespace from a mutable string.
PetscErrorCode ReadAllSwarmFields(UserCtx *user, PetscInt ti)
Reads multiple fields (positions, velocity, CellID, and weight) into a DMSwarm.
PetscErrorCode RestoreFieldStatisticsState(SimCtx *simCtx, PetscInt ti)
Restores field-statistics window state and accumulators from a checkpoint.
PetscInt CreateVTKFileFromMetadata(const char *filename, const VTKMetaData *meta, MPI_Comm comm)
Creates a VTK file from prepared metadata and field payloads.
#define LOCAL
Logging scope definitions for controlling message output.
#define GLOBAL
Scope for global logging across all processes.
#define LOG_ALLOW(scope, level, fmt,...)
Logging macro that checks both the log level and whether the calling function is in the allowed-funct...
#define PROFILE_FUNCTION_END
Marks the end of a profiled code block.
PetscErrorCode ProfilingFinalize(SimCtx *simCtx)
the profiling excercise and build a profiling summary which is then printed to a log file.
#define LOG(scope, level, fmt,...)
Logging macro for PETSc-based applications with scope control.
void PrintProgressBar(PetscInt step, PetscInt startStep, PetscInt totalSteps, PetscReal currentTime)
Prints a progress bar to the console.
PetscErrorCode RuntimeMemoryLogSample(SimCtx *simCtx, PetscInt step, const char *event, const char *reason)
Append a reduced runtime memory sample to the configured memory log.
LogLevel get_log_level()
Retrieves the current logging level from the environment variable LOG_LEVEL.
@ LOG_ERROR
Critical errors that may halt the program.
@ LOG_INFO
Informational messages about program execution.
@ LOG_WARNING
Non-critical issues that warrant attention.
@ LOG_DEBUG
Detailed debugging information.
#define PROFILE_FUNCTION_BEGIN
Marks the beginning of a profiled code block (typically a function).
PetscErrorCode ComputeParticleMSD(UserCtx *user, const char *stats_prefix, PetscInt ti)
Computes the mean-squared displacement (MSD) of a particle cloud.
PetscErrorCode ComputeQCriterion(UserCtx *user)
Computes the Q-criterion diagnostic from the local velocity-gradient tensor.
PetscErrorCode ComputeSpecificKE(UserCtx *user, const char *velocity_field, const char *ske_field)
Computes the specific kinetic energy (KE per unit mass) for each particle.
PetscErrorCode NormalizeRelativeField(UserCtx *user, const char *relative_field_name)
Normalizes pressure using the value at the configured logical grid point.
PetscErrorCode ComputeWindowStatisticsSummary(UserCtx *user, PetscInt window_index, const char *output_prefix, PetscInt ti)
Appends one convergence row for an accumulated window to its CSV history.
PetscErrorCode DimensionalizeAllLoadedFields(UserCtx *user)
Orchestrates the dimensionalization of all relevant fields loaded from a file.
PetscErrorCode ComputeNodalAverage(UserCtx *user, const char *in_field_name, const char *out_field_name)
Interpolates a cell-centered field to nodal locations using local stencil averaging.
PetscErrorCode ComputeWindowStatisticNodal(UserCtx *user, PetscInt window_index, const char *outputs, PetscInt output_index, char *out_name, size_t name_size, Vec *out_vec, PetscInt *out_components)
Derives one accumulated statistic and converts it to nodal values.
PetscErrorCode EulerianDataProcessingPipeline(UserCtx *user, PostProcessParams *pps)
Implementation of EulerianDataProcessingPipeline().
PetscErrorCode WriteEulerianFile(UserCtx *user, PostProcessParams *pps, PetscInt ti)
Implementation of WriteEulerianFile().
PetscErrorCode GlobalStatisticsPipeline(UserCtx *user, PostProcessParams *pps, PetscInt ti)
Internal helper implementation: GlobalStatisticsPipeline().
int main(int argc, char **argv)
Entry point for the postprocessor executable.
PetscErrorCode ParticleDataProcessingPipeline(UserCtx *user, PostProcessParams *pps)
Implementation of ParticleDataProcessingPipeline().
PetscErrorCode WriteParticleFile(UserCtx *user, PostProcessParams *pps, PetscInt ti)
Implementation of WriteParticleFile().
PetscErrorCode FieldStatisticsPipeline(UserCtx *user, PostProcessParams *pps, PetscInt ti)
Implementation of FieldStatisticsPipeline().
PetscErrorCode SetupPostProcessSwarm(UserCtx *user, PostProcessParams *pps)
Internal helper implementation: SetupPostProcessSwarm().
PetscErrorCode SetupDomainRankInfo(SimCtx *simCtx)
Sets up the full rank communication infrastructure, including neighbor ranks and bounding box exchang...
PetscErrorCode SetupGridAndSolvers(SimCtx *simCtx)
The main orchestrator for setting up all grid-related components.
PetscErrorCode SetupSimulationEnvironment(SimCtx *simCtx)
Verifies and prepares the complete I/O environment for a simulation run.
PetscErrorCode CreateSimulationContext(int argc, char **argv, SimCtx **p_simCtx)
Allocates and populates the master SimulationContext object.
PetscErrorCode SetupBoundaryConditions(SimCtx *simCtx)
(Orchestrator) Sets up all boundary conditions for the simulation.
PetscErrorCode FinalizeSimulation(SimCtx *simCtx)
Main cleanup function for the entire simulation context.
Per-window PETSc accumulator storage and pointwise application.
PetscErrorCode PicurvWindowDerivedCount(const PicurvWindowDefinition *definition, const PicurvWindowStorage *storage, const char *outputs, PetscInt *count)
Reports how many derived fields a requested output set produces.
Window lifecycle, scheduling, and weighting for the field-statistics pipeline.
PicurvWindowDefinition definition
PetscBool FieldStatisticsIsActive(const struct SimCtx *simCtx)
Reports whether this run has live field-statistics state.
Runtime state of one window.
PetscInt fieldStatisticsWindowCount
char statistics_output_prefix[256]
basename for CSV output, e.g.
char particle_output_prefix[256]
PetscInt num_point_data_fields
SimCtx * simCtx
Back-pointer to the master simulation context.
#define MAX_FIELD_LIST_LENGTH
#define MAX_FILENAME_LENGTH
char statistics_pipeline[1024]
e.g.
char field_statistics_formats[1024]
Comma-separated formats: vtk for derived fields, csv for the convergence history.
char output_fields_instantaneous[1024]
struct PicurvWindow * fieldStatisticsWindows
char particle_pipeline[1024]
char process_pipeline[1024]
char particle_fields[1024]
PetscBool outputParticles
VTKFieldInfo point_data_fields[20]
struct PicurvWindowStorage * fieldStatisticsStorage
@ EXEC_MODE_POSTPROCESSOR
PetscInt field_statistics_source_step
Committed step supplying the state; negative means the step being processed.
char field_statistics_windows[1024]
Comma-separated window names to derive; empty disables the pipeline.
char field_statistics_outputs[1024]
Comma-separated outputs: mean, reynolds_stress, rms, tke, flux.
#define MAX_VTK_FIELD_NAME_LENGTH
Maximum length for VTK field names.
PetscBool fieldStatisticsContinue
Holds all configuration parameters for a post-processing run.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.
PetscErrorCode FinishStructuredVTKOutput(VTKMetaData *meta, const char *filename)
Writes an assembled structured VTK file and releases its buffers.
PetscErrorCode BeginStructuredVTKOutput(UserCtx *user, VTKMetaData *meta)
Begins one structured VTK file: clears the metadata and builds its coordinates.
PetscErrorCode AppendStructuredVTKField(UserCtx *user, VTKMetaData *meta, const char *name, Vec field_vec, PetscInt components)
Adds one point-data field to a structured VTK file being assembled.
PetscErrorCode PrepareOutputParticleData(UserCtx *user, PostProcessParams *pps, VTKMetaData *meta, PetscInt *p_n_total)
Gathers, subsamples, and prepares all particle data for VTK output.