9 #include "CoordinateElement.h"
11 #include "ElementDofLayout.h"
12 #include <dolfinx/common/types.h>
13 #include <dolfinx/fem/Form.h>
14 #include <dolfinx/fem/Function.h>
15 #include <dolfinx/la/SparsityPattern.h>
16 #include <dolfinx/mesh/cell_types.h>
57 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>>
61 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>>
64 std::vector<std::array<std::shared_ptr<const fem::FunctionSpace>, 2>>(
66 for (std::size_t i = 0; i < a.size(); ++i)
68 for (std::size_t j = 0; j < a[i].size(); ++j)
71 spaces[i][j] = {form->function_spaces()[0], form->function_spaces()[1]};
87 throw std::runtime_error(
88 "Cannot create sparsity pattern. Form is not a bilinear form");
92 std::array<const std::reference_wrapper<const fem::DofMap>, 2> dofmaps{
95 std::shared_ptr mesh = a.
mesh();
99 if (types.find(IntegralType::interior_facet) != types.end()
100 or types.find(IntegralType::exterior_facet) != types.end())
103 const int tdim = mesh->topology().dim();
104 mesh->topology_mutable().create_entities(tdim - 1);
105 mesh->topology_mutable().create_connectivity(tdim - 1, tdim);
116 const std::array<
const std::reference_wrapper<const fem::DofMap>, 2>&
118 const std::set<IntegralType>& integrals);
123 const std::vector<int>& parent_map
130 DofMap
create_dofmap(MPI_Comm comm,
const ufc_dofmap& dofmap,
131 mesh::Topology& topology);
150 template <
typename T>
152 const ufc_form& ufc_form,
153 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
157 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
159 if (ufc_form.rank != (
int)spaces.size())
160 throw std::runtime_error(
"Wrong number of argument spaces for Form.");
161 if (ufc_form.num_coefficients != (
int)coefficients.size())
163 throw std::runtime_error(
164 "Mismatch between number of expected and provided Form coefficients.");
166 if (ufc_form.num_constants != (
int)constants.size())
168 throw std::runtime_error(
169 "Mismatch between number of expected and provided Form constants.");
174 for (std::size_t i = 0; i < spaces.size(); ++i)
176 assert(spaces[i]->element());
177 ufc_finite_element* ufc_element = ufc_form.finite_elements[i];
179 if (std::string(ufc_element->signature)
180 != spaces[i]->element()->signature())
182 throw std::runtime_error(
183 "Cannot create form. Wrong type of function space for argument.");
191 = std::function<void(T*,
const T*,
const T*,
const double*,
const int*,
192 const std::uint8_t*,
const std::uint32_t)>;
193 std::map<IntegralType, std::pair<std::vector<std::pair<int, kern>>,
197 bool needs_permutation_data =
false;
200 std::vector<int> cell_integral_ids(ufc_form.integral_ids(cell),
201 ufc_form.integral_ids(cell)
202 + ufc_form.num_integrals(cell));
203 for (
int i = 0; i < ufc_form.num_integrals(cell); ++i)
205 ufc_integral* integral = ufc_form.integrals(cell)[i];
207 if (integral->needs_transformation_data)
208 needs_permutation_data =
true;
209 integral_data[IntegralType::cell].first.emplace_back(
210 cell_integral_ids[i], integral->tabulate_tensor);
214 if (
auto it = subdomains.find(IntegralType::cell);
215 it != subdomains.end() and !cell_integral_ids.empty())
217 integral_data[IntegralType::cell].second = it->second;
223 if (ufc_form.num_integrals(exterior_facet) > 0
224 or ufc_form.num_integrals(interior_facet) > 0)
228 auto mesh = spaces[0]->mesh();
229 const int tdim = mesh->topology().dim();
230 spaces[0]->mesh()->topology_mutable().create_entities(tdim - 1);
235 std::vector<int> exterior_facet_integral_ids(
236 ufc_form.integral_ids(exterior_facet),
237 ufc_form.integral_ids(exterior_facet)
238 + ufc_form.num_integrals(exterior_facet));
239 for (
int i = 0; i < ufc_form.num_integrals(exterior_facet); ++i)
241 ufc_integral* integral = ufc_form.integrals(exterior_facet)[i];
243 if (integral->needs_transformation_data)
244 needs_permutation_data =
true;
245 integral_data[IntegralType::exterior_facet].first.emplace_back(
246 exterior_facet_integral_ids[i], integral->tabulate_tensor);
250 if (
auto it = subdomains.find(IntegralType::exterior_facet);
251 it != subdomains.end() and !exterior_facet_integral_ids.empty())
253 integral_data[IntegralType::exterior_facet].second = it->second;
257 std::vector<int> interior_facet_integral_ids(
258 ufc_form.integral_ids(interior_facet),
259 ufc_form.integral_ids(interior_facet)
260 + ufc_form.num_integrals(interior_facet));
261 for (
int i = 0; i < ufc_form.num_integrals(interior_facet); ++i)
263 ufc_integral* integral = ufc_form.integrals(interior_facet)[i];
265 if (integral->needs_transformation_data)
266 needs_permutation_data =
true;
267 integral_data[IntegralType::interior_facet].first.emplace_back(
268 interior_facet_integral_ids[i], integral->tabulate_tensor);
272 if (
auto it = subdomains.find(IntegralType::interior_facet);
273 it != subdomains.end() and !interior_facet_integral_ids.empty())
275 integral_data[IntegralType::interior_facet].second = it->second;
278 return fem::Form(spaces, integral_data, coefficients, constants,
279 needs_permutation_data, mesh);
291 template <
typename T>
293 const ufc_form& ufc_form,
294 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
300 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
303 std::vector<std::shared_ptr<const fem::Function<T>>> coeff_map;
306 if (
auto it = coefficients.find(name); it != coefficients.end())
307 coeff_map.push_back(it->second);
310 throw std::runtime_error(
"Form coefficient \"" + name
311 +
"\" not provided.");
316 std::vector<std::shared_ptr<const fem::Constant<T>>> const_map;
319 if (
auto it = constants.find(name); it != constants.end())
320 const_map.push_back(it->second);
323 throw std::runtime_error(
"Form constant \"" + name +
"\" not provided.");
327 return create_form(ufc_form, spaces, coeff_map, const_map, subdomains, mesh);
341 template <
typename T>
344 const std::vector<std::shared_ptr<const fem::FunctionSpace>>& spaces,
350 const std::shared_ptr<const mesh::Mesh>& mesh =
nullptr)
352 ufc_form* form = fptr();
353 auto L = std::make_shared<fem::Form<T>>(fem::create_form<T>(
354 *form, spaces, coefficients, constants, subdomains, mesh));
368 std::shared_ptr<fem::FunctionSpace>
370 const std::string function_name,
371 std::shared_ptr<mesh::Mesh> mesh);
375 template <
typename U>
378 using T =
typename U::scalar_type;
381 const std::vector<std::shared_ptr<const fem::Function<T>>> coefficients
383 const std::vector<int> offsets = u.coefficient_offsets();
384 std::vector<const fem::DofMap*> dofmaps(coefficients.size());
385 std::vector<int> bs(coefficients.size());
386 std::vector<std::reference_wrapper<const std::vector<T>>> v;
387 v.reserve(coefficients.size());
388 for (std::size_t i = 0; i < coefficients.size(); ++i)
390 dofmaps[i] = coefficients[i]->function_space()->dofmap().get();
391 bs[i] = dofmaps[i]->bs();
392 v.push_back(coefficients[i]->x()->array());
396 std::shared_ptr<const mesh::Mesh> mesh = u.mesh();
398 const int tdim = mesh->topology().dim();
399 const std::int32_t num_cells
400 = mesh->topology().index_map(tdim)->size_local()
401 + mesh->topology().index_map(tdim)->num_ghosts();
405 if (!coefficients.empty())
407 for (
int cell = 0; cell < num_cells; ++cell)
409 for (std::size_t coeff = 0; coeff < dofmaps.size(); ++coeff)
411 xtl::span<const std::int32_t> dofs = dofmaps[coeff]->cell_dofs(cell);
412 const std::vector<T>& _v = v[coeff];
413 for (std::size_t i = 0; i < dofs.size(); ++i)
415 for (
int k = 0; k < bs[coeff]; ++k)
417 c(cell, bs[coeff] * i + k + offsets[coeff])
418 = _v[bs[coeff] * dofs[i] + k];
430 template <
typename U>
433 using T =
typename U::scalar_type;
434 const std::vector<std::shared_ptr<const fem::Constant<T>>>& constants
439 = std::accumulate(constants.begin(), constants.end(), 0,
440 [](std::int32_t sum,
const auto& constant) {
441 return sum + constant->value.size();
445 std::vector<T> constant_values(size);
446 std::int32_t offset = 0;
447 for (
const auto& constant : constants)
449 const std::vector<T>& value = constant->value;
450 for (std::size_t i = 0; i < value.size(); ++i)
451 constant_values[offset + i] = value[i];
452 offset += value.size();
455 return constant_values;