PICurv 0.1.0
A Parallel Particle-In-Cell Solver for Curvilinear LES
Loading...
Searching...
No Matches
Boundaries.h
Go to the documentation of this file.
1#ifndef BOUNDARIES_H
2#define BOUNDARIES_H
3
4#include <petscpf.h>
5#include <petscdmswarm.h>
6#include <stdlib.h>
7#include <time.h>
8#include <math.h>
9#include <petsctime.h>
10#include <petscsys.h>
11#include <petscdmcomposite.h>
12#include <petscsystypes.h>
13
14// Include additional headers
15#include "variables.h" // Shared type definitions
16#include "field_catalog.h" // Typed Eulerian field identities
17#include "ParticleSwarm.h" // Particle swarm functions
18#include "walkingsearch.h" // Particle location functions
19#include "grid.h" // Grid functions
20#include "logging.h" // Logging macros
21#include "io.h" // Data Input and Output functions
22#include "interpolation.h" // Interpolation routines
23#include "ParticleMotion.h" // Functions related to motion of particles
24#include "BC_Handlers.h" // Boundary Handlers
25#include "wallfunction.h" // wall functions for LES
26//================================================================================
27//
28// PUBLIC SYSTEM-LEVEL FUNCTIONS
29//
30// These are the main entry points for interacting with the boundary system.
31//
32//================================================================================
33
34/**
35 * @brief (Public) Validates the consistency and compatibility of the parsed boundary condition system.
36 *
37 * This function is the main entry point for all boundary condition validation. It should be
38 * called from the main setup sequence AFTER the configuration file has been parsed by
39 * `ParseAllBoundaryConditions` but BEFORE any `BoundaryCondition` handler objects are created.
40 *
41 * It acts as a dispatcher, calling specialized private sub-validators for different complex
42 * BC setups (like driven flow) to ensure the combination of `mathematical_type` and `handler_type`
43 * across all six faces is physically and numerically valid. This provides a "fail-fast"
44 * mechanism to prevent users from running improperly configured simulations.
45 *
46 * @param user The UserCtx for a single block, containing the populated `boundary_faces` configuration.
47 * @return PetscErrorCode 0 on success, non-zero PETSc error code on failure.
48 */
49PetscErrorCode BoundarySystem_Validate(UserCtx *user);
50
51/**
52 * @brief (Private) Creates and configures a specific BoundaryCondition handler object.
53 *
54 * This function acts as a factory. Based on the requested handler_type, it allocates
55 * a BoundaryCondition object and populates it with the correct set of function
56 * pointers corresponding to that specific behavior.
57 *
58 * @param handler_type The specific handler to create (e.g., BC_HANDLER_WALL_NOSLIP).
59 * @param[out] new_bc_ptr A pointer to where the newly created BoundaryCondition
60 * object's address will be stored.
61 * @return PetscErrorCode 0 on success.
62 */
63
64PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr);
65
66/**
67 * @brief Initializes the entire boundary system.
68 *
69 * @param[in,out] user Finest-level block context receiving parsed face configuration.
70 * @param bcs_filename Path to the generated boundary-condition definition file.
71 * @return PetscErrorCode 0 on success.
72 */
73PetscErrorCode BoundarySystem_Initialize(UserCtx *user, const char *bcs_filename);
74
75/**
76 * @brief Propagates boundary condition configuration from finest to all coarser multigrid levels.
77 *
78 * Coarser levels need BC type information for geometric operations (e.g., periodic corrections)
79 * but do NOT need full handler objects since timestepping only occurs at the finest level.
80 * This function copies the boundary_faces configuration down the hierarchy.
81 *
82 * @param simCtx The master SimCtx containing the multigrid hierarchy
83 * @return PetscErrorCode 0 on success
84 */
86
87/**
88 * @brief Executes one full boundary condition update cycle for a time step.
89 *
90 * @param[in,out] user Block context whose boundary handlers update target values and fluxes.
91 * @return PetscErrorCode 0 on success.
92 */
93PetscErrorCode BoundarySystem_ExecuteStep(UserCtx *user);
94
95/**
96 * @brief (Private) A lightweight execution engine that calls the UpdateUbcs() method on all relevant handlers.
97 *
98 * This function's sole purpose is to re-evaluate the target boundary values (`ubcs`) for
99 * flow-dependent boundary conditions (e.g., Symmetry, Outlets) after the interior
100 * velocity field has changed, such as after the projection step.
101 *
102 * It operates based on a "pull" model: it iterates through all boundary handlers and
103 * executes their `UpdateUbcs` method only if the handler has provided one. This makes the
104 * system extensible, as new flow-dependent handlers can be added without changing this
105 * engine. Handlers for fixed boundary conditions (e.g., a wall with a constant velocity)
106 * will have their `UpdateUbcs` pointer set to `NULL` and will be skipped automatically.
107 *
108 * @note This function is a critical part of the post-projection refresh. It intentionally
109 * does NOT modify `ucont` and does NOT perform flux balancing.
110 *
111 * @param user The main UserCtx struct.
112 * @return PetscErrorCode 0 on success.
113 */
114PetscErrorCode BoundarySystem_RefreshUbcs(UserCtx *user);
115
116/**
117 * @brief Cleans up and destroys all boundary system resources.
118 *
119 * @param[in,out] user Block context whose boundary handlers and temporary state are released.
120 * @return PetscErrorCode 0 on success.
121 */
122PetscErrorCode BoundarySystem_Destroy(UserCtx *user);
123
124/**
125 * @brief Determines if the current MPI rank owns any part of the globally defined inlet face,
126 * making it responsible for placing particles on that portion of the surface.
127 *
128 * The determination is based on the rank's owned nodes (from `DMDALocalInfo`) and
129 * the global node counts, in conjunction with the `user->identifiedInletBCFace`.
130 * A rank can service an inlet face if it owns the cells adjacent to that global boundary
131 * and has a non-zero extent (owns cells) in the tangential dimensions of that face.
132 *
133 * @param user Pointer to the UserCtx structure, containing `identifiedInletBCFace`.
134 * @param info Pointer to the DMDALocalInfo for the current rank's DA (node-based).
135 * @param IM_nodes_global Global number of nodes in the I-direction (e.g., user->IM + 1 if user->IM is cell count).
136 * @param JM_nodes_global Global number of nodes in the J-direction.
137 * @param KM_nodes_global Global number of nodes in the K-direction.
138 * @param[out] can_service_inlet_out Pointer to a PetscBool; set to PETSC_TRUE if the rank
139 * services (part of) the inlet, PETSC_FALSE otherwise.
140 * @return PetscErrorCode 0 on success, non-zero on failure.
141 */
142PetscErrorCode CanRankServiceInletFace(UserCtx *user, const DMDALocalInfo *info,
143 PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global,
144 PetscBool *can_service_inlet_out);
145
146/**
147 * @brief Determines if the current MPI rank owns any part of a specified global face.
148 *
149 * This function is a general utility for parallel boundary operations. It checks if the
150 * local domain of the current MPI rank is adjacent to a specified global boundary face.
151 * A rank "services" a face if it owns the cells adjacent to that global boundary and has
152 * a non-zero extent (i.e., owns at least one cell) in the tangential dimensions of that face.
153 *
154 * @param info Pointer to the DMDALocalInfo for the current rank's DA.
155 * @param IM_nodes_global Global number of nodes in the I-direction (e.g., user->IM + 1 if user->IM is cell count).
156 * @param JM_nodes_global Global number of nodes in the J-direction.
157 * @param KM_nodes_global Global number of nodes in the K-direction.
158 * @param face_id The specific global face (e.g., BC_FACE_NEG_Z) to check.
159 * @param[out] can_service_out Pointer to a PetscBool; set to PETSC_TRUE if the rank
160 * services the face, PETSC_FALSE otherwise.
161 * @return PetscErrorCode 0 on success.
162 */
163PetscErrorCode CanRankServiceFace(const DMDALocalInfo *info, PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global,
164 BCFace face_id, PetscBool *can_service_out);
165
166/**
167 * @brief Places particles in a deterministic grid/raster pattern on a specified domain face.
168 *
169 * This function creates a set of equidistant, parallel lines of particles near the four
170 * edges of the face specified by user->identifiedInletBCFace. The number of lines drawn
171 * from each edge is hardcoded within this function (default is 2).
172 * For example, if grid_layers=2 on face BC_FACE_NEG_X, the function will create particle lines at:
173 * - y ~ 0*dy, y ~ 1*dy (parallel to the Z-axis, starting from the J=0 edge)
174 * - y ~ y_max, y ~ y_max-dy (parallel to the Z-axis, starting from the J=max edge)
175 * - z ~ 0*dz, z ~ 1*dz (parallel to the Y-axis, starting from the K=0 edge)
176 * - z ~ z_max, z ~ z_max-dz (parallel to the Y-axis, starting from the K=max edge)
177 * The particle's final position is set just inside the target cell face to ensure it is
178 * correctly located. The total number of particles (simCtx->np) is distributed as evenly
179 * as possible among all generated lines.
180 * The function includes extensive validation to stop with an error if the requested grid
181 * placement is geometrically impossible (e.g., in a 2D domain or if layers would overlap).
182 * It also issues warnings for non-fatal but potentially unintended configurations.
183 *
184 * @param user Inlet-boundary context that defines the target face and grid layers.
185 * @param info Local ownership and ghost-range information.
186 * @param xs_gnode_rank Global xi node index at this rank's owned lower corner.
187 * @param ys_gnode_rank Global eta node index at this rank's owned lower corner.
188 * @param zs_gnode_rank Global zeta node index at this rank's owned lower corner.
189 * @param IM_cells_global Global number of xi cells.
190 * @param JM_cells_global Global number of eta cells.
191 * @param KM_cells_global Global number of zeta cells.
192 * @param particle_global_id Global particle ordinal used for deterministic placement.
193 * @param[out] ci_metric_lnode_out Local xi metric-node index of the chosen cell.
194 * @param[out] cj_metric_lnode_out Local eta metric-node index of the chosen cell.
195 * @param[out] ck_metric_lnode_out Local zeta metric-node index of the chosen cell.
196 * @param[out] xi_metric_logic_out Logical xi coordinate within the chosen cell.
197 * @param[out] eta_metric_logic_out Logical eta coordinate within the chosen cell.
198 * @param[out] zta_metric_logic_out Logical zeta coordinate within the chosen cell.
199 * @param[out] placement_successful_out PETSC_TRUE when this rank owns a valid placement.
200 * @return PetscErrorCode 0 on success.
201 */
203 UserCtx *user, const DMDALocalInfo *info,
204 PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank,
205 PetscInt IM_cells_global, PetscInt JM_cells_global, PetscInt KM_cells_global,
206 PetscInt64 particle_global_id,
207 PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out,
208 PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out,
209 PetscBool *placement_successful_out);
210
211
212/**
213 * @brief Assuming the current rank services the inlet face, this function selects a random
214 * cell (owned by this rank on that face) and random logical coordinates within that cell,
215 * suitable for placing a particle on the inlet surface.
216 *
217 * It is the caller's responsibility to ensure CanRankServiceInletFace returned true.
218 *
219 * @param user Pointer to UserCtx.
220 * @param info Pointer to DMDALocalInfo for the current rank (node-based).
221 * @param xs_gnode_rank Local i-start node index (including ghosts) for this rank.
222 * @param ys_gnode_rank Local j-start node index (including ghosts) for this rank.
223 * @param zs_gnode_rank Local k-start node index (including ghosts) for this rank.
224 * @param IM_nodes_global Global node count in i.
225 * @param JM_nodes_global Global node count in j.
226 * @param KM_nodes_global Global node count in k.
227 * @param rand_logic_i_ptr RNG handle for sampling local logical xi.
228 * @param rand_logic_j_ptr RNG handle for sampling local logical eta.
229 * @param rand_logic_k_ptr RNG handle for sampling local logical zta.
230 * @param[out] ci_metric_lnode_out Local i node index of selected cell origin.
231 * @param[out] cj_metric_lnode_out Local j node index of selected cell origin.
232 * @param[out] ck_metric_lnode_out Local k node index of selected cell origin.
233 * @param[out] xi_metric_logic_out Logical xi coordinate in [0,1].
234 * @param[out] eta_metric_logic_out Logical eta coordinate in [0,1].
235 * @param[out] zta_metric_logic_out Logical zta coordinate in [0,1].
236 * @return PetscErrorCode
237 */
239 UserCtx *user, const DMDALocalInfo *info,
240 PetscInt xs_gnode_rank, PetscInt ys_gnode_rank, PetscInt zs_gnode_rank, // Local starting node index (with ghosts) of the rank's DA patch
241 PetscInt IM_nodes_global, PetscInt JM_nodes_global, PetscInt KM_nodes_global,
242 PetscRandom *rand_logic_i_ptr, PetscRandom *rand_logic_j_ptr, PetscRandom *rand_logic_k_ptr,
243 PetscInt *ci_metric_lnode_out, PetscInt *cj_metric_lnode_out, PetscInt *ck_metric_lnode_out,
244 PetscReal *xi_metric_logic_out, PetscReal *eta_metric_logic_out, PetscReal *zta_metric_logic_out);
245
246/**
247 * @brief Classification of one staggered momentum row (location + component).
248 *
249 * @see ClassifyMomentumRow() for the meaning of each member and for the
250 * single-source-of-truth contract these values participate in.
251 */
252typedef enum {
253 MOM_ROW_PHYSICAL = 0, /**< Independent unknown governed by the momentum equation. */
254 MOM_ROW_FIXED_CONDITIONED, /**< Strong Dirichlet row; the value comes from ApplyBoundaryConditions(). */
255 MOM_ROW_FIXED_HOMOGENEOUS, /**< Dummy/tangential row carrying no unknown at all. */
256 MOM_ROW_PERIODIC_DUPLICATE /**< Duplicate of a wrapped representative row (see @p ri, @p rj, @p rk). */
258
259/**
260 * @brief Single source of truth for "which staggered momentum rows are unknowns".
261 *
262 * Every consumer of the momentum system must agree on which rows the solver is
263 * responsible for, and every consumer must derive that answer from this function
264 * rather than restating the index arithmetic locally. Three independent
265 * restatements previously disagreed, and the disagreement was silent: the
266 * residual assembly skipped the periodic duplicate column at index 0 while
267 * nothing zeroed it, so `ComputeTotalResidual()`'s BDF term accumulated there
268 * without bound and the reported residual norm stopped describing the state.
269 *
270 * The classification depends only on @p user->info, the configured boundary
271 * types, and the queried index; it reads no field data and performs no
272 * communication, so it is safe to call inside assembly loops.
273 *
274 * Periodicity of an axis is taken from that axis's NEGATIVE face, matching
275 * `ComputeRHS()` and `TransferPeriodicStaggeredFieldByDirection()`. A periodic
276 * axis is expected to carry PERIODIC on both of its faces.
277 *
278 * Callers act on the classification differently, and both actions are correct:
279 * - residual/pseudo-time consumers (`EnforceRHSBoundaryConditions()`) zero
280 * every non-physical row, because the value there is imposed immediately
281 * afterwards by the boundary sweep or the periodic synchronisation;
282 * - the matrix-free Newton path substitutes an explicit equation instead
283 * (`F = X - U_conditioned`, `F = X`, `F = X_dup - X_rep`), because a zeroed
284 * row would leave a zero Jacobian row.
285 *
286 * @param[in] user Block context supplying `info` and `boundary_faces`.
287 * @param[in] i Location index along xi.
288 * @param[in] j Location index along eta.
289 * @param[in] k Location index along zeta.
290 * @param[in] component Staggered component of the row (0 = xi, 1 = eta, 2 = zeta).
291 * @param[out] ri Representative xi index; equals @p i unless the row wraps.
292 * @param[out] rj Representative eta index; equals @p j unless the row wraps.
293 * @param[out] rk Representative zeta index; equals @p k unless the row wraps.
294 * @return The row classification. Only #MOM_ROW_PHYSICAL denotes an unknown.
295 */
296MomentumRowType ClassifyMomentumRow(UserCtx *user, PetscInt i, PetscInt j, PetscInt k,
297 PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk);
298
299/**
300 * @brief Zeroes every momentum RHS row that does not carry an independent unknown.
301 *
302 * The set of such rows is not restated here: each owned location and component is
303 * asked of ClassifyMomentumRow(), and anything other than #MOM_ROW_PHYSICAL is
304 * zeroed. That covers, without enumerating them,
305 *
306 * - strong Dirichlet rows on non-periodic faces, so the time-stepping scheme
307 * cannot alter the values `ApplyBoundaryConditions()` has just set;
308 * - dummy layers at the far index of every axis, which hold no unknown; and
309 * - periodic duplicate columns, whose value the next
310 * `SynchronizePeriodicStaggeredFields()` copies from the wrapped master.
311 *
312 * The last case is the one that must not be skipped. `ComputeRHS()` leaves the
313 * transverse components of a periodic duplicate column untouched, so a row left
314 * unzeroed here retains its previous contents while `ComputeTotalResidual()`
315 * adds the BDF term on top of them on every call. The residual norm then grows
316 * by |dU|/dt per evaluation regardless of the state, and no pseudo-time
317 * iteration can reduce it.
318 *
319 * Call immediately after the RHS vector is fully assembled (spatial + temporal
320 * terms) and before it is used in a time-stepping update.
321 *
322 * @param user The UserCtx for the specific block being computed.
323 * @return PetscErrorCode 0 on success.
324 */
325PetscErrorCode EnforceRHSBoundaryConditions(UserCtx *user);
326
327/**
328 * @brief Synchronizes periodic endpoint cells for a list of cell-centered fields.
329 *
330 * The fields are first communicated from global to local storage. Each periodic
331 * direction is then transferred in i-j-k order, with an intermediate ghost
332 * refresh after every active direction so periodic edges and corners inherit the
333 * values established by earlier directions. Only global duplicate planes in active
334 * periodic directions are repaired; non-periodic directions are untouched. The
335 * routine is a no-op, including no local refresh, when every direction is
336 * nonperiodic. During active periodic synchronization it internally refreshes the
337 * local vectors, but it is not a general replacement for `UpdateLocalGhosts()`.
338 *
339 * Supported fields are selected by
340 * `FIELD_CAPABILITY_PERIODIC_CELL_SYNC` in the field catalog.
341 *
342 * @param user The main UserCtx struct.
343 * @param num_fields The number of entries in `field_ids`.
344 * @param field_ids The cell-centered fields to synchronize.
345 * @return PetscErrorCode 0 on success.
346 */
347PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[]);
348
349/**
350 * @brief Synchronizes persistent fields belonging to one face family.
351 *
352 * The function performs deterministic I/J/K directional passes with an
353 * intermediate ghost refresh after each active periodic direction. It updates
354 * persistent global seam/dummy values only; face-specific local stencil repair
355 * remains a separate operation.
356 *
357 * @param user The main UserCtx struct.
358 * @param face_direction Face family shared by every field (`'i'`, `'j'`, or `'k'`).
359 * @param[in] num_fields Count of registered face fields.
360 * @param field_ids Registered persistent face-field identities.
361 * @return PetscErrorCode 0 on success.
362 */
363PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const FieldId field_ids[]);
364
365/**
366 * @brief Synchronizes persistent component-staggered vector fields.
367 *
368 * The function performs deterministic I/J/K endpoint transfers with an
369 * intermediate ghost refresh after every active periodic direction. Currently
370 * `Ucont` is the only registered component-staggered field.
371 *
372 * @param user The main UserCtx struct.
373 * @param num_fields Number of entries in `field_ids`.
374 * @param field_ids Registered component-staggered field identities.
375 * @return PetscErrorCode 0 on success.
376 */
377PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields,
378 const FieldId field_ids[]);
379
380/**
381 * @brief Repairs the outer adjacent periodic ghosts used by QUICK cell stencils.
382 *
383 * The supplied local vectors must already contain a current PETSc periodic
384 * ghost exchange. The vector and scalar fields are repaired two logical cells
385 * across each active periodic seam so QUICK's `i-1/i+2` equivalents are valid.
386 *
387 * @param user Main block context containing periodic boundary metadata.
388 * @param local_vector_field Ghosted three-component cell-centered field.
389 * @param local_scalar_field Ghosted scalar cell-centered field.
390 * @return PetscErrorCode 0 on success.
391 */
392PetscErrorCode PreparePeriodicQuickStencilFields(UserCtx *user, Vec local_vector_field,
393 Vec local_scalar_field);
394
395/**
396 * @brief Synchronizes one local-only component-staggered periodic work field.
397 *
398 * This helper communicates locally computed owned entries, establishes the
399 * normal-component periodic endpoint values, and communicates once more.
400 *
401 * @param user Main block context containing periodic boundary metadata.
402 * @param local_field Ghosted local component-staggered vector.
403 * @return PetscErrorCode 0 on success.
404 */
405PetscErrorCode SynchronizePeriodicLocalStaggeredField(UserCtx *user, Vec local_field);
406
407/**
408 * @brief (Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundaries.
409 *
410 * This function synchronizes cell-centered `Aj` and the persistent I/J/K metric
411 * face families through the canonical MPI-safe synchronizers.
412 *
413 * @param user The main UserCtx struct.
414 * @return PetscErrorCode 0 on success.
415 */
416PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user);
417
418/**
419 * @brief Applies periodic boundary conditions by copying data across domain boundaries for all relevant fields.
420 *
421 * This is the canonical periodic orchestrator for geometric consistency. It updates
422 * `Ucat`, `P`, and `Nvert` through the generic cell synchronizer and updates
423 * staggered `Ucont` through the component-staggered synchronizer.
424 *
425 * Future extension rule: add new periodic variables by extending the existing field
426 * string dispatchers and invoking them from this orchestrator.
427 *
428 * @param user The main UserCtx struct.
429 * @return PetscErrorCode 0 on success.
430 */
431PetscErrorCode ApplyPeriodicBCs(UserCtx *user);
432
433/**
434 * @brief Updates the dummy cells (ghost nodes) on the faces of the local domain for NON-PERIODIC boundaries.
435 *
436 * This function's role is to apply a second-order extrapolation to set the ghost
437 * cell values based on the boundary condition value (stored in `ubcs`) and the
438 * first interior cell.
439 *
440 * NOTE: This function deliberately IGNORES periodic boundaries. It is part of a
441 * larger workflow where `ApplyPeriodicBCs` handles periodic faces first.
442 *
443 * CRITICAL DETAIL: This function uses shrunken loop ranges (lxs, lxe, etc.) to
444 * intentionally update only the flat part of the faces, avoiding the edges and
445
446 * corners. The edges and corners are then handled separately by `UpdateCornerNodes`.
447 * This precisely replicates the logic of the original FormBCS function.
448 *
449 * @param user The main UserCtx struct containing all necessary data.
450 * @return PetscErrorCode 0 on success.
451 */
452PetscErrorCode UpdateDummyCells(UserCtx *user);
453
454/**
455 * @brief Updates the corner and edge ghost nodes of the local domain by averaging.
456 *
457 * This function should be called AFTER the face ghost nodes are finalized by both
458 * `ApplyPeriodicBCs` and `UpdateDummyCells`. It resolves the values at shared
459 * edges and corners by averaging the values of adjacent, previously-computed
460 * ghost nodes.
461 *
462 * The logic is generic and works correctly regardless of the boundary types on
463 * the adjacent faces (e.g., it will correctly average a periodic face neighbor
464 * with a wall face neighbor).
465 *
466 * @param user The main UserCtx struct containing all necessary data.
467 * @return PetscErrorCode 0 on success.
468 */
469PetscErrorCode UpdateCornerNodes(UserCtx *user);
470
471/**
472 * @brief Applies wall function modeling to near-wall velocities for all wall-type boundaries.
473 *
474 * This function implements log-law wall functions to model the near-wall velocity profile
475 * without fully resolving the viscous sublayer. It is applicable to ALL wall-type boundaries
476 * regardless of their specific boundary condition (no-slip, moving wall, slip, etc.), as
477 * determined by the mathematical_type being WALL.
478 *
479 * MATHEMATICAL BACKGROUND:
480 * Wall functions bridge the gap between the wall (y=0) and the first computational cell
481 * center by using empirical log-law relationships:
482 * - Viscous sublayer (y+ < 11.81): u+ = y+
483 * - Log-law region (y+ > 11.81): u+ = (1/κ) * ln(E * y+)
484 * where u+ = u/u_τ, y+ = y*u_τ/ν, κ = 0.41 (von Karman constant), E = exp(κB)
485 *
486 * IMPLEMENTATION DETAILS:
487 * Unlike standard boundary conditions that set ghost cell values, wall functions:
488 * 1. Read velocity from the SECOND interior cell (i±2, j±2, k±2)
489 * 2. Compute wall shear stress using log-law
490 * 3. Modify velocity at the FIRST interior cell (i±1, j±1, k±1)
491 * 4. Keep ghost cell boundary values (ubcs, ucont) at zero
492 *
493 * WORKFLOW:
494 * - Called from ApplyBoundaryConditions after standard BC application
495 * - Operates on ucat (Cartesian velocity)
496 * - Updates ustar (friction velocity field) for diagnostics/turbulence models
497 * - Ghost cells remain zero; UpdateDummyCells handles extrapolation afterward
498 *
499 * GEOMETRIC QUANTITIES:
500 * sb = wall-normal distance from wall to first interior cell center
501 * sc = wall-normal distance from wall to second interior cell center
502 * These are computed from cell Jacobians (aj) and face area vectors
503 *
504 * APPLICABILITY:
505 * - Requires simCtx->wallfunction = true
506 * - Only processes faces where mathematical_type == WALL
507 * - Skips solid-embedded cells (nvert >= 0.1)
508 *
509 * @param user The UserCtx containing all simulation state and geometry
510 * @return PetscErrorCode 0 on success
511 *
512 * @note This function modifies interior cell velocities, NOT ghost cells
513 * @note Wall roughness (ks) is currently set to 1e-16 (smooth wall)
514 * @see wall_function_loglaw() in wallfunction.c for the actual log-law implementation
515 * @see noslip() in wallfunction.c for the initial linear interpolation
516 */
517PetscErrorCode ApplyWallFunction(UserCtx *user);
518
519/**
520 * @brief Finalizes cell-centered fields after the projection step.
521 *
522 * This function completes the cell-centered state derived from the final,
523 * divergence-free `Ucont` produced by `Projection`. It fills non-periodic
524 * `Ucat` dummy faces, synchronizes periodic `Ucat` and `P` endpoints, resolves
525 * edges and corners, and refreshes the corresponding local vectors.
526 *
527 * This function is fundamentally different from `ApplyBoundaryConditions`: it
528 * does NOT modify `Ucont`, reapply wall functions, or rerun the full physical
529 * boundary-condition workflow.
530 *
531 * WORKFLOW:
532 * 1. Refreshes local `Ucat` and any flow-dependent `Ubcs` targets.
533 * 2. Fills non-periodic dummy faces and establishes periodic cell endpoints.
534 * 3. Resolves edges/corners, restores exact periodic relationships, and refreshes
535 * local `Ucat` and `P`.
536 *
537 * @param user The main UserCtx struct, containing all simulation state.
538 * @return PetscErrorCode 0 on success.
539 */
540PetscErrorCode FinalizePostProjectionCellFields(UserCtx *user);
541
542/**
543 * @brief Main boundary-condition orchestrator executed during solver timestepping.
544 *
545 * This routine performs the full BC workflow for the current block, including
546 * dynamic boundary refresh, periodic transfer, dummy/corner updates, and optional
547 * wall-function corrections in the same order expected by the runtime solver.
548 * It may iterate boundary updates to enforce coupled boundary dependencies.
549 *
550 * @param user The main UserCtx struct containing field vectors and boundary system state.
551 * @return PetscErrorCode 0 on success.
552 */
553PetscErrorCode ApplyBoundaryConditions(UserCtx *user);
554
555#endif // BOUNDARIES_H
PetscErrorCode ApplyPeriodicBCs(UserCtx *user)
Applies periodic boundary conditions by copying data across domain boundaries for all relevant fields...
PetscErrorCode PreparePeriodicQuickStencilFields(UserCtx *user, Vec local_vector_field, Vec local_scalar_field)
Repairs the outer adjacent periodic ghosts used by QUICK cell stencils.
MomentumRowType
Classification of one staggered momentum row (location + component).
Definition Boundaries.h:252
@ MOM_ROW_FIXED_HOMOGENEOUS
Dummy/tangential row carrying no unknown at all.
Definition Boundaries.h:255
@ MOM_ROW_PHYSICAL
Independent unknown governed by the momentum equation.
Definition Boundaries.h:253
@ MOM_ROW_PERIODIC_DUPLICATE
Duplicate of a wrapped representative row (see ri, rj, rk).
Definition Boundaries.h:256
@ MOM_ROW_FIXED_CONDITIONED
Strong Dirichlet row; the value comes from ApplyBoundaryConditions().
Definition Boundaries.h:254
PetscErrorCode BoundarySystem_Initialize(UserCtx *user, const char *bcs_filename)
Initializes the entire boundary system.
Definition Boundaries.c:850
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...
Definition Boundaries.c:400
PetscErrorCode ApplyWallFunction(UserCtx *user)
Applies wall function modeling to near-wall velocities for all wall-type boundaries.
MomentumRowType ClassifyMomentumRow(UserCtx *user, PetscInt i, PetscInt j, PetscInt k, PetscInt component, PetscInt *ri, PetscInt *rj, PetscInt *rk)
Single source of truth for "which staggered momentum rows are unknowns".
Definition Boundaries.c:597
PetscErrorCode PropagateBoundaryConfigToCoarserLevels(SimCtx *simCtx)
Propagates boundary condition configuration from finest to all coarser multigrid levels.
Definition Boundaries.c:947
PetscErrorCode ApplyMetricsPeriodicBCs(UserCtx *user)
(Orchestrator) Updates all metric-related fields in the local ghost cell regions for periodic boundar...
PetscErrorCode EnforceRHSBoundaryConditions(UserCtx *user)
Zeroes every momentum RHS row that does not carry an independent unknown.
Definition Boundaries.c:660
PetscErrorCode UpdateDummyCells(UserCtx *user)
Updates the dummy cells (ghost nodes) on the faces of the local domain for NON-PERIODIC boundaries.
PetscErrorCode BoundarySystem_RefreshUbcs(UserCtx *user)
(Private) A lightweight execution engine that calls the UpdateUbcs() method on all relevant handlers.
PetscErrorCode SynchronizePeriodicLocalStaggeredField(UserCtx *user, Vec local_field)
Synchronizes one local-only component-staggered periodic work field.
PetscErrorCode BoundarySystem_Validate(UserCtx *user)
(Public) Validates the consistency and compatibility of the parsed boundary condition system.
Definition Boundaries.c:789
PetscErrorCode BoundaryCondition_Create(BCHandlerType handler_type, BoundaryCondition **new_bc_ptr)
(Private) Creates and configures a specific BoundaryCondition handler object.
Definition Boundaries.c:703
PetscErrorCode SynchronizePeriodicStaggeredFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent component-staggered vector fields.
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,...
Definition Boundaries.c:11
PetscErrorCode ApplyBoundaryConditions(UserCtx *user)
Main boundary-condition orchestrator executed during solver timestepping.
PetscErrorCode FinalizePostProjectionCellFields(UserCtx *user)
Finalizes cell-centered fields after the projection step.
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.
Definition Boundaries.c:127
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.
Definition Boundaries.c:213
PetscErrorCode BoundarySystem_ExecuteStep(UserCtx *user)
Executes one full boundary condition update cycle for a time step.
PetscErrorCode SynchronizePeriodicFaceFields(UserCtx *user, char face_direction, PetscInt num_fields, const FieldId field_ids[])
Synchronizes persistent fields belonging to one face family.
PetscErrorCode BoundarySystem_Destroy(UserCtx *user)
Cleans up and destroys all boundary system resources.
PetscErrorCode SynchronizePeriodicCellFields(UserCtx *user, PetscInt num_fields, const FieldId field_ids[])
Synchronizes periodic endpoint cells for a list of cell-centered fields.
PetscErrorCode UpdateCornerNodes(UserCtx *user)
Updates the corner and edge ghost nodes of the local domain by averaging.
Header file for Particle Motion and migration related functions.
Header file for Particle Swarm management functions.
Authoritative identities and storage metadata for persistent Eulerian fields.
FieldId
Compile-time identity for a catalogued Eulerian field.
Public interface for grid, solver, and metric setup routines.
Public interface for data input/output routines.
Logging utilities and macros for PETSc-based applications.
The "virtual table" struct for a boundary condition handler object.
Definition variables.h:353
Main header file for a complex fluid dynamics solver.
BCHandlerType
Defines the specific computational "strategy" for a boundary handler.
Definition variables.h:303
BCFace
Identifies the six logical faces of a structured computational block.
Definition variables.h:261
The master context for the entire simulation.
Definition variables.h:695
User-defined context containing data specific to a single computational grid level.
Definition variables.h:906
Header file for particle location functions using the walking search algorithm.