IPPL (Independent Parallel Particle Layer)
IPPL
Loading...
Searching...
No Matches
FiniteElementSpace.hpp
Go to the documentation of this file.
1
2namespace ippl {
3 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
4 typename QuadratureType, typename FieldLHS, typename FieldRHS>
5 FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
7 ElementType& ref_element,
8 const QuadratureType& quadrature)
9 : mesh_m(mesh)
10 , ref_element_m(ref_element)
11 , quadrature_m(quadrature) {
12 assert(mesh.Dimension == Dim && "Mesh dimension does not match the dimension of the space");
13
14 nr_m = mesh_m.getGridsize();
15 hr_m = mesh_m.getMeshSpacing();
16 origin_m = mesh_m.getOrigin();
17
18 /*for (size_t d = 0; d < Dim; ++d) {
19 assert(nr_m[d] > 1 && "Mesh has no cells in at least one dimension");
20 }*/
21 }
22
23 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
24 typename QuadratureType, typename FieldLHS, typename FieldRHS>
25 void FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
27 {
28 assert(mesh.Dimension == Dim && "Mesh dimension does not match the dimension of the space");
29
30 mesh_m = mesh;
31
32 nr_m = mesh_m.getGridsize();
33 hr_m = mesh_m.getMeshSpacing();
34 origin_m = mesh_m.getOrigin();
35
36 for (size_t d = 0; d < Dim; ++d) {
37 assert(nr_m[d] > 1 && "Mesh has no cells in at least one dimension");
38 }
39 }
40
41 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
42 typename QuadratureType, typename FieldLHS, typename FieldRHS>
43 KOKKOS_FUNCTION size_t FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
44 FieldLHS, FieldRHS>::numElements() const {
45 Vector<size_t, Dim> cells_per_dim = nr_m - 1u;
46
47 size_t num_elements = 1;
48 for (size_t d = 0; d < Dim; ++d) {
49 num_elements *= cells_per_dim[d];
50 }
51
52 return num_elements;
53 }
54
55 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
56 typename QuadratureType, typename FieldLHS, typename FieldRHS>
57 KOKKOS_FUNCTION size_t
58 FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
59 FieldRHS>::numElementsInDim(const size_t& dim) const {
60 return nr_m[dim] - 1u;
61 }
62
63 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
64 typename QuadratureType, typename FieldLHS, typename FieldRHS>
65 KOKKOS_FUNCTION typename FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
66 FieldLHS, FieldRHS>::indices_t
67 FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
68 FieldRHS>::getMeshVertexNDIndex(const size_t& vertex_index) const {
69 // Copy the vertex index to the index variable we can alter during the computation.
70 size_t index = vertex_index;
71
72 // Create a vector to store the vertex indices in each dimension for the corresponding
73 // vertex.
74 indices_t vertex_indices;
75
76 // This is the number of vertices in each dimension.
77 Vector<size_t, Dim> vertices_per_dim = nr_m;
78
79 // The number_of_lower_dim_vertices is the product of the number of vertices per
80 // dimension, it will get divided by the current dimensions number to get the index in
81 // that dimension
82 size_t remaining_number_of_vertices = 1;
83 for (const size_t num_vertices : vertices_per_dim) {
84 remaining_number_of_vertices *= num_vertices;
85 }
86
87 for (int d = Dim - 1; d >= 0; --d) {
88 remaining_number_of_vertices /= vertices_per_dim[d];
89 vertex_indices[d] = index / remaining_number_of_vertices;
90 index -= vertex_indices[d] * remaining_number_of_vertices;
91 }
92
93 return vertex_indices;
94 };
95
96 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
97 typename QuadratureType, typename FieldLHS, typename FieldRHS>
98 KOKKOS_FUNCTION size_t
101 const FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
102 FieldRHS>::indices_t& vertexNDIndex) const {
103 // Compute the vector to multiply the ndindex with
105 for (size_t d = 1; d < dim; ++d) {
106 for (size_t d2 = d; d2 < Dim; ++d2) {
107 vec[d2] *= nr_m[d - 1];
108 }
109 }
110
111 // return the dot product between the vertex ndindex and vec.
112 return vertexNDIndex.dot(vec);
113 }
114
115 // implementation of function to retrieve the index of an element in each dimension
116 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
117 typename QuadratureType, typename FieldLHS, typename FieldRHS>
118 KOKKOS_FUNCTION typename FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
119 FieldLHS, FieldRHS>::indices_t
120 FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
121 FieldRHS>::getElementNDIndex(const size_t& element_index) const {
122 // Copy the element index to the index variable we can alter during the computation.
123 size_t index = element_index;
124
125 // Create a vector to store the element indices in each dimension for the corresponding
126 // element.
127 indices_t element_nd_index;
128
129 // This is the number of cells in each dimension. It is one less than the number of
130 // vertices in each dimension, which is in nr_m (mesh.getGridsize()).
131 Vector<size_t, Dim> cells_per_dim = nr_m - 1;
132
133 // The number_of_lower_dim_cells is the product of all the number of cells per
134 // dimension, it will get divided by the current dimension's size to get the index in
135 // that dimension
136 size_t remaining_number_of_cells = 1;
137 for (const size_t num_cells : cells_per_dim) {
138 remaining_number_of_cells *= num_cells;
139 }
140
141 for (int d = Dim - 1; d >= 0; --d) {
142 remaining_number_of_cells /= cells_per_dim[d];
143 element_nd_index[d] = (index / remaining_number_of_cells);
144 index -= (element_nd_index[d]) * remaining_number_of_cells;
145 }
147 return element_nd_index;
148 }
149
150 // implementation of function to retrieve the global index of an element given the ndindex
151 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
152 typename QuadratureType, typename FieldLHS, typename FieldRHS>
153 KOKKOS_FUNCTION size_t
156 const FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
157 FieldRHS>::indices_t& ndindex) const {
158 size_t element_index = 0;
159
160 // This is the number of cells in each dimension. It is one less than the number of
161 // vertices in each dimension, which is returned by Mesh::getGridsize().
162 Vector<size_t, Dim> cells_per_dim = nr_m - 1;
163
164 size_t remaining_number_of_cells = 1;
165
166 for (unsigned int d = 0; d < Dim; ++d) {
167 element_index += ndindex[d] * remaining_number_of_cells;
168 remaining_number_of_cells *= cells_per_dim[d];
169 }
170
171 return element_index;
172 }
173
174 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
175 typename QuadratureType, typename FieldLHS, typename FieldRHS>
176 KOKKOS_FUNCTION typename FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
177 FieldLHS, FieldRHS>::vertex_indices_t
180 const FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
181 FieldRHS>::indices_t& element_nd_index) const {
182 const Vector<size_t, Dim> num_vertices = nr_m;
183
184 size_t smallest_vertex_index = 0;
185 for (int d = Dim - 1; d >= 0; --d) {
186 size_t temp_index = element_nd_index[d];
187 for (int i = d; i >= 1; --i) {
188 temp_index *= num_vertices[i];
189 }
190 smallest_vertex_index += temp_index;
191 }
192
193 // Vector to store the vertex indices for the element
194 vertex_indices_t vertex_indices;
195 vertex_indices[0] = smallest_vertex_index;
196 vertex_indices[1] = vertex_indices[0] + 1;
197
198 /*
199 The following for loop computes the following computations:
200
201 2D:
202 vertex_indices[2] = vertex_indices[0] + num_vertices[0];
203 vertex_indices[3] = vertex_indices[1] + num_vertices[0];
204 3D:
205 vertex_indices[4] = vertex_indices[0] + (num_vertices[0] * num_vertices[1]);
206 vertex_indices[5] = vertex_indices[1] + (num_vertices[0] * num_vertices[1]);
207 vertex_indices[6] = vertex_indices[2] + (num_vertices[0] * num_vertices[1]);
208 vertex_indices[7] = vertex_indices[3] + (num_vertices[0] * num_vertices[1]);
209
210 ...
211 */
212
213 for (size_t d = 1; d < Dim; ++d) {
214 for (size_t i = 0; i < static_cast<unsigned>(1 << d); ++i) {
215 size_t size = 1;
216 for (size_t j = 0; j < d; ++j) {
217 size *= num_vertices[j];
218 }
219 vertex_indices[i + (1 << d)] = vertex_indices[i] + size;
220 }
221 }
222
223 return vertex_indices;
224 }
225
226 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
227 typename QuadratureType, typename FieldLHS, typename FieldRHS>
228 KOKKOS_FUNCTION typename FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
229 FieldLHS, FieldRHS>::indices_list_t
232 const FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
233 FieldRHS>::indices_t& elementNDIndex) const {
234 indices_list_t vertex_nd_indices;
235
236 indices_t smallest_vertex_nd_index = elementNDIndex;
237
238 // vertex_nd_indices[0] = smallest_vertex_nd_index;
239 // vertex_nd_indices[1] = smallest_vertex_nd_index;
240 // vertex_nd_indices[1][0] += 1;
241
242 // vertex_nd_indices[2] = vertex_nd_indices[0];
243 // vertex_nd_indices[2][1] += 1;
244 // vertex_nd_indices[3] = vertex_nd_indices[1];
245 // vertex_nd_indices[3][1] += 1;
246
247 // vertex_nd_indices[4] = vertex_nd_indices[0];
248 // vertex_nd_indices[4][2] += 1;
249 // vertex_nd_indices[5] = vertex_nd_indices[1];
250 // vertex_nd_indices[5][2] += 1;
251 // vertex_nd_indices[6] = vertex_nd_indices[2];
252 // vertex_nd_indices[6][2] += 1;
253 // vertex_nd_indices[7] = vertex_nd_indices[3];
254 // vertex_nd_indices[7][2] += 1;
255
256 for (size_t i = 0; i < (1 << Dim); ++i) {
257 vertex_nd_indices[i] = smallest_vertex_nd_index;
258 for (size_t j = 0; j < Dim; ++j) {
259 vertex_nd_indices[i][j] += (i >> j) & 1;
260 }
261 }
262
263 return vertex_nd_indices;
264 }
265
266 template <typename T, unsigned Dim, unsigned NumElementDOFs, typename ElementType,
267 typename QuadratureType, typename FieldLHS, typename FieldRHS>
268 KOKKOS_FUNCTION typename FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType,
269 FieldLHS, FieldRHS>::vertex_points_t
272 const FiniteElementSpace<T, Dim, NumElementDOFs, ElementType, QuadratureType, FieldLHS,
273 FieldRHS>::indices_t& elementNDIndex) const {
274 vertex_points_t vertex_points;
275
276 // get all the NDIndices for the vertices of this element
277 indices_list_t vertex_nd_indices = this->getElementMeshVertexNDIndices(elementNDIndex);
278
279 // get the coordinates of the vertices of this element
280 for (size_t i = 0; i < vertex_nd_indices.dim; ++i) {
281 NDIndex<Dim> temp_ndindex;
282 for (size_t d = 0; d < Dim; ++d) {
283 temp_ndindex[d] = Index(vertex_nd_indices[i][d], vertex_nd_indices[i][d]);
284 vertex_points[i][d] = (temp_ndindex[d].first() * this->hr_m[d]) + this->origin_m[d];
285 }
286 }
287 return vertex_points;
288 }
289
290} // namespace ippl
constexpr unsigned Dim
Definition Archive.h:20
The FiniteElementSpace class handles the mesh index mapping to vertices and elements and is the base ...
KOKKOS_FUNCTION vertex_indices_t getElementMeshVertexIndices(const indices_t &elementNDIndex) const
Get all the global vertex indices of an element (given by its NDIndex).
KOKKOS_FUNCTION size_t getElementIndex(const indices_t &ndindex) const
Get the global index of a mesh element given the NDIndex.
FiniteElementSpace(UniformCartesian< T, Dim > &mesh, ElementType &ref_element, const QuadratureType &quadrature)
Construct a new FiniteElementSpace object.
Vector< indices_t, numElementVertices > indices_list_t
static constexpr unsigned dim
Vector< size_t, numElementVertices > vertex_indices_t
KOKKOS_FUNCTION indices_list_t getElementMeshVertexNDIndices(const indices_t &elementNDIndex) const
Get all the NDIndices of the vertices of an element (given by its NDIndex).
const QuadratureType & quadrature_m
KOKKOS_FUNCTION size_t numElementsInDim(const size_t &dim) const
Get the number of elements in a given dimension.
Vector< size_t, Dim > nr_m
Vector< point_t, numElementVertices > vertex_points_t
KOKKOS_FUNCTION indices_t getMeshVertexNDIndex(const size_t &vertex_index) const
Get the NDIndex of a mesh vertex.
Vector< double, Dim > origin_m
KOKKOS_FUNCTION vertex_points_t getElementMeshVertexPoints(const indices_t &elementNDIndex) const
Get all the global vertex points of an element (given by its NDIndex).
void setMesh(UniformCartesian< T, Dim > &mesh)
UniformCartesian< T, Dim > & mesh_m
Member variables //////////////////////////////////////////////////.
KOKKOS_FUNCTION size_t getMeshVertexIndex(const indices_t &vertex_nd_index) const
Get the global index of a mesh vertex given its NDIndex.
KOKKOS_FUNCTION indices_t getElementNDIndex(const size_t &elementIndex) const
Get the NDIndex (vector of indices for each dimension) of a mesh element.
Vector< double, Dim > hr_m
KOKKOS_FUNCTION size_t numElements() const
Mesh and Element operations ///////////////////////////////////////.
KOKKOS_INLINE_FUNCTION Vector< int, Dim > first() const
Definition NDIndex.hpp:170
@ Dimension
Definition Mesh.h:19
static constexpr unsigned dim
Definition Vector.h:26