Mesh Oriented datABase  (version 5.5.0)
An array-based unstructured mesh library
moab::Intx2MeshOnSphere Class Reference

#include <Intx2MeshOnSphere.hpp>

+ Inheritance diagram for moab::Intx2MeshOnSphere:
+ Collaboration diagram for moab::Intx2MeshOnSphere:

Public Member Functions

 Intx2MeshOnSphere (Interface *mbimpl, IntxAreaUtils::AreaMethod amethod=IntxAreaUtils::lHuiller)
 
virtual ~Intx2MeshOnSphere ()
 
void set_radius_source_mesh (double radius)
 
void set_radius_destination_mesh (double radius)
 
double setup_tgt_cell (EntityHandle tgt, int &nsTgt)
 
ErrorCode computeIntersectionBetweenTgtAndSrc (EntityHandle tgt, EntityHandle src, double *P, int &nP, double &area, int markb[MAXEDGES], int markr[MAXEDGES], int &nsSrc, int &nsTgt, bool check_boxes_first=false)
 
ErrorCode findNodes (EntityHandle tgt, int nsTgt, EntityHandle src, int nsSrc, double *iP, int nP)
 
ErrorCode update_tracer_data (EntityHandle out_set, Tag &tagElem, Tag &tagArea)
 
- Public Member Functions inherited from moab::Intx2Mesh
 Intx2Mesh (Interface *mbimpl)
 
virtual ~Intx2Mesh ()
 
ErrorCode intersect_meshes (EntityHandle mbs1, EntityHandle mbs2, EntityHandle &outputSet)
 
ErrorCode intersect_meshes_kdtree (EntityHandle mbset1, EntityHandle mbset2, EntityHandle &outputSet)
 
virtual ErrorCode FindMaxEdgesInSet (EntityHandle eset, int &max_edges)
 
virtual ErrorCode FindMaxEdges (EntityHandle set1, EntityHandle set2)
 
virtual ErrorCode createTags ()
 
ErrorCode DetermineOrderedNeighbors (EntityHandle inputSet, int max_edges, Tag &neighTag)
 
void set_error_tolerance (double eps)
 
void clean ()
 
void set_box_error (double berror)
 
ErrorCode create_departure_mesh_2nd_alg (EntityHandle &euler_set, EntityHandle &covering_lagr_set)
 
ErrorCode create_departure_mesh_3rd_alg (EntityHandle &lagr_set, EntityHandle &covering_set)
 
void correct_polygon (EntityHandle *foundIds, int &nP)
 

Public Attributes

const IntxAreaUtils::AreaMethod areaMethod
 

Private Attributes

int plane
 
double Rsrc
 
double Rdest
 

Additional Inherited Members

- Protected Attributes inherited from moab::Intx2Mesh
Interfacemb
 
EntityHandle mbs1
 
EntityHandle mbs2
 
Range rs1
 
Range rs2
 
EntityHandle outSet
 
Tag gid
 
Tag TgtFlagTag
 
Range TgtEdges
 
Tag tgtParentTag
 
Tag srcParentTag
 
Tag countTag
 
Tag srcNeighTag
 
Tag tgtNeighTag
 
Tag neighTgtEdgeTag
 
Tag orgSendProcTag
 
const EntityHandletgtConn
 for coverage mesh, will store the original sender More...
 
const EntityHandlesrcConn
 
CartVect tgtCoords [MAXEDGES]
 
CartVect srcCoords [MAXEDGES]
 
double tgtCoords2D [MAXEDGES2]
 
double srcCoords2D [MAXEDGES2]
 
std::vector< std::vector< EntityHandle > * > extraNodesVec
 
double epsilon_1
 
double epsilon_area
 
std::vector< double > allBoxes
 
double box_error
 
EntityHandle localRoot
 
Range localEnts
 
unsigned int my_rank
 
int max_edges_1
 
int max_edges_2
 
int counting
 

Detailed Description

Definition at line 16 of file Intx2MeshOnSphere.hpp.

Constructor & Destructor Documentation

◆ Intx2MeshOnSphere()

moab::Intx2MeshOnSphere::Intx2MeshOnSphere ( Interface mbimpl,
IntxAreaUtils::AreaMethod  amethod = IntxAreaUtils::lHuiller 
)

Definition at line 27 of file Intx2MeshOnSphere.cpp.

28  : Intx2Mesh( mbimpl ), areaMethod( amethod ), plane( 0 ), Rsrc( 0.0 ), Rdest( 0.0 )
29 {
30 }

◆ ~Intx2MeshOnSphere()

moab::Intx2MeshOnSphere::~Intx2MeshOnSphere ( )
virtual

Definition at line 32 of file Intx2MeshOnSphere.cpp.

32 {}

Member Function Documentation

◆ computeIntersectionBetweenTgtAndSrc()

ErrorCode moab::Intx2MeshOnSphere::computeIntersectionBetweenTgtAndSrc ( EntityHandle  tgt,
EntityHandle  src,
double *  P,
int &  nP,
double &  area,
int  markb[MAXEDGES],
int  markr[MAXEDGES],
int &  nsSrc,
int &  nsTgt,
bool  check_boxes_first = false 
)
virtual

Implements moab::Intx2Mesh.

Definition at line 77 of file Intx2MeshOnSphere.cpp.

