LCOV - code coverage report
Current view: top level - boundary/omp - boundary_conditions_outlet_omp.c (source / functions) Coverage Total Hit
Test: coverage.info Lines: 90.9 % 22 20
Test Date: 2026-03-04 10:22:18 Functions: 100.0 % 1 1

            Line data    Source code
       1              : /**
       2              :  * Outlet Boundary Conditions - OpenMP Implementation
       3              :  *
       4              :  * OpenMP parallelized outlet boundary condition implementation.
       5              :  * Parallelizes over rows for left/right boundaries and
       6              :  * over columns for top/bottom boundaries.
       7              :  *
       8              :  * Supports:
       9              :  * - Zero-gradient (Neumann) outlet
      10              :  * - Convective outlet (advection-based)
      11              :  * - 3D z-face outlets (FRONT/BACK edges)
      12              :  */
      13              : 
      14              : #include "../boundary_conditions_outlet_common.h"
      15              : 
      16              : #ifdef CFD_ENABLE_OPENMP
      17              : #include <omp.h>
      18              : 
      19           13 : cfd_status_t bc_apply_outlet_omp_impl(double* field, size_t nx, size_t ny,
      20              :                                        size_t nz, size_t stride_z,
      21              :                                        const bc_outlet_config_t* config) {
      22           13 :     if (!field || !config || nx < 3 || ny < 3) {
      23              :         return CFD_ERROR_INVALID;
      24              :     }
      25              : 
      26           25 :     if (!bc_outlet_is_valid_edge(config->edge)) {
      27              :         return CFD_ERROR_INVALID;
      28              :     }
      29              : 
      30           12 :     if (!bc_outlet_is_valid_type(config->type)) {
      31              :         return CFD_ERROR_INVALID;
      32              :     }
      33              : 
      34           12 :     int edge_idx = bc_outlet_edge_to_index(config->edge);
      35           12 :     const bc_outlet_edge_loop_t* loop = &bc_outlet_edge_loops[edge_idx];
      36              : 
      37           12 :     switch (config->type) {
      38              :         case BC_OUTLET_ZERO_GRADIENT:
      39              :         case BC_OUTLET_CONVECTIVE:
      40              :             /* Both types use zero-gradient for now.
      41              :              * Full convective BC would require temporal information. */
      42           12 :             if (loop->is_z_face) {
      43              :                 /* Z-face outlet (FRONT or BACK): copy entire xy-plane */
      44            1 :                 if (nz <= 1) {
      45              :                     return CFD_ERROR_INVALID;
      46              :                 }
      47            1 :                 size_t dst_plane, src_plane;
      48            1 :                 if (config->edge == BC_EDGE_FRONT) {
      49            0 :                     dst_plane = (nz - 1) * stride_z;
      50            0 :                     src_plane = (nz - 2) * stride_z;
      51              :                 } else { /* BC_EDGE_BACK */
      52              :                     dst_plane = 0;
      53              :                     src_plane = stride_z;
      54              :                 }
      55            1 :                 int plane_size_int = (int)(nx * ny);
      56            1 :                 int idx;
      57            1 :                 #pragma omp parallel for schedule(static)
      58              :                 for (idx = 0; idx < plane_size_int; idx++) {
      59              :                     field[dst_plane + (size_t)idx] = field[src_plane + (size_t)idx];
      60              :                 }
      61              :             } else {
      62              :                 /* X/Y-face outlet: loop over each z-plane */
      63           11 :                 size_t count = loop->use_ny_for_count ? ny : nx;
      64           11 :                 int count_int = (int)count;
      65           22 :                 for (size_t k = 0; k < nz; k++) {
      66           11 :                     size_t base = k * stride_z;
      67           11 :                     int i;
      68           11 :                     #pragma omp parallel for schedule(static)
      69              :                     for (i = 0; i < count_int; i++) {
      70              :                         size_t dst_idx = base + loop->dst_fn((size_t)i, nx, ny);
      71              :                         size_t src_idx = base + loop->src_fn((size_t)i, nx, ny);
      72              :                         field[dst_idx] = field[src_idx];
      73              :                     }
      74              :                 }
      75              :             }
      76              :             break;
      77              : 
      78              :         default:
      79              :             return CFD_ERROR_INVALID;
      80              :     }
      81              : 
      82              :     return CFD_SUCCESS;
      83              : }
      84              : 
      85              : #else /* !CFD_ENABLE_OPENMP */
      86              : 
      87              : cfd_status_t bc_apply_outlet_omp_impl(double* field, size_t nx, size_t ny,
      88              :                                        size_t nz, size_t stride_z,
      89              :                                        const bc_outlet_config_t* config) {
      90              :     (void)field; (void)nx; (void)ny; (void)nz; (void)stride_z; (void)config;
      91              :     return CFD_ERROR_UNSUPPORTED;
      92              : }
      93              : 
      94              : #endif /* CFD_ENABLE_OPENMP */
        

Generated by: LCOV version 2.0-1