computestep.clΒΆ

///
/// @file computestep.cl
///
/// Compute single streamline integration step.
///
/// @author CPS
///

#if defined(KERNEL_INTEGRATE_TRAJECTORY) || defined(KERNEL_CONNECT_CHANNELS) \
    || defined(KERNEL_MAP_CHANNEL_HEADS) || defined(KERNEL_COUNT_DOWNCHANNELS) \
    || defined(KERNEL_HILLSLOPES)        || defined(KERNEL_SEGMENT_HILLSLOPES) \
    || defined(KERNEL_SUBSEGMENT_FLANKS) || defined(KERNEL_HILLSLOPE_LENGTHS) \
    || defined(KERNEL_FIX_RIGHT_FLANKS)  || defined(KERNEL_FIX_LEFT_FLANKS)
///
/// Compute a 2nd-order Runge-Kutta integration step along a streamline.
///
/// Compiled if any of the following are defined:
///    - KERNEL_INTEGRATE_TRAJECTORY
///    - KERNEL_CONNECT_CHANNELS
///    - KERNEL_MAP_CHANNEL_HEADS
///    - KERNEL_COUNT_DOWNCHANNELS
///    - KERNEL_HILLSLOPES
///    - KERNEL_SEGMENT_HILLSLOPES
///    - KERNEL_SUBSEGMENT_FLANKS
///    - KERNEL_HILLSLOPE_LENGTHS
///
/// @param[in]      dt: delta time step
/// @param[in]      uv_array  (float *,  RO): gridded velocity vector components (u,v)
/// @param[in,out]  dxy1_vec: R-K first order delta step vector
/// @param[in,out]  dxy2_vec: R-K second order delta step vector
/// @param[in,out]  uv1_vec: flow velocity vector at current coordinate (at @p vec)
/// @param[in,out]  uv2_vec: flow velocity vector at RK1 stepped coordinate
///                           (at @p vec + @p dxy1_vec)
/// @param[in]      vec: current (x,y) coordinate vector at tip of streamline trajectory
/// @param[in,out]  next_vec: next (x,y) coordinate vector on streamline trajectory
/// @param[in,out]  idx: array index of pixel at current (x,y) position
///
/// @returns void
///
/// @ingroup trajectoryfns
///
static inline void compute_step_vec(const float dt,
                                    const __global float2 *uv_array,
                                    float2 *dxy1_vec, float2 *dxy2_vec,
                                    float2 *uv1_vec, float2 *uv2_vec,
                                    const float2 vec,
                                    float2 *next_vec, uint *idx) {
    // Calculate RK2 next pt vector and approx into a fixed-point-res vector.
    // Do this using randomly biased =jittered flow vector field.
    // Then get the next pixel's data array index.
    *uv1_vec = speed_interpolator(vec,uv_array);
    *dxy1_vec = approximate(*uv1_vec*COMBO_FACTOR*dt);
    *uv2_vec = speed_interpolator(vec+*dxy1_vec,uv_array);
    *dxy2_vec = approximate(0.5f*(*dxy1_vec+*uv2_vec*COMBO_FACTOR*dt));
    *next_vec = vec+*dxy2_vec;
    *idx = get_array_idx(*next_vec);
}
#endif

#if defined(KERNEL_INTEGRATE_FIELDS) && defined(IS_RNG_AVAILABLE)
///
/// Compute a jittered 2nd-order Runge-Kutta integration step along a streamline.
/// Jittering is achieved by adding a uniform random vector to of the RK2 flow velocity
///   vectors, then normalizing to provide two RK2 unit step vectors.
/// The [0,1) uniform variates are scaled by JITTER_MAGNITUDE before addition
///   to the unit flow vectors.
///
/// Compiled if KERNEL_INTEGRATE_FIELDS and IS_RNG_AVAILABLE is defined.
///
/// @param[in]      dt: delta time step
/// @param[in]      uv_array  (float *,  RO): gridded velocity vector components (u,v)
/// @param[in,out]  rng_state: RNG state (thus initally the seed) and RNG variate
/// @param[in,out]  dxy1_vec: R-K first order delta step vector
/// @param[in,out]  dxy2_vec: R-K second order delta step vector
/// @param[in,out]  uv1_vec: flow velocity vector at current coordinate (at @p vec)
/// @param[in,out]  uv2_vec: flow velocity vector at RK1 stepped coordinate
///                           (at @p vec + @p dxy1_vec)
/// @param[in]      vec: current (x,y) coordinate vector at tip of streamline trajectory
/// @param[in,out]  next_vec: next (x,y) coordinate vector on streamline trajectory
/// @param[in,out]  idx: array index of pixel at current (x,y) position
///
/// @returns void
///
/// @ingroup trajectoryfns
///
static inline void compute_step_vec_jittered(const float dt,
                                             const __global float2 *uv_array,
                                             uint *rng_state,
                                             float2 *dxy1_vec, float2 *dxy2_vec,
                                             float2 *uv1_vec,  float2 *uv2_vec,
                                             const float2 vec, float2 *next_vec,
                                             uint *idx) {
    // Calculate RK2 next pt vector and approx into a fixed-point-res vector.
    // Do this using randomly biased aka jittered flow vector field.
    // Then get the next pixel's data array index.
    *uv1_vec = speed_interpolator(vec,uv_array);
    *uv1_vec += lehmer_rand_vec(rng_state)*JITTER_MAGNITUDE;
    *uv1_vec /= fast_length(*uv1_vec);
    *dxy1_vec = approximate(*uv1_vec*COMBO_FACTOR*dt);
    *uv2_vec = speed_interpolator(vec+*dxy1_vec,uv_array);
    *uv2_vec += lehmer_rand_vec(rng_state)*JITTER_MAGNITUDE;
    *uv2_vec /= fast_length(*uv2_vec);
    *dxy2_vec = approximate(0.5f*(*dxy1_vec+*uv2_vec*COMBO_FACTOR*dt));
    *next_vec = vec+*dxy2_vec;
    *idx = get_array_idx(*next_vec);
}
#endif