87 {
88  // the area will be used from now on, to see how well we fill the target cell with polygons
89  // the points will be at most 40; they will describe a convex patch, after the points will be
90  // ordered and collapsed (eliminate doubles)
91 
92  // CartVect srccoords[4];
93  int num_nodes = 0;
94  ErrorCode rval = mb->get_connectivity( src, srcConn, num_nodes );MB_CHK_ERR( rval );
95  nsBlue = num_nodes;
96  // account for possible padded polygons
97  while( srcConn[nsBlue - 2] == srcConn[nsBlue - 1] && nsBlue > 3 )
98  nsBlue--;
99  rval = mb->get_coords( srcConn, nsBlue, &( srcCoords[0][0] ) );MB_CHK_ERR( rval );
100 
101  area = 0.;
102  nP = 0; // number of intersection points we are marking the boundary of src!
103  if( check_boxes_first )
104  {
105  // look at the boxes formed with vertices; if they are far away, return false early
106  // make sure the target is setup already
107  setup_tgt_cell( tgt, nsTgt ); // we do not need area here
108  // use here gnomonic plane (plane) to see where source is
109  bool overlap3d = GeomUtil::bounding_boxes_overlap( tgtCoords, nsTgt, srcCoords, nsBlue, box_error );
110  int planeb;
111  CartVect mid3 = ( srcCoords[0] + srcCoords[1] + srcCoords[2] ) / 3;
112  IntxUtils::decide_gnomonic_plane( mid3, planeb );
113  if( !overlap3d && ( plane != planeb ) ) // plane was set at setup_tgt_cell
114  return MB_SUCCESS; // no error, but no intersection, decide early to get out
115  // if same plane, still check for gnomonic plane in 2d
116  // if no overlap in 2d, get out
117  if( !overlap3d && plane == planeb ) // CHECK 2D too
118  {
119  for( int j = 0; j < nsBlue; j++ )
120  {
122  srcCoords2D[2 * j + 1] );MB_CHK_ERR( rval );
123  }
124  bool overlap2d = GeomUtil::bounding_boxes_overlap_2d( srcCoords2D, nsBlue, tgtCoords2D, nsTgt, box_error );
125  if( !overlap2d ) return MB_SUCCESS; // we are sure they are not overlapping in 2d , either
126  }
127  }
128 #ifdef ENABLE_DEBUG
129  if( dbg_1 )
130  {
131  std::cout << "tgt " << mb->id_from_handle( tgt ) << "\n";
132  for( int j = 0; j < nsTgt; j++ )
133  {
134  std::cout << tgtCoords[j] << "\n";
135  }
136  std::cout << "src " << mb->id_from_handle( src ) << "\n";
137  for( int j = 0; j < nsBlue; j++ )
138  {
139  std::cout << srcCoords[j] << "\n";
140  }
141  mb->list_entities( &tgt, 1 );
142  mb->list_entities( &src, 1 );
143  }
144 #endif
145 
146  for( int j = 0; j < nsBlue; j++ )
147  {
148  rval = IntxUtils::gnomonic_projection( srcCoords[j], Rsrc, plane, srcCoords2D[2 * j], srcCoords2D[2 * j + 1] );MB_CHK_ERR( rval );
149  }
150 
151 #ifdef ENABLE_DEBUG
152  if( dbg_1 )
153  {
154  std::cout << "gnomonic plane: " << plane << "\n";
155  std::cout << " target src\n";
156  for( int j = 0; j < nsTgt; j++ )
157  {
158  std::cout << tgtCoords2D[2 * j] << " " << tgtCoords2D[2 * j + 1] << "\n";
159  }
160  for( int j = 0; j < nsBlue; j++ )
161  {
162  std::cout << srcCoords2D[2 * j] << " " << srcCoords2D[2 * j + 1] << "\n";
163  }
164  }
165 #endif
166 
167  rval = IntxUtils::EdgeIntersections2( srcCoords2D, nsBlue, tgtCoords2D, nsTgt, markb, markr, P, nP );MB_CHK_ERR( rval );
168 
169  int side[MAXEDGES] = { 0 }; // this refers to what side? source or tgt?
170  int extraPoints =
171  IntxUtils::borderPointsOfXinY2( srcCoords2D, nsBlue, tgtCoords2D, nsTgt, &( P[2 * nP] ), side, epsilon_area );
172  if( extraPoints >= 1 )
173  {
174  for( int k = 0; k < nsBlue; k++ )
175  {
176  if( side[k] )
177  {
178  // this means that vertex k of source is inside convex tgt; mark edges k-1 and k in
179  // src,
180  // as being "intersected" by tgt; (even though they might not be intersected by
181  // other edges, the fact that their apex is inside, is good enough)
182  markb[k] = 1;
183  markb[( k + nsBlue - 1 ) % nsBlue] =
184  1; // it is the previous edge, actually, but instead of doing -1, it is
185  // better to do modulo +3 (modulo 4)
186  // null side b for next call
187  side[k] = 0;
188  }
189  }
190  }
191  nP += extraPoints;
192 
193  extraPoints =
194  IntxUtils::borderPointsOfXinY2( tgtCoords2D, nsTgt, srcCoords2D, nsBlue, &( P[2 * nP] ), side, epsilon_area );
195  if( extraPoints >= 1 )
196  {
197  for( int k = 0; k < nsTgt; k++ )
198  {
199  if( side[k] )
200  {
201  // this is to mark that target edges k-1 and k are intersecting src
202  markr[k] = 1;
203  markr[( k + nsTgt - 1 ) % nsTgt] =
204  1; // it is the previous edge, actually, but instead of doing -1, it is
205  // better to do modulo +3 (modulo 4)
206  // null side b for next call
207  }
208  }
209  }
210  nP += extraPoints;
211 
212  // now sort and orient the points in P, such that they are forming a convex polygon
213  // this will be the foundation of our new mesh
214  // this works if the polygons are convex
215  IntxUtils::SortAndRemoveDoubles2( P, nP, epsilon_1 ); // nP should be at most 8 in the end ?
216  // if there are more than 3 points, some area will be positive
217 
218  if( nP >= 3 )
219  {
220  for( int k = 1; k < nP - 1; k++ )
221  area += IntxUtils::area2D( P, &P[2 * k], &P[2 * k + 2] );
222 #ifdef CHECK_CONVEXITY
223  // each edge should be large enough that we can compute angles between edges
224  for( int k = 0; k < nP; k++ )
225  {
226  int k1 = ( k + 1 ) % nP;
227  int k2 = ( k1 + 1 ) % nP;
228  double orientedArea = IntxUtils::area2D( &P[2 * k], &P[2 * k1], &P[2 * k2] );
229  if( orientedArea < 0 )
230  {
231  std::cout << " oriented area is negative: " << orientedArea << " k:" << k << " target, src:" << tgt
232  << " " << src << " \n";
233  }
234  }
235 #endif
236  }
237 
238  return MB_SUCCESS; // no error
239 }

