///
/// @file writearray.cl
///
/// Functions to write to slc & slc grid arrays using atomic ops (mask-checked and not)
///
/// @author CPS
/// @bug No known bugs
///
#ifdef KERNEL_INTEGRATE_FIELDS
///
/// Add the current streamline length (@p l_trajectory) to the current pixel of the
/// @p slt accumulation array.
/// Similarly, increment the streamline count at the current pixel of the
/// @p slc accumulation array.
/// Atomic operations are used since several kernel instances may need to write
/// to the same pixel effectively simultaneously.
///
/// Compiled if KERNEL_INTEGRATE_TRAJECTORY is defined.
///
/// @param[in,out] slt: grid recording accumulated count of streamline segment lengths
/// crossing each pixel (padded)
/// @param[in,out] slc: grid recording accumulated count of streamline integration
/// steps across each pixel (padded)
/// @param[in] l_trajectory: total streamline distance so far
///
/// @returns void
///
/// @ingroup trajectoryfns
///
static inline void atomic_write_sl_data(__global uint *slt, __global uint *slc,
const float l_trajectory) {
// Add streamline length-so-far to total slt for this pixel
// - rounding up to & casting as 32bit int
// There may be issues for short trajectories as a result.
// Also if step distance is << pixel width.
atomic_add(slt, (uint)(l_trajectory+0.5f));
// Increment the 'visit' counter slc at this pixel.
atomic_inc(slc);
}
#endif
#ifdef KERNEL_INTEGRATE_FIELDS
///
/// Extended version of atomic_write_sl_data() to include testing whether the
/// current pixel is masked, and an assignment of the previous pixel index
/// to the current pixel index.
///
/// Add the current streamline length (@p l_trajectory) to the current pixel of the
/// @p slt accumulation array.
/// Similarly, increment the streamline count at the current pixel of the
/// @p slc accumulation array.
/// Atomic operations are used since several kernel instances may need to write
/// to the same pixel effectively simultaneously.
///
/// Compiled if KERNEL_INTEGRATE_TRAJECTORY is defined.
///
/// @param[in] idx: array index of pixel at current (x,y) position
/// @param[in] mask_flag: whether current pixel is masked or not
/// @param[in,out] slt: grid recording accumulated count of streamline segment lengths
/// crossing each pixel (padded)
/// @param[in,out] slc: grid recording accumulated count of streamline integration
/// steps across each pixel (padded)
/// @param[in] l_trajectory: total streamline distance so far
///
/// @returns void
///
/// @ingroup trajectoryfns
///
static inline void check_atomic_write_sl_data(const uint idx, const bool mask_flag,
__global uint *slt, __global uint *slc,
const float l_trajectory) {
if (idx<NXY_PADDED && !mask_flag) {
// Add streamline length-so-far to total slt for this pixel
// - rounding up to & casting as 32bit int
// There may be issues for short trajectories as a result.
// Also if step distance is << pixel width.
atomic_add(slt, (uint)(l_trajectory+0.5f));
// Increment the 'visit' counter slc at this pixel.
atomic_inc(slc);
}
}
#endif