| 263 | |
| 264 | template <typename Number, typename Number2> |
| 265 | void |
| 266 | do_function_values(const ArrayView<Number2> &dof_values, |
| 267 | const dealii::Table<2, double> &shape_values, |
| 268 | std::vector<Number> &values) |
| 269 | { |
| 270 | // scalar finite elements, so shape_values.size() == dofs_per_cell |
| 271 | const unsigned int dofs_per_cell = shape_values.n_rows(); |
| 272 | const unsigned int n_quadrature_points = values.size(); |
| 273 | |
| 274 | // initialize with zero |
| 275 | std::fill_n(values.begin(), |
| 276 | n_quadrature_points, |
| 277 | dealii::internal::NumberType<Number>::value(0.0)); |
| 278 | |
| 279 | // add up contributions of trial functions. note that here we deal with |
| 280 | // scalar finite elements, so no need to check for non-primitivity of |
| 281 | // shape functions. in order to increase the speed of this function, we |
| 282 | // directly access the data in the shape_values array, and increment |
| 283 | // pointers for accessing the data. this saves some lookup time and |
| 284 | // indexing. moreover, the order of the loops is such that we can access |
| 285 | // the shape_values data stored contiguously |
| 286 | for (unsigned int shape_func = 0; shape_func < dofs_per_cell; ++shape_func) |
| 287 | { |
| 288 | const Number2 value = dof_values[shape_func]; |
| 289 | // For auto-differentiable numbers, the fact that a DoF value is zero |
| 290 | // does not imply that its derivatives are zero as well. So we |
| 291 | // can't filter by value for these number types. |
| 292 | if (!Differentiation::AD::is_ad_number<Number2>::value) |
| 293 | if (value == dealii::internal::NumberType<Number2>::value(0.0)) |
| 294 | continue; |
| 295 | |
| 296 | const double *shape_value_ptr = &shape_values(shape_func, 0); |
| 297 | for (unsigned int point = 0; point < n_quadrature_points; ++point) |
| 298 | values[point] += value * (*shape_value_ptr++); |
| 299 | } |
| 300 | } |
| 301 | |
| 302 | |
| 303 |
no test coverage detected