Note: this is documentation for an old release. View the latest documentation at docs.fenicsproject.org/dolfinx/v0.9.0/cpp/doxygen/d9/dd0/assemble__scalar__impl_8h_source.html
DOLFINx 0.7.3
DOLFINx C++ interface
Loading...
Searching...
No Matches
assemble_scalar_impl.h
1// Copyright (C) 2019-2020 Garth N. Wells
2//
3// This file is part of DOLFINx (https://www.fenicsproject.org)
4//
5// SPDX-License-Identifier: LGPL-3.0-or-later
6
7#pragma once
8
9#include "Constant.h"
10#include "Form.h"
11#include "FunctionSpace.h"
12#include "utils.h"
13#include <algorithm>
14#include <dolfinx/common/IndexMap.h>
15#include <dolfinx/mesh/Geometry.h>
16#include <dolfinx/mesh/Mesh.h>
17#include <dolfinx/mesh/Topology.h>
18#include <memory>
19#include <vector>
20
21namespace dolfinx::fem::impl
22{
23
25template <dolfinx::scalar T>
26T assemble_cells(mdspan2_t x_dofmap, std::span<const scalar_value_type_t<T>> x,
27 std::span<const std::int32_t> cells, FEkernel<T> auto fn,
28 std::span<const T> constants, std::span<const T> coeffs,
29 int cstride)
30{
31 T value(0);
32 if (cells.empty())
33 return value;
34
35 // Create data structures used in assembly
36 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
37
38 // Iterate over all cells
39 for (std::size_t index = 0; index < cells.size(); ++index)
40 {
41 std::int32_t c = cells[index];
42
43 // Get cell coordinates/geometry
44 auto x_dofs
45 = MDSPAN_IMPL_STANDARD_NAMESPACE::MDSPAN_IMPL_PROPOSED_NAMESPACE::
46 submdspan(x_dofmap, c, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
47 for (std::size_t i = 0; i < x_dofs.size(); ++i)
48 {
49 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
50 std::next(coordinate_dofs.begin(), 3 * i));
51 }
52
53 const T* coeff_cell = coeffs.data() + index * cstride;
54 fn(&value, coeff_cell, constants.data(), coordinate_dofs.data(), nullptr,
55 nullptr);
56 }
57
58 return value;
59}
60
62template <dolfinx::scalar T>
63T assemble_exterior_facets(mdspan2_t x_dofmap,
64 std::span<const scalar_value_type_t<T>> x,
65 std::span<const std::int32_t> facets,
66 FEkernel<T> auto fn, std::span<const T> constants,
67 std::span<const T> coeffs, int cstride)
68{
69 T value(0);
70 if (facets.empty())
71 return value;
72
73 // Create data structures used in assembly
74 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * x_dofmap.extent(1));
75
76 // Iterate over all facets
77 assert(facets.size() % 2 == 0);
78 for (std::size_t index = 0; index < facets.size(); index += 2)
79 {
80 std::int32_t cell = facets[index];
81 std::int32_t local_facet = facets[index + 1];
82
83 // Get cell coordinates/geometry
84 auto x_dofs = MDSPAN_IMPL_STANDARD_NAMESPACE::
85 MDSPAN_IMPL_PROPOSED_NAMESPACE::submdspan(
86 x_dofmap, cell, MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
87 for (std::size_t i = 0; i < x_dofs.size(); ++i)
88 {
89 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
90 std::next(coordinate_dofs.begin(), 3 * i));
91 }
92
93 const T* coeff_cell = coeffs.data() + index / 2 * cstride;
94 fn(&value, coeff_cell, constants.data(), coordinate_dofs.data(),
95 &local_facet, nullptr);
96 }
97
98 return value;
99}
100
102template <dolfinx::scalar T>
103T assemble_interior_facets(mdspan2_t x_dofmap,
104 std::span<const scalar_value_type_t<T>> x,
105 int num_cell_facets,
106 std::span<const std::int32_t> facets,
107 FEkernel<T> auto fn, std::span<const T> constants,
108 std::span<const T> coeffs, int cstride,
109 std::span<const int> offsets,
110 std::span<const std::uint8_t> perms)
111{
112 T value(0);
113 if (facets.empty())
114 return value;
115
116 // Create data structures used in assembly
117 using X = scalar_value_type_t<T>;
118 std::vector<X> coordinate_dofs(2 * x_dofmap.extent(1) * 3);
119 std::span<X> cdofs0(coordinate_dofs.data(), x_dofmap.extent(1) * 3);
120 std::span<X> cdofs1(coordinate_dofs.data() + x_dofmap.extent(1) * 3,
121 x_dofmap.extent(1) * 3);
122
123 std::vector<T> coeff_array(2 * offsets.back());
124 assert(offsets.back() == cstride);
125
126 // Iterate over all facets
127 assert(facets.size() % 4 == 0);
128 for (std::size_t index = 0; index < facets.size(); index += 4)
129 {
130 std::array<std::int32_t, 2> cells = {facets[index], facets[index + 2]};
131 std::array<std::int32_t, 2> local_facet
132 = {facets[index + 1], facets[index + 3]};
133
134 // Get cell geometry
135 auto x_dofs0 = MDSPAN_IMPL_STANDARD_NAMESPACE::
136 MDSPAN_IMPL_PROPOSED_NAMESPACE::submdspan(
137 x_dofmap, cells[0], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
138 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
139 {
140 std::copy_n(std::next(x.begin(), 3 * x_dofs0[i]), 3,
141 std::next(cdofs0.begin(), 3 * i));
142 }
143 auto x_dofs1 = MDSPAN_IMPL_STANDARD_NAMESPACE::
144 MDSPAN_IMPL_PROPOSED_NAMESPACE::submdspan(
145 x_dofmap, cells[1], MDSPAN_IMPL_STANDARD_NAMESPACE::full_extent);
146 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
147 {
148 std::copy_n(std::next(x.begin(), 3 * x_dofs1[i]), 3,
149 std::next(cdofs1.begin(), 3 * i));
150 }
151
152 const std::array perm{perms[cells[0] * num_cell_facets + local_facet[0]],
153 perms[cells[1] * num_cell_facets + local_facet[1]]};
154 fn(&value, coeffs.data() + index / 2 * cstride, constants.data(),
155 coordinate_dofs.data(), local_facet.data(), perm.data());
156 }
157
158 return value;
159}
160
162template <dolfinx::scalar T, std::floating_point U>
163T assemble_scalar(
164 const fem::Form<T, U>& M, mdspan2_t x_dofmap,
165 std::span<const scalar_value_type_t<T>> x, std::span<const T> constants,
166 const std::map<std::pair<IntegralType, int>,
167 std::pair<std::span<const T>, int>>& coefficients)
168{
169 std::shared_ptr<const mesh::Mesh<U>> mesh = M.mesh();
170 assert(mesh);
171
172 T value = 0;
173 for (int i : M.integral_ids(IntegralType::cell))
174 {
175 auto fn = M.kernel(IntegralType::cell, i);
176 assert(fn);
177 auto& [coeffs, cstride] = coefficients.at({IntegralType::cell, i});
178 std::span<const std::int32_t> cells = M.domain(IntegralType::cell, i);
179 value += impl::assemble_cells(x_dofmap, x, cells, fn, constants, coeffs,
180 cstride);
181 }
182
183 for (int i : M.integral_ids(IntegralType::exterior_facet))
184 {
185 auto fn = M.kernel(IntegralType::exterior_facet, i);
186 assert(fn);
187 auto& [coeffs, cstride]
188 = coefficients.at({IntegralType::exterior_facet, i});
189 value += impl::assemble_exterior_facets(
190 x_dofmap, x, M.domain(IntegralType::exterior_facet, i), fn, constants,
191 coeffs, cstride);
192 }
193
194 if (M.num_integrals(IntegralType::interior_facet) > 0)
195 {
196 mesh->topology_mutable()->create_entity_permutations();
197 const std::vector<std::uint8_t>& perms
198 = mesh->topology()->get_facet_permutations();
199 auto cell_types = mesh->topology()->cell_types();
200 if (cell_types.size() > 1)
201 throw std::runtime_error("Multiple cell types in the assembler");
202 int num_cell_facets = mesh::cell_num_entities(cell_types.back(),
203 mesh->topology()->dim() - 1);
204 const std::vector<int> c_offsets = M.coefficient_offsets();
205 for (int i : M.integral_ids(IntegralType::interior_facet))
206 {
207 auto fn = M.kernel(IntegralType::interior_facet, i);
208 assert(fn);
209 auto& [coeffs, cstride]
210 = coefficients.at({IntegralType::interior_facet, i});
211 value += impl::assemble_interior_facets(
212 x_dofmap, x, num_cell_facets,
213 M.domain(IntegralType::interior_facet, i), fn, constants, coeffs,
214 cstride, c_offsets, perms);
215 }
216 }
217
218 return value;
219}
220
221} // namespace dolfinx::fem::impl
void cells(la::SparsityPattern &pattern, std::span< const std::int32_t > cells, std::array< std::reference_wrapper< const DofMap >, 2 > dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition sparsitybuild.cpp:18
IntegralType
Type of integral.
Definition Form.h:33
@ interior_facet
Interior facet.
@ exterior_facet
Exterior facet.
int cell_num_entities(CellType type, int dim)
Number of entities of dimension dim.
Definition cell_types.cpp:139