*/
namespace CUDAWrappers
{
+ namespace internal
+ {
+ /**
+ * Compute the dof/quad index for a given thread id, dimension, and
+ * number of points in each space dimensions.
+ */
+ template <int dim, int n_points_1d>
+ __device__ inline unsigned int
+ compute_index()
+ {
+ return (dim == 1 ?
+ threadIdx.x % n_points_1d :
+ dim == 2 ?
+ threadIdx.x % n_points_1d + n_points_1d * threadIdx.y :
+ threadIdx.x % n_points_1d +
+ n_points_1d * (threadIdx.y + n_points_1d * threadIdx.z));
+ }
+ } // namespace internal
+
/**
* This class provides all the functions necessary to evaluate functions at
* quadrature points and cell integrations. In functionality, this class is
/**
* Return the value of a finite element function at quadrature point
* number @p q_point after a call to @p evaluate(true,...).
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ value_type
+ get_value(const unsigned int q_point) const;
+
+ /**
+ * Same as above, except that the quadrature point is computed from thread
+ * id.
*/
__device__ value_type
- get_value(const unsigned int q_point) const;
+ get_value() const;
/**
* Return the value of a finite element function at degree of freedom
* @p dof after a call to integrate() or before a call to evaluate().
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ value_type
+ get_dof_value(const unsigned int dof) const;
+
+ /**
+ * Same as above, except that the local dof index is computed from the
+ * thread id.
*/
__device__ value_type
- get_dof_value(const unsigned int dof) const;
+ get_dof_value() const;
/**
* Write a value to the field containing the values on quadrature points
* with component @p q_point. Access to the same fields as through @p
* get_value(). This specifies the value which is tested by all basis
* function on the current cell and integrated over.
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ void
+ submit_value(const value_type &val_in, const unsigned int q_point);
+
+ /**
+ * Same as above, except that the quadrature point is computed from the
+ * thread id.
*/
__device__ void
- submit_value(const value_type &val_in, const unsigned int q_point);
+ submit_value(const value_type &val_in);
/**
* Write a value to the field containing the values for the degree of
* freedom with index @p dof after a call to integrate() or before
* calling evaluate(). Access through the same fields as through
* get_dof_value().
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ void
+ submit_dof_value(const value_type &val_in, const unsigned int dof);
+
+ /**
+ * Same as above, except that the local dof index is computed from the
+ * thread id.
*/
__device__ void
- submit_dof_value(const value_type &val_in, const unsigned int dof);
+ submit_dof_value(const value_type &val_in);
/**
* Return the gradient of a finite element function at quadrature point
* number @p q_point after a call to @p evaluate(...,true).
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ gradient_type
+ get_gradient(const unsigned int q_point) const;
+
+ /**
+ * Same as above, except that the quadrature point is computed from the
+ * thread id.
*/
__device__ gradient_type
- get_gradient(const unsigned int q_point) const;
+ get_gradient() const;
/**
* Write a contribution that is tested by the gradient to the field
- * containing the values on quadrature points with component @p q_point
+ * containing the values on quadrature points with component @p q_point.
+ *
+ * @deprecated Use the version without parameters instead.
+ */
+ DEAL_II_DEPRECATED __device__ void
+ submit_gradient(const gradient_type &grad_in, const unsigned int q_point);
+
+
+ /**
+ * Same as above, except that the quadrature point is computed from the
+ * thread id.
*/
__device__ void
- submit_gradient(const gradient_type &grad_in, const unsigned int q_point);
+ submit_gradient(const gradient_type &grad_in);
// clang-format off
/**
* CUDAWrappers::FEEvaluation<dim, fe_degree, n_q_points_1d, n_components, Number> *fe_eval,
* const unsigned int q_point) const;
* \endcode
+ *
+ * @deprecated Use apply_for_each_quad_point() instead.
+ */
+ // clang-format on
+ template <typename Functor>
+ DEAL_II_DEPRECATED __device__ void
+ apply_quad_point_operations(const Functor &func);
+
+ // clang-format off
+ /**
+ * Same as above, except that the functor @func only takes a single input
+ * argument (fe_eval) and computes the quadrature point from the thread id.
+ *
+ * @p func needs to define
+ * \code
+ * __device__ void operator()(
+ * CUDAWrappers::FEEvaluation<dim, fe_degree, n_q_points_1d, n_components, Number> *fe_eval) const;
+ * \endcode
*/
// clang-format on
template <typename Functor>
__device__ void
- apply_quad_point_operations(const Functor &func);
+ apply_for_each_quad_point(const Functor &func);
private:
types::global_dof_index *local_to_global;
{
static_assert(n_components_ == 1, "This function only supports FE with one \
components");
- const unsigned int idx =
- (threadIdx.x % n_q_points_1d) +
- (dim > 1 ? threadIdx.y : 0) * n_q_points_1d +
- (dim > 2 ? threadIdx.z : 0) * n_q_points_1d * n_q_points_1d;
+ const unsigned int idx = internal::compute_index<dim, n_q_points_1d>();
const types::global_dof_index src_idx = local_to_global[idx];
// Use the read-only data cache.
internal::resolve_hanging_nodes<dim, fe_degree, true>(constraint_mask,
values);
- const unsigned int idx =
- (threadIdx.x % n_q_points_1d) +
- (dim > 1 ? threadIdx.y : 0) * n_q_points_1d +
- (dim > 2 ? threadIdx.z : 0) * n_q_points_1d * n_q_points_1d;
+ const unsigned int idx = internal::compute_index<dim, n_q_points_1d>();
+
const types::global_dof_index destination_idx = local_to_global[idx];
if (use_coloring)
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ typename FEEvaluation<dim,
+ fe_degree,
+ n_q_points_1d,
+ n_components_,
+ Number>::value_type
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ get_value() const
+ {
+ return get_value(internal::compute_index<dim, n_q_points_1d>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ typename FEEvaluation<dim,
+ fe_degree,
+ n_q_points_1d,
+ n_components_,
+ Number>::value_type
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ get_dof_value() const
+ {
+ return get_dof_value(internal::compute_index<dim, fe_degree + 1>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ void
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ submit_value(const value_type &val_in)
+ {
+ submit_value(val_in, internal::compute_index<dim, n_q_points_1d>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ void
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ submit_dof_value(const value_type &val_in)
+ {
+ submit_dof_value(val_in, internal::compute_index<dim, fe_degree + 1>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ typename FEEvaluation<dim,
+ fe_degree,
+ n_q_points_1d,
+ n_components_,
+ Number>::gradient_type
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ get_gradient() const
+ {
+ static_assert(n_components_ == 1, "This function only supports FE with one \
+ components");
+
+ return get_gradient(internal::compute_index<dim, n_q_points_1d>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ __device__ void
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ submit_gradient(const gradient_type &grad_in)
+ {
+ submit_gradient(grad_in, internal::compute_index<dim, n_q_points_1d>());
+ }
+
+
+
template <int dim,
int fe_degree,
int n_q_points_1d,
FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
apply_quad_point_operations(const Functor &func)
{
- const unsigned int q_point =
- (dim == 1 ?
- threadIdx.x % n_q_points_1d :
- dim == 2 ?
- threadIdx.x % n_q_points_1d + n_q_points_1d * threadIdx.y :
- threadIdx.x % n_q_points_1d +
- n_q_points_1d * (threadIdx.y + n_q_points_1d * threadIdx.z));
- func(this, q_point);
+ func(this, internal::compute_index<dim, n_q_points_1d>());
+
+ __syncthreads();
+ }
+
+
+
+ template <int dim,
+ int fe_degree,
+ int n_q_points_1d,
+ int n_components_,
+ typename Number>
+ template <typename Functor>
+ __device__ void
+ FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::
+ apply_for_each_quad_point(const Functor &func)
+ {
+ func(this);
__syncthreads();
}
__device__ void operator()(
CUDAWrappers::FEEvaluation<dim, fe_degree, n_q_points_1d, 1, Number>
- * fe_eval,
- const unsigned int q_point) const;
+ *fe_eval) const;
private:
Number coef;
template <int dim, int fe_degree, typename Number, int n_q_points_1d>
__device__ void HelmholtzOperatorQuad<dim, fe_degree, Number, n_q_points_1d>::
- operator()(
- CUDAWrappers::FEEvaluation<dim, fe_degree, n_q_points_1d, 1, Number> *fe_eval,
- const unsigned int q) const
+ operator()(CUDAWrappers::FEEvaluation<dim, fe_degree, n_q_points_1d, 1, Number>
+ *fe_eval) const
{
- fe_eval->submit_value(coef * fe_eval->get_value(q), q);
- fe_eval->submit_gradient(fe_eval->get_gradient(q), q);
+ fe_eval->submit_value(coef * fe_eval->get_value());
+ fe_eval->submit_gradient(fe_eval->get_gradient());
}
cell, gpu_data, shared_data);
fe_eval.read_dof_values(src);
fe_eval.evaluate(true, true);
- fe_eval.apply_quad_point_operations(
+ fe_eval.apply_for_each_quad_point(
HelmholtzOperatorQuad<dim, fe_degree, Number, n_q_points_1d>(coef[pos]));
fe_eval.integrate(true, true);
fe_eval.distribute_local_to_global(dst);