MOAB: Mesh Oriented datABase  (version 5.2.1)
Intx2Mesh.cpp
Go to the documentation of this file.
00001 /*
00002  * Intx2Mesh.cpp
00003  *
00004  *  Created on: Oct 2, 2012
00005  */
00006 
00007 #include "moab/IntxMesh/Intx2Mesh.hpp"
00008 #ifdef MOAB_HAVE_MPI
00009 #include "moab/ParallelComm.hpp"
00010 #include "MBParallelConventions.h"
00011 #include "moab/ParallelMergeMesh.hpp"
00012 #endif /* MOAB_HAVE_MPI */
00013 #include "MBTagConventions.hpp"
00014 // this is for DBL_MAX
00015 #include <cfloat>
00016 #include <queue>
00017 #include <sstream>
00018 #include "moab/GeomUtil.hpp"
00019 #include "moab/AdaptiveKDTree.hpp"
00020 
00021 namespace moab
00022 {
00023 
00024 #ifdef ENABLE_DEBUG
00025 int Intx2Mesh::dbg_1 = 0;
00026 #endif
00027 
00028 Intx2Mesh::Intx2Mesh( Interface* mbimpl )
00029     : mb( mbimpl ), mbs1( 0 ), mbs2( 0 ), outSet( 0 ), gid( 0 ), TgtFlagTag( 0 ), tgtParentTag( 0 ), srcParentTag( 0 ),
00030       countTag( 0 ), srcNeighTag( 0 ), tgtNeighTag( 0 ), neighTgtEdgeTag( 0 ), orgSendProcTag( 0 ), tgtConn( NULL ),
00031       srcConn( NULL ), epsilon_1( 0.0 ), epsilon_area( 0.0 ), box_error( 0.0 ), localRoot( 0 ), my_rank( 0 )
00032 #ifdef MOAB_HAVE_MPI
00033       ,
00034       parcomm( NULL ), remote_cells( NULL ), remote_cells_with_tracers( NULL )
00035 #endif
00036       ,
00037       max_edges_1( 0 ), max_edges_2( 0 ), counting( 0 )
00038 {
00039     gid = mbimpl->globalId_tag();
00040 }
00041 
00042 Intx2Mesh::~Intx2Mesh()
00043 {
00044     // TODO Auto-generated destructor stub
00045 #ifdef MOAB_HAVE_MPI
00046     if( remote_cells )
00047     {
00048         delete remote_cells;
00049         remote_cells = NULL;
00050     }
00051 #endif
00052 }
00053 ErrorCode Intx2Mesh::FindMaxEdgesInSet( EntityHandle eset, int& max_edges )
00054 {
00055     Range cells;
00056     ErrorCode rval = mb->get_entities_by_dimension( eset, 2, cells );MB_CHK_ERR( rval );
00057 
00058     max_edges = 0;  // can be 0 for point clouds
00059     for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ )
00060     {
00061         EntityHandle cell = *cit;
00062         const EntityHandle* conn4;
00063         int nnodes = 3;
00064         rval       = mb->get_connectivity( cell, conn4, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity of a cell" );
00065         if( nnodes > max_edges ) max_edges = nnodes;
00066     }
00067     // if in parallel, communicate the actual max_edges; it is not needed for tgt mesh (to be
00068     // global) but it is better to be consistent
00069 #ifdef MOAB_HAVE_MPI
00070     if( parcomm )
00071     {
00072         int local_max_edges = max_edges;
00073         // now reduce max_edges over all processors
00074         int mpi_err =
00075             MPI_Allreduce( &local_max_edges, &max_edges, 1, MPI_INT, MPI_MAX, parcomm->proc_config().proc_comm() );
00076         if( MPI_SUCCESS != mpi_err ) return MB_FAILURE;
00077     }
00078 #endif
00079 
00080     return MB_SUCCESS;
00081 }
00082 ErrorCode Intx2Mesh::FindMaxEdges( EntityHandle set1, EntityHandle set2 )
00083 {
00084     ErrorCode rval = FindMaxEdgesInSet( set1, max_edges_1 );MB_CHK_SET_ERR( rval, "can't determine max_edges in set 1" );
00085     rval = FindMaxEdgesInSet( set2, max_edges_2 );MB_CHK_SET_ERR( rval, "can't determine max_edges in set 2" );
00086 
00087     return MB_SUCCESS;
00088 }
00089 
00090 ErrorCode Intx2Mesh::createTags()
00091 {
00092     if( tgtParentTag ) mb->tag_delete( tgtParentTag );
00093     if( srcParentTag ) mb->tag_delete( srcParentTag );
00094     if( countTag ) mb->tag_delete( countTag );
00095 
00096     unsigned char def_data_bit = 0;  // unused by default
00097     // maybe the tgt tag is better to be deleted every time, and recreated;
00098     // or is it easy to set all values to something again? like 0?
00099     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" );
00100 
00101     // create tgt edges if they do not exist yet; so when they are looked upon, they are found
00102     // this is the only call that is potentially NlogN, in the whole method
00103     rval = mb->get_adjacencies( rs2, 1, true, TgtEdges, Interface::UNION );MB_CHK_SET_ERR( rval, "can't get adjacent tgt edges" );
00104 
00105     // now, create a map from each edge to a list of potential new nodes on a tgt edge
00106     // this memory has to be cleaned up
00107     // change it to a vector, and use the index in range of tgt edges
00108     int indx = 0;
00109     extraNodesVec.resize( TgtEdges.size() );
00110     for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, indx++ )
00111     {
00112         std::vector< EntityHandle >* nv = new std::vector< EntityHandle >;
00113         extraNodesVec[indx]             = nv;
00114     }
00115 
00116     int defaultInt = -1;
00117 
00118     rval = mb->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag, MB_TAG_DENSE | MB_TAG_CREAT,
00119                                &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" );
00120 
00121     rval = mb->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag, MB_TAG_DENSE | MB_TAG_CREAT,
00122                                &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" );
00123 
00124     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" );
00125 
00126     // for each cell in set 1, determine its neigh in set 1 (could be null too)
00127     // for each cell in set 2, determine its neigh in set 2 (if on boundary, could be 0)
00128     rval = DetermineOrderedNeighbors( mbs1, max_edges_1, srcNeighTag );MB_CHK_SET_ERR( rval, "can't determine neighbors for set 1" );
00129     rval = DetermineOrderedNeighbors( mbs2, max_edges_2, tgtNeighTag );MB_CHK_SET_ERR( rval, "can't determine neighbors for set 2" );
00130 
00131     // for tgt cells, save a dense tag with the bordering edges, so we do not have to search for
00132     // them each time edges were for sure created before (tgtEdges)
00133     std::vector< EntityHandle > zeroh( max_edges_2, 0 );
00134     // if we have a tag with this name, it could be of a different size, so delete it
00135     rval = mb->tag_get_handle( "__tgtEdgeNeighbors", neighTgtEdgeTag );
00136     if( rval == MB_SUCCESS && neighTgtEdgeTag ) mb->tag_delete( neighTgtEdgeTag );
00137     rval = mb->tag_get_handle( "__tgtEdgeNeighbors", max_edges_2, MB_TYPE_HANDLE, neighTgtEdgeTag,
00138                                MB_TAG_DENSE | MB_TAG_CREAT, &zeroh[0] );MB_CHK_SET_ERR( rval, "can't create tgt edge neighbors tag" );
00139     for( Range::iterator rit = rs2.begin(); rit != rs2.end(); rit++ )
00140     {
00141         EntityHandle tgtCell = *rit;
00142         int num_nodes        = 0;
00143         rval                 = mb->get_connectivity( tgtCell, tgtConn, num_nodes );MB_CHK_SET_ERR( rval, "can't get  tgt conn" );
00144         // account for padded polygons
00145         while( tgtConn[num_nodes - 2] == tgtConn[num_nodes - 1] && num_nodes > 3 )
00146             num_nodes--;
00147 
00148         int i = 0;
00149         for( i = 0; i < num_nodes; i++ )
00150         {
00151             EntityHandle v[2] = { tgtConn[i],
00152                                   tgtConn[( i + 1 ) % num_nodes] };  // this is fine even for padded polygons
00153             std::vector< EntityHandle > adj_entities;
00154             rval = mb->get_adjacencies( v, 2, 1, false, adj_entities, Interface::INTERSECT );
00155             if( rval != MB_SUCCESS || adj_entities.size() < 1 ) return rval;  // get out , big error
00156             zeroh[i] = adj_entities[0];                                       // should be only one edge between 2 nodes
00157             // also, even if number of edges is less than max_edges_2, they will be ignored, even if
00158             // the tag is dense
00159         }
00160         // now set the value of the tag
00161         rval = mb->tag_set_data( neighTgtEdgeTag, &tgtCell, 1, &( zeroh[0] ) );MB_CHK_SET_ERR( rval, "can't set edge tgt tag" );
00162     }
00163     return MB_SUCCESS;
00164 }
00165 
00166 ErrorCode Intx2Mesh::DetermineOrderedNeighbors( EntityHandle inputSet, int max_edges, Tag& neighTag )
00167 {
00168     Range cells;
00169     ErrorCode rval = mb->get_entities_by_dimension( inputSet, 2, cells );MB_CHK_SET_ERR( rval, "can't get cells in set" );
00170 
00171     std::vector< EntityHandle > neighbors( max_edges );
00172     std::vector< EntityHandle > zeroh( max_edges, 0 );
00173     // nameless tag, as the name is not important; we will have 2 related tags, but one on tgt mesh,
00174     // one on src mesh
00175     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" );
00176 
00177     for( Range::iterator cit = cells.begin(); cit != cells.end(); cit++ )
00178     {
00179         EntityHandle cell = *cit;
00180         int nnodes        = 3;
00181         // will get the nnodes ordered neighbors;
00182         // first cell is for nodes 0, 1, second to 1, 2, third to 2, 3, last to nnodes-1,
00183         const EntityHandle* conn4;
00184         rval = mb->get_connectivity( cell, conn4, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity of a cell" );
00185         int nsides = nnodes;
00186         // account for possible padded polygons
00187         while( conn4[nsides - 2] == conn4[nsides - 1] && nsides > 3 )
00188             nsides--;
00189 
00190         for( int i = 0; i < nsides; i++ )
00191         {
00192             EntityHandle v[2];
00193             v[0] = conn4[i];
00194             v[1] = conn4[( i + 1 ) % nsides];
00195             // get all cells adjacent to these 2 vertices on the edge
00196             std::vector< EntityHandle > adjcells;
00197             std::vector< EntityHandle > cellsInSet;
00198             rval = mb->get_adjacencies( v, 2, 2, false, adjcells, Interface::INTERSECT );MB_CHK_SET_ERR( rval, "can't adjacency to 2 verts" );
00199             // now look for the cells contained in the input set;
00200             // the input set should be a correct mesh, not overlapping cells, and manifold
00201             size_t siz = adjcells.size();
00202             for( size_t j = 0; j < siz; j++ )
00203                 if( mb->contains_entities( inputSet, &( adjcells[j] ), 1 ) ) cellsInSet.push_back( adjcells[j] );
00204             siz = cellsInSet.size();
00205 
00206             if( siz > 2 )
00207             {
00208                 std::cout << "non manifold mesh, error" << mb->list_entities( &( cellsInSet[0] ), cellsInSet.size() )
00209                           << "\n";MB_CHK_SET_ERR( MB_FAILURE, "non-manifold input mesh set" );  // non-manifold
00210             }
00211             if( siz == 1 )
00212             {
00213                 // it must be the border of the input mesh;
00214                 neighbors[i] = 0;  // we are guaranteed that ids are !=0; this is marking a border
00215                 // borders do not appear for a sphere in serial, but they do appear for
00216                 // parallel processing anyway
00217                 continue;
00218             }
00219             // here siz ==2, it is either the first or second
00220             if( cell == cellsInSet[0] )
00221                 neighbors[i] = cellsInSet[1];
00222             else
00223                 neighbors[i] = cellsInSet[0];
00224         }
00225         // fill the rest with 0
00226         for( int i = nsides; i < max_edges; i++ )
00227             neighbors[i] = 0;
00228         // now simply set the neighbors tag; the last few positions will not be used, but for
00229         // simplicity will keep them all (MAXEDGES)
00230         rval = mb->tag_set_data( neighTag, &cell, 1, &neighbors[0] );MB_CHK_SET_ERR( rval, "can't set neigh tag" );
00231     }
00232     return MB_SUCCESS;
00233 }
00234 
00235 // slow interface; this will not do the advancing front trick
00236 // some are triangles, some are quads, some are polygons ...
00237 ErrorCode Intx2Mesh::intersect_meshes_kdtree( EntityHandle mbset1, EntityHandle mbset2, EntityHandle& outputSet )
00238 {
00239     ErrorCode rval;
00240     mbs1   = mbset1;  // set 1 is departure, and it is completely covering the euler set on proc
00241     mbs2   = mbset2;
00242     outSet = outputSet;
00243     rval   = mb->get_entities_by_dimension( mbs1, 2, rs1 );MB_CHK_ERR( rval );
00244     rval = mb->get_entities_by_dimension( mbs2, 2, rs2 );MB_CHK_ERR( rval );
00245     // from create tags, copy relevant ones
00246     if( tgtParentTag ) mb->tag_delete( tgtParentTag );
00247     if( srcParentTag ) mb->tag_delete( srcParentTag );
00248     if( countTag ) mb->tag_delete( countTag );
00249 
00250     // create tgt edges if they do not exist yet; so when they are looked upon, they are found
00251     // this is the only call that is potentially NlogN, in the whole method
00252     rval = mb->get_adjacencies( rs2, 1, true, TgtEdges, Interface::UNION );MB_CHK_SET_ERR( rval, "can't get adjacent tgt edges" );
00253 
00254     int indx = 0;
00255     extraNodesVec.resize( TgtEdges.size() );
00256     for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, indx++ )
00257     {
00258         std::vector< EntityHandle >* nv = new std::vector< EntityHandle >;
00259         extraNodesVec[indx]             = nv;
00260     }
00261 
00262     int defaultInt = -1;
00263 
00264     rval = mb->tag_get_handle( "TargetParent", 1, MB_TYPE_INTEGER, tgtParentTag, MB_TAG_DENSE | MB_TAG_CREAT,
00265                                &defaultInt );MB_CHK_SET_ERR( rval, "can't create positive tag" );
00266 
00267     rval = mb->tag_get_handle( "SourceParent", 1, MB_TYPE_INTEGER, srcParentTag, MB_TAG_DENSE | MB_TAG_CREAT,
00268                                &defaultInt );MB_CHK_SET_ERR( rval, "can't create negative tag" );
00269 
00270     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" );
00271 
00272     // for tgt cells, save a dense tag with the bordering edges, so we do not have to search for
00273     // them each time edges were for sure created before (tgtEdges)
00274     // if we have a tag with this name, it could be of a different size, so delete it
00275     rval = mb->tag_get_handle( "__tgtEdgeNeighbors", neighTgtEdgeTag );
00276     if( rval == MB_SUCCESS && neighTgtEdgeTag ) mb->tag_delete( neighTgtEdgeTag );
00277     std::vector< EntityHandle > zeroh( max_edges_2, 0 );
00278     rval = mb->tag_get_handle( "__tgtEdgeNeighbors", max_edges_2, MB_TYPE_HANDLE, neighTgtEdgeTag,
00279                                MB_TAG_DENSE | MB_TAG_CREAT, &zeroh[0] );MB_CHK_SET_ERR( rval, "can't create tgt edge neighbors tag" );
00280     for( Range::iterator rit = rs2.begin(); rit != rs2.end(); rit++ )
00281     {
00282         EntityHandle tgtCell = *rit;
00283         int num_nodes        = 0;
00284         rval                 = mb->get_connectivity( tgtCell, tgtConn, num_nodes );MB_CHK_SET_ERR( rval, "can't get  tgt conn" );
00285         // account for padded polygons
00286         while( tgtConn[num_nodes - 2] == tgtConn[num_nodes - 1] && num_nodes > 3 )
00287             num_nodes--;
00288 
00289         int i = 0;
00290         for( i = 0; i < num_nodes; i++ )
00291         {
00292             EntityHandle v[2] = { tgtConn[i],
00293                                   tgtConn[( i + 1 ) % num_nodes] };  // this is fine even for padded polygons
00294             std::vector< EntityHandle > adj_entities;
00295             rval = mb->get_adjacencies( v, 2, 1, false, adj_entities, Interface::INTERSECT );
00296             if( rval != MB_SUCCESS || adj_entities.size() < 1 ) return rval;  // get out , big error
00297             zeroh[i] = adj_entities[0];                                       // should be only one edge between 2 nodes
00298             // also, even if number of edges is less than max_edges_2, they will be ignored, even if
00299             // the tag is dense
00300         }
00301         // now set the value of the tag
00302         rval = mb->tag_set_data( neighTgtEdgeTag, &tgtCell, 1, &( zeroh[0] ) );MB_CHK_SET_ERR( rval, "can't set edge tgt tag" );
00303     }
00304 
00305     // create the kd tree on source cells, and intersect all targets in an expensive loop
00306     // build a kd tree with the rs1 (source) cells
00307     AdaptiveKDTree kd( mb );
00308     EntityHandle tree_root = 0;
00309     rval                   = kd.build_tree( rs1, &tree_root );MB_CHK_ERR( rval );
00310 
00311     // find out max edge on source mesh;
00312     double max_length = 0;
00313     {
00314         std::vector< double > coords;
00315         coords.resize( 3 * max_edges_1 );
00316         for( Range::iterator it = rs1.begin(); it != rs1.end(); it++ )
00317         {
00318             const EntityHandle* conn = NULL;
00319             int nnodes;
00320             rval = mb->get_connectivity( *it, conn, nnodes );MB_CHK_SET_ERR( rval, "can't get connectivity" );
00321             while( conn[nnodes - 2] == conn[nnodes - 1] && nnodes > 3 )
00322                 nnodes--;
00323             rval = mb->get_coords( conn, nnodes, &coords[0] );MB_CHK_SET_ERR( rval, "can't get coordinates" );
00324             for( int j = 0; j < nnodes; j++ )
00325             {
00326                 int next = ( j + 1 ) % nnodes;
00327                 double leng;
00328                 leng = ( coords[3 * j] - coords[3 * next] ) * ( coords[3 * j] - coords[3 * next] ) +
00329                        ( coords[3 * j + 1] - coords[3 * next + 1] ) * ( coords[3 * j + 1] - coords[3 * next + 1] ) +
00330                        ( coords[3 * j + 2] - coords[3 * next + 2] ) * ( coords[3 * j + 2] - coords[3 * next + 2] );
00331                 leng = sqrt( leng );
00332                 if( leng > max_length ) max_length = leng;
00333             }
00334         }
00335     }
00336     // maximum sag on a spherical mesh make sense only for intx on a sphere, with radius 1 :(
00337     double tolerance = 1.e-15;
00338     if( max_length < 1. )
00339     {
00340         // basically, the sag for an arc of length max_length on a circle of radius 1
00341         tolerance = 1. - sqrt( 1 - max_length * max_length / 4 );
00342         if (box_error < tolerance)
00343             box_error = tolerance;
00344         tolerance = 3 * tolerance;  // we use it for gnomonic plane too, projected sag could be =* sqrt(2.)
00345         // be more generous, use 1.5 ~= sqrt(2.)
00346 
00347         if( !my_rank )
00348         {
00349             std::cout << " max edge length: " << max_length << "  tolerance for kd tree: " << tolerance << "\n";
00350             std::cout << " box overlap tolerance: " << box_error << "\n";
00351         }
00352 
00353     }
00354     for( Range::iterator it = rs2.begin(); it != rs2.end(); ++it )
00355     {
00356         EntityHandle tcell = *it;
00357         // find vertex positions
00358         const EntityHandle* conn = NULL;
00359         int nnodes               = 0;
00360         rval                     = mb->get_connectivity( tcell, conn, nnodes );MB_CHK_ERR( rval );
00361         // find leaves close to those positions
00362         double areaTgtCell   = setup_tgt_cell( tcell, nnodes );  // this is the area in the gnomonic plane
00363         double recoveredArea = 0;
00364         std::vector< double > positions;
00365         positions.resize( nnodes * 3 );
00366         rval = mb->get_coords( conn, nnodes, &positions[0] );MB_CHK_ERR( rval );
00367 
00368         // distance to search will be based on average edge length
00369         double av_len = 0;
00370         for( int k = 0; k < nnodes; k++ )
00371         {
00372             int ik      = ( k + 1 ) % nnodes;
00373             double len1 = 0;
00374             for( int j = 0; j < 3; j++ )
00375             {
00376                 double len2 = positions[3 * k + j] - positions[3 * ik + j];
00377                 len1 += len2 * len2;
00378             }
00379             av_len += sqrt( len1 );
00380         }
00381         if( nnodes > 0 ) av_len /= nnodes;
00382         // find leaves within a distance from each vertex of target
00383         // in those leaves, collect all cells; we will try for an intx in there
00384         Range close_source_cells;
00385         std::vector< EntityHandle > leaves;
00386         for( int i = 0; i < nnodes; i++ )
00387         {
00388 
00389             leaves.clear();
00390             rval = kd.distance_search( &positions[3 * i], av_len, leaves, tolerance, epsilon_1 );MB_CHK_ERR( rval );
00391 
00392             for( std::vector< EntityHandle >::iterator j = leaves.begin(); j != leaves.end(); ++j )
00393             {
00394                 Range tmp;
00395                 rval = mb->get_entities_by_dimension( *j, 2, tmp );MB_CHK_ERR( rval );
00396 
00397                 close_source_cells.merge( tmp.begin(), tmp.end() );
00398             }
00399         }
00400 #ifdef VERBOSE
00401         if( close_source_cells.empty() )
00402         {
00403             std::cout << " there are no close source cells to target cell " << tcell << " id from handle "
00404                       << mb->id_from_handle( tcell ) << "\n";
00405         }
00406 #endif
00407         for( Range::iterator it2 = close_source_cells.begin(); it2 != close_source_cells.end(); ++it2 )
00408         {
00409             EntityHandle startSrc = *it2;
00410             double area           = 0;
00411             // if area is > 0 , we have intersections
00412             double P[10 * MAXEDGES];  // max 8 intx points + 8 more in the polygon
00413             //
00414             int nP = 0;
00415             int nb[MAXEDGES], nr[MAXEDGES];  // sides 3 or 4? also, check boxes first
00416             int nsTgt, nsSrc;
00417             rval = computeIntersectionBetweenTgtAndSrc( tcell, startSrc, P, nP, area, nb, nr, nsSrc, nsTgt, true );MB_CHK_ERR( rval );
00418             if( area > 0 )
00419             {
00420                 if( nP > 1 )
00421                 {  // this will also construct triangles/polygons in the new mesh, if needed
00422                     rval = findNodes( tcell, nnodes, startSrc, nsSrc, P, nP );MB_CHK_ERR( rval );
00423                 }
00424                 recoveredArea += area;
00425             }
00426         }
00427         recoveredArea = ( recoveredArea - areaTgtCell ) / areaTgtCell;  // replace now with recovery fract
00428     }
00429     // before cleaning up , we need to settle the position of the intersection points
00430     // on the boundary edges
00431     // this needs to be collective, so we should maybe wait something
00432 #ifdef MOAB_HAVE_MPI
00433     rval = resolve_intersection_sharing();MB_CHK_SET_ERR( rval, "can't correct position, Intx2Mesh.cpp \n" );
00434 #endif
00435 
00436     this->clean();
00437     return MB_SUCCESS;
00438 }
00439 // main interface; this will do the advancing front trick
00440 // some are triangles, some are quads, some are polygons ...
00441 ErrorCode Intx2Mesh::intersect_meshes( EntityHandle mbset1, EntityHandle mbset2, EntityHandle& outputSet )
00442 {
00443     ErrorCode rval;
00444     mbs1   = mbset1;  // set 1 is departure, and it is completely covering the euler set on proc
00445     mbs2   = mbset2;
00446     outSet = outputSet;
00447 #ifdef VERBOSE
00448     std::stringstream ffs, fft;
00449     ffs << "source_rank0" << my_rank << ".vtk";
00450     rval = mb->write_mesh( ffs.str().c_str(), &mbset1, 1 );MB_CHK_ERR( rval );
00451     fft << "target_rank0" << my_rank << ".vtk";
00452     rval = mb->write_mesh( fft.str().c_str(), &mbset2, 1 );MB_CHK_ERR( rval );
00453 
00454 #endif
00455     // really, should be something from t1 and t2; src is 1 (lagrange), tgt is 2 (euler)
00456 
00457     EntityHandle startSrc = 0, startTgt = 0;
00458 
00459     rval = mb->get_entities_by_dimension( mbs1, 2, rs1 );MB_CHK_ERR( rval );
00460     rval = mb->get_entities_by_dimension( mbs2, 2, rs2 );MB_CHK_ERR( rval );
00461     // std::cout << "rs1.size() = " << rs1.size() << " and rs2.size() = "  << rs2.size() << "\n";
00462     // std::cout.flush();
00463 
00464     createTags();  // will also determine max_edges_1, max_edges_2 (for src and tgt meshes)
00465 
00466     Range rs22 = rs2;  // a copy of the initial range; we will remove from it elements as we
00467                        // advance ; rs2 is needed for marking the polygon to the tgt parent
00468 
00469     // create the local kdd tree with source elements; will use it to search
00470     // more efficiently for the seeds in advancing front;
00471     // some of the target cells will not be covered by source cells, and they need to be eliminated
00472     // early from contention
00473 
00474     // build a kd tree with the rs1 (source) cells
00475     AdaptiveKDTree kd( mb );
00476     EntityHandle tree_root = 0;
00477     rval                   = kd.build_tree( rs1, &tree_root );MB_CHK_ERR( rval );
00478 
00479     while( !rs22.empty() )
00480     {
00481 #if defined( ENABLE_DEBUG ) || defined( VERBOSE )
00482         if( rs22.size() < rs2.size() )
00483         {
00484             std::cout << " possible not connected arrival mesh; my_rank: " << my_rank << " counting: " << counting
00485                       << "\n";
00486             std::stringstream ffo;
00487             ffo << "file0" << counting << "rank0" << my_rank << ".vtk";
00488             rval = mb->write_mesh( ffo.str().c_str(), &outSet, 1 );MB_CHK_ERR( rval );
00489         }
00490 #endif
00491         bool seedFound = false;
00492         for( Range::iterator it = rs22.begin(); it != rs22.end(); ++it )
00493         {
00494             startTgt  = *it;
00495             int found = 0;
00496             // find vertex positions
00497             const EntityHandle* conn = NULL;
00498             int nnodes               = 0;
00499             rval                     = mb->get_connectivity( startTgt, conn, nnodes );MB_CHK_ERR( rval );
00500             // find leaves close to those positions
00501             std::vector< double > positions;
00502             positions.resize( nnodes * 3 );
00503             rval = mb->get_coords( conn, nnodes, &positions[0] );MB_CHK_ERR( rval );
00504             // find leaves within a distance from each vertex of target
00505             // in those leaves, collect all cells; we will try for an intx in there, instead of
00506             // looping over all rs1 cells, as before
00507             Range close_source_cells;
00508             std::vector< EntityHandle > leaves;
00509             for( int i = 0; i < nnodes; i++ )
00510             {
00511 
00512                 leaves.clear();
00513                 rval = kd.distance_search( &positions[3 * i], epsilon_1, leaves, epsilon_1, epsilon_1 );MB_CHK_ERR( rval );
00514 
00515                 for( std::vector< EntityHandle >::iterator j = leaves.begin(); j != leaves.end(); ++j )
00516                 {
00517                     Range tmp;
00518                     rval = mb->get_entities_by_dimension( *j, 2, tmp );MB_CHK_ERR( rval );
00519 
00520                     close_source_cells.merge( tmp.begin(), tmp.end() );
00521                 }
00522             }
00523 
00524             for( Range::iterator it2 = close_source_cells.begin(); it2 != close_source_cells.end() && !found; ++it2 )
00525             {
00526                 startSrc    = *it2;
00527                 double area = 0;
00528                 // if area is > 0 , we have intersections
00529                 double P[10 * MAXEDGES];  // max 8 intx points + 8 more in the polygon
00530                 //
00531                 int nP = 0;
00532                 int nb[MAXEDGES], nr[MAXEDGES];  // sides 3 or 4? also, check boxes first
00533                 int nsTgt, nsSrc;
00534                 rval =
00535                     computeIntersectionBetweenTgtAndSrc( startTgt, startSrc, P, nP, area, nb, nr, nsSrc, nsTgt, true );MB_CHK_ERR( rval );
00536                 if( area > 0 )
00537                 {
00538                     found     = 1;
00539                     seedFound = true;
00540                     break;  // found 2 elements that intersect; these will be the seeds
00541                 }
00542             }
00543             if( found )
00544                 break;
00545             else
00546             {
00547 #if defined( VERBOSE )
00548                 std::cout << " on rank " << my_rank << " target cell " << ID_FROM_HANDLE( startTgt )
00549                           << " not intx with any source\n";
00550 #endif
00551                 rs22.erase( startTgt );
00552             }
00553         }
00554         if( !seedFound ) continue;  // continue while(!rs22.empty())
00555 
00556         std::queue< EntityHandle > srcQueue;  // these are corresponding to Ta,
00557         srcQueue.push( startSrc );
00558         std::queue< EntityHandle > tgtQueue;
00559         tgtQueue.push( startTgt );
00560 
00561         Range toResetSrcs;  // will be used to reset src flags for every tgt quad
00562         // processed
00563 
00564         /*if (my_rank==0)
00565           dbg_1 = 1;*/
00566         unsigned char used = 1;
00567         // mark the start tgt quad as used, so it will not come back again
00568         rval = mb->tag_set_data( TgtFlagTag, &startTgt, 1, &used );MB_CHK_ERR( rval );
00569         while( !tgtQueue.empty() )
00570         {
00571             // flags for the side : 0 means a src cell not found on side
00572             // a paired src not found yet for the neighbors of tgt
00573             Range nextSrc[MAXEDGES];  // there are new ranges of possible next src cells for
00574                                       // seeding the side j of tgt cell
00575 
00576             EntityHandle currentTgt = tgtQueue.front();
00577             tgtQueue.pop();
00578             int nsidesTgt;                                                   // will be initialized now
00579             double areaTgtCell   = setup_tgt_cell( currentTgt, nsidesTgt );  // this is the area in the gnomonic plane
00580             double recoveredArea = 0;
00581             // get the neighbors of tgt, and if they are solved already, do not bother with that
00582             // side of tgt
00583             EntityHandle tgtNeighbors[MAXEDGES] = { 0 };
00584             rval                                = mb->tag_get_data( tgtNeighTag, &currentTgt, 1, tgtNeighbors );MB_CHK_SET_ERR( rval, "can't get neighbors of current tgt" );
00585 #ifdef ENABLE_DEBUG
00586             if( dbg_1 )
00587             {
00588                 std::cout << "Next: neighbors for current tgt ";
00589                 for( int kk = 0; kk < nsidesTgt; kk++ )
00590                 {
00591                     if( tgtNeighbors[kk] > 0 )
00592                         std::cout << mb->id_from_handle( tgtNeighbors[kk] ) << " ";
00593                     else
00594                         std::cout << 0 << " ";
00595                 }
00596                 std::cout << std::endl;
00597             }
00598 #endif
00599             // now get the status of neighbors; if already solved, make them 0, so not to bother
00600             // anymore on that side of tgt
00601             for( int j = 0; j < nsidesTgt; j++ )
00602             {
00603                 EntityHandle tgtNeigh = tgtNeighbors[j];
00604                 unsigned char status  = 1;
00605                 if( tgtNeigh == 0 ) continue;
00606                 rval = mb->tag_get_data( TgtFlagTag, &tgtNeigh, 1, &status );MB_CHK_ERR( rval );                     // status 0 is unused
00607                 if( 1 == status ) tgtNeighbors[j] = 0;  // so will not look anymore on this side of tgt
00608             }
00609 
00610 #ifdef ENABLE_DEBUG
00611             if( dbg_1 )
00612             {
00613                 std::cout << "reset sources: ";
00614                 for( Range::iterator itr = toResetSrcs.begin(); itr != toResetSrcs.end(); ++itr )
00615                     std::cout << mb->id_from_handle( *itr ) << " ";
00616                 std::cout << std::endl;
00617             }
00618 #endif
00619             EntityHandle currentSrc = srcQueue.front();
00620             // tgt and src queues are parallel; for clarity we should have kept in the queue pairs
00621             // of entity handle std::pair<EntityHandle, EntityHandle>; so just one queue, with
00622             // pairs;
00623             //  at every moment, the queue contains pairs of cells that intersect, and they form the
00624             //  "advancing front"
00625             srcQueue.pop();
00626             toResetSrcs.clear();  // empty the range of used srcs, will have to be set unused again,
00627             // at the end of tgt element processing
00628             toResetSrcs.insert( currentSrc );
00629             // mb2->set_tag_data
00630             std::queue< EntityHandle > localSrc;
00631             localSrc.push( currentSrc );
00632 #ifdef VERBOSE
00633             int countingStart = counting;
00634 #endif
00635             // will advance-front search in the neighborhood of tgt cell, until we finish processing
00636             // all
00637             //   possible src cells; localSrc queue will contain all possible src cells that cover
00638             //   the current tgt cell
00639             while( !localSrc.empty() )
00640             {
00641                 //
00642                 EntityHandle srcT = localSrc.front();
00643                 localSrc.pop();
00644                 double P[10 * MAXEDGES], area;  //
00645                 int nP           = 0;
00646                 int nb[MAXEDGES] = { 0 };
00647                 int nr[MAXEDGES] = { 0 };
00648 
00649                 int nsidesSrc;  ///
00650                 // area is in 2d, points are in 3d (on a sphere), back-projected, or in a plane
00651                 // intersection points could include the vertices of initial elements
00652                 // nb [j] = 0 means no intersection on the side j for element src (markers)
00653                 // nb [j] = 1 means that the side j (from j to j+1) of src poly intersects the
00654                 // tgt poly.  A potential next poly in the tgt queue is the tgt poly that is
00655                 // adjacent to this side
00656                 rval = computeIntersectionBetweenTgtAndSrc( /* tgt */ currentTgt, srcT, P, nP, area, nb, nr, nsidesSrc,
00657                                                             nsidesTgt );MB_CHK_ERR( rval );
00658                 if( nP > 0 )
00659                 {
00660 #ifdef ENABLE_DEBUG
00661                     if( dbg_1 )
00662                     {
00663                         for( int k = 0; k < 3; k++ )
00664                         {
00665                             std::cout << " nb, nr: " << k << " " << nb[k] << " " << nr[k] << "\n";
00666                         }
00667                     }
00668 #endif
00669 
00670                     // intersection found: output P and original triangles if nP > 2
00671                     EntityHandle neighbors[MAXEDGES] = { 0 };
00672                     rval                             = mb->tag_get_data( srcNeighTag, &srcT, 1, neighbors );
00673                     if( rval != MB_SUCCESS )
00674                     {
00675                         std::cout << " can't get the neighbors for src element " << mb->id_from_handle( srcT );
00676                         return MB_FAILURE;
00677                     }
00678 
00679                     // add neighbors to the localSrc queue, if they are not marked
00680                     for( int nn = 0; nn < nsidesSrc; nn++ )
00681                     {
00682                         EntityHandle neighbor = neighbors[nn];
00683                         if( neighbor > 0 && nb[nn] > 0 )  // advance across src boundary nn
00684                         {
00685                             if( toResetSrcs.find( neighbor ) == toResetSrcs.end() )
00686                             {
00687                                 localSrc.push( neighbor );
00688 #ifdef ENABLE_DEBUG
00689                                 if( dbg_1 )
00690                                 {
00691                                     std::cout << " local src elem " << mb->id_from_handle( neighbor )
00692                                               << " for tgt:" << mb->id_from_handle( currentTgt ) << "\n";
00693                                     mb->list_entities( &neighbor, 1 );
00694                                 }
00695 #endif
00696                                 toResetSrcs.insert( neighbor );
00697                             }
00698                         }
00699                     }
00700                     // n(find(nc>0))=ac;        % ac is starting candidate for neighbor
00701                     for( int nn = 0; nn < nsidesTgt; nn++ )
00702                     {
00703                         if( nr[nn] > 0 && tgtNeighbors[nn] > 0 )
00704                             nextSrc[nn].insert( srcT );  // potential src cell that can intersect
00705                                                          // the tgt neighbor nn
00706                     }
00707                     if( nP > 1 )
00708                     {  // this will also construct triangles/polygons in the new mesh, if needed
00709                         rval = findNodes( currentTgt, nsidesTgt, srcT, nsidesSrc, P, nP );MB_CHK_ERR( rval );
00710                     }
00711 
00712                     recoveredArea += area;
00713                 }
00714 #ifdef ENABLE_DEBUG
00715                 else if( dbg_1 )
00716                 {
00717                     std::cout << " tgt, src, do not intersect: " << mb->id_from_handle( currentTgt ) << " "
00718                               << mb->id_from_handle( srcT ) << "\n";
00719                 }
00720 #endif
00721             }                                                               // end while (!localSrc.empty())
00722             recoveredArea = ( recoveredArea - areaTgtCell ) / areaTgtCell;  // replace now with recovery fraction
00723 #if defined( ENABLE_DEBUG ) || defined( VERBOSE )
00724             if( fabs( recoveredArea ) > epsilon_1 )
00725             {
00726 #ifdef VERBOSE
00727                 std::cout << " tgt area: " << areaTgtCell << " recovered :" << recoveredArea * ( 1 + areaTgtCell )
00728                           << " fraction error recovery:" << recoveredArea
00729                           << " tgtID: " << mb->id_from_handle( currentTgt ) << " countingStart:" << countingStart
00730                           << "\n";
00731 #endif
00732             }
00733 #endif
00734             // here, we are finished with tgtCurrent, take it out of the rs22 range (tgt, arrival
00735             // mesh)
00736             rs22.erase( currentTgt );
00737             // also, look at its neighbors, and add to the seeds a next one
00738 
00739             for( int j = 0; j < nsidesTgt; j++ )
00740             {
00741                 EntityHandle tgtNeigh = tgtNeighbors[j];
00742                 if( tgtNeigh == 0 || nextSrc[j].size() == 0 )  // if tgt is bigger than src, there could be no src
00743                                                                // to advance on that side
00744                     continue;
00745                 int nsidesTgt2 = 0;
00746                 setup_tgt_cell( tgtNeigh,
00747                                 nsidesTgt2 );  // find possible intersection with src cell from nextSrc
00748                 for( Range::iterator nit = nextSrc[j].begin(); nit != nextSrc[j].end(); ++nit )
00749                 {
00750                     EntityHandle nextB = *nit;
00751                     // we identified tgt quad n[j] as possibly intersecting with neighbor j of the
00752                     // src quad
00753                     double P[10 * MAXEDGES], area;  //
00754                     int nP           = 0;
00755                     int nb[MAXEDGES] = { 0 };
00756                     int nr[MAXEDGES] = { 0 };
00757 
00758                     int nsidesSrc;  ///
00759                     rval = computeIntersectionBetweenTgtAndSrc(
00760                         /* tgt */ tgtNeigh, nextB, P, nP, area, nb, nr, nsidesSrc, nsidesTgt2 );MB_CHK_ERR( rval );
00761                     if( area > 0 )
00762                     {
00763                         tgtQueue.push( tgtNeigh );
00764                         srcQueue.push( nextB );
00765 #ifdef ENABLE_DEBUG
00766                         if( dbg_1 )
00767                             std::cout << "new polys pushed: src, tgt:" << mb->id_from_handle( tgtNeigh ) << " "
00768                                       << mb->id_from_handle( nextB ) << std::endl;
00769 #endif
00770                         rval = mb->tag_set_data( TgtFlagTag, &tgtNeigh, 1, &used );MB_CHK_ERR( rval );
00771                         break;  // so we are done with this side of tgt, we have found a proper next
00772                                 // seed
00773                     }
00774                 }
00775             }
00776 
00777         }  // end while (!tgtQueue.empty())
00778     }
00779 #ifdef ENABLE_DEBUG
00780     if( dbg_1 )
00781     {
00782         for( int k = 0; k < 6; k++ )
00783             mout_1[k].close();
00784     }
00785 #endif
00786     // before cleaning up , we need to settle the position of the intersection points
00787     // on the boundary edges
00788     // this needs to be collective, so we should maybe wait something
00789 #ifdef MOAB_HAVE_MPI
00790     rval = resolve_intersection_sharing();MB_CHK_SET_ERR( rval, "can't correct position, Intx2Mesh.cpp \n" );
00791 #endif
00792 
00793     this->clean();
00794     return MB_SUCCESS;
00795 }
00796 
00797 // clean some memory allocated
00798 void Intx2Mesh::clean()
00799 {
00800     //
00801     int indx = 0;
00802     for( Range::iterator eit = TgtEdges.begin(); eit != TgtEdges.end(); ++eit, indx++ )
00803     {
00804         delete extraNodesVec[indx];
00805     }
00806     // extraNodesMap.clear();
00807     extraNodesVec.clear();
00808     // also, delete some bit tags, used to mark processed tgts and srcs
00809     mb->tag_delete( TgtFlagTag );
00810     counting = 0;  // reset counting to original value
00811 }
00812 // this method will reduce number of nodes, collapse edges that are of length 0
00813 // so a polygon like 428 431 431 will become a line 428 431
00814 // or something like 428 431 431 531 -> 428 431 531
00815 void Intx2Mesh::correct_polygon( EntityHandle* nodes, int& nP )
00816 {
00817     int i = 0;
00818     while( i < nP )
00819     {
00820         int nextIndex = ( i + 1 ) % nP;
00821         if( nodes[i] == nodes[nextIndex] )
00822         {
00823 #ifdef ENABLE_DEBUG
00824             // we need to reduce nP, and collapse nodes
00825             if( dbg_1 )
00826             {
00827                 std::cout << " nodes duplicated in list: ";
00828                 for( int j = 0; j < nP; j++ )
00829                     std::cout << nodes[j] << " ";
00830                 std::cout << "\n";
00831                 std::cout << " node " << nodes[i] << " at index " << i << " is duplicated"
00832                           << "\n";
00833             }
00834 #endif
00835             // this will work even if we start from 1 2 3 1; when i is 3, we find nextIndex is 0,
00836             // then next thing does nothing
00837             //  (nP-1 is 3, so k is already >= nP-1); it will result in nodes -> 1, 2, 3
00838             for( int k = i; k < nP - 1; k++ )
00839                 nodes[k] = nodes[k + 1];
00840             nP--;  // decrease the number of nodes; also, decrease i, just if we may need to check
00841                    // again
00842             i--;
00843         }
00844         i++;
00845     }
00846     return;
00847 }
00848 #ifdef MOAB_HAVE_MPI
00849 ErrorCode Intx2Mesh::build_processor_euler_boxes( EntityHandle euler_set, Range& local_verts )
00850 {
00851     localEnts.clear();
00852     ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, localEnts );ERRORR( rval, "can't get ents by dimension" );
00853 
00854     rval                = mb->get_connectivity( localEnts, local_verts );
00855     int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" );
00856 
00857     assert( parcomm != NULL );
00858 
00859     // get the position of local vertices, and decide local boxes (allBoxes...)
00860     double bmin[3] = { DBL_MAX, DBL_MAX, DBL_MAX };
00861     double bmax[3] = { -DBL_MAX, -DBL_MAX, -DBL_MAX };
00862 
00863     std::vector< double > coords( 3 * num_local_verts );
00864     rval = mb->get_coords( local_verts, &coords[0] );ERRORR( rval, "can't get coords of vertices " );
00865 
00866     for( int i = 0; i < num_local_verts; i++ )
00867     {
00868         for( int k = 0; k < 3; k++ )
00869         {
00870             double val = coords[3 * i + k];
00871             if( val < bmin[k] ) bmin[k] = val;
00872             if( val > bmax[k] ) bmax[k] = val;
00873         }
00874     }
00875     int numprocs = parcomm->proc_config().proc_size();
00876     allBoxes.resize( 6 * numprocs );
00877 
00878     my_rank = parcomm->proc_config().proc_rank();
00879     for( int k = 0; k < 3; k++ )
00880     {
00881         allBoxes[6 * my_rank + k]     = bmin[k];
00882         allBoxes[6 * my_rank + 3 + k] = bmax[k];
00883     }
00884 
00885     // now communicate to get all boxes
00886     int mpi_err;
00887 #if( MPI_VERSION >= 2 )
00888     // use "in place" option
00889     mpi_err = MPI_Allgather( MPI_IN_PLACE, 0, MPI_DATATYPE_NULL, &allBoxes[0], 6, MPI_DOUBLE,
00890                              parcomm->proc_config().proc_comm() );
00891 #else
00892     {
00893         std::vector< double > allBoxes_tmp( 6 * parcomm->proc_config().proc_size() );
00894         mpi_err  = MPI_Allgather( &allBoxes[6 * my_rank], 6, MPI_DOUBLE, &allBoxes_tmp[0], 6, MPI_DOUBLE,
00895                                  parcomm->proc_config().proc_comm() );
00896         allBoxes = allBoxes_tmp;
00897     }
00898 #endif
00899     if( MPI_SUCCESS != mpi_err ) return MB_FAILURE;
00900 
00901     if( my_rank == 0 )
00902     {
00903         std::cout << " maximum number of vertices per cell are " << max_edges_1 << " on first mesh and " << max_edges_2
00904                   << " on second mesh \n";
00905         for( int i = 0; i < numprocs; i++ )
00906         {
00907             std::cout << "proc: " << i << " box min: " << allBoxes[6 * i] << " " << allBoxes[6 * i + 1] << " "
00908                       << allBoxes[6 * i + 2] << " \n";
00909             std::cout << "        box max: " << allBoxes[6 * i + 3] << " " << allBoxes[6 * i + 4] << " "
00910                       << allBoxes[6 * i + 5] << " \n";
00911         }
00912     }
00913 
00914     return MB_SUCCESS;
00915 }
00916 ErrorCode Intx2Mesh::create_departure_mesh_2nd_alg( EntityHandle& euler_set, EntityHandle& covering_lagr_set )
00917 {
00918     // compute the bounding box on each proc
00919     assert( parcomm != NULL );
00920 
00921     localEnts.clear();
00922     ErrorCode rval = mb->get_entities_by_dimension( euler_set, 2, localEnts );ERRORR( rval, "can't get ents by dimension" );
00923 
00924     Tag dpTag = 0;
00925     std::string tag_name( "DP" );
00926     rval = mb->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, dpTag, MB_TAG_DENSE );ERRORR( rval, "can't get DP tag" );
00927 
00928     EntityHandle dum = 0;
00929     Tag corrTag;
00930     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" );
00931     // get all local verts
00932     Range local_verts;
00933     rval                = mb->get_connectivity( localEnts, local_verts );
00934     int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" );
00935 
00936     rval = Intx2Mesh::build_processor_euler_boxes( euler_set, local_verts );ERRORR( rval, "can't build processor boxes" );
00937 
00938     std::vector< int > gids( num_local_verts );
00939     rval = mb->tag_get_data( gid, local_verts, &gids[0] );ERRORR( rval, "can't get local vertices gids" );
00940 
00941     // now see the departure points; to what boxes should we send them?
00942     std::vector< double > dep_points( 3 * num_local_verts );
00943     rval = mb->tag_get_data( dpTag, local_verts, (void*)&dep_points[0] );ERRORR( rval, "can't get DP tag values" );
00944     // ranges to send to each processor; will hold vertices and elements (quads?)
00945     // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances)
00946     std::map< int, Range > Rto;
00947     int numprocs = parcomm->proc_config().proc_size();
00948 
00949     for( Range::iterator eit = localEnts.begin(); eit != localEnts.end(); ++eit )
00950     {
00951         EntityHandle q = *eit;
00952         const EntityHandle* conn4;
00953         int num_nodes;
00954         rval = mb->get_connectivity( q, conn4, num_nodes );ERRORR( rval, "can't get DP tag values" );
00955         CartVect qbmin( DBL_MAX );
00956         CartVect qbmax( -DBL_MAX );
00957         for( int i = 0; i < num_nodes; i++ )
00958         {
00959             EntityHandle v = conn4[i];
00960             size_t index   = local_verts.find( v ) - local_verts.begin();
00961             CartVect dp( &dep_points[3 * index] );  // will use constructor
00962             for( int j = 0; j < 3; j++ )
00963             {
00964                 if( qbmin[j] > dp[j] ) qbmin[j] = dp[j];
00965                 if( qbmax[j] < dp[j] ) qbmax[j] = dp[j];
00966             }
00967         }
00968         for( int p = 0; p < numprocs; p++ )
00969         {
00970             CartVect bbmin( &allBoxes[6 * p] );
00971             CartVect bbmax( &allBoxes[6 * p + 3] );
00972             if( GeomUtil::boxes_overlap( bbmin, bbmax, qbmin, qbmax, box_error ) ) { Rto[p].insert( q ); }
00973         }
00974     }
00975 
00976     // now, build TLv and TLq, for each p
00977     size_t numq = 0;
00978     size_t numv = 0;
00979     for( int p = 0; p < numprocs; p++ )
00980     {
00981         if( p == (int)my_rank ) continue;  // do not "send" it, because it is already here
00982         Range& range_to_P = Rto[p];
00983         // add the vertices to it
00984         if( range_to_P.empty() ) continue;  // nothing to send to proc p
00985         Range vertsToP;
00986         rval = mb->get_connectivity( range_to_P, vertsToP );ERRORR( rval, "can't get connectivity" );
00987         numq = numq + range_to_P.size();
00988         numv = numv + vertsToP.size();
00989         range_to_P.merge( vertsToP );
00990     }
00991     TupleList TLv;
00992     TupleList TLq;
00993     TLv.initialize( 2, 0, 0, 3, numv );  // to proc, GLOBAL ID, DP points
00994     TLv.enableWriteAccess();
00995 
00996     int sizeTuple = 2 + max_edges_1;  // determined earlier, for src, first mesh
00997     TLq.initialize( 2 + max_edges_1, 0, 1, 0,
00998                     numq );  // to proc, elem GLOBAL ID, connectivity[10] (global ID v), local eh
00999     TLq.enableWriteAccess();
01000 #ifdef VERBOSE
01001     std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n";
01002 #endif
01003     for( int to_proc = 0; to_proc < numprocs; to_proc++ )
01004     {
01005         if( to_proc == (int)my_rank ) continue;
01006         Range& range_to_P = Rto[to_proc];
01007         Range V           = range_to_P.subset_by_type( MBVERTEX );
01008 
01009         for( Range::iterator it = V.begin(); it != V.end(); ++it )
01010         {
01011             EntityHandle v       = *it;
01012             unsigned int index   = local_verts.find( v ) - local_verts.begin();
01013             int n                = TLv.get_n();
01014             TLv.vi_wr[2 * n]     = to_proc;                // send to processor
01015             TLv.vi_wr[2 * n + 1] = gids[index];            // global id needs index in the local_verts range
01016             TLv.vr_wr[3 * n]     = dep_points[3 * index];  // departure position, of the node local_verts[i]
01017             TLv.vr_wr[3 * n + 1] = dep_points[3 * index + 1];
01018             TLv.vr_wr[3 * n + 2] = dep_points[3 * index + 2];
01019             TLv.inc_n();
01020         }
01021         // also, prep the quad for sending ...
01022         Range Q = range_to_P.subset_by_dimension( 2 );
01023         for( Range::iterator it = Q.begin(); it != Q.end(); ++it )
01024         {
01025             EntityHandle q = *it;
01026             int global_id;
01027             rval = mb->tag_get_data( gid, &q, 1, &global_id );ERRORR( rval, "can't get gid for polygon" );
01028             int n                        = TLq.get_n();
01029             TLq.vi_wr[sizeTuple * n]     = to_proc;    //
01030             TLq.vi_wr[sizeTuple * n + 1] = global_id;  // global id of element, used to identify it ...
01031             const EntityHandle* conn4;
01032             int num_nodes;
01033             rval = mb->get_connectivity( q, conn4,
01034                                          num_nodes );  // could be up to MAXEDGES, but it is limited by max_edges_1
01035             ERRORR( rval, "can't get connectivity for cell" );
01036             if( num_nodes > MAXEDGES ) ERRORR( MB_FAILURE, "too many nodes in a polygon" );
01037             for( int i = 0; i < num_nodes; i++ )
01038             {
01039                 EntityHandle v                   = conn4[i];
01040                 unsigned int index               = local_verts.find( v ) - local_verts.begin();
01041                 TLq.vi_wr[sizeTuple * n + 2 + i] = gids[index];
01042             }
01043             for( int k = num_nodes; k < max_edges_1; k++ )
01044             {
01045                 TLq.vi_wr[sizeTuple * n + 2 + k] =
01046                     0;  // fill the rest of node ids with 0; we know that the node ids start from 1!
01047             }
01048             TLq.vul_wr[n] = q;  // save here the entity handle, it will be communicated back
01049             // maybe we should forget about global ID
01050             TLq.inc_n();
01051         }
01052     }
01053 
01054     // now we are done populating the tuples; route them to the appropriate processors
01055     ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 );
01056     ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLq, 0 );
01057     // the elements are already in localEnts;
01058 
01059     // maps from global ids to new vertex and quad handles, that are added
01060     std::map< int, EntityHandle > globalID_to_handle;
01061     /*std::map<int, EntityHandle> globalID_to_eh;*/
01062     globalID_to_eh.clear();  // need for next iteration
01063     // now, look at every TLv, and see if we have to create a vertex there or not
01064     int n = TLv.get_n();  // the size of the points received
01065     for( int i = 0; i < n; i++ )
01066     {
01067         int globalId = TLv.vi_rd[2 * i + 1];
01068         if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() )
01069         {
01070             EntityHandle new_vert;
01071             double dp_pos[3] = { TLv.vr_wr[3 * i], TLv.vr_wr[3 * i + 1], TLv.vr_wr[3 * i + 2] };
01072             rval             = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " );
01073             globalID_to_handle[globalId] = new_vert;
01074         }
01075     }
01076 
01077     // now, all dep points should be at their place
01078     // look in the local list of q for this proc, and create all those quads and vertices if needed
01079     // it may be an overkill, but because it does not involve communication, we do it anyway
01080     Range& local  = Rto[my_rank];
01081     Range local_q = local.subset_by_dimension( 2 );
01082     // the local should have all the vertices in local_verts
01083     for( Range::iterator it = local_q.begin(); it != local_q.end(); ++it )
01084     {
01085         EntityHandle q = *it;
01086         int nnodes;
01087         const EntityHandle* conn4;
01088         rval = mb->get_connectivity( q, conn4, nnodes );ERRORR( rval, "can't get connectivity of local q " );
01089         EntityHandle new_conn[MAXEDGES];
01090         for( int i = 0; i < nnodes; i++ )
01091         {
01092             EntityHandle v1    = conn4[i];
01093             unsigned int index = local_verts.find( v1 ) - local_verts.begin();
01094             int globalId       = gids[index];
01095             if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() )
01096             {
01097                 // we need to create that vertex, at this position dep_points
01098                 double dp_pos[3] = { dep_points[3 * index], dep_points[3 * index + 1], dep_points[3 * index + 2] };
01099                 EntityHandle new_vert;
01100                 rval = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " );
01101                 globalID_to_handle[globalId] = new_vert;
01102             }
01103             new_conn[i] = globalID_to_handle[gids[index]];
01104         }
01105         EntityHandle new_element;
01106         //
01107         EntityType entType = MBQUAD;
01108         if( nnodes > 4 ) entType = MBPOLYGON;
01109         if( nnodes < 4 ) entType = MBTRI;
01110 
01111         rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new quad " );
01112         rval = mb->add_entities( covering_lagr_set, &new_element, 1 );ERRORR( rval, "can't add new element to dep set" );
01113         int gid_el;
01114         // get the global ID of the initial quad
01115         rval = mb->tag_get_data( gid, &q, 1, &gid_el );ERRORR( rval, "can't get element global ID " );
01116         globalID_to_eh[gid_el] = new_element;
01117         // is this redundant or not?
01118         rval = mb->tag_set_data( corrTag, &new_element, 1, &q );ERRORR( rval, "can't set corr tag on new el" );
01119         // set the global id on new elem
01120         rval = mb->tag_set_data( gid, &new_element, 1, &gid_el );ERRORR( rval, "can't set global id tag on new el" );
01121     }
01122     // now look at all elements received through; we do not want to duplicate them
01123     n = TLq.get_n();  // number of elements received by this processor
01124     // form the remote cells, that will be used to send the tracer info back to the originating proc
01125     remote_cells = new TupleList();
01126     remote_cells->initialize( 2, 0, 1, 0, n );  // will not have tracer data anymore
01127     remote_cells->enableWriteAccess();
01128     for( int i = 0; i < n; i++ )
01129     {
01130         int globalIdEl = TLq.vi_rd[sizeTuple * i + 1];
01131         int from_proc  = TLq.vi_wr[sizeTuple * i];
01132         // do we already have a quad with this global ID, represented?
01133         if( globalID_to_eh.find( globalIdEl ) == globalID_to_eh.end() )
01134         {
01135             // construct the conn quad
01136             EntityHandle new_conn[MAXEDGES];
01137             int nnodes = -1;
01138             for( int j = 0; j < max_edges_1; j++ )
01139             {
01140                 int vgid = TLq.vi_rd[sizeTuple * i + 2 + j];  // vertex global ID
01141                 if( vgid == 0 )
01142                     new_conn[j] = 0;
01143                 else
01144                 {
01145                     assert( globalID_to_handle.find( vgid ) != globalID_to_handle.end() );
01146                     new_conn[j] = globalID_to_handle[vgid];
01147                     nnodes      = j + 1;  // nodes are at the beginning, and are variable number
01148                 }
01149             }
01150             EntityHandle new_element;
01151             //
01152             EntityType entType = MBQUAD;
01153             if( nnodes > 4 ) entType = MBPOLYGON;
01154             if( nnodes < 4 ) entType = MBTRI;
01155             rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new element " );
01156             globalID_to_eh[globalIdEl] = new_element;
01157             rval                       = mb->add_entities( covering_lagr_set, &new_element, 1 );ERRORR( rval, "can't add new element to dep set" );
01158             /* rval = mb->tag_set_data(corrTag, &new_element, 1, &q);ERRORR(rval, "can't set corr tag on new el");*/
01159             remote_cells->vi_wr[2 * i]     = from_proc;
01160             remote_cells->vi_wr[2 * i + 1] = globalIdEl;
01161             //     remote_cells->vr_wr[i] = 0.; // no contribution yet sent back
01162             remote_cells->vul_wr[i] = TLq.vul_rd[i];  // this is the corresponding tgt cell (arrival)
01163             remote_cells->inc_n();
01164             // set the global id on new elem
01165             rval = mb->tag_set_data( gid, &new_element, 1, &globalIdEl );ERRORR( rval, "can't set global id tag on new el" );
01166         }
01167     }
01168     // order the remote cells tuple list, with the global id, because we will search in it
01169     // remote_cells->print("remote_cells before sorting");
01170     moab::TupleList::buffer sort_buffer;
01171     sort_buffer.buffer_init( n );
01172     remote_cells->sort( 1, &sort_buffer );
01173     sort_buffer.reset();
01174     return MB_SUCCESS;
01175 }
01176 
01177 // this algorithm assumes lagr set is already created, and some elements will be coming from
01178 // other procs, and populate the covering_set
01179 // we need to keep in a tuple list the remote cells from other procs, because we need to send back
01180 // the intersection info (like area of the intx polygon, and the current concentration) maybe total
01181 // mass in that intx
01182 ErrorCode Intx2Mesh::create_departure_mesh_3rd_alg( EntityHandle& lagr_set, EntityHandle& covering_set )
01183 {
01184     EntityHandle dum = 0;
01185 
01186     Tag corrTag;
01187     ErrorCode rval = mb->tag_get_handle( CORRTAGNAME, 1, MB_TYPE_HANDLE, corrTag, MB_TAG_DENSE | MB_TAG_CREAT, &dum );
01188     // start copy from 2nd alg
01189     // compute the bounding box on each proc
01190     assert( parcomm != NULL );
01191     if( 1 == parcomm->proc_config().proc_size() )
01192     {
01193         covering_set = lagr_set;  // nothing to communicate, it must be serial
01194         return MB_SUCCESS;
01195     }
01196 
01197     // get all local verts
01198     Range local_verts;
01199     rval                = mb->get_connectivity( localEnts, local_verts );
01200     int num_local_verts = (int)local_verts.size();ERRORR( rval, "can't get local vertices" );
01201 
01202     std::vector< int > gids( num_local_verts );
01203     rval = mb->tag_get_data( gid, local_verts, &gids[0] );ERRORR( rval, "can't get local vertices gids" );
01204 
01205     Range localDepCells;
01206     rval = mb->get_entities_by_dimension( lagr_set, 2, localDepCells );ERRORR( rval, "can't get ents by dimension from lagr set" );
01207 
01208     // get all lagr verts (departure vertices)
01209     Range lagr_verts;
01210     rval = mb->get_connectivity( localDepCells, lagr_verts );  // they should be created in
01211     // the same order as the euler vertices
01212     int num_lagr_verts = (int)lagr_verts.size();ERRORR( rval, "can't get local lagr vertices" );
01213 
01214     // now see the departure points position; to what boxes should we send them?
01215     std::vector< double > dep_points( 3 * num_lagr_verts );
01216     rval = mb->get_coords( lagr_verts, &dep_points[0] );ERRORR( rval, "can't get departure points position" );
01217     // ranges to send to each processor; will hold vertices and elements (quads?)
01218     // will look if the box of the dep quad covers box of euler mesh on proc (with tolerances)
01219     std::map< int, Range > Rto;
01220     int numprocs = parcomm->proc_config().proc_size();
01221 
01222     for( Range::iterator eit = localDepCells.begin(); eit != localDepCells.end(); ++eit )
01223     {
01224         EntityHandle q = *eit;
01225         const EntityHandle* conn4;
01226         int num_nodes;
01227         rval = mb->get_connectivity( q, conn4, num_nodes );ERRORR( rval, "can't get DP tag values" );
01228         CartVect qbmin( DBL_MAX );
01229         CartVect qbmax( -DBL_MAX );
01230         for( int i = 0; i < num_nodes; i++ )
01231         {
01232             EntityHandle v = conn4[i];
01233             int index      = lagr_verts.index( v );
01234             assert( -1 != index );
01235             CartVect dp( &dep_points[3 * index] );  // will use constructor
01236             for( int j = 0; j < 3; j++ )
01237             {
01238                 if( qbmin[j] > dp[j] ) qbmin[j] = dp[j];
01239                 if( qbmax[j] < dp[j] ) qbmax[j] = dp[j];
01240             }
01241         }
01242         for( int p = 0; p < numprocs; p++ )
01243         {
01244             CartVect bbmin( &allBoxes[6 * p] );
01245             CartVect bbmax( &allBoxes[6 * p + 3] );
01246             if( GeomUtil::boxes_overlap( bbmin, bbmax, qbmin, qbmax, box_error ) ) { Rto[p].insert( q ); }
01247         }
01248     }
01249 
01250     // now, build TLv and TLq, for each p
01251     size_t numq = 0;
01252     size_t numv = 0;
01253     for( int p = 0; p < numprocs; p++ )
01254     {
01255         if( p == (int)my_rank ) continue;  // do not "send" it, because it is already here
01256         Range& range_to_P = Rto[p];
01257         // add the vertices to it
01258         if( range_to_P.empty() ) continue;  // nothing to send to proc p
01259         Range vertsToP;
01260         rval = mb->get_connectivity( range_to_P, vertsToP );ERRORR( rval, "can't get connectivity" );
01261         numq = numq + range_to_P.size();
01262         numv = numv + vertsToP.size();
01263         range_to_P.merge( vertsToP );
01264     }
01265     TupleList TLv;
01266     TupleList TLq;
01267     TLv.initialize( 2, 0, 0, 3, numv );  // to proc, GLOBAL ID, DP points
01268     TLv.enableWriteAccess();
01269 
01270     int sizeTuple = 2 + max_edges_1;  // max edges could be up to MAXEDGES :) for polygons
01271     TLq.initialize( 2 + max_edges_1, 0, 1, 0,
01272                     numq );  // to proc, elem GLOBAL ID, connectivity[max_edges] (global ID v)
01273     // send also the corresponding tgt cell it will come to
01274     TLq.enableWriteAccess();
01275 #ifdef VERBOSE
01276     std::cout << "from proc " << my_rank << " send " << numv << " vertices and " << numq << " elements\n";
01277 #endif
01278 
01279     for( int to_proc = 0; to_proc < numprocs; to_proc++ )
01280     {
01281         if( to_proc == (int)my_rank ) continue;
01282         Range& range_to_P = Rto[to_proc];
01283         Range V           = range_to_P.subset_by_type( MBVERTEX );
01284 
01285         for( Range::iterator it = V.begin(); it != V.end(); ++it )
01286         {
01287             EntityHandle v = *it;
01288             int index = lagr_verts.index( v );  // will be the same index as the corresponding vertex in euler verts
01289             assert( -1 != index );
01290             int n                = TLv.get_n();
01291             TLv.vi_wr[2 * n]     = to_proc;                // send to processor
01292             TLv.vi_wr[2 * n + 1] = gids[index];            // global id needs index in the local_verts range
01293             TLv.vr_wr[3 * n]     = dep_points[3 * index];  // departure position, of the node local_verts[i]
01294             TLv.vr_wr[3 * n + 1] = dep_points[3 * index + 1];
01295             TLv.vr_wr[3 * n + 2] = dep_points[3 * index + 2];
01296             TLv.inc_n();
01297         }
01298         // also, prep the 2d cells for sending ...
01299         Range Q = range_to_P.subset_by_dimension( 2 );
01300         for( Range::iterator it = Q.begin(); it != Q.end(); ++it )
01301         {
01302             EntityHandle q = *it;  // this is a src cell
01303             int global_id;
01304             rval = mb->tag_get_data( gid, &q, 1, &global_id );ERRORR( rval, "can't get gid for polygon" );
01305             int n                        = TLq.get_n();
01306             TLq.vi_wr[sizeTuple * n]     = to_proc;    //
01307             TLq.vi_wr[sizeTuple * n + 1] = global_id;  // global id of element, used to identify it ...
01308             const EntityHandle* conn4;
01309             int num_nodes;
01310             rval = mb->get_connectivity(
01311                 q, conn4, num_nodes );  // could be up to 10;ERRORR( rval, "can't get connectivity for quad" );
01312             if( num_nodes > MAXEDGES ) ERRORR( MB_FAILURE, "too many nodes in a polygon" );
01313             for( int i = 0; i < num_nodes; i++ )
01314             {
01315                 EntityHandle v = conn4[i];
01316                 int index      = lagr_verts.index( v );
01317                 assert( -1 != index );
01318                 TLq.vi_wr[sizeTuple * n + 2 + i] = gids[index];
01319             }
01320             for( int k = num_nodes; k < max_edges_1; k++ )
01321             {
01322                 TLq.vi_wr[sizeTuple * n + 2 + k] =
01323                     0;  // fill the rest of node ids with 0; we know that the node ids start from 1!
01324             }
01325             EntityHandle tgtCell;
01326             rval = mb->tag_get_data( corrTag, &q, 1, &tgtCell );ERRORR( rval, "can't get corresponding tgt cell for dep cell" );
01327             TLq.vul_wr[n] = tgtCell;  // this will be sent to remote_cells, to be able to come back
01328             TLq.inc_n();
01329         }
01330     }
01331     // now we can route them to each processor
01332     // now we are done populating the tuples; route them to the appropriate processors
01333     ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLv, 0 );
01334     ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, TLq, 0 );
01335     // the elements are already in localEnts;
01336 
01337     // maps from global ids to new vertex and quad handles, that are added
01338     std::map< int, EntityHandle > globalID_to_handle;
01339     // we already have vertices from lagr set; they are already in the processor, even before
01340     // receiving other verts from neighbors
01341     int k = 0;
01342     for( Range::iterator vit = lagr_verts.begin(); vit != lagr_verts.end(); ++vit, k++ )
01343     {
01344         globalID_to_handle[gids[k]] = *vit;  // a little bit of overkill
01345         // we do know that the global ids between euler and lagr verts are parallel
01346     }
01347     /*std::map<int, EntityHandle> globalID_to_eh;*/  // do we need this one?
01348     globalID_to_eh.clear();
01349     // now, look at every TLv, and see if we have to create a vertex there or not
01350     int n = TLv.get_n();  // the size of the points received
01351     for( int i = 0; i < n; i++ )
01352     {
01353         int globalId = TLv.vi_rd[2 * i + 1];
01354         if( globalID_to_handle.find( globalId ) == globalID_to_handle.end() )
01355         {
01356             EntityHandle new_vert;
01357             double dp_pos[3] = { TLv.vr_wr[3 * i], TLv.vr_wr[3 * i + 1], TLv.vr_wr[3 * i + 2] };
01358             rval             = mb->create_vertex( dp_pos, new_vert );ERRORR( rval, "can't create new vertex " );
01359             globalID_to_handle[globalId] = new_vert;
01360         }
01361     }
01362 
01363     // now, all dep points should be at their place
01364     // look in the local list of 2d cells for this proc, and create all those cells if needed
01365     // it may be an overkill, but because it does not involve communication, we do it anyway
01366     Range& local  = Rto[my_rank];
01367     Range local_q = local.subset_by_dimension( 2 );
01368     // the local should have all the vertices in lagr_verts
01369     for( Range::iterator it = local_q.begin(); it != local_q.end(); ++it )
01370     {
01371         EntityHandle q = *it;  // these are from lagr cells, local
01372         int gid_el;
01373         rval = mb->tag_get_data( gid, &q, 1, &gid_el );ERRORR( rval, "can't get element global ID " );
01374         globalID_to_eh[gid_el] = q;  // do we need this? maybe to just mark the ones on this processor
01375         // maybe a range of global cell ids is fine?
01376     }
01377     // now look at all elements received through; we do not want to duplicate them
01378     n = TLq.get_n();  // number of elements received by this processor
01379     // a cell should be received from one proc only; so why are we so worried about duplicated
01380     // elements? a vertex can be received from multiple sources, that is fine
01381 
01382     remote_cells = new TupleList();
01383     remote_cells->initialize( 2, 0, 1, 0, n );  // no tracers anymore in these tuples
01384     remote_cells->enableWriteAccess();
01385     for( int i = 0; i < n; i++ )
01386     {
01387         int globalIdEl = TLq.vi_rd[sizeTuple * i + 1];
01388         int from_proc  = TLq.vi_rd[sizeTuple * i];
01389         // do we already have a quad with this global ID, represented?
01390         if( globalID_to_eh.find( globalIdEl ) == globalID_to_eh.end() )
01391         {
01392             // construct the conn quad
01393             EntityHandle new_conn[MAXEDGES];
01394             int nnodes = -1;
01395             for( int j = 0; j < max_edges_1; j++ )
01396             {
01397                 int vgid = TLq.vi_rd[sizeTuple * i + 2 + j];  // vertex global ID
01398                 if( vgid == 0 )
01399                     new_conn[j] = 0;
01400                 else
01401                 {
01402                     assert( globalID_to_handle.find( vgid ) != globalID_to_handle.end() );
01403                     new_conn[j] = globalID_to_handle[vgid];
01404                     nnodes      = j + 1;  // nodes are at the beginning, and are variable number
01405                 }
01406             }
01407             EntityHandle new_element;
01408             //
01409             EntityType entType = MBQUAD;
01410             if( nnodes > 4 ) entType = MBPOLYGON;
01411             if( nnodes < 4 ) entType = MBTRI;
01412             rval = mb->create_element( entType, new_conn, nnodes, new_element );ERRORR( rval, "can't create new element " );
01413             globalID_to_eh[globalIdEl] = new_element;
01414             local_q.insert( new_element );
01415             rval = mb->tag_set_data( gid, &new_element, 1, &globalIdEl );ERRORR( rval, "can't set gid on new element " );
01416         }
01417         remote_cells->vi_wr[2 * i]     = from_proc;
01418         remote_cells->vi_wr[2 * i + 1] = globalIdEl;
01419         //    remote_cells->vr_wr[i] = 0.; will have a different tuple for communication
01420         remote_cells->vul_wr[i] = TLq.vul_rd[i];  // this is the corresponding tgt cell (arrival)
01421         remote_cells->inc_n();
01422     }
01423     // now, create a new set, covering_set
01424     rval = mb->create_meshset( MESHSET_SET, covering_set );ERRORR( rval, "can't create new mesh set " );
01425     rval = mb->add_entities( covering_set, local_q );ERRORR( rval, "can't add entities to new mesh set " );
01426     // order the remote cells tuple list, with the global id, because we will search in it
01427     // remote_cells->print("remote_cells before sorting");
01428     moab::TupleList::buffer sort_buffer;
01429     sort_buffer.buffer_init( n );
01430     remote_cells->sort( 1, &sort_buffer );
01431     sort_buffer.reset();
01432     return MB_SUCCESS;
01433     // end copy
01434 }
01435 
01436 ErrorCode Intx2Mesh::resolve_intersection_sharing()
01437 {
01438     if( parcomm && parcomm->size() > 1 )
01439     {
01440         /*
01441             moab::ParallelMergeMesh pm(parcomm, epsilon_1);
01442             ErrorCode rval = pm.merge(outSet, false, 2); // resolve only the output set, do not skip
01443            local merge, use dim 2 ERRORR(rval, "can't merge intersection ");
01444         */
01445         // look at non-owned shared vertices, that could be part of original source set
01446         // they should be removed from intx set reference, because they might not have a
01447         // correspondent on the other task
01448         Range nonOwnedVerts;
01449         Range vertsInIntx;
01450         Range intxCells;
01451         ErrorCode rval = mb->get_entities_by_dimension( outSet, 2, intxCells );MB_CHK_ERR( rval );
01452         rval = mb->get_connectivity( intxCells, vertsInIntx );MB_CHK_ERR( rval );
01453 
01454         rval = parcomm->filter_pstatus( vertsInIntx, PSTATUS_NOT_OWNED, PSTATUS_AND, -1, &nonOwnedVerts );MB_CHK_ERR( rval );
01455 
01456         // some of these vertices can be in original set 1, which was covered, transported;
01457         // but they should not be "shared" from the intx point of view, because they are not shared
01458         // with another task they might have come from coverage as a plain vertex, so losing the
01459         // sharing property ?
01460 
01461         Range coverVerts;
01462         rval = mb->get_connectivity( rs1, coverVerts );MB_CHK_ERR( rval );
01463         // find out those that are on the interface
01464         Range vertsCovInterface;
01465         rval = parcomm->filter_pstatus( coverVerts, PSTATUS_INTERFACE, PSTATUS_AND, -1, &vertsCovInterface );MB_CHK_ERR( rval );
01466         // how many of these are in
01467         Range nodesToDuplicate = intersect( vertsCovInterface, nonOwnedVerts );
01468         // first, get all cells connected to these vertices, from intxCells
01469 
01470         Range connectedCells;
01471         rval = mb->get_adjacencies( nodesToDuplicate, 2, false, connectedCells, Interface::UNION );MB_CHK_ERR( rval );
01472         // only those in intx set:
01473         connectedCells = intersect( connectedCells, intxCells );
01474         // first duplicate vertices in question:
01475         std::map< EntityHandle, EntityHandle > duplicatedVerticesMap;
01476         for( Range::iterator vit = nodesToDuplicate.begin(); vit != nodesToDuplicate.end(); vit++ )
01477         {
01478             EntityHandle vertex = *vit;
01479             double coords[3];
01480             rval = mb->get_coords( &vertex, 1, coords );MB_CHK_ERR( rval );
01481             EntityHandle newVertex;
01482             rval = mb->create_vertex( coords, newVertex );MB_CHK_ERR( rval );
01483             duplicatedVerticesMap[vertex] = newVertex;
01484         }
01485 
01486         // look now at connectedCells, and change their connectivities:
01487         for( Range::iterator eit = connectedCells.begin(); eit != connectedCells.end(); eit++ )
01488         {
01489             EntityHandle intxCell = *eit;
01490             // replace connectivity
01491             std::vector< EntityHandle > connectivity;
01492             rval = mb->get_connectivity( &intxCell, 1, connectivity );MB_CHK_ERR( rval );
01493             for( size_t i = 0; i < connectivity.size(); i++ )
01494             {
01495                 EntityHandle currentVertex                           = connectivity[i];
01496                 std::map< EntityHandle, EntityHandle >::iterator mit = duplicatedVerticesMap.find( currentVertex );
01497                 if( mit != duplicatedVerticesMap.end() )
01498                 {
01499                     connectivity[i] = mit->second;  // replace connectivity directly
01500                 }
01501             }
01502             int nnodes = (int)connectivity.size();
01503             rval       = mb->set_connectivity( intxCell, &connectivity[0], nnodes );MB_CHK_ERR( rval );
01504         }
01505     }
01506     return MB_SUCCESS;
01507 }
01508 #endif /* MOAB_HAVE_MPI */
01509 } /* namespace moab */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines