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