Line data Source code
1 : /**
2 : * Outlet Boundary Conditions - Scalar (CPU) Implementation
3 : *
4 : * Baseline scalar implementation of outlet boundary conditions.
5 : * No SIMD, no OpenMP - pure C loops.
6 : *
7 : * Supports:
8 : * - Zero-gradient (Neumann) outlet
9 : * - Convective outlet (advection-based)
10 : * - 3D z-face outlets (FRONT/BACK edges)
11 : */
12 :
13 : #include "../boundary_conditions_outlet_common.h"
14 :
15 48 : cfd_status_t bc_apply_outlet_scalar_impl(double* field, size_t nx, size_t ny,
16 : size_t nz, size_t stride_z,
17 : const bc_outlet_config_t* config) {
18 48 : if (!field || !config || nx < 3 || ny < 3) {
19 : return CFD_ERROR_INVALID;
20 : }
21 :
22 93 : if (!bc_outlet_is_valid_edge(config->edge)) {
23 : return CFD_ERROR_INVALID;
24 : }
25 :
26 45 : if (!bc_outlet_is_valid_type(config->type)) {
27 : return CFD_ERROR_INVALID;
28 : }
29 :
30 44 : int edge_idx = bc_outlet_edge_to_index(config->edge);
31 44 : const bc_outlet_edge_loop_t* loop = &bc_outlet_edge_loops[edge_idx];
32 :
33 44 : switch (config->type) {
34 : case BC_OUTLET_ZERO_GRADIENT:
35 : case BC_OUTLET_CONVECTIVE:
36 : /* Both types use zero-gradient for now.
37 : * Full convective BC would require temporal information. */
38 44 : if (loop->is_z_face) {
39 : /* Z-face outlet (FRONT or BACK): copy entire xy-plane from adjacent interior */
40 1 : if (nz <= 1) {
41 : return CFD_ERROR_INVALID;
42 : }
43 0 : size_t dst_plane, src_plane;
44 0 : if (config->edge == BC_EDGE_FRONT) {
45 0 : dst_plane = (nz - 1) * stride_z;
46 0 : src_plane = ((nz - 2) * stride_z);
47 : } else { /* BC_EDGE_BACK */
48 : dst_plane = 0;
49 : src_plane = stride_z;
50 : }
51 0 : for (size_t j = 0; j < ny; j++) {
52 0 : for (size_t i = 0; i < nx; i++) {
53 0 : size_t offset = IDX_2D(i, j, nx);
54 0 : field[dst_plane + offset] = field[src_plane + offset];
55 : }
56 : }
57 : } else {
58 : /* X/Y-face outlet: loop over each z-plane */
59 43 : size_t count = loop->use_ny_for_count ? ny : nx;
60 86 : for (size_t k = 0; k < nz; k++) {
61 43 : size_t base = k * stride_z;
62 439 : for (size_t i = 0; i < count; i++) {
63 396 : size_t dst_idx = base + loop->dst_fn(i, nx, ny);
64 396 : size_t src_idx = base + loop->src_fn(i, nx, ny);
65 396 : field[dst_idx] = field[src_idx];
66 : }
67 : }
68 : }
69 : break;
70 :
71 : default:
72 : return CFD_ERROR_INVALID;
73 : }
74 :
75 : return CFD_SUCCESS;
76 : }
|