MFEM v4.7.0
Finite element discretization library
Loading...
Searching...
No Matches
restriction.cpp
Go to the documentation of this file.
1// Copyright (c) 2010-2024, Lawrence Livermore National Security, LLC. Produced
2// at the Lawrence Livermore National Laboratory. All Rights reserved. See files
3// LICENSE and NOTICE for details. LLNL-CODE-806117.
4//
5// This file is part of the MFEM library. For more information and source code
6// availability visit https://mfem.org.
7//
8// MFEM is free software; you can redistribute it and/or modify it under the
9// terms of the BSD-3 license. We welcome feedback and contributions, see file
10// CONTRIBUTING.md for details.
11
12#include "../../../fem/gridfunc.hpp"
13#include "ceed.hpp"
14
15namespace mfem
16{
17
18namespace ceed
19{
20
21#ifdef MFEM_USE_CEED
22
23static void InitNativeRestr(const mfem::FiniteElementSpace &fes,
24 Ceed ceed, CeedElemRestriction *restr)
25{
26 const mfem::FiniteElement *fe = fes.GetFE(0);
27 const int P = fe->GetDof();
28 CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
29 const mfem::Table &el_dof = fes.GetElementToDofTable();
30 mfem::Array<int> tp_el_dof(el_dof.Size_of_connections());
31 const mfem::TensorBasisElement * tfe =
32 dynamic_cast<const mfem::TensorBasisElement *>(fe);
33 const int stride = compstride == 1 ? fes.GetVDim() : 1;
34 const mfem::Array<int>& dof_map = tfe->GetDofMap();
35
36 for (int i = 0; i < fes.GetNE(); i++)
37 {
38 const int el_offset = P * i;
39 for (int j = 0; j < P; j++)
40 {
41 tp_el_dof[j+el_offset] = stride*el_dof.GetJ()[dof_map[j]+el_offset];
42 }
43 }
44
45 CeedElemRestrictionCreate(ceed, fes.GetNE(), P, fes.GetVDim(),
46 compstride, (fes.GetVDim())*(fes.GetNDofs()),
47 CEED_MEM_HOST, CEED_COPY_VALUES,
48 tp_el_dof.GetData(), restr);
49}
50
51static void InitLexicoRestr(const mfem::FiniteElementSpace &fes,
52 Ceed ceed, CeedElemRestriction *restr)
53{
54 const mfem::FiniteElement *fe = fes.GetFE(0);
55 const int P = fe->GetDof();
56 CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
57 const mfem::Table &el_dof = fes.GetElementToDofTable();
58 mfem::Array<int> tp_el_dof(el_dof.Size_of_connections());
59 const int stride = compstride == 1 ? fes.GetVDim() : 1;
60
61 for (int e = 0; e < fes.GetNE(); e++)
62 {
63 for (int i = 0; i < P; i++)
64 {
65 tp_el_dof[i + e*P] = stride*el_dof.GetJ()[i + e*P];
66 }
67 }
68
69 CeedElemRestrictionCreate(ceed, fes.GetNE(), P, fes.GetVDim(),
70 compstride, (fes.GetVDim())*(fes.GetNDofs()),
71 CEED_MEM_HOST, CEED_COPY_VALUES,
72 tp_el_dof.GetData(), restr);
73}
74
75static void InitRestrictionImpl(const mfem::FiniteElementSpace &fes,
76 Ceed ceed, CeedElemRestriction *restr)
77{
78 const mfem::FiniteElement *fe = fes.GetFE(0);
79 const mfem::TensorBasisElement * tfe =
80 dynamic_cast<const mfem::TensorBasisElement *>(fe);
81 if ( tfe && tfe->GetDofMap().Size()>0 ) // Native ordering using dof_map
82 {
83 InitNativeRestr(fes, ceed, restr);
84 }
85 else // Lexicographic ordering
86 {
87 InitLexicoRestr(fes, ceed, restr);
88 }
89}
90
91static void InitNativeRestrWithIndices(
92 const mfem::FiniteElementSpace &fes,
93 int nelem,
94 const int* indices,
95 Ceed ceed, CeedElemRestriction *restr)
96{
97 const mfem::FiniteElement *fe = fes.GetFE(indices[0]);
98 const int P = fe->GetDof();
99 CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
100 mfem::Array<int> tp_el_dof(nelem*P);
101 const mfem::TensorBasisElement * tfe =
102 dynamic_cast<const mfem::TensorBasisElement *>(fe);
103 Array<int> dofs;
104 const int stride = compstride == 1 ? fes.GetVDim() : 1;
105 const mfem::Array<int>& dof_map = tfe->GetDofMap();
106
107 for (int i = 0; i < nelem; i++)
108 {
109 const int elem_index = indices[i];
110 fes.GetElementDofs(elem_index, dofs);
111 const int el_offset = P * i;
112 for (int j = 0; j < P; j++)
113 {
114 tp_el_dof[j + el_offset] = stride*dofs[dof_map[j]];
115 }
116 }
117
118 CeedElemRestrictionCreate(ceed, nelem, P, fes.GetVDim(),
119 compstride, (fes.GetVDim())*(fes.GetNDofs()),
120 CEED_MEM_HOST, CEED_COPY_VALUES,
121 tp_el_dof.GetData(), restr);
122}
123
124static void InitLexicoRestrWithIndices(
125 const mfem::FiniteElementSpace &fes,
126 int nelem,
127 const int* indices,
128 Ceed ceed, CeedElemRestriction *restr)
129{
130 const mfem::FiniteElement *fe = fes.GetFE(indices[0]);
131 const int P = fe->GetDof();
132 CeedInt compstride = fes.GetOrdering()==Ordering::byVDIM ? 1 : fes.GetNDofs();
133 mfem::Array<int> tp_el_dof(nelem*P);
134 Array<int> dofs;
135 const int stride = compstride == 1 ? fes.GetVDim() : 1;
136
137 for (int i = 0; i < nelem; i++)
138 {
139 const int elem_index = indices[i];
140 fes.GetElementDofs(elem_index, dofs);
141 const int el_offset = P * i;
142 for (int j = 0; j < P; j++)
143 {
144 tp_el_dof[j + el_offset] = stride*dofs[j];
145 }
146 }
147
148 CeedElemRestrictionCreate(ceed, nelem, P, fes.GetVDim(),
149 compstride, (fes.GetVDim())*(fes.GetNDofs()),
150 CEED_MEM_HOST, CEED_COPY_VALUES,
151 tp_el_dof.GetData(), restr);
152}
153
154static void InitRestrictionWithIndicesImpl(
155 const mfem::FiniteElementSpace &fes,
156 int nelem,
157 const int* indices,
158 Ceed ceed, CeedElemRestriction *restr)
159{
160 const mfem::FiniteElement *fe = fes.GetFE(indices[0]);
161 const mfem::TensorBasisElement * tfe =
162 dynamic_cast<const mfem::TensorBasisElement *>(fe);
163 if ( tfe && tfe->GetDofMap().Size()>0 ) // Native ordering using dof_map
164 {
165 InitNativeRestrWithIndices(fes, nelem, indices, ceed, restr);
166 }
167 else // Lexicographic ordering
168 {
169 InitLexicoRestrWithIndices(fes, nelem, indices, ceed, restr);
170 }
171}
172
173static void InitCoeffRestrictionWithIndicesImpl(
174 const mfem::FiniteElementSpace &fes,
175 int nelem,
176 const int* indices,
177 int nquads,
178 int ncomp,
179 Ceed ceed,
180 CeedElemRestriction *restr)
181{
182 mfem::Array<int> tp_el_dof(nelem*nquads);
183 const int stride_quad = ncomp;
184 const int stride_elem = ncomp*nquads;
185 // TODO generalize to support different #quads
186 for (int i = 0; i < nelem; i++)
187 {
188 const int elem_index = indices[i];
189 const int el_offset = elem_index * stride_elem;
190 for (int j = 0; j < nquads; j++)
191 {
192 tp_el_dof[j + nquads * i] = j * stride_quad + el_offset;
193 }
194 }
195 CeedElemRestrictionCreate(ceed, nelem, nquads, ncomp, 1,
196 ncomp*fes.GetNE()*nquads,
197 CEED_MEM_HOST, CEED_COPY_VALUES,
198 tp_el_dof.GetData(), restr);
199}
200
202 CeedInt nelem, CeedInt nqpts, CeedInt qdatasize,
203 const CeedInt *strides,
204 CeedElemRestriction *restr)
205{
206 RestrKey restr_key(&fes, nelem, nqpts, qdatasize, restr_type::Strided);
207 auto restr_itr = mfem::internal::ceed_restr_map.find(restr_key);
208 if (restr_itr == mfem::internal::ceed_restr_map.end())
209 {
210 CeedElemRestrictionCreateStrided(mfem::internal::ceed, nelem, nqpts, qdatasize,
211 nelem*nqpts*qdatasize,
212 strides,
213 restr);
214 // Will be automatically destroyed when @a fes gets destroyed.
215 mfem::internal::ceed_restr_map[restr_key] = *restr;
216 }
217 else
218 {
219 *restr = restr_itr->second;
220 }
221}
222
224 Ceed ceed,
225 CeedElemRestriction *restr)
226{
227 // Check for FES -> basis, restriction in hash tables
228 const mfem::FiniteElement *fe = fes.GetFE(0);
229 const int P = fe->GetDof();
230 const int nelem = fes.GetNE();
231 const int ncomp = fes.GetVDim();
232 RestrKey restr_key(&fes, nelem, P, ncomp, restr_type::Standard);
233 auto restr_itr = mfem::internal::ceed_restr_map.find(restr_key);
234
235 // Init or retrieve key values
236 if (restr_itr == mfem::internal::ceed_restr_map.end())
237 {
238 InitRestrictionImpl(fes, ceed, restr);
239 mfem::internal::ceed_restr_map[restr_key] = *restr;
240 }
241 else
242 {
243 *restr = restr_itr->second;
244 }
245}
246
248 int nelem,
249 const int* indices,
250 Ceed ceed,
251 CeedElemRestriction *restr)
252{
253 // Check for FES -> basis, restriction in hash tables
254 const mfem::FiniteElement *fe = fes.GetFE(indices[0]);
255 const int P = fe->GetDof();
256 const int ncomp = fes.GetVDim();
257 RestrKey restr_key(&fes, nelem, P, ncomp, restr_type::Standard);
258 auto restr_itr = mfem::internal::ceed_restr_map.find(restr_key);
259
260 // Init or retrieve key values
261 if (restr_itr == mfem::internal::ceed_restr_map.end())
262 {
263 InitRestrictionWithIndicesImpl(fes, nelem, indices, ceed, restr);
264 mfem::internal::ceed_restr_map[restr_key] = *restr;
265 }
266 else
267 {
268 *restr = restr_itr->second;
269 }
270}
271
273 int nelem,
274 const int* indices,
275 int nquads,
276 int ncomp,
277 Ceed ceed,
278 CeedElemRestriction *restr)
279{
280 // Check for FES -> basis, restriction in hash tables
281 RestrKey restr_key(&fes, nelem, nquads, ncomp, restr_type::Coeff);
282 auto restr_itr = mfem::internal::ceed_restr_map.find(restr_key);
283
284 // Init or retrieve key values
285 if (restr_itr == mfem::internal::ceed_restr_map.end())
286 {
287 InitCoeffRestrictionWithIndicesImpl(fes, nelem, indices, nquads, ncomp,
288 ceed, restr);
289 mfem::internal::ceed_restr_map[restr_key] = *restr;
290 }
291 else
292 {
293 *restr = restr_itr->second;
294 }
295}
296
297#endif
298
299} // namespace ceed
300
301} // namespace mfem
int Size() const
Return the logical size of the array.
Definition: array.hpp:144
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:220
const Table & GetElementToDofTable() const
Return a reference to the internal Table that stores the lists of scalar dofs, for each mesh element,...
Definition: fespace.hpp:1136
DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element 'elem'. The returned indices are offsets into an ldo...
Definition: fespace.cpp:2846
int GetNDofs() const
Returns number of degrees of freedom. This is the number of Local Degrees of Freedom.
Definition: fespace.hpp:710
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i'th element in t...
Definition: fespace.cpp:3168
Ordering::Type GetOrdering() const
Return the ordering method.
Definition: fespace.hpp:725
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:740
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:706
Abstract class for all finite elements.
Definition: fe_base.hpp:239
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe_base.hpp:329
int * GetJ()
Definition: table.hpp:114
int Size_of_connections() const
Definition: table.hpp:98
const Array< int > & GetDofMap() const
Get an Array<int> that maps lexicographically ordered indices to the indices of the respective nodes/...
Definition: fe_base.hpp:1222
void InitCoeffRestrictionWithIndices(const FiniteElementSpace &fes, int nelem, const int *indices, int nquads, int ncomp, Ceed ceed, CeedElemRestriction *restr)
Initialize a CeedElemRestriction for a mfem::Coefficient on a mixed mesh.
std::tuple< const mfem::FiniteElementSpace *, int, int, int, int > RestrKey
Definition: util.hpp:150
void InitStridedRestriction(const mfem::FiniteElementSpace &fes, CeedInt nelem, CeedInt nqpts, CeedInt qdatasize, const CeedInt *strides, CeedElemRestriction *restr)
Initialize a strided CeedElemRestriction.
void InitRestriction(const FiniteElementSpace &fes, Ceed ceed, CeedElemRestriction *restr)
Initialize a CeedElemRestriction for non-mixed meshes.
void InitRestrictionWithIndices(const FiniteElementSpace &fes, int nelem, const int *indices, Ceed ceed, CeedElemRestriction *restr)
Initialize a CeedElemRestriction for mixed meshes.
@ Standard
Definition: util.hpp:146
@ Strided
Definition: util.hpp:146