///
/// @file jittertrajectory.cl
///
/// Streamline integration functions.
///
/// @author CPS
///
///
/// @defgroup integrate Streamline integration
/// Kernels and functions used to integrate streamlines.
///
#ifdef KERNEL_INTEGRATE_FIELDS
///
/// Integrate a jittered flow path downstream or upstream.
/// Write the streamline count and lengths to slc, slt arrays.
/// Don't record the trajectory itself.
///
/// Compiled if KERNEL_INTEGRATE_FIELDS 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] slc_array: grid recording accumulated count of streamline integration
/// steps across each pixel (padded)
/// @param[out] slt_array: grid recording accumulated count of streamline segment lengths
/// crossing each pixel (padded)
/// @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
/// @param[in] initial_rng_state: RNG state and integer variate
///
/// @returns void
///
/// @ingroup integrate
///
static inline void jittered_trajectory( __global const float2 *uv_array,
__global const bool *mask_array,
__global uint *mapping_array,
__global uint *slc_array,
__global uint *slt_array,
const uint global_id,
const uint seed_idx,
const float2 current_seed_point_vec,
const uint initial_rng_state )
{
// Private variables - non-constant within this kernel instance
__private uint idx, n_steps=0u, rng_state=initial_rng_state;
__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, next_vec;
prev_vec = vec;
// Start by recording the seed point
idx = get_array_idx(vec);
if (!mask_array[idx])
atomic_write_sl_data(&slt_array[idx], &slc_array[idx], l_trajectory);
// Loop downstream until the pixel is masked, i.e., we've exited the basin or grid,
// or if the streamline is too long (in l_trajectory or n_steps)
while (idx<NXY_PADDED && !mask_array[idx]
&& (l_trajectory<MAX_LENGTH && n_steps<MAX_N_STEPS)) {
compute_step_vec_jittered(dt, uv_array, &rng_state, &dxy1_vec, &dxy2_vec,
&uv1_vec, &uv2_vec, vec, &next_vec, &idx);
if (idx<NXY_PADDED) {
if (!mask_array[idx])
if (runge_kutta_step_write_sl_data(&dt, &dl, &l_trajectory,
&dxy1_vec, &dxy2_vec,
&vec, &prev_vec, next_vec,
&n_steps, &idx,
mask_array, mapping_array,
slt_array, slc_array)) {
break;
}
} else {
euler_step_write_sl_data(&dt, &dl, &l_trajectory, uv1_vec,
&vec, prev_vec, &n_steps, &idx,
mask_array, slt_array, slc_array);
break;
}
}
return;
}
#endif