Flow123d  JS_before_hm-887-g601087d
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  for (unsigned int i=0; i<4; i++)
35  faces[i] = nullptr;
36 }
37 
38 
40 : mesh_(mesh),
41  n_duplicated_nodes_(0)
42 {
43  init_nodes();
47 }
48 
49 
50 
52 {
53  // initialize the nodes
56 }
57 
58 
59 
61 {
62  // initialize the objects from edges
63  for (auto edge : mesh_->edge_range()) {
64  MeshObject obj(edge.side(0)->dim());
65  for (unsigned int i=0; i<edge.side(0)->dim()+1; ++i)
66  obj.nodes[i] = edge.side(0)->node(i).idx();
67  obj_4_edg_.push_back(objects_[edge.side(0)->dim()].size());
68  objects_[edge.side(0)->dim()].push_back(obj);
69  }
70 }
71 
72 
73 
75 {
76  // initialize the objects from elements
77  for ( auto ele : mesh_->elements_range() ) {
78  MeshObject l(ele->dim());
79  for (unsigned int i=0; i<ele->dim()+1; i++)
80  l.nodes[i] = ele->node_idx(i);
81  for (unsigned int i=0; i<ele->dim()+1; i++)
82  l.faces[i] = &objects_[ele->dim()-1][obj_4_edg_[ele->edge_idx(i)]];
83  obj_4_el_.push_back(objects_[ele->dim()].size());
84  objects_[ele->dim()].push_back(l);
85  }
86 }
87 
88 
89 /**
90  * The main functionality of the class creates duplicate nodes
91  * at interfaces with fractures.
92  *
93  * For each node:
94  * 1) Create the lists of elements (node_elements) sharing the node.
95  * 2) Divide node_elements into groups (components) connected by edges.
96  * 3) If more than one component was created, create for each extra component a new node
97  * and update its index in the elements from this component.
98  * Also set node_dim_ (dimension of elements using the node).
99  */
101 {
102  START_TIMER("duplicate_nodes");
103  for ( auto n : mesh_->node_range() ){
104  // create list of adjacent elements from mesh_->node_elements[n.idx()]
105  std::list<unsigned int> node_elements;
106  std::copy( mesh_->node_elements()[n.idx()].begin(), mesh_->node_elements()[n.idx()].end(), std::back_inserter( node_elements ) );
107 
108  // divide node_elements into components connected by node_edges
110  while (node_elements.size() > 0)
111  {
112  // create component containing the first element in node_elements
113  std::queue<unsigned int> q;
114  q.push(*node_elements.begin());
115  node_elements.erase(node_elements.begin());
116  std::set<unsigned int> component;
117  while (q.size() > 0) {
118  auto elem = mesh_->element_accessor(q.front());
119  component.insert(elem.idx());
120  // add to queue adjacent elements sharing one of node_edges
121  for (unsigned int sid=0; sid<elem->n_sides(); ++sid) {
122  auto side = elem.side(sid);
123  for (unsigned int esid=0; esid < side->edge().n_sides(); ++esid) {
124  auto adj_el_idx = side->edge().side(esid)->elem_idx();
125  if (adj_el_idx != elem.idx())
126  {
127  auto it = std::find(node_elements.begin(), node_elements.end(), adj_el_idx);
128  if (it != node_elements.end()) {
129  node_elements.erase(it);
130  q.push(adj_el_idx);
131  }
132  }
133  }
134  }
135  q.pop();
136  }
137  components.push_back(component);
138  }
139 
140  // For the first component leave the current node and set its node_dim_.
141  // If there are more components, then for each additional component
142  // create a duplicate of the node and update the affected mesh objects.
143  if (components.size() > 0) {
144  node_dim_[n.idx()] = mesh_->element_accessor(*(components.begin()->begin())).dim();
145  components.erase(components.begin());
146  }
147  for (auto component : components) {
148  unsigned int new_nid = n_duplicated_nodes_++;
149  node_dim_.push_back(mesh_->element_accessor(*component.begin()).dim());
150  for (auto el_idx : component) {
151  // After we have complete graph tetrahedron-triangles-lines-points,
152  // the updating of duplicated nodes will have to change.
153  MeshObject *elem = &objects_[mesh_->element_accessor(el_idx).dim()][obj_4_el_[el_idx]];
154  for (unsigned int i=0; i<mesh_->element_accessor(el_idx).dim()+1; i++)
155  if (elem->nodes[i] == n.idx())
156  elem->nodes[i] = new_nid;
157  for (unsigned int fi=0; fi<mesh_->element_accessor(el_idx).dim()+1; fi++)
158  for (unsigned int ni=0; ni<mesh_->element_accessor(el_idx).dim(); ni++)
159  if (elem->faces[fi]->nodes[ni] == n.idx())
160  elem->faces[fi]->nodes[ni] = new_nid;
161  }
162  }
163  }
164  END_TIMER("duplicate_nodes");
165 }
166 
167 
168 
169 
vector< vector< unsigned int > > const & node_elements()
Definition: mesh.cc:1054
std::vector< unsigned int > node_dim_
Vector of space dimensions of elements using the particular duplicated node.
MeshObject * faces[4]
(dim-1)-dimensional faces
Edge edge() const
Returns pointer to the edge connected to the side.
unsigned int n_duplicated_nodes_
Number of nodes (including duplicated ones).
Mesh * mesh_
The mesh object.
Definition: mesh.h:78
SideIter side(const unsigned int loc_index)
virtual unsigned int n_nodes() const
Definition: mesh.h:126
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:780
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:1088
unsigned int nodes[4]
Indices of nodes.
std::vector< unsigned int > obj_4_edg_
Vector of object indices for each mesh edge.
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:1094
unsigned int elem_idx() const
Returns index of element in Mesh::element_vec_.
Definition: accessors.hh:419
unsigned int dim() const
Definition: accessors.hh:157
SideIter side(const unsigned int i) const
Gets side iterator of the i -th side.
Range< Edge > edge_range() const
Returns range of edges.
Definition: mesh.cc:1100