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.6.0
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 <typename T>
26T assemble_cells(const mesh::Geometry& geometry,
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 // Prepare cell geometry
36 const graph::AdjacencyList<std::int32_t>& x_dofmap = geometry.dofmap();
37 const std::size_t num_dofs_g = geometry.cmap().dim();
38 std::span<const double> x = geometry.x();
39
40 // Create data structures used in assembly
41 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * num_dofs_g);
42
43 // Iterate over all cells
44 for (std::size_t index = 0; index < cells.size(); ++index)
45 {
46 std::int32_t c = cells[index];
47
48 // Get cell coordinates/geometry
49 auto x_dofs = x_dofmap.links(c);
50 for (std::size_t i = 0; i < x_dofs.size(); ++i)
51 {
52 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
53 std::next(coordinate_dofs.begin(), 3 * i));
54 }
55
56 const T* coeff_cell = coeffs.data() + index * cstride;
57 fn(&value, coeff_cell, constants.data(), coordinate_dofs.data(), nullptr,
58 nullptr);
59 }
60
61 return value;
62}
63
65template <typename T>
66T assemble_exterior_facets(const mesh::Geometry& geometry,
67 std::span<const std::int32_t> facets,
68 FEkernel<T> auto fn, std::span<const T> constants,
69 std::span<const T> coeffs, int cstride)
70{
71 T value(0);
72 if (facets.empty())
73 return value;
74
75 // Prepare cell geometry
76 const graph::AdjacencyList<std::int32_t>& x_dofmap = geometry.dofmap();
77 const std::size_t num_dofs_g = geometry.cmap().dim();
78 std::span<const double> x = geometry.x();
79
80 // Create data structures used in assembly
81 std::vector<scalar_value_type_t<T>> coordinate_dofs(3 * num_dofs_g);
82
83 // Iterate over all facets
84 assert(facets.size() % 2 == 0);
85 for (std::size_t index = 0; index < facets.size(); index += 2)
86 {
87 std::int32_t cell = facets[index];
88 std::int32_t local_facet = facets[index + 1];
89
90 // Get cell coordinates/geometry
91 auto x_dofs = x_dofmap.links(cell);
92 for (std::size_t i = 0; i < x_dofs.size(); ++i)
93 {
94 std::copy_n(std::next(x.begin(), 3 * x_dofs[i]), 3,
95 std::next(coordinate_dofs.begin(), 3 * i));
96 }
97
98 const T* coeff_cell = coeffs.data() + index / 2 * cstride;
99 fn(&value, coeff_cell, constants.data(), coordinate_dofs.data(),
100 &local_facet, nullptr);
101 }
102
103 return value;
104}
105
107template <typename T>
108T assemble_interior_facets(const mesh::Geometry& geometry, int num_cell_facets,
109 std::span<const std::int32_t> facets,
110 FEkernel<T> auto fn, std::span<const T> constants,
111 std::span<const T> coeffs, int cstride,
112 std::span<const int> offsets,
113 std::span<const std::uint8_t> perms)
114{
115 T value(0);
116 if (facets.empty())
117 return value;
118
119 // Prepare cell geometry
120 const graph::AdjacencyList<std::int32_t>& x_dofmap = geometry.dofmap();
121 const std::size_t num_dofs_g = geometry.cmap().dim();
122 std::span<const double> x = geometry.x();
123
124 // Create data structures used in assembly
125 using X = scalar_value_type_t<T>;
126 std::vector<X> coordinate_dofs(2 * num_dofs_g * 3);
127 std::span<X> cdofs0(coordinate_dofs.data(), num_dofs_g * 3);
128 std::span<X> cdofs1(coordinate_dofs.data() + num_dofs_g * 3, num_dofs_g * 3);
129
130 std::vector<T> coeff_array(2 * offsets.back());
131 assert(offsets.back() == cstride);
132
133 // Iterate over all facets
134 assert(facets.size() % 4 == 0);
135 for (std::size_t index = 0; index < facets.size(); index += 4)
136 {
137 std::array<std::int32_t, 2> cells = {facets[index], facets[index + 2]};
138 std::array<std::int32_t, 2> local_facet
139 = {facets[index + 1], facets[index + 3]};
140
141 // Get cell geometry
142 auto x_dofs0 = x_dofmap.links(cells[0]);
143 for (std::size_t i = 0; i < x_dofs0.size(); ++i)
144 {
145 std::copy_n(std::next(x.begin(), 3 * x_dofs0[i]), 3,
146 std::next(cdofs0.begin(), 3 * i));
147 }
148 auto x_dofs1 = x_dofmap.links(cells[1]);
149 for (std::size_t i = 0; i < x_dofs1.size(); ++i)
150 {
151 std::copy_n(std::next(x.begin(), 3 * x_dofs1[i]), 3,
152 std::next(cdofs1.begin(), 3 * i));
153 }
154
155 const std::array perm{perms[cells[0] * num_cell_facets + local_facet[0]],
156 perms[cells[1] * num_cell_facets + local_facet[1]]};
157 fn(&value, coeffs.data() + index / 2 * cstride, constants.data(),
158 coordinate_dofs.data(), local_facet.data(), perm.data());
159 }
160
161 return value;
162}
163
165template <typename T>
166T assemble_scalar(
167 const fem::Form<T>& M, std::span<const T> constants,
168 const std::map<std::pair<IntegralType, int>,
169 std::pair<std::span<const T>, int>>& coefficients)
170{
171 std::shared_ptr<const mesh::Mesh> mesh = M.mesh();
172 assert(mesh);
173
174 T value = 0;
175 for (int i : M.integral_ids(IntegralType::cell))
176 {
177 const auto& fn = M.kernel(IntegralType::cell, i);
178 const auto& [coeffs, cstride] = coefficients.at({IntegralType::cell, i});
179 const std::vector<std::int32_t>& cells = M.cell_domains(i);
180 value += impl::assemble_cells(mesh->geometry(), cells, fn, constants,
181 coeffs, cstride);
182 }
183
184 for (int i : M.integral_ids(IntegralType::exterior_facet))
185 {
186 const auto& fn = M.kernel(IntegralType::exterior_facet, i);
187 const auto& [coeffs, cstride]
188 = coefficients.at({IntegralType::exterior_facet, i});
189 const std::vector<std::int32_t>& facets = M.exterior_facet_domains(i);
190 value += impl::assemble_exterior_facets(mesh->geometry(), facets, fn,
191 constants, coeffs, cstride);
192 }
193
194 if (M.num_integrals(IntegralType::interior_facet) > 0)
195 {
196 mesh->topology_mutable().create_entity_permutations();
197
198 const std::vector<std::uint8_t>& perms
199 = mesh->topology().get_facet_permutations();
200
201 int num_cell_facets = mesh::cell_num_entities(mesh->topology().cell_type(),
202 mesh->topology().dim() - 1);
203 const std::vector<int> c_offsets = M.coefficient_offsets();
204 for (int i : M.integral_ids(IntegralType::interior_facet))
205 {
206 const auto& fn = M.kernel(IntegralType::interior_facet, i);
207 const auto& [coeffs, cstride]
208 = coefficients.at({IntegralType::interior_facet, i});
209 const std::vector<std::int32_t>& facets = M.interior_facet_domains(i);
210 value += impl::assemble_interior_facets(mesh->geometry(), num_cell_facets,
211 facets, fn, constants, coeffs,
212 cstride, c_offsets, perms);
213 }
214 }
215
216 return value;
217}
218
219} // namespace dolfinx::fem::impl
void cells(la::SparsityPattern &pattern, const mesh::Topology &topology, const std::array< const std::reference_wrapper< const DofMap >, 2 > &dofmaps)
Iterate over cells and insert entries into sparsity pattern.
Definition: sparsitybuild.cpp:18
@ 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