16 #ifndef dealii_cuda_fe_evaluation_h 17 #define dealii_cuda_fe_evaluation_h 19 #include <deal.II/base/tensor.h> 20 #include <deal.II/base/utilities.h> 21 #include <deal.II/lac/cuda_vector.h> 22 #include <deal.II/matrix_free/cuda_matrix_free.h> 23 #include <deal.II/matrix_free/cuda_matrix_free.templates.h> 24 #include <deal.II/matrix_free/cuda_tensor_product_kernels.h> 26 DEAL_II_NAMESPACE_OPEN
35 template <
int dim,
int fe_degree,
bool transpose,
typename Number>
36 __device__
void resolve_hanging_nodes_shmem(Number *values,
const unsigned 72 template <
int dim,
int fe_degree,
int n_q_points_1d = fe_degree+1,
73 int n_components_ = 1,
typename Number =
double>
77 typedef Number value_type;
80 static constexpr
unsigned int dimension = dim;
81 static constexpr
unsigned int n_components = n_components_;
82 static constexpr
unsigned int n_q_points =
Utilities::pow(n_q_points_1d, dim);
83 static constexpr
unsigned int tensor_dofs_per_cell =
Utilities::pow(fe_degree + 1, dim);
90 SharedData<dim,Number> *shdata);
117 __device__
void evaluate(
const bool evaluate_val,
118 const bool evaluate_grad);
127 __device__
void integrate(
const bool integrate_val,
128 const bool integrate_grad);
134 __device__ value_type
get_value(
const unsigned int q_point)
const;
143 const unsigned int q_point);
156 const unsigned int q_point);
161 template <
typename functor>
165 unsigned int *local_to_global;
166 unsigned int n_cells;
167 unsigned int padding_length;
169 const unsigned int constraint_mask;
176 Number *gradients[dim];
181 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
187 SharedData<dim,Number> *shdata)
189 n_cells(data->n_cells),
190 padding_length(data->padding_length),
191 constraint_mask(data->constraint_mask[cell_id]),
192 values(shdata->values)
194 local_to_global = data->local_to_global + padding_length*cell_id;
195 inv_jac = data->inv_jacobian + padding_length*cell_id;
196 JxW = data->JxW + padding_length*cell_id;
198 for (
unsigned int i=0; i < dim; ++i)
199 gradients[i] = shdata->gradients[i];
204 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
210 static_assert(n_components_ == 1,
"This function only supports FE with one \ 212 const unsigned int idx = (threadIdx.x%n_q_points_1d)
213 +(dim>1 ? threadIdx.y : 0)*n_q_points_1d
214 +(dim>2 ? threadIdx.z : 0)*n_q_points_1d*n_q_points_1d;
216 const unsigned int src_idx = local_to_global[idx];
218 values[idx] = __ldg(&src[src_idx]);
221 internal::resolve_hanging_nodes_shmem<dim,fe_degree,false>(values,
229 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
235 static_assert(n_components_ == 1,
"This function only supports FE with one \ 238 internal::resolve_hanging_nodes_shmem<dim,fe_degree,true>(values,
242 const unsigned int idx = (threadIdx.x%n_q_points_1d)
243 + (dim>1 ? threadIdx.y : 0) * n_q_points_1d
244 + (dim>2 ? threadIdx.z : 0) * n_q_points_1d * n_q_points_1d;
245 const unsigned int destination_idx = local_to_global[idx];
247 dst[destination_idx] += values[idx];
252 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
256 evaluate(
const bool evaluate_val,
const bool evaluate_grad)
261 dim, fe_degree,n_q_points_1d, Number> evaluator_tensor_product;
262 if (evaluate_grad ==
true)
264 evaluator_tensor_product.gradient_at_quad_pts(values, gradients);
268 if (evaluate_val ==
true)
270 evaluator_tensor_product.value_at_quad_pts(values);
277 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
281 integrate(
const bool integrate_val,
const bool integrate_grad)
284 dim, fe_degree,n_q_points_1d, Number> evaluator_tensor_product;
285 if (integrate_val ==
true)
287 evaluator_tensor_product.integrate_value(values);
289 if (integrate_grad ==
true)
291 evaluator_tensor_product.integrate_gradient<
true>(values, gradients);
295 else if (integrate_grad ==
true)
297 evaluator_tensor_product.integrate_gradient<
false>(values, gradients);
304 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
307 typename FEEvaluation<dim, fe_degree, n_q_points_1d, n_components_, Number>::value_type
311 return values[q_point];
316 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
322 values[q_point] = val_in * JxW[q_point];
327 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
334 static_assert(n_components_ == 1,
"This function only supports FE with one \ 337 const Number *inv_jacobian = &inv_jac[q_point];
339 for (
int d_1=0; d_1<dim; ++d_1)
342 for (
int d_2=0; d_2<dim; ++d_2)
343 tmp += inv_jacobian[padding_length*n_cells*(dim*d_2+d_1)] *
344 gradients[d_2][q_point];
353 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
360 const Number *inv_jacobian = &inv_jac[q_point];
361 for (
int d_1=0; d_1<dim; ++d_1)
364 for (
int d_2=0; d_2<dim; ++d_2)
365 tmp += inv_jacobian[n_cells*padding_length*(dim*d_1+d_2)] *
367 gradients[d_1][q_point] = tmp * JxW[q_point];
373 template <
int dim,
int fe_degree,
int n_q_points_1d,
int n_components_,
375 template <
typename functor>
380 const unsigned int q_point = (dim == 1 ? threadIdx.x%n_q_points_1d :
381 dim == 2 ? threadIdx.x%n_q_points_1d + n_q_points_1d *threadIdx.y :
382 threadIdx.x%n_q_points_1d + n_q_points_1d * (threadIdx.y +
383 n_q_points_1d*threadIdx.z));
390 DEAL_II_NAMESPACE_CLOSE
void submit_value(const value_type &val_in, const unsigned int q_point)
constexpr unsigned int pow(const unsigned int base, const unsigned int iexp)
value_type get_value(const unsigned int q_point) const
gradient_type get_gradient(const unsigned int q_point) const
void evaluate(const bool evaluate_val, const bool evaluate_grad)
FEEvaluation(int cell_id, const data_type *data, SharedData< dim, Number > *shdata)
void apply_quad_point_operations(const functor &func)
void read_dof_values(const Number *src)
void submit_gradient(const gradient_type &grad_in, const unsigned int q_point)
void distribute_local_to_global(Number *dst) const
void integrate(const bool integrate_val, const bool integrate_grad)