Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
Pane_connectivity.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_connectivity.C,v 1.35 2008/12/06 08:43:21 mtcampbe Exp $
24 
25 #include <set>
26 #include <map>
27 #include <cassert>
28 #include <algorithm>
29 #include <iostream>
30 
31 #include "kdtree_d.h"
32 #include "Pane_connectivity.h"
33 #include "Pane_boundary.h"
34 
36 
37 class Point_3_ref : protected Point_3<Real> {
38 public:
39  Point_3_ref() : offs_(-1) {}
40  Point_3_ref( Real x, Real y, Real z) : Point_3<Real>(x,y,z), offs_(-1) {}
41  Point_3_ref( const Point_3<Real> &r, int k) : Point_3<Real>(r), offs_(k) {}
42 
44 
45  int offset() const
46  { assert( offs_>1); return offs_; }
47 
48 private:
49  int offs_;
50 };
51 
52 class KD_tree_3 :
53  public CGAL::Kdtree_d<CGAL::Kdtree_interface<Point_3<Real> > >
54 {
55  typedef CGAL::Kdtree_d<CGAL::Kdtree_interface<Point_3<Real> > > Base;
56 public:
57  KD_tree_3() : Base(3) {}
58 };
59 
61  public CGAL::Kdtree_d<CGAL::Kdtree_interface<Point_3_ref > >
62 {
63  typedef CGAL::Kdtree_d<CGAL::Kdtree_interface<Point_3_ref > > Base;
64 public:
66 };
67 
68 typedef std::pair<int,int> pair_int;
69 typedef std::pair<int,int> Node_ID;
70 
72 Pane_connectivity( const COM::Attribute *mesh, MPI_Comm c)
73  : _win(mesh->window()), _mani2(NULL),
74  _comm( COMMPI_Initialized()?c:MPI_COMM_NULL)
75 {
76  _win->panes( const_cast<std::vector<const COM::Pane*>&>(_panes));
77 }
78 
80 Pane_connectivity( const Simple_manifold_2 **mani2, MPI_Comm c)
81  : _win( mani2[0]->pane()->window()), _mani2(mani2),
82  _comm( COMMPI_Initialized()?c:MPI_COMM_NULL)
83 {
84  _win->panes( const_cast<std::vector<const COM::Pane*>&>(_panes));
85 }
86 
87 static void convert_nodelist( const std::vector<bool> &bs,
88  std::vector<int> &nodes) {
89  nodes.clear();
90  const int s = bs.size();
91  for ( int i=0; i<s; ++i)
92  if ( bs[i]) nodes.push_back( i+1);
93 }
94 
96 collect_nodes( const std::vector<std::vector<int> > &ns,
97  std::vector<int> &nodes,
98  std::vector<Point_3> &pnts,
99  bool for_facet) {
100  int count=0;
101  for (unsigned int i=0; i<ns.size(); ++i) count+=ns[i].size();
102 
103  // Collect the nodes
104  nodes.clear(); nodes.reserve( count+2*ns.size());
105  pnts.clear(); pnts.reserve( count+2*ns.size());
106 
107  for ( int i=0, s=_panes.size(); i<s; ++i) {
108  nodes.push_back( _panes[i]->id());
109  nodes.push_back( ns[i].size());
110 
111  nodes.insert( nodes.end(), ns[i].begin(), ns[i].end());
112 
113  pnts.push_back( Point_3(HUGE_VAL,HUGE_VAL,HUGE_VAL));
114  Point_3 &bnd_min = pnts.back();
115  pnts.push_back( Point_3(-HUGE_VAL,-HUGE_VAL,-HUGE_VAL));
116  Point_3 &bnd_max = pnts.back();
117 
118  const COM::Attribute *attr = _panes[i]->attribute( COM::COM_NC);
119  const int d = attr->size_of_components();
120 
121  for (std::vector<int>::const_iterator it=ns[i].begin(), iend=ns[i].end();
122  it!=iend;++it) {
123  Point_3 p(0,0,0);
124  if ( !for_facet) {
125  int j=*it-1;
126 
127  for ( int k=0; k<d; ++k)
128  p[k] = *(const double*)attr->get_addr( j, k);
129  }
130  else {
131  Facet_ID eID=(Facet_ID&)(*it);
132  Element_node_enumerator ene( _panes[i], eID.eid());
133  int vdst=(ene[eID.lid()+1==ene.size_of_edges()?0:eID.lid()+1]);
134  int j1=ene[eID.lid()]-1, j2=vdst-1;
135 
136  for ( int k=0; k<d; ++k) {
137  p[k] = 0.5*(*(const double*)attr->get_addr( j1, k) +
138  *(const double*)attr->get_addr( j2, k));
139  }
140  }
141 
142  pnts.push_back( p);
143 
144  for (int k=0; k<3; ++k) {
145  bnd_min[k] = std::min( bnd_min[k], p[k]);
146  bnd_max[k] = std::max( bnd_max[k], p[k]);
147  }
148  }
149  }
150 }
151 
153 collect_points( const std::vector<std::vector<int> > &ns,
154  std::vector<Point_3> &pnts) {
155  int count=0;
156  for (unsigned int i=0; i<ns.size(); ++i) count+=ns[i].size();
157  pnts.clear(); pnts.reserve( count);
158 
159  for ( int i=0, s=_panes.size(); i<s; ++i) {
160  const COM::Attribute *attr = _panes[i]->attribute( COM::COM_NC);
161  const int d = attr->size_of_components();
162 
163  for (std::vector<int>::const_iterator it=ns[i].begin(), iend=ns[i].end();
164  it!=iend;++it) {
165  Point_3 p(0,0,0);
166  int j=*it-1;
167  for ( int k=0; k<d; ++k)
168  p[k] = *(const double*)attr->get_addr( j, k);
169 
170  pnts.push_back( p);
171  }
172  }
173 }
174 
175 
176 // Determine the real nodes that coincide with given isolated points.
178 determine_coisolated_nodes( const COM::Pane &pn,
179  std::vector<Point_3> &pnts,
180  const double tol,
181  std::vector<bool> &is_co,
182  KD_tree_3 *tree) throw(int) {
183 
184  int n=pn.size_of_real_nodes();
185  is_co.clear(); is_co.resize( n, false);
186 
187  // Build a kd-tree from the points in pnts if not give at input
188  KD_tree_3 ktree_local;
189 
190  if ( tree == NULL) {
191  ktree_local.build( pnts);
192  tree = &ktree_local;
193  }
194 
195  // Define a temporary buffer for holding the matching points.
196  std::vector< Point_3> outList; outList.reserve(4);
197 
198  // Loop through the nodes in the current pane to determine coisolated nodes
199  const COM::Attribute *attr = pn.attribute( COM::COM_NC);
200  const int d = attr->size_of_components();
201 
202  for ( int j=0; j<n; ++j) {
203  Point_3 q(0,0,0);
204  for ( int k=0; k<d; ++k)
205  q[k] = *(const double*)attr->get_addr( j, k);
206 
207  Point_3 lb(q.x()-tol, q.y()-tol, q.z()-tol);
208  Point_3 ub(q.x()+tol, q.y()+tol, q.z()+tol);
209  KD_tree_3::Box box( lb, ub, 3);
210 
211  // If found match in the tree, then the current node is coisolated.
212  outList.clear();
213 
214  tree->search( std::back_inserter( outList), box);
215 
216  if ( outList.size()) is_co[j]=true;
217  }
218 }
219 
220 double Pane_connectivity::
221 get_local_boundary_nodes( std::vector<int> &nodes,
222  std::vector<Point_3> &pnts,
223  bool for_facet) throw(int) {
224 
225  std::vector< std::vector<int> > ns(_panes.size());
226  std::vector< std::vector<int> > iso_ns(_panes.size());
227 
228  double sql = HUGE_VAL;
229  int iso_local=0;
230  for ( int i=0, s=_panes.size(); i<s; ++i) {
231  std::vector<bool> is_border;
232  std::vector<bool> is_isolated;
233  std::vector<Facet_ID> facets;
234 
235  Pane_boundary pb =
236  _mani2 ? Pane_boundary( _mani2[i]) : Pane_boundary( _panes[i]);
237 
238  pb.determine_border_nodes( is_border, is_isolated, &facets);
239  sql = std::min( sql, pb.min_squared_edge_len( facets));
240 
241  if ( !for_facet) {
242  convert_nodelist( is_border, ns[i]);
243  convert_nodelist( is_isolated, iso_ns[i]);
244 
245  iso_local += iso_ns[i].size();
246  }
247  else {
248  ns[i].clear();
249  ns[i].insert( ns[i].end(), (int*)&*facets.begin(), (int*)&*facets.end());
250  }
251  }
252 
253  // Compute minimum squared edge length.
254  double g_sql=sql;
255  if ( _comm != MPI_COMM_NULL)
256  MPI_Allreduce( &sql, &g_sql, 1, MPI_DOUBLE, MPI_MIN, _comm);
257 
258  if ( g_sql==HUGE_VAL) g_sql=0;
259  double tol = std::sqrt( g_sql)*0.03;
260 
261  if ( !for_facet) {
262  std::vector<int> iso_counts;
263 
264  // Is there any isolated nodes?
265  int comm_size, comm_rank;
266  if ( _comm != MPI_COMM_NULL) {
267  MPI_Comm_size( _comm, &comm_size);
268  MPI_Comm_rank( _comm, &comm_rank);
269 
270  iso_counts.resize(comm_size);
271  MPI_Allgather(&iso_local, 1, MPI_INT, &iso_counts[0], 1, MPI_INT, _comm);
272 
273  iso_local=0;
274  for (int i=0; i<comm_size; ++i) iso_local+=iso_counts[i];
275  }
276  else {
277  comm_size=1;
278  comm_rank=0;
279  }
280 
281  if ( iso_local) { // Determine all nodes incident on isolated nodes.
282  collect_points( iso_ns, pnts);
283 
284  // Collect all isolated nodes onto the processor
285  std::vector< Point_3> pnts_g( iso_local);
286 
287  if ( _comm != MPI_COMM_NULL) {
288  for (int i=0; i<comm_size; ++i)
289  iso_counts[i]*=3;
290 
291  std::vector<int> iso_disps(comm_size, 0);
292  for (int i=1; i<comm_size; ++i)
293  iso_disps[i]=iso_disps[i-1]+iso_counts[i-1];
294 
295  MPI_Allgatherv( &pnts[0], iso_counts[comm_rank], MPI_DOUBLE,
296  &pnts_g[0], &iso_counts[0], &iso_disps[0],
297  MPI_DOUBLE, _comm);
298  }
299  else
300  pnts_g = pnts;
301 
302  if ( pnts_g.size()>0) {
303  // Build a kd-tree from the points in pnts_g
304  KD_tree_3 ktree;
305  ktree.build( pnts_g);
306 
307  for ( int i=0, s=_panes.size(); i<s; ++i) {
308  std::vector<bool> is_co;
309  determine_coisolated_nodes( *_panes[i], pnts_g, tol, is_co, &ktree);
310  convert_nodelist( is_co, iso_ns[i]);
311  }
312  }
313  }
314 
315  // Merge the lists
316  for ( unsigned int i=0; i<ns.size(); ++i) {
317  std::vector<int> &nsi = ns[i];
318  nsi.insert( ns[i].end(), iso_ns[i].begin(), iso_ns[i].end());
319 
320  // sort and unique the entries in ns[i]
321  std::sort(nsi.begin(), nsi.end());
322  std::vector<int>::iterator new_end=std::unique(nsi.begin(), nsi.end());
323  nsi.erase( new_end, nsi.end());
324  }
325  }
326 
327  // Copy the nodes from ns into nodes and pnts
328  collect_nodes( ns, nodes, pnts, for_facet);
329 
330  return tol;
331 }
332 
333 static void
334 make_kd_tree( const std::vector<int> &nodes,
335  const std::vector<Point_3<Real> > &pnts,
336  std::vector<Point_3<Real> > &bbox,
337  KD_tree_pntref_3 &ktree) {
338  if ( nodes.empty()) return;
339  assert( nodes.size() == pnts.size());
340  std::vector< Point_3_ref> b; b.reserve( pnts.size());
341  bbox.clear();
342 
343  unsigned int count = 0;
344  while (count<nodes.size()) {
345  bbox.push_back( pnts[count]);
346  bbox.push_back( pnts[++count]);
347  for ( int i=0, n = nodes[count++]; i<n; ++i, ++count) {
348  b.push_back( Point_3_ref(pnts[count],count));
349  }
350  }
351  ktree.build( b);
352 }
353 
354 static bool
355 intersect_bbox( const Point_3<Real> &bmin1, const Point_3<Real> &bmax1,
356  const Point_3<Real> &bmin2, const Point_3<Real> &bmax2,
357  Real eps) {
358  // check for emptiness ??
359  if (bmax1.x()+eps < bmin2.x() || bmax2.x()+eps < bmin1.x())
360  return false;
361  if (bmax1.y()+eps < bmin2.y() || bmax2.y()+eps < bmin1.y())
362  return false;
363  if (bmax1.z()+eps < bmin2.z() || bmax2.z()+eps < bmin1.z())
364  return false;
365  return true;
366 }
367 
368 static bool
369 intersect_bbox( const Point_3<Real> &bmin, const Point_3<Real> &bmax,
370  const std::vector<Point_3<Real> > &bbox, Real tol) {
371  for ( int i=0, n=bbox.size(); i<n; i+=2) {
372  if ( intersect_bbox( bmin, bmax, bbox[i], bbox[i+1], tol))
373  return true;
374  }
375  return false;
376 }
377 
378 static void
379 collect_coincident_nodes( const std::vector<int> &r_nodes,
380  const std::vector<Point_3<Real> > &r_pnts,
381  const std::vector<Point_3<Real> > &bbox,
382  KD_tree_pntref_3 &ktree, double tol,
383  std::vector<int> &nodes,
384  std::vector<Point_3<Real> > &pnts) {
385  unsigned int count = 0;
386 
387  while (count<r_nodes.size()) {
388  const Point_3<Real> &xmin=r_pnts[count], &xmax=r_pnts[count+1];
389 
390  if ( !intersect_bbox( xmin, xmax, bbox, tol))
391  { count += 2+r_nodes[count+1]; continue; }
392  int pane = r_nodes[count++];
393 
394  int nn = 0;
395  for ( int i=0, n = r_nodes[count++]; i<n; ++i, ++count) {
396  const Point_3<Real> &p=r_pnts[count];
397  Point_3_ref lb(p.x()-tol, p.y()-tol, p.z()-tol);
398  Point_3_ref ub(p.x()+tol, p.y()+tol, p.z()+tol);
399  KD_tree_pntref_3::Box box( lb, ub, 3);
400 
401  std::vector< Point_3_ref> outList; outList.reserve(4);
402  ktree.search( std::back_inserter( outList), box);
403  if ( !outList.empty()) {
404  if ( nn==0) {
405  nodes.push_back( -pane); // Use negative for remote panes
406  nodes.push_back( 0);
407  pnts.push_back( xmin); pnts.push_back( xmax);
408  }
409  nodes.push_back( r_nodes[count]);
410  pnts.push_back( p);
411  ++nn;
412  }
413  }
414  if ( nn>0) *(nodes.end()-nn-1) = nn;
415  }
416 }
417 
418 
432 double Pane_connectivity::
433 collect_boundary_nodes( std::vector<int> &nodes,
434  std::vector<Point_3> &pnts,
435  bool for_facet) throw(int) {
436 
437  double tol = get_local_boundary_nodes( nodes, pnts, for_facet);
438  if ( _comm == MPI_COMM_NULL) return tol;
439 
440  int comm_size, comm_rank;
441  MPI_Comm_size( _comm, &comm_size);
442  MPI_Comm_rank( _comm, &comm_rank);
443 
444  // Gather the size info
445  int ns=nodes.size(); assert( pnts.size()==nodes.size());
446  std::vector<int> nss( comm_size);
447 
448  MPI_Allgather( &ns, 1, MPI_INT, &nss[0], 1, MPI_INT, _comm);
449 
450  std::vector<MPI_Request> reqs; reqs.reserve( (comm_size-1)*2);
451 
452  std::vector<int> l_nodes = nodes;
453  std::vector<Point_3> l_pnts = pnts;
454  // Now have each processor broadcast their
455  for ( int i=1; i<comm_size; ++i) {
456  const int to_rank = (comm_rank+i)%comm_size;
457  MPI_Request req;
458  MPI_Isend( &l_nodes[0], nodes.size(), MPI_INT, to_rank,
459  101, _comm, &req); reqs.push_back(req);
460  MPI_Isend( &l_pnts[0], 3*pnts.size(), MPI_DOUBLE, to_rank,
461  102, _comm, &req); reqs.push_back(req);
462  }
463 
464  KD_tree_pntref_3 local_rtree;
465  std::vector< Point_3> bbox;
466  std::vector< int> r_nodes, r_nodes_pre = nodes;
467  std::vector< Point_3> r_pnts, r_pnts_pre;
468  int from_rank_pre = comm_rank;
469 
470  for ( int i=comm_size-1; i>=1; --i) {
471  MPI_Request l_reqs[2];
472  MPI_Status l_stats[2];
473 
474  const int from_rank = (comm_rank+i)%comm_size;
475  r_nodes.resize( nss[from_rank]);
476  r_pnts.resize( nss[from_rank]);
477  MPI_Irecv( &r_nodes[0], r_nodes.size(), MPI_INT, from_rank,
478  101, _comm, &l_reqs[0]);
479  MPI_Irecv( &r_pnts[0], 3*r_pnts.size(), MPI_DOUBLE, from_rank,
480  102, _comm, &l_reqs[1]);
481 
482  // Overlap computation with communication.
483  if ( i==comm_size-1) {
484  make_kd_tree( r_nodes_pre, pnts, bbox, local_rtree);
485  }
486  else {
487  collect_coincident_nodes( r_nodes_pre, r_pnts_pre, bbox, local_rtree,
488  tol, nodes, pnts);
489  }
490  MPI_Waitall( 2, l_reqs, l_stats);
491  r_nodes_pre.swap( r_nodes); r_pnts_pre.swap( r_pnts);
492  from_rank_pre = from_rank;
493  }
494 
495  collect_coincident_nodes( r_nodes_pre, r_pnts_pre, bbox,
496  local_rtree, tol, nodes, pnts);
497 
498  std::vector<MPI_Status> stat( reqs.size());
499  if (reqs.size())
500  MPI_Waitall( reqs.size(), &reqs[0], &stat[0]);
501 
502  return tol;
503 }
504 
505 
513 create_b2map( std::vector< std::vector<int> > &b2v,
514  bool for_facet) throw(int) {
515 
516  typedef std::map< int, std::map< int, std::vector<pair_int> > > B2v_map;
517  B2v_map b2v_map;
518 
519  //< This is a mapping for pane_1-->pane_2-->node_1-->node2, where
520  //< <pane_1,node_1> and <pane_2,node_2> are two coincident nodes.
521  //< Furthermore, pane_1 is always <= pane_2; If pane_1<=pane_2, then
522  //< node_1<node_2.
523 
524  try {
525  // Create a mapping in b2v_map
526  std::vector<int> nodes, panes;
527  std::vector<Point_3> pnts;
528 
529  // Obtain the boundary nodes of all panes that are coincident with
530  // the boundary nodes of local panes.
531  double tol = collect_boundary_nodes( nodes, pnts, for_facet);
532 
533  panes.resize( nodes.size());
534  for (unsigned int count=0; count<nodes.size(); count+=nodes[count+1]+2) {
535  std::fill( &panes[count], &panes[count+nodes[count+1]+2], nodes[count]);
536  }
537 
538  std::vector< Point_3> bbox;
539  KD_tree_pntref_3 ktree;
540  make_kd_tree( nodes, pnts, bbox, ktree);
541 
542  std::vector< bool> processed(nodes.size());
543  std::fill_n( processed.begin(), nodes.size(), false);
544 
545  unsigned int count = 0;
546  while (count<nodes.size()) {
547  int paneid = nodes[count++];
548  // If the pane is remote (i.e., paneid<0), we stop processing the
549  // array because the local ones are always before the remote ones.
550  if (paneid<0) break;
551 
552  for ( int i=0, n=nodes[count++]; i<n; ++i, ++count) {
553  if ( processed[count]) continue;
554 
555  const Point_3 &p = pnts[count];
556  Point_3_ref lb(p.x()-tol, p.y()-tol, p.z()-tol);
557  Point_3_ref ub(p.x()+tol, p.y()+tol, p.z()+tol);
558  KD_tree_pntref_3::Box box( lb, ub, 3);
559 
560  std::vector< Point_3_ref> outList; outList.reserve(4);
561  ktree.search( std::back_inserter( outList), box);
562  assert( !outList.empty());
563 
564  std::vector< Node_ID> ids; ids.reserve( outList.size());
565  for ( std::vector< Point_3_ref>::iterator
566  i=outList.begin(); i!=outList.end(); ++i) {
567  int offset=i->offset();
568  processed[ offset] = true;
569  ids.push_back( Node_ID( panes[offset],nodes[offset]));
570  }
571 
572  std::vector< Node_ID >::const_iterator id1=ids.begin();
573  for ( id1=ids.begin(); id1!=ids.end(); ++id1) {
574  std::vector< Node_ID >::const_iterator id2=id1; ++id2;
575 
576  for ( ; id2!=ids.end(); ++id2) {
577  if ( abs(id1->first) < abs(id2->first) ||
578  abs(id1->first) == abs(id2->first) &&
579  id1->second < id2->second)
580  b2v_map[id1->first][id2->first].
581  push_back(pair_int(id1->second, id2->second));
582  else
583  b2v_map[id2->first][id1->first].
584  push_back(pair_int(id2->second, id1->second));
585  }
586  }
587  }
588  }
589  }
590  catch (int ex) {
591  throw ex;
592  }
593 
594  // Now copy from b2v_map into b2v_t
595  std::map<int, std::vector<int> > b2v_t;
596  B2v_map::iterator i, iend;
597  for ( i=b2v_map.begin(), iend=b2v_map.end(); i!=iend; ++i) {
598  // Try to catch branchcut.
599  std::map<int,int> branchcut;
600 
601  B2v_map::mapped_type::iterator j, jend;
602  for ( j=i->second.begin(), jend=i->second.end(); j!=jend; ++j) {
603  // Sort the ids in the group so that the mapping between the local
604  // boundary ids and the node ids is monotonically increasing on process.
605  // with smaller rank. This is useful for correcting correspondence
606  // across processors and is also useful for defining primary node as the
607  // one with the smallest <pane_id,node_id> pair (for Rocface). When they
608  // are ordered incrementally, the primary copy can be detected locally.
609  std::sort( j->second.begin(), j->second.end());
610  if ( i->first == j->first) {
611  COM_assertion( i->first>0);
612 
613  std::vector< int> &b2v_i = b2v_t[i->first];
614  b2v_i.push_back( j->first);
615  b2v_i.push_back( j->second.size()*2);
616 
617  B2v_map::mapped_type::mapped_type::const_iterator k, kend;
618  for ( k=j->second.begin(), kend=j->second.end(); k!=kend; ++k) {
619  b2v_i.push_back( k->first);
620  b2v_i.push_back( k->second);
621  branchcut[k->first] = k->second;
622  }
623  }
624  else {
625  if ( i->first>0) { // First pane is local
626  std::vector< int> &b2v_i = b2v_t[i->first];
627  b2v_i.push_back( std::abs(j->first));
628  b2v_i.push_back( j->second.size());
629 
630  B2v_map::mapped_type::mapped_type::const_iterator k, kend;
631  for ( k=j->second.begin(), kend=j->second.end(); k!=kend; ++k)
632  b2v_i.push_back( k->first);
633  }
634  if ( j->first>0) { // Second pane is local
635  std::vector< int> &b2v_j = b2v_t[j->first];
636  b2v_j.push_back( std::abs(i->first));
637  b2v_j.push_back( j->second.size());
638 
639  B2v_map::mapped_type::mapped_type::const_iterator k, kend;
640  for ( k=j->second.begin(), kend=j->second.end(); k!=kend; ++k)
641  b2v_j.push_back( k->second);
642  }
643  }
644  }
645 
646  if ( !branchcut.empty()) {
647  if ( _win->pane(i->first).is_structured())
648  std::cerr << "\nRocmap Info: Got a branchcut in pane "
649  << i->first << " of window " << _win->name() << std::endl;
650  else {
651  std::cerr << "\nRocmap Warning: Got duplicate nodes within pane "
652  << i->first << " of window " << _win->name() << std::endl;
653  while ( !branchcut.empty()) {
654  std::map<int,int>::iterator it=branchcut.begin();
655 
656  std::cerr << "Rocmap Warning: Duplicate nodes " << it->first
657  << " and " << it->second << std::endl;
658 
659  branchcut.erase(it);
660  }
661  }
662  }
663  }
664 
665  b2v_map.clear();
666 
667  // Copy from b2v_t into b2v
668  b2v.resize(_panes.size());
669  Pane_set::const_iterator it=_panes.begin();
670  for ( int i=0, s=_panes.size(); i<s; ++i, ++it) {
671  b2v[i].swap( b2v_t[(*it)->id()]);
672  }
673 }
674 
676 void Pane_connectivity::create_b2map( COM::Attribute *pconn,
677  bool for_facet) throw(int)
678 {
679  std::vector< std::vector<int> > b2v;
680 
681  create_b2map( b2v, for_facet);
682 
683  // Loop through the panes to get the connectivity map for each pane.
684  for ( int i=0, n=b2v.size(); i!=n; ++i) {
685  COM::Attribute *attr;
686  attr = const_cast<COM::Attribute*>(_panes[i]->attribute( pconn->id()));
687 
688  int size = b2v[i].size() + _pconn_offset;
689  attr->set_size( size);
690 
691  int *addr;
692  // If not yet initialized, allocate memory for it.
693  if ( !attr->initialized())
694  addr = (int*)attr->allocate( 1, size, false);
695  else
696  addr = (int*)attr->pointer();
697 
698  int cap = attr->capacity();
699  int cpanes = 0; // number of communicating panes.
700  int j=0,len=b2v[i].size();
701  for(; j+1<len; j+=2+(b2v[i])[j+1]){
702  // Count all the panes in b2v
703  cpanes ++;
704  }
705  COM_assertion_msg(j==len, "Invalid communication map");
706 
707  // Make sure to output pconn in correct format
708  if (_pconn_offset && cap >= 1){
709  addr[0] = cpanes;
710  std::copy(b2v[i].begin(), b2v[i].begin()+std::min(size-1,cap-1), addr+1);
711  }
712  else if (cap >= 1)
713  std::copy( b2v[i].begin(), b2v[i].begin()+std::min(size,cap),addr);
714  }
715 }
716 
717 void Pane_connectivity::compute_pconn( COM::Attribute *pconn_n,
718  COM::Attribute *pconn_f) throw(int) {
719  if ( pconn_n) create_b2map( pconn_n, false);
720  if ( pconn_f) create_b2map( pconn_f, true);
721 }
722 
723 void Pane_connectivity::size_of_cpanes( const COM::Attribute *pconn,
724  const int *pane_id,
725  int *npanes_total, int *npanes_ghost){
726  const COM::Window *win = pconn->window();
727  const COM::Attribute *pconn_pn;
728  pconn_pn = pconn->window()->pane( *pane_id).attribute( pconn->id());
729 
730  // Obtain the address and sizes of the map
731  const int *tmp_ptr = (const int *)pconn_pn->pointer();
732  const int *ptr_pconn = tmp_ptr ? tmp_ptr+_pconn_offset : tmp_ptr;
733  const int len_real = ptr_pconn ? pconn_pn->size_of_real_items()-_pconn_offset : 0;
734  const int len_total = ptr_pconn ? pconn_pn->size_of_items()-_pconn_offset : 0;
735 
736  COM_assertion_msg( npanes_total,
737  "Invalid NULL pointer for argument npanes_total");
738 
739  *npanes_total = 0;
740  int i=0;
741  for ( ; i+1<len_real; i+=2+ptr_pconn[i+1]) {
742  // Count only the panes existing in the window
743  *npanes_total += win->owner_rank( ptr_pconn[i])>=0;
744  }
745  COM_assertion_msg( i==len_real, "Invalid communication map");
746 
747  for ( ; i+1<len_total; i+=2+ptr_pconn[i+1]) {
748  // Count only the panes existing in the window
749  *npanes_total += win->owner_rank( ptr_pconn[i])>=0;
750  }
751 
752  // Compute the communicating panes that involve ghost nodes
753  if ( npanes_ghost) {
754  *npanes_ghost = 0;
755  for ( i=len_real; i+1<len_total; i+=2+ptr_pconn[i+1])
756  *npanes_ghost += win->owner_rank( ptr_pconn[i])>=0;
757  }
758 
759  COM_assertion_msg( i==len_total, "Invalid communication map");
760 }
761 
762 int Pane_connectivity::pconn_nblocks( const COM::Attribute *pconn) {
763  const COM::Window *win = pconn->window();
764 
765  int nblocks = 0;
766  // Loop through all panes
767  std::vector<const COM::Pane*> panes; win->panes(panes);
768  for ( int p=0, np=panes.size(); p<np; ++p) {
769  const COM::Attribute *pconn_pn = panes[p]->attribute( pconn->id());
770 
771  // Obtain the address and sizes of the map
772  const int *pconn_ptr = (const int *)pconn_pn->pointer();
773 
774  if ( pconn_ptr==NULL) continue;
775 
776  const int len_total = pconn_pn->size_of_items()-_pconn_offset;
777 
778  const int len_ghost = pconn_ptr ? pconn_pn->size_of_ghost_items() : 0;
779  if ( len_ghost == 0) { nblocks = std::max( nblocks, 1); continue; }
780 
781  pconn_ptr += len_total-len_ghost+_pconn_offset;
782 
783  // Skip real nodes
784  int index=1, ncpanes=pconn_ptr[0];
785  for ( int i=1; i<=ncpanes; ++i, index+=pconn_ptr[index+1]+2);
786  // Skip ghost nodes
787  ncpanes=pconn_ptr[index++];
788  for ( int i=1; i<=ncpanes; ++i, index+=pconn_ptr[index+1]+2);
789 
790  nblocks = std::max( nblocks, 2+(index<len_ghost));
791  }
792 
793  // Communicate to get the maximum of nblocks.
794  if ( COMMPI_Initialized()) {
795  int nblocks_local = nblocks;
796  MPI_Allreduce( &nblocks_local, &nblocks, 1, MPI_INT, MPI_MAX,
797  win->get_communicator());
798  }
799 
800  return nblocks;
801 }
802 
804 
805 
807 
808 
809 
810 
811 
812 
std::pair< int, int > Node_ID
#define MAP_END_NAMESPACE
Definition: mapbasic.h:29
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
Utility for constructing pane connectivities in parallel.
void create_b2map(COM::Attribute *pconn, bool for_facet)
Create b2v mapping (pane connectivity) for nodes or edges and store the solution into the given Rocco...
static void convert_nodelist(const std::vector< bool > &bs, std::vector< int > &nodes)
void determine_coisolated_nodes(const COM::Pane &pn, std::vector< Point_3 > &pnts, const double tol, std::vector< bool > &is_co, KD_tree_3 *tree=NULL)
An adaptor for enumerating node IDs of an element.
void collect_nodes(const std::vector< std::vector< int > > &ns, std::vector< int > &nodes, std::vector< Point_3 > &pnts, bool for_facet)
const NT & d
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_MAX
j indices k indices k
Definition: Indexing.h:6
#define COM_assertion_msg(EX, msg)
double s
Definition: blastest.C:80
const Pane_set _panes
Vector_n max(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:354
char lid() const
Local edge ID of the halfedge within its element.
KD_tree::Box box
Definition: Overlay_0d.C:47
void compute_pconn(COM::Attribute *pconn_n, COM::Attribute *pconn_f=NULL)
Create b2v mapping for nodes and facets (edges or faces) correspondence.
here we put it at the!beginning of the common block The point to point and collective!routines know about but MPI_TYPE_STRUCT as yet does not!MPI_STATUS_IGNORE and MPI_STATUSES_IGNORE are similar objects!Until the underlying MPI library implements the C version of these are declared as arrays of MPI_STATUS_SIZE!The types and are OPTIONAL!Their values are zero if they are not available Note that!using these reduces the portability of MPI_IO INTEGER MPI_BOTTOM INTEGER MPI_DOUBLE_PRECISION INTEGER MPI_LOGICAL INTEGER MPI_2REAL INTEGER MPI_2DOUBLE_COMPLEX INTEGER MPI_LB INTEGER MPI_WTIME_IS_GLOBAL INTEGER MPI_GROUP_EMPTY INTEGER MPI_MIN
double Real
Definition: mapbasic.h:322
std::pair< int, int > pair_int
double sqrt(double d)
Definition: double.h:73
real *8 function offset(vNorm, x2, y2, z2)
Definition: PlaneNorm.f90:211
void collect_points(const std::vector< std::vector< int > > &ns, std::vector< Point_3 > &pnts)
int offset() const
int eid() const
Element ID of the halfedge.
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 const int _pconn_offset
*********************************************************************Illinois Open Source License ****University of Illinois NCSA **Open Source License University of Illinois All rights reserved ****Developed free of to any person **obtaining a copy of this software and associated documentation to deal with the Software without including without limitation the rights to ** copy
Definition: roccomf90.h:20
MAP::Point_3< double > Point_3
double collect_boundary_nodes(std::vector< int > &nodes, std::vector< Point_3 > &pnts, bool for_facet)
Collect the boundary nodes of all panes that are coincident with the boundary nodes of local panes...
**********************************************************************Rocstar Simulation Suite Illinois Rocstar LLC All rights reserved ****Illinois Rocstar LLC IL **www illinoisrocstar com **sales illinoisrocstar com WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **Arising OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE **********************************************************************INTERFACE SUBROUTINE knode iend
blockLoc i
Definition: read.cpp:79
Provides a data structure accessing nodes, elements, and edges in a pane, in a manner similar to the ...
const NT & n
const COM::Window *const _win
static void make_kd_tree(const std::vector< int > &nodes, const std::vector< Point_3< Real > > &pnts, std::vector< Point_3< Real > > &bbox, KD_tree_pntref_3 &ktree)
FT x() const
Definition: Point_3.h:129
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
FT y() const
Definition: Point_3.h:132
static void collect_coincident_nodes(const std::vector< int > &r_nodes, const std::vector< Point_3< Real > > &r_pnts, const std::vector< Point_3< Real > > &bbox, KD_tree_pntref_3 &ktree, double tol, std::vector< int > &nodes, std::vector< Point_3< Real > > &pnts)
j indices j
Definition: Indexing.h:6
**********************************************************************Rocstar Simulation Suite Illinois Rocstar LLC All rights reserved ****Illinois Rocstar LLC IL **www illinoisrocstar com **sales illinoisrocstar com WITHOUT WARRANTY OF ANY **EXPRESS OR INCLUDING BUT NOT LIMITED TO THE WARRANTIES **OF FITNESS FOR A PARTICULAR PURPOSE AND **NONINFRINGEMENT IN NO EVENT SHALL THE CONTRIBUTORS OR **COPYRIGHT HOLDERS BE LIABLE FOR ANY DAMAGES OR OTHER WHETHER IN AN ACTION OF TORT OR **Arising OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE **USE OR OTHER DEALINGS WITH THE SOFTWARE **********************************************************************INTERFACE SUBROUTINE knode jend
Pane_connectivity(const COM::Attribute *mesh, MPI_Comm c=MPI_COMM_WORLD)
Constructors.
NT q
double get_local_boundary_nodes(std::vector< int > &nodes, std::vector< Point_3 > &pnts, bool for_facet)
Obtains the IDs and coordinates of boundary nodes of all local panes.
CGAL::Kdtree_d< CGAL::Kdtree_interface< Point_3_ref > > Base
The ID of a facet (edge in 2D and face in 3D) encodes an element ID and the local facet&#39;s ID internal...
NT abs(const NT &x)
Definition: number_utils.h:130
Point_3_ref(const Point_3< Real > &r, int k)
#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.
CGAL::Kdtree_d< CGAL::Kdtree_interface< Point_3< Real > > > Base
int COMMPI_Initialized()
Definition: commpi.h:168
static void size_of_cpanes(const COM::Attribute *pconn, const int *pane_id, int *npanes_total, int *npanes_ghost=NULL)
Get the number of communicating panes.
static int pconn_nblocks(const COM::Attribute *pconn)
Determine the number of pconn blocks for all panes.
Utility for detecting boundaries of a pane.
static bool intersect_bbox(const Point_3< Real > &bmin1, const Point_3< Real > &bmax1, const Point_3< Real > &bmin2, const Point_3< Real > &bmax2, Real eps)
Point_3_ref(Real x, Real y, Real z)
FT z() const
Definition: Point_3.h:135