Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Pane_boundary.C
Go to the documentation of this file.
1 /* *******************************************************************
2  * Rocstar Simulation Suite *
3  * Copyright@2015, Illinois Rocstar LLC. All rights reserved. *
4  * *
5  * Illinois Rocstar LLC *
6  * Champaign, IL *
7  * www.illinoisrocstar.com *
8  * sales@illinoisrocstar.com *
9  * *
10  * License: See LICENSE file in top level of distribution package or *
11  * http://opensource.org/licenses/NCSA *
12  *********************************************************************/
13 /* *******************************************************************
14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *
15  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *
16  * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *
17  * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR *
18  * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, *
20  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE *
21  * USE OR OTHER DEALINGS WITH THE SOFTWARE. *
22  *********************************************************************/
23 // $Id: Pane_boundary.C,v 1.31 2008/12/06 08:43:21 mtcampbe Exp $
24 
25 #include <map>
26 #include <algorithm>
27 #include <cassert>
28 #include <cstdlib>
29 #include <iostream>
30 #include <sstream>
31 
32 #include "Pane_boundary.h"
33 
35 
36 void Pane_boundary::
37 determine_border_nodes( std::vector<bool> &is_border,
38  std::vector<bool> &is_isolated,
39  std::vector<Facet_ID > *b,
40  int ghost_level) throw(int) {
41  if ( _pane.dimension() == 2) {
42  int ng;
43  int *ng_ptr = ghost_level ? &ng : (int*)NULL;
44 
45  if ( _pm) {
46  _pm->get_borders( is_border, is_isolated, b, ng_ptr);
47  }
48  else
49  Simple_manifold_2( &_pane, NULL, ghost_level).
50  get_borders( is_border, is_isolated, b, ng_ptr);
51  }
52  else {
53 
54  determine_border_nodes_3( is_border, b, ghost_level);
55  determine_isolated_nodes( is_isolated, ghost_level);
56  }
57 }
58 
59 // A helper class for comparing two faces.
60 struct Four_tuple {
61  Four_tuple( int a, int b, int c, int d)
62  : _a(a), _b(b), _c(c), _d(d) {}
63  int &operator[](int i) { return (&_a)[i]; }
64  const int &operator[](int i) const { return (&_a)[i]; }
65  bool operator<( const Four_tuple &x) const {
66  return _a<x._a || (_a==x._a && (_b<x._b || _b==x._b &&
67  (_c<x._c || _c==x._c && _d<x._d)));
68  }
69 private:
70  int _a, _b, _c, _d;
71 };
72 
73 typedef std::map< Four_tuple, Facet_ID> Corners2Face_Map;
74 
75 // Check whether a given face exists in the facemap. If so, remove the
76 // face from the map; otherwise, insert it into the map. This function
77 // uses a vector of Corners2Face_Map to reduce worst-case time complexity.
78 static void
79 check_face_unique( const Four_tuple &face_corners,
80  const Facet_ID &fid,
81  std::vector< Corners2Face_Map > &c2f_vec,
82  int &num_external_face, int &counter) {
83 
84  // Sort the node ids of the face
85  Four_tuple sorted_ns( face_corners);
86  std::sort( &sorted_ns[0], &sorted_ns[4]);
87 
88  // Check whether the sorted node-list is in vec2facemap_vec
89  // by trying to insert it
90  Corners2Face_Map &c2f = c2f_vec[sorted_ns[1]-1];
91 
92  std::pair<Corners2Face_Map::iterator, bool>
93  ans = c2f.insert( std::make_pair(sorted_ns, fid));
94 
95  // If the node-list already exists, then remove it from vecFaceMap
96  if ( !ans.second) {
97  counter++;
98  c2f.erase( ans.first);
99  --num_external_face;
100  }
101  // Otherwise, insertion succeeded.
102  else ++num_external_face;
103 }
104 
105 void Pane_boundary::
106 determine_border_nodes_3( std::vector<bool> &is_border,
107  std::vector<Facet_ID > *b,
108  int ghost_level ) throw(int) {
109  int num_nodes, num_elmts;
110 
111  if (ghost_level == 0){
112  num_nodes=_pane.size_of_real_nodes();
113  num_elmts=_pane.size_of_real_elements();
114  }
115  else {
116  COM_assertion_msg(ghost_level > 0, "Ghost level must be positive");
117  num_nodes=_pane.size_of_nodes();
118  num_elmts=_pane.size_of_elements();
119  }
120 
121  // Initialize is_border to false for all nodes.
122  is_border.clear(); is_border.resize( num_nodes, false);
123 
124  // Handle structured meshes
125  if ( _pane.is_structured()) {
126 
127  const int ni=_pane.size_i(), nj=_pane.size_j(), nk=_pane.size_k();
128 
129  // s = the first index on the level above the bottom
130  // t = the first index on the top level
131  // h = an offset for the first index on a layer with ghosts
132  // w = the length of the i dimension with ghosts
133  // buffer = number of layers we 'skip' for determining borders
134 
135  int buffer = _pane.size_of_ghost_layers() - ghost_level;
136  buffer = buffer < 0 ? 0 : buffer;
137  int s = ni*nj;
138  int t = ni*nj*(nk-1);
139  int h = buffer*ni + buffer;
140  int w = ni - 2*buffer;
141 
142  //bottom
143  for ( int j=s*(buffer) + h, j_end = s*(1+buffer) - ni*buffer; j< j_end; j += ni){
144  std::fill_n( is_border.begin() +j, w, true);
145  }
146  //top
147  for ( int j= t+h-s*buffer, end = s*nk - s*buffer- ni*buffer; j< end; j += ni){
148  std::fill_n( is_border.begin() +j, w, true);
149  }
150 
151  //left and right
152  for ( int j= s*(1+buffer)+h, stop = t-s*buffer+h; j< stop; j += ni*nj){
153  std::fill_n( is_border.begin() +j, w, true);
154  std::fill_n( is_border.begin() +j + ni*((nj-1) - 2*buffer), w, true);
155  }
156 
157  //upper and lower
158  for ( int j= s*(1+buffer)+h; j< t-s*buffer+h; j += ni*nj){
159  for (int k=ni, k_end = ni*(nj-(1+2*buffer)); k< k_end; k += ni){
160  is_border[j+k] = true;
161  is_border[j+k + (ni - (2*buffer+ 1)) ] = true;
162  }
163  }
164 
165  return;
166  }
167 
168  // Now consider unstructured panes
169  std::vector< Corners2Face_Map> c2f_vec(num_nodes);
170  int num_external_face=0;
171 
172 
173  // Determine all border faces
174  Element_node_enumerator ene( &_pane, 1);
175  int counter = 0;
176  int count2 = 0;
177 
178  for (int i=1; i<=num_elmts; ++i, ene.next()) {
179  //for (int i=1; i<=6; ++i, ene.next()) {
180  for (int j=0, nf=ene.size_of_faces(); j<nf; ++j ){
181  Facet_node_enumerator fne( &ene, j) ;
182 
183  Four_tuple ns( fne[0], fne[1], fne[2], fne.size_of_edges()>3?fne[3]:-1);
184  count2++;
185  check_face_unique( ns, Facet_ID(i, j), c2f_vec, num_external_face, counter);
186  }
187  }
188 
189  // Mark all nodes of the border faces as border nodes, and
190  // insert their edges into b.
191  if ( b)
192  { b->clear(); b->reserve( num_external_face); }
193 
194  std::vector<int> nodes; nodes.reserve(9);
195 
196  for (int i=0; i<num_nodes; ++i){
197  Corners2Face_Map::const_iterator vit = c2f_vec[i].begin();
198  Corners2Face_Map::const_iterator v_end = c2f_vec[i].end();
199 
200  for ( ; vit != v_end; ++vit) {
201  // Get all nodes of the face into vector nodes.
202  const Facet_ID &fid = vit->second;
203  Element_node_enumerator_uns ene( &_pane, fid.eid());
204  Facet_node_enumerator fne( &ene, fid.lid());
205  fne.get_nodes( nodes, true);
206 
207  for ( int i=0, n=nodes.size(); i<n; ++i)
208  is_border[ nodes[i] - 1 ] = true;
209 
210  if (b) b->push_back( fid);
211  }
212  }
213 
214 }
215 
216 void Pane_boundary::
217 determine_isolated_nodes( std::vector<bool> &is_isolated,
218  int ghost_level) throw(int) {
219  // Initialize to true
220  is_isolated.clear();
221 
222  int nnodes = ghost_level ?
223  _pane.size_of_nodes() : _pane.size_of_real_nodes();
224 
225  if ( _pane.is_structured()) {
226  // A structured mesh have no isolated nodes.
227  is_isolated.resize( nnodes, false);
228  return;
229  }
230 
231  is_isolated.resize( nnodes, true);
232 
233  // Loop through the connectivity table to mark their nodes as false.
234  Element_node_enumerator_uns ene(&_pane, 1);
235  int nelems = ghost_level ?
236  _pane.size_of_elements() : _pane.size_of_real_elements();
237  for ( int i=0,size=nelems; i<size; ++i, ene.next()) {
238  for ( int j=ene.size_of_nodes()-1; j>=0; --j)
239  is_isolated[ ene[j]-1] = false;
240  }
241 }
242 
243 inline double square( double x) { return x*x; }
244 
245 double Pane_boundary::
246 min_squared_edge_len( const std::vector<Facet_ID > &be) throw(int) {
247  const COM::Attribute *attr = _pane.attribute( COM::COM_NC);
248 
249  double sql = HUGE_VAL;
250 
251  // Loop through all the edges of border facets to compute the
252  // shortest squared edge length.
253  std::vector<Facet_ID >::const_iterator it;
254  for ( it=be.begin(); it!=be.end(); ++it) {
255  Element_node_enumerator ene( &_pane, it->eid());
256  Facet_node_enumerator fne( &ene, it->lid());
257  int ne = fne.size_of_corners();
258 
259  // Loop through all edges of the facet.
260  for ( int j=0; j<fne.size_of_edges(); ++j) {
261  int n1 = fne[j], n2 = fne[(j+1)%ne];
262  const double *x1 = (const double*)attr->get_addr( n1-1, 0);
263  const double *x2 = (const double*)attr->get_addr( n2-1, 0);
264 
265  double sqdiff;
266  if ( attr->stride() >= 3) {
267  // Contiguous layout of coordinates
268  sqdiff = square(x1[0]-x2[0])+square(x1[1]-x2[1])+square(x1[2]-x2[2]);
269  }
270  else {
271  // This supports R^2 points.
272  sqdiff=square(x1[0]-x2[0]);
273  for ( int i=1, d=attr->size_of_components(); i<d; ++i) {
274  sqdiff += square((const double*)attr->get_addr( n1-1, i)-
275  (const double*)attr->get_addr( n2-1, i));
276  }
277  }
278 
279  sql = std::min( sql, sqdiff);
280  }
281  }
282 
283  return sql;
284 }
285 
286 void Pane_boundary::determine_borders( const COM::Attribute *mesh,
287  COM::Attribute *isborder,
288  int ghost_level) {
289  COM_assertion_msg( mesh, "Unexpected NULL pointer");
290  COM_assertion_msg( isborder, "Unexpected NULL pointer");
291  COM_assertion_msg( COM_compatible_types( isborder->data_type(), COM_INT),
292  "Border-list must have integer type");
293  COM_assertion_msg( isborder->is_nodal() == 1,
294  "Border-list must have integer type");
295 
296  std::vector<COM::Pane*> panes;
297  isborder->window()->panes( panes);
298 
299  for ( int i=0, n=panes.size(); i<n; ++i) {
300  Pane_boundary pb( panes[i]);
301  COM::Attribute *bdl_pane = panes[i]->attribute(isborder->id());
302 
303  std::vector<bool> is_border_bitmap, is_isolated;
304  pb.determine_border_nodes( is_border_bitmap, is_isolated,
305  NULL, ghost_level);
306 
307  int *ptr = (int *)bdl_pane->pointer();
308  int nj=0;
309  if (ghost_level == 0)
310  nj=panes[i]->size_of_real_nodes();
311  else {
312  COM_assertion_msg(ghost_level > 0, "Ghost level must be positive");
313  nj=panes[i]->size_of_nodes();
314  }
315  for ( int j=0; j<nj; ++j) {
316  ptr[j] = is_border_bitmap[j];
317  }
318  }
319 }
320 
322 
323 
324 
325 
326 
327 
bool operator<(const Four_tuple &x) const
Definition: Pane_boundary.C:65
#define MAP_END_NAMESPACE
Definition: mapbasic.h:29
double square(double x)
A structure used to represent element faces.
Definition: Pane_boundary.C:60
An adaptor for enumerating node IDs of an element.
const NT & d
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
double s
Definition: blastest.C:80
void get_nodes(std::vector< int > &nodes, bool quad_ret)
char lid() const
Local edge ID of the halfedge within its element.
const int & operator[](int i) const
Definition: Pane_boundary.C:64
Adaptor for enumerating node IDs of a facet of an element.
int eid() const
Element ID of the halfedge.
std::map< Four_tuple, Facet_ID > Corners2Face_Map
Definition: Pane_boundary.C:73
void determine_border_nodes(std::vector< bool > &is_border, std::vector< bool > &is_isolated, std::vector< Facet_ID > *b=NULL, int ghost_level=0)
Determine the border nodes (excluding isolated nodes)
Definition: Pane_boundary.C:37
static void check_face_unique(const Four_tuple &face_corners, const Facet_ID &fid, std::vector< Corners2Face_Map > &c2f_vec, int &num_external_face, int &counter)
Definition: Pane_boundary.C:79
const int num_nodes
Definition: ex1.C:96
int COM_compatible_types(COM_Type type1, COM_Type type2)
Definition: roccom_c++.h:563
blockLoc i
Definition: read.cpp:79
void int int REAL * x
Definition: read.cpp:74
void determine_isolated_nodes(std::vector< bool > &is_isolated, int ghost_level)
Determine the isolated nodes (i.e. not belonging to any element)
Four_tuple(int a, int b, int c, int d)
Definition: Pane_boundary.C:61
Provides a data structure accessing nodes, elements, and edges in a pane, in a manner similar to the ...
const NT & n
int & operator[](int i)
Definition: Pane_boundary.C:63
void determine_border_nodes_3(std::vector< bool > &is_border, std::vector< Facet_ID > *b, int ghost_level)
Determine the border nodes for a 3-D mesh.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
static void determine_borders(const COM::Attribute *mesh, COM::Attribute *isborder, int ghost_level=0)
Determine the nodes at pane boundaries of a given mesh.
void int int * nk
Definition: read.cpp:74
const int num_elmts
Definition: ex1.C:97
j indices j
Definition: Indexing.h:6
int size_of_faces() const
Number of faces per element.
The ID of a facet (edge in 2D and face in 3D) encodes an element ID and the local facet&#39;s ID internal...
#define MAP_BEGIN_NAMESPACE
Definition: mapbasic.h:28
double min_squared_edge_len(const std::vector< Facet_ID > &)
Compute the minimum squared edge length of given edges.
void next()
Go to the next element within the connectivity tables of a pane.
void int int REAL REAL REAL *z blockDim dim * ni
Definition: read.cpp:77
void int * nj
Definition: read.cpp:74
Optimized version for unstructured meshes.
Utility for detecting boundaries of a pane.