LehrFEM++ 1.0.0
A simple Finite Element Library for teaching
Loading...
Searching...
No Matches
dofhandler.cc
1/***************************************************************************
2 * LehrFEM++ - A simple C++ finite element libray for teaching
3 * Developed from 2018 at the Seminar of Applied Mathematics of ETH Zurich,
4 * lead developers Dr. R. Casagrande and Prof. R. Hiptmair
5 ***************************************************************************/
6
15#include "dofhandler.h"
16
17#include "lf/mesh/entity.h"
18
19namespace lf::assemble {
20
21// Implementation of output operator for interface class
22std::ostream &operator<<(std::ostream &o, const DofHandler &dof_handler) {
24 return o;
25}
26
27// NOLINTNEXTLINE(readability-function-cognitive-complexity)
28void PrintInfo(std::ostream &stream, const DofHandler &dof_handler,
29 unsigned ctrl) {
30 // Obtain pointer to the underlying mesh
31 auto mesh = dof_handler.Mesh();
32 // Number of degrees of freedom managed by the DofHandler object
34
35 stream << "DofHandler(" << dof_handler.NumDofs() << " dofs)";
36 if (ctrl > 0) {
37 // More detailed output
38 stream << '\n';
39 if (ctrl % 2 == 0) {
40 for (lf::base::dim_t codim = 0; codim <= mesh->DimMesh(); codim++) {
41 // Visit all entities of a specific codimension
42 for (const lf::mesh::Entity *e : mesh->Entities(codim)) {
43 // Fetch unique index of current entity supplied by mesh object
44 const lf::base::glb_idx_t e_idx = mesh->Index(*e);
45 // Number of shape functions covering current entity
46 const lf::assemble::size_type no_dofs(dof_handler.NumLocalDofs(*e));
47 // Obtain global indices of those shape functions ...
48 const std::span<const gdof_idx_t> doflist(
49 dof_handler.GlobalDofIndices(*e));
50 // and print them
51 stream << *e << ' ' << e_idx << ": " << no_dofs << " dofs = [";
52 for (const lf::assemble::gdof_idx_t &dof : doflist) {
53 stream << dof << ' ';
54 }
55 stream << ']';
56 if (ctrl % 5 == 0) {
57 // Also output indices of interior shape functions
58 const std::span<const gdof_idx_t> intdoflist(
59 dof_handler.InteriorGlobalDofIndices(*e));
60 stream << " int = [";
62 stream << int_dof << ' ';
63 }
64 stream << ']';
65 }
66 stream << '\n';
67 }
68 }
69 }
70 if (ctrl % 3 == 0) {
71 // List entities associated wit the dofs managed by the current
72 // DofHandler object
74 const lf::mesh::Entity &e(dof_handler.Entity(dof_idx));
75 stream << "dof " << dof_idx << " -> " << e << " " << mesh->Index(e)
76 << '\n';
77 }
78 }
79 }
80}
81
82// ----------------------------------------------------------------------
83// Implementation UniformFEDofHandler
84// ----------------------------------------------------------------------
85
87 std::shared_ptr<const lf::mesh::Mesh> mesh, dof_map_t dofmap,
89 : mesh_(std::move(mesh)),
90 num_dofs_(),
91 check_edge_orientation_(check_edge_orientation) {
92 LF_ASSERT_MSG((mesh_->DimMesh() == 2), "Can handle 2D meshes only");
93
94 // For checking whether a key was found
95 auto map_end = dofmap.end();
96
97 // Get no of interior dof specified for nodes
99 if (map_el_pt != map_end) {
101 }
102
103 // Get no of interior dof specified for edges
105 if (map_el_ed != map_end) {
107 }
108
109 // Get no of interior dof specified for triangles
111 if (map_el_tr != map_end) {
113 }
114
115 // Get no of interior dof specified for quads
117 if (map_el_qd != map_end) {
119 }
120
121 // If an entity type is not represented in the map, we assume that
122 // no shape functions are attached to those entities
123
124 // Initialize total number of shape functions covering an entity.
126
127 // Initializatin of dof index arrays
129}
130
140
141// NOLINTNEXTLINE(readability-function-cognitive-complexity)
143 // This method assumes a proper initialization
144 // of the data in no_loc_dof_* and num_dofs_, num_dof_tria, num_dofs_quad_
146
147 // Step I: Set indices for shape functions on nodes
148 // Total number of degrees of freedom on nodes (entities of co-dim = 2)
149 const size_type no_nodes = mesh_->NumEntities(2);
152 // Run through nodes in the order given by their numbering
154 const mesh::Entity *node_p{mesh_->EntityByIndex(2, node_idx)};
155 LF_ASSERT_MSG(mesh_->Index(*node_p) == node_idx, "Node index mismatch");
156 // Beginning of section for concrete node in the dof index vector
157 // for entities of co-dimension 2
159 for (unsigned j = 0; j < num_loc_dof_point_; j++) {
161 dof_entities_.push_back(node_p); // Store entity for current dof
162 dof_idx++; // Move on to next index
163 }
164 }
165
166 // Step II: Set indices for shape functions on edges
167 // Total number of degrees of freedom belonging to edges (entities of co-dim =
168 // 1)
169 const size_type no_edges = mesh_->NumEntities(1);
172 // Visit all edges
173 // Old implementation, see remarks above
174 // for (const lf::mesh::Entity &edge : mesh_->Entities(1)) {
176 // Obtain pointer to edge entity
177 const mesh::Entity *edge_p{mesh_->EntityByIndex(1, edge_idx)};
178 LF_ASSERT_MSG(mesh_->Index(*edge_p) == edge_idx, "Edge index mismatch");
179 // Beginning of section for concrete edge in the dof index vector
180 // for entities of co-dimension 1
182
183 // Obtain indices for basis functions sitting at endpoints
184 for (const lf::mesh::Entity *endpoint : edge_p->SubEntities(1)) {
185 const glb_idx_t ep_idx(mesh_->Index(*endpoint));
187 // Copy indices of shape functions from nodes to edge
188 for (unsigned j = 0; j < num_dofs_[kNodeOrd]; j++) {
190 }
191 }
192 // Set indices for interior edge degrees of freedom
193 for (unsigned j = 0; j < num_loc_dof_segment_; j++) {
195 dof_entities_.push_back(edge_p);
196 dof_idx++;
197 }
198 }
199
200 // Step III: Set indices for shape functions on cells
201 const size_type no_cells = mesh_->NumEntities(0);
204
205 // Number of (non-)interior shape functins for edges
208
209 // Visit all cells
210 // Old implementation without strong link between cell
211 // indices and ordering of global shape functions
212 // for (const lf::mesh::Entity &cell : mesh_->Entities(0)) {
214 // Obtain pointer to current ell
215 const mesh::Entity *cell_p{mesh_->EntityByIndex(0, cell_idx)};
216 LF_ASSERT_MSG(cell_idx == mesh_->Index(*cell_p), "cell index mismatch");
217 // Offset for cell dof indices in large dof index vector
219
220 // Obtain indices for basis functions in vertices
221 for (const lf::mesh::Entity *vertex : cell_p->SubEntities(2)) {
222 const glb_idx_t vt_idx(mesh_->Index(*vertex));
224 // Copy indices of shape functions from nodes to cell
225 for (unsigned j = 0; j < num_dofs_[kNodeOrd]; j++) {
227 }
228 }
229
230 // Collect indices of interior shape functions of edges
231 // Internal ordering may depend on the orientation of the edge, if
232 // the check_edge_orientation_ flag is set
233 const std::span<const lf::mesh::Orientation> edge_orientations =
234 cell_p->RelativeOrientations();
235 auto edges = cell_p->SubEntities(1);
236 // Loop over edges
237 const size_type no_edges_cell = cell_p->RefEl().NumSubEntities(1);
238 for (int ed_sub_idx = 0; ed_sub_idx < no_edges_cell; ed_sub_idx++) {
239 const glb_idx_t edge_idx = mesh_->Index(*edges[ed_sub_idx]);
242 // Copy indices of shape functions from edges to cell
243 // The order, in which they are copied depends on the relative orientation
244 // of the edge w.r.t. the cell, if the edge_orientation_flag is set
247 // Cell-internal and intrinsic orientation match, do not tinker with
248 // the numbering of local shape functions
249 for (int j = 0; j < no_int_dof_edge; j++) {
252 }
253 } else {
254 // lf::mesh::Orientation::negative: Mismatch of orientations
255 // reverse numbering of cell-internal d.o.f.s
256 for (int j = static_cast<int>(no_int_dof_edge - 1); j >= 0; j--) {
259 }
260 }
261 }
262
263 // Set indices for interior cell degrees of freedom depending on the type of
264 // cell. Here we add new degrees of freedom
266 if (cell_p->RefEl() == lf::base::RefEl::kTria()) {
268 } else if (cell_p->RefEl() == lf::base::RefEl::kQuad()) {
270 } else {
271 LF_ASSERT_MSG(
272 false, "Illegal cell type; only triangles and quads are supported");
273 }
274
275 // enlist new interior cell-associated dofs
276 for (unsigned j = 0; j < num_int_dofs_cell; j++) {
278 dof_entities_.push_back(cell_p);
279 dof_idx++;
280 }
281 }
282 // Finally store total number of shape functions on the mesh.
284} // end constructor
285
286std::span<const gdof_idx_t> UniformFEDofHandler::GlobalDofIndices(
288 // Co-dimension of entity in a 2D mesh
289 const dim_t codim = 2 - ref_el_type.Dimension();
291
292 LF_ASSERT_MSG((mesh_->NumEntities(codim) > entity_index),
293 "Index " << entity_index << " out of range");
294 // Pointers to range of dof indices
295 const gdof_idx_t *begin =
296 dofs_[codim].data() +
297 (static_cast<std::size_t>(num_dofs_[codim]) * entity_index);
299 return {begin, end};
300}
301
302std::span<const gdof_idx_t> UniformFEDofHandler::GlobalDofIndices(
303 const lf::mesh::Entity &entity) const {
304 return GlobalDofIndices(entity.RefEl(), mesh_->Index(entity));
305}
306
309 // Co-dimension of entity in a 2D mesh
310 const dim_t codim = 2 - ref_el_type.Dimension();
313
314 LF_ASSERT_MSG((mesh_->NumEntities(codim) > entity_index),
315 "Index " << entity_index << " out of range");
316 // Pointers to range of dof indices
317 const gdof_idx_t *begin =
318 dofs_[codim].data() +
319 (static_cast<std::size_t>(num_dofs_[codim]) * entity_index);
322 return {begin, end};
323}
324
326 const lf::mesh::Entity &entity) const {
327 return InteriorGlobalDofIndices(entity.RefEl(), mesh_->Index(entity));
328}
329
334
339
340// ----------------------------------------------------------------------
341// Implementation DynamicFEDofHandler
342// ----------------------------------------------------------------------
343
344std::span<const gdof_idx_t> DynamicFEDofHandler::GlobalDofIndices(
345 const lf::mesh::Entity &entity) const {
346 // Topological type
348 // Co-dimension of entity in a 2D mesh
349 const dim_t codim = 2 - ref_el_type.Dimension();
350 // Index of current mesh entity
351 const glb_idx_t entity_index = mesh_p_->Index(entity);
352 // Offset of dof indices for current entity
354 // Number of shape functions covering current entity
357 // Pointers to range of dof indices
358 const gdof_idx_t *begin = dofs_[codim].data() + idx_offset;
360 return {begin, end};
361}
362
364 const lf::mesh::Entity &entity) const {
365 // Topological type
367 // Co-dimension of entity in a 2D mesh
368 const dim_t codim = 2 - ref_el_type.Dimension();
369 // Index of current mesh entity
370 const glb_idx_t entity_index = mesh_p_->Index(entity);
371 // Offset of indices for current entity
373 // Number of shape functions covering current entity
376 // Number of shape functions associated with the current entity
378 // Pointers to range of dof indices
379 const gdof_idx_t *begin = dofs_[codim].data() + idx_offset;
381 // Move pointer to location of indices for interior dofs
382 // This is the only difference to GlobalDofIndices()
384 return {begin, end};
385}
386
394
403
404} // namespace lf::assemble
A general (interface) class for DOF handling, see Lecture Document Paragraph 2.7.4....
Definition dofhandler.h:112
size_type NumInteriorDofs(const lf::mesh::Entity &entity) const override
provides number of shape functions associated with an entity
std::shared_ptr< const lf::mesh::Mesh > mesh_p_
Definition dofhandler.h:765
std::span< const gdof_idx_t > InteriorGlobalDofIndices(const lf::mesh::Entity &entity) const override
global indices of shape functions associated with an entity_
std::span< const gdof_idx_t > GlobalDofIndices(const lf::mesh::Entity &entity) const override
access to indices of global dof's belonging to an entity
std::array< std::vector< size_type >, 3 > offsets_
Definition dofhandler.h:784
size_type NumLocalDofs(const lf::mesh::Entity &entity) const override
tells the number of degrees of freedom subordinate/_belonging_ to to an entity
std::array< std::vector< gdof_idx_t >, 3 > dofs_
Definition dofhandler.h:787
std::array< std::vector< size_type >, 3 > num_int_dofs_
Definition dofhandler.h:782
void initIndexArrays()
initialization of internal index arrays
size_type GetNumLocalDofs(lf::base::RefEl ref_el_type, glb_idx_t) const
Definition dofhandler.h:411
std::array< size_type, 3 > num_dofs_
Definition dofhandler.h:489
std::span< const gdof_idx_t > GlobalDofIndices(const lf::mesh::Entity &entity) const override
access to indices of global dof's belonging to an entity
std::array< std::vector< gdof_idx_t >, 3 > dofs_
Definition dofhandler.h:487
std::span< const gdof_idx_t > InteriorGlobalDofIndices(const lf::mesh::Entity &entity) const override
global indices of shape functions associated with an entity_
UniformFEDofHandler(std::shared_ptr< const lf::mesh::Mesh > mesh, dof_map_t dofmap, bool check_edge_orientation=true)
Construction from a map object.
Definition dofhandler.cc:86
size_type NumInteriorDofs(const lf::mesh::Entity &entity) const override
provides number of shape functions associated with an entity
size_type NumLocalDofs(const lf::mesh::Entity &entity) const override
tells the number of degrees of freedom subordinate/_belonging_ to to an entity
std::shared_ptr< const lf::mesh::Mesh > mesh_
Definition dofhandler.h:480
std::map< lf::base::RefEl, base::size_type > dof_map_t
Map data type for telling number of global shape functions associated with every topological kind of ...
Definition dofhandler.h:269
std::vector< const lf::mesh::Entity * > dof_entities_
Definition dofhandler.h:484
void InitTotalNumDofs()
compute number of shape functions covering an entity type
size_type NumCoveredDofs(lf::base::RefEl ref_el_type) const
Definition dofhandler.h:424
Represents a reference element with all its properties.
Definition ref_el.h:109
static constexpr RefEl kSegment()
Returns the (1-dimensional) reference segment.
Definition ref_el.h:153
constexpr RefEl(RefElType type) noexcept
Create a RefEl from a lf::base::RefElType enum.
Definition ref_el.h:175
static constexpr RefEl kPoint()
Returns the (0-dimensional) reference point.
Definition ref_el.h:144
static constexpr RefEl kTria()
Returns the reference triangle.
Definition ref_el.h:161
static constexpr RefEl kQuad()
Returns the reference quadrilateral.
Definition ref_el.h:169
Interface class representing a topological entity in a cellular complex
Definition entity.h:42
void AssembleMatrixLocally(dim_t codim, const DofHandler &dof_handler_trial, const DofHandler &dof_handler_test, ENTITY_MATRIX_PROVIDER &entity_matrix_provider, TMPMATRIX &matrix)
Assembly function for standard assembly of finite element matrices.
Definition assembler.h:115
unsigned int dim_t
type for dimensions and co-dimensions and numbers derived from them
Definition types.h:32
unsigned int glb_idx_t
type for global index of mesh entities (nodes, edges, cells)
Definition types.h:24
D.o.f. index mapping and assembly facilities.
Definition assemble.h:31
lf::base::glb_idx_t glb_idx_t
lf::base::size_type size_type
void PrintInfo(std::ostream &stream, const DofHandler &dof_handler, unsigned ctrl)
Definition dofhandler.cc:28
std::ostream & operator<<(std::ostream &o, const COOMatrix< SCALARTYPE > &mat)
Definition coomatrix.h:229
lf::base::dim_t dim_t
Eigen::Index gdof_idx_t