20 PetscScalar *coords = NULL;
21 PetscInt nx = 0, ny = 0, nz = 0, npoints = 0;
23 PetscFunctionBeginUser;
30 PetscCall(
PicurvAssertIntEqual(27, npoints,
"PrepareOutputCoordinates should output (IM-1)*(JM-1)*(KM-1) points"));
32 if (simCtx->
rank == 0) {
33 PetscCall(
PicurvAssertBool((PetscBool)(coords != NULL),
"PrepareOutputCoordinates should allocate coordinates on rank 0"));
34 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(coords[0]), 1.0e-12,
"First coordinate x should be 0"));
35 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(coords[1]), 1.0e-12,
"First coordinate y should be 0"));
36 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(coords[2]), 1.0e-12,
"First coordinate z should be 0"));
38 PetscCall(
PicurvAssertRealNear(2.0, PetscRealPart(coords[3 * (npoints - 1) + 0]), 1.0e-12,
"Last subsampled coordinate x should be IM-2"));
39 PetscCall(
PicurvAssertRealNear(2.0, PetscRealPart(coords[3 * (npoints - 1) + 1]), 1.0e-12,
"Last subsampled coordinate y should be JM-2"));
40 PetscCall(
PicurvAssertRealNear(2.0, PetscRealPart(coords[3 * (npoints - 1) + 2]), 1.0e-12,
"Last subsampled coordinate z should be KM-2"));
42 PetscCall(PetscFree(coords));
46 PetscFunctionReturn(0);
56 PetscScalar *field_out = NULL;
57 PetscInt start = 0, end = 0;
59 PetscFunctionBeginUser;
62 PetscCall(VecGetOwnershipRange(user->
P_nodal, &start, &end));
63 for (PetscInt idx = start; idx < end; ++idx) {
64 PetscCall(VecSetValue(user->
P_nodal, idx, (PetscScalar)idx, INSERT_VALUES));
66 PetscCall(VecAssemblyBegin(user->
P_nodal));
67 PetscCall(VecAssemblyEnd(user->
P_nodal));
70 if (simCtx->
rank == 0) {
72 "PrepareOutputEulerianFieldData should allocate subsampled data on rank 0"));
73 PetscCall(
PicurvAssertRealNear(0.0, PetscRealPart(field_out[0]), 1.0e-12,
"Subsampled first value should map to source index 0"));
75 "Subsampled last value should map to source index (2,2,2)=42 in 4x4x4"));
76 PetscCall(PetscFree(field_out));
80 PetscFunctionReturn(0);
93 PetscReal (*position)[3] = NULL;
94 PetscReal (*velocity)[3] = NULL;
96 PetscFunctionBeginUser;
97 PetscCall(PetscMemzero(&pps,
sizeof(pps)));
98 PetscCall(PetscMemzero(&meta,
sizeof(meta)));
105 PetscCall(DMSwarmGetField(user->
swarm,
"position", NULL, NULL, (
void *)&position));
106 PetscCall(DMSwarmGetField(user->
swarm,
"velocity", NULL, NULL, (
void *)&velocity));
107 for (PetscInt p = 0; p < 5; ++p) {
108 position[p][0] = (PetscReal)p;
109 position[p][1] = 0.0;
110 position[p][2] = 0.0;
111 velocity[p][0] = 10.0 + (PetscReal)p;
112 velocity[p][1] = 20.0 + (PetscReal)p;
113 velocity[p][2] = 30.0 + (PetscReal)p;
115 PetscCall(DMSwarmRestoreField(user->
swarm,
"position", NULL, NULL, (
void *)&position));
116 PetscCall(DMSwarmRestoreField(user->
swarm,
"velocity", NULL, NULL, (
void *)&velocity));
119 if (simCtx->
rank == 0) {
120 PetscCall(
PicurvAssertIntEqual(5, n_total,
"PrepareOutputParticleData should report total particles before subsampling"));
125 "Particle field name should propagate to VTK metadata"));
131 PetscCall(PetscFree(meta.
coords));
136 PetscCall(PetscFree(meta.
offsets));
140 PetscFunctionReturn(0);
148 char tmpdir[PETSC_MAX_PATH_LEN];
149 char vtk_path[PETSC_MAX_PATH_LEN];
155 PetscFunctionBeginUser;
156 PetscCall(PetscMemzero(&meta,
sizeof(meta)));
158 PetscCall(PetscSNPrintf(vtk_path,
sizeof(vtk_path),
"%s/field_00001.vts", tmpdir));
172 for (PetscInt p = 0; p < meta.
npoints; ++p) {
173 meta.
coords[3 * p + 0] = (PetscScalar)(p % 2);
174 meta.
coords[3 * p + 1] = (PetscScalar)((p / 2) % 2);
175 meta.
coords[3 * p + 2] = (PetscScalar)(p / 4);
182 file = fopen(vtk_path,
"rb");
183 PetscCheck(file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open generated VTK file '%s'.", vtk_path);
184 nread = fread(probe, 1,
sizeof(probe) - 1, file);
187 PetscCall(
PicurvAssertBool((PetscBool)(strstr(probe,
"StructuredGrid") != NULL),
188 "Generated VTK header should declare StructuredGrid type"));
190 PetscCall(PetscFree(meta.
coords));
192 PetscFunctionReturn(0);
208 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv VTK I/O tests");
213 ierr =
PicurvRunTests(
"unit-post-vtk", cases,
sizeof(cases) /
sizeof(cases[0]));
219 ierr = PetscFinalize();
PetscInt CreateVTKFileFromMetadata(const char *filename, const VTKMetaData *meta, MPI_Comm comm)
Implementation of CreateVTKFileFromMetadata().
PetscErrorCode PicurvMakeTempDir(char *path, size_t path_len)
Shared test-support routine.
PetscErrorCode PicurvCreateMinimalContexts(SimCtx **simCtx_out, UserCtx **user_out, PetscInt mx, PetscInt my, PetscInt mz)
Shared test-support routine.
PetscErrorCode PicurvAssertRealNear(PetscReal expected, PetscReal actual, PetscReal tol, const char *context)
Shared test-support routine.
PetscErrorCode PicurvDestroyMinimalContexts(SimCtx **simCtx_ptr, UserCtx **user_ptr)
Shared test-support routine.
PetscErrorCode PicurvCreateSwarmPair(UserCtx *user, PetscInt nlocal, const char *post_field_name)
Shared test-support routine.
PetscErrorCode PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
Shared test-support routine.
PetscErrorCode PicurvAssertFileExists(const char *path, const char *context)
Shared test-support routine.
PetscErrorCode PicurvAssertIntEqual(PetscInt expected, PetscInt actual, const char *context)
Shared test-support routine.
PetscErrorCode PicurvAssertBool(PetscBool value, const char *context)
Shared test-support routine.
C test module for PICurv.
Named test case descriptor consumed by PicurvRunTests.
static PetscErrorCode TestPrepareOutputEulerianFieldDataSubsamplesScalar(void)
Test-local routine.
static PetscErrorCode TestPrepareOutputParticleDataSubsampling(void)
Test-local routine.
int main(int argc, char **argv)
Entry point for this unit-test binary.
static PetscErrorCode TestCreateVTKFileFromMetadataWritesStructuredGrid(void)
Test-local routine.
static PetscErrorCode TestPrepareOutputCoordinatesSubsamplesInteriorGrid(void)
Test-local routine.
PetscInt num_point_data_fields
PetscInt particle_output_freq
char particle_fields[1024]
VTKFieldInfo point_data_fields[20]
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 PrepareOutputEulerianFieldData(UserCtx *user, Vec field_vec, PetscInt num_components, PetscScalar **out_data)
Creates a C array of field data corresponding to a subsampled (legacy-style) grid.
PetscErrorCode PrepareOutputCoordinates(UserCtx *user, PetscScalar **out_coords, PetscInt *out_nx, PetscInt *out_ny, PetscInt *out_nz, PetscInt *out_npoints)
Creates a C array of coordinates corresponding to a subsampled (legacy-style) grid.
PetscErrorCode PrepareOutputParticleData(UserCtx *user, PostProcessParams *pps, VTKMetaData *meta, PetscInt *p_n_total)
Gathers, subsamples, and prepares all particle data for VTK output.