trajectory.clΒΆ

///
/// @file trajectory.cl
///
/// Streamline integration functions.
///
/// @author CPS
///

///
/// @defgroup integrate Streamline integration
/// Kernels and functions used to integrate streamlines.
///

#ifdef KERNEL_INTEGRATE_TRAJECTORY
///
/// Integrate a streamline downstream or upstream; record the trajectory.
///
/// Compiled if KERNEL_INTEGRATE_TRAJECTORY is defined.
///
/// @param[in]  uv_array: flow unit velocity vector grid (padded)
/// @param[in]  mask_array: grid pixel mask (padded),
///                         with @p true = masked, @p false = good
/// @param[out] mapping_array: multi-flag array
/// @param[out] traj_nsteps_array: list of number of steps along each trajectory;
///                                 one per @p seed_point_array vector
/// @param[out] traj_length_array: list of lengths of each trajectory;
///                                 one per @p seed_point_array vector
/// @param[out] trajectory_vec: sequence of compressed-as-byte dx,dy integration steps
///                             along this streamline trajectory
/// @param[in]  global_id: ID of the kernel instance
/// @param[in]  seed_idx: index of the seed vector in the list seed_point_array;
///                       if chunkified, the sequence of indexes is offset from
///                       @p global_id by @p SEEDS_CHUNK_OFFSET
/// @param[in]  current_seed_point_vec: vector (real, float2) for the current point
///                                     along the streamline trajectory
///
/// @returns void
///
/// @ingroup integrate
///
static inline void trajectory_record( __global const float2 *uv_array,
                                      __global const bool   *mask_array,
                                      __global       uint   *mapping_array,
                                      __global       ushort *traj_nsteps_array,
                                      __global       float  *traj_length_array,
                                      __global       char2  *trajectory_vec,
                                               const uint    global_id,
                                               const uint    seed_idx,
                                               const float2  current_seed_point_vec )
{
    // Private variables - non-constant within this kernel instance
    __private uint idx, prev_idx, n_steps=0u;
    __private float l_trajectory=0.0f, dl=0.0f, dt=DT_MAX;
    __private float2 uv1_vec, uv2_vec, dxy1_vec, dxy2_vec,
                     vec=current_seed_point_vec, prev_vec=vec, next_vec;
    // Start
    prev_vec = vec;
    idx = get_array_idx(vec);
    // Loop downstream until the pixel is masked, i.e., we've exited the basin or grid,
    //   or if the streamline is too long (l or n)
    while (!mask_array[idx] && (l_trajectory<MAX_LENGTH && n_steps<MAX_N_STEPS)) {
        compute_step_vec(dt, uv_array, &dxy1_vec, &dxy2_vec, &uv1_vec, &uv2_vec,
                         vec, &next_vec, &idx);
        if (!mask_array[idx]) {
            if (runge_kutta_step_record(&dt, &dl, &l_trajectory, &dxy1_vec, &dxy2_vec,
                &vec, &prev_vec, &next_vec, &n_steps, &idx, &prev_idx, trajectory_vec)) {
//                atomic_or(&mapping_array[idx],IS_STUCK);
                break;
            }
        } else {
            euler_step_record(&dt, &dl, &l_trajectory, uv1_vec,
                              &vec, prev_vec, &n_steps, trajectory_vec);
            break;
        }
    }
    // Record this final trajectory point and return
    finalize_trajectory(global_id, n_steps, l_trajectory,
                        traj_nsteps_array, traj_length_array);
    return;
}
#endif