MFEM  v4.5.1
Finite element discretization library
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Pages
restriction.cpp
Go to the documentation of this file.
1 // Copyright (c) 2010-2022, 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 
15 namespace mfem
16 {
17 
18 namespace ceed
19 {
20 
21 #ifdef MFEM_USE_CEED
22 
23 static 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 
51 static 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 
75 static 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 
91 static 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 
124 static 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 
154 static 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 
173 static 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
Abstract class for all finite elements.
Definition: fe_base.hpp:235
Ordering::Type GetOrdering() const
Return the ordering method.
Definition: fespace.hpp:599
int Size() const
Return the logical size of the array.
Definition: array.hpp:138
int GetNDofs() const
Returns number of degrees of freedom.
Definition: fespace.hpp:584
int * GetJ()
Definition: table.hpp:114
std::tuple< const mfem::FiniteElementSpace *, int, int, int, int > RestrKey
Definition: util.hpp:132
int Size_of_connections() const
Definition: table.hpp:98
int GetNE() const
Returns number of elements in the mesh.
Definition: fespace.hpp:614
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.
int GetVDim() const
Returns vector dimension.
Definition: fespace.hpp:581
virtual DofTransformation * GetElementDofs(int elem, Array< int > &dofs) const
Returns indices of degrees of freedom of element &#39;elem&#39;.
Definition: fespace.cpp:2678
Class FiniteElementSpace - responsible for providing FEM view of the mesh, mainly managing the set of...
Definition: fespace.hpp:96
int GetDof() const
Returns the number of degrees of freedom in the finite element.
Definition: fe_base.hpp:323
void InitStridedRestriction(const mfem::FiniteElementSpace &fes, CeedInt nelem, CeedInt nqpts, CeedInt qdatasize, const CeedInt *strides, CeedElemRestriction *restr)
Initialize a strided CeedElemRestriction.
const Array< int > & GetDofMap() const
Get an Array&lt;int&gt; that maps lexicographically ordered indices to the indices of the respective nodes/...
Definition: fe_base.hpp:1182
void InitRestrictionWithIndices(const FiniteElementSpace &fes, int nelem, const int *indices, Ceed ceed, CeedElemRestriction *restr)
Initialize a CeedElemRestriction for mixed meshes.
virtual const FiniteElement * GetFE(int i) const
Returns pointer to the FiniteElement in the FiniteElementCollection associated with i&#39;th element in t...
Definition: fespace.cpp:2781
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:750
void InitRestriction(const FiniteElementSpace &fes, Ceed ceed, CeedElemRestriction *restr)
Initialize a CeedElemRestriction for non-mixed meshes.