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 
24 
25 #ifndef OGS_MAX_ELEMENT_DIM
26 static_assert(false, "The macro OGS_MAX_ELEMENT_DIM is undefined.");
27 #endif
28 
29 #ifndef OGS_MAX_ELEMENT_ORDER
30 static_assert(false, "The macro OGS_MAX_ELEMENT_ORDER is undefined.");
31 #endif
32 
33 // The following macros decide which element types will be compiled, i.e.
34 // which element types will be available for use in simulations.
35 
36 #ifdef OGS_ENABLE_ELEMENT_SIMPLEX
37 #define ENABLED_ELEMENT_TYPE_SIMPLEX 1u
38 #else
39 #define ENABLED_ELEMENT_TYPE_SIMPLEX 0u
40 #endif
41 
42 #ifdef OGS_ENABLE_ELEMENT_CUBOID
43 #define ENABLED_ELEMENT_TYPE_CUBOID 1u << 1
44 #else
45 #define ENABLED_ELEMENT_TYPE_CUBOID 0u
46 #endif
47 
48 #ifdef OGS_ENABLE_ELEMENT_PRISM
49 #define ENABLED_ELEMENT_TYPE_PRISM 1u << 2
50 #else
51 #define ENABLED_ELEMENT_TYPE_PRISM 0u
52 #endif
53 
54 #ifdef OGS_ENABLE_ELEMENT_PYRAMID
55 #define ENABLED_ELEMENT_TYPE_PYRAMID 1u << 3
56 #else
57 #define ENABLED_ELEMENT_TYPE_PYRAMID 0u
58 #endif
59 
60 // Dependent element types.
61 // Faces of tets, pyramids and prisms are triangles
62 #define ENABLED_ELEMENT_TYPE_TRI \
63  ((ENABLED_ELEMENT_TYPE_SIMPLEX) | (ENABLED_ELEMENT_TYPE_PYRAMID) | \
64  (ENABLED_ELEMENT_TYPE_PRISM))
65 // Faces of hexes, pyramids and prisms are quads
66 #define ENABLED_ELEMENT_TYPE_QUAD \
67  ((ENABLED_ELEMENT_TYPE_CUBOID) | (ENABLED_ELEMENT_TYPE_PYRAMID) | \
68  (ENABLED_ELEMENT_TYPE_PRISM))
69 
70 // All enabled element types
71 #define OGS_ENABLED_ELEMENTS \
72  ((ENABLED_ELEMENT_TYPE_SIMPLEX) | (ENABLED_ELEMENT_TYPE_CUBOID) | \
73  (ENABLED_ELEMENT_TYPE_PYRAMID) | (ENABLED_ELEMENT_TYPE_PRISM))
74 
75 // Include only what is needed (Well, the conditions are not sharp).
76 #if OGS_ENABLED_ELEMENTS != 0
79 #endif
80 
81 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_SIMPLEX) != 0
84 #endif
85 
86 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_TRI) != 0
89 #endif
90 
91 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_CUBOID) != 0
94 #endif
95 
96 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_QUAD) != 0
100 #endif
101 
102 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PRISM) != 0
105 #endif
106 
107 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PYRAMID) != 0
110 #endif
111 
112 namespace ProcessLib
113 {
114 namespace LIE
115 {
116 namespace HydroMechanics
117 {
127 template <typename LocalAssemblerInterface,
128  template <typename, typename, typename, int>
129  class LocalAssemblerDataMatrix,
130  template <typename, typename, typename, int>
131  class LocalAssemblerDataMatrixNearFracture,
132  template <typename, typename, typename, int>
133  class LocalAssemblerDataFracture,
134  int GlobalDim, typename... ConstructorArgs>
136 {
137 public:
138  using LADataIntfPtr = std::unique_ptr<LocalAssemblerInterface>;
139 
141  const unsigned shapefunction_order)
142  : _dof_table(dof_table)
143  {
144  if (shapefunction_order != 2)
145  {
146  OGS_FATAL(
147  "The given shape function order {:d} is not supported.\nOnly "
148  "shape functions of order 2 are supported.",
149  shapefunction_order);
150  }
151  // /// Quads and Hexahedra ///////////////////////////////////
152 
153 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_QUAD) != 0 && \
154  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
155  _builder[std::type_index(typeid(MeshLib::Quad8))] =
156  makeLocalAssemblerBuilder<NumLib::ShapeQuad8>();
157  _builder[std::type_index(typeid(MeshLib::Quad9))] =
158  makeLocalAssemblerBuilder<NumLib::ShapeQuad9>();
159 #endif
160 
161 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_CUBOID) != 0 && \
162  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
163  _builder[std::type_index(typeid(MeshLib::Hex20))] =
164  makeLocalAssemblerBuilder<NumLib::ShapeHex20>();
165 #endif
166 
167  // /// Simplices ////////////////////////////////////////////////
168 
169 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_TRI) != 0 && \
170  OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
171  _builder[std::type_index(typeid(MeshLib::Tri6))] =
172  makeLocalAssemblerBuilder<NumLib::ShapeTri6>();
173 #endif
174 
175 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_SIMPLEX) != 0 && \
176  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
177  _builder[std::type_index(typeid(MeshLib::Tet10))] =
178  makeLocalAssemblerBuilder<NumLib::ShapeTet10>();
179 #endif
180 
181  // /// Prisms ////////////////////////////////////////////////////
182 
183 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PRISM) != 0 && \
184  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
185  _builder[std::type_index(typeid(MeshLib::Prism15))] =
186  makeLocalAssemblerBuilder<NumLib::ShapePrism15>();
187 #endif
188 
189  // /// Pyramids //////////////////////////////////////////////////
190 
191 #if (OGS_ENABLED_ELEMENTS & ENABLED_ELEMENT_TYPE_PYRAMID) != 0 && \
192  OGS_MAX_ELEMENT_DIM >= 3 && OGS_MAX_ELEMENT_ORDER >= 2
193  _builder[std::type_index(typeid(MeshLib::Pyramid13))] =
194  makeLocalAssemblerBuilder<NumLib::ShapePyra13>();
195 #endif
196  // /// Lines ///////////////////////////////////
197 
198 // /// Lines ///////////////////////////////////
199 #if OGS_MAX_ELEMENT_DIM >= 2 && OGS_MAX_ELEMENT_ORDER >= 2
200  _builder[std::type_index(typeid(MeshLib::Line3))] =
201  makeLocalAssemblerBuilder<NumLib::ShapeLine3>();
202 #endif
203  }
204 
210  LADataIntfPtr operator()(std::size_t const id,
211  MeshLib::Element const& mesh_item,
212  ConstructorArgs&&... args) const
213  {
214  auto const type_idx = std::type_index(typeid(mesh_item));
215  auto const it = _builder.find(type_idx);
216 
217  if (it == _builder.end())
218  {
219  OGS_FATAL(
220  "You are trying to build a local assembler for an unknown mesh "
221  "element type ({:s})."
222  " Maybe you have disabled this mesh element type in your build "
223  "configuration, or a mesh element order does not match shape "
224  "function order given in the project file.",
225  type_idx.name());
226  }
227 
228  auto const n_local_dof = _dof_table.getNumberOfElementDOF(id);
229  auto const varIDs = _dof_table.getElementVariableIDs(id);
230  bool const isPressureDeactivated = (varIDs.front() != 0);
231  std::vector<int> involved_varIDs; // including deactivated elements
232  involved_varIDs.reserve(varIDs.size() + 1);
233  if (isPressureDeactivated)
234  {
235  involved_varIDs.push_back(0); // always pressure come in
236  }
237  involved_varIDs.insert(involved_varIDs.end(), varIDs.begin(),
238  varIDs.end());
239 
240  std::vector<unsigned> dofIndex_to_localIndex;
241 
242  // matrix and fracture assemblers with enrichments
243  dofIndex_to_localIndex.resize(n_local_dof);
244  std::vector<unsigned> vec_n_element_nodes;
245  // TODO how to get the shape function order for each variable?
246  vec_n_element_nodes.push_back(
247  mesh_item.getNumberOfBaseNodes()); // pressure
248  auto const max_varID = *std::max_element(varIDs.begin(), varIDs.end());
249  for (int i = 1; i < max_varID + 1; i++)
250  {
251  vec_n_element_nodes.push_back(
252  mesh_item.getNumberOfNodes()); // displacements
253  }
254 
255  unsigned local_id = 0;
256  unsigned dof_id = 0;
257  for (unsigned i = 0; i < involved_varIDs.size(); i++)
258  {
259  auto const var_id = involved_varIDs[i];
260  auto const n_var_comp =
262  auto const n_var_element_nodes = vec_n_element_nodes[i];
263  for (int var_comp_id = 0; var_comp_id < n_var_comp; var_comp_id++)
264  {
265  auto const& ms = _dof_table.getMeshSubset(var_id, var_comp_id);
266  auto const mesh_id = ms.getMeshID();
267  for (unsigned k = 0; k < n_var_element_nodes; k++)
268  {
269  MeshLib::Location l(mesh_id,
271  getNodeIndex(mesh_item, k));
272  auto global_index =
273  _dof_table.getGlobalIndex(l, var_id, var_comp_id);
274  if (global_index != NumLib::MeshComponentMap::nop)
275  {
276  dofIndex_to_localIndex[dof_id++] = local_id;
277  }
278  local_id++;
279  }
280  }
281  }
282 
283  return it->second(mesh_item, involved_varIDs.size(), n_local_dof,
284  dofIndex_to_localIndex,
285  std::forward<ConstructorArgs>(args)...);
286  }
287 
288 private:
289  using LADataBuilder = std::function<LADataIntfPtr(
290  MeshLib::Element const& e,
291  std::size_t const n_variables,
292  std::size_t const local_matrix_size,
293  std::vector<unsigned> const& dofIndex_to_localIndex,
294  ConstructorArgs&&...)>;
295 
296  template <typename ShapeFunctionDisplacement>
298  typename ShapeFunctionDisplacement::MeshElement>::IntegrationMethod;
299 
300  template <typename ShapeFunctionDisplacement,
301  typename ShapeFunctionPressure>
302  using LADataMatrix = LocalAssemblerDataMatrix<
303  ShapeFunctionDisplacement, ShapeFunctionPressure,
305 
306  template <typename ShapeFunctionDisplacement,
307  typename ShapeFunctionPressure>
308  using LADataMatrixNearFracture = LocalAssemblerDataMatrixNearFracture<
309  ShapeFunctionDisplacement, ShapeFunctionPressure,
311 
312  template <typename ShapeFunctionDisplacement,
313  typename ShapeFunctionPressure>
314  using LAFractureData = LocalAssemblerDataFracture<
315  ShapeFunctionDisplacement, ShapeFunctionPressure,
317 
321  template <typename ShapeFunctionDisplacement>
323  {
324  return makeLocalAssemblerBuilder<ShapeFunctionDisplacement>(
325  static_cast<std::integral_constant<
326  bool, (GlobalDim >= ShapeFunctionDisplacement::DIM)>*>(
327  nullptr));
328  }
329 
331  std::unordered_map<std::type_index, LADataBuilder> _builder;
332 
334 
335 private:
342  template <typename ShapeFunctionDisplacement>
343  static LADataBuilder makeLocalAssemblerBuilder(std::true_type* /*unused*/)
344  {
345  // (Lower order elements = Order(ShapeFunctionDisplacement) - 1).
346  using ShapeFunctionPressure =
348  return [](MeshLib::Element const& e,
349  std::size_t const n_variables,
350  std::size_t const local_matrix_size,
351  std::vector<unsigned> const& dofIndex_to_localIndex,
352  ConstructorArgs&&... args) {
353  if (e.getDimension() == GlobalDim)
354  {
355  if (n_variables == 2)
356  {
357  return LADataIntfPtr{
358  new LADataMatrix<ShapeFunctionDisplacement,
359  ShapeFunctionPressure>{
360  e, n_variables, local_matrix_size,
361  dofIndex_to_localIndex,
362  std::forward<ConstructorArgs>(args)...}};
363  }
365  ShapeFunctionDisplacement, ShapeFunctionPressure>{
366  e, n_variables, local_matrix_size, dofIndex_to_localIndex,
367  std::forward<ConstructorArgs>(args)...}};
368  }
369  return LADataIntfPtr{new LAFractureData<ShapeFunctionDisplacement,
370  ShapeFunctionPressure>{
371  e, local_matrix_size, dofIndex_to_localIndex,
372  std::forward<ConstructorArgs>(args)...}};
373  };
374  }
375 
378  template <typename ShapeFunctionDisplacement>
379  static LADataBuilder makeLocalAssemblerBuilder(std::false_type* /*unused*/)
380  {
381  return nullptr;
382  }
383 };
384 
385 } // namespace HydroMechanics
386 } // namespace LIE
387 } // namespace ProcessLib
388 
389 #undef ENABLED_ELEMENT_TYPE_SIMPLEX
390 #undef ENABLED_ELEMENT_TYPE_CUBOID
391 #undef ENABLED_ELEMENT_TYPE_PYRAMID
392 #undef ENABLED_ELEMENT_TYPE_PRISM
393 #undef ENABLED_ELEMENT_TYPE_TRI
394 #undef ENABLED_ELEMENT_TYPE_QUAD
395 #undef OGS_ENABLED_ELEMENTS
#define OGS_FATAL(...)
Definition: Error.h:26
virtual unsigned getNumberOfNodes() const =0
virtual unsigned getNumberOfBaseNodes() 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::vector< int > getElementVariableIDs(std::size_t const mesh_item_id) const
static NUMLIB_EXPORT GlobalIndexType const nop
typename NumLib::GaussLegendreIntegrationPolicy< typename ShapeFunctionDisplacement::MeshElement >::IntegrationMethod IntegrationMethod
LocalAssemblerDataFracture< ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod< ShapeFunctionDisplacement >, GlobalDim > LAFractureData
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
LADataIntfPtr operator()(std::size_t const id, MeshLib::Element const &mesh_item, ConstructorArgs &&... args) const
LocalDataInitializer(NumLib::LocalToGlobalIndexMap const &dof_table, const unsigned shapefunction_order)
static LADataBuilder makeLocalAssemblerBuilder(std::false_type *)
static LADataBuilder makeLocalAssemblerBuilder(std::true_type *)
LocalAssemblerDataMatrixNearFracture< ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod< ShapeFunctionDisplacement >, GlobalDim > LADataMatrixNearFracture
LocalAssemblerDataMatrix< ShapeFunctionDisplacement, ShapeFunctionPressure, IntegrationMethod< ShapeFunctionDisplacement >, GlobalDim > LADataMatrix
std::unique_ptr< LocalAssemblerInterface > LADataIntfPtr
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