OGS
LocalDataInitializer.h
Go to the documentation of this file.
1 
11 #pragma once
12 
13 #include <functional>
14 #include <memory>
15 #include <type_traits>
16 #include <typeindex>
17 #include <typeinfo>
18 #include <unordered_map>
19 
23 
24 #ifndef OGS_MAX_ELEMENT_DIM
25 static_assert(false, "The macro OGS_MAX_ELEMENT_DIM is undefined.");
26 #endif
27 
28 #ifndef OGS_MAX_ELEMENT_ORDER
29 static_assert(false, "The macro OGS_MAX_ELEMENT_ORDER is undefined.");
30 #endif
31 
32 // The following macros decide which element types will be compiled, i.e.
33 // which element types will be available for use in simulations.
34 
35 #ifdef OGS_ENABLE_ELEMENT_SIMPLEX
36 #define ENABLED_ELEMENT_TYPE_SIMPLEX 1u
37 #else
38 #define ENABLED_ELEMENT_TYPE_SIMPLEX 0u
39 #endif
40 
41 #ifdef OGS_ENABLE_ELEMENT_CUBOID
42 #define ENABLED_ELEMENT_TYPE_CUBOID 1u << 1
43 #else
44 #define ENABLED_ELEMENT_TYPE_CUBOID 0u
45 #endif
46 
47 #ifdef OGS_ENABLE_ELEMENT_PRISM
48 #define ENABLED_ELEMENT_TYPE_PRISM 1u << 2
49 #else
50 #define ENABLED_ELEMENT_TYPE_PRISM 0u
51 #endif
52 
53 #ifdef OGS_ENABLE_ELEMENT_PYRAMID
54 #define ENABLED_ELEMENT_TYPE_PYRAMID 1u << 3
55 #else
56 #define ENABLED_ELEMENT_TYPE_PYRAMID 0u
57 #endif
58 
59 // Dependent element types.
60 // Faces of tets, pyramids and prisms are triangles
61 #define ENABLED_ELEMENT_TYPE_TRI \
62  ((ENABLED_ELEMENT_TYPE_SIMPLEX) | (ENABLED_ELEMENT_TYPE_PYRAMID) | \
63  (ENABLED_ELEMENT_TYPE_PRISM))
64 // Faces of hexes, pyramids and prisms are quads
65 #define ENABLED_ELEMENT_TYPE_QUAD \
66  ((ENABLED_ELEMENT_TYPE_CUBOID) | (ENABLED_ELEMENT_TYPE_PYRAMID) | \
67  (ENABLED_ELEMENT_TYPE_PRISM))
68 
69 // All enabled element types
70 #define OGS_ENABLED_ELEMENTS \
71  ((ENABLED_ELEMENT_TYPE_SIMPLEX) | (ENABLED_ELEMENT_TYPE_CUBOID) | \
72  (ENABLED_ELEMENT_TYPE_PYRAMID) | (ENABLED_ELEMENT_TYPE_PRISM))
73 
74 // Include only what is needed (Well, the conditions are not sharp).
75 #if OGS_ENABLED_ELEMENTS != 0
78 #endif
79 
80 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_SIMPLEX) != 0
83 #endif
84 
85 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_TRI) != 0
88 #endif
89 
90 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_CUBOID) != 0
93 #endif
94 
95 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_QUAD) != 0
99 #endif
100 
101 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PRISM) != 0
104 #endif
105 
106 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PYRAMID) != 0
109 #endif
110 
111 namespace ProcessLib
112 {
113 namespace LIE
114 {
115 namespace SmallDeformation
116 {
122 template <typename LocalAssemblerInterface,
123  template <typename, typename, int> class LocalAssemblerDataMatrix,
124  template <typename, typename, int>
125  class LocalAssemblerDataMatrixNearFracture,
126  template <typename, typename, int> class LocalAssemblerDataFracture,
127  int GlobalDim, typename... ConstructorArgs>
129 {
130 public:
131  using LADataIntfPtr = std::unique_ptr<LocalAssemblerInterface>;
132 
134  NumLib::LocalToGlobalIndexMap const& dof_table)
135  : _dof_table(dof_table)
136  {
137  // REMARKS: At the moment, only a 2D mesh with 1D elements are
138  // supported.
139 
140  // /// Quads and Hexahedra ///////////////////////////////////
141 
142 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_QUAD) != 0 && \
143  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 1
144  _builder[std::type_index(typeid(MeshLib::Quad))] =
145  makeLocalAssemblerBuilder<NumLib::ShapeQuad4>();
146 #endif
147 
148 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_CUBOID) != 0 && \
149  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 1
150  _builder[std::type_index(typeid(MeshLib::Hex))] =
151  makeLocalAssemblerBuilder<NumLib::ShapeHex8>();
152 #endif
153 
154 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_QUAD) != 0 && \
155  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
156  _builder[std::type_index(typeid(MeshLib::Quad8))] =
157  makeLocalAssemblerBuilder<NumLib::ShapeQuad8>();
158  _builder[std::type_index(typeid(MeshLib::Quad9))] =
159  makeLocalAssemblerBuilder<NumLib::ShapeQuad9>();
160 #endif
161 
162 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_CUBOID) != 0 && \
163  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
164  _builder[std::type_index(typeid(MeshLib::Hex20))] =
165  makeLocalAssemblerBuilder<NumLib::ShapeHex20>();
166 #endif
167 
168  // /// Simplices ////////////////////////////////////////////////
169 
170 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_TRI) != 0 && \
171  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 1
172  _builder[std::type_index(typeid(MeshLib::Tri))] =
173  makeLocalAssemblerBuilder<NumLib::ShapeTri3>();
174 #endif
175 
176 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_SIMPLEX) != 0 && \
177  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 1
178  _builder[std::type_index(typeid(MeshLib::Tet))] =
179  makeLocalAssemblerBuilder<NumLib::ShapeTet4>();
180 #endif
181 
182 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_TRI) != 0 && \
183  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
184  _builder[std::type_index(typeid(MeshLib::Tri6))] =
185  makeLocalAssemblerBuilder<NumLib::ShapeTri6>();
186 #endif
187 
188 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_SIMPLEX) != 0 && \
189  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
190  _builder[std::type_index(typeid(MeshLib::Tet10))] =
191  makeLocalAssemblerBuilder<NumLib::ShapeTet10>();
192 #endif
193 
194  // /// Prisms ////////////////////////////////////////////////////
195 
196 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PRISM) != 0 && \
197  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 1
198  _builder[std::type_index(typeid(MeshLib::Prism))] =
199  makeLocalAssemblerBuilder<NumLib::ShapePrism6>();
200 #endif
201 
202 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PRISM) != 0 && \
203  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
204  _builder[std::type_index(typeid(MeshLib::Prism15))] =
205  makeLocalAssemblerBuilder<NumLib::ShapePrism15>();
206 #endif
207 
208  // /// Pyramids //////////////////////////////////////////////////
209 
210 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PYRAMID) != 0 && \
211  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 1
212  _builder[std::type_index(typeid(MeshLib::Pyramid))] =
213  makeLocalAssemblerBuilder<NumLib::ShapePyra5>();
214 #endif
215 
216 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PYRAMID) != 0 && \
217  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
218  _builder[std::type_index(typeid(MeshLib::Pyramid13))] =
219  makeLocalAssemblerBuilder<NumLib::ShapePyra13>();
220 #endif
221  // /// Lines ///////////////////////////////////
222 
223 #if OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 1
224  _builder[std::type_index(typeid(MeshLib::Line))] =
225  makeLocalAssemblerBuilder<NumLib::ShapeLine2>();
226 #endif
227 
228 #if OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
229  _builder[std::type_index(typeid(MeshLib::Line3))] =
230  makeLocalAssemblerBuilder<NumLib::ShapeLine3>();
231 #endif
232  }
233 
239  LADataIntfPtr operator()(std::size_t const id,
240  MeshLib::Element const& mesh_item,
241  ConstructorArgs&&... args) const
242  {
243  auto const type_idx = std::type_index(typeid(mesh_item));
244  auto const it = _builder.find(type_idx);
245 
246  if (it == _builder.end())
247  {
248  OGS_FATAL(
249  "You are trying to build a local assembler for an unknown mesh "
250  "element type ({:s})."
251  " Maybe you have disabled this mesh element type in your build "
252  "configuration, or a mesh element order does not match shape "
253  "function order given in the project file.",
254  type_idx.name());
255  }
256 
257  auto const n_local_dof = _dof_table.getNumberOfElementDOF(id);
258  auto const n_global_components =
260  auto const varIDs = _dof_table.getElementVariableIDs(id);
261 
262  std::vector<unsigned> dofIndex_to_localIndex;
263  if (mesh_item.getDimension() < GlobalDim ||
264  n_global_components > GlobalDim)
265  {
266  dofIndex_to_localIndex.resize(n_local_dof);
267  unsigned dof_id = 0;
268  unsigned local_id = 0;
269  for (auto i : varIDs)
270  {
271  for (int j = 0; j < _dof_table.getNumberOfVariableComponents(i);
272  j++)
273  {
274  auto const& ms = _dof_table.getMeshSubset(i, j);
275  auto const mesh_id = ms.getMeshID();
276  for (unsigned k = 0; k < mesh_item.getNumberOfNodes(); k++)
277  {
278  MeshLib::Location l(mesh_id,
280  getNodeIndex(mesh_item, k));
281  auto global_index = _dof_table.getGlobalIndex(l, i, j);
282  if (global_index != NumLib::MeshComponentMap::nop)
283  {
284  dofIndex_to_localIndex[dof_id++] = local_id;
285  }
286  local_id++;
287  }
288  }
289  }
290  }
291 
292  return it->second(mesh_item, varIDs.size(), n_local_dof,
293  dofIndex_to_localIndex,
294  std::forward<ConstructorArgs>(args)...);
295  }
296 
297 private:
298  using LADataBuilder = std::function<LADataIntfPtr(
299  MeshLib::Element const& e,
300  std::size_t const n_variables,
301  std::size_t const local_matrix_size,
302  std::vector<unsigned> const& dofIndex_to_localIndex,
303  ConstructorArgs&&...)>;
304 
305  template <typename ShapeFunction>
307  typename ShapeFunction::MeshElement>::IntegrationMethod;
308 
309  template <typename ShapeFunction>
310  using LADataMatrix =
311  LocalAssemblerDataMatrix<ShapeFunction,
313 
317  template <typename ShapeFunction>
319  {
320  return makeLocalAssemblerBuilder<ShapeFunction>(
321  static_cast<std::integral_constant<
322  bool, (GlobalDim >= ShapeFunction::DIM)>*>(nullptr));
323  }
324 
326  std::unordered_map<std::type_index, LADataBuilder> _builder;
327 
329 
330  template <typename ShapeFunction>
331  using LADataMatrixNearFracture = LocalAssemblerDataMatrixNearFracture<
332  ShapeFunction, IntegrationMethod<ShapeFunction>, GlobalDim>;
333 
334  template <typename ShapeFunction>
336  LocalAssemblerDataFracture<ShapeFunction,
338 
339  // local assembler builder implementations.
340 private:
346  template <typename ShapeFunction>
347  static LADataBuilder makeLocalAssemblerBuilder(std::true_type* /*unused*/)
348  {
349  return [](MeshLib::Element const& e,
350  std::size_t const n_variables,
351  std::size_t const local_matrix_size,
352  std::vector<unsigned> const& dofIndex_to_localIndex,
353  ConstructorArgs&&... args) {
354  if (e.getDimension() == GlobalDim)
355  {
356  if (dofIndex_to_localIndex.empty())
357  {
359  e, local_matrix_size,
360  std::forward<ConstructorArgs>(args)...}};
361  }
362 
363  return LADataIntfPtr{
365  e, n_variables, local_matrix_size,
366  dofIndex_to_localIndex,
367  std::forward<ConstructorArgs>(args)...}};
368  }
370  e, n_variables, local_matrix_size, dofIndex_to_localIndex,
371  std::forward<ConstructorArgs>(args)...}};
372  };
373  }
374 
377  template <typename ShapeFunction>
378  static LADataBuilder makeLocalAssemblerBuilder(std::false_type* /*unused*/)
379  {
380  return nullptr;
381  }
382 };
383 
384 } // namespace SmallDeformation
385 } // namespace LIE
386 } // namespace ProcessLib
387 
388 #undef ENABLED_ELEMENT_TYPE_SIMPLEX
389 #undef ENABLED_ELEMENT_TYPE_CUBOID
390 #undef ENABLED_ELEMENT_TYPE_PYRAMID
391 #undef ENABLED_ELEMENT_TYPE_PRISM
392 #undef ENABLED_ELEMENT_TYPE_TRI
393 #undef ENABLED_ELEMENT_TYPE_QUAD
394 #undef OGS_ENABLED_ELEMENTS
#define OGS_FATAL(...)
Definition: Error.h:26
virtual unsigned getNumberOfNodes() const =0
virtual constexpr unsigned getDimension() const =0
Get dimension of the mesh element.
std::size_t getMeshID() const
return this mesh ID
Definition: MeshSubset.h:71
std::size_t getNumberOfElementDOF(std::size_t const mesh_item_id) const
GlobalIndexType getGlobalIndex(MeshLib::Location const &l, int const variable_id, int const component_id) const
int getNumberOfVariableComponents(int variable_id) const
MeshLib::MeshSubset const & getMeshSubset(int const variable_id, int const component_id) const
std::size_t getNumberOfElementComponents(std::size_t const mesh_item_id) const
std::vector< int > getElementVariableIDs(std::size_t const mesh_item_id) const
static NUMLIB_EXPORT GlobalIndexType const nop
std::function< LADataIntfPtr(MeshLib::Element const &e, std::size_t const n_variables, std::size_t const local_matrix_size, std::vector< unsigned > const &dofIndex_to_localIndex, ConstructorArgs &&...)> LADataBuilder
typename NumLib::GaussLegendreIntegrationPolicy< typename ShapeFunction::MeshElement >::IntegrationMethod IntegrationMethod
LocalAssemblerDataMatrix< ShapeFunction, IntegrationMethod< ShapeFunction >, GlobalDim > LADataMatrix
LocalAssemblerDataFracture< ShapeFunction, IntegrationMethod< ShapeFunction >, GlobalDim > LAFractureData
static LADataBuilder makeLocalAssemblerBuilder(std::true_type *)
LocalDataInitializer(NumLib::LocalToGlobalIndexMap const &dof_table)
LADataIntfPtr operator()(std::size_t const id, MeshLib::Element const &mesh_item, ConstructorArgs &&... args) const
std::unique_ptr< LocalAssemblerInterface > LADataIntfPtr
static LADataBuilder makeLocalAssemblerBuilder(std::false_type *)
LocalAssemblerDataMatrixNearFracture< ShapeFunction, IntegrationMethod< ShapeFunction >, GlobalDim > LADataMatrixNearFracture
std::unordered_map< std::type_index, LADataBuilder > _builder
Mapping of element types to local assembler constructors.
std::size_t getNodeIndex(Element const &element, unsigned const idx)
Definition: Element.cpp:225