References moab::IntxUtils::area2D(), moab::IntxUtils::borderPointsOfXinY2(), moab::GeomUtil::bounding_boxes_overlap(), moab::GeomUtil::bounding_boxes_overlap_2d(), moab::Intx2Mesh::box_error, moab::IntxUtils::decide_gnomonic_plane(), moab::IntxUtils::EdgeIntersections2(), moab::Intx2Mesh::epsilon_1, moab::Intx2Mesh::epsilon_area, ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::IntxUtils::gnomonic_projection(), moab::Interface::id_from_handle(), moab::Interface::list_entities(), MAXEDGES, moab::Intx2Mesh::mb, MB_CHK_ERR, MB_SUCCESS, plane, Rsrc, setup_tgt_cell(), moab::IntxUtils::SortAndRemoveDoubles2(), moab::Intx2Mesh::srcConn, moab::Intx2Mesh::srcCoords, moab::Intx2Mesh::srcCoords2D, moab::Intx2Mesh::tgtCoords, and moab::Intx2Mesh::tgtCoords2D.

◆ findNodes()

ErrorCode moab::Intx2MeshOnSphere::findNodes ( EntityHandle  tgt,
int  nsTgt,
EntityHandle  src,
int  nsSrc,
double *  iP,
int  nP 
)
virtual

Implements moab::Intx2Mesh.

Definition at line 246 of file Intx2MeshOnSphere.cpp.

