74 std::vector<std::shared_ptr<const DofMap>>
dofmaps)
76 _id(boost::uuids::random_generator()()), _root_space_id(_id)
78 std::vector<mesh::CellType> cell_types =
mesh->topology()->cell_types();
79 std::size_t num_cell_types = cell_types.size();
80 if (
elements.size() != num_cell_types)
82 throw std::invalid_argument(
83 "Number of elements must match number of cell types");
85 if (_dofmaps.size() != num_cell_types)
87 throw std::invalid_argument(
88 "Number of dofmaps must match number of cell types");
90 for (std::size_t i = 0; i < num_cell_types; ++i)
92 if (
elements.at(i)->cell_type() != cell_types.at(i))
94 throw std::invalid_argument(
95 "Element cell types must match mesh cell types");
98 check_facet_orientations();
244 if (!_component.empty())
246 throw std::invalid_argument(
"Cannot tabulate coordinates for a "
247 "FunctionSpace that is a subspace.");
250 assert(_elements.front());
251 if (_elements.front()->is_mixed())
253 throw std::invalid_argument(
254 "Cannot tabulate coordinates for a mixed FunctionSpace.");
259 assert(_elements.front());
260 const std::size_t gdim = _mesh->geometry().dim();
261 const int tdim = _mesh->topology()->dim();
264 assert(_dofmaps.front());
265 std::shared_ptr<const common::IndexMap> index_map
266 = _dofmaps.front()->index_map;
268 const int index_map_bs = _dofmaps.front()->index_map_bs();
269 const int dofmap_bs = _dofmaps.front()->bs();
271 const int element_block_size = _elements.front()->block_size();
272 const std::size_t scalar_dofs
273 = _elements.front()->space_dimension() / element_block_size;
274 const std::int32_t num_dofs
275 = index_map_bs * (index_map->size_local() + index_map->num_ghosts())
278 std::size_t num_cell_types = _elements.size();
281 const std::size_t shape_c0 = transpose ? 3 : num_dofs;
282 const std::size_t shape_c1 = transpose ? num_dofs : 3;
283 std::vector<geometry_type> coords(shape_c0 * shape_c1, 0);
284 using mdspan2_t = md::mdspan<geometry_type, md::dextents<std::size_t, 2>>;
286 = md::mdspan<const geometry_type, md::dextents<std::size_t, 4>>;
287 std::span<const geometry_type> x_g = _mesh->geometry().x();
288 std::vector<geometry_type> x_b(scalar_dofs * gdim);
289 mdspan2_t x(x_b.data(), scalar_dofs, gdim);
291 for (std::size_t i = 0; i < num_cell_types; ++i)
294 if (!_elements[i]->interpolation_ident())
296 throw std::runtime_error(
297 "Cannot evaluate dof coordinates - this element "
298 "does not have pointwise evaluation.");
300 const auto [X, Xshape] = _elements[i]->interpolation_points();
304 = _mesh->geometry().cmaps().at(i);
307 auto x_dofmap = _mesh->geometry().dofmaps().at(i);
308 const std::size_t num_dofs_g = cmap.
dim();
309 std::vector<geometry_type> coordinate_dofs_b(num_dofs_g * gdim);
310 mdspan2_t coordinate_dofs(coordinate_dofs_b.data(), num_dofs_g, gdim);
312 auto map = _mesh->topology()->index_maps(tdim)[i];
314 const int num_cells = map->size_local() + map->num_ghosts();
316 std::span<const std::uint32_t> cell_info;
317 if (_elements[i]->needs_dof_transformations())
319 _mesh->topology_mutable()->create_cell_permutations();
320 cell_info = std::span(_mesh->topology()->get_cell_permutation_info());
323 const std::array<std::size_t, 4> phi_shape
325 std::vector<geometry_type> phi_b(std::reduce(
326 phi_shape.begin(), phi_shape.end(), 1, std::multiplies{}));
327 cmdspan4_t phi_full(phi_b.data(), phi_shape);
330 = md::submdspan(phi_full, 0, md::full_extent, md::full_extent, 0);
339 auto apply_dof_transformation
340 = _elements[i]->template dof_transformation_fn<geometry_type>(
343 for (
int c = 0; c < num_cells; ++c)
346 auto x_dofs = md::submdspan(x_dofmap, c, md::full_extent);
347 for (std::size_t j = 0; j < x_dofs.size(); ++j)
348 for (std::size_t k = 0; k < gdim; ++k)
349 coordinate_dofs(j, k) = x_g[3 * x_dofs[j] + k];
353 if (apply_dof_transformation)
355 apply_dof_transformation(
356 x_b, std::span(cell_info.data(), cell_info.size()), c,
361 auto dofs = _dofmaps[i]->cell_dofs(c);
366 for (std::size_t j = 0; j < dofs.size(); ++j)
367 for (std::size_t k = 0; k < gdim; ++k)
368 coords[dofs[j] * 3 + k] = x(j, k);
372 for (std::size_t j = 0; j < dofs.size(); ++j)
373 for (std::size_t k = 0; k < gdim; ++k)
374 coords[k * num_dofs + dofs[j]] = x(j, k);