21 PetscBool exists = PETSC_FALSE;
23 PetscFunctionBeginUser;
24 PetscCall(PetscTestDirectory(path,
'r', &exists));
26 PetscFunctionReturn(0);
36 PetscFunctionBeginUser;
37 file = fopen(path,
"w");
38 PetscCheck(file != NULL, PETSC_COMM_SELF, PETSC_ERR_FILE_OPEN,
"Failed to open '%s' for writing.", path);
39 fputs(contents, file);
41 PetscFunctionReturn(0);
50 size_t control_path_len)
52 char bcs_path[PETSC_MAX_PATH_LEN];
53 char post_path[PETSC_MAX_PATH_LEN];
54 char output_dir[PETSC_MAX_PATH_LEN];
55 char log_dir[PETSC_MAX_PATH_LEN];
56 char control_buffer[8192];
58 PetscFunctionBeginUser;
60 PetscCall(PetscSNPrintf(bcs_path,
sizeof(bcs_path),
"%s/bcs.run", tmpdir));
61 PetscCall(PetscSNPrintf(post_path,
sizeof(post_path),
"%s/post.run", tmpdir));
62 PetscCall(PetscSNPrintf(output_dir,
sizeof(output_dir),
"%s/results", tmpdir));
63 PetscCall(PetscSNPrintf(log_dir,
sizeof(log_dir),
"%s/logs", tmpdir));
64 PetscCall(PetscSNPrintf(control_path, control_path_len,
"%s/test.control", tmpdir));
72 "-Zeta INLET constant_velocity vx=0.0 vy=0.0 vz=1.5\n"
73 "+Zeta OUTLET conservation\n"));
79 "output_particles = false\n"));
80 PetscCall(PetscSNPrintf(
82 sizeof(control_buffer),
92 "-profiling_timestep_mode off\n"
93 "-profiling_final_summary true\n"
94 "-postprocessing_config_file %s\n"
110 "-euler_field_source solve\n"
111 "-mom_solver_type DUALTIME_PICARD_RK4\n"
112 "-mom_dt_rk4_residual_norm_noise_allowance_factor 1.07\n"
113 "-mom_resid_atol 1.0e-8\n"
114 "-mom_resid_rtol 1.0e-3\n"
115 "-mom_nk_pic_monitor\n"
119 "-particle_console_output_freq 0\n"
126 "-allow_unsafe_log_dir true\n"
136 PetscFunctionReturn(0);
144 PetscFunctionBeginUser;
146 PetscFunctionReturn(0);
154 PetscFunctionBeginUser;
156 PetscFunctionReturn(0);
164 char control_path[PETSC_MAX_PATH_LEN];
167 PetscFunctionBeginUser;
168 PetscCall(PetscOptionsClear(NULL));
170 PetscCall(PetscOptionsSetValue(NULL,
"-control_file", control_path));
173 *simCtx_out = simCtx;
174 PetscFunctionReturn(0);
184 char tmpdir[PETSC_MAX_PATH_LEN];
186 PetscFunctionBeginUser;
189 PetscCall(
PicurvAssertBool((PetscBool)(user->
bbox.
min_coords.
x >= -2.0e-6),
"runtime fixture bbox xmin should stay inside normalized domain tolerance"));
190 PetscCall(
PicurvAssertBool((PetscBool)(user->
bbox.
max_coords.
x <= 1.0 + 2.0e-6),
"runtime fixture bbox xmax should stay inside normalized domain tolerance"));
191 PetscCall(
PicurvAssertBool((PetscBool)(user->
bbox.
max_coords.
y <= 1.0 + 2.0e-6),
"runtime fixture bbox ymax should stay inside normalized domain tolerance"));
192 PetscCall(
PicurvAssertBool((PetscBool)(user->
bbox.
max_coords.
z <= 1.0 + 2.0e-6),
"runtime fixture bbox zmax should stay inside normalized domain tolerance"));
193 PetscCall(
PicurvAssertBool((PetscBool)(simCtx->
bboxlist != NULL),
"runtime fixture should gather bboxlist through SetupDomainRankInfo"));
196 "runtime fixture rank bbox entry should include the local bbox extent"));
200 PetscFunctionReturn(0);
210 char tmpdir[PETSC_MAX_PATH_LEN];
211 char results_dir[PETSC_MAX_PATH_LEN];
212 char logs_dir[PETSC_MAX_PATH_LEN];
215 PetscFunctionBeginUser;
219 PetscCall(PetscSNPrintf(results_dir,
sizeof(results_dir),
"%s/results", tmpdir));
220 PetscCall(PetscSNPrintf(logs_dir,
sizeof(logs_dir),
"%s/logs", tmpdir));
221 PetscCall(
PicurvAssertBool((PetscBool)(user->
da != NULL),
"SetupGridAndSolvers should allocate da"));
222 PetscCall(
PicurvAssertBool((PetscBool)(user->
fda != NULL),
"SetupGridAndSolvers should allocate coordinate DM"));
228 PetscCall(
AssertDirectoryExists(results_dir,
"SetupSimulationEnvironment should create the output directory"));
229 PetscCall(
AssertDirectoryExists(logs_dir,
"SetupSimulationEnvironment should create the log directory"));
232 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Ucont, &ucont));
234 "InitializeEulerianState should seed a positive inlet-aligned interior field"));
236 "InitializeEulerianState should initialize a spatially consistent interior field"));
237 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Ucont, &ucont));
241 PetscFunctionReturn(0);
251 char tmpdir[PETSC_MAX_PATH_LEN];
253 PetscInt *cell_ids = NULL;
254 PetscInt *status = NULL;
256 PetscFunctionBeginUser;
263 PetscCall(
PicurvAssertBool((PetscBool)(user->
swarm != NULL),
"InitializeParticleSwarm should allocate the solver swarm"));
264 PetscCall(DMSwarmGetLocalSize(user->
swarm, &nlocal));
265 PetscCall(
PicurvAssertIntEqual(8, nlocal,
"single-rank lifecycle particle setup should own all seeded particles"));
267 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
268 PetscCall(DMSwarmGetField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
269 for (PetscInt p = 0; p < nlocal; ++p) {
270 PetscCall(
PicurvAssertBool((PetscBool)(cell_ids[3 * p + 0] >= 0),
"settled particles should have a valid i cell id"));
271 PetscCall(
PicurvAssertBool((PetscBool)(cell_ids[3 * p + 1] >= 0),
"settled particles should have a valid j cell id"));
272 PetscCall(
PicurvAssertBool((PetscBool)(cell_ids[3 * p + 2] >= 0),
"settled particles should have a valid k cell id"));
275 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_CellID", NULL, NULL, (
void **)&cell_ids));
276 PetscCall(DMSwarmRestoreField(user->
swarm,
"DMSwarm_location_status", NULL, NULL, (
void **)&status));
280 PetscFunctionReturn(0);
290 char tmpdir[PETSC_MAX_PATH_LEN];
291 char metrics_path[PETSC_MAX_PATH_LEN];
293 PetscFunctionBeginUser;
313 PetscCall(PetscSNPrintf(metrics_path,
sizeof(metrics_path),
"%s/results/analysis/metrics/scatter_metrics.csv", tmpdir));
315 "PerformInitializedParticleSetup should emit scatter_metrics.csv for a zero-step scalar verification run"));
317 "zero-step scalar verification setup should leave the swarm initialized"));
321 PetscFunctionReturn(0);
331 PetscRandom randx = NULL, randy = NULL, randz = NULL;
332 PetscRandom rand_i = NULL, rand_j = NULL, rand_k = NULL;
333 PetscScalar sample_x = 0.0, sample_i = 0.0;
334 PetscReal seconds = 0.0;
336 PetscFunctionBeginUser;
350 PetscCall(
PicurvAssertRealNear(12.5, seconds, 1.0e-12,
"RuntimeWalltimeGuardParsePositiveSeconds parsed value"));
352 PetscCall(PetscRandomGetValue(randx, &sample_x));
353 PetscCall(PetscRandomGetValue(rand_i, &sample_i));
354 PetscCall(
PicurvAssertBool((PetscBool)(PetscRealPart(sample_x) >= 0.0 && PetscRealPart(sample_x) <= 1.0),
355 "InitializeRandomGenerators should honor the configured bbox interval"));
356 PetscCall(
PicurvAssertBool((PetscBool)(PetscRealPart(sample_i) >= 0.0 && PetscRealPart(sample_i) <= 1.0),
357 "InitializeLogicalSpaceRNGs should generate logical coordinates in [0,1]"));
359 PetscCall(PetscRandomDestroy(&randx));
360 PetscCall(PetscRandomDestroy(&randy));
361 PetscCall(PetscRandomDestroy(&randz));
362 PetscCall(PetscRandomDestroy(&rand_i));
363 PetscCall(PetscRandomDestroy(&rand_j));
364 PetscCall(PetscRandomDestroy(&rand_k));
366 PetscFunctionReturn(0);
374 SimCtx *context_only = NULL;
376 char context_tmpdir[PETSC_MAX_PATH_LEN];
377 char grid_tmpdir[PETSC_MAX_PATH_LEN];
379 PetscFunctionBeginUser;
380 PetscCall(
BuildContextOnly(&context_only, context_tmpdir,
sizeof(context_tmpdir)));
381 PetscCall(
PicurvAssertBool((PetscBool)(context_only != NULL),
"CreateSimulationContext should allocate the top-level SimCtx"));
384 "deprecated RK4 selector should normalize to the Jameson solver enum"));
386 "deprecated RK4 residual-noise option should populate the Jameson control"));
388 "momentum absolute residual tolerance should be parsed"));
390 "momentum relative residual tolerance should be parsed"));
392 "Newton structured history monitor should be parsed"));
393 PetscCall(PetscOptionsClear(NULL));
401 "SetupGridAndSolvers should allocate baseline Eulerian vectors"));
404 PetscFunctionReturn(0);
417 Vec coordinates = NULL;
418 Vec local_coordinates = NULL;
419 PetscErrorCode unknown_name_ierr;
420 PetscErrorCode unavailable_view_ierr;
422 PetscFunctionBeginUser;
428 "catalog entry should retain its declared FieldId"));
431 "every field descriptor should have a canonical name"));
433 descriptor->
dof == 2 ||
434 descriptor->
dof == 3),
435 "every ghost-updatable catalog field should declare a supported dof"));
438 "every phase-one field should advertise ghost-update capability"));
441 "canonical field names should round-trip to their IDs"));
444 "FieldCanonicalName should return catalog-owned canonical text"));
449 "Nu_t compatibility alias should resolve case-insensitively"));
452 "CS compatibility alias should resolve case-insensitively"));
455 "diagnostic face-center name should resolve to the canonical field"));
459 "Ucont should retain component-staggered topology metadata"));
461 "Ucont should retain component-staggered ghost repair metadata"));
464 "Csi should retain I-face topology metadata"));
466 "Csi should retain I-face ghost repair metadata"));
469 "IAj should retain scalar face-field metadata"));
475 "P field view should bind the existing scalar DM and Vec pair"));
480 "Ucat field view should bind the existing vector DM and Vec pair"));
482 PetscCall(DMGetCoordinates(user->
da, &coordinates));
483 PetscCall(DMGetCoordinatesLocal(user->
da, &local_coordinates));
488 "coordinate field view should bind PETSc-owned coordinate vectors"));
490 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
491 unknown_name_ierr =
FieldIdFromName(
"NotARegisteredEulerianField", &parsed_id);
492 PetscCall(PetscPopErrorHandler());
494 "unknown field names should fail at the name-ingress boundary"));
496 "failed field-name resolution should return FIELD_ID_INVALID"));
498 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
500 PetscCall(PetscPopErrorHandler());
502 "catalogued optional fields without storage should report unavailable state"));
505 PetscFunctionReturn(0);
515 PetscErrorCode unknown_name_ierr;
517 PetscFunctionBeginUser;
521 "particle catalog entry should retain its declared ID"));
524 "every particle field should have a canonical DMSwarm name"));
527 "persistent particle fields should declare one or three components"));
530 "canonical particle field names should round-trip to their IDs"));
533 "ParticleFieldName should return catalog-owned PETSc text"));
538 "particle velocity alias should resolve case-insensitively"));
541 "migration-status output alias should resolve to the PETSc field"));
546 "Psi should advertise its active particle-to-Eulerian scatter"));
548 "particle Psi should target Eulerian Psi"));
551 "particle IDs should be marked as PETSc-managed"));
553 "particle IDs should retain 64-bit storage metadata"));
555 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
557 PetscCall(PetscPopErrorHandler());
559 "unknown particle names should fail at the text-ingress boundary"));
561 "failed particle name resolution should return the invalid ID"));
562 PetscFunctionReturn(0);
573 PetscFunctionBeginUser;
576 PetscCall(VecSet(user->
P, 4.25));
577 PetscCall(VecSet(user->
lP, -1.0));
580 "typed scalar ghost update should scatter P"));
582 PetscCall(VecSet(user->
Ucat, 7.5));
583 PetscCall(VecSet(user->
lUcat, -1.0));
586 "typed cell-vector ghost update should scatter Ucat"));
588 PetscCall(VecSet(user->
IAj, 2.0));
589 PetscCall(VecSet(user->
lIAj, -1.0));
592 "typed scalar face-field ghost update should scatter IAj"));
594 PetscCall(VecSet(user->
Ucont, 3.0));
595 PetscCall(VecSet(user->
lUcont, -1.0));
598 "typed component-staggered ghost update should scatter Ucont"));
601 PetscFunctionReturn(0);
622 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv setup lifecycle tests");
627 ierr =
PicurvRunTests(
"unit-setup", cases,
sizeof(cases) /
sizeof(cases[0]));
633 ierr = PetscFinalize();
Header file for Particle Swarm management functions.
PetscErrorCode InitializeParticleSwarm(SimCtx *simCtx)
High-level particle initialization orchestrator for a simulation run.
PetscErrorCode FieldIdFromName(const char *field_name, FieldId *field_id)
Resolve a user-facing field name once into its typed identity.
@ FIELD_CAPABILITY_GHOST_UPDATE
@ FIELD_SYNC_COMPONENT_STAGGERED
unsigned int capabilities
const char * FieldCanonicalName(FieldId field_id)
Return the canonical printable name for an ID.
PetscErrorCode FieldGetView(UserCtx *user, FieldId field_id, FieldView *view)
Resolve the existing DM and global/local vectors for one field.
@ FIELD_LAYOUT_COMPONENT_STAGGERED
const char * canonical_name
FieldSyncClass sync_class
PetscErrorCode FieldGetDescriptor(FieldId field_id, const FieldDescriptor **descriptor)
Return immutable metadata for a valid field identifier.
FieldId
Compile-time identity for a catalogued Eulerian field.
Immutable metadata for one field identity.
Non-owning runtime objects resolved for one field and UserCtx.
PetscErrorCode InitializeEulerianState(SimCtx *simCtx)
High-level orchestrator to set the complete initial state of the Eulerian solver.
const char * ParticleFieldName(ParticleFieldId field_id)
Return the canonical PETSc DMSwarm name for an ID.
ParticleFieldId
Compile-time identity for a persistent solver-particle field.
@ PARTICLE_FIELD_ID_LOCATION_STATUS
@ PARTICLE_FIELD_ID_COUNT
@ PARTICLE_FIELD_ID_INVALID
@ PARTICLE_FIELD_ID_VELOCITY
unsigned int capabilities
ParticleFieldRegistration registration
PetscErrorCode ParticleFieldIdFromName(const char *field_name, ParticleFieldId *field_id)
Resolve a canonical name or registered alias at a text-ingress boundary.
@ PARTICLE_FIELD_CAPABILITY_EULERIAN_SCATTER
@ PARTICLE_FIELD_REGISTRATION_PETSC
PetscErrorCode ParticleFieldGetDescriptor(ParticleFieldId field_id, const ParticleFieldDescriptor **descriptor)
Return immutable metadata for a valid particle field ID.
const char * canonical_name
FieldId eulerian_scatter_target
Immutable metadata for one persistent particle field.
PetscErrorCode PerformInitializedParticleSetup(SimCtx *simCtx)
Finalizes the simulation setup at t=0, ensuring a consistent state before time marching.
PetscErrorCode InitializeRandomGenerators(UserCtx *user, PetscRandom *randx, PetscRandom *randy, PetscRandom *randz)
Initializes random number generators for assigning particle properties.
PetscErrorCode SetupGridAndSolvers(SimCtx *simCtx)
The main orchestrator for setting up all grid-related components.
PetscErrorCode InitializeBrownianRNG(SimCtx *simCtx)
Initializes a single master RNG for time-stepping physics (Brownian motion).
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 InitializeLogicalSpaceRNGs(PetscRandom *rand_logic_i, PetscRandom *rand_logic_j, PetscRandom *rand_logic_k)
Initializes random number generators for logical space operations [0.0, 1.0).
PetscErrorCode UpdateLocalGhosts(UserCtx *user, FieldId field_id)
Updates the local vector (including ghost points) from its corresponding global vector.
PetscBool RuntimeWalltimeGuardParsePositiveSeconds(const char *text, PetscReal *seconds_out)
Parse a positive floating-point seconds value from runtime metadata.
static PetscErrorCode TestParticleFieldCatalogMetadata(void)
Verifies the separate DMSwarm field catalog and its Eulerian bridge metadata.
static PetscErrorCode BuildContextOnly(SimCtx **simCtx_out, char *tmpdir, size_t tmpdir_len)
Builds only the top-level simulation context used by partial-initialization cleanup tests.
static PetscErrorCode PrepareContextOnlyConfig(char *tmpdir, size_t tmpdir_len, char *control_path, size_t control_path_len)
Creates the control-file bundle needed for the context-only cleanup test.
int main(int argc, char **argv)
Runs the unit-setup PETSc test binary.
static PetscErrorCode AssertDirectoryExists(const char *path, const char *context)
Asserts that a directory path exists and is readable.
static PetscErrorCode TestSetupLifecycleScatterMetricsAtStepZero(void)
Tests that step-zero scalar verification emits scatter_metrics.csv during initialized setup.
static PetscErrorCode TestFieldCatalogMetadataAndViews(void)
Verifies catalog completeness, stable name resolution, and runtime view binding.
static PetscErrorCode TestSetupLifecycleRandomGeneratorsAndCleanup(void)
Tests standalone RNG initialization helpers and minimal-context cleanup.
static PetscErrorCode WriteContextOnlyFile(const char *path, const char *contents)
Writes one small temporary text file used by the partial-lifecycle context-only fixture.
static PetscErrorCode BuildLifecycleContext(PetscBool enable_particles, SimCtx **simCtx_out, char *tmpdir, size_t tmpdir_len)
Builds a full setup fixture through environment, grid, BC, and domain-rank initialization.
static PetscErrorCode FreeLifecycleContext(SimCtx **simCtx_ptr)
Finalizes and frees one lifecycle test context, then clears any PETSc options used to build it.
static PetscErrorCode TestSetupLifecycleParticleInitialization(void)
Tests particle-swarm initialization and deterministic settlement on a tiny fully initialized case.
static PetscErrorCode TestSetupLifecycleCoreSolverSetup(void)
Tests the core setup lifecycle through environment, grid, BC, rank-info, and Eulerian-state initializ...
static PetscErrorCode TestSharedRuntimeFixtureContracts(void)
Tests that the shared richer runtime fixture mirrors normalized production setup contracts.
static PetscErrorCode TestFieldCatalogTypedGhostUpdates(void)
Verifies typed ghost updates preserve scalar, vector, face, and staggered behavior.
static PetscErrorCode TestSetupLifecycleCleanupAcrossInitializationStates(void)
Tests cleanup after partial and fuller setup states without requiring unsupported double-finalization...
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 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 PicurvDestroyRuntimeContext(SimCtx **simCtx_ptr)
Finalizes and frees a runtime context built by PicurvBuildTinyRuntimeContext.
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 PicurvBuildTinyRuntimeContext(const char *bcs_contents, PetscBool enable_particles, SimCtx **simCtx_out, UserCtx **user_out, char *tmpdir, size_t tmpdir_len)
Builds a tiny runtime context through the real setup path for behavior-level tests.
PetscErrorCode PicurvAssertFileExists(const char *path, const char *context)
Asserts that a filesystem path exists as a readable file.
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 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.
Shared declarations for the PICurv C test fixture and assertion layer.
Named test case descriptor consumed by PicurvRunTests.
PetscBool mom_nk_monitor_history
PetscBool inletFaceDefined
BCFace identifiedInletBCFace
Cmpnts max_coords
Maximum x, y, z coordinates of the bounding box.
Cmpnts min_coords
Minimum x, y, z coordinates of the bounding box.
@ MOMENTUM_SOLVER_DUALTIME_PICARD_JAMESON_RK
RankCellInfo * RankCellInfoMap
VerificationScalarConfig verificationScalar
char eulerianSource[PETSC_MAX_PATH_LEN]
PetscReal mom_dt_jameson_residual_norm_noise_allowance_factor
char AnalyticalSolutionType[PETSC_MAX_PATH_LEN]
PetscRandom BrownianMotionRNG
MomentumSolverType mom_solver_type
A 3D point or vector with PetscScalar components.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.