247 {
248 #ifdef ENABLE_DEBUG
249  // first of all, check against target and source vertices
250  //
251  if( dbg_1 )
252  {
253  std::cout << "tgt, src, nP, P " << mb->id_from_handle( tgt ) << " " << mb->id_from_handle( src ) << " " << nP
254  << "\n";
255  for( int n = 0; n < nP; n++ )
256  std::cout << " \t" << iP[2 * n] << "\t" << iP[2 * n + 1] << "\n";
257  }
258 #endif
259 
260  // get the edges for the target triangle; the extra points will be on those edges, saved as
261  // lists (unordered)
262 
263  // first get the list of edges adjacent to the target cell
264  // use the neighTgtEdgeTag
265  EntityHandle adjTgtEdges[MAXEDGES];
266  ErrorCode rval = mb->tag_get_data( neighTgtEdgeTag, &tgt, 1, &( adjTgtEdges[0] ) );MB_CHK_SET_ERR( rval, "can't get edge target tag" );
267  // we know that we have only nsTgt edges here; [nsTgt, MAXEDGES) are ignored, but it is small
268  // potatoes some of them will be handles to the initial vertices from source or target meshes
269 
270  std::vector< EntityHandle > foundIds;
271  foundIds.resize( nP );
272 #ifdef CHECK_CONVEXITY
273  int npBefore1 = nP;
274  int oldNodes = 0;
275  int otherIntx = 0;
276 #endif
277  for( int i = 0; i < nP; i++ )
278  {
279  double* pp = &iP[2 * i]; // iP+2*i
280  // project the point back on the sphere
281  CartVect pos;
282  IntxUtils::reverse_gnomonic_projection( pp[0], pp[1], Rdest, plane, pos );
283  int found = 0;
284  // first, are they on vertices from target or src?
285  // priority is the target mesh (mb2?)
286  int j = 0;
287  EntityHandle outNode = (EntityHandle)0;
288  for( j = 0; j < nsTgt && !found; j++ )
289  {
290  // int node = tgtTri.v[j];
291  double d2 = IntxUtils::dist2( pp, &tgtCoords2D[2 * j] );
292  if( d2 < epsilon_1 )
293  {
294 
295  foundIds[i] = tgtConn[j]; // no new node
296  found = 1;
297 #ifdef CHECK_CONVEXITY
298  oldNodes++;
299 #endif
300 #ifdef ENABLE_DEBUG
301  if( dbg_1 )
302  std::cout << " target node j:" << j << " id:" << mb->id_from_handle( tgtConn[j] )
303  << " 2d coords:" << tgtCoords2D[2 * j] << " " << tgtCoords2D[2 * j + 1] << " d2: " << d2
304  << " \n";
305 #endif
306  }
307  }
308 
309  for( j = 0; j < nsBlue && !found; j++ )
310  {
311  // int node = srcTri.v[j];
312  double d2 = IntxUtils::dist2( pp, &srcCoords2D[2 * j] );
313  if( d2 < epsilon_1 )
314  {
315  // suspect is srcConn[j] corresponding in mbOut
316 
317  foundIds[i] = srcConn[j]; // no new node
318  found = 1;
319 #ifdef CHECK_CONVEXITY
320  oldNodes++;
321 #endif
322 #ifdef ENABLE_DEBUG
323  if( dbg_1 )
324  std::cout << " source node " << j << " " << mb->id_from_handle( srcConn[j] ) << " d2:" << d2
325  << " \n";
326 #endif
327  }
328  }
329 
330  if( !found )
331  {
332  // find the edge it belongs, first, on the red element
333  // look at the minimum area, not at the first below some tolerance
334  double minArea = 1.e+38;
335  int index_min = -1;
336  for( j = 0; j < nsTgt; j++ )
337  {
338  int j1 = ( j + 1 ) % nsTgt;
339  double area = fabs( IntxUtils::area2D( &tgtCoords2D[2 * j], &tgtCoords2D[2 * j1], pp ) );
340  // how to check if pp is between redCoords2D[j] and redCoords2D[j1] ?
341  // they should form a straight line; the sign should be -1
342  double checkx = IntxUtils::dist2( &tgtCoords2D[2 * j], pp ) +
343  IntxUtils::dist2( &tgtCoords2D[2 * j1], pp ) -
344  IntxUtils::dist2( &tgtCoords2D[2 * j], &tgtCoords2D[2 * j1] );
345  if( area < minArea && checkx < 2 * epsilon_1 ) // round off error or not?
346  {
347  index_min = j;
348  minArea = area;
349  }
350  }
351  // verify that index_min is valid
352  assert( index_min >= 0 );
353 
354  if( minArea < epsilon_1 / 2 ) // we found the smallest area, so we think we found the
355  // target edge it belongs
356  {
357  // found the edge; now find if there is a point in the list here
358  // std::vector<EntityHandle> * expts = extraNodesMap[tgtEdges[j]];
359  int indx = TgtEdges.index( adjTgtEdges[index_min] );
360  if( indx < 0 ) // CID 181166 (#1 of 1): Argument cannot be negative (NEGATIVE_RETURNS)
361  {
362  std::cerr << " error in adjacent target edge: " << mb->id_from_handle( adjTgtEdges[index_min] )
363  << "\n";
364  return MB_FAILURE;
365  }
366  std::vector< EntityHandle >* expts = extraNodesVec[indx];
367  // if the points pp is between extra points, then just give that id
368  // if not, create a new point, (check the id)
369  // get the coordinates of the extra points so far
370  int nbExtraNodesSoFar = expts->size();
371  if( nbExtraNodesSoFar > 0 )
372  {
373  std::vector< CartVect > coords1;
374  coords1.resize( nbExtraNodesSoFar );
375  mb->get_coords( &( *expts )[0], nbExtraNodesSoFar, &( coords1[0][0] ) );
376  // std::list<int>::iterator it;
377  for( int k = 0; k < nbExtraNodesSoFar && !found; k++ )
378  {
379  // int pnt = *it;
380  double d2 = ( pos - coords1[k] ).length();
381  if( d2 < 2 * epsilon_1 ) // is this below machine precision?
382  {
383  found = 1;
384  foundIds[i] = ( *expts )[k];
385 #ifdef CHECK_CONVEXITY
386  otherIntx++;
387 #endif
388  }
389  }
390  }
391  if( !found )
392  {
393  // create a new point in 2d (at the intersection)
394  // foundIds[i] = m_num2dPoints;
395  // expts.push_back(m_num2dPoints);
396  // need to create a new node in mbOut
397  // this will be on the edge, and it will be added to the local list
398  rval = mb->create_vertex( pos.array(), outNode );MB_CHK_ERR( rval );
399  ( *expts ).push_back( outNode );
400  // CID 181168; avoid leak storage error
401  rval = mb->add_entities( outSet, &outNode, 1 );MB_CHK_ERR( rval );
402  foundIds[i] = outNode;
403  found = 1;
404  }
405  }
406  }
407  if( !found )
408  {
409  std::cout << " target quad: ";
410  for( int j1 = 0; j1 < nsTgt; j1++ )
411  {
412  std::cout << tgtCoords2D[2 * j1] << " " << tgtCoords2D[2 * j1 + 1] << "\n";
413  }
414  std::cout << " a point pp is not on a target quad " << *pp << " " << pp[1] << " target quad "
415  << mb->id_from_handle( tgt ) << " \n";
416  return MB_FAILURE;
417  }
418  }
419 #ifdef ENABLE_DEBUG
420  if( dbg_1 )
421  {
422  std::cout << " candidate polygon: nP" << nP << " plane: " << plane << "\n";
423  for( int i1 = 0; i1 < nP; i1++ )
424  std::cout << iP[2 * i1] << " " << iP[2 * i1 + 1] << " " << foundIds[i1] << "\n";
425  }
426 #endif
427  // first, find out if we have nodes collapsed; shrink them
428  // we may have to reduce nP
429  // it is possible that some nodes are collapsed after intersection only
430  // nodes will always be in order (convex intersection)
431 #ifdef CHECK_CONVEXITY
432  int npBefore2 = nP;
433 #endif
434  correct_polygon( &foundIds[0], nP );
435  // now we can build the triangles, from P array, with foundIds
436  // we will put them in the out set
437  if( nP >= 3 )
438  {
439  EntityHandle polyNew;
440  rval = mb->create_element( MBPOLYGON, &foundIds[0], nP, polyNew );MB_CHK_ERR( rval );
441  rval = mb->add_entities( outSet, &polyNew, 1 );MB_CHK_ERR( rval );
442 
443  // tag it with the global ids from target and source elements
444  int globalID;
445  rval = mb->tag_get_data( gid, &src, 1, &globalID );MB_CHK_ERR( rval );
446  rval = mb->tag_set_data( srcParentTag, &polyNew, 1, &globalID );MB_CHK_ERR( rval );
447  // if(!parcomm->rank()) std::cout << "Setting parent for " << mb->id_from_handle(polyNew) <<
448  // " : Blue = " << globalID << ", " << mb->id_from_handle(src) << "\t\n";
449  rval = mb->tag_get_data( gid, &tgt, 1, &globalID );MB_CHK_ERR( rval );
450  rval = mb->tag_set_data( tgtParentTag, &polyNew, 1, &globalID );MB_CHK_ERR( rval );
451  // if(parcomm->rank()) std::cout << "Setting parent for " << mb->id_from_handle(polyNew) <<
452  // " : target = " << globalID << ", " << mb->id_from_handle(tgt) << "\n";
453 
454  counting++;
455  rval = mb->tag_set_data( countTag, &polyNew, 1, &counting );MB_CHK_ERR( rval );
456  if( orgSendProcTag )
457  {
458  int org_proc = -1;
459  rval = mb->tag_get_data( orgSendProcTag, &src, 1, &org_proc );MB_CHK_ERR( rval );
460  rval = mb->tag_set_data( orgSendProcTag, &polyNew, 1, &org_proc );MB_CHK_ERR( rval ); // yet another tag
461  }
462 #ifdef CHECK_CONVEXITY
463  // each edge should be large enough that we can compute angles between edges
464  std::vector< double > coords;
465  coords.resize( 3 * nP );
466  rval = mb->get_coords( &foundIds[0], nP, &coords[0] );MB_CHK_ERR( rval );
467  std::vector< CartVect > posi( nP );
468  rval = mb->get_coords( &foundIds[0], nP, &( posi[0][0] ) );MB_CHK_ERR( rval );
469 
470  for( int k = 0; k < nP; k++ )
471  {
472  int k1 = ( k + 1 ) % nP;
473  int k2 = ( k1 + 1 ) % nP;
474  double orientedArea =
475  area_spherical_triangle_lHuiller( &coords[3 * k], &coords[3 * k1], &coords[3 * k2], Rdest );
476  if( orientedArea < 0 )
477  {
478  std::cout << " np before 1 , 2, current " << npBefore1 << " " << npBefore2 << " " << nP << "\n";
479  for( int i = 0; i < nP; i++ )
480  {
481  int nexti = ( i + 1 ) % nP;
482  double lengthEdge = ( posi[i] - posi[nexti] ).length();
483  std::cout << " " << foundIds[i] << " edge en:" << lengthEdge << "\n";
484  }
485  std::cout << " old verts: " << oldNodes << " other intx:" << otherIntx << "\n";
486 
487  std::cout << "rank:" << my_rank << " oriented area in 3d is negative: " << orientedArea << " k:" << k
488  << " target, src:" << tgt << " " << src << " \n";
489  }
490  }
491 #endif
492 
493 #ifdef ENABLE_DEBUG
494  if( dbg_1 )
495  {
496  std::cout << "Counting: " << counting << "\n";
497  std::cout << " polygon " << mb->id_from_handle( polyNew ) << " nodes: " << nP << " :";
498  for( int i1 = 0; i1 < nP; i1++ )
499  std::cout << " " << mb->id_from_handle( foundIds[i1] );
500  std::cout << " plane: " << plane << "\n";
501  std::vector< CartVect > posi( nP );
502  mb->get_coords( &foundIds[0], nP, &( posi[0][0] ) );
503  for( int i1 = 0; i1 < nP; i1++ )
504  std::cout << foundIds[i1] << " " << posi[i1] << "\n";
505 
506  std::stringstream fff;
507  fff << "file0" << counting << ".vtk";
508  rval = mb->write_mesh( fff.str().c_str(), &outSet, 1 );MB_CHK_ERR( rval );
509  }
510 #endif
511  }
512  // else {
513  // std::cout << "[[FAILURE]] Number of vertices in polygon is less than 3\n";
514  // }
515  // disable_debug();
516  return MB_SUCCESS;
517 }

