18 PetscFunctionBeginUser;
19 PetscCheck(head != NULL, PETSC_COMM_SELF, PETSC_ERR_ARG_NULL,
"BC param list head cannot be NULL.");
20 PetscCall(PetscCalloc1(1, &
node));
21 PetscCall(PetscStrallocpy(key, &
node->key));
22 PetscCall(PetscStrallocpy(value, &
node->value));
24 cursor = &(*cursor)->
next;
27 PetscFunctionReturn(0);
36 PetscFunctionBeginUser;
37 if (!bc_ptr || !*bc_ptr) PetscFunctionReturn(0);
43 PetscCall(PetscFree(bc));
45 PetscFunctionReturn(0);
66 PetscFunctionBeginUser;
68 PetscCall(
PicurvAssertBool((PetscBool)(bc != NULL),
"periodic geometric factory should allocate a handler"));
70 PetscCall(
PicurvAssertBool((PetscBool)(bc->
Apply == NULL),
"periodic geometric handler should not expose Apply"));
73 PetscFunctionReturn(0);
83 PetscReal expected_neg_face = 0.0;
84 PetscReal expected_pos_face = 0.0;
85 PetscReal expected_neg_ghost = 0.0;
86 PetscReal expected_pos_ghost = 0.0;
88 PetscFunctionBeginUser;
92 PetscCall(DMDAVecGetArray(user->
fda, user->
Ucont, &ucont));
93 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
94 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
95 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
96 ucont[k][j][i].
x = (PetscReal)i;
97 ucont[k][j][i].
y = 10.0 + (PetscReal)i;
98 ucont[k][j][i].
z = 20.0 + (PetscReal)i;
102 PetscCall(DMDAVecRestoreArray(user->
fda, user->
Ucont, &ucont));
103 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
104 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
105 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
106 expected_neg_face = ucont[2][2][user->
info.mx - 2].
x;
107 expected_pos_face = ucont[2][2][1].
x;
108 expected_neg_ghost = ucont[2][2][user->
info.mx - 3].
x;
109 expected_pos_ghost = ucont[2][2][2].
x;
110 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
114 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
115 PetscCall(
PicurvAssertRealNear(expected_neg_face, ucont[2][2][0].x, 1.0e-12,
"NEG_X periodic face should copy from the opposite interior face"));
116 PetscCall(
PicurvAssertRealNear(expected_pos_face, ucont[2][2][user->
info.mx - 1].
x, 1.0e-12,
"POS_X periodic face should copy from the leading interior face"));
117 PetscCall(
PicurvAssertRealNear(expected_neg_ghost, ucont[2][2][-1].x, 1.0e-12,
"NEG_X ghost face should copy the second-to-last interior face"));
118 PetscCall(
PicurvAssertRealNear(expected_pos_ghost, ucont[2][2][user->
info.mx].
x, 1.0e-12,
"POS_X ghost face should copy the second interior face"));
119 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
122 PetscFunctionReturn(0);
131 PetscReal ***aj = NULL;
132 PetscReal expected_neg_face = 0.0;
133 PetscReal expected_pos_face = 0.0;
134 PetscReal expected_neg_ghost = 0.0;
135 PetscReal expected_pos_ghost = 0.0;
137 PetscFunctionBeginUser;
141 PetscCall(DMDAVecGetArray(user->
da, user->
Aj, &aj));
142 for (PetscInt k = user->
info.zs; k < user->
info.zs + user->
info.zm; ++k) {
143 for (PetscInt j = user->
info.ys; j < user->
info.ys + user->
info.ym; ++j) {
144 for (PetscInt i = user->
info.xs; i < user->
info.xs + user->
info.xm; ++i) {
145 aj[k][j][i] = 100.0 + (PetscReal)i;
149 PetscCall(DMDAVecRestoreArray(user->
da, user->
Aj, &aj));
150 PetscCall(DMGlobalToLocalBegin(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
151 PetscCall(DMGlobalToLocalEnd(user->
da, user->
Aj, INSERT_VALUES, user->
lAj));
152 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
153 expected_neg_face = aj[2][2][user->
info.mx - 2];
154 expected_pos_face = aj[2][2][1];
155 expected_neg_ghost = aj[2][2][user->
info.mx - 3];
156 expected_pos_ghost = aj[2][2][2];
157 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
161 PetscCall(DMDAVecGetArrayRead(user->
da, user->
lAj, &aj));
162 PetscCall(
PicurvAssertRealNear(expected_neg_face, aj[2][2][0], 1.0e-12,
"NEG_X periodic metric face should copy from the opposite interior face"));
163 PetscCall(
PicurvAssertRealNear(expected_pos_face, aj[2][2][user->
info.mx - 1], 1.0e-12,
"POS_X periodic metric face should copy from the leading interior face"));
164 PetscCall(
PicurvAssertRealNear(expected_neg_ghost, aj[2][2][-1], 1.0e-12,
"NEG_X periodic metric ghost should copy the second-to-last interior face"));
165 PetscCall(
PicurvAssertRealNear(expected_pos_ghost, aj[2][2][user->
info.mx], 1.0e-12,
"POS_X periodic metric ghost should copy the second interior face"));
166 PetscCall(DMDAVecRestoreArrayRead(user->
da, user->
lAj, &aj));
169 PetscFunctionReturn(0);
180 PetscReal dummy_inflow = 0.0;
181 PetscReal dummy_outflow = 0.0;
185 PetscFunctionBeginUser;
186 PetscCall(PetscMemzero(&ctx,
sizeof(ctx)));
189 PetscCall(VecSet(user->
Ucont, 1.0));
190 PetscCall(DMGlobalToLocalBegin(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
191 PetscCall(DMGlobalToLocalEnd(user->
fda, user->
Ucont, INSERT_VALUES, user->
lUcont));
206 PetscCall(bc->
PreStep(bc, &ctx, &dummy_inflow, &dummy_outflow));
210 PetscCall(bc->
Apply(bc, &ctx));
211 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
lUcont, &ucont));
212 PetscCall(DMDAVecGetArrayRead(user->
fda, user->
Bcs.
Uch, &uch));
213 PetscCall(
PicurvAssertRealNear(1.2, ucont[0][3][3].z, 1.0e-12,
"periodic driven trim should update the boundary face flux"));
214 PetscCall(
PicurvAssertRealNear(0.2, uch[0][3][3].z, 1.0e-12,
"periodic driven trim should be recorded in Uch"));
215 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
lUcont, &ucont));
216 PetscCall(DMDAVecRestoreArrayRead(user->
fda, user->
Bcs.
Uch, &uch));
222 PetscFunctionReturn(0);
233 PetscErrorCode ierr_init = 0;
235 PetscFunctionBeginUser;
236 PetscCall(PetscMemzero(&ctx,
sizeof(ctx)));
246 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
248 PetscCall(PetscPopErrorHandler());
249 PetscCall(
PicurvAssertBool((PetscBool)(ierr_init != 0),
"periodic driven initialization should reject non-periodic faces"));
255 PetscFunctionReturn(0);
271 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv periodic development tests");
276 ierr =
PicurvRunTests(
"unit-periodic-dev", cases,
sizeof(cases) /
sizeof(cases[0]));
282 ierr = PetscFinalize();
PetscErrorCode TransferPeriodicFaceField(UserCtx *user, const char *field_name)
(Primitive) Copies periodic data from the interior to the local ghost cell region for a single field.
PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user)
(Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundar...
PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr)
(Private) Creates and configures a specific BoundaryCondition handler object.
void FreeBC_ParamList(BC_Param *head)
Frees an entire linked list of boundary-condition parameters.
The "virtual table" struct for a boundary condition handler object.
PetscErrorCode(* PreStep)(BoundaryCondition *self, BCContext *ctx, PetscReal *local_inflow, PetscReal *local_outflow)
PetscErrorCode(* Destroy)(BoundaryCondition *self)
PetscErrorCode(* Initialize)(BoundaryCondition *self, BCContext *ctx)
PetscErrorCode(* Apply)(BoundaryCondition *self, BCContext *ctx)
static void MarkXPeriodic(UserCtx *user)
Marks the x faces as periodic for periodic-transfer harnesses.
static PetscErrorCode TestPeriodicDrivenConstantRejectsNonPeriodicFace(void)
Tests that the periodic driven handler rejects non-periodic faces during initialization.
static PetscErrorCode AppendBCParam(BC_Param **head, const char *key, const char *value)
Appends one key/value pair to a linked list of boundary-condition parameters.
static PetscErrorCode TestPeriodicGeometricFactoryAssignment(void)
Tests periodic geometric factory construction in the non-gating periodic harness.
int main(int argc, char **argv)
Runs the non-gating periodic development PETSc test binary.
static PetscErrorCode TestApplyMetricsPeriodicBCsCopiesAjFaces(void)
Tests periodic metric transfer through the aggregate periodic-metrics helper.
static PetscErrorCode DestroyBoundaryHandler(BoundaryCondition **bc_ptr)
Destroys one boundary-condition handler allocated by a periodic test.
static PetscErrorCode TestTransferPeriodicFaceFieldCopiesXFaces(void)
Tests direct periodic face transfer on the staggered velocity field.
static PetscErrorCode TestPeriodicDrivenConstantHandlerBehavior(void)
Tests periodic driven-flow controller initialization, sensing, and trim application.
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 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 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.
BoundaryFaceConfig boundary_faces[6]
PetscReal targetVolumetricFlux
@ BC_HANDLER_PERIODIC_GEOMETRIC
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
BCHandlerType handler_type
PetscReal bulkVelocityCorrection
Vec Uch
Characteristic velocity for boundary conditions.
Provides execution context for a boundary condition handler.
A node in a linked list for storing key-value parameters from the bcs.dat file.
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.
A generic C-style linked list node for integers.