Line data Source code
1 : /**
2 : * Boundary Conditions - Scalar (CPU) Implementation
3 : *
4 : * Baseline scalar implementations of boundary conditions.
5 : * No SIMD, no OpenMP - pure C loops.
6 : *
7 : * Neumann, Periodic, and Dirichlet are generated from the shared template.
8 : * Inlet is in boundary_conditions_inlet_scalar.c.
9 : * Outlet is in boundary_conditions_outlet_scalar.c.
10 : */
11 :
12 : #include "cfd/core/indexing.h"
13 :
14 : #define BC_CORE_FUNC_PREFIX scalar
15 : #define BC_CORE_USE_OMP 0
16 : #include "../boundary_conditions_core_impl.h"
17 :
18 17 : cfd_status_t bc_apply_symmetry_scalar_impl(double* u, double* v, double* w,
19 : size_t nx, size_t ny,
20 : size_t nz, size_t stride_z,
21 : const bc_symmetry_config_t* config) {
22 17 : if (!u || !v || !config) {
23 : return CFD_ERROR_INVALID;
24 : }
25 17 : if (nx < 3 || ny < 3) {
26 : return CFD_ERROR_INVALID;
27 : }
28 17 : if (nz == 0 || nz == 2 || (nz > 1 && stride_z < nx * ny)) {
29 : return CFD_ERROR_INVALID;
30 : }
31 :
32 17 : size_t j, i, k;
33 17 : bc_edge_t edges = config->edges;
34 :
35 : /* Left boundary (X-symmetry plane at x=0):
36 : * - u = 0 (normal velocity is zero)
37 : * - dv/dx = 0 (tangential gradient is zero, copy from interior)
38 : * - dw/dx = 0 (tangential gradient is zero, copy from interior) */
39 17 : if (edges & BC_EDGE_LEFT) {
40 16 : for (k = 0; k < nz; k++) {
41 8 : size_t base = k * stride_z;
42 136 : for (j = 0; j < ny; j++) {
43 128 : u[base + IDX_2D(0, j, nx)] = 0.0;
44 128 : v[base + IDX_2D(0, j, nx)] = v[base + IDX_2D(1, j, nx)];
45 : }
46 8 : if (w) {
47 0 : for (j = 0; j < ny; j++) {
48 0 : w[base + IDX_2D(0, j, nx)] = w[base + IDX_2D(1, j, nx)];
49 : }
50 : }
51 : }
52 : }
53 :
54 : /* Right boundary (X-symmetry plane at x=Lx):
55 : * - u = 0 (normal velocity is zero)
56 : * - dv/dx = 0 (tangential gradient is zero, copy from interior)
57 : * - dw/dx = 0 (tangential gradient is zero, copy from interior) */
58 17 : if (edges & BC_EDGE_RIGHT) {
59 12 : for (k = 0; k < nz; k++) {
60 6 : size_t base = k * stride_z;
61 102 : for (j = 0; j < ny; j++) {
62 96 : u[base + IDX_2D(nx - 1, j, nx)] = 0.0;
63 96 : v[base + IDX_2D(nx - 1, j, nx)] = v[base + IDX_2D(nx - 2, j, nx)];
64 : }
65 6 : if (w) {
66 0 : for (j = 0; j < ny; j++) {
67 0 : w[base + IDX_2D(nx - 1, j, nx)] = w[base + IDX_2D(nx - 2, j, nx)];
68 : }
69 : }
70 : }
71 : }
72 :
73 : /* Bottom boundary (Y-symmetry plane at y=0):
74 : * - v = 0 (normal velocity is zero)
75 : * - du/dy = 0 (tangential gradient is zero, copy from interior)
76 : * - dw/dy = 0 (tangential gradient is zero, copy from interior) */
77 17 : if (edges & BC_EDGE_BOTTOM) {
78 14 : for (k = 0; k < nz; k++) {
79 7 : size_t base = k * stride_z;
80 119 : for (i = 0; i < nx; i++) {
81 112 : v[base + i] = 0.0;
82 112 : u[base + i] = u[base + nx + i];
83 : }
84 7 : if (w) {
85 0 : for (i = 0; i < nx; i++) {
86 0 : w[base + i] = w[base + nx + i];
87 : }
88 : }
89 : }
90 : }
91 :
92 : /* Top boundary (Y-symmetry plane at y=Ly):
93 : * - v = 0 (normal velocity is zero)
94 : * - du/dy = 0 (tangential gradient is zero, copy from interior)
95 : * - dw/dy = 0 (tangential gradient is zero, copy from interior) */
96 17 : if (edges & BC_EDGE_TOP) {
97 12 : for (k = 0; k < nz; k++) {
98 6 : size_t base = k * stride_z;
99 6 : double* u_top = u + base + ((ny - 1) * nx);
100 6 : double* v_top = v + base + ((ny - 1) * nx);
101 6 : double* u_interior = u + base + ((ny - 2) * nx);
102 102 : for (i = 0; i < nx; i++) {
103 96 : v_top[i] = 0.0;
104 96 : u_top[i] = u_interior[i];
105 : }
106 6 : if (w) {
107 : double* w_top = w + base + ((ny - 1) * nx);
108 : double* w_interior = w + base + ((ny - 2) * nx);
109 0 : for (i = 0; i < nx; i++) {
110 0 : w_top[i] = w_interior[i];
111 : }
112 : }
113 : }
114 : }
115 :
116 : /* Back boundary (Z-symmetry plane at z=0):
117 : * - w = 0 (normal velocity is zero, only when w is provided)
118 : * - du/dz = 0 (tangential gradient is zero, copy from interior)
119 : * - dv/dz = 0 (tangential gradient is zero, copy from interior) */
120 17 : if ((edges & BC_EDGE_BACK) && nz > 1) {
121 1 : size_t plane_size = nx * ny;
122 26 : for (i = 0; i < plane_size; i++) {
123 25 : if (w) {
124 25 : w[i] = 0.0;
125 : }
126 25 : u[i] = u[stride_z + i];
127 25 : v[i] = v[stride_z + i];
128 : }
129 : }
130 :
131 : /* Front boundary (Z-symmetry plane at z=Lz):
132 : * - w = 0 (normal velocity is zero, only when w is provided)
133 : * - du/dz = 0 (tangential gradient is zero, copy from interior)
134 : * - dv/dz = 0 (tangential gradient is zero, copy from interior) */
135 17 : if ((edges & BC_EDGE_FRONT) && nz > 1) {
136 1 : size_t plane_size = nx * ny;
137 1 : size_t front = (nz - 1) * stride_z;
138 1 : size_t interior = (nz - 2) * stride_z;
139 26 : for (i = 0; i < plane_size; i++) {
140 25 : if (w) {
141 25 : w[front + i] = 0.0;
142 : }
143 25 : u[front + i] = u[interior + i];
144 25 : v[front + i] = v[interior + i];
145 : }
146 : }
147 :
148 : return CFD_SUCCESS;
149 : }
150 :
151 : /* Scalar backend implementation table
152 : * Note: bc_apply_inlet_scalar_impl is defined in boundary_conditions_inlet_scalar.c
153 : * Note: bc_apply_outlet_scalar_impl is defined in boundary_conditions_outlet_scalar.c */
154 : const bc_backend_impl_t bc_impl_scalar = {
155 : .apply_neumann = bc_apply_neumann_scalar_impl,
156 : .apply_periodic = bc_apply_periodic_scalar_impl,
157 : .apply_dirichlet = bc_apply_dirichlet_scalar_impl,
158 : .apply_inlet = bc_apply_inlet_scalar_impl,
159 : .apply_outlet = bc_apply_outlet_scalar_impl,
160 : .apply_symmetry = bc_apply_symmetry_scalar_impl
161 : };
|