References moab::Interface::add_entities(), moab::IntxUtils::area2D(), moab::CartVect::array(), moab::Intx2Mesh::correct_polygon(), moab::Intx2Mesh::counting, moab::Intx2Mesh::countTag, moab::Interface::create_element(), moab::Interface::create_vertex(), moab::IntxUtils::dist2(), moab::Intx2Mesh::epsilon_1, ErrorCode, moab::Intx2Mesh::extraNodesVec, moab::Interface::get_coords(), moab::Intx2Mesh::gid, moab::Interface::id_from_handle(), moab::Range::index(), length(), MAXEDGES, moab::Intx2Mesh::mb, MB_CHK_ERR, MB_CHK_SET_ERR, MB_SUCCESS, MBPOLYGON, moab::Intx2Mesh::my_rank, moab::Intx2Mesh::neighTgtEdgeTag, moab::Intx2Mesh::orgSendProcTag, moab::Intx2Mesh::outSet, plane, Rdest, moab::IntxUtils::reverse_gnomonic_projection(), moab::Intx2Mesh::srcConn, moab::Intx2Mesh::srcCoords2D, moab::Intx2Mesh::srcParentTag, moab::Interface::tag_get_data(), moab::Interface::tag_set_data(), moab::Intx2Mesh::tgtConn, moab::Intx2Mesh::tgtCoords2D, moab::Intx2Mesh::TgtEdges, moab::Intx2Mesh::tgtParentTag, and moab::Interface::write_mesh().

