Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Simple_manifold_2.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: Simple_manifold_2.C,v 1.12 2008/12/06 08:43:21 mtcampbe Exp $
24 
25 #include "Simple_manifold_2.h"
26 #include "Dual_connectivity.h"
27 #include <iterator>
28 
30 
31 void Simple_manifold_2::init( const COM::Pane *p,
32  const Simple_manifold_2 *parent,
33  bool with_ghost) {
34  COM_assertion_msg( p, "Caught NULL pointer");
35  _pane = p;
36  _is_str = p->is_structured();
37 
38  // Initialize _nspe to 4 for structured or mixed meshes and to the
39  // actual number of edges per element for other type of meshes.
40  if ( _is_str) {
41  _with_ghost = with_ghost && p->size_of_ghost_layers()>0;
42  _nspe = 4;
43  }
44  else {
45  // It is possible to have ghost nodes but no ghost elements and vice versa
46  _with_ghost = with_ghost &&
47  (p->size_of_ghost_nodes()>0 || p->size_of_ghost_elements()>0);
48 
49  p->elements( _elem_conns);
50  _nspe = 0;
51  // Loop through the connectivity
52  for ( int i=_elem_conns.size()-1; i>=0; --i) {
53  _nspe = std::max( _nspe, int( _elem_conns[i]->size_of_edges_pe()));
54  }
55  }
56 
57  _maxsize_real_nodes = p->maxsize_of_real_nodes();
58  _maxsize_real_elmts = p->maxsize_of_real_elements();
59 
60  if ( parent) {
61  _isghostnode = parent->_isghostnode;
62  _isghostelmt = parent->_isghostelmt;
63 
64  // Copy border infomation from parent
66  _oeIDs_ghost = parent->_oeIDs_ghost;
68  _ieIDs_ghost = parent->_ieIDs_ghost;
69 
70  _beIDs = parent->_beIDs;
71  _isovIDs = parent->_isovIDs;
72  }
73  else {
77  }
78 }
79 
82  // _isghostnode and _isghostelmt not used for unstructured meshes
83  // and meshes without ghost
84  _isghostnode.clear();
85  _isghostelmt.clear();
86 
87  if ( !_is_str || !_with_ghost) return;
88 
89  // Fill in _isghostnode and _isghostelmt for structured mesh with ghosts
90  _isghostnode.resize( _pane->size_of_nodes(), false);
91  _isghostelmt.resize( _pane->size_of_elements(), false);
92 
93  COM_assertion_msg( false,
94  "Not fully implemented yet for structured mesh");
95 }
96 
99 
100  // Compute the dual connectivity.
102 
103  int nr = _nspe*_pane->size_of_real_elements();
104  _oeIDs_real_or_str.clear(); _oeIDs_real_or_str.resize( nr, Edge_ID());
105 
106  int ng = _with_ghost ? _nspe*_pane->size_of_ghost_elements():0;
107  _oeIDs_ghost.clear(); _oeIDs_ghost.resize( ng, Edge_ID());
108 
109  // Buffer array for holding border edges between real and ghost
110  std::vector<Edge_ID> beIDs_rg;
111 
112  // Determine the neighbor elements from the dual connectivity.
113  Element_node_enumerator ene( _pane, 1);
114  std::vector<int> ies1, ies2;
115  std::vector<int> ies_common; ies_common.reserve(2);
116 
117  // Process real elements of unstructured meshes or structured meshes
118  int nn = _is_str && _with_ghost
119  ? _pane->size_of_elements():_pane->size_of_real_elements();
120  for ( int j=0; j<nn; ++j, ene.next()) {
121  const int ne = ene.size_of_edges();
122  COM_assertion( _nspe>=ne);
123 
124  int ij = j*_nspe;
125  for ( int i=0; i<ne; ++i, ++ij) {
126  // Determine the elements that incident on both nodes of the edge
127  pdc.incident_elements( ene[i], ies1);
128  pdc.incident_elements( ene[(i==ne-1)?0:i+1], ies2);
129 
130  ies_common.clear();
131  std::back_insert_iterator< std::vector<int> > ii(ies_common);;
132  std::set_intersection( ies1.begin(), ies1.end(),
133  ies2.begin(), ies2.end(), ii);
134  COM_assertion( ies_common.size()<=2);
135 
136  int eid=0;
137  for ( std::vector<int>::iterator it_ies = ies_common.begin();
138  it_ies != ies_common.end(); ++it_ies)
139  if ( *it_ies != ene.id()) { eid = *it_ies; break; }
140 
141  // Determing the local side ID
142  if ( eid) {
143  int node_id = ene[i];
144  Element_node_enumerator ene_opp( _pane, eid);
145  const int nk=ene_opp.size_of_edges();
146  for ( int k=0; k<nk; ++k) if ( ene_opp[k] == node_id) {
147  Edge_ID opp = Edge_ID( eid, k?k-1:nk-1);
148 
149  bool isreal_edge = !_with_ghost || !_is_str || is_real_element( ene.id());
150  bool isghost_opp = _with_ghost && is_ghost_element( eid);
151 
152  if ( isreal_edge || isghost_opp)
153  // ghost elements of structured mesh
154  _oeIDs_real_or_str[ij] = opp;
155 
156  // Insert border edges incident on ghost elements into _beIDs_rg
157  if ( isghost_opp && isreal_edge) {
158  beIDs_rg.push_back( Edge_ID( ene.id(), i));
159 
160  Edge_ID bid = Edge_ID( beIDs_rg.size(), Edge_ID::BndID);
161  if (_is_str)
162  _oeIDs_real_or_str[ get_edge_index( opp)] = bid;
163  else
165  }
166 
167  break;
168  }
170  } // eid
171  else {
172  // Insert border edges of the real part into _beIDs
173  _beIDs.push_back( Edge_ID(ene.id(), i));
175  }
176  }
177  }
178 
179  // Save the number of real borders edges.
180  _size_real_borders = _beIDs.size();
181  _size_rg_borders = beIDs_rg.size();
182 
183  // Update the rg_border IDs
184  for ( int i=0; i<_size_rg_borders; ++i) {
185  Edge_ID gid = _oeIDs_real_or_str[get_edge_index(beIDs_rg[i])];
186 
187  Edge_ID *bid;
188  if ( _is_str)
189  bid = &_oeIDs_real_or_str[ get_edge_index( gid)];
190  else
192 
193  COM_assertion( bid->eid() == i+1);
194  *bid = Edge_ID( bid->eid()+_size_real_borders, Edge_ID::BndID);
195  }
196 
197  // Merge _beIDs and beIDs_rg together
198  _beIDs.insert( _beIDs.end(), beIDs_rg.begin(), beIDs_rg.end());
199  beIDs_rg.clear();
200 
201  // Process ghost elements
202  nn = _is_str || !_with_ghost ? 0 : _pane->size_of_ghost_elements();
204  for ( int j=0; j<nn; ++j, ene.next()) {
205  const int ne = ene.size_of_edges();
206  COM_assertion( _nspe>=ne);
207 
208  int ij = j*_nspe;
209  for ( int i=0; i<ne; ++i, ++ij) {
210  // Determine the elements that incident on both nodes of the edge
211  pdc.incident_elements( ene[i], ies1);
212  pdc.incident_elements( ene[(i==ne-1)?0:i+1], ies2);
213 
214  ies_common.clear();
215  std::back_insert_iterator< std::vector<int> > ii(ies_common);;
216  std::set_intersection( ies1.begin(), ies1.end(),
217  ies2.begin(), ies2.end(), ii);
218  COM_assertion( ies_common.size()<=2);
219 
220  int eid=0;
221  for ( std::vector<int>::iterator it_ies = ies_common.begin();
222  it_ies != ies_common.end(); ++it_ies)
223  if ( *it_ies != ene.id()) { eid = *it_ies; break; }
224 
225  // Determing the local side ID
226  if ( eid) {
227  if ( is_real_element( eid)) continue;
228 
229  int node_id = ene[i];
230  Element_node_enumerator ene_opp( _pane, eid);
231  const int nk=ene_opp.size_of_edges();
232  for ( int k=0; k<nk; ++k) if ( ene_opp[k] == node_id) {
233  _oeIDs_ghost[ij] = Edge_ID( eid, k?k-1:nk-1);
234  break;
235  }
237  }
238  else {
239  // Insert border edges of the ghost part of the pane into _beIDs
240  _beIDs.push_back( Edge_ID(ene.id(), i));
241  _oeIDs_ghost[ij] = Edge_ID( _beIDs.size(), Edge_ID::BndID);
242  }
243  }
244  }
245 
247 }
248 
252  int(_pane->size_of_real_nodes())==_maxsize_real_nodes &&
253  int(_pane->size_of_real_elements())==_maxsize_real_elmts,
254  "Support for maxsize not yet fully implemented");
255 
256  int nnodes, nelems;
257  if ( _is_str) { // For structured meshes, real and ghost are stored together
258  nnodes = _pane->size_of_nodes();
259  nelems = _pane->size_of_elements();
260  }
261  else {
262  nnodes = _pane->size_of_real_nodes();
263  nelems = _pane->size_of_real_elements();
264  }
265 
266  _ieIDs_real_or_str.clear(); _ieIDs_real_or_str.resize( nnodes, Edge_ID());
267 
268  Element_node_enumerator ene( _pane, 1);
269  for ( int j=0; j<nelems; ++j, ene.next()) {
270  int ne=ene.size_of_edges();
271 
272  for ( int i=0; i<ne; ++i) {
273  int vID=ene[i];
274 
275  // If the incident elements has not been assigned, or the
276  // incident edge is a border edge, then assign the incident elements.
277  Edge_ID prev( ene.id(),i?i-1:ne-1);
278  Edge_ID eoppID = is_real_element( ene.id()) ?
281 
282  Edge_ID &iid = _ieIDs_real_or_str[ vID-1];
283  if ( eoppID.is_border() && !is_border_edge( iid)) {
284  iid = eoppID;
285  COM_assertion( get_origin( iid) == vID);
286  }
287  else if ( iid==Edge_ID()) {
288  iid = Edge_ID( ene.id(), i);
289  COM_assertion( get_origin( iid, &ene) == vID);
290  }
291  }
292 
293  // Special treatment for edge centers of quadratic elements
294  int ne2 = std::min(ne+ne,ene.size_of_nodes());
295  for ( int i=ne, ni=ne2; i<ni; ++i) {
296  int vID=ene[i];
297 
298  // Make sure every edge centers points to one of its halfedge, and
299  // always points to the border halfedge if on the boundary.
300  Edge_ID eID( ene.id(), i-ne);
301  Edge_ID eoppID = is_real_element( ene.id()) ?
304 
305  Edge_ID &iid = _ieIDs_real_or_str[ vID-1];
306  if ( eoppID.is_border() && !is_border_edge( iid))
307  iid =eoppID;
308  else if ( iid==Edge_ID())
309  iid = eID;
310  }
311 
312  // Finally, handle face center.
313  if ( ne2<ene.size_of_nodes())
314  _ieIDs_real_or_str[ene[ne2]-1] = Edge_ID(ene.id(),0);
315  }
316 
317  if (!_is_str) {
318  // Identify isolated nodes that are not incident on any element
319  // and create a numbering for the isolated nodes.
320  _isovIDs.clear();
321  // Loop through all the nodes
322  for ( int i=1; i<=nnodes; ++i) {
323  Edge_ID &iid = _ieIDs_real_or_str[ i-1];
324  if ( iid == Edge_ID()) {
325  _isovIDs.push_back( i);
326  iid = Edge_ID( _beIDs.size()+_isovIDs.size(), -1);
327  }
328  }
329  }
330 
331  // We are done for structured mesh and unstructured without ghost
332  nnodes = _with_ghost ? _pane->size_of_ghost_nodes() : 0;
333  _ieIDs_ghost.clear(); _ieIDs_ghost.resize( nnodes, Edge_ID());
334  if ( _is_str || nnodes==0) return;
335 
336  // Handle ghost nodes and elements
337  nelems = _pane->size_of_ghost_elements();
338  if ( nelems>0) ene = Element_node_enumerator( _pane, _maxsize_real_elmts+1);
339 
340  for ( int j=0; j<nelems; ++j, ene.next()) {
341  int ne=ene.size_of_edges();
342 
343  for ( int i=0; i<ne; ++i) {
344  int vID=ene[i];
345  if ( is_real_node( vID)) continue; // skip real nodes.
346 
347  // If the incident elements has not been assigned, or the
348  // incident edge is a border edge, then assign the incident elements.
349  Edge_ID prev( ene.id(),i?i-1:ne-1);
351 
353  if ( eoppID.is_border() && !is_border_edge( iid)) {
354  iid = eoppID;
355  COM_assertion( get_origin( iid) == vID);
356  }
357  else if ( iid==Edge_ID()) {
358  iid = Edge_ID( ene.id(), i);
359  COM_assertion( get_origin( iid, &ene) == vID);
360  }
361  }
362 
363  // Special treatment for edge centers of quadratic elements
364  int ne2 = std::min(ne+ne,ene.size_of_nodes());
365  for ( int i=ne, ni=ne2; i<ni; ++i) {
366  int vID=ene[i];
367  if ( is_real_node( vID)) continue; // skip real nodes.
368 
369  // Make sure every edge centers points to one of its halfedge, and
370  // always points to the border halfedge if on the boundary.
371  Edge_ID eID( ene.id(), i-ne);
373 
375  if ( eoppID.is_border() && !is_border_edge( iid)) {
376  iid =eoppID;
377  COM_assertion( get_origin( iid) == vID);
378  }
379  else if ( iid==Edge_ID()) {
380  iid = eID;
381  COM_assertion( get_origin( iid, &ene) == vID);
382  }
383  }
384 
385  // Finally, handle face center.
386  if ( ne2<ene.size_of_nodes())
387  _ieIDs_ghost[ene[ne2]-_maxsize_real_nodes-1] = Edge_ID(ene.id(),0);
388  }
389 }
390 
392 get_borders( std::vector< bool> &is_border,
393  std::vector< bool> &is_isolated,
394  std::vector< Edge_ID > *b,
395  int *ng) const {
396 
397  int nr = size_of_real_nodes();
398  int nnodes;
399 
400  if ( ng != NULL) {
401  *ng = _with_ghost ? size_of_ghost_nodes() : 0;
402  nnodes = nr + *ng;
403  }
404  else
405  nnodes = nr;
406 
407  // First, get the isolated nodes
408  is_isolated.resize( nnodes, false);
409  if ( !_is_str) {
410  for ( int i=0; i<nr; ++i)
411  is_isolated[ i] = is_isolated_node( i+1);
412  }
413 
414  // Second, obtain the border nodes
415  is_border.resize( nnodes, false);
416  if ( ng && *ng) {
417  for ( int i=0; i<nr; ++i)
418  is_border[ i] = is_border_node( i+1);
419 
420  // Loop through all the nodes
421  const int offset=_maxsize_real_nodes-nr+1, nlast = nr+*ng;
422  for ( int i=nr; i<nlast; ++i)
423  is_border[ i] = is_border_node( offset+i);
424  }
425  else {
426  for ( int i=0; i<nr; ++i)
427  is_border[ i] = is_real_border_node( i+1);
428  }
429 
430  // Finally, fill in the border edges into b if exist.
431  if ( b) {
432  b->clear();
433 
434  if ( ng) {
436  b->insert( b->end(), &_beIDs[0], &_beIDs[_size_real_borders]);
437 
439  b->insert( b->end(), &_beIDs[nstart],
440  &_beIDs[nstart+_size_ghost_borders]);
441  }
442  else {
443  b->insert( b->end(), &_beIDs[0],
445  }
446  }
447 }
448 
449 #define SIZE_OF_ELMTS( prefix, name, nedges) \
450 int Simple_manifold_2:: prefix##name() const { \
451  int n=0; \
452  std::vector<const COM::Connectivity*>::const_iterator it=_elem_conns.begin(); \
453  for ( ; it != _elem_conns.end(); ++it) { \
454  if ( (*it)->size_of_edges_pe()==nedges) \
455  n += (*it)-> prefix##items(); \
456  } \
457  return n; \
458 }
459 
460 SIZE_OF_ELMTS( size_of_, triangles, 3);
461 SIZE_OF_ELMTS( size_of_real_, triangles, 3);
462 SIZE_OF_ELMTS( size_of_ghost_, triangles, 3);
463 
464 SIZE_OF_ELMTS( maxsize_of_, triangles, 3);
465 SIZE_OF_ELMTS( maxsize_of_real_, triangles, 3);
466 SIZE_OF_ELMTS( maxsize_of_ghost_, triangles, 3);
467 
468 SIZE_OF_ELMTS( size_of_, quadrilaterals, 4);
469 SIZE_OF_ELMTS( size_of_real_, quadrilaterals, 4);
470 SIZE_OF_ELMTS( size_of_ghost_, quadrilaterals, 4);
471 
472 SIZE_OF_ELMTS( maxsize_of_, quadrilaterals, 4);
473 SIZE_OF_ELMTS( maxsize_of_real_, quadrilaterals, 4);
474 SIZE_OF_ELMTS( maxsize_of_ghost_, quadrilaterals, 4);
475 
476 #define SIZE_OF_EDGES( prefix, name, multiple) \
477 int Simple_manifold_2::prefix##name() const { \
478  int n=prefix##border_edges(); \
479  std::vector<const COM::Connectivity*>::const_iterator it=_elem_conns.begin(); \
480  for ( ; it != _elem_conns.end(); ++it) { \
481  n += (*it)->prefix##items()*(*it)->size_of_edges_pe(); \
482  } \
483  return n/=multiple; \
484 }
485 
486 SIZE_OF_EDGES( size_of_, halfedges, 1);
487 SIZE_OF_EDGES( size_of_real_, halfedges, 1);
488 SIZE_OF_EDGES( size_of_ghost_, halfedges, 1);
489 
490 SIZE_OF_EDGES( size_of_, edges, 2);
491 SIZE_OF_EDGES( size_of_real_, edges, 2);
492 SIZE_OF_EDGES( size_of_ghost_, edges, 2);
493 
495 
496 
497 
498 
499 
500 
std::vector< Edge_ID > _oeIDs_real_or_str
#define MAP_END_NAMESPACE
Definition: mapbasic.h:29
void get_borders(std::vector< bool > &is_border, std::vector< bool > &is_isolated, std::vector< Edge_ID > *b, int *ng=NULL) const
Obtain all the border nodes, isolated nodes, and border edges.
std::vector< const COM::Connectivity * > _elem_conns
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
An adaptor for enumerating node IDs of an element.
bool is_real_node(int vID) const
Is the given node a real node?
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
#define SIZE_OF_ELMTS(prefix, name, nedges)
bool is_real_border_node(int vID) const
Is the node on the pane boundary of real part (not isolated)?
std::vector< Edge_ID > _ieIDs_ghost
int size_of_real_nodes() const
Number of real nodes of the pane.
bool is_border_edge(const Edge_ID &eID) const
Is a given edge on the boundary of the whole pane?
void incident_elements(int node_id, std::vector< int > &elists)
Obtain the IDs of the elements incident on a given node.
real *8 function offset(vNorm, x2, y2, z2)
Definition: PlaneNorm.f90:211
std::vector< Edge_ID > _ieIDs_real_or_str
int eid() const
Element ID of the halfedge.
int id() const
Get the local id of the element within the pane.
std::vector< bool > _isghostelmt
Edge_ID get_opposite_ghost_edge_interior(const Edge_ID &eID) const
Get the opposite edge of an interior edge of the ghost part.
void init(const COM::Pane *p, const Simple_manifold_2 *parent=NULL, bool with_ghost=true)
Initialize the database for the pane, including ghost information, opposite halfedges, incident halfedges, and border halfedges.
int get_edge_index(const Edge_ID &eid, const int offset=0) const
Get an index for internal edges.
std::vector< Edge_ID > _oeIDs_ghost
int size_of_edges() const
Number of edges per element.
blockLoc i
Definition: read.cpp:79
bool is_ghost_element(int eid) const
Is the element incident on the give edge a ghost element?
bool is_real_element(int eid) const
Is the element incident on the give edge a real element?
int size_of_nodes() const
Number of nodes per element.
Provides a data structure accessing nodes, elements, and edges in a pane, in a manner similar to the ...
std::vector< int > _isovIDs
int size_of_ghost_nodes() const
Number of ghost nodes of the pane.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
void int int * nk
Definition: read.cpp:74
const COM::Pane * _pane
j indices j
Definition: Indexing.h:6
The ID of a facet (edge in 2D and face in 3D) encodes an element ID and the local facet&#39;s ID internal...
std::vector< bool > _isghostnode
#define MAP_BEGIN_NAMESPACE
Definition: mapbasic.h:28
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
std::vector< Edge_ID > _beIDs
#define SIZE_OF_EDGES(prefix, name, multiple)
void determine_incident_halfedges()
Determine an incident halfedge for each node.
int get_origin(Edge_ID eID, Element_node_enumerator *ene_in=NULL) const
Get the ID of the origin of a given edge.
bool is_border_node(int vID) const
Is the node on pane boundary (not isolated)?
Edge_ID get_opposite_real_edge_interior(const Edge_ID &eID) const
Get the opposite edge of an interior edge of the real part.
Constructs the dual connectivity for the whole pane (including ghost nodes and elements), which contains information about incident elements for each node.
void determine_ghosts()
Determine the ghost nodes and elements.
void determine_opposite_halfedges()
Determine the opposite halfedges of each halfedge, and identify border halfedge.
bool is_isolated_node(int vID) const
Is the node isolated (i.e. not incident on any element)?