PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
 
Loading...
Searching...
No Matches
Functions
test_statistics.c File Reference

C unit tests for particle statistics kernels and CSV output. More...

#include "test_support.h"
#include "particle_statistics.h"
#include <stdio.h>
#include <string.h>
Include dependency graph for test_statistics.c:

Go to the source code of this file.

Functions

static PetscErrorCode TestComputeParticleMSDWritesCSV (void)
 Tests MSD CSV generation for a populated particle swarm.
 
static PetscErrorCode TestComputeParticleMSDDimensionalizedColumns (void)
 Tests that a dimensionalizing post-processor reports MSD columns physically.
 
static PetscErrorCode TestComputeParticleMSDEmptySwarmNoOutput (void)
 Tests that empty swarms do not emit MSD CSV output.
 
int main (int argc, char **argv)
 Runs the unit-post-statistics PETSc test binary.
 

Detailed Description

C unit tests for particle statistics kernels and CSV output.

Definition in file test_statistics.c.

Function Documentation

◆ TestComputeParticleMSDWritesCSV()

static PetscErrorCode TestComputeParticleMSDWritesCSV ( void  )
static

Tests MSD CSV generation for a populated particle swarm.

Definition at line 16 of file test_statistics.c.

17{
18 SimCtx *simCtx = NULL;
19 UserCtx *user = NULL;
20 char tmpdir[PETSC_MAX_PATH_LEN];
21 char csv_prefix[PETSC_MAX_PATH_LEN];
22 char csv_path[PETSC_MAX_PATH_LEN];
23 FILE *file = NULL;
24 char header[512];
25 char row[512];
26 PetscReal (*pos_arr)[3] = NULL;
27
28 PetscFunctionBeginUser;
29 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
30 PetscCall(PicurvCreateSwarmPair(user, 2, "ske"));
31 simCtx->dt = 1.0;
32 simCtx->ren = 1.0;
33 simCtx->schmidt_number = 1.0;
34 simCtx->psrc_x = 0.0;
35 simCtx->psrc_y = 0.0;
36 simCtx->psrc_z = 0.0;
37
38 PetscCall(PicurvMakeTempDir(tmpdir, sizeof(tmpdir)));
39 PetscCall(PetscSNPrintf(csv_prefix, sizeof(csv_prefix), "%s/stats", tmpdir));
40 PetscCall(PetscSNPrintf(csv_path, sizeof(csv_path), "%s_msd.csv", csv_prefix));
41
42 PetscCall(DMSwarmGetField(user->swarm, "position", NULL, NULL, (void *)&pos_arr));
43 pos_arr[0][0] = 1.0;
44 pos_arr[0][1] = 0.0;
45 pos_arr[0][2] = 0.0;
46 pos_arr[1][0] = -1.0;
47 pos_arr[1][1] = 0.0;
48 pos_arr[1][2] = 0.0;
49 PetscCall(DMSwarmRestoreField(user->swarm, "position", NULL, NULL, (void *)&pos_arr));
50
51 PetscCall(ComputeParticleMSD(user, csv_prefix, 1));
52 PetscCall(PicurvAssertFileExists(csv_path, "ComputeParticleMSD should emit a CSV summary"));
53
54 file = fopen(csv_path, "r");
55 PetscCheck(file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Failed to open generated stats CSV '%s'.", csv_path);
56 PetscCheck(fgets(header, sizeof(header), file) != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "CSV header is missing.");
57 PetscCheck(fgets(row, sizeof(row), file) != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "CSV data row is missing.");
58 fclose(file);
59
60 PetscCall(PicurvAssertBool((PetscBool)(strstr(header, "MSD_total") != NULL),
61 "MSD CSV header should contain MSD_total"));
62 PetscCall(PicurvAssertBool((PetscBool)(strstr(row, "2") != NULL),
63 "MSD CSV row should include the particle count"));
64
65 PetscCall(PicurvRemoveTempDir(tmpdir));
66 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
67 PetscFunctionReturn(0);
68}
PetscErrorCode ComputeParticleMSD(UserCtx *user, const char *stats_prefix, PetscInt ti)
Computes the mean-squared displacement (MSD) of a particle cloud.
PetscErrorCode PicurvMakeTempDir(char *path, size_t path_len)
Creates a unique temporary directory for one test case.
PetscErrorCode PicurvCreateMinimalContexts(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz)
Builds minimal SimCtx and UserCtx fixtures for C unit tests.
PetscErrorCode PicurvDestroyMinimalContexts(SimCtx **simCtx_ptr, UserCtx **user_ptr)
Destroys minimal SimCtx/UserCtx fixtures and all owned PETSc objects.
PetscErrorCode PicurvCreateSwarmPair(UserCtx *user, PetscInt nlocal, const char *post_field_name)
Creates matched solver and post-processing swarms for tests.
PetscErrorCode PicurvAssertFileExists(const char *path, const char *context)
Asserts that a filesystem path exists as a readable file.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
PetscErrorCode PicurvRemoveTempDir(const char *path)
Recursively removes a temporary directory created by PicurvMakeTempDir.
PetscReal schmidt_number
Definition variables.h:948
PetscReal psrc_x
Definition variables.h:945
PetscReal ren
Definition variables.h:906
PetscReal dt
Definition variables.h:874
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
Definition variables.h:945
PetscReal psrc_y
Definition variables.h:945
The master context for the entire simulation.
Definition variables.h:859
User-defined context containing data specific to a single computational grid level.
Definition variables.h:1074
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestComputeParticleMSDDimensionalizedColumns()

static PetscErrorCode TestComputeParticleMSDDimensionalizedColumns ( void  )
static

Tests that a dimensionalizing post-processor reports MSD columns physically.

Two particles at x = +/-1 (solver units) about the origin, step 1, dt = 1. At L = 2 and U = 4 the time column is scaled by L/U = 0.5, MSD by L^2 = 4, and the RMS radius and centre of mass by L; the relative error is unchanged.

Definition at line 75 of file test_statistics.c.

76{
77 SimCtx *simCtx = NULL;
78 UserCtx *user = NULL;
79 char tmpdir[PETSC_MAX_PATH_LEN];
80 char csv_prefix[PETSC_MAX_PATH_LEN];
81 char csv_path[PETSC_MAX_PATH_LEN];
82 FILE *file = NULL;
83 char header[512];
84 int step = 0;
85 double values[15];
86 PetscReal (*pos_arr)[3] = NULL;
87
88 PetscFunctionBeginUser;
89 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
90 PetscCall(PicurvCreateSwarmPair(user, 2, "ske"));
91 PetscCall(PetscCalloc1(1, &simCtx->pps));
92 simCtx->pps->dimensionalize = PETSC_TRUE;
93 simCtx->scaling.L_ref = 2.0;
94 simCtx->scaling.U_ref = 4.0;
95 simCtx->scaling.rho_ref = 1.0;
96 simCtx->dt = 1.0;
97 simCtx->ren = 1.0;
98 simCtx->schmidt_number = 1.0;
99
100 PetscCall(PicurvMakeTempDir(tmpdir, sizeof(tmpdir)));
101 PetscCall(PetscSNPrintf(csv_prefix, sizeof(csv_prefix), "%s/stats", tmpdir));
102 PetscCall(PetscSNPrintf(csv_path, sizeof(csv_path), "%s_msd.csv", csv_prefix));
103 PetscCall(DMSwarmGetField(user->swarm, "position", NULL, NULL, (void *)&pos_arr));
104 pos_arr[0][0] = 1.0; pos_arr[0][1] = 0.0; pos_arr[0][2] = 0.0;
105 pos_arr[1][0] = -1.0; pos_arr[1][1] = 0.0; pos_arr[1][2] = 0.0;
106 PetscCall(DMSwarmRestoreField(user->swarm, "position", NULL, NULL, (void *)&pos_arr));
107
108 PetscCall(ComputeParticleMSD(user, csv_prefix, 1));
109 file = fopen(csv_path, "r");
110 PetscCheck(file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN, "Failed to open '%s'.", csv_path);
111 PetscCheck(fgets(header, sizeof(header), file) != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "CSV header is missing.");
112 PetscCheck(fscanf(file, "%d,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf,%lf", &step,
113 &values[0], &values[1], &values[2], &values[3], &values[4], &values[5], &values[6],
114 &values[7], &values[8], &values[9], &values[10], &values[11], &values[12],
115 &values[13], &values[14]) == 16,
116 PETSC_COMM_SELF, PETSC_ERR_FILE_READ, "MSD row has an unexpected layout.");
117 fclose(file);
118
119 /* Solver units: t = 1, MSD_x = 1, r = 1, r_theory = sqrt(6), com = 0. */
120 PetscCall(PicurvAssertRealNear(0.5, values[0], 1.0e-6, "time is scaled by L/U"));
121 PetscCall(PicurvAssertRealNear(4.0, values[2], 1.0e-6, "MSD_x is scaled by L^2"));
122 PetscCall(PicurvAssertRealNear(4.0, values[5], 1.0e-6, "MSD_total is scaled by L^2"));
123 PetscCall(PicurvAssertRealNear(2.0, values[6], 1.0e-6, "the RMS radius is scaled by L"));
124 PetscCall(PicurvAssertRealNear(2.0 * PetscSqrtReal(6.0), values[7], 1.0e-5, "the theory radius is scaled by L"));
125 PetscCall(PicurvAssertRealNear(100.0 * (PetscSqrtReal(6.0) - 1.0) / PetscSqrtReal(6.0), values[8], 1.0e-3,
126 "the relative error is the same in either unit system"));
127
128 PetscCall(PicurvRemoveTempDir(tmpdir));
129 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
130 PetscFunctionReturn(0);
131}
PetscErrorCode PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Asserts that two real values agree within tolerance.
PetscBool dimensionalize
Whether derived output leaves non-dimensional form, from global_operations.dimensionalize.
Definition variables.h:789
PetscReal L_ref
Definition variables.h:841
ScalingCtx scaling
Definition variables.h:946
PostProcessParams * pps
Definition variables.h:1058
PetscReal rho_ref
Definition variables.h:843
PetscReal U_ref
Definition variables.h:842
Here is the call graph for this function:
Here is the caller graph for this function:

◆ TestComputeParticleMSDEmptySwarmNoOutput()

static PetscErrorCode TestComputeParticleMSDEmptySwarmNoOutput ( void  )
static

Tests that empty swarms do not emit MSD CSV output.

Definition at line 136 of file test_statistics.c.

137{
138 SimCtx *simCtx = NULL;
139 UserCtx *user = NULL;
140 char tmpdir[PETSC_MAX_PATH_LEN];
141 char csv_prefix[PETSC_MAX_PATH_LEN];
142 char csv_path[PETSC_MAX_PATH_LEN];
143 PetscBool exists = PETSC_FALSE;
144
145 PetscFunctionBeginUser;
146 PetscCall(PicurvCreateMinimalContexts(&simCtx, &user, 4, 4, 4));
147 PetscCall(PicurvCreateSwarmPair(user, 0, "ske"));
148
149 PetscCall(PicurvMakeTempDir(tmpdir, sizeof(tmpdir)));
150 PetscCall(PetscSNPrintf(csv_prefix, sizeof(csv_prefix), "%s/stats", tmpdir));
151 PetscCall(PetscSNPrintf(csv_path, sizeof(csv_path), "%s_msd.csv", csv_prefix));
152
153 PetscCall(ComputeParticleMSD(user, csv_prefix, 5));
154 PetscCall(VerifyPathExistence(csv_path, PETSC_FALSE, PETSC_TRUE, "MSD CSV for empty swarm", &exists));
155 PetscCall(PicurvAssertBool((PetscBool)!exists,
156 "ComputeParticleMSD should not write output when no particles are present"));
157
158 PetscCall(PicurvRemoveTempDir(tmpdir));
159 PetscCall(PicurvDestroyMinimalContexts(&simCtx, &user));
160 PetscFunctionReturn(0);
161}
PetscErrorCode VerifyPathExistence(const char *path, PetscBool is_dir, PetscBool is_optional, const char *description, PetscBool *exists)
A parallel-safe helper to verify the existence of a generic file or directory path.
Definition io.c:1136
Here is the call graph for this function:
Here is the caller graph for this function:

◆ main()

int main ( int  argc,
char **  argv 
)

Runs the unit-post-statistics PETSc test binary.

Definition at line 166 of file test_statistics.c.

167{
168 PetscErrorCode ierr;
169 const PicurvTestCase cases[] = {
170 {"compute-particle-msd-writes-csv", TestComputeParticleMSDWritesCSV},
171 {"compute-particle-msd-dimensionalized-columns", TestComputeParticleMSDDimensionalizedColumns},
172 {"compute-particle-msd-empty-swarm-no-output", TestComputeParticleMSDEmptySwarmNoOutput},
173 };
174
175 ierr = PetscInitialize(&argc, &argv, NULL, "PICurv statistics tests");
176 if (ierr) {
177 return (int)ierr;
178 }
179
180 ierr = PicurvRunTests("unit-post-statistics", cases, sizeof(cases) / sizeof(cases[0]));
181 if (ierr) {
182 PetscFinalize();
183 return (int)ierr;
184 }
185
186 ierr = PetscFinalize();
187 return (int)ierr;
188}
static PetscErrorCode TestComputeParticleMSDEmptySwarmNoOutput(void)
Tests that empty swarms do not emit MSD CSV output.
static PetscErrorCode TestComputeParticleMSDWritesCSV(void)
Tests MSD CSV generation for a populated particle swarm.
static PetscErrorCode TestComputeParticleMSDDimensionalizedColumns(void)
Tests that a dimensionalizing post-processor reports MSD columns physically.
PetscErrorCode PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
Runs a named C test suite and prints pass/fail progress markers.
Named test case descriptor consumed by PicurvRunTests.
Here is the call graph for this function: