Flow123d  release_3.0.0-960-g55da6da
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 #include "mesh/side_impl.hh"
28 
29 
30 
31 
32 MeshObject::MeshObject(unsigned int dim)
33  : dim_(dim)
34 {
35  for (unsigned int i=0; i<4; i++)
36  faces[i] = nullptr;
37 }
38 
39 
41 : mesh_(mesh),
42  n_duplicated_nodes_(0)
43 {
44  init_nodes();
48 }
49 
50 
51 
53 {
54  // initialize the nodes
57 }
58 
59 
60 
62 {
63  // initialize the objects from edges
64  for (auto edge : mesh_->edges) {
65  MeshObject obj(edge.side(0)->dim());
66  for (unsigned int i=0; i<edge.side(0)->dim()+1; ++i)
67  obj.nodes[i] = edge.side(0)->node(i).idx();
68  obj_4_edg_.push_back(objects_[edge.side(0)->dim()].size());
69  objects_[edge.side(0)->dim()].push_back(obj);
70  }
71 }
72 
73 
74 
76 {
77  // initialize the objects from elements
78  for ( auto ele : mesh_->elements_range() ) {
79  MeshObject l(ele->dim());
80  for (unsigned int i=0; i<ele->dim()+1; i++)
81  l.nodes[i] = ele->node_idx(i);
82  for (unsigned int i=0; i<ele->dim()+1; i++)
83  l.faces[i] = &objects_[ele->dim()-1][obj_4_edg_[ele->edge_idx(i)]];
84  obj_4_el_.push_back(objects_[ele->dim()].size());
85  objects_[ele->dim()].push_back(l);
86  }
87 }
88 
89 
90 /**
91  * The main functionality of the class creates duplicate nodes
92  * at interfaces with fractures.
93  *
94  * For each node:
95  * 1) Create the lists of elements (node_elements) sharing the node.
96  * 2) Divide node_elements into groups (components) connected by edges.
97  * 3) If more than one component was created, create for each extra component a new node
98  * and update its index in the elements from this component.
99  * Also set node_dim_ (dimension of elements using the node).
100  */
102 {
103  START_TIMER("duplicate_nodes");
104  for ( auto n : mesh_->node_range() ){
105  // create list of adjacent elements from mesh_->node_elements[n.idx()]
106  std::list<unsigned int> node_elements;
107  std::copy( mesh_->node_elements()[n.idx()].begin(), mesh_->node_elements()[n.idx()].end(), std::back_inserter( node_elements ) );
108 
109  // divide node_elements into components connected by node_edges
111  while (node_elements.size() > 0)
112  {
113  // create component containing the first element in node_elements
114  std::queue<unsigned int> q;
115  q.push(*node_elements.begin());
116  node_elements.erase(node_elements.begin());
117  std::set<unsigned int> component;
118  while (q.size() > 0) {
119  auto elem = mesh_->element_accessor(q.front());
120  component.insert(elem.idx());
121  // add to queue adjacent elements sharing one of node_edges
122  for (unsigned int sid=0; sid<elem->n_sides(); ++sid) {
123  auto side = elem.side(sid);
124  for (unsigned int esid=0; esid < side->edge()->n_sides; ++esid) {
125  auto adj_el_idx = side->edge()->side(esid)->elem_idx();
126  if (adj_el_idx != elem.idx())
127  {
128  auto it = std::find(node_elements.begin(), node_elements.end(), adj_el_idx);
129  if (it != node_elements.end()) {
130  node_elements.erase(it);
131  q.push(adj_el_idx);
132  }
133  }
134  }
135  }
136  q.pop();
137  }
138  components.push_back(component);
139  }
140 
141  // For the first component leave the current node and set its node_dim_.
142  // If there are more components, then for each additional component
143  // create a duplicate of the node and update the affected mesh objects.
144  if (components.size() > 0) {
145  node_dim_[n.idx()] = mesh_->element_accessor(*(components.begin()->begin())).dim();
146  components.erase(components.begin());
147  }
148  for (auto component : components) {
149  unsigned int new_nid = n_duplicated_nodes_++;
150  node_dim_.push_back(mesh_->element_accessor(*component.begin()).dim());
151  for (auto el_idx : component) {
152  // After we have complete graph tetrahedron-triangles-lines-points,
153  // the updating of duplicated nodes will have to change.
154  MeshObject *elem = &objects_[mesh_->element_accessor(el_idx).dim()][obj_4_el_[el_idx]];
155  for (unsigned int i=0; i<mesh_->element_accessor(el_idx).dim()+1; i++)
156  if (elem->nodes[i] == n.idx())
157  elem->nodes[i] = new_nid;
158  for (unsigned int fi=0; fi<mesh_->element_accessor(el_idx).dim()+1; fi++)
159  for (unsigned int ni=0; ni<mesh_->element_accessor(el_idx).dim(); ni++)
160  if (elem->faces[fi]->nodes[ni] == n.idx())
161  elem->faces[fi]->nodes[ni] = new_nid;
162  }
163  }
164  }
165  END_TIMER("duplicate_nodes");
166 }
167 
168 
169 
170 
const Edge * edge() const
Definition: side_impl.hh:66
vector< vector< unsigned int > > const & node_elements()
Definition: mesh.cc:998
std::vector< unsigned int > node_dim_
Vector of space dimensions of elements using the particular duplicated node.
MeshObject * faces[4]
(dim-1)-dimensional faces
unsigned int n_duplicated_nodes_
Number of nodes (including duplicated ones).
Mesh * mesh_
The mesh object.
Definition: mesh.h:76
SideIter side(const unsigned int loc_index)
Definition: accessors.hh:137
virtual unsigned int n_nodes() const
Definition: mesh.h:129
void init_from_edges()
Initialize objects from mesh edges.
virtual ElementAccessor< 3 > element_accessor(unsigned int idx) const
Create and return ElementAccessor to element of given idx.
Definition: mesh.cc:726
void duplicate_nodes()
Duplicate nodes that are lying on interfaces with fractures.
MeshObject(unsigned int dim)
void init_nodes()
Initialize the vector of nodes from mesh.
std::vector< unsigned int > obj_4_el_
std::vector< MeshObject > objects_[4]
Array of n-faces by their dimension.
#define START_TIMER(tag)
Starts a timer with specified tag.
virtual Range< ElementAccessor< 3 > > elements_range() const
Returns range of bulk elements.
Definition: mesh.cc:1040
unsigned int nodes[4]
Indices of nodes.
std::vector< unsigned int > obj_4_edg_
Vector of object indices for each mesh edge.
std::vector< Edge > edges
Vector of MH edges, this should not be part of the geometrical mesh.
Definition: mesh.h:252
void init_from_elements()
Initialize objects from mesh elements.
#define END_TIMER(tag)
Ends a timer with specified tag.
DuplicateNodes(Mesh *mesh)
Range< NodeAccessor< 3 > > node_range() const
Returns range of nodes.
Definition: mesh.cc:1046
unsigned int elem_idx() const
Definition: side_impl.hh:87
unsigned int dim() const
Definition: accessors.hh:87
SideIter side(const unsigned int i) const
Definition: edges.h:31