Rocstar  1.0
Rocstar multiphysics simulation application
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
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: Manifold_2.C,v 1.32 2008/12/06 08:43:23 mtcampbe Exp $
24 
25 #include "Manifold_2.h"
26 #include "Generic_element_2.h"
27 #include "../Rocmap/include/Pane_connectivity.h"
28 #include "../Rocmap/include/Pane_communicator.h"
29 #include "../Rocmap/include/Rocmap.h"
30 #include "../Rocblas/include/Rocblas.h"
31 
32 #include <iterator>
33 #include "Rocsurf.h"
34 #include <algorithm>
35 
37 
38 // TODO: Save face normals so that h.normal() would be more efficient.
39 
45 MPI_Op Window_manifold_2::OP_BAND=MPI_BAND;
48 MPI_Op Window_manifold_2::OP_MAXABS=MPI_MAXLOC;
49 MPI_Op Window_manifold_2::OP_DIFF=MPI_MINLOC;
50 
53 
56  const Pane_manifold_2 *parent)
57  : Simple_manifold_2( p, parent)
58 {
59  if ( parent) {
60  _cnt_pn = parent->_cnt_pn;
61  _bd_cnt = parent->_bd_cnt;
62  _nd_prm = parent->_nd_prm;
63  }
64  else; // Otherwise, they are filled by Window_manifold_2::init()
65 }
66 
68 
69 
71 get_prev_edge( Edge_ID eID, Access_Mode mode) const
72 {
73  Edge_ID prv;
74  switch ( mode) {
75  case REAL_PANE:
76  prv = get_prev_real_edge( eID); break;
77  case WHOLE_PANE:
78  prv = Simple_manifold_2::get_prev_edge( eID); break;
79  case ACROSS_PANE: {
80  // In the across-pane mode, it is illegal to access halfedges that are
81  // not on physical boundaries but on pane boundaries. So a pane-border
82  // halfedge must be a physical border edge.
83  if ( !eID.is_border())
84  { prv = get_prev_real_edge( eID); break; }
85  else { // the edge is on physical boundary.
87  while ( !h.is_border()) h = h.next().opposite();
88  return h;
89  }
90  }
91  default: COM_assertion_msg(false, "Should never reach here");
92  }
93 
94  return Halfedge( this, prv, mode);
95 }
96 
98 get_next_edge( Edge_ID eID, Access_Mode mode) const
99 {
100  Edge_ID nxt;
101  switch ( mode) {
102  case REAL_PANE:
103  nxt = get_next_real_edge( eID); break;
104  case WHOLE_PANE:
105  nxt = Simple_manifold_2::get_next_edge( eID); break;
106  case ACROSS_PANE: {
107  // In the across-pane mode, it is illegal to access halfedges that are
108  // not on physical boundaries but on pane boundaries. So a pane-border
109  // halfedge must be a physical border edge.
110  if ( !is_real_border_edge(eID))
111  { nxt = get_next_real_edge( eID); break; }
112  else { // the edge is on physical boundary.
114  while ( !h.is_border()) h = h.prev().opposite();
115  return h;
116  }
117  }
118  default: COM_assertion_msg(false, "Should never reach here");
119  }
120  return Halfedge( this, nxt, mode);
121 }
122 
124 {
125  switch (mode) {
126  case REAL_PANE: return size_of_real_nodes();
128  case ACROSS_PANE: {
129  int n = size_of_real_nodes();
130  // Loop through border nodes
131  for ( std::vector<Node>::const_iterator
132  it=_nd_prm.begin(), iend=_nd_prm.end(); it != iend; ++it) {
133  if ( it->pane_manifold()) --n;
134  }
135  return n;
136  }
137  default:
138  COM_assertion_msg(false, "Should never reach here");
139  }
140 
141  return 0;
142 }
143 
145 {
146  switch (mode) {
147  case REAL_PANE: return size_of_real_edges();
149  case ACROSS_PANE: {
150  int n = size_of_real_edges();
151 
152  int branch=0;
153  // Loop through border edges
154  for ( std::vector<Halfedge>::const_iterator
155  it=_bd_cnt.begin(), iend=_bd_cnt.end(); it != iend; ++it) {
156  Halfedge hopp = *it;
157  if ( hopp.pane_manifold()) {
158  if (hopp.pane()->id()<_pane->id()) --n;
159  else if (hopp.pane()->id()==_pane->id()) ++branch;
160  }
161  }
162  if ( branch) n-=branch/2;
163  return n;
164  }
165  default:
166  COM_assertion_msg(false, "Should never reach here");
167  }
168  return 0;
169 }
170 
171 void Window_manifold_2::init( const COM::Attribute *pmesh) {
172  COM_assertion_msg( pmesh && pmesh->id()==COM::COM_MESH ||
173  pmesh->id()==COM::COM_PMESH,
174  "Input to Window_manifold_2::init must be mesh or pmesh");
175  if ( _buf_window) delete _buf_window;
176 
177  const COM::Window *w = pmesh->window();
178 
179  // Create a buffer window by inheriting from the given mesh.
180  _buf_window = new COM::Window(w->name()+"-buf", w->get_communicator());
181  _buf_window->inherit( const_cast<COM::Attribute*>(pmesh), "",
182  false, true, NULL, 0);
183 
184  // If pconn is not given, allocate pconn by cloning the pconn from user space
185  COM::Attribute *pconn_user =
186  const_cast<COM::Attribute*>(w->attribute(COM::COM_PCONN));
187  bool nopconn = ( pmesh->id() == COM::COM_MESH ||
188  MAP::Pane_connectivity::pconn_nblocks( pconn_user)==0);
189 
190  // Determine whether to compute pconn by itself.
191  COM::Attribute *pconn_n = nopconn ?
192  _buf_window->inherit( pconn_user, "", true, true, NULL, 0) :
193  _buf_window->attribute( COM::COM_PCONN);
194 
195  // Create an attribute for edge connectivity across panes
196  COM::Attribute *pconn_e =
197  _buf_window->new_attribute( "pconn_e", 'p', COM_INT, 1, "");
198 
199  _buf_window->init_done();
200 
201  std::vector<const COM::Pane*> panes;
202  _buf_window->panes(panes);
203 
204  std::vector<const MAP::Simple_manifold_2*> mani2(panes.size());
205 
206  // Initialize pane-manifolds.
207  _pms.resize( panes.size());
208  for ( int i=panes.size()-1; i>=0; --i) {
209  _pi_map[ panes[i]->id()] = i; // Internal local pane-ID
210 
211  _pms[i].init( panes[i]);
212  mani2[i] = &_pms[i];
213 
214  // _bd_cnt and _phy_bnd will be updated by determine_counterparts
215  int nb = _pms[i].size_of_real_border_edges();
216  _pms[i]._cnt_pn.resize( nb, 0);
217  _pms[i]._bd_cnt.resize( nb, Halfedge(NULL, Edge_ID(),ACROSS_PANE));
218 
219  // _nd_prm to be updated by determine_primaries
220  _pms[i]._nd_prm.resize( nb+_pms[i].size_of_isolated_nodes(),
221  Node(NULL,0,ACROSS_PANE));
222  }
223 
224  // Compute node and edge correspondence if not given
225  if ( !mani2.empty()) {
226  MAP::Pane_connectivity pc( &mani2[0], w->get_communicator());
227  pc.compute_pconn( nopconn?pconn_n:(COM::Attribute*)NULL, pconn_e);
228 
229  determine_counterparts( pconn_e); // Update _cnt_pn and _bd_cnt
230  determine_primaries( pconn_n); // Update _nd_prm
231  }
232  else {
233  MAP::Pane_connectivity pc( pmesh, w->get_communicator());
234  pc.compute_pconn( nopconn?pconn_n:(COM::Attribute*)NULL, pconn_e);
235  }
236 
237  // Obtain the number of pconn blocks
238  _pconn_nb = MAP::Pane_connectivity::pconn_nblocks( pconn_n);
239 }
240 
241 void Window_manifold_2::determine_counterparts(const COM::Attribute *pconn_e) {
242 
243  const int pconn_offset=MAP::Pane_connectivity::pconn_offset();
244 
245  typedef std::map< std::pair<int,int>,
246  std::pair< const int*, const int*> > B2e_map;
247  B2e_map bm;
248 
249  // First, loop through the pane-connectivity arrays in all local panes
250  // to construct a mapping from the internal local pane ids (between 0 and
251  // #local_panes-1) of each pair of abutting local panes to the addresses
252  // in the pane-connectivity arrays corresponding to the communication
253  // patterns of the two panes. This mapping is stored in B2e_map, and
254  // will allow convenient construction of the counterparts in the second step.
255  // Note: As a side-product, this step also fills in _cnt_pn for the edges.
256  for ( int i=0, n=_pms.size(); i<n; ++i) {
257  Pane_manifold_2 &pm = _pms[i];
258  const COM::Attribute *pconn_l = pm.pane()->attribute(pconn_e->id());
259  const int *b2e_l = (const int*)pconn_l->pointer();
260 
261  int pane_id_l = i;
262 
263  for ( int j=pconn_offset, nj=pconn_l->size_of_real_items();
264  j<nj; j+=b2e_l[j+1]+2) {
265 
266  std::map<int,int>::iterator it= _pi_map.find( b2e_l[j]);
267  bool is_remote = it == _pi_map.end();
268 
269  // Loop through the edges in the pconn to assign _cnt_pn.
270  int pnid_other = b2e_l[j];
271  if ( is_remote) pnid_other = -pnid_other;
272 
273  const Edge_ID *es = (const Edge_ID*)(&b2e_l[j+2]);
274  for ( int k=0, nk=b2e_l[j+1]; k<nk; ++k) {
276  = pnid_other;
277  // Note: this handles branch-cut as well.
278  }
279 
280  if ( is_remote) continue; // skip remote panes
281 
282  // Insert addresses of the pconn arrayes into B2e_map
283  int pane_id_r = it->second;
284 
285  if ( pane_id_l <= pane_id_r)
286  bm[ std::make_pair( pane_id_l, pane_id_r)].first = &b2e_l[j+1];
287  if ( pane_id_l >= pane_id_r)
288  bm[ std::make_pair( pane_id_r, pane_id_l)].second = &b2e_l[j+1];
289  }
290  }
291 
292  // Second, loop through the B2e_map to insert *local* counterparts of
293  // border-edges into _bd_cnt (i.e., if the counterpart of an edge is
294  // on a remote process, the counterpart is ignored).
295  for ( B2e_map::const_iterator it=bm.begin(); it!=bm.end(); ++it) {
296  Pane_manifold_2 *p1 = &_pms[it->first.first];
297  Pane_manifold_2 *p2 = &_pms[it->first.second];
298  const int *v1 = it->second.first;
299  const int *v2 = it->second.second;
300 
301  int is_branchcut = (it->first.first == it->first.second);
302  COM_assertion_msg( ! is_branchcut || *v1%2==0,
303  "Branch-cut must list nodes in pairs.");
304 
305  for ( int k=1, nk=*v1; k<=nk; ++k) {
306  const Edge_ID e1 = (Edge_ID&)v1[k];
307  const Edge_ID e2 = (Edge_ID&)v2[k+is_branchcut];
308 
309  p1->_bd_cnt[p1->get_border_edgeID(p1->get_opposite_real_edge(e1))-1] =
310  Halfedge(p2, e2, ACROSS_PANE);
311 
312  p2->_bd_cnt[p2->get_border_edgeID(p2->get_opposite_real_edge(e2))-1] =
313  Halfedge(p1, e1, ACROSS_PANE);
314 
315  if (is_branchcut) ++k;
316  }
317  }
318 }
319 
320 void Window_manifold_2::determine_primaries( const COM::Attribute *pconn_n) {
321  // Using the pane connectivity to construct a helper map bm, which
322  // maps from the pane IDs of each pair of incident panes to its
323  // correponding arrays in b2v.
324  // Note in each pane-ID pair, the first ID is no greater than the second.
325  typedef std::map< std::pair<int,int>,
326  std::pair< const int*, const int*> > B2v_map;
327  B2v_map bm;
328 
329  const int pconn_offset=MAP::Pane_connectivity::pconn_offset();
330 
331  for ( int i=0, n=_pms.size(); i<n; ++i) {
332  const COM::Attribute *pconn_l = _pms[i].pane()->attribute(pconn_n->id());
333  const int *b2v_l = (const int*)pconn_l->pointer();
334  int pane_id_l = i;
335 
336  for ( int j=pconn_offset, nj=pconn_l->size_of_real_items();
337  j<nj; j+=b2v_l[j+1]+2) {
338 
339  std::map<int,int>::iterator it= _pi_map.find( b2v_l[j]);
340  if ( it == _pi_map.end()) continue; // skip remote panes
341 
342  int pane_id_r = it->second;
343 
344  if ( pane_id_l <= pane_id_r)
345  bm[ std::make_pair( pane_id_l, pane_id_r)].first = &b2v_l[j+1];
346  if ( pane_id_l >= pane_id_r)
347  bm[ std::make_pair( pane_id_r, pane_id_l)].second = &b2v_l[j+1];
348  }
349  }
350 
351  // Now loop through bm to compute _nd_prm within the process.
352  for ( B2v_map::const_iterator it=bm.begin(); it!=bm.end(); ++it) {
353  Pane_manifold_2 *p1 = &_pms[it->first.first];
354  Pane_manifold_2 *p2 = &_pms[it->first.second];
355  const int *v1 = it->second.first, *v2=it->second.second;
356 
357  int is_branchcut = (it->first.first == it->first.second);
358  COM_assertion_msg( ! is_branchcut || *v1%2==0,
359  "Branch-cut must list nodes in pairs.");
360 
361  for ( int k=1, nk=*v1; k<=nk; ++k) {
362  Node node1( p1, v1[k], ACROSS_PANE);
363  Node node2( p2, v2[k+is_branchcut], ACROSS_PANE);
364 
365  int i1 = p1->get_bnode_index( v1[k]);
366  if ( i1>=0 && !node2.is_isolated() &&
367  ( node2.halfedge().is_border() ||
368  node1.is_isolated() && p1->_nd_prm[i1].pane()==0 )) {
369  p1->_nd_prm[i1] = node2;
370  }
371  else {
372  int i2 = p2->get_bnode_index( v2[k+is_branchcut]);
373  if ( i2 >= 0 && !node1.is_isolated() &&
374  (node1.halfedge().is_border() || p2->_nd_prm[i2].pane()==0)) {
375  p2->_nd_prm[i2] = node1;
376  }
377  }
378 
379  if (is_branchcut) ++k;
380  }
381  }
382 }
383 
385  if (_cc) delete _cc; _cc=NULL;
386  if ( _buf_window) delete _buf_window;
387 }
388 
390  if ( _cc) { delete _cc; }
391 
392  _cc = new MAP::Pane_communicator( _buf_window,
393  _buf_window->get_communicator());
394 }
395 
398 shortest_edge_length( COM::Attribute *lens) {
399  COM_assertion_msg( lens && (lens->is_nodal() || lens->is_elemental()),
400  "Argument must be nodal or elemental attribute");
401  COM_assertion_msg( lens->size_of_components()== 1 &&
402  COM_compatible_types(lens->data_type(), COM_DOUBLE),
403  "Argument must be double-precision scalars");
404 
405  if ( lens->is_nodal()) {
407  }
408  else {
410  }
411 }
412 
415 compute_shortest_edgelen_nodes( COM::Attribute *lens) {
416  std::vector< COM:: Pane*> panes;
417  lens->window()-> panes( panes);
418  std::vector< COM::Pane*>::const_iterator it = panes.begin();
419 
420  // Initialize to HUGE_VAL
421  double inf=HUGE_VAL;
422  Rocblas::copy_scalar( &inf, lens);
423 
424  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
425  const COM::Pane &pane = **it;
426  const Point_3<Real> *pnts =
427  reinterpret_cast<const Point_3<Real>*>(pane.coordinates());
428  Real *lp = (Real *)(pane.attribute( lens->id())->pointer());
429 
430  // Loop through elements of the pane
431  Element_node_enumerator ene( &pane, 1);
432  for ( int j=pane.size_of_elements(); j>0; --j, ene.next()) {
433  int nn=ene.size_of_nodes();
434  int uindex = ene[0]-1;
435  for (int k = 0, ne=ene.size_of_edges(); k<ne; k++){
436  int vindex=ene[(k+1)%ne]-1;
437  double sqlen = (pnts[ uindex]-pnts[ vindex]).squared_norm();
438 
439  lp[uindex] = std::min( lp[uindex], sqlen);
440  lp[vindex] = std::min( lp[vindex], sqlen);
441  if ( nn>ne) lp[uindex+ne] = std::min( lp[uindex+ne], sqlen);
442  if ( nn>ne+ne) lp[uindex+ne+ne] = std::min( lp[uindex+ne+ne], sqlen);
443 
444  uindex = vindex;
445  }
446  }
447  }
448 
449  // Reduce on shared nodes and then compute squared roots.
451  Rocblas::sqrt( lens, lens);
452 }
453 
454 
457 compute_shortest_edgelen_elements( COM::Attribute *lens) {
458  std::vector< COM:: Pane*> panes;
459  lens->window()-> panes( panes);
460  std::vector< COM::Pane*>::const_iterator it = panes.begin();
461 
462  for (int i=0, local_npanes = panes.size(); i<local_npanes; ++i, ++it){
463  const COM::Pane &pane = **it;
464  const Point_3<Real> *pnts =
465  reinterpret_cast<const Point_3<Real>*>(pane.coordinates());
466  Real *lp = (Real *)(pane.attribute( lens->id())->pointer());
467 
468  // Loop through elements of the pane
469  Element_node_enumerator ene( &pane, 1);
470  for ( int j=pane.size_of_elements(); j>0; --j, ene.next(),++lp) {
471  Real sqlen = HUGE_VAL;
472 
473  int uindex = ene[0]-1;
474  for (int k = 0, ne=ene.size_of_edges(); k<ne; k++){
475  int vindex=ene[(k+1)%ne]-1;
476  sqlen = std::min( sqlen, (pnts[ uindex]-pnts[ vindex]).squared_norm());
477  uindex = vindex;
478  }
479  *lp = std::sqrt(sqlen);
480  }
481  }
482 }
483 
485 update_bd_normals( const COM::Attribute *normals,
486  bool to_normalize) {
487  const COM::Attribute *normals_inherited = normals;
488  COM_assertion( normals->size_of_components()== 3 &&
489  COM_compatible_types(normals->data_type(), COM_DOUBLE));
490 
491  // Allocate buffer arrays
492  if ( normals->window()!=_buf_window)
493  normals_inherited = _buf_window->inherit
494  ( const_cast< COM::Attribute *>(normals), "facenormals__CNNTEMP",
495  false, true, NULL, 0);
496  COM::Attribute *nrm=_buf_window->new_attribute( "normals__PMTEMP",
497  'p', COM_DOUBLE, 3, "");
498  COM::Attribute *pconn_g=_buf_window->new_attribute( "pconn__PMTEMP",
499  'p', COM_INT, 1, "");
500  COM::Attribute *pconn_e=_buf_window->attribute( "pconn_e");
501 
502 
503  // Fill in normals and pconn
504  for ( PM_iterator it=pm_begin(), iend=pm_end(); it != iend; ++it) {
505  COM::Pane *pn = const_cast<COM::Pane*>(it->pane());
506  const Vector_3<Real> *nrms_face = reinterpret_cast<Vector_3<Real> *>
507  (pn->attribute( normals_inherited->id())->pointer());
508 
509  COM::Attribute *nrm_pn = pn->attribute( nrm->id());
510  int n = it->size_of_real_border_edges();
511  nrm_pn->set_size( n, 0);
512  it->_bd_nrms.resize( n);
513 
514  Vector_3<Real> *nrms_bd = &it->_bd_nrms[0];
515  _buf_window->set_array( nrm->name(), pn->id(), nrms_bd);
516 
517  for ( int i=0; i<n; ++i) {
518  Edge_ID eid=it->get_opposite_real_edge(Edge_ID(i+1, Edge_ID::BndID));
519 
520  nrms_bd[i] = nrms_face[eid.eid()-1];
521  if ( to_normalize) nrms_bd[i].normalize();
522  }
523 
524  // Construct pane-connectivity
525  it->convert_pconn_edge2ghost( pn->attribute( pconn_e->id()),
526  pn->attribute( pconn_g->id()));
527  }
528  _buf_window->init_done(false);
529 
530  // Perform communication
531  MAP::Rocmap::update_ghosts( nrm, pconn_g);
532 
533  _buf_window->delete_attribute( pconn_g->name());
534  _buf_window->delete_attribute( nrm->name());
535  if ( normals_inherited != normals)
536  _buf_window->delete_attribute( normals_inherited->name());
537  _buf_window->init_done(false);
538 }
539 
541 update_bd_flags( const COM::Attribute *flags) {
542  const COM::Attribute *flags_inherited = flags;
543  COM_assertion( flags->size_of_components()== 1 &&
544  COM_compatible_types(flags->data_type(), COM_INT));
545 
546  // Allocate buffer arrays
547  if ( flags->window()!=_buf_window)
548  flags_inherited = _buf_window->inherit
549  ( const_cast< COM::Attribute *>(flags), "faceflags__CNNTEMP",
550  false, true, NULL, 0);
551  COM::Attribute *flg=_buf_window->new_attribute( "flags__PMTEMP",
552  'p', COM_INT, 1, "");
553  COM::Attribute *pconn_g=_buf_window->new_attribute( "pconn__PMTEMP",
554  'p', COM_INT, 1, "");
555  COM::Attribute *pconn_e=_buf_window->attribute( "pconn_e");
556 
557  // Fill in flags and pconn
558  for ( PM_iterator it=pm_begin(), iend=pm_end(); it != iend; ++it) {
559  COM::Pane *pn = const_cast<COM::Pane*>(it->pane());
560  const int *flgs_face = reinterpret_cast<int *>
561  (pn->attribute( flags_inherited->id())->pointer());
562 
563  COM::Attribute *flg_pn = pn->attribute( flg->id());
564  int n = it->size_of_real_border_edges();
565  flg_pn->set_size( n, 0);
566  it->_bd_flgs.resize( n);
567 
568  int *flgs_bd = &it->_bd_flgs[0];
569  _buf_window->set_array( flg->name(), pn->id(), flgs_bd);
570 
571  for ( int i=0; i<n; ++i) {
572  Edge_ID eid=it->get_opposite_real_edge(Edge_ID(i+1, Edge_ID::BndID));
573 
574  flgs_bd[i] = flgs_face[eid.eid()-1];
575  }
576 
577  // Construct pane-connectivity
578  it->convert_pconn_edge2ghost( pn->attribute( pconn_e->id()),
579  pn->attribute( pconn_g->id()));
580  }
581  _buf_window->init_done(false);
582 
583  // Perform communication
584  MAP::Rocmap::update_ghosts( flg, pconn_g);
585 
586  _buf_window->delete_attribute( pconn_g->name());
587  _buf_window->delete_attribute( flg->name());
588  if ( flags_inherited != flags)
589  _buf_window->delete_attribute( flags_inherited->name());
590  _buf_window->init_done(false);
591 }
592 
594 update_bdedge_bitmap( const COM::Attribute *bitmap) {
595  const COM::Attribute *bm_inherited = bitmap;
596  COM_assertion( bm_inherited->size_of_components()== 1 &&
597  COM_compatible_types(bm_inherited->data_type(), COM_CHAR));
598 
599  // Allocate buffer arrays
600  if ( bm_inherited->window()!=_buf_window)
601  bm_inherited = _buf_window->inherit
602  ( const_cast< COM::Attribute *>(bitmap), "facebm__CNNTEMP",
603  false, true, NULL, 0);
604  COM::Attribute *bm=_buf_window->new_attribute( "bm__PMTEMP",
605  'p', COM_CHAR, 1, "");
606  COM::Attribute *pconn_g=_buf_window->new_attribute( "pconn__PMTEMP",
607  'p', COM_INT, 1, "");
608  COM::Attribute *pconn_e=_buf_window->attribute( "pconn_e");
609 
610  // Fill in bm and pconn
611  for ( PM_iterator it=pm_begin(), iend=pm_end(); it != iend; ++it) {
612  COM::Pane *pn = const_cast<COM::Pane*>(it->pane());
613  const char *bms_face = reinterpret_cast<char *>
614  (pn->attribute( bm_inherited->id())->pointer());
615 
616  COM::Attribute *bm_pn = pn->attribute( bm->id());
617  int n = it->size_of_real_border_edges();
618  bm_pn->set_size( n, 0);
619  it->_bd_bm.resize( n);
620 
621  char *bms_bd = &it->_bd_bm[0];
622  _buf_window->set_array( bm->name(), pn->id(), bms_bd);
623 
624  for ( int i=0; i<n; ++i) {
625  Edge_ID eid=it->get_opposite_real_edge(Edge_ID(i+1, Edge_ID::BndID));
626 
627  bms_bd[i] = bms_face[eid.eid()-1] & (1<<eid.lid());
628  }
629 
630  // Construct pane-connectivity
631  it->convert_pconn_edge2ghost( pn->attribute( pconn_e->id()),
632  pn->attribute( pconn_g->id()));
633  }
634  _buf_window->init_done(false);
635 
636  // Perform communication
637  MAP::Rocmap::update_ghosts( bm, pconn_g);
638 
639  _buf_window->delete_attribute( pconn_g->name());
640  _buf_window->delete_attribute( bm->name());
641  if ( bm_inherited != bitmap)
642  _buf_window->delete_attribute( bm_inherited->name());
643  _buf_window->init_done(false);
644 }
645 
647 accumulate_bd_values( const COM::Attribute *vals) {
648  COM_assertion( vals->size_of_components()==1);
649  const COM::Attribute *vals_inherited = vals;
650  // Allocate buffer arrays
651  if ( vals->window()!=_buf_window)
652  vals_inherited = _buf_window->inherit
653  ( const_cast< COM::Attribute *>(vals), "vals__CNNTEMP", false, true, NULL, 0);
654  COM::Attribute *buf=_buf_window->new_attribute( "buf__PMTEMP", 'p',
655  vals->data_type(), 1, "");
656  COM::Attribute *pconn_g=_buf_window->new_attribute( "pconn__PMTEMP",
657  'p', COM_INT, 1, "");
658  COM::Attribute *pconn_e=_buf_window->attribute( "pconn_e");
659 
660  int size_base_type = COM_get_sizeof( vals->data_type(),1);
661 
662  // Fill in vals and pconn
663  for ( PM_iterator it=pm_begin(), iend=pm_end(); it != iend; ++it) {
664  COM::Pane *pn = const_cast<COM::Pane*>(it->pane());
665  const char *vals_face = reinterpret_cast<char *>
666  (pn->attribute( vals_inherited->id())->pointer());
667 
668  COM::Attribute *buf_pn = pn->attribute( buf->id());
669  int n = it->size_of_real_border_edges();
670  buf_pn->set_size( n, 0);
671 
672  char *val_bd;
673  _buf_window->resize_array( buf->name(), pn->id(), (void**)&val_bd);
674 
675  for ( int i=0; i<n; ++i) {
676  Edge_ID eid=it->get_opposite_real_edge(Edge_ID(i+1, Edge_ID::BndID));
677  int fid = eid.eid();
678 
679  std::copy( &vals_face[(fid-1)*size_base_type],
680  &vals_face[fid*size_base_type], &val_bd[i*size_base_type]);
681  }
682 
683  // Construct pane-connectivity
684  it->convert_pconn_edge2ghost( pn->attribute( pconn_e->id()),
685  pn->attribute( pconn_g->id()));
686  }
687  _buf_window->init_done(false);
688 
689  // Perform communication
690  MAP::Rocmap::update_ghosts( buf, pconn_g);
691 
692  // Reduce on the values.
693  for ( PM_iterator it=pm_begin(), iend=pm_end(); it != iend; ++it) {
694  COM::Pane *pn = const_cast<COM::Pane*>(it->pane());
695  char *vals_face = reinterpret_cast<char *>
696  (pn->attribute( vals_inherited->id())->pointer());
697 
698  int n = it->size_of_real_border_edges();
699 
700  COM::Window::Pointer_descriptor ptr(NULL);
701  _buf_window->get_array( buf->name(), pn->id(), ptr);
702  char *val_bd = (char*)ptr.ptr;
703 
704  for ( int i=0; i<n; ++i) {
705  Edge_ID eid=it->get_opposite_real_edge(Edge_ID(i+1, Edge_ID::BndID));
706 
707  switch (vals->data_type()) {
708  case COM_CHAR: vals_face[eid.eid()-1] += val_bd[i]; break;
709  case COM_INT:
710  case COM_INTEGER:
711  (int&)vals_face[(eid.eid()-1)*size_base_type] +=
712  (int&)val_bd[i*size_base_type]; break;
713  case COM_FLOAT:
714  case COM_REAL:
715  (float&)vals_face[(eid.eid()-1)*size_base_type] +=
716  (float&)val_bd[i*size_base_type]; break;
717  case COM_DOUBLE:
718  case COM_DOUBLE_PRECISION:
719  (double&)vals_face[(eid.eid()-1)*size_base_type] +=
720  (double&)val_bd[i*size_base_type]; break;
721  default:
722  COM_assertion_msg( false, "Unsupported type for reduction"); break;
723  }
724  }
725  }
726 
727  _buf_window->delete_attribute( pconn_g->name());
728  _buf_window->delete_attribute( buf->name());
729  if ( vals_inherited != vals)
730  _buf_window->delete_attribute( vals_inherited->name());
731  _buf_window->init_done(false);
732 }
733 
735 convert_pconn_edge2ghost( const COM::Attribute *pconn_e,
736  COM::Attribute *pconn_g) {
737  const int *b2e_l = (const int*)pconn_e->pointer();
738 
739  int n=pconn_e->size_of_items();
740  pconn_g->set_size( n+n+1, n+n);
741  int *buf = (int*)pconn_g->allocate( 1, n+n+1, true);
742 
743  buf[0] = 0; // Shared-node part is empty
744  buf[1] = b2e_l[ 0]; // Number of communicating panes
745 
746  // Extracting the edge-ID part.
747  for ( int j=1; j<n; j+=b2e_l[j+1]+2) {
748  buf[j+1] = b2e_l[j]; // Pane ID
749  buf[j+2] = b2e_l[j+1]; // Number of items
750 
751  const Edge_ID *es = (const Edge_ID*)(&b2e_l[j+2]);
752  for ( int k=0, nk=b2e_l[j+1]; k<nk; ++k) {
753  buf[j+k+3] = get_opposite_real_edge(es[k]).eid();
754  COM_assertion( buf[j+k+3]>=1 && buf[j+k+3]<=size_of_real_border_edges());
755  }
756  }
757 
758  // Copy the sending part into the receiving part.
759  std::copy( &buf[1], &buf[n+1], &buf[n+1]);
760 }
761 
762 // Evaluate nodal normals
764 compute_nodal_normals( COM::Attribute *nrms,
765  int scheme,
766  bool to_normalize,
767  const COM::Attribute *weights) {
768  COM_assertion_msg( weights==NULL || weights->is_elemental(),
769  "Weights for elemental normals must be elemental");
770  if ( _cc==NULL) init_communicator();
771 
772  // Inherit normals onto the window
773  COM::Attribute *nodal_normals;
774  if ( nrms->window() != _buf_window)
775  nodal_normals = _buf_window->inherit( nrms, "nodal_normals__CNNTEMP",
776  false, true, NULL, 0);
777  else
778  nodal_normals = nrms;
779 
780  COM::Attribute *elem_normals = _buf_window->
781  new_attribute( "elem_normals__CNNTEMP", 'e', COM_DOUBLE, 3, "");
782  _buf_window->resize_array( elem_normals, NULL);
783  _buf_window->init_done();
784 
785  if ( scheme == E2N_AREA) {
786  int normalize=false;
787  Rocsurf::compute_element_normals( elem_normals, &normalize);
788  elements_to_nodes( elem_normals, nodal_normals, E2N_ONE, NULL, NULL, true);
789  }
790  else {
791  Rocsurf::compute_element_normals( elem_normals);
792  elements_to_nodes( elem_normals, nodal_normals, scheme, weights);
793  }
794 
795  // Normalize the vectors
796  if ( to_normalize) {
797  std::vector<COM::Pane*>::iterator it=_cc->panes().begin();
798  for (int i=0, n=_cc->panes().size(); i<n; ++i, ++it) {
799  int nnodes = (*it)->size_of_real_nodes();
800  Vector_3<double>* ptrs =
801  (Vector_3<double>*)(*it)->attribute(nodal_normals->id())->pointer();
802  for ( int j=0; j<nnodes; ++j)
803  ptrs[j].normalize();
804  }
805  }
806 
807  // Deallocate buffer in reverse order
808  _buf_window->delete_attribute( elem_normals->name());
809  if ( nrms->window() != _buf_window)
810  _buf_window->delete_attribute( nodal_normals->name());
811  _buf_window->init_done( false);
812 }
813 
814 // Convert elemental values to nodal values.
816 elements_to_nodes( const COM::Attribute *e_vals,
817  COM::Attribute *n_vals,
818  const int scheme,
819  const COM::Attribute *e_weights,
820  COM::Attribute *n_weights,
821  const int tosum) {
822  COM_assertion_msg( e_vals && e_vals->is_elemental(),
823  "First argument must be elemental attribute");
824  COM_assertion_msg( n_vals && n_vals->is_nodal(),
825  "Second argument must be nodal attribute");
826  COM_assertion_msg( scheme!=E2N_USER ||
827  e_weights && e_weights->is_elemental(),
828  "Third argument must be elemental attribute");
829  COM_assertion_msg( !n_weights || n_weights->is_nodal() &&
830  COM_compatible_types(COM_DOUBLE, n_weights->data_type()),
831  "Output weights must be nodal with double precision");
832 
833  // Inherit nodal and elemental values onto the window
834  COM::Attribute *nodal_vals;
835  if ( n_vals->window() != _buf_window)
836  nodal_vals = _buf_window->inherit( n_vals, "nodal_vals__E2NTEMP",
837  false, true, NULL, 0);
838  else
839  nodal_vals = n_vals;
840 
841  const COM::Attribute *elem_vals;
842  if ( e_vals->window() != _buf_window)
843  elem_vals = _buf_window->inherit
844  ( const_cast<COM::Attribute*>(e_vals), "elem_vals__E2NTEMP",
845  false, true, NULL, 0);
846  else
847  elem_vals = e_vals;
848 
849  // Inherit nodal and elemental weights onto the window
850  COM::Attribute *nodal_weights;
851  if ( n_weights && n_weights->window()!=_buf_window)
852  nodal_weights = _buf_window->inherit( n_weights, "nodal_weights__E2NTEMP",
853  false, true, NULL, 0);
854  else {
855  nodal_weights = _buf_window->new_attribute( "nodal_weights__E2NTEMP", 'n',
856  COM_DOUBLE, 1, "");
857  _buf_window->resize_array( nodal_weights, NULL);
858  }
859 
860  const COM::Attribute *elem_weights;
861  if ( e_weights && e_weights->window()!=_buf_window)
862  elem_weights = _buf_window->inherit
863  ( const_cast<COM::Attribute*>(e_weights), "elem_weights__E2NTEMP",
864  false, true, NULL, 0);
865  else
866  elem_weights = e_weights;
867  _buf_window->init_done( false);
868 
869  // Initialize communicator
870  if ( _cc==NULL) init_communicator();
871  int local_npanes = _cc->panes().size();
872 
873  // Initialize buffer spaces for nodal weights.
874  std::vector< Real*> weights_ptrs(local_npanes);
875  std::vector< int> weights_strds(local_npanes);
876 
877  int ncomp = nodal_vals->size_of_components();
878  COM_assertion_msg( elem_vals->size_of_components()==ncomp,
879  "Numbers of components must match");
880 
881  for (int i=0; i<local_npanes; ++i) {
882  int nn=_cc->panes()[i]->size_of_real_nodes();
883  Real *p;
884  int strd;
885  COM::Attribute *a = _cc->panes()[i]->attribute(nodal_weights->id());
886  p = weights_ptrs[i] = reinterpret_cast<Real*>(a->pointer());
887  strd = weights_strds[i] = a->stride();
888 
889  // Initialize values to 0.
890  for ( int k=0; k<nn; ++k, p+=strd) *p = 0.;
891  }
892 
893  Vector_3<Real> J[2];
894  Vector_2<Real> nc(0.5,0.5);
895 
897  Element_vectors_k_const<Real> elem_vals_evk;
898  Element_node_vectors_k<Real> nodal_vals_evk;
899  Element_vectors_k_const<Real> elem_weights_evk;
900  Element_node_vectors_k<Real> nodal_weights_evk;
901 
902  // Compute nodal sums and weights on each processor
903  std::vector< COM::Pane*>::const_iterator it=_cc->panes().begin();
904  for (int i=0; i<local_npanes; ++i, ++it) { // Loop through the panes
905  COM::Pane &pane = **it;
906 
907  const Point_3<Real> *pnts = reinterpret_cast<const Point_3<Real>*>
908  (pane.coordinates());
909  const COM::Attribute *elem_vals_pane =
910  pane.attribute( elem_vals->id());
911  const COM::Attribute *elem_weights_pane =
912  elem_weights ? pane.attribute( elem_weights->id()) : NULL;
913  COM::Attribute *nodal_vals_pane =
914  pane.attribute( nodal_vals->id());
915 
916  // Initialize values of nodal_vals_pane to 0.
917  for ( int d=1; d<=ncomp; ++d) {
918  COM::Attribute *nvpi = ncomp==1?nodal_vals_pane:(nodal_vals_pane+d);
919  Real *p=reinterpret_cast<Real*>(nvpi->pointer());
920  for ( int j=0,s=nvpi->stride(),n=nvpi->size_of_real_items()*s; j<n; j+=s)
921  p[j] = 0.;
922  }
923 
924  // Loop through the elements of the pane
925  Element_node_enumerator ene( &pane, 1);
926  for ( int j=pane.size_of_real_elements(); j>0; --j, ene.next()) {
927  ps.set( pnts, ene, 1);
928  elem_vals_evk.set( elem_vals_pane, ene);
929  nodal_vals_evk.set( nodal_vals_pane, ene);
930  nodal_weights_evk.set( weights_ptrs[i], ene, weights_strds[i]);
931 
932  int ne=ene.size_of_edges();
933  int nn=ene.size_of_nodes();
934  Real w = 1.;
935  switch ( scheme) {
936  case E2N_USER:
937  case E2N_AREA:
938  if ( scheme == E2N_USER) {
939  // Use user specified weights.
940  elem_weights_evk.set( elem_weights_pane, ene);
941  w = elem_weights_evk[0];
942  } // Continue to the case of E2N_ONE
943  else {
944  Generic_element_2 e(ne, nn);
945  e.Jacobian( ps, nc, J);
946 
947  const Vector_3<Real> v = Vector_3<Real>::cross_product( J[0], J[1]);
948  w = std::sqrt(v.squared_norm());
949  if ( ne==3) w*=0.5;
950  } // Continue to the case of E2N_ONE
951  case E2N_ONE: {
952  // Update nodal weights
953  for ( int k=0; k<nn; ++k)
954  nodal_weights_evk[k] += w;
955 
956  // Update nodal sums
957  for ( int d=0; d<ncomp; ++d) {
958  Real t = w*elem_vals_evk(0,d);
959  for ( int k=0; k<nn; ++k)
960  nodal_vals_evk(k,d) += t;
961  }
962  break;
963  }
964  case E2N_ANGLE:
965  case E2N_SPHERE: {
966  for ( int k=0; k<ne; ++k) {
967  J[0] = ps[k==ne-1?0:k+1]-ps[k]; J[1] = ps[k?k-1:ne-1]-ps[k];
968  double s = std::sqrt((J[0]*J[0])*(J[1]*J[1]));
969  if ( s>0) {
970  double cosw = J[0]*J[1]/s;
971  if (cosw>1) cosw=1; else if ( cosw<-1) cosw=-1;
972  w = std::acos( cosw);
973 
974  if ( scheme==SURF::E2N_SPHERE)
975  w = std::sin(w)/s;
976 
977  // Update nodal weights
978  nodal_weights_evk[k] += w;
979 
980  // Update nodal sums
981  for ( int d=0; d<ncomp; ++d)
982  nodal_vals_evk(k,d) += w*elem_vals_evk(0,d);
983  }
984  }
985  for ( int k=ne; k<nn; ++k) {
986  // Update nodal weights
987  nodal_weights_evk[k] += 1;
988 
989  // Update nodal sums
990  for ( int d=0; d<ncomp; ++d)
991  nodal_vals_evk(k,d) += elem_vals_evk(0,d);
992  }
993  break;
994  }
995 
996  default: COM_assertion_msg(false, "Should never reach here");
997  }
998  }
999  }
1000 
1001  // Performan reductions on shared nodes for nodal sums
1002  reduce_on_shared_nodes( nodal_vals, OP_SUM);
1003 
1004  // Performan reductions on shared nodes for nodal weights
1005  _cc->init( &(void*&)weights_ptrs[0], COM_DOUBLE, 1, NULL, NULL);
1006  _cc->begin_update_shared_nodes();
1007  _cc->reduce_on_shared_nodes( MPI_SUM);
1008  _cc->end_update_shared_nodes();
1009 
1010  if ( !tosum) {
1011  // Divide nodal sums by weights on each processor
1012  it=_cc->panes().begin();
1013  for (int i=0; i<local_npanes; ++i, ++it) { // Loop through the panes
1014  COM::Pane &pane = **it;
1015  COM::Attribute *nodal_vals_pane = pane.attribute( nodal_vals->id());
1016 
1017  for ( int d=1; d<=ncomp; ++d) {
1018  COM::Attribute *nvpi = ncomp==1?nodal_vals_pane:(nodal_vals_pane+d);
1019  Real *v=reinterpret_cast<Real*>(nvpi->pointer());
1020  Real *w = weights_ptrs[i];
1021  for ( int j=0,js=nvpi->stride(),n=nvpi->size_of_real_items()*js,
1022  k=0, ks=weights_strds[i]; j<n; j+=js, k+=ks) {
1023  if ( w[k]==0) {
1024  std::cout << "***Rocsurf Error: Got zero weight for node "
1025  << j+1 << " in pane " << pane.id() << std::endl;
1026  }
1027  if ( w[k] == 0) v[j] = 0;
1028  else v[j] /= w[k];
1029  }
1030  }
1031  }
1032  }
1033 
1034  // Delete the temporary attributs in reverse order.
1035  if ( elem_weights != e_weights)
1036  _buf_window->delete_attribute( elem_weights->name());
1037  _buf_window->delete_attribute( nodal_weights->name());
1038  if ( elem_vals != e_vals)
1039  _buf_window->delete_attribute( elem_vals->name());
1040  if (nodal_vals != n_vals)
1041  _buf_window->delete_attribute( nodal_vals->name());
1042  _buf_window->init_done( false);
1043 }
1044 
1045 void Window_manifold_2::compute_normals( COM::Attribute *normal,
1046  int scheme,
1047  bool to_normalize) {
1048  COM_assertion_msg( normal, "Encountered NULL pointer/");
1049  COM_assertion_msg( normal->size_of_components()==3,
1050  "Normal must have three components");
1051  COM_assertion_msg( COM_compatible_types(normal->data_type(), COM_DOUBLE),
1052  "Base type of Normal must be double precision");
1053 
1054  if ( normal->is_nodal()) {
1055  compute_nodal_normals( normal, scheme, to_normalize);
1056  }
1057  else {
1058  COM_assertion_msg( normal->is_elemental(),
1059  "Normal must be nodal or elemental");
1060  int to_nrm = to_normalize;
1061  Rocsurf::compute_element_normals( normal, &to_nrm);
1062  }
1063 }
1064 
1065 void Window_manifold_2::perturb_mesh( double range) {
1066  // Allocate buffer arrays
1067  COM::Attribute *nrm=_buf_window->new_attribute( "normals__PMTEMP",
1068  'n', COM_DOUBLE, 3, "");
1069  _buf_window->resize_array( nrm, NULL);
1070 
1071  COM::Attribute *rnd=_buf_window->new_attribute( "randoms__PMTEMP",
1072  'n', COM_DOUBLE, 1, "");
1073  _buf_window->resize_array( rnd, NULL);
1074 
1075  COM::Attribute *lens=_buf_window->new_attribute( "lengths__PMTEMP",
1076  'n', COM_DOUBLE, 1, "");
1077  _buf_window->resize_array( lens, NULL);
1078 
1079  _buf_window->init_done( false);
1080 
1081  // Obtain random numbers between -range and +range
1082  double dbl_range=range*2;
1083  Rocblas::rand_scalar( &dbl_range, rnd);
1084  Rocblas::sub_scalar( rnd, &range, rnd);
1086 
1087  // Compute normal direction and multiply it with random numbers
1088  compute_nodal_normals( nrm);
1090  Rocblas::mul( rnd, lens, rnd);
1091  Rocblas::mul( nrm, rnd, nrm);
1092 
1093  // Add normal components to coordinates
1094  COM::Attribute *nc = _buf_window->attribute(COM::COM_NC);
1095  Rocblas::add( nc, nrm, nc);
1096 
1097  // Deallocate buffers
1098  _buf_window->delete_attribute( lens->name());
1099  _buf_window->delete_attribute( rnd->name());
1100  _buf_window->delete_attribute( nrm->name());
1101  _buf_window->init_done( false);
1102 }
1103 
1105 reduce_on_shared_nodes( COM::Attribute *attr, MPI_Op op) {
1106  COM_assertion( attr->is_nodal());
1107 
1108  COM::Attribute *attr_inherited = attr;
1109  if ( attr->window() != _buf_window) {
1110  // If attribute is not on buffer-window, inherit it.
1111  attr_inherited = _buf_window->inherit(attr, "SuRf_ReDuCe_On_ShArEd_TeMp__",
1112  COM::Pane::INHERIT_USE, true, NULL, 0);
1113  _buf_window->init_done( false);
1114  }
1115  _cc->init( attr_inherited);
1116  _cc->begin_update_shared_nodes();
1117  if ( op == OP_MAXABS)
1118  _cc->reduce_maxabs_on_shared_nodes();
1119  else if ( op == OP_DIFF)
1120  _cc->reduce_diff_on_shared_nodes();
1121  else
1122  _cc->reduce_on_shared_nodes( op);
1123  _cc->end_update_shared_nodes();
1124 
1125  if ( attr_inherited != attr) {
1126  _buf_window->delete_attribute( attr_inherited->name());
1127  _buf_window->init_done( false);
1128  }
1129 }
1130 
1131 int
1133  int n = 0;
1134  // Loop through panes
1136  for ( ; it != iend; ++it) {
1137  n += it->size_of_nodes( mode);
1138  }
1139  return n;
1140 }
1141 
1142 int
1144  int n = 0;
1145  // Loop through panes
1147  for ( ; it != iend; ++it) {
1148  n += it->size_of_faces( mode);
1149  }
1150 
1151  return n;
1152 }
1153 
1154 int
1156  int n = 0;
1157  // Loop through panes
1159  for ( ; it != iend; ++it) {
1160  n += it->size_of_triangles( mode);
1161  }
1162 
1163  return n;
1164 }
1165 
1166 int
1168  int n = 0;
1169  // Loop through panes
1171  for ( ; it != iend; ++it) {
1172  n += it->size_of_quadrilaterals( mode);
1173  }
1174 
1175  return n;
1176 }
1177 
1178 int
1180  int n = 0;
1181  // Loop through panes
1183  for ( ; it != iend; ++it) {
1184  n += it->size_of_edges( mode);
1185  }
1186 
1187  return n;
1188 }
1189 
1191 const void *Node::addr( const COM::Attribute *a) const {
1192  COM_assertion_msg( a, "Unexpected NULL pointer");
1193  COM_assertion_msg( a->is_nodal(), "Expect a nodal attribute");
1194 
1195  const COM::Attribute *attr;
1196 
1197  const COM::Pane *pn = _pm->pane();
1198  int pid = pn->id();
1199  if ( a->pane()->id() == pid)
1200  attr = a;
1201  else {
1202  if ( a->window() != pn->window()) {
1203  pn = &a->window()->pane( pid);
1204  COM_assertion_msg( pn, "Pane does not exist");
1205  }
1206  attr=pn->attribute( a->id());
1207  COM_assertion_msg( attr, "Attribute does not exist");
1208  }
1209 
1210  return ((const char*)attr->pointer()) +
1211  COM_get_sizeof( attr->data_type(), attr->stride()*(_vID-1));
1212 }
1213 
1215 const void *Halfedge::addr( const COM::Attribute *a) const {
1216  COM_assertion( !is_border());
1217  COM_assertion_msg( a, "Unexpected NULL pointer");
1218  COM_assertion_msg( a->is_elemental(), "Expect a element-centered attribute");
1219 
1220  const COM::Attribute *attr;
1221 
1222  const COM::Pane *pn = _pm->pane();
1223  int pid = pn->id();
1224  if ( a->pane()->id() == pid)
1225  attr = a;
1226  else {
1227  if ( a->window() != pn->window()) {
1228  pn = &a->window()->pane( pid);
1229  COM_assertion_msg( pn, "Pane does not exist");
1230  }
1231  attr=pn->attribute( a->id());
1232  COM_assertion_msg( attr, "Attribute does not exist");
1233  }
1234 
1235  return ((const char*)attr->pointer()) +
1236  COM_get_sizeof( attr->data_type(), attr->stride()*(_eID.eid()-1));
1237 }
1238 
1240 get_normal( const Halfedge &h, const Vector_2<Real> &nc) {
1241  if ( h.is_border()) {
1242  // Precondition: boundary normal must have been updated.
1243  return h.pane_manifold()->get_bd_normal( h.id());
1244  }
1245 
1246  Element_node_enumerator ene( h.pane(), h.id().eid());
1247  const int ne = ene.size_of_edges();
1248  Generic_element_2 e(ne);
1249 
1250  // First evaluate face normal
1252  ps.set((const Point_3<Real>*)(h.pane()->coordinates()), ene,1);
1253 
1254  Vector_3<Real> J[2];
1255  e.Jacobian( ps, nc, J);
1256  return Vector_3<Real>::cross_product( J[0], J[1]);
1257 }
1258 
1260  return get_normal( *this, Vector_2<Real>( 0.5, 0.5));
1261 }
1262 
1264  const Vector_2<Real> &nc,
1265  const COM::Attribute *disp)
1266 {
1267  COM_assertion_msg( disp, "Unexpected NULL pointer");
1268  COM_assertion_msg( disp->is_nodal(), "disp must be nodal attribute");
1269 
1270  // Obtain the deformed coordinates
1271  Point_3<Real> points[4];
1272 
1273  int ne = 0;
1274  Halfedge hit = h;
1275  do {
1276  Node v=hit.origin();
1277  points[ne] = v.point() + *(Vector_3<Real>*)v.addr( disp);
1278  ++ne;
1279  COM_assertion( ne<=4);
1280  } while ( (hit=hit.next()) != h);
1281 
1282  // Evaluate the Jacobian and the cross product
1283  Vector_3<Real> J[2];
1284  Generic_element_2(ne).Jacobian( points, nc, J);
1285 
1286  return Vector_3<Real>::cross_product( J[0], J[1]);
1287 }
1288 
1290 deformed_normal( const COM::Attribute *disp) const {
1291  return get_deformed_normal( *this, Vector_2<Real>( 0.5, 0.5), disp);
1292 }
1293 
1298  const double pi=3.14159265358979;
1299  if ( is_physical_border()) return pi;
1300 
1301  Halfedge hopp = opposite();
1302  if ( hopp.is_physical_border()) return pi;
1303 
1304  Vector_3<Real> normals[2] = { normal(), hopp.normal() };
1305 
1306  double cos_a = normals[0]*normals[1]
1307  / std::sqrt( (normals[0]*normals[0])*(normals[1]*normals[1]));
1308 
1309  // Resolve roundoff error
1310  if ( cos_a>1) cos_a=1;
1311  if ( cos_a<-1) cos_a=-1;
1312 
1313  return std::acos( cos_a);
1314 }
1315 
1316 // Assign global ids for all nodes
1318 assign_global_nodeIDs( std::vector<std::vector<int> > &gids) const {
1319  // Initialize the vector gids
1320  gids.clear(); gids.resize( size_of_panes());
1321  std::map<int, std::vector<int>*> maps;
1323  for ( int i=0; it!=iend; ++it, ++i) {
1324  gids[i].resize( it->size_of_real_nodes(), 0);
1325  maps[it->pane()->id()] = &gids[i];
1326  }
1327 
1328  Access_Mode mode = ACROSS_PANE;
1329  // Loop through the panes to assign primary nodes
1330  int gid = 0;
1331  it=pm_begin();
1332  for ( int i=0; it!=iend; ++it, ++i) {
1333  for (int v=0, nv=it->size_of_real_nodes(); v<nv; ++v) {
1334  if ( it->is_primary( v+1, mode))
1335  gids[i][v] = ++gid;
1336  }
1337  }
1338  COM_assertion( gid == size_of_nodes( mode));
1339 
1340  // Loop through the panes to assign other nodes
1341  it=pm_begin();
1342  for ( int i=0; it!=iend; ++it, ++i) {
1343  for (int v=0, nv=it->size_of_real_nodes(); v<nv; ++v) {
1344  if (gids[i][v]==0) {
1345  // Obtain the primary.
1346  Node nd = it->get_primary(v+1, mode);
1347  gids[i][v] = (*maps[nd.pane()->id()])[nd.id()-1];
1348  }
1349  }
1350  }
1351 }
1352 
1353 void Window_manifold_2::serialize_window( COM::Window *outwin) const {
1354  // Clearn up the output window
1355  outwin->delete_pane(0);
1356 
1357  // Build a renumbering of nodes
1358  std::vector<std::vector<int> > nodes_gids;
1359  assign_global_nodeIDs( nodes_gids);
1360 
1361  Access_Mode mode = ACROSS_PANE;
1362  // Create a pane
1363  int nnodes=size_of_nodes( mode);
1364  outwin->set_size( "nc", 1, nnodes);
1365 
1366  double *coors;
1367  outwin->resize_array( "nc",1,(void**)&coors);
1368 
1369  // Mesh vertices
1370  int gid=0;
1371  // Loop through the panes to write the nodes
1373  for ( ; it!=iend; ++it) {
1374  const COM::Pane &pn = *it->pane();
1375  const double *p = pn.coordinates();
1376 
1377  for ( int i=0, nn=pn.size_of_real_nodes(); i<nn; ++i) {
1378  if ( it->is_primary( i+1, mode)) {
1379  std::copy( &p[3*i], &p[3*i+3], &coors[3*gid]);
1380  ++gid;
1381  }
1382  }
1383  }
1384  COM_assertion( gid==nnodes);
1385 
1386  // Mesh triangles.
1387  int *tris;
1388  outwin->set_size( ":t3:", 1, size_of_faces(REAL_PANE));
1389  outwin->resize_array( ":t3:", 1, (void**)&tris);
1390 
1391  int i=0, k=0;
1392  for ( it=pm_begin(); it!=iend; ++it, ++i) {
1393  int fn=it->size_of_faces(REAL_PANE); if ( fn==0) continue;
1394 
1395  Element_node_enumerator ene( it->pane(), 1);
1396 
1397  for ( int f=0; f<fn; ++f, ++k, ene.next()) {
1398  for ( int j=0; j<3; ++j) {
1399  tris[3*k+j] = nodes_gids[i][ene[j]-1];
1400  }
1401  }
1402  }
1403 
1404  outwin->init_done();
1405 }
1406 
1407 
1409 
1410 
1411 
1412 
1413 
1414 
int size_of_panes() const
Obtain the number of panes.
Definition: Manifold_2.h:220
static MPI_Op OP_LAND
Definition: Manifold_2.h:353
static MPI_Op OP_MAXABS
Definition: Manifold_2.h:353
void update_bd_normals(const COM::Attribute *normals, bool to_normalize=false)
Update the normals for border faces.
Definition: Manifold_2.C:485
static MPI_Op OP_SUM
Definition: Manifold_2.h:353
#define COM_assertion(EX)
Error checking utility similar to the assert macro of the C language.
Pane_manifold_2()
Default constructors.
Definition: Manifold_2.C:52
PM_iterator pm_begin()
Obtain an iterator to the first pane manifold of the window.
Definition: Manifold_2.h:223
An adaptor for enumerating node IDs of an element.
int size_of_edges() const
Number of edges of the pane.
bool is_real_border_edge(const Edge_ID &eID) const
Determine whether a given edge is a border edge of real part of the pane (either on physical border o...
This class encapsulate a node over a window manifold.
Definition: Manifold_2.h:370
int size_of_faces(Access_Mode mode) const
Obtain the number of faces.
Definition: Manifold_2.C:1143
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
int size_of_triangles(Access_Mode mode) const
Obtain the number of triangles.
Definition: Manifold_2.C:1155
MAP::Pane_communicator * _cc
Definition: Manifold_2.h:364
j indices k indices k
Definition: Indexing.h:6
COM::Window * _buf_window
Definition: Manifold_2.h:360
Vector_3< Real > deformed_normal(const COM::Attribute *disp) const
Get the normal of the deformed shape (coordinates plus given displacements) of the incident facet of ...
Definition: Manifold_2.C:1290
static MPI_Op OP_DIFF
Definition: Manifold_2.h:353
#define COM_assertion_msg(EX, msg)
std::vector< int > _cnt_pn
Definition: Manifold_2.h:169
double s
Definition: blastest.C:80
void elements_to_nodes(const COM::Attribute *evals, COM::Attribute *nvals, const int scheme=E2N_ONE, const COM::Attribute *ews=NULL, COM::Attribute *nws=NULL, const int tosum=false)
Convert element values to nodal values using weighted averaging.
Definition: Manifold_2.C:816
#define SURF_END_NAMESPACE
Definition: surfbasic.h:29
const COM::Pane * pane() const
Obtain a const pointer to the pane.
MAP::Facet_ID Edge_ID
Definition: Manifold_2.h:49
int id() const
Obtain the node ID within its Pane_manifold_2.
Definition: Manifold_2.h:391
void convert_pconn_edge2ghost(const COM::Attribute *pconn_e, COM::Attribute *pconn_g)
Convert from edge-based pconn to a ghost-node-style pconn for a pane attribute.
Definition: Manifold_2.C:735
NT p1
Halfedge get_prev_edge(Edge_ID, Access_Mode mode) const
Obtain the previous edge in a given access mode.
Definition: Manifold_2.C:71
Halfedge opposite() const
Get the ID of the opposite edge of a given edge.
Definition: Manifold_2.h:454
Halfedge get_next_edge(Edge_ID, Access_Mode mode) const
Obtain the next edge in a given access mode.
Definition: Manifold_2.C:98
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
bool is_physical_border() const
Is the edge on the physical boundary?
Definition: Manifold_2.h:480
Encapsulation of the element-wise computations for two-dimensional elements.
Halfedge prev() const
Get the previous halfedge of its owner element.
Definition: Manifold_2.h:460
int size_of_real_nodes() const
Number of real nodes of the pane.
This class encapsulate a halfedge over a window manifold.
Definition: Manifold_2.h:446
Definition: points.h:30
Edge_ID id() const
Obtain the ID of the edge.
Definition: Manifold_2.h:547
C/C++ Data types.
Definition: roccom_basic.h:129
double Real
Definition: mapbasic.h:322
Access_Mode
Definition: Manifold_2.h:52
std::vector< Pane_manifold_2 >::const_iterator PM_const_iterator
Definition: Manifold_2.h:188
int size_of_edges(Access_Mode mode) const
Obtain the number of edges.
Definition: Manifold_2.C:1179
void init(const COM::Attribute *pmesh)
Initialize the manifold by inheriting the given mesh.
Definition: Manifold_2.C:171
Halfedge next() const
Get the next halfedge of its owner element.
Definition: Manifold_2.h:465
const void * addr(const COM::Attribute *attr) const
Obtain the address of an attribute associated with its bounded element.
Definition: Manifold_2.C:1215
double sqrt(double d)
Definition: double.h:73
Vector_3 & normalize()
Definition: mapbasic.h:114
int _vID
Definition: Manifold_2.h:441
int get_border_edgeID(Edge_ID eID) const
Get the border edge index. Return -1 if not a border edge.
void set(Value *p, Element_node_enumerator &ene, int strd)
int eid() const
Element ID of the halfedge.
static MPI_Op OP_BAND
Definition: Manifold_2.h:353
const COM::Attribute * attr(const COM::Attribute *a) const
Obtain the attribute on the parent pane of the node.
Definition: Manifold_2.h:404
std::map< int, int > _pi_map
Definition: Manifold_2.h:363
Node get_primary() const
Get the primary copy of the node.
Definition: Manifold_2.h:419
~Pane_manifold_2()
Destructor.
Definition: Manifold_2.C:67
Edge_ID get_opposite_real_edge(const Edge_ID &eID) const
Get the ID of the opposite real edge of a given real or border edge.
Edge_ID _eID
Definition: Manifold_2.h:577
*********************************************************************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 and or **sell copies of the and to permit persons to whom the **Software is furnished to do subject to the following this list of conditions and the following disclaimers ****Redistributions in binary form must reproduce the above **copyright this list of conditions and the following **disclaimers in the documentation and or other materials **provided with the distribution ****Neither the names of the Center for Simulation of Advanced the University of nor the names of its **contributors may be used to endorse or promote products derived **from this Software without specific prior written permission ****THE SOFTWARE IS PROVIDED AS 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 v
Definition: roccomf90.h:20
std::vector< Pane_manifold_2 >::iterator PM_iterator
Definition: Manifold_2.h:187
Vector_3< Real > get_normal(const Halfedge &h, const Vector_2< Real > &nc)
Get the face normal of a point in the element incident on h.
Definition: Manifold_2.C:1240
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_BAND INTEGER MPI_BOR
static const int scheme
#define SURF_BEGIN_NAMESPACE
Definition: surfbasic.h:28
Vector_3< Real > normal() const
Get the normal of the incident facet.
Definition: Manifold_2.C:1259
This is a helper class for accessing nodal data.
*********************************************************************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
bool is_isolated() const
Is the node isolated?
Definition: Manifold_2.h:413
static void add(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for addition.
Definition: op3args.C:221
void reduce_on_shared_nodes(COM::Attribute *attr, MPI_Op op)
Perform reduction over a given nodal attributes.
Definition: Manifold_2.C:1105
static void compute_shortest_edgelen_elements(COM::Attribute *lens)
Obtain shortest edge length of incident edges of each element.
Definition: Manifold_2.C:457
const Pane_manifold_2 * _pm
Definition: Manifold_2.h:440
**********************************************************************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
int size_of_quadrilaterals(Access_Mode mode) const
Obtain the number of quadrilaterals.
Definition: Manifold_2.C:1167
void determine_primaries(const COM::Attribute *pconn_n)
Determine the primary nodes for across-pane access.
Definition: Manifold_2.C:320
void assign_global_nodeIDs(std::vector< std::vector< int > > &gids) const
Definition: Manifold_2.C:1318
void update_bdedge_bitmap(const COM::Attribute *bitmap)
Update bitmap for border edges.
Definition: Manifold_2.C:594
NT & sin
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_LAND
static MPI_Op OP_MIN
Definition: Manifold_2.h:353
int size_of_edges() const
Number of edges per element.
int COM_compatible_types(COM_Type type1, COM_Type type2)
Definition: roccom_c++.h:563
void set(const Value *p, Element_node_enumerator &ene, int strd)
initialize the accessor with a pointer and a specific stride.
blockLoc i
Definition: read.cpp:79
void accumulate_bd_values(const COM::Attribute *vals)
Accumulate the values for border faces.
Definition: Manifold_2.C:647
Vector_3< Real > get_deformed_normal(const Halfedge &h, const Vector_2< Real > &nc, const COM::Attribute *disp)
Get the normal of the deformed shape (coordinates plus given displacements) of the incident facet of ...
Definition: Manifold_2.C:1263
void update_bd_flags(const COM::Attribute *flags)
Update the flags for border faces.
Definition: Manifold_2.C:541
void shortest_edge_length(COM::Attribute *lens)
Obtain shortest edge length of incident edges of each node or element.
Definition: Manifold_2.C:398
This is a helper class for accessing elemental data.
int size_of_nodes() const
Number of nodes per element.
Type squared_norm() const
Definition: mapbasic.h:110
Provides a data structure accessing nodes, elements, and edges in a pane, in a manner similar to the ...
const NT & n
const COM::Attribute * attr(const COM::Attribute *a) const
Obtain the attribute on the parent pane of the node.
Definition: Manifold_2.h:556
static Vector_3 cross_product(const Vector_3 &v, const Vector_3 &w)
Definition: mapbasic.h:104
int COM_get_sizeof(const COM_Type type, int c)
Definition: roccom_c++.h:560
Edge_ID get_next_real_edge(const Edge_ID &eID) const
Get the ID of the next real edge of the element or along the boundary.
std::vector< Node > _nd_prm
Definition: Manifold_2.h:179
static MPI_Op OP_BOR
Definition: Manifold_2.h:353
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_BAND INTEGER MPI_LOR
const void * addr(const COM::Attribute *attr) const
Obtain the address of an attribute associated with the node.
Definition: Manifold_2.C:1191
Edge_ID get_prev_edge(const Edge_ID &eID) const
Get the ID of the previous edge of the element or along the boundary.
Vector_n min(const Array_n_const &v1, const Array_n_const &v2)
Definition: Vector_n.h:346
static void compute_element_normals(COM::Attribute *nrm, const int *to_normalize=NULL, const COM::Attribute *pnts=NULL)
Computes elemental normals of a given window.
void determine_counterparts(const COM::Attribute *pconn_e)
Determine the counterparts of pane-border edges for across-pane access.
Definition: Manifold_2.C:241
bool is_border() const
Is the edge a border edge?
Definition: Manifold_2.h:476
void int int * nk
Definition: read.cpp:74
static void copy_scalar(const void *x, Attribute *y)
Operation wrapper for copy (x is a scalar pointer).
Definition: op2args.C:583
const COM::Pane * _pane
j indices j
Definition: Indexing.h:6
int size_of_nodes() const
Number of nodes of the pane.
friend class Halfedge
Definition: Manifold_2.h:60
const double pi
void compute_normals(COM::Attribute *normals, int scheme=E2N_ANGLE, bool to_normalize=true)
Compute the normals at nodes or faces, depending on the type of the attribute normals.
Definition: Manifold_2.C:1045
Halfedge get_opposite_edge(Edge_ID, Access_Mode mode) const
Obtain the opposite edge in a given access mode.
Definition: Manifold_2.h:607
void init_communicator()
Initialize a pane communicator.
Definition: Manifold_2.C:389
void serialize_window(COM::Window *outwin) const
Create a serial window (with single pane) from the current window.
Definition: Manifold_2.C:1353
std::vector< Halfedge > _bd_cnt
Definition: Manifold_2.h:175
static void rand_scalar(const void *a, Attribute *z)
Generate a random number between 0 and $a$ for each entry in z.
Definition: op2args.C:604
const Point_3< Real > & point() const
Obtain the coordinates of a node.
Definition: Manifold_2.h:394
const Pane_manifold_2 * pane_manifold() const
Obtain the pane manifold that owns the edge.
Definition: Manifold_2.h:540
void set(const Value *p, Element_node_enumerator &ene, int strd)
initialize the accessor with a pointer and a specific stride.
int size_of_real_edges() const
Number of real edges of the pane.
The ID of a facet (edge in 2D and face in 3D) encodes an element ID and the local facet&#39;s ID internal...
const COM::Pane * pane() const
Obtain the owner Pane_manifold_2 of the node.
Definition: Manifold_2.h:387
int size_of_real_border_edges() const
Number of border edges of the real part of the pane.
void Jacobian(const Field &f, const Nat_coor &nc, Vector_3 J[2]) const
Evaluates the Jacobian at a given point.
CImg< _cimg_Tfloat > acos(const CImg< T > &instance)
Definition: CImg.h:6051
void next()
Go to the next element within the connectivity tables of a pane.
double dihedral_angle() const
Return the dihedral angle at the edge.
Definition: Manifold_2.C:1297
void int * nj
Definition: read.cpp:74
Edge_ID get_prev_real_edge(const Edge_ID &eID) const
Get the ID of the previous real edge of the element or along the boundary.
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_PROD
for(;;)
This class implements a data structure for 2-manifold on each pane.
Definition: Manifold_2.h:57
static MPI_Op OP_MAX
Definition: Manifold_2.h:353
PM_iterator pm_end()
Obtain an iterator to the past-the-last pane manifold of the window.
Definition: Manifold_2.h:227
Node origin() const
Obtain the (primary copy of the) origin of the edge.
Definition: Manifold_2.h:468
static void sqrt(const Attribute *x, Attribute *y)
Wrapper for sqrt (y=sqrt(x)).
Definition: op2args.C:507
const Vector_3< Real > & get_bd_normal(Edge_ID) const
Obtain normal of incident face of border edge.
Definition: Manifold_2.h:587
const Pane_manifold_2 * _pm
Definition: Manifold_2.h:576
static MPI_Op OP_PROD
Definition: Manifold_2.h:353
void compute_nodal_normals(COM::Attribute *nrm, int scheme=E2N_ANGLE, bool to_normalize=true, const COM::Attribute *weights=NULL)
Compute nodal normals using one of the following weighting schemes: E2N_ONE, E2N_AREA, and E2N_ANGLE, and E2N_USER.
Definition: Manifold_2.C:764
void compute_shortest_edgelen_nodes(COM::Attribute *lens)
Obtain shortest edge length of incident edges of each nodes.
Definition: Manifold_2.C:415
std::vector< Pane_manifold_2 > _pms
Definition: Manifold_2.h:361
bool is_border() const
Determines whether the facet is on border.
static MPI_Op OP_LOR
Definition: Manifold_2.h:353
int size_of_nodes(Access_Mode mode) const
Obtain the number of nodes (shared nodes are counted only once.
Definition: Manifold_2.C:1132
int get_bnode_index(int vID) const
Obtain the border node index (equal to ID of incident border edge).
Definition: Manifold_2.h:157
Edge_ID get_next_edge(const Edge_ID &eID) const
Get the ID of the next edge of the element or along the boundary.
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_SUM
Halfedge halfedge() const
Get an incident halfedge originated from the node.
Definition: Manifold_2.h:670
void perturb_mesh(double range)
Perturb the given mesh along its normal direction by length equal to a random number between -range a...
Definition: Manifold_2.C:1065
const COM::Pane * pane() const
Obtain the owner Pane_manifold_2 of the node.
Definition: Manifold_2.h:543
static void mul(const Attribute *x, const Attribute *y, Attribute *z)
Operation wrapper for multiplication.
Definition: op3args.C:253
static void sub_scalar(const Attribute *x, const void *y, Attribute *z, int swap=0)
Operation wrapper for subtraction with y as a scalar pointer.
Definition: op3args.C:331