◆ set_radius_destination_mesh()

void moab::Intx2MeshOnSphere::set_radius_destination_mesh ( double  radius)
inline

Definition at line 27 of file Intx2MeshOnSphere.hpp.

28  {
29  Rdest = radius;
30  }

References radius, and Rdest.

Referenced by moab::TempestRemapper::ConstructCoveringSet(), main(), test_intx_in_parallel_elem_based(), and update_tracer().

◆ set_radius_source_mesh()

void moab::Intx2MeshOnSphere::set_radius_source_mesh ( double  radius)
inline

Definition at line 23 of file Intx2MeshOnSphere.hpp.

24  {
25  Rsrc = radius;
26  }

References radius, and Rsrc.

Referenced by moab::TempestRemapper::ConstructCoveringSet(), main(), test_intx_in_parallel_elem_based(), and update_tracer().

◆ setup_tgt_cell()

double moab::Intx2MeshOnSphere::setup_tgt_cell ( EntityHandle  tgt,
int &  nsTgt 
)
virtual

Implements moab::Intx2Mesh.

Definition at line 37 of file Intx2MeshOnSphere.cpp.

38 {
39 
40  // get coordinates of the target quad, to decide the gnomonic plane
41  double cellArea = 0;
42 
43  int num_nodes;
44  ErrorCode rval = mb->get_connectivity( tgt, tgtConn, num_nodes );MB_CHK_ERR_RET_VAL( rval, cellArea );
45 
46  nsTgt = num_nodes;
47  // account for possible padded polygons
48  while( tgtConn[nsTgt - 2] == tgtConn[nsTgt - 1] && nsTgt > 3 )
49  nsTgt--;
50 
51  // CartVect coords[4];
52  rval = mb->get_coords( tgtConn, nsTgt, &( tgtCoords[0][0] ) );MB_CHK_ERR_RET_VAL( rval, cellArea );
53 
54  CartVect middle = tgtCoords[0];
55  for( int i = 1; i < nsTgt; i++ )
56  middle += tgtCoords[i];
57  middle = 1. / nsTgt * middle;
58 
59  IntxUtils::decide_gnomonic_plane( middle, plane ); // output the plane
60  for( int j = 0; j < nsTgt; j++ )
61  {
62  // populate coords in the plane for intersection
63  // they should be oriented correctly, positively
64  rval = IntxUtils::gnomonic_projection( tgtCoords[j], Rdest, plane, tgtCoords2D[2 * j], tgtCoords2D[2 * j + 1] );MB_CHK_ERR_RET_VAL( rval, cellArea );
65  }
66 
67  for( int j = 1; j < nsTgt - 1; j++ )
68  cellArea += IntxUtils::area2D( &tgtCoords2D[0], &tgtCoords2D[2 * j], &tgtCoords2D[2 * j + 2] );
69 
70  // take target coords in order and compute area in plane
71  return cellArea;
72 }

References moab::IntxUtils::area2D(), moab::IntxUtils::decide_gnomonic_plane(), ErrorCode, moab::Interface::get_connectivity(), moab::Interface::get_coords(), moab::IntxUtils::gnomonic_projection(), moab::Intx2Mesh::mb, MB_CHK_ERR_RET_VAL, plane, Rdest, moab::Intx2Mesh::tgtConn, moab::Intx2Mesh::tgtCoords, and moab::Intx2Mesh::tgtCoords2D.

Referenced by computeIntersectionBetweenTgtAndSrc().

◆ update_tracer_data()

ErrorCode moab::Intx2MeshOnSphere::update_tracer_data ( EntityHandle  out_set,
Tag tagElem,
Tag tagArea 
)

TODO: VSM: Its unclear whether we need the source or destination radius here.

Definition at line 519 of file Intx2MeshOnSphere.cpp.

