Flow123d  DF_patch_fe_data_tables-da7858b
duplicate_nodes.cc
Go to the documentation of this file.
1 /*!
2  *
3  * Copyright (C) 2015 Technical University of Liberec. All rights reserved.
4  *
5  * This program is free software; you can redistribute it and/or modify it under
6  * the terms of the GNU General Public License version 3 as published by the
7  * Free Software Foundation. (http://www.gnu.org/licenses/gpl-3.0.en.html)
8  *
9  * This program is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11  * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
12  *
13  *
14  * @file duplicate_nodes.cc
15  * @ingroup mesh
16  * @brief Construction of mesh structure with nodes duplicated at fractures.
17  */
18 
19 #include <set>
20 #include <queue>
21 
22 #include "system/sys_profiler.hh"
23 #include "mesh/duplicate_nodes.h"
24 #include "mesh/mesh.h"
25 #include "mesh/node_accessor.hh"
26 #include "mesh/accessors.hh"
27 
28 
29 
30 
31 MeshObject::MeshObject(unsigned int dim)
32  : dim_(dim)
33 {}
34 
35 
37 : mesh_(mesh),
38  n_duplicated_nodes_(0)
39 {
40  init_nodes();
44 }
45 
46 
47 
49 {
50  // initialize the nodes
53 }
54 
55 
56 
58 {
59  // initialize the objects from edges
60  for (auto edge : mesh_->edge_range()) {
61  MeshObject obj(edge.side(0)->dim());
62  for (unsigned int i=0; i<edge.side(0)->dim()+1; ++i)
63  obj.nodes[i] = edge.side(0)->node(i).idx();
64  obj_4_edg_.push_back(objects_[edge.side(0)->dim()].size());
65  objects_[edge.side(0)->dim()].push_back(obj);
66  }
67 }
68 
69 
70 
72 {
73  // initialize the objects from elements
74  for ( auto ele : mesh_->elements_range() ) {
75  MeshObject l(ele->dim());
76  for (unsigned int i=0; i<ele->dim()+1; i++)
77  l.nodes[i] = ele->node_idx(i);
78  if (ele->dim() > 0)
79  for (unsigned int i=0; i<ele->dim()+1; i++)
80  l.faces[i] = obj_4_edg_[ele->edge_idx(i)];
81  obj_4_el_.push_back(objects_[ele->dim()].size());
82  objects_[ele->dim()].push_back(l);
83  }
84 }
85 
86 
87 /**
88  * The main functionality of the class creates duplicate nodes
89  * at interfaces with fractures.
90  *
91  * For each node:
92  * 1) Create the lists of elements (node_elements) sharing the node.
93  * 2) Divide node_elements into groups (components) connected by edges.
94  * 3) If more than one component was created, create for each extra component a new node
95  * and update its index in the elements from this component.
96  * Also set node_dim_ (dimension of elements using the node).
97  */
99 {
100  START_TIMER("duplicate_nodes");
101  for ( auto n : mesh_->node_range() ){
102  // create list of adjacent elements from mesh_->node_elements[n.idx()]
103  std::list<unsigned int> node_elements;
104  std::copy( mesh_->node_elements()[n.idx()].begin(), mesh_->node_elements()[n.idx()].end(), std::back_inserter( node_elements ) );
105 
106  // divide node_elements into components connected by node_edges
108  while (node_elements.size() > 0)
109  {
110  // create component containing the first element in node_elements
111  std::queue<unsigned int> q;
112  q.push(*node_elements.begin());
113  node_elements.erase(node_elements.begin());
114  std::set<unsigned int> component;
115  while (q.size() > 0) {
116  auto elem = mesh_->element_accessor(q.front());
117  component.insert(elem.idx());
118  // add to queue adjacent elements sharing one of node_edges
119  for (unsigned int sid=0; sid<elem->n_sides(); ++sid) {
120  auto side = elem.side(sid);
121  for (unsigned int esid=0; esid < side->edge().n_sides(); ++esid) {
122  auto adj_el_idx = side->edge().side(esid)->elem_idx();
123  if (adj_el_idx != elem.idx())
124  {
125  auto it = std::find(node_elements.begin(), node_elements.end(), adj_el_idx);
126  if (it != node_elements.end()) {
127  node_elements.erase(it);
128  q.push(adj_el_idx);
129  }
130  }
131  }
132  }
133  q.pop();
134  }
135  components.push_back(component);
136  }
137 
138  // For the first component leave the current node and set its node_dim_.
139  // If there are more components, then for each additional component
140  // create a duplicate of the node and update the affected mesh objects.
141  if (components.size() > 0) {
142  node_dim_[n.idx()] = mesh_->element_accessor(*(components.begin()->begin())).dim();
143  components.erase(components.begin());
144  }
145  for (auto component : components) {
146  unsigned int new_nid = n_duplicated_nodes_++;
147  node_dim_.push_back(mesh_->element_accessor(*component.begin()).dim());
148  for (auto el_idx : component) {
149  // After we have complete graph tetrahedron-triangles-lines-points,
150  // the updating of duplicated nodes will have to change.
151  const unsigned int el_dim = mesh_->element_accessor(el_idx).dim();
152  MeshObject *elem = &objects_[el_dim][obj_4_el_[el_idx]];
153  for (unsigned int i=0; i<el_dim+1; i++)
154  if (elem->nodes[i] == n.idx())
155  elem->nodes[i] = new_nid;
156  for (unsigned int fi=0; fi<el_dim+1; fi++)
157  for (unsigned int ni=0; ni<el_dim; ni++)
158  if (objects_[el_dim-1][elem->faces[fi]].nodes[ni] == n.idx())
159  objects_[el_dim-1][elem->faces[fi]].nodes[ni] = new_nid;
160  }
161  }
162  }
163  END_TIMER("duplicate_nodes");
164 }
165 
166 
167 
168 
std::vector< unsigned int > obj_4_el_
unsigned int n_duplicated_nodes_
Number of nodes (including duplicated ones).
void duplicate_nodes()
Duplicate nodes that are lying on interfaces with fractures.
void init_nodes()
Initialize the vector of nodes from mesh.
std::vector< unsigned int > node_dim_
Vector of space dimensions of elements using the particular duplicated node.
MeshBase * mesh_
The mesh object.
std::vector< unsigned int > obj_4_edg_
Vector of object indices for each mesh edge.
void init_from_elements()
Initialize objects from mesh elements.
void init_from_edges()
Initialize objects from mesh edges.
DuplicateNodes(MeshBase *mesh)
std::vector< MeshObject > objects_[4]
Array of n-faces by their dimension.
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
SideIter side(const unsigned int loc_index)
unsigned int dim() const
Definition: accessors.hh:188
Base class for Mesh and BCMesh.
Definition: mesh.h:96
Range< Edge > edge_range() const
Return range of edges.
Definition: mesh.cc:125
unsigned int n_nodes() const
Definition: mesh.h:171
vector< vector< unsigned int > > const & node_elements()
Definition: mesh.cc:1134
Range< ElementAccessor< 3 > > elements_range() const
Returns range of mesh elements.
Definition: mesh.cc:1174
Range< NodeAccessor< 3 > > node_range() const
Returns range of nodes.
Definition: mesh.cc:1180
ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:866
MeshObject(unsigned int dim)
unsigned int faces[4]
Indices of (dim-1)-dimensional faces within the global vector of objects with given dimension.
unsigned int nodes[4]
Indices of nodes.
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:448
Edge edge() const
Returns pointer to the edge connected to the side.
@ edge
#define END_TIMER(tag)
Ends a timer with specified tag.
#define START_TIMER(tag)
Starts a timer with specified tag.