16 PetscFunctionBeginUser;
17 if (!bc_ptr || !*bc_ptr) PetscFunctionReturn(0);
23 PetscCall(PetscFree(bc));
25 PetscFunctionReturn(0);
35 PetscBool generic_face = PETSC_FALSE;
36 PetscBool inlet_face = PETSC_FALSE;
37 PetscBool any_face_serviceable = PETSC_FALSE;
39 PetscFunctionBeginUser;
45 any_face_serviceable = PETSC_TRUE;
51 PetscCall(
PicurvAssertBool((PetscBool)(inlet_face == generic_face),
"inlet face service check should match generic face check"));
53 PetscCall(
PicurvAssertBool(any_face_serviceable,
"at least one global face should be serviceable in a non-degenerate domain"));
56 PetscFunctionReturn(0);
66 PetscBool can_service = PETSC_FALSE;
68 PetscFunctionBeginUser;
75 PetscCall(
PicurvAssertBool((PetscBool)!can_service,
"undefined inlet face should not be serviceable"));
79 PetscFunctionReturn(0);
90 PetscFunctionBeginUser;
92 PetscCall(
PicurvAssertBool((PetscBool)(wall != NULL),
"factory should return wall handler"));
95 PetscCall(
PicurvAssertBool((PetscBool)(wall->
Destroy == NULL),
"wall handler should not require destroy hook"));
99 PetscCall(
PicurvAssertBool((PetscBool)(driven != NULL),
"factory should return driven periodic handler"));
103 PetscCall(
PicurvAssertBool((PetscBool)(driven->
Apply != NULL),
"driven handler should expose Apply"));
107 PetscFunctionReturn(0);
115 struct HandlerExpectation {
118 PetscBool expect_apply;
119 PetscBool expect_initialize;
121 const struct HandlerExpectation expectations[] = {
130 PetscFunctionBeginUser;
131 for (
size_t i = 0; i <
sizeof(expectations) /
sizeof(expectations[0]); ++i) {
134 PetscCall(
PicurvAssertBool((PetscBool)(bc != NULL),
"factory should allocate a handler object"));
136 PetscCall(
PicurvAssertBool((PetscBool)((bc->
Apply != NULL) == expectations[i].expect_apply),
"Apply hook expectation mismatch"));
137 PetscCall(
PicurvAssertBool((PetscBool)((bc->
Initialize != NULL) == expectations[i].expect_initialize),
"Initialize hook expectation mismatch"));
140 PetscFunctionReturn(0);
149 PetscErrorCode ierr_create;
151 PetscFunctionBeginUser;
152 PetscCall(PetscPushErrorHandler(PetscIgnoreErrorHandler, NULL));
154 PetscCall(PetscPopErrorHandler());
156 PetscCall(
PicurvAssertBool((PetscBool)(ierr_create != 0),
"unsupported handler should return a non-zero error code"));
158 PetscCall(PetscFree(bc));
160 PetscFunctionReturn(0);
171 PetscFunctionBeginUser;
176 PetscInt ci = -1, cj = -1, ck = -1;
177 PetscReal xi = -1.0, eta = -1.0, zta = -1.0;
178 PetscBool placed = PETSC_FALSE;
186 &ci, &cj, &ck, &xi, &eta, &zta, &placed));
188 PetscCall(
PicurvAssertBool(placed,
"single-rank deterministic face placement should succeed"));
189 PetscCall(
PicurvAssertBool((PetscBool)(ci >= user->
info.xs && ci < user->info.xs + user->
info.xm),
"ci must map to owned node window"));
190 PetscCall(
PicurvAssertBool((PetscBool)(cj >= user->
info.ys && cj < user->info.ys + user->
info.ym),
"cj must map to owned node window"));
191 PetscCall(
PicurvAssertBool((PetscBool)(ck >= user->
info.zs && ck < user->info.zs + user->
info.zm),
"ck must map to owned node window"));
192 PetscCall(
PicurvAssertBool((PetscBool)(xi >= 0.0 && xi < 1.0),
"xi should be in [0,1)"));
193 PetscCall(
PicurvAssertBool((PetscBool)(eta >= 0.0 && eta < 1.0),
"eta should be in [0,1)"));
194 PetscCall(
PicurvAssertBool((PetscBool)(zta >= 0.0 && zta < 1.0),
"zta should be in [0,1)"));
197 PetscCall(
PicurvAssertRealNear(0.5, xi, 1.0e-10,
"deterministic x-face placement should sit halfway into boundary-adjacent cell"));
199 PetscCall(
PicurvAssertRealNear(0.5, eta, 1.0e-10,
"deterministic y-face placement should sit halfway into boundary-adjacent cell"));
201 PetscCall(
PicurvAssertRealNear(0.5, zta, 1.0e-10,
"deterministic z-face placement should sit halfway into boundary-adjacent cell"));
206 PetscFunctionReturn(0);
216 PetscRandom rand_i = NULL, rand_j = NULL, rand_k = NULL;
218 PetscFunctionBeginUser;
221 PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rand_i));
222 PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rand_j));
223 PetscCall(PetscRandomCreate(PETSC_COMM_WORLD, &rand_k));
224 PetscCall(PetscRandomSetInterval(rand_i, 0.0, 1.0));
225 PetscCall(PetscRandomSetInterval(rand_j, 0.0, 1.0));
226 PetscCall(PetscRandomSetInterval(rand_k, 0.0, 1.0));
227 PetscCall(PetscRandomSetFromOptions(rand_i));
228 PetscCall(PetscRandomSetFromOptions(rand_j));
229 PetscCall(PetscRandomSetFromOptions(rand_k));
232 PetscInt ci = -1, cj = -1, ck = -1;
233 PetscReal xi = -1.0, eta = -1.0, zta = -1.0;
234 const PetscReal boundary_eps = 5.0e-4;
241 &rand_i, &rand_j, &rand_k,
245 PetscCall(
PicurvAssertBool((PetscBool)(ci >= user->
info.xs && ci < user->info.xs + user->
info.xm),
"ci must map to owned node window"));
246 PetscCall(
PicurvAssertBool((PetscBool)(cj >= user->
info.ys && cj < user->info.ys + user->
info.ym),
"cj must map to owned node window"));
247 PetscCall(
PicurvAssertBool((PetscBool)(ck >= user->
info.zs && ck < user->info.zs + user->
info.zm),
"ck must map to owned node window"));
248 PetscCall(
PicurvAssertBool((PetscBool)(xi >= 0.0 && xi <= 1.0),
"xi should be in [0,1]"));
249 PetscCall(
PicurvAssertBool((PetscBool)(eta >= 0.0 && eta <= 1.0),
"eta should be in [0,1]"));
250 PetscCall(
PicurvAssertBool((PetscBool)(zta >= 0.0 && zta <= 1.0),
"zta should be in [0,1]"));
254 PetscCall(
PicurvAssertBool((PetscBool)(xi <= boundary_eps),
"NEG_X should pin xi near 0"));
257 PetscCall(
PicurvAssertBool((PetscBool)(xi >= 1.0 - boundary_eps),
"POS_X should pin xi near 1"));
260 PetscCall(
PicurvAssertBool((PetscBool)(eta <= boundary_eps),
"NEG_Y should pin eta near 0"));
263 PetscCall(
PicurvAssertBool((PetscBool)(eta >= 1.0 - boundary_eps),
"POS_Y should pin eta near 1"));
266 PetscCall(
PicurvAssertBool((PetscBool)(zta <= boundary_eps),
"NEG_Z should pin zta near 0"));
269 PetscCall(
PicurvAssertBool((PetscBool)(zta >= 1.0 - boundary_eps),
"POS_Z should pin zta near 1"));
274 PetscCall(PetscRandomDestroy(&rand_i));
275 PetscCall(PetscRandomDestroy(&rand_j));
276 PetscCall(PetscRandomDestroy(&rand_k));
278 PetscFunctionReturn(0);
297 ierr = PetscInitialize(&argc, &argv, NULL,
"PICurv boundary tests");
302 ierr =
PicurvRunTests(
"unit-boundaries", cases,
sizeof(cases) /
sizeof(cases[0]));
308 ierr = PetscFinalize();
PetscErrorCode GetRandomCellAndLogicalCoordsOnInletFace(UserCtx *user, const DMDALocalInfo *info, PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr, PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out, PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out)
Assuming the current rank services the inlet face, this function selects a random cell (owned by this...
PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr)
(Private) Creates and configures a specific BoundaryCondition handler object.
PetscErrorCode CanRankServiceInletFace(UserCtx *user, const DMDALocalInfo *info, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, PetscBool *can_service_inlet_out)
Determines if the current MPI rank owns any part of the globally defined inlet face,...
PetscErrorCode CanRankServiceFace(const DMDALocalInfo *info, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global, BCFace face_id, PetscBool *can_service_out)
Determines if the current MPI rank owns any part of a specified global face.
PetscErrorCode GetDeterministicFaceGridLocation(UserCtx *user, const DMDALocalInfo *info, PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank, PetscInt IM_cells_global, PetscInt JM_cells_global, PetscInt KM_cells_global, PetscInt64 particle_global_id, PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out, PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out, PetscBool *placement_successful_out)
Places particles in a deterministic grid/raster pattern on a specified domain face.
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 PetscErrorCode TestCanRankServiceFaceMatchesInletWhenDefined(void)
Test-local routine.
static PetscErrorCode TestBoundaryConditionFactoryAssignments(void)
Test-local routine.
int main(int argc, char **argv)
Entry point for this unit-test binary.
static PetscErrorCode TestGetDeterministicFaceGridLocationFaceMatrix(void)
Test-local routine.
static PetscErrorCode TestBoundaryConditionFactoryRejectsUnsupportedHandler(void)
Test-local routine.
static PetscErrorCode TestGetRandomCellAndLogicalCoordsOnInletFaceMatrix(void)
Test-local routine.
static PetscErrorCode TestBoundaryConditionFactoryImplementedHandlerMatrix(void)
Test-local routine.
static PetscErrorCode TestCanRankServiceInletFaceRequiresDefinition(void)
Test-local routine.
static PetscErrorCode DestroyBoundaryHandler(BoundaryCondition **bc_ptr)
Test-local 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 PicurvRunTests(const char *suite_name, const PicurvTestCase *cases, size_t case_count)
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.
PetscBool inletFaceDefined
BCFace identifiedInletBCFace
BCHandlerType
Defines the specific computational "strategy" for a boundary handler.
@ BC_HANDLER_PERIODIC_GEOMETRIC
@ BC_HANDLER_INLET_PARABOLIC
@ BC_HANDLER_INLET_CONSTANT_VELOCITY
@ BC_HANDLER_PERIODIC_DRIVEN_CONSTANT_FLUX
@ BC_HANDLER_OUTLET_CONSERVATION
@ BC_HANDLER_OUTLET_PRESSURE
BCFace
Identifies the six logical faces of a structured computational block.
The master context for the entire simulation.
User-defined context containing data specific to a single computational grid level.