520 {
521  EntityHandle dum = 0;
522 
523  Tag corrTag;
525  &dum ); // it should have been created
526  MB_CHK_SET_ERR( rval, "can't get correlation tag" );
527 
528  // get all polygons out of out_set; then see where are they coming from
529  Range polys;
530  rval = mb->get_entities_by_dimension( out_set, 2, polys );MB_CHK_SET_ERR( rval, "can't get polygons out" );
531 
532  // rs2 is the target range, arrival; rs1 is src, departure;
533  // there is a connection between rs1 and rs2, through the corrTag
534  // corrTag is __correlation
535  // basically, mb->tag_get_data(corrTag, &(tgtPoly), 1, &srcPoly);
536  // also, mb->tag_get_data(corrTag, &(srcPoly), 1, &tgtPoly);
537  // we start from rs2 existing, then we have to update something
538 
539  // tagElem will have multiple tracers
540  int numTracers = 0;
541  rval = mb->tag_get_length( tagElem, numTracers );MB_CHK_SET_ERR( rval, "can't get number of tracers in simulation" );
542  if( numTracers < 1 ) MB_CHK_SET_ERR( MB_FAILURE, "no tracers data" );
543 
544  std::vector< double > currentVals( rs2.size() * numTracers );
545  rval = mb->tag_get_data( tagElem, rs2, &currentVals[0] );MB_CHK_SET_ERR( rval, "can't get existing tracers values" );
546 
547  // create new tuple list for tracers to other processors, from remote_cells
548 #ifdef MOAB_HAVE_MPI
549  if( remote_cells )
550  {
551  int n = remote_cells->get_n();
552  if( n > 0 )
553  {
554  remote_cells_with_tracers = new TupleList();
555  remote_cells_with_tracers->initialize( 2, 0, 1, numTracers,
556  n ); // tracers are in these tuples
557  remote_cells_with_tracers->enableWriteAccess();
558  for( int i = 0; i < n; i++ )
559  {
560  remote_cells_with_tracers->vi_wr[2 * i] = remote_cells->vi_wr[2 * i];
561  remote_cells_with_tracers->vi_wr[2 * i + 1] = remote_cells->vi_wr[2 * i + 1];
562  // remote_cells->vr_wr[i] = 0.; will have a different tuple for communication
563  remote_cells_with_tracers->vul_wr[i] =
564  remote_cells->vul_wr[i]; // this is the corresponding target cell (arrival)
565  for( int k = 0; k < numTracers; k++ )
566  remote_cells_with_tracers->vr_wr[numTracers * i + k] = 0; // initialize tracers to be transported
567  remote_cells_with_tracers->inc_n();
568  }
569  }
570  delete remote_cells;
571  remote_cells = NULL;
572  }
573 #endif
574  // for each polygon, we have 2 indices: target and source parents
575  // we need index source to update index tgt?
576  std::vector< double > newValues( rs2.size() * numTracers,
577  0. ); // initialize with 0 all of them
578  // area of the polygon * conc on target (old) current quantity
579  // finally, divide by the area of the tgt
580  double check_intx_area = 0.;
581  moab::IntxAreaUtils intxAreas( this->areaMethod ); // use_lHuiller = true
582  for( Range::iterator it = polys.begin(); it != polys.end(); ++it )
583  {
584  EntityHandle poly = *it;
585  int srcIndex, tgtIndex;
586  rval = mb->tag_get_data( srcParentTag, &poly, 1, &srcIndex );MB_CHK_SET_ERR( rval, "can't get source tag" );
587 
588  EntityHandle src = rs1[srcIndex - 1]; // big assumption, it should work for meshes where global id is the same
589  // as element handle (ordered from 1 to number of elements); should be OK for Homme meshes
590  rval = mb->tag_get_data( tgtParentTag, &poly, 1, &tgtIndex );MB_CHK_SET_ERR( rval, "can't get target tag" );
591  // EntityHandle target = rs2[tgtIndex];
592  // big assumption here, target and source are "parallel" ;we should have an index from
593  // source to target (so a deformed source corresponds to an arrival tgt)
594  /// TODO: VSM: Its unclear whether we need the source or destination radius here.
595  double radius = Rsrc;
596  double areap = intxAreas.area_spherical_element( mb, poly, radius );
597  check_intx_area += areap;
598  // so the departure cell at time t (srcIndex) covers a portion of a tgtCell
599  // that quantity will be transported to the tgtCell at time t+dt
600  // the source corresponds to a target arrival
601  EntityHandle tgtArr;
602  rval = mb->tag_get_data( corrTag, &src, 1, &tgtArr );
603  if( 0 == tgtArr || MB_TAG_NOT_FOUND == rval )
604  {
605 #ifdef MOAB_HAVE_MPI
606  if( !remote_cells_with_tracers ) MB_CHK_SET_ERR( MB_FAILURE, "no remote cells, failure\n" );
607  // maybe the element is remote, from another processor
608  int global_id_src;
609  rval = mb->tag_get_data( gid, &src, 1, &global_id_src );MB_CHK_SET_ERR( rval, "can't get arrival target for corresponding source gid" );
610  // find the
611  int index_in_remote = remote_cells_with_tracers->find( 1, global_id_src );
612  if( index_in_remote == -1 )
613  MB_CHK_SET_ERR( MB_FAILURE, "can't find the global id element in remote cells\n" );
614  for( int k = 0; k < numTracers; k++ )
615  remote_cells_with_tracers->vr_wr[index_in_remote * numTracers + k] +=
616  currentVals[numTracers * ( tgtIndex - 1 ) + k] * areap;
617 #endif
618  }
619  else if( MB_SUCCESS == rval )
620  {
621  int arrTgtIndex = rs2.index( tgtArr );
622  if( -1 == arrTgtIndex ) MB_CHK_SET_ERR( MB_FAILURE, "can't find the target arrival index" );
623  for( int k = 0; k < numTracers; k++ )
624  newValues[numTracers * arrTgtIndex + k] += currentVals[( tgtIndex - 1 ) * numTracers + k] * areap;
625  }
626 
627  else
628  MB_CHK_SET_ERR( rval, "can't get arrival target for corresponding " );
629  }
630  // now, send back the remote_cells_with_tracers to the processors they came from, with the
631  // updated values for the tracer mass in a cell
632 #ifdef MOAB_HAVE_MPI
633  if( remote_cells_with_tracers )
634  {
635  // so this means that some cells will be sent back with tracer info to the procs they were
636  // sent from
637  ( parcomm->proc_config().crystal_router() )->gs_transfer( 1, *remote_cells_with_tracers, 0 );
638  // now, look at the global id, find the proper "tgt" cell with that index and update its
639  // mass
640  // remote_cells->print("remote cells after routing");
641  int n = remote_cells_with_tracers->get_n();
642  for( int j = 0; j < n; j++ )
643  {
644  EntityHandle tgtCell = remote_cells_with_tracers->vul_rd[j]; // entity handle sent back
645  int arrTgtIndex = rs2.index( tgtCell );
646  if( -1 == arrTgtIndex ) MB_CHK_SET_ERR( MB_FAILURE, "can't find the target arrival index" );
647  for( int k = 0; k < numTracers; k++ )
648  newValues[arrTgtIndex * numTracers + k] += remote_cells_with_tracers->vr_rd[j * numTracers + k];
649  }
650  }
651 #endif /* MOAB_HAVE_MPI */
652  // now divide by target area (current)
653  int j = 0;
654  Range::iterator iter = rs2.begin();
655  void* data = NULL; // used for stored area
656  int count = 0;
657  std::vector< double > total_mass_local( numTracers, 0. );
658  while( iter != rs2.end() )
659  {
660  rval = mb->tag_iterate( tagArea, iter, rs2.end(), count, data );MB_CHK_SET_ERR( rval, "can't tag iterate" );
661  double* ptrArea = (double*)data;
662  for( int i = 0; i < count; i++, ++iter, j++, ptrArea++ )
663  {
664  for( int k = 0; k < numTracers; k++ )
665  {
666  total_mass_local[k] += newValues[j * numTracers + k];
667  newValues[j * numTracers + k] /= ( *ptrArea );
668  }
669  }
670  }
671  rval = mb->tag_set_data( tagElem, rs2, &newValues[0] );MB_CHK_SET_ERR( rval, "can't set new values tag" );
672 
673 #ifdef MOAB_HAVE_MPI
674  std::vector< double > total_mass( numTracers, 0. );
675  double total_intx_area = 0;
676  int mpi_err =
677  MPI_Reduce( &total_mass_local[0], &total_mass[0], numTracers, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
678  if( MPI_SUCCESS != mpi_err ) return MB_FAILURE;
679  // now reduce total area
680  mpi_err = MPI_Reduce( &check_intx_area, &total_intx_area, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
681  if( MPI_SUCCESS != mpi_err ) return MB_FAILURE;
682  if( my_rank == 0 )
683  {
684  for( int k = 0; k < numTracers; k++ )
685  std::cout << "total mass now tracer k=" << k + 1 << " " << total_mass[k] << "\n";
686  std::cout << "check: total intersection area: (4 * M_PI * R^2): " << 4 * M_PI * Rsrc * Rsrc << " "
687  << total_intx_area << "\n";
688  }
689 
690  if( remote_cells_with_tracers )
691  {
692  delete remote_cells_with_tracers;
693  remote_cells_with_tracers = NULL;
694  }
695 #else
696  for( int k = 0; k < numTracers; k++ )
697  std::cout << "total mass now tracer k=" << k + 1 << " " << total_mass_local[k] << "\n";
698  std::cout << "check: total intersection area: (4 * M_PI * R^2): " << 4 * M_PI * Rsrc * Rsrc << " "
699  << check_intx_area << "\n";
700 #endif
701  return MB_SUCCESS;
702 }

References moab::IntxAreaUtils::area_spherical_element(), areaMethod, moab::Range::begin(), CORRTAGNAME, moab::dum, moab::Range::end(), ErrorCode, moab::Interface::get_entities_by_dimension(), moab::Intx2Mesh::gid, moab::Range::index(), moab::Intx2Mesh::mb, MB_CHK_SET_ERR, MB_SUCCESS, MB_TAG_DENSE, MB_TAG_NOT_FOUND, MB_TYPE_HANDLE, moab::Intx2Mesh::my_rank, radius, moab::Intx2Mesh::rs1, moab::Intx2Mesh::rs2, Rsrc, moab::Range::size(), moab::Intx2Mesh::srcParentTag, moab::Interface::tag_get_data(), moab::Interface::tag_get_handle(), moab::Interface::tag_get_length(), moab::Interface::tag_iterate(), moab::Interface::tag_set_data(), and moab::Intx2Mesh::tgtParentTag.

Referenced by compute_tracer_case1(), update_tracer(), and update_tracer_test().

Member Data Documentation

◆ areaMethod

const IntxAreaUtils::AreaMethod moab::Intx2MeshOnSphere::areaMethod

Definition at line 58 of file Intx2MeshOnSphere.hpp.

Referenced by update_tracer_data().

◆ plane

int moab::Intx2MeshOnSphere::plane
private

◆ Rdest

double moab::Intx2MeshOnSphere::Rdest
private

Definition at line 62 of file Intx2MeshOnSphere.hpp.

Referenced by findNodes(), set_radius_destination_mesh(), and setup_tgt_cell().

◆ Rsrc

double moab::Intx2MeshOnSphere::Rsrc
private

The documentation for this class was generated from the following files: