17 PetscReal (*vel_arr)[3] = NULL;
18 PetscScalar *ske_arr = NULL;
20 PetscFunctionBeginUser;
24 PetscCall(DMSwarmGetField(user->
swarm,
"velocity", NULL, NULL, (
void *)&vel_arr));
31 PetscCall(DMSwarmRestoreField(user->
swarm,
"velocity", NULL, NULL, (
void *)&vel_arr));
34 PetscCall(DMSwarmGetField(user->
post_swarm,
"ske", NULL, NULL, (
void *)&ske_arr));
37 PetscCall(DMSwarmRestoreField(user->
post_swarm,
"ske", NULL, NULL, (
void *)&ske_arr));
40 PetscFunctionReturn(0);
50 PetscReal (*pos_arr)[3] = NULL;
51 PetscScalar *disp_arr = NULL;
53 PetscFunctionBeginUser;
61 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void *)&pos_arr));
62 pos_arr[0][0] = 1.0; pos_arr[0][1] = 2.0; pos_arr[0][2] = 3.0;
63 pos_arr[1][0] = 4.0; pos_arr[1][1] = 6.0; pos_arr[1][2] = 3.0;
64 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void *)&pos_arr));
67 PetscCall(DMSwarmGetField(user->
post_swarm,
"disp", NULL, NULL, (
void *)&disp_arr));
68 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(disp_arr[0]), 1.0e-12,
"ComputeDisplacement first particle"));
69 PetscCall(
PicurvAssertRealNear(5.0, PetscRealPart(disp_arr[1]), 1.0e-12,
"ComputeDisplacement second particle"));
70 PetscCall(DMSwarmRestoreField(user->
post_swarm,
"disp", NULL, NULL, (
void *)&disp_arr));
73 PetscFunctionReturn(0);
83 const PetscScalar ***p_nodal_arr = NULL;
85 PetscFunctionBeginUser;
87 PetscCall(VecSet(user->
P, 7.0));
88 PetscCall(VecSet(user->
P_nodal, -1.0));
92 PetscCall(DMDAVecGetArrayRead(user->
da, user->
P_nodal, (
void *)&p_nodal_arr));
93 PetscCall(
PicurvAssertRealNear(7.0, PetscRealPart(p_nodal_arr[0][0][0]), 1.0e-12,
"ComputeNodalAverage interior node"));
95 "ComputeNodalAverage untouched non-physical boundary node"));
96 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
P_nodal, (
void *)&p_nodal_arr));
99 PetscFunctionReturn(0);
112 const PetscScalar ***q_nodal_arr = NULL;
114 PetscFunctionBeginUser;
116 PetscCall(VecSet(user->
Qcrit, 3.0));
121 PetscCall(DMDAVecGetArrayRead(user->
da, user->
Qcrit_nodal, (
void *)&q_nodal_arr));
123 "ComputeNodalAverage should average Qcrit onto nodes"));
124 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
Qcrit_nodal, (
void *)&q_nodal_arr));
127 PetscFunctionReturn(0);
137 PetscInt ref_idx = 0;
138 PetscScalar ref_value = 0.0;
139 PetscReal vmin = 0.0, vmax = 0.0;
141 PetscFunctionBeginUser;
143 PetscCall(PetscCalloc1(1, &simCtx->
pps));
148 PetscCall(VecSet(user->
P, 10.0));
152 PetscCall(VecSetValue(user->
P, ref_idx, 4.0, INSERT_VALUES));
153 PetscCall(VecAssemblyBegin(user->
P));
154 PetscCall(VecAssemblyEnd(user->
P));
158 PetscCall(VecGetValues(user->
P, 1, &ref_idx, &ref_value));
159 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(ref_value), 1.0e-12,
"NormalizeRelativeField reference value"));
160 PetscCall(VecMin(user->
P, NULL, &vmin));
161 PetscCall(VecMax(user->
P, NULL, &vmax));
166 PetscFunctionReturn(0);
177 PetscFunctionBeginUser;
184 PetscCall(VecSet(user->
P, 2.0));
189 PetscFunctionReturn(0);
201 PetscErrorCode refused = 0;
203 PetscFunctionBeginUser;
209 PetscCall(VecSet(user->
Ucat, 1.0));
210 PetscCall(VecSet(user->
Ucont, 1.0));
211 PetscCall(VecSet(user->
Phi, 1.0));
212 PetscCall(VecSet(user->
Nvert, 1.0));
223 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
225 PetscCall(PetscPopErrorHandler());
227 "an uncatalogued name is refused, not silently left unscaled"));
230 PetscFunctionReturn(0);
243 Vec nondimensional = NULL;
245 PetscReal difference = 0.0, reference = 0.0;
247 PetscFunctionBeginUser;
250 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucat, &ucat));
251 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; k++)
252 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; j++)
253 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; i++)
254 ucat[k][j][i] = (
Cmpnts){-(PetscReal)j, (PetscReal)i, 0.0};
255 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucat, &ucat));
258 PetscCall(VecDuplicate(user->
Qcrit, &nondimensional));
259 PetscCall(VecCopy(user->
Qcrit, nondimensional));
260 PetscCall(VecNorm(nondimensional, NORM_INFINITY, &reference));
261 PetscCall(
PicurvAssertBool((PetscBool)(reference > 0.1),
"a rotating field should have a positive Q"));
263 PetscCall(PetscNew(&pps));
268 PetscCall(VecAXPY(nondimensional, -4.0, user->
Qcrit));
269 PetscCall(VecNorm(nondimensional, NORM_INFINITY, &difference));
271 "dimensionalized Q must be the nondimensional Q over L_ref^2"));
274 PetscCall(PetscFree(pps));
275 PetscCall(VecDestroy(&nondimensional));
277 PetscFunctionReturn(0);
289 PetscFunctionBeginUser;
292 PetscCall(VecSet(user->
Aj, 1.0));
293 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
294 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
296 PetscCall(VecSet(user->
Ucat, 0.0));
297 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
298 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucat, INSERT_VALUES, user->
lUcat));
299 PetscCall(VecSet(user->
Nvert, 0.0));
300 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Nvert, INSERT_VALUES, user->
lNvert));
301 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Nvert, INSERT_VALUES, user->
lNvert));
307 PetscFunctionReturn(0);
328 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv post-processing tests");
333 ierr =
PicurvRunTests(
"unit-post", cases,
sizeof(cases) /
sizeof(cases[0]));
339 ierr = PetscFinalize();
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 ComputeDisplacement(UserCtx *user, const char *disp_field)
Computes the displacement magnitude |r_i - r_0| for each particle (per-particle VTK kernel).
PetscErrorCode NormalizeRelativeField(UserCtx *user, const char *relative_field_name)
Normalizes pressure using the value at the configured logical grid point.
PetscErrorCode DimensionalizeField(UserCtx *user, const char *field_name)
Scales a specified field from non-dimensional to dimensional units in-place.
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.
static PetscErrorCode TestComputeNodalAverageQcrit(void)
Tests that the cell-centred Q-criterion can be averaged to nodes.
int main(int argc, char **argv)
Runs the unit-post PETSc test binary.
static PetscErrorCode TestComputeQCriterionZeroFlow(void)
Tests Q-criterion computation for a quiescent velocity field.
static PetscErrorCode TestComputeSpecificKE(void)
Tests specific turbulent kinetic energy computation on particle data.
static PetscErrorCode TestComputeDisplacement(void)
Tests particle displacement computation against reference positions.
static PetscErrorCode TestDimensionalizeFieldUsesCatalogDimensions(void)
Tests that each field is scaled by the dimension its catalog entry records.
static PetscErrorCode TestComputeQCriterionDimensionalizedScalesByLengthSquared(void)
Tests that a dimensionalized Q-criterion carries (U_ref/L_ref)^2, not U_ref^2.
static PetscErrorCode TestDimensionalizePressureField(void)
Tests dimensionalization of pressure data from nondimensional values.
static PetscErrorCode TestComputeNodalAverageScalar(void)
Tests nodal averaging of scalar cell-centered data.
static PetscErrorCode TestNormalizeRelativeField(void)
Tests normalization of one field relative to a reference field.
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 PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Asserts that two real values agree within tolerance.
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 PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
Runs a named C test suite and prints pass/fail progress markers.
PetscErrorCode PicurvAssertVecConstant(Vec vec, PetscScalar expected, PetscReal tol, const char *context)
Asserts that a PETSc vector is spatially constant within tolerance.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Asserts that two integer values are equal.
PetscErrorCode PicurvPopulateIdentityMetrics(UserCtx *user)
Populates identity metric vectors on the minimal grid fixture.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Asserts that one boolean condition is true.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
Vec Qcrit_nodal
Q-criterion averaged to grid nodes; the field a .vts can place correctly.
PetscBool dimensionalize
Whether derived output leaves non-dimensional form, from global_operations.dimensionalize.
PetscReal psrc_z
Point source location for PARTICLE_INIT_POINT_SOURCE.
A 3D point or vector with PetscScalar components.
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.