LCOV - code coverage report
Current view: top level - boundary/cpu - boundary_conditions_scalar.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 86.9 % 61 53
Test Date: 2026-03-04 10:22:18 Functions: 100.0 % 1 1

            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              : };
        

Generated by: LCOV version 2.0-1