9 #include <dolfinx/fem/FunctionSpace.h>
10 #include <dolfinx/mesh/Mesh.h>
11 #include <dolfinx/mesh/MeshTags.h>
75 Form(
const std::vector<std::shared_ptr<const fem::FunctionSpace>>&
80 std::vector<std::pair<
81 int, std::function<
void(
82 T*,
const T*,
const T*,
const double*,
const int*,
83 const std::uint8_t*,
const std::uint32_t)>>>,
88 const std::shared_ptr<const mesh::Mesh>&
mesh =
nullptr)
97 if (_mesh != V->mesh())
98 throw std::runtime_error(
"Incompatible mesh");
100 throw std::runtime_error(
"No mesh could be associated with the Form.");
103 for (
auto& integral_type : integrals)
107 auto it = _integrals.emplace(
108 type, std::map<
int, std::pair<kern, std::vector<std::int32_t>>>());
111 for (
auto& integral : integral_type.second.first)
112 it.first->second.insert({integral.first, {integral.second, {}}});
116 if (integral_type.second.second)
118 assert(_mesh == integral_type.second.second->mesh());
119 set_domains(type, *integral_type.second.second);
125 set_default_domains(*_mesh);
135 virtual ~Form() =
default;
140 int rank()
const {
return _function_spaces.size(); }
144 std::shared_ptr<const mesh::Mesh>
mesh()
const {
return _mesh; }
148 const std::vector<std::shared_ptr<const fem::FunctionSpace>>&
151 return _function_spaces;
159 const std::function<void(T*,
const T*,
const T*,
const double*,
const int*,
160 const std::uint8_t*,
const std::uint32_t)>&
163 auto it0 = _integrals.find(type);
164 if (it0 == _integrals.end())
165 throw std::runtime_error(
"No kernels for requested type.");
166 auto it1 = it0->second.find(i);
167 if (it1 == it0->second.end())
168 throw std::runtime_error(
"No kernel for requested domain index.");
170 return it1->second.first;
177 std::set<IntegralType> set;
178 for (
auto& type : _integrals)
179 set.insert(type.first);
188 if (
auto it = _integrals.find(type); it == _integrals.end())
191 return it->second.size();
202 std::vector<int> ids;
203 if (
auto it = _integrals.find(type); it != _integrals.end())
205 for (
auto&
kernel : it->second)
206 ids.push_back(
kernel.first);
219 auto it0 = _integrals.find(type);
220 if (it0 == _integrals.end())
221 throw std::runtime_error(
"No mesh entities for requested type.");
222 auto it1 = it0->second.find(i);
223 if (it1 == it0->second.end())
224 throw std::runtime_error(
"No mesh entities for requested domain index.");
225 return it1->second.second;
229 const std::vector<std::shared_ptr<const fem::Function<T>>>
232 return _coefficients;
245 std::vector<int> n{0};
246 for (
const auto& c : _coefficients)
249 throw std::runtime_error(
"Not all form coefficients have been set.");
250 n.push_back(n.back() + c->function_space()->element()->space_dimension());
256 const std::vector<std::shared_ptr<const fem::Constant<T>>>&
constants()
const
272 auto it0 = _integrals.find(type);
273 assert(it0 != _integrals.end());
275 std::shared_ptr<const mesh::Mesh>
mesh = marker.
mesh();
277 const int tdim = topology.
dim();
279 if (type == IntegralType::exterior_facet
280 or type == IntegralType::interior_facet)
283 mesh->topology_mutable().create_connectivity(dim, tdim);
285 else if (type == IntegralType::vertex)
288 if (dim != marker.
dim())
290 throw std::runtime_error(
"Invalid MeshTags dimension:"
291 + std::to_string(marker.
dim()));
295 std::map<int, std::pair<kern, std::vector<std::int32_t>>>& integrals
299 const std::vector<int>& values = marker.
values();
300 const std::vector<std::int32_t>& tagged_entities = marker.
indices();
302 const auto entity_end
303 = std::lower_bound(tagged_entities.begin(), tagged_entities.end(),
310 if (type == IntegralType::exterior_facet)
315 std::set<std::int32_t> fwd_shared;
316 if (topology.
index_map(tdim)->num_ghosts() == 0)
319 topology.
index_map(tdim - 1)->shared_indices().array().begin(),
320 topology.
index_map(tdim - 1)->shared_indices().array().end());
323 for (
auto f = tagged_entities.begin(); f != entity_end; ++f)
327 if (f_to_c->num_links(*f) == 1
328 and fwd_shared.find(*f) == fwd_shared.end())
330 const std::size_t i = std::distance(tagged_entities.cbegin(), f);
331 if (
auto it = integrals.find(values[i]); it != integrals.end())
332 it->second.second.push_back(*f);
336 else if (type == IntegralType::interior_facet)
338 for (
auto f = tagged_entities.begin(); f != entity_end; ++f)
340 if (f_to_c->num_links(*f) == 2)
342 const std::size_t i = std::distance(tagged_entities.cbegin(), f);
343 if (
auto it = integrals.find(values[i]); it != integrals.end())
344 it->second.second.push_back(*f);
353 for (
auto e = tagged_entities.begin(); e != entity_end; ++e)
355 const std::size_t i = std::distance(tagged_entities.cbegin(), e);
356 if (
auto it = integrals.find(values[i]); it != integrals.end())
357 it->second.second.push_back(*e);
370 const int tdim = topology.
dim();
373 if (
auto kernels = _integrals.find(IntegralType::cell);
374 kernels != _integrals.end())
376 if (
auto it = kernels->second.find(-1); it != kernels->second.end())
378 std::vector<std::int32_t>& active_entities = it->second.second;
379 const int num_cells = topology.
index_map(tdim)->size_local();
380 active_entities.resize(num_cells);
381 std::iota(active_entities.begin(), active_entities.end(), 0);
387 if (
auto kernels = _integrals.find(IntegralType::exterior_facet);
388 kernels != _integrals.end())
390 if (
auto it = kernels->second.find(-1); it != kernels->second.end())
392 std::vector<std::int32_t>& active_entities = it->second.second;
393 active_entities.clear();
396 mesh.topology_mutable().create_connectivity(tdim - 1, tdim);
399 std::set<std::int32_t> fwd_shared_facets;
402 if (topology.
index_map(tdim)->num_ghosts() == 0)
404 fwd_shared_facets.insert(
405 topology.
index_map(tdim - 1)->shared_indices().array().begin(),
406 topology.
index_map(tdim - 1)->shared_indices().array().end());
409 const int num_facets = topology.
index_map(tdim - 1)->size_local();
410 for (
int f = 0; f < num_facets; ++f)
412 if (f_to_c->num_links(f) == 1
413 and fwd_shared_facets.find(f) == fwd_shared_facets.end())
415 active_entities.push_back(f);
423 if (
auto kernels = _integrals.find(IntegralType::interior_facet);
424 kernels != _integrals.end())
426 if (
auto it = kernels->second.find(-1); it != kernels->second.end())
428 std::vector<std::int32_t>& active_entities = it->second.second;
431 mesh.topology_mutable().create_connectivity(tdim - 1, tdim);
433 const int num_facets = topology.
index_map(tdim - 1)->size_local();
435 active_entities.clear();
436 active_entities.reserve(num_facets);
437 for (
int f = 0; f < num_facets; ++f)
439 if (f_to_c->num_links(f) == 2)
440 active_entities.push_back(f);
447 std::vector<std::shared_ptr<const fem::FunctionSpace>> _function_spaces;
450 std::vector<std::shared_ptr<const fem::Function<T>>> _coefficients;
453 std::vector<std::shared_ptr<const fem::Constant<T>>> _constants;
456 std::shared_ptr<const mesh::Mesh> _mesh;
459 = std::function<void(T*,
const T*,
const T*,
const double*,
const int*,
460 const std::uint8_t*,
const std::uint32_t)>;
462 std::map<int, std::pair<kern, std::vector<std::int32_t>>>>
466 bool _needs_permutation_data;