Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Intx2Mesh.cpp
Go to the documentation of this file.
1 /* 2  * Intx2Mesh.cpp 3  * 4  * Created on: Oct 2, 2012 5  */ 6  7 #include <limits> 8 #include <queue> 9 #include <sstream> 10 // 11 #include "moab/IntxMesh/Intx2Mesh.hpp" 12 #ifdef MOAB_HAVE_MPI 13 #include "moab/ParallelComm.hpp" 14 #include "MBParallelConventions.h" 15 #include "moab/ParallelMergeMesh.hpp" 16 #endif /* MOAB_HAVE_MPI */ 17 #include "MBTagConventions.hpp" 18 #include "moab/GeomUtil.hpp" 19 #include "moab/AdaptiveKDTree.hpp" 20  21 namespace moab 22 { 23  24 #ifdef ENABLE_DEBUG 25 int Intx2Mesh::dbg_1 = 0; 26 #endif 27  28 Intx2Mesh::Intx2Mesh( Interface* mbimpl ) 29  : mb( mbimpl ), mbs1( 0 ), mbs2( 0 ), outSet( 0 ), gid( 0 ), TgtFlagTag( 0 ), tgtParentTag( 0 ), srcParentTag( 0 ), 30  countTag( 0 ), srcNeighTag( 0 ), tgtNeighTag( 0 ), neighTgtEdgeTag( 0 ), orgSendProcTag( 0 ), imaskTag( 0 ), 31  tgtConn( NULL ), srcConn( NULL ), epsilon_1( 0.0 ), epsilon_area( 0.0 ), box_error( 0.0 ), localRoot( 0 ), 32  my_rank( 0 ) 33 #ifdef MOAB_HAVE_MPI 34  , 35  parcomm( NULL ), remote_cells( NULL ), remote_cells_with_tracers( NULL ) 36 #endif 37  , 38  max_edges_1( 0 ), max_edges_2( 0 ), counting( 0 ) 39 { 40  gid = mbimpl->globalId_tag(); 41 } 42  43 Intx2Mesh::~Intx2Mesh() 44 { 45  // TODO Auto-generated destructor stub 46 #ifdef MOAB_HAVE_MPI 47  if( remote_cells ) 48  { 49  delete remote_cells; 50  remote_cells = NULL; 51  } 52 #endif 53 } 54  55 ErrorCode Intx2Mesh::FindMaxEdgesInSet( EntityHandle eset, int& max_edges ) 56 { 57  Range cells; 58  ErrorCode rval = mb->get_entities_by_dimension( eset, 2, cells );MB_CHK_ERR( rval ); 59  60  max_edges = 0; // can be 0 for point clouds 61  for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ ) 62  { 63  EntityHandle cell = *cit; 64  const EntityHandle* conn4; 65  int nnodes = 3; 66  rval = mb->get_connectivity( cell, conn4, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity of a cell" ); 67  if( nnodes > max_edges ) max_edges = nnodes; 68  } 69  // if in parallel, communicate the actual max_edges; it is not needed for tgt mesh (to be 70  // global) but it is better to be consistent 71 #ifdef MOAB_HAVE_MPI 72  if( parcomm ) 73  { 74  int local_max_edges = max_edges; 75  // now reduce max_edges over all processors 76  int mpi_err = 77  MPI_Allreduce( &local_max_edges, &max_edges, 1, MPI_INT, MPI_MAX, parcomm->proc_config().proc_comm() ); 78  if( MPI_SUCCESS != mpi_err ) return MB_FAILURE; 79  } 80 #endif 81  82  return MB_SUCCESS; 83 } 84  85 ErrorCode Intx2Mesh::FindMaxEdges( EntityHandle set1, EntityHandle set2 ) 86 { 87  ErrorCode rval = FindMaxEdgesInSet( set1, max_edges_1 );MB_CHK_SET_ERR( rval, "can't determine max_edges in set 1" ); 88  rval = FindMaxEdgesInSet( set2, max_edges_2 );MB_CHK_SET_ERR( rval, "can't determine max_edges in set 2" ); 89  90  return MB_SUCCESS; 91 } 92  93 ErrorCode Intx2Mesh::createTags() 94 { 95  if( tgtParentTag ) mb->tag_delete( tgtParentTag ); 96  if( srcParentTag ) mb->tag_delete( srcParentTag ); 97  if( countTag ) mb->tag_delete( countTag ); 98  99  unsigned char def_data_bit = 0; // unused by default 100  // maybe the tgt tag is better to be deleted every time, and recreated; 101  // or is it easy to set all values to something again? like 0? 102  ErrorCode rval = mb->tag_get_handle( "tgtFlag", 1, MB_TYPE_BIT, TgtFlagTag, MB_TAG_CREAT, &def_data_bit );MB_CHK_SET_ERR( rval, "can't get tgt flag tag" ); 103  // create tgt edges if they do not exist yet; so when they are looked upon, they are found 104  // this is the only call that is potentially NlogN, in the whole method 105  rval = mb->get_adjacencies( rs2, 1, true, TgtEdges, Interface::UNION );MB_CHK_SET_ERR( rval, "can't get adjacent tgt edges" ); 106  107  // now, create a map from each edge to a list of potential new nodes on a tgt edge 108  // this memory has to be cleaned up 109  // change it to a vector, and use the index in range of tgt edges 110  int indx = 0; 111  extraNodesVec.resize( TgtEdges.size() ); 112  for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, indx++ ) 113  { 114  std::vector< EntityHandle >* nv = new std::vector< EntityHandle >; 115  extraNodesVec[indx] = nv; 116  } 117  118  int defaultInt = -1; 119  120  rval = mb->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag, MB_TAG_DENSE | MB_TAG_CREAT, 121  &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" ); 122  123  rval = mb->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag, MB_TAG_DENSE | MB_TAG_CREAT, 124  &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" ); 125  126  rval = mb->tag_get_handle( "Counting", 1, MB_TYPE_INTEGER, countTag, MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create Counting tag" ); 127  128  // for each cell in set 1, determine its neigh in set 1 (could be null too) 129  // for each cell in set 2, determine its neigh in set 2 (if on boundary, could be 0) 130  rval = DetermineOrderedNeighbors( mbs1, max_edges_1, srcNeighTag );MB_CHK_SET_ERR( rval, "can't determine neighbors for set 1" ); 131  rval = DetermineOrderedNeighbors( mbs2, max_edges_2, tgtNeighTag );MB_CHK_SET_ERR( rval, "can't determine neighbors for set 2" ); 132  133  // for tgt cells, save a dense tag with the bordering edges, so we do not have to search for 134  // them each time edges were for sure created before (tgtEdges) 135  std::vector< EntityHandle > zeroh( max_edges_2, 0 ); 136  // if we have a tag with this name, it could be of a different size, so delete it 137  rval = mb->tag_get_handle( "__tgtEdgeNeighbors", neighTgtEdgeTag ); 138  if( rval == MB_SUCCESS && neighTgtEdgeTag ) mb->tag_delete( neighTgtEdgeTag ); 139  rval = mb->tag_get_handle( "__tgtEdgeNeighbors", max_edges_2, MB_TYPE_HANDLE, neighTgtEdgeTag, 140  MB_TAG_DENSE | MB_TAG_CREAT, &zeroh[0] );MB_CHK_SET_ERR( rval, "can't create tgt edge neighbors tag" ); 141  for( Range::iterator rit = rs2.begin(); rit != rs2.end(); rit++ ) 142  { 143  EntityHandle tgtCell = *rit; 144  int num_nodes = 0; 145  rval = mb->get_connectivity( tgtCell, tgtConn, num_nodes );MB_CHK_SET_ERR( rval, "can't get tgt conn" ); 146  // account for padded polygons 147  while( tgtConn[num_nodes - 2] == tgtConn[num_nodes - 1] && num_nodes > 3 ) 148  num_nodes--; 149  150  int i = 0; 151  for( i = 0; i < num_nodes; i++ ) 152  { 153  EntityHandle v[2] = { tgtConn[i], 154  tgtConn[( i + 1 ) % num_nodes] }; // this is fine even for padded polygons 155  std::vector< EntityHandle > adj_entities; 156  rval = mb->get_adjacencies( v, 2, 1, false, adj_entities, Interface::INTERSECT ); 157  if( rval != MB_SUCCESS || adj_entities.size() < 1 ) return rval; // get out , big error 158  zeroh[i] = adj_entities[0]; // should be only one edge between 2 nodes 159  // also, even if number of edges is less than max_edges_2, they will be ignored, even if 160  // the tag is dense 161  } 162  // now set the value of the tag 163  rval = mb->tag_set_data( neighTgtEdgeTag, &tgtCell, 1, &( zeroh[0] ) );MB_CHK_SET_ERR( rval, "can't set edge tgt tag" ); 164  } 165  return MB_SUCCESS; 166 } 167  168 ErrorCode Intx2Mesh::DetermineOrderedNeighbors( EntityHandle inputSet, int max_edges, Tag& neighTag ) 169 { 170  Range cells; 171  ErrorCode rval = mb->get_entities_by_dimension( inputSet, 2, cells );MB_CHK_SET_ERR( rval, "can't get cells in set" ); 172  173  std::vector< EntityHandle > neighbors( max_edges ); 174  std::vector< EntityHandle > zeroh( max_edges, 0 ); 175  // nameless tag, as the name is not important; we will have 2 related tags, but one on tgt mesh, 176  // one on src mesh 177  rval = mb->tag_get_handle( "", max_edges, MB_TYPE_HANDLE, neighTag, MB_TAG_DENSE | MB_TAG_CREAT, &zeroh[0] );MB_CHK_SET_ERR( rval, "can't create neighbors tag" ); 178  179  for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ ) 180  { 181  EntityHandle cell = *cit; 182  int nnodes = 3; 183  // will get the nnodes ordered neighbors; 184  // first cell is for nodes 0, 1, second to 1, 2, third to 2, 3, last to nnodes-1, 185  const EntityHandle* conn4; 186  rval = mb->get_connectivity( cell, conn4, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity of a cell" ); 187  int nsides = nnodes; 188  // account for possible padded polygons 189  while( conn4[nsides - 2] == conn4[nsides - 1] && nsides > 3 ) 190  nsides--; 191  192  for( int i = 0; i < nsides; i++ ) 193  { 194  EntityHandle v[2]; 195  v[0] = conn4[i]; 196  v[1] = conn4[( i + 1 ) % nsides]; 197  // get all cells adjacent to these 2 vertices on the edge 198  std::vector< EntityHandle > adjcells; 199  std::vector< EntityHandle > cellsInSet; 200  rval = mb->get_adjacencies( v, 2, 2, false, adjcells, Interface::INTERSECT );MB_CHK_SET_ERR( rval, "can't adjacency to 2 verts" ); 201  // now look for the cells contained in the input set; 202  // the input set should be a correct mesh, not overlapping cells, and manifold 203  size_t siz = adjcells.size(); 204  for( size_t j = 0; j < siz; j++ ) 205  if( mb->contains_entities( inputSet, &( adjcells[j] ), 1 ) ) cellsInSet.push_back( adjcells[j] ); 206  siz = cellsInSet.size(); 207  208  if( siz > 2 ) 209  { 210  std::cout << "non manifold mesh, error" << mb->list_entities( &( cellsInSet[0] ), cellsInSet.size() ) 211  << std::endl; 212  MB_CHK_SET_ERR( MB_FAILURE, "non-manifold input mesh set" ); // non-manifold 213  } 214  if( siz == 1 ) 215  { 216  // it must be the border of the input mesh; 217  neighbors[i] = 0; // we are guaranteed that ids are !=0; this is marking a border 218  // borders do not appear for a sphere in serial, but they do appear for 219  // parallel processing anyway 220  continue; 221  } 222  // here siz ==2, it is either the first or second 223  if( cell == cellsInSet[0] ) 224  neighbors[i] = cellsInSet[1]; 225  else 226  neighbors[i] = cellsInSet[0]; 227  } 228  // fill the rest with 0 229  for( int i = nsides; i < max_edges; i++ ) 230  neighbors[i] = 0; 231  // now simply set the neighbors tag; the last few positions will not be used, but for 232  // simplicity will keep them all (MAXEDGES) 233  rval = mb->tag_set_data( neighTag, &cell, 1, &neighbors[0] );MB_CHK_SET_ERR( rval, "can't set neigh tag" ); 234  } 235  return MB_SUCCESS; 236 } 237  238 // slow interface; this will not do the advancing front trick 239 // some are triangles, some are quads, some are polygons ... 240 ErrorCode Intx2Mesh::intersect_meshes_kdtree( EntityHandle mbset1, EntityHandle mbset2, EntityHandle& outputSet ) 241 { 242  ErrorCode rval; 243  mbs1 = mbset1; // set 1 is departure, and it is completely covering the euler set on proc 244  mbs2 = mbset2; 245  outSet = outputSet; 246  rval = mb->get_entities_by_dimension( mbs1, 2, rs1 );MB_CHK_ERR( rval ); 247  rval = mb->get_entities_by_dimension( mbs2, 2, rs2 );MB_CHK_ERR( rval ); 248  // from create tags, copy relevant ones 249  if( tgtParentTag ) mb->tag_delete( tgtParentTag ); 250  if( srcParentTag ) mb->tag_delete( srcParentTag ); 251  if( countTag ) mb->tag_delete( countTag ); 252  253  // filter rs1 and rs2 by mask; remove everything with 0 mask 254  // get the mask tag if it exists; if not, leave it uninitialized (NULL) 255  rval = mb->tag_get_handle( "GRID_IMASK", imaskTag ); 256  if( imaskTag != NULL && rval != MB_SUCCESS ) MB_CHK_SET_ERR( rval, "can't get GRID_IMASK tag" ); 257  rval = filterByMask( rs1 );MB_CHK_ERR( rval ); 258  rval = filterByMask( rs2 );MB_CHK_ERR( rval ); 259  // create tgt edges if they do not exist yet; so when they are looked upon, they are found 260  // this is the only call that is potentially NlogN, in the whole method 261  rval = mb->get_adjacencies( rs2, 1, true, TgtEdges, Interface::UNION );MB_CHK_SET_ERR( rval, "can't get adjacent tgt edges" ); 262  263  int index = 0; 264  extraNodesVec.resize( TgtEdges.size() ); 265  for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, index++ ) 266  { 267  std::vector< EntityHandle >* nv = new std::vector< EntityHandle >; 268  extraNodesVec[index] = nv; 269  } 270  271  int defaultInt = -1; 272  // Now let us create the association tags to source and target parent, along with internal counters 273  rval = mb->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag, MB_TAG_DENSE | MB_TAG_CREAT, 274  &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" ); 275  rval = mb->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag, MB_TAG_DENSE | MB_TAG_CREAT, 276  &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" ); 277  rval = mb->tag_get_handle( "Counting", 1, MB_TYPE_INTEGER, countTag, MB_TAG_DENSE | MB_TAG_CREAT, &defaultInt );MB_CHK_SET_ERR( rval, "can't create Counting tag" ); 278  279  // for tgt cells, save a dense tag with the bordering edges, so we do not have to search for 280  // them each time edges were for sure created before (tgtEdges) 281  // if we have a tag with this name, it could be of a different size, so delete it 282  rval = mb->tag_get_handle( "__tgtEdgeNeighbors", neighTgtEdgeTag ); 283  if( rval == MB_SUCCESS && neighTgtEdgeTag ) mb->tag_delete( neighTgtEdgeTag ); 284  std::vector< EntityHandle > zeroh( max_edges_2, 0 ); 285  rval = mb->tag_get_handle( "__tgtEdgeNeighbors", max_edges_2, MB_TYPE_HANDLE, neighTgtEdgeTag, 286  MB_TAG_DENSE | MB_TAG_CREAT, &zeroh[0] );MB_CHK_SET_ERR( rval, "can't create tgt edge neighbors tag" ); 287  288  for( Range::iterator rit = rs2.begin(); rit != rs2.end(); rit++ ) 289  { 290  EntityHandle tgtCell = *rit; 291  int num_nodes = 0; 292  rval = mb->get_connectivity( tgtCell, tgtConn, num_nodes );MB_CHK_SET_ERR( rval, "can't get tgt conn" ); 293  // account for padded polygons 294  while( tgtConn[num_nodes - 2] == tgtConn[num_nodes - 1] && num_nodes > 3 ) 295  num_nodes--; 296  297  for( int i = 0; i < num_nodes; i++ ) 298  { 299  EntityHandle v[2] = { tgtConn[i], 300  tgtConn[( i + 1 ) % num_nodes] }; // this is fine even for padded polygons 301  std::vector< EntityHandle > adj_entities; 302  rval = mb->get_adjacencies( v, 2, 1, false, adj_entities, Interface::INTERSECT ); 303  if( rval != MB_SUCCESS || adj_entities.size() < 1 ) return rval; // get out , big error 304  zeroh[i] = adj_entities[0]; // should be only one edge between 2 nodes 305  // also, even if number of edges is less than max_edges_2, they will be ignored, even if 306  // the tag is dense 307  } 308  // now set the value of the tag 309  rval = mb->tag_set_data( neighTgtEdgeTag, &tgtCell, 1, &( zeroh[0] ) );MB_CHK_SET_ERR( rval, "can't set edge tgt tag" ); 310  } 311  312  // find out max edge on source mesh; 313  double max_length = 0; 314  { 315  std::vector< double > coords( 3 * max_edges_1, 0.0 ); 316  for( Range::iterator it = rs1.begin(); it != rs1.end(); it++ ) 317  { 318  const EntityHandle* conn = NULL; 319  int nnodes; 320  rval = mb->get_connectivity( *it, conn, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity" ); 321  while( conn[nnodes - 2] == conn[nnodes - 1] && nnodes > 3 ) 322  nnodes--; 323  rval = mb->get_coords( conn, nnodes, &coords[0] );MB_CHK_SET_ERR( rval, "can't get coordinates" ); 324  for( int j = 0; j < nnodes; j++ ) 325  { 326  int next = ( j + 1 ) % nnodes; 327  double edge_length = 328  ( coords[3 * j] - coords[3 * next] ) * ( coords[3 * j] - coords[3 * next] ) + 329  ( coords[3 * j + 1] - coords[3 * next + 1] ) * ( coords[3 * j + 1] - coords[3 * next + 1] ) + 330  ( coords[3 * j + 2] - coords[3 * next + 2] ) * ( coords[3 * j + 2] - coords[3 * next + 2] ); 331  if( edge_length > max_length ) max_length = edge_length; 332  } 333  } 334  max_length = std::sqrt( max_length ); 335  } 336  337  // maximum sag on a spherical mesh make sense only for intx on a sphere, with radius 1 :( 338  double tolerance = 1.e-15; 339  if( max_length < 1. ) 340  { 341  // basically, the sag for an arc of length max_length on a circle of radius 1 342  tolerance = 1. - sqrt( 1 - max_length * max_length / 4 ); 343  if( box_error < tolerance ) box_error = tolerance; 344  tolerance = 3 * tolerance; // we use it for gnomonic plane too, projected sag could be =* sqrt(2.) 345  // be more generous, use 1.5 ~= sqrt(2.) 346  347  if( !my_rank ) 348  { 349  std::cout << " max edge length: " << max_length << " tolerance for kd tree: " << tolerance << "\n"; 350  std::cout << " box overlap tolerance: " << box_error << "\n"; 351  } 352  } 353 #ifdef MOAB_HAVE_MPI 354  // reduce box tolerance on every task, if needed 355  double min_box_eps; 356  MPI_Allreduce( &box_error, &min_box_eps, 1, MPI_DOUBLE, MPI_MIN, parcomm->comm() ); 357  box_error = min_box_eps; 358 #endif 359  360  // create the kd tree on source cells, and intersect all targets in an expensive loop 361  // build a kd tree with the rs1 (source) cells 362  FileOptions kdOpts( "PLANE_SET=1;SPLITS_PER_DIR=2;SPHERICAL;RADIUS=1.0;" ); 363  AdaptiveKDTree kd( mb ); 364  kd.parse_options( kdOpts ); 365  EntityHandle tree_root = 0; 366  rval = kd.build_tree( rs1, &tree_root );MB_CHK_ERR( rval ); 367  368  for( Range::iterator it = rs2.begin(); it != rs2.end(); ++it ) 369  { 370  EntityHandle tcell = *it; 371  // find vertex positions 372  const EntityHandle* conn = NULL; 373  int nnodes = 0; 374  rval = mb->get_connectivity( tcell, conn, nnodes );MB_CHK_ERR( rval ); 375  // find leaves close to those positions 376  double areaTgtCell = setup_tgt_cell( tcell, nnodes ); // this is the area in the gnomonic plane 377  double recoveredArea = 0; 378  std::vector< double > positions; 379  positions.resize( nnodes * 3 ); 380  rval = mb->get_coords( conn, nnodes, &positions[0] );MB_CHK_ERR( rval ); 381  382  // distance to search will be based on average edge length 383  double av_len = 0; 384  for( int k = 0; k < nnodes; k++ ) 385  { 386  int ik = ( k + 1 ) % nnodes; 387  double len1 = 0; 388  for( int j = 0; j < 3; j++ ) 389  { 390  double len2 = positions[3 * k + j] - positions[3 * ik + j]; 391  len1 += len2 * len2; 392  } 393  av_len += sqrt( len1 ); 394  } 395  if( nnodes > 0 ) av_len /= nnodes; 396  // find leaves within a distance from each vertex of target 397  // in those leaves, collect all cells; we will try for an intx in there 398  Range close_source_cells; 399  std::vector< EntityHandle > leaves; 400  for( int i = 0; i < nnodes; i++ ) 401  { 402  leaves.clear(); 403  rval = kd.distance_search( &positions[3 * i], av_len, leaves, tolerance, epsilon_1 );MB_CHK_ERR( rval ); 404  405  for( std::vector< EntityHandle >::iterator j = leaves.begin(); j != leaves.end(); ++j ) 406  { 407  Range tmp; 408  rval = mb->get_entities_by_dimension( *j, 2, tmp );MB_CHK_ERR( rval ); 409  410  close_source_cells.merge( tmp.begin(), tmp.end() ); 411  } 412  } 413 #ifdef VERBOSE 414  if( close_source_cells.empty() ) 415  { 416  std::cout << " there are no close source cells to target cell " << tcell << " id from handle " 417  << mb->id_from_handle( tcell ) << "\n"; 418  } 419 #endif 420  for( Range::iterator it2 = close_source_cells.begin(); it2 != close_source_cells.end(); ++it2 ) 421  { 422  EntityHandle startSrc = *it2; 423  double area = 0; 424  // if area is > 0 , we have intersections 425  double P[10 * MAXEDGES]; // max 8 intx points + 8 more in the polygon 426  // 427  int nP = 0; 428  int nb[MAXEDGES], nr[MAXEDGES]; // sides 3 or 4? also, check boxes first 429  int nsTgt, nsSrc; 430  rval = computeIntersectionBetweenTgtAndSrc( tcell, startSrc, P, nP, area, nb, nr, nsSrc, nsTgt, true );MB_CHK_ERR( rval ); 431  if( area > 0 ) 432  { 433  if( nP > 1 ) 434  { // this will also construct triangles/polygons in the new mesh, if needed 435  rval = findNodes( tcell, nnodes, startSrc, nsSrc, P, nP );MB_CHK_ERR( rval ); 436  } 437  recoveredArea += area; 438  } 439  } 440  recoveredArea = ( recoveredArea - areaTgtCell ) / areaTgtCell; // replace now with recovery fract 441  } 442  // before cleaning up , we need to settle the position of the intersection points 443  // on the boundary edges 444  // this needs to be collective, so we should maybe wait something 445 #ifdef MOAB_HAVE_MPI 446  rval = resolve_intersection_sharing();MB_CHK_SET_ERR( rval, "can't correct position, Intx2Mesh.cpp \n" ); 447 #endif 448  449  this->clean(); 450  return MB_SUCCESS; 451 } 452  453 // main interface; this will do the advancing front trick 454 // some are triangles, some are quads, some are polygons ... 455 ErrorCode Intx2Mesh::intersect_meshes( EntityHandle mbset1, EntityHandle mbset2, EntityHandle& outputSet ) 456 { 457  ErrorCode rval; 458  mbs1 = mbset1; // set 1 is departure, and it is completely covering the euler set on proc 459  mbs2 = mbset2; 460  outSet = outputSet; 461 #ifdef VERBOSE 462  std::stringstream ffs, fft; 463  ffs << "source_rank0" << my_rank << ".vtk"; 464  rval = mb->write_mesh( ffs.str().c_str(), &mbset1, 1 );MB_CHK_ERR( rval ); 465  fft << "target_rank0" << my_rank << ".vtk"; 466  rval = mb->write_mesh( fft.str().c_str(), &mbset2, 1 );MB_CHK_ERR( rval ); 467  468 #endif 469  // really, should be something from t1 and t2; src is 1 (lagrange), tgt is 2 (euler) 470  471  EntityHandle startSrc = 0, startTgt = 0; 472  473  rval = mb->get_entities_by_dimension( mbs1, 2, rs1 );MB_CHK_ERR( rval ); 474  rval = mb->get_entities_by_dimension( mbs2, 2, rs2 );MB_CHK_ERR( rval ); 475  476  // filter rs1 and rs2 by mask; remove everything with 0 mask 477  // get the mask tag if it exists; if not, leave it uninitialized (NULL) 478  mb->tag_get_handle( "GRID_IMASK", imaskTag ); 479  if( imaskTag != NULL && rval != MB_SUCCESS ) MB_CHK_SET_ERR( rval, "can't get GRID_IMASK tag" ); 480  481  rval = filterByMask( rs1 );MB_CHK_ERR( rval ); 482  rval = filterByMask( rs2 );MB_CHK_ERR( rval ); 483  484  createTags(); // will also determine max_edges_1, max_edges_2 (for src and tgt meshes) 485  486  Range rs22 = rs2; // a copy of the initial range; we will remove from it elements as we 487  // advance ; rs2 is needed for marking the polygon to the tgt parent 488  489  // create the local kdd tree with source elements; will use it to search 490  // more efficiently for the seeds in advancing front; 491  // some of the target cells will not be covered by source cells, and they need to be eliminated 492  // early from contention 493  494  // build a kd tree with the rs1 (source) cells 495  FileOptions kdOpts( "PLANE_SET=1;SPLITS_PER_DIR=2;SPHERICAL;RADIUS=1.0;" ); 496  AdaptiveKDTree kd( mb ); 497  kd.parse_options( kdOpts ); 498  EntityHandle tree_root = 0; 499  rval = kd.build_tree( rs1, &tree_root );MB_CHK_ERR( rval ); 500  501  while( !rs22.empty() ) 502  { 503 #if defined( ENABLE_DEBUG ) || defined( VERBOSE ) 504  if( rs22.size() < rs2.size() ) 505  { 506  std::cout << " possible not connected arrival mesh; my_rank: " << my_rank << " counting: " << counting 507  << "\n"; 508  std::stringstream ffo; 509  ffo << "file0" << counting << "rank0" << my_rank << ".vtk"; 510  rval = mb->write_mesh( ffo.str().c_str(), &outSet, 1 );MB_CHK_ERR( rval ); 511  } 512 #endif 513  bool seedFound = false; 514  for( Range::iterator it = rs22.begin(); it != rs22.end(); ++it ) 515  { 516  startTgt = *it; 517  int found = 0; 518  // find vertex positions 519  const EntityHandle* conn = NULL; 520  int nnodes = 0; 521  rval = mb->get_connectivity( startTgt, conn, nnodes );MB_CHK_ERR( rval ); 522  // find leaves close to those positions 523  std::vector< double > positions; 524  positions.resize( nnodes * 3 ); 525  rval = mb->get_coords( conn, nnodes, &positions[0] );MB_CHK_ERR( rval ); 526  // find leaves within a distance from each vertex of target 527  // in those leaves, collect all cells; we will try for an intx in there, instead of 528  // looping over all rs1 cells, as before 529  Range close_source_cells; 530  std::vector< EntityHandle > leaves; 531  for( int i = 0; i < nnodes; i++ ) 532  { 533  leaves.clear(); 534  rval = kd.distance_search( &positions[3 * i], epsilon_1, leaves, epsilon_1, epsilon_1 );MB_CHK_ERR( rval ); 535  536  for( std::vector< EntityHandle >::iterator j = leaves.begin(); j != leaves.end(); ++j ) 537  { 538  Range tmp; 539  rval = mb->get_entities_by_dimension( *j, 2, tmp );MB_CHK_ERR( rval ); 540  541  close_source_cells.merge( tmp.begin(), tmp.end() ); 542  } 543  } 544  545  for( Range::iterator it2 = close_source_cells.begin(); it2 != close_source_cells.end() && !found; ++it2 ) 546  { 547  startSrc = *it2; 548  double area = 0; 549  // if area is > 0 , we have intersections 550  double P[10 * MAXEDGES]; // max 8 intx points + 8 more in the polygon 551  // 552  int nP = 0; 553  int nb[MAXEDGES], nr[MAXEDGES]; // sides 3 or 4? also, check boxes first 554  int nsTgt, nsSrc; 555  rval = 556  computeIntersectionBetweenTgtAndSrc( startTgt, startSrc, P, nP, area, nb, nr, nsSrc, nsTgt, true );MB_CHK_ERR( rval ); 557  if( area > 0 ) 558  { 559  found = 1; 560  seedFound = true; 561  break; // found 2 elements that intersect; these will be the seeds 562  } 563  } 564  if( found ) 565  break; 566  else 567  { 568 #if defined( VERBOSE ) 569  std::cout << " on rank " << my_rank << " target cell " << ID_FROM_HANDLE( startTgt ) 570  << " not intx with any source\n"; 571 #endif 572  rs22.erase( startTgt ); 573  } 574  } 575  if( !seedFound ) continue; // continue while(!rs22.empty()) 576  577  std::queue< EntityHandle > srcQueue; // these are corresponding to Ta, 578  srcQueue.push( startSrc ); 579  std::queue< EntityHandle > tgtQueue; 580  tgtQueue.push( startTgt ); 581  582  Range toResetSrcs; // will be used to reset src flags for every tgt element processed 583  584  /*if (my_rank==0) 585  dbg_1 = 1;*/ 586  unsigned char used = 1; 587  // mark the start tgt quad as used, so it will not come back again 588  rval = mb->tag_set_data( TgtFlagTag, &startTgt, 1, &used );MB_CHK_ERR( rval ); 589  while( !tgtQueue.empty() ) 590  { 591  // flags for the side : 0 means a src cell not found on side 592  // a paired src not found yet for the neighbors of tgt 593  Range nextSrc[MAXEDGES]; // there are new ranges of possible next src cells for 594  // seeding the side j of tgt cell 595  596  EntityHandle currentTgt = tgtQueue.front(); 597  tgtQueue.pop(); 598  int nsidesTgt; // will be initialized now 599  double areaTgtCell = setup_tgt_cell( currentTgt, nsidesTgt ); // this is the area in the gnomonic plane 600  double recoveredArea = 0; 601  // get the neighbors of tgt, and if they are solved already, do not bother with that 602  // side of tgt 603  EntityHandle tgtNeighbors[MAXEDGES] = { 0 }; 604  rval = mb->tag_get_data( tgtNeighTag, &currentTgt, 1, tgtNeighbors );MB_CHK_SET_ERR( rval, "can't get neighbors of current tgt" ); 605 #ifdef ENABLE_DEBUG 606  if( dbg_1 ) 607  { 608  std::cout << "Next: neighbors for current tgt "; 609  for( int kk = 0; kk < nsidesTgt; kk++ ) 610  { 611  if( tgtNeighbors[kk] > 0 ) 612  std::cout << mb->id_from_handle( tgtNeighbors[kk] ) << " "; 613  else 614  std::cout << 0 << " "; 615  } 616  std::cout << std::endl; 617  } 618 #endif 619  // now get the status of neighbors; if already solved, make them 0, so not to bother 620  // anymore on that side of tgt 621  for( int j = 0; j < nsidesTgt; j++ ) 622  { 623  EntityHandle tgtNeigh = tgtNeighbors[j]; 624  unsigned char status = 1; 625  if( tgtNeigh == 0 ) continue; 626  rval = mb->tag_get_data( TgtFlagTag, &tgtNeigh, 1, &status );MB_CHK_ERR( rval ); // status 0 is unused 627  if( 1 == status ) tgtNeighbors[j] = 0; // so will not look anymore on this side of tgt 628  } 629  630 #ifdef ENABLE_DEBUG 631  if( dbg_1 ) 632  { 633  std::cout << "reset sources: "; 634  for( Range::iterator itr = toResetSrcs.begin(); itr != toResetSrcs.end(); ++itr ) 635  std::cout << mb->id_from_handle( *itr ) << " "; 636  std::cout << std::endl; 637  } 638 #endif 639  EntityHandle currentSrc = srcQueue.front(); 640  // tgt and src queues are parallel; for clarity we should have kept in the queue pairs 641  // of entity handle std::pair<EntityHandle, EntityHandle>; so just one queue, with 642  // pairs; 643  // at every moment, the queue contains pairs of cells that intersect, and they form the 644  // "advancing front" 645  srcQueue.pop(); 646  toResetSrcs.clear(); // empty the range of used srcs, will have to be set unused again, 647  // at the end of tgt element processing 648  toResetSrcs.insert( currentSrc ); 649  // mb2->set_tag_data 650  std::queue< EntityHandle > localSrc; 651  localSrc.push( currentSrc ); 652 #ifdef VERBOSE 653  int countingStart = counting; 654 #endif 655  // will advance-front search in the neighborhood of tgt cell, until we finish processing 656  // all 657  // possible src cells; localSrc queue will contain all possible src cells that cover 658  // the current tgt cell 659  while( !localSrc.empty() ) 660  { 661  // 662  EntityHandle srcT = localSrc.front(); 663  localSrc.pop(); 664  double P[10 * MAXEDGES], area; // 665  int nP = 0; 666  int nb[MAXEDGES] = { 0 }; 667  int nr[MAXEDGES] = { 0 }; 668  669  int nsidesSrc; /// 670  // area is in 2d, points are in 3d (on a sphere), back-projected, or in a plane 671  // intersection points could include the vertices of initial elements 672  // nb [j] = 0 means no intersection on the side j for element src (markers) 673  // nb [j] = 1 means that the side j (from j to j+1) of src poly intersects the 674  // tgt poly. A potential next poly in the tgt queue is the tgt poly that is 675  // adjacent to this side 676  rval = computeIntersectionBetweenTgtAndSrc( /* tgt */ currentTgt, srcT, P, nP, area, nb, nr, nsidesSrc, 677  nsidesTgt );MB_CHK_ERR( rval ); 678  if( nP > 0 ) 679  { 680 #ifdef ENABLE_DEBUG 681  if( dbg_1 ) 682  { 683  for( int k = 0; k < 3; k++ ) 684  { 685  std::cout << " nb, nr: " << k << " " << nb[k] << " " << nr[k] << "\n"; 686  } 687  } 688 #endif 689  690  // intersection found: output P and original triangles if nP > 2 691  EntityHandle neighbors[MAXEDGES] = { 0 }; 692  rval = mb->tag_get_data( srcNeighTag, &srcT, 1, neighbors ); 693  if( rval != MB_SUCCESS ) 694  { 695  std::cout << " can't get the neighbors for src element " << mb->id_from_handle( srcT ); 696  return MB_FAILURE; 697  } 698  699  // add neighbors to the localSrc queue, if they are not marked 700  for( int nn = 0; nn < nsidesSrc; nn++ ) 701  { 702  EntityHandle neighbor = neighbors[nn]; 703  if( neighbor > 0 && nb[nn] > 0 ) // advance across src boundary nn 704  { 705  if( toResetSrcs.find( neighbor ) == toResetSrcs.end() ) 706  { 707  localSrc.push( neighbor ); 708 #ifdef ENABLE_DEBUG 709  if( dbg_1 ) 710  { 711  std::cout << " local src elem " << mb->id_from_handle( neighbor ) 712  << " for tgt:" << mb->id_from_handle( currentTgt ) << "\n"; 713  mb->list_entities( &neighbor, 1 ); 714  } 715 #endif 716  toResetSrcs.insert( neighbor ); 717  } 718  } 719  } 720  // n(find(nc>0))=ac; % ac is starting candidate for neighbor 721  for( int nn = 0; nn < nsidesTgt; nn++ ) 722  { 723  if( nr[nn] > 0 && tgtNeighbors[nn] > 0 ) 724  nextSrc[nn].insert( srcT ); // potential src cell that can intersect 725  // the tgt neighbor nn 726  } 727  if( nP > 1 ) 728  { // this will also construct triangles/polygons in the new mesh, if needed 729  rval = findNodes( currentTgt, nsidesTgt, srcT, nsidesSrc, P, nP );MB_CHK_ERR( rval ); 730  } 731  732  recoveredArea += area; 733  } 734 #ifdef ENABLE_DEBUG 735  else if( dbg_1 ) 736  { 737  std::cout << " tgt, src, do not intersect: " << mb->id_from_handle( currentTgt ) << " " 738  << mb->id_from_handle( srcT ) << "\n"; 739  } 740 #endif 741  } // end while (!localSrc.empty()) 742  recoveredArea = ( recoveredArea - areaTgtCell ) / areaTgtCell; // replace now with recovery fraction 743 #if defined( ENABLE_DEBUG ) || defined( VERBOSE ) 744  if( fabs( recoveredArea ) > epsilon_1 ) 745  { 746 #ifdef VERBOSE 747  std::cout << " tgt area: " << areaTgtCell << " recovered :" << recoveredArea * ( 1 + areaTgtCell ) 748  << " fraction error recovery:" << recoveredArea 749  << " tgtID: " << mb->id_from_handle( currentTgt ) << " countingStart:" << countingStart 750  << "\n"; 751 #endif 752  } 753 #endif 754  // here, we are finished with tgtCurrent, take it out of the rs22 range (tgt, arrival 755  // mesh) 756  rs22.erase( currentTgt ); 757  // also, look at its neighbors, and add to the seeds a next one 758  759  for( int j = 0; j < nsidesTgt; j++ ) 760  { 761  EntityHandle tgtNeigh = tgtNeighbors[j]; 762  if( tgtNeigh == 0 || nextSrc[j].size() == 0 ) // if tgt is bigger than src, there could be no src 763  // to advance on that side 764  continue; 765  int nsidesTgt2 = 0; 766  setup_tgt_cell( tgtNeigh, 767  nsidesTgt2 ); // find possible intersection with src cell from nextSrc 768  for( Range::iterator nit = nextSrc[j].begin(); nit != nextSrc[j].end(); ++nit ) 769  { 770  EntityHandle nextB = *nit; 771  // we identified tgt quad n[j] as possibly intersecting with neighbor j of the 772  // src quad 773  double P[10 * MAXEDGES], area; // 774  int nP = 0; 775  int nb[MAXEDGES] = { 0 }; 776  int nr[MAXEDGES] = { 0 }; 777  778  int nsidesSrc; /// 779  rval = computeIntersectionBetweenTgtAndSrc( 780  /* tgt */ tgtNeigh, nextB, P, nP, area, nb, nr, nsidesSrc, nsidesTgt2 );MB_CHK_ERR( rval ); 781  if( area > 0 ) 782  { 783  tgtQueue.push( tgtNeigh ); 784  srcQueue.push( nextB ); 785 #ifdef ENABLE_DEBUG 786  if( dbg_1 ) 787  std::cout << "new polys pushed: src, tgt:" << mb->id_from_handle( tgtNeigh ) << " " 788  << mb->id_from_handle( nextB ) << std::endl; 789 #endif 790  rval = mb->tag_set_data( TgtFlagTag, &tgtNeigh, 1, &used );MB_CHK_ERR( rval ); 791  break; // so we are done with this side of tgt, we have found a proper next 792  // seed 793  } 794  } 795  } 796  797  } // end while (!tgtQueue.empty()) 798  } 799 #ifdef ENABLE_DEBUG 800  if( dbg_1 ) 801  { 802  for( int k = 0; k < 6; k++ ) 803  mout_1[k].close(); 804  } 805 #endif 806  // before cleaning up , we need to settle the position of the intersection points 807  // on the boundary edges 808  // this needs to be collective, so we should maybe wait something 809 #ifdef MOAB_HAVE_MPI 810  rval = resolve_intersection_sharing();MB_CHK_SET_ERR( rval, "can't correct position, Intx2Mesh.cpp \n" ); 811 #endif 812  813  this->clean(); 814  return MB_SUCCESS; 815 } 816  817 ErrorCode Intx2Mesh::filterByMask( Range& cells ) 818 { 819  if( !imaskTag ) return MB_SUCCESS; // nothing to do 820  size_t sz = cells.size(); 821  std::vector< int > masks( sz ); 822  823  ErrorCode rval = mb->tag_get_data( imaskTag, cells, &masks[0] );MB_CHK_ERR( rval ); 824  Range cellsToRemove; 825  size_t indx = 0; 826  for( Range::iterator eit = cells.begin(); eit != cells.end(); ++eit, ++indx ) 827  { 828  if( masks[indx] ) continue; 829  cellsToRemove.insert( *eit ); 830  } 831  cells = subtract( cells, cellsToRemove ); 832  return MB_SUCCESS; 833 } 834  835 // clean some memory allocated 836 void Intx2Mesh::clean() 837 { 838  // 839  int indx = 0; 840  for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, indx++ ) 841  { 842  delete extraNodesVec[indx]; 843  } 844  // extraNodesMap.clear(); 845  extraNodesVec.clear(); 846  // also, delete some bit tags, used to mark processed tgts and srcs 847  mb->tag_delete( TgtFlagTag ); 848  counting = 0; // reset counting to original value 849 } 850  851 // this method will reduce number of nodes, collapse edges that are of length 0 852 // so a polygon like 428 431 431 will become a line 428 431 853 // or something like 428 431 431 531 -> 428 431 531 854 void Intx2Mesh::correct_polygon( EntityHandle* nodes, int& nP ) 855 { 856  int i = 0; 857  while( i < nP ) 858  { 859  int nextIndex = ( i + 1 ) % nP; 860  if( nodes[i] == nodes[nextIndex] ) 861  { 862 #ifdef ENABLE_DEBUG 863  // we need to reduce nP, and collapse nodes 864  if( dbg_1 ) 865  { 866  std::cout << " nodes duplicated in list: "; 867  for( int j = 0; j < nP; j++ ) 868  std::cout << nodes[j] << " "; 869  std::cout << "\n"; 870  std::cout << " node " << nodes[i] << " at index " << i << " is duplicated" << "\n"; 871  } 872 #endif 873  // this will work even if we start from 1 2 3 1; when i is 3, we find nextIndex is 0, 874  // then next thing does nothing 875  // (nP-1 is 3, so k is already >= nP-1); it will result in nodes -> 1, 2, 3 876  for( int k = i; k < nP - 1; k++ ) 877  nodes[k] = nodes[k + 1]; 878  nP--; // decrease the number of nodes; also, decrease i, just if we may need to check 879  // again 880  i--; 881  } 882  i++; 883  } 884  return; 885 } 886  887 #ifdef MOAB_HAVE_MPI 888  889 ErrorCode Intx2Mesh::build_processor_euler_boxes( EntityHandle euler_set, Range& local_verts, bool gnomonic ) 890 { 891  // if it comes here, we want regular 3d boxes 892  // need to refactor this code 893  if( gnomonic ) gnomonic = false; 894  localEnts.clear(); 895  ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, localEnts );ERRORR( rval, "can't get ents by dimension" ); 896  897  rval = mb->get_connectivity( localEnts, local_verts ); 898  int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" ); 899  900  assert( parcomm != NULL ); 901  902  // get the position of local vertices, and decide local boxes (allBoxes...) 903  double bmin[3] = { std::numeric_limits< double >::max(), std::numeric_limits< double >::max(), 904  std::numeric_limits< double >::max() }; 905  double bmax[3] = { -std::numeric_limits< double >::max(), -std::numeric_limits< double >::max(), 906  -std::numeric_limits< double >::max() }; 907  908  std::vector< double > coords( 3 * num_local_verts ); 909  rval = mb->get_coords( local_verts, &coords[0] );ERRORR( rval, "can't get coords of vertices " ); 910  911  for( int i = 0; i < num_local_verts; i++ ) 912  { 913  for( int k = 0; k < 3; k++ ) 914  { 915  double val = coords[3 * i + k]; 916  if( val < bmin[k] ) bmin[k] = val; 917  if( val > bmax[k] ) bmax[k] = val; 918  } 919  } 920  int numprocs = parcomm->proc_config().proc_size(); 921  allBoxes.resize( 6 * numprocs ); 922  923  my_rank = parcomm->proc_config().proc_rank(); 924  for( int k = 0; k < 3; k++ ) 925  { 926  allBoxes[6 * my_rank + k] = bmin[k]; 927  allBoxes[6 * my_rank + 3 + k] = bmax[k]; 928  } 929  930  // now communicate to get all boxes 931  int mpi_err; 932 #if( MPI_VERSION >= 2 ) 933  // use "in place" option 934  mpi_err = MPI_Allgather( MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, &allBoxes[0], 6, MPI_DOUBLE, 935  parcomm->proc_config().proc_comm() ); 936 #else 937  { 938  std::vector< double > allBoxes_tmp( 6 * parcomm->proc_config().proc_size() ); 939  mpi_err = MPI_Allgather( &allBoxes[6 * my_rank], 6, MPI_DOUBLE, &allBoxes_tmp[0], 6, MPI_DOUBLE, 940  parcomm->proc_config().proc_comm() ); 941  allBoxes = allBoxes_tmp; 942  } 943 #endif 944  if( MPI_SUCCESS != mpi_err ) return MB_FAILURE; 945  946 #ifdef VERBOSE 947  if( my_rank == 0 ) 948  { 949  std::cout << " maximum number of vertices per cell are " << max_edges_1 << " on first mesh and " << max_edges_2 950  << " on second mesh \n"; 951  for( int i = 0; i < numprocs; i++ ) 952  { 953  std::cout << "proc: " << i << " box min: " << allBoxes[6 * i] << " " << allBoxes[6 * i + 1] << " " 954  << allBoxes[6 * i + 2] << " \n"; 955  std::cout << " box max: " << allBoxes[6 * i + 3] << " " << allBoxes[6 * i + 4] << " " 956  << allBoxes[6 * i + 5] << " \n"; 957  } 958  } 959 #endif 960  961  return MB_SUCCESS; 962 } 963  964 ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg( EntityHandle& euler_set, EntityHandle& covering_lagr_set ) 965 { 966  // compute the bounding box on each proc 967  assert( parcomm != NULL ); 968  969  localEnts.clear(); 970  ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, localEnts );ERRORR( rval, "can't get ents by dimension" ); 971  972  Tag dpTag = 0; 973  std::string tag_name( "DP" ); 974  rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE );ERRORR( rval, "can't get DP tag" ); 975  976  EntityHandle dum = 0; 977  Tag corrTag; 978  rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum );ERRORR( rval, "can't get CORR tag" ); 979  // get all local verts 980  Range local_verts; 981  rval = mb->get_connectivity( localEnts, local_verts ); 982  int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" ); 983  984  rval = Intx2Mesh::build_processor_euler_boxes( euler_set, local_verts );ERRORR( rval, "can't build processor boxes" ); 985  986  std::vector< int > gids( num_local_verts ); 987  rval = mb->tag_get_data( gid, local_verts, &gids[0] );ERRORR( rval, "can't get local vertices gids" ); 988  989  // now see the departure points; to what boxes should we send them? 990  std::vector< double > dep_points( 3 * num_local_verts ); 991  rval = mb->tag_get_data( dpTag, local_verts, (void*)&dep_points[0] );ERRORR( rval, "can't get DP tag values" ); 992  // ranges to send to each processor; will hold vertices and elements (quads?) 993  // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances) 994  std::map< int, Range > Rto; 995  int numprocs = parcomm->proc_config().proc_size(); 996  997  for( Range::iterator eit = localEnts.begin(); eit != localEnts.end(); ++eit ) 998  { 999  EntityHandle q = *eit; 1000  const EntityHandle* conn4; 1001  int num_nodes; 1002  rval = mb->get_connectivity( q, conn4, num_nodes );ERRORR( rval, "can't get DP tag values" ); 1003  CartVect qbmin( std::numeric_limits< double >::max() ); 1004  CartVect qbmax( -std::numeric_limits< double >::max() ); 1005  for( int i = 0; i < num_nodes; i++ ) 1006  { 1007  EntityHandle v = conn4[i]; 1008  size_t index = local_verts.find( v ) - local_verts.begin(); 1009  CartVect dp( &dep_points[3 * index] ); // will use constructor 1010  for( int j = 0; j < 3; j++ ) 1011  { 1012  if( qbmin[j] > dp[j] ) qbmin[j] = dp[j]; 1013  if( qbmax[j] < dp[j] ) qbmax[j] = dp[j]; 1014  } 1015  } 1016  for( int p = 0; p < numprocs; p++ ) 1017  { 1018  CartVect bbmin( &allBoxes[6 * p] ); 1019  CartVect bbmax( &allBoxes[6 * p + 3] ); 1020  if( GeomUtil::boxes_overlap( bbmin, bbmax, qbmin, qbmax, box_error ) ) 1021  { 1022  Rto[p].insert( q ); 1023  } 1024  } 1025  } 1026  1027  // now, build TLv and TLq, for each p 1028  size_t numq = 0; 1029  size_t numv = 0; 1030  for( int p = 0; p < numprocs; p++ ) 1031  { 1032  if( p == (int)my_rank ) continue; // do not "send" it, because it is already here 1033  Range& range_to_P = Rto[p]; 1034  // add the vertices to it 1035  if( range_to_P.empty() ) continue; // nothing to send to proc p 1036  Range vertsToP; 1037  rval = mb->get_connectivity( range_to_P, vertsToP );ERRORR( rval, "can't get connectivity" ); 1038  numq = numq + range_to_P.size(); 1039  numv = numv + vertsToP.size(); 1040  range_to_P.merge( vertsToP ); 1041  } 1042  TupleList TLv; 1043  TupleList TLq; 1044  TLv.initialize( 2, 0, 0, 3, numv ); // to proc, GLOBAL ID, DP points 1045  TLv.enableWriteAccess(); 1046  1047  int sizeTuple = 2 + max_edges_1; // determined earlier, for src, first mesh 1048  TLq.initialize( 2 + max_edges_1, 0, 1, 0, 1049  numq ); // to proc, elem GLOBAL ID, connectivity[10] (global ID v), local eh 1050  TLq.enableWriteAccess(); 1051 #ifdef VERBOSE 1052  std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n"; 1053 #endif 1054  for( int to_proc = 0; to_proc < numprocs; to_proc++ ) 1055  { 1056  if( to_proc == (int)my_rank ) continue; 1057  Range& range_to_P = Rto[to_proc]; 1058  Range V = range_to_P.subset_by_type( MBVERTEX ); 1059  1060  for( Range::iterator it = V.begin(); it != V.end(); ++it ) 1061  { 1062  EntityHandle v = *it; 1063  unsigned int index = local_verts.find( v ) - local_verts.begin(); 1064  int n = TLv.get_n(); 1065  TLv.vi_wr[2 * n] = to_proc; // send to processor 1066  TLv.vi_wr[2 * n + 1] = gids[index]; // global id needs index in the local_verts range 1067  TLv.vr_wr[3 * n] = dep_points[3 * index]; // departure position, of the node local_verts[i] 1068  TLv.vr_wr[3 * n + 1] = dep_points[3 * index + 1]; 1069  TLv.vr_wr[3 * n + 2] = dep_points[3 * index + 2]; 1070  TLv.inc_n(); 1071  } 1072  // also, prep the quad for sending ... 1073  Range Q = range_to_P.subset_by_dimension( 2 ); 1074  for( Range::iterator it = Q.begin(); it != Q.end(); ++it ) 1075  { 1076  EntityHandle q = *it; 1077  int global_id; 1078  rval = mb->tag_get_data( gid, &q, 1, &global_id );ERRORR( rval, "can't get gid for polygon" ); 1079  int n = TLq.get_n(); 1080  TLq.vi_wr[sizeTuple * n] = to_proc; // 1081  TLq.vi_wr[sizeTuple * n + 1] = global_id; // global id of element, used to identify it ... 1082  const EntityHandle* conn4; 1083  int num_nodes; 1084  rval = mb->get_connectivity( q, conn4, 1085  num_nodes ); // could be up to MAXEDGES, but it is limited by max_edges_1 1086  ERRORR( rval, "can't get connectivity for cell" ); 1087  if( num_nodes > MAXEDGES ) ERRORR( MB_FAILURE, "too many nodes in a polygon" ); 1088  for( int i = 0; i < num_nodes; i++ ) 1089  { 1090  EntityHandle v = conn4[i]; 1091  unsigned int index = local_verts.find( v ) - local_verts.begin(); 1092  TLq.vi_wr[sizeTuple * n + 2 + i] = gids[index]; 1093  } 1094  for( int k = num_nodes; k < max_edges_1; k++ ) 1095  { 1096  TLq.vi_wr[sizeTuple * n + 2 + k] = 1097  0; // fill the rest of node ids with 0; we know that the node ids start from 1! 1098  } 1099  TLq.vul_wr[n] = q; // save here the entity handle, it will be communicated back 1100  // maybe we should forget about global ID 1101  TLq.inc_n(); 1102  } 1103  } 1104  1105  // now we are done populating the tuples; route them to the appropriate processors 1106  ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 ); 1107  ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLq, 0 ); 1108  // the elements are already in localEnts; 1109  1110  // maps from global ids to new vertex and quad handles, that are added 1111  std::map< int, EntityHandle > globalID_to_handle; 1112  /*std::map<int, EntityHandle> globalID_to_eh;*/ 1113  globalID_to_eh.clear(); // need for next iteration 1114  // now, look at every TLv, and see if we have to create a vertex there or not 1115  int n = TLv.get_n(); // the size of the points received 1116  for( int i = 0; i < n; i++ ) 1117  { 1118  int globalId = TLv.vi_rd[2 * i + 1]; 1119  if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() ) 1120  { 1121  EntityHandle new_vert; 1122  double dp_pos[3] = { TLv.vr_wr[3 * i], TLv.vr_wr[3 * i + 1], TLv.vr_wr[3 * i + 2] }; 1123  rval = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " ); 1124  globalID_to_handle[globalId] = new_vert; 1125  } 1126  } 1127  1128  // now, all dep points should be at their place 1129  // look in the local list of q for this proc, and create all those quads and vertices if needed 1130  // it may be an overkill, but because it does not involve communication, we do it anyway 1131  Range& local = Rto[my_rank]; 1132  Range local_q = local.subset_by_dimension( 2 ); 1133  // the local should have all the vertices in local_verts 1134  for( Range::iterator it = local_q.begin(); it != local_q.end(); ++it ) 1135  { 1136  EntityHandle q = *it; 1137  int nnodes; 1138  const EntityHandle* conn4; 1139  rval = mb->get_connectivity( q, conn4, nnodes );ERRORR( rval, "can't get connectivity of local q " ); 1140  EntityHandle new_conn[MAXEDGES]; 1141  for( int i = 0; i < nnodes; i++ ) 1142  { 1143  EntityHandle v1 = conn4[i]; 1144  unsigned int index = local_verts.find( v1 ) - local_verts.begin(); 1145  int globalId = gids[index]; 1146  if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() ) 1147  { 1148  // we need to create that vertex, at this position dep_points 1149  double dp_pos[3] = { dep_points[3 * index], dep_points[3 * index + 1], dep_points[3 * index + 2] }; 1150  EntityHandle new_vert; 1151  rval = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " ); 1152  globalID_to_handle[globalId] = new_vert; 1153  } 1154  new_conn[i] = globalID_to_handle[gids[index]]; 1155  } 1156  EntityHandle new_element; 1157  // 1158  EntityType entType = MBQUAD; 1159  if( nnodes > 4 ) entType = MBPOLYGON; 1160  if( nnodes < 4 ) entType = MBTRI; 1161  1162  rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new quad " ); 1163  rval = mb->add_entities( covering_lagr_set, &new_element, 1 );ERRORR( rval, "can't add new element to dep set" ); 1164  int gid_el; 1165  // get the global ID of the initial quad 1166  rval = mb->tag_get_data( gid, &q, 1, &gid_el );ERRORR( rval, "can't get element global ID " ); 1167  globalID_to_eh[gid_el] = new_element; 1168  // is this redundant or not? 1169  rval = mb->tag_set_data( corrTag, &new_element, 1, &q );ERRORR( rval, "can't set corr tag on new el" ); 1170  // set the global id on new elem 1171  rval = mb->tag_set_data( gid, &new_element, 1, &gid_el );ERRORR( rval, "can't set global id tag on new el" ); 1172  } 1173  // now look at all elements received through; we do not want to duplicate them 1174  n = TLq.get_n(); // number of elements received by this processor 1175  // form the remote cells, that will be used to send the tracer info back to the originating proc 1176  remote_cells = new TupleList(); 1177  remote_cells->initialize( 2, 0, 1, 0, n ); // will not have tracer data anymore 1178  remote_cells->enableWriteAccess(); 1179  for( int i = 0; i < n; i++ ) 1180  { 1181  int globalIdEl = TLq.vi_rd[sizeTuple * i + 1]; 1182  int from_proc = TLq.vi_wr[sizeTuple * i]; 1183  // do we already have a quad with this global ID, represented? 1184  if( globalID_to_eh.find( globalIdEl ) == globalID_to_eh.end() ) 1185  { 1186  // construct the conn quad 1187  EntityHandle new_conn[MAXEDGES]; 1188  int nnodes = -1; 1189  for( int j = 0; j < max_edges_1; j++ ) 1190  { 1191  int vgid = TLq.vi_rd[sizeTuple * i + 2 + j]; // vertex global ID 1192  if( vgid == 0 ) 1193  new_conn[j] = 0; 1194  else 1195  { 1196  assert( globalID_to_handle.find( vgid ) != globalID_to_handle.end() ); 1197  new_conn[j] = globalID_to_handle[vgid]; 1198  nnodes = j + 1; // nodes are at the beginning, and are variable number 1199  } 1200  } 1201  EntityHandle new_element; 1202  // 1203  EntityType entType = MBQUAD; 1204  if( nnodes > 4 ) entType = MBPOLYGON; 1205  if( nnodes < 4 ) entType = MBTRI; 1206  rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new element " ); 1207  globalID_to_eh[globalIdEl] = new_element; 1208  rval = mb->add_entities( covering_lagr_set, &new_element, 1 );ERRORR( rval, "can't add new element to dep set" ); 1209  /* rval = mb->tag_set_data(corrTag, &new_element, 1, &q);ERRORR(rval, "can't set corr tag on new el");*/ 1210  remote_cells->vi_wr[2 * i] = from_proc; 1211  remote_cells->vi_wr[2 * i + 1] = globalIdEl; 1212  // remote_cells->vr_wr[i] = 0.; // no contribution yet sent back 1213  remote_cells->vul_wr[i] = TLq.vul_rd[i]; // this is the corresponding tgt cell (arrival) 1214  remote_cells->inc_n(); 1215  // set the global id on new elem 1216  rval = mb->tag_set_data( gid, &new_element, 1, &globalIdEl );ERRORR( rval, "can't set global id tag on new el" ); 1217  } 1218  } 1219  // order the remote cells tuple list, with the global id, because we will search in it 1220  // remote_cells->print("remote_cells before sorting"); 1221  moab::TupleList::buffer sort_buffer; 1222  sort_buffer.buffer_init( n ); 1223  remote_cells->sort( 1, &sort_buffer ); 1224  sort_buffer.reset(); 1225  return MB_SUCCESS; 1226 } 1227  1228 // this algorithm assumes lagr set is already created, and some elements will be coming from 1229 // other procs, and populate the covering_set 1230 // we need to keep in a tuple list the remote cells from other procs, because we need to send back 1231 // the intersection info (like area of the intx polygon, and the current concentration) maybe total 1232 // mass in that intx 1233 ErrorCode Intx2Mesh::create_departure_mesh_3rd_alg( EntityHandle& lagr_set, EntityHandle& covering_set ) 1234 { 1235  EntityHandle dum = 0; 1236  1237  Tag corrTag; 1238  ErrorCode rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum ); 1239  // start copy from 2nd alg 1240  // compute the bounding box on each proc 1241  assert( parcomm != NULL ); 1242  if( 1 == parcomm->proc_config().proc_size() ) 1243  { 1244  covering_set = lagr_set; // nothing to communicate, it must be serial 1245  return MB_SUCCESS; 1246  } 1247  1248  // get all local verts 1249  Range local_verts; 1250  rval = mb->get_connectivity( localEnts, local_verts ); 1251  int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" ); 1252  1253  std::vector< int > gids( num_local_verts ); 1254  rval = mb->tag_get_data( gid, local_verts, &gids[0] );ERRORR( rval, "can't get local vertices gids" ); 1255  1256  Range localDepCells; 1257  rval = mb->get_entities_by_dimension( lagr_set, 2, localDepCells );ERRORR( rval, "can't get ents by dimension from lagr set" ); 1258  1259  // get all lagr verts (departure vertices) 1260  Range lagr_verts; 1261  rval = mb->get_connectivity( localDepCells, lagr_verts ); // they should be created in 1262  // the same order as the euler vertices 1263  int num_lagr_verts = (int)lagr_verts.size();ERRORR( rval, "can't get local lagr vertices" ); 1264  1265  // now see the departure points position; to what boxes should we send them? 1266  std::vector< double > dep_points( 3 * num_lagr_verts ); 1267  rval = mb->get_coords( lagr_verts, &dep_points[0] );ERRORR( rval, "can't get departure points position" ); 1268  // ranges to send to each processor; will hold vertices and elements (quads?) 1269  // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances) 1270  std::map< int, Range > Rto; 1271  int numprocs = parcomm->proc_config().proc_size(); 1272  1273  for( Range::iterator eit = localDepCells.begin(); eit != localDepCells.end(); ++eit ) 1274  { 1275  EntityHandle q = *eit; 1276  const EntityHandle* conn4; 1277  int num_nodes; 1278  rval = mb->get_connectivity( q, conn4, num_nodes );ERRORR( rval, "can't get DP tag values" ); 1279  CartVect qbmin( std::numeric_limits< double >::max() ); 1280  CartVect qbmax( -std::numeric_limits< double >::max() ); 1281  for( int i = 0; i < num_nodes; i++ ) 1282  { 1283  EntityHandle v = conn4[i]; 1284  int index = lagr_verts.index( v ); 1285  assert( -1 != index ); 1286  CartVect dp( &dep_points[3 * index] ); // will use constructor 1287  for( int j = 0; j < 3; j++ ) 1288  { 1289  if( qbmin[j] > dp[j] ) qbmin[j] = dp[j]; 1290  if( qbmax[j] < dp[j] ) qbmax[j] = dp[j]; 1291  } 1292  } 1293  for( int p = 0; p < numprocs; p++ ) 1294  { 1295  CartVect bbmin( &allBoxes[6 * p] ); 1296  CartVect bbmax( &allBoxes[6 * p + 3] ); 1297  if( GeomUtil::boxes_overlap( bbmin, bbmax, qbmin, qbmax, box_error ) ) 1298  { 1299  Rto[p].insert( q ); 1300  } 1301  } 1302  } 1303  1304  // now, build TLv and TLq, for each p 1305  size_t numq = 0; 1306  size_t numv = 0; 1307  for( int p = 0; p < numprocs; p++ ) 1308  { 1309  if( p == (int)my_rank ) continue; // do not "send" it, because it is already here 1310  Range& range_to_P = Rto[p]; 1311  // add the vertices to it 1312  if( range_to_P.empty() ) continue; // nothing to send to proc p 1313  Range vertsToP; 1314  rval = mb->get_connectivity( range_to_P, vertsToP );ERRORR( rval, "can't get connectivity" ); 1315  numq = numq + range_to_P.size(); 1316  numv = numv + vertsToP.size(); 1317  range_to_P.merge( vertsToP ); 1318  } 1319  TupleList TLv; 1320  TupleList TLq; 1321  TLv.initialize( 2, 0, 0, 3, numv ); // to proc, GLOBAL ID, DP points 1322  TLv.enableWriteAccess(); 1323  1324  int sizeTuple = 2 + max_edges_1; // max edges could be up to MAXEDGES :) for polygons 1325  TLq.initialize( 2 + max_edges_1, 0, 1, 0, 1326  numq ); // to proc, elem GLOBAL ID, connectivity[max_edges] (global ID v) 1327  // send also the corresponding tgt cell it will come to 1328  TLq.enableWriteAccess(); 1329 #ifdef VERBOSE 1330  std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n"; 1331 #endif 1332  1333  for( int to_proc = 0; to_proc < numprocs; to_proc++ ) 1334  { 1335  if( to_proc == (int)my_rank ) continue; 1336  Range& range_to_P = Rto[to_proc]; 1337  Range V = range_to_P.subset_by_type( MBVERTEX ); 1338  1339  for( Range::iterator it = V.begin(); it != V.end(); ++it ) 1340  { 1341  EntityHandle v = *it; 1342  int index = lagr_verts.index( v ); // will be the same index as the corresponding vertex in euler verts 1343  assert( -1 != index ); 1344  int n = TLv.get_n(); 1345  TLv.vi_wr[2 * n] = to_proc; // send to processor 1346  TLv.vi_wr[2 * n + 1] = gids[index]; // global id needs index in the local_verts range 1347  TLv.vr_wr[3 * n] = dep_points[3 * index]; // departure position, of the node local_verts[i] 1348  TLv.vr_wr[3 * n + 1] = dep_points[3 * index + 1]; 1349  TLv.vr_wr[3 * n + 2] = dep_points[3 * index + 2]; 1350  TLv.inc_n(); 1351  } 1352  // also, prep the 2d cells for sending ... 1353  Range Q = range_to_P.subset_by_dimension( 2 ); 1354  for( Range::iterator it = Q.begin(); it != Q.end(); ++it ) 1355  { 1356  EntityHandle q = *it; // this is a src cell 1357  int global_id; 1358  rval = mb->tag_get_data( gid, &q, 1, &global_id );ERRORR( rval, "can't get gid for polygon" ); 1359  int n = TLq.get_n(); 1360  TLq.vi_wr[sizeTuple * n] = to_proc; // 1361  TLq.vi_wr[sizeTuple * n + 1] = global_id; // global id of element, used to identify it ... 1362  const EntityHandle* conn4; 1363  int num_nodes; 1364  rval = mb->get_connectivity( 1365  q, conn4, num_nodes ); // could be up to 10;ERRORR( rval, "can't get connectivity for quad" ); 1366  if( num_nodes > MAXEDGES ) ERRORR( MB_FAILURE, "too many nodes in a polygon" ); 1367  for( int i = 0; i < num_nodes; i++ ) 1368  { 1369  EntityHandle v = conn4[i]; 1370  int index = lagr_verts.index( v ); 1371  assert( -1 != index ); 1372  TLq.vi_wr[sizeTuple * n + 2 + i] = gids[index]; 1373  } 1374  for( int k = num_nodes; k < max_edges_1; k++ ) 1375  { 1376  TLq.vi_wr[sizeTuple * n + 2 + k] = 1377  0; // fill the rest of node ids with 0; we know that the node ids start from 1! 1378  } 1379  EntityHandle tgtCell; 1380  rval = mb->tag_get_data( corrTag, &q, 1, &tgtCell );ERRORR( rval, "can't get corresponding tgt cell for dep cell" ); 1381  TLq.vul_wr[n] = tgtCell; // this will be sent to remote_cells, to be able to come back 1382  TLq.inc_n(); 1383  } 1384  } 1385  // now we can route them to each processor 1386  // now we are done populating the tuples; route them to the appropriate processors 1387  ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 ); 1388  ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLq, 0 ); 1389  // the elements are already in localEnts; 1390  1391  // maps from global ids to new vertex and quad handles, that are added 1392  std::map< int, EntityHandle > globalID_to_handle; 1393  // we already have vertices from lagr set; they are already in the processor, even before 1394  // receiving other verts from neighbors 1395  int k = 0; 1396  for( Range::iterator vit = lagr_verts.begin(); vit != lagr_verts.end(); ++vit, k++ ) 1397  { 1398  globalID_to_handle[gids[k]] = *vit; // a little bit of overkill 1399  // we do know that the global ids between euler and lagr verts are parallel 1400  } 1401  /*std::map<int, EntityHandle> globalID_to_eh;*/ // do we need this one? 1402  globalID_to_eh.clear(); 1403  // now, look at every TLv, and see if we have to create a vertex there or not 1404  int n = TLv.get_n(); // the size of the points received 1405  for( int i = 0; i < n; i++ ) 1406  { 1407  int globalId = TLv.vi_rd[2 * i + 1]; 1408  if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() ) 1409  { 1410  EntityHandle new_vert; 1411  double dp_pos[3] = { TLv.vr_wr[3 * i], TLv.vr_wr[3 * i + 1], TLv.vr_wr[3 * i + 2] }; 1412  rval = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " ); 1413  globalID_to_handle[globalId] = new_vert; 1414  } 1415  } 1416  1417  // now, all dep points should be at their place 1418  // look in the local list of 2d cells for this proc, and create all those cells if needed 1419  // it may be an overkill, but because it does not involve communication, we do it anyway 1420  Range& local = Rto[my_rank]; 1421  Range local_q = local.subset_by_dimension( 2 ); 1422  // the local should have all the vertices in lagr_verts 1423  for( Range::iterator it = local_q.begin(); it != local_q.end(); ++it ) 1424  { 1425  EntityHandle q = *it; // these are from lagr cells, local 1426  int gid_el; 1427  rval = mb->tag_get_data( gid, &q, 1, &gid_el );ERRORR( rval, "can't get element global ID " ); 1428  globalID_to_eh[gid_el] = q; // do we need this? maybe to just mark the ones on this processor 1429  // maybe a range of global cell ids is fine? 1430  } 1431  // now look at all elements received through; we do not want to duplicate them 1432  n = TLq.get_n(); // number of elements received by this processor 1433  // a cell should be received from one proc only; so why are we so worried about duplicated 1434  // elements? a vertex can be received from multiple sources, that is fine 1435  1436  remote_cells = new TupleList(); 1437  remote_cells->initialize( 2, 0, 1, 0, n ); // no tracers anymore in these tuples 1438  remote_cells->enableWriteAccess(); 1439  for( int i = 0; i < n; i++ ) 1440  { 1441  int globalIdEl = TLq.vi_rd[sizeTuple * i + 1]; 1442  int from_proc = TLq.vi_rd[sizeTuple * i]; 1443  // do we already have a quad with this global ID, represented? 1444  if( globalID_to_eh.find( globalIdEl ) == globalID_to_eh.end() ) 1445  { 1446  // construct the conn quad 1447  EntityHandle new_conn[MAXEDGES]; 1448  int nnodes = -1; 1449  for( int j = 0; j < max_edges_1; j++ ) 1450  { 1451  int vgid = TLq.vi_rd[sizeTuple * i + 2 + j]; // vertex global ID 1452  if( vgid == 0 ) 1453  new_conn[j] = 0; 1454  else 1455  { 1456  assert( globalID_to_handle.find( vgid ) != globalID_to_handle.end() ); 1457  new_conn[j] = globalID_to_handle[vgid]; 1458  nnodes = j + 1; // nodes are at the beginning, and are variable number 1459  } 1460  } 1461  EntityHandle new_element; 1462  // 1463  EntityType entType = MBQUAD; 1464  if( nnodes > 4 ) entType = MBPOLYGON; 1465  if( nnodes < 4 ) entType = MBTRI; 1466  rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new element " ); 1467  globalID_to_eh[globalIdEl] = new_element; 1468  local_q.insert( new_element ); 1469  rval = mb->tag_set_data( gid, &new_element, 1, &globalIdEl );ERRORR( rval, "can't set gid on new element " ); 1470  } 1471  remote_cells->vi_wr[2 * i] = from_proc; 1472  remote_cells->vi_wr[2 * i + 1] = globalIdEl; 1473  // remote_cells->vr_wr[i] = 0.; will have a different tuple for communication 1474  remote_cells->vul_wr[i] = TLq.vul_rd[i]; // this is the corresponding tgt cell (arrival) 1475  remote_cells->inc_n(); 1476  } 1477  // now, create a new set, covering_set 1478  rval = mb->create_meshset( MESHSET_SET, covering_set );ERRORR( rval, "can't create new mesh set " ); 1479  rval = mb->add_entities( covering_set, local_q );ERRORR( rval, "can't add entities to new mesh set " ); 1480  // order the remote cells tuple list, with the global id, because we will search in it 1481  // remote_cells->print("remote_cells before sorting"); 1482  moab::TupleList::buffer sort_buffer; 1483  sort_buffer.buffer_init( n ); 1484  remote_cells->sort( 1, &sort_buffer ); 1485  sort_buffer.reset(); 1486  return MB_SUCCESS; 1487  // end copy 1488 } 1489  1490 ErrorCode Intx2Mesh::resolve_intersection_sharing() 1491 { 1492  if( parcomm && parcomm->size() > 1 ) 1493  { 1494  /* 1495  moab::ParallelMergeMesh pm(parcomm, epsilon_1); 1496  ErrorCode rval = pm.merge(outSet, false, 2); // resolve only the output set, do not skip 1497  local merge, use dim 2 ERRORR(rval, "can't merge intersection "); 1498  */ 1499  // look at non-owned shared vertices, that could be part of original source set 1500  // they should be removed from intx set reference, because they might not have a 1501  // correspondent on the other task 1502  Range nonOwnedVerts; 1503  Range vertsInIntx; 1504  Range intxCells; 1505  ErrorCode rval = mb->get_entities_by_dimension( outSet, 2, intxCells );MB_CHK_ERR( rval ); 1506  rval = mb->get_connectivity( intxCells, vertsInIntx );MB_CHK_ERR( rval ); 1507  1508  rval = parcomm->filter_pstatus( vertsInIntx, PSTATUS_NOT_OWNED, PSTATUS_AND, -1, &nonOwnedVerts );MB_CHK_ERR( rval ); 1509  1510  // some of these vertices can be in original set 1, which was covered, transported; 1511  // but they should not be "shared" from the intx point of view, because they are not shared 1512  // with another task they might have come from coverage as a plain vertex, so losing the 1513  // sharing property ? 1514  1515  Range coverVerts; 1516  rval = mb->get_connectivity( rs1, coverVerts );MB_CHK_ERR( rval ); 1517  // find out those that are on the interface 1518  Range vertsCovInterface; 1519  rval = parcomm->filter_pstatus( coverVerts, PSTATUS_INTERFACE, PSTATUS_AND, -1, &vertsCovInterface );MB_CHK_ERR( rval ); 1520  // how many of these are in 1521  Range nodesToDuplicate = intersect( vertsCovInterface, nonOwnedVerts ); 1522  // first, get all cells connected to these vertices, from intxCells 1523  1524  Range connectedCells; 1525  rval = mb->get_adjacencies( nodesToDuplicate, 2, false, connectedCells, Interface::UNION );MB_CHK_ERR( rval ); 1526  // only those in intx set: 1527  connectedCells = intersect( connectedCells, intxCells ); 1528  // first duplicate vertices in question: 1529  std::map< EntityHandle, EntityHandle > duplicatedVerticesMap; 1530  for( Range::iterator vit = nodesToDuplicate.begin(); vit != nodesToDuplicate.end(); vit++ ) 1531  { 1532  EntityHandle vertex = *vit; 1533  double coords[3]; 1534  rval = mb->get_coords( &vertex, 1, coords );MB_CHK_ERR( rval ); 1535  EntityHandle newVertex; 1536  rval = mb->create_vertex( coords, newVertex );MB_CHK_ERR( rval ); 1537  duplicatedVerticesMap[vertex] = newVertex; 1538  } 1539  1540  // look now at connectedCells, and change their connectivities: 1541  for( Range::iterator eit = connectedCells.begin(); eit != connectedCells.end(); eit++ ) 1542  { 1543  EntityHandle intxCell = *eit; 1544  // replace connectivity 1545  std::vector< EntityHandle > connectivity; 1546  rval = mb->get_connectivity( &intxCell, 1, connectivity );MB_CHK_ERR( rval ); 1547  for( size_t i = 0; i < connectivity.size(); i++ ) 1548  { 1549  EntityHandle currentVertex = connectivity[i]; 1550  std::map< EntityHandle, EntityHandle >::iterator mit = duplicatedVerticesMap.find( currentVertex ); 1551  if( mit != duplicatedVerticesMap.end() ) 1552  { 1553  connectivity[i] = mit->second; // replace connectivity directly 1554  } 1555  } 1556  int nnodes = (int)connectivity.size(); 1557  rval = mb->set_connectivity( intxCell, &connectivity[0], nnodes );MB_CHK_ERR( rval ); 1558  } 1559  } 1560  return MB_SUCCESS; 1561 } 1562 #endif /* MOAB_HAVE_MPI */ 1563 } /* namespace moab */