Mesh Oriented datABase  (version 5.6.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 ()
 
virtual ErrorCode filterByMask (Range &cells)
 
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
 
Tag imaskTag
 for coverage mesh, will store the original sender More...
 
const EntityHandletgtConn
 
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 28 of file Intx2MeshOnSphere.cpp.

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

◆ ~Intx2MeshOnSphere()

moab::Intx2MeshOnSphere::~Intx2MeshOnSphere ( )
virtual

Definition at line 33 of file Intx2MeshOnSphere.cpp.

33 {}

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 78 of file Intx2MeshOnSphere.cpp.

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

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, 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 248 of file Intx2MeshOnSphere.cpp.

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

References moab::Interface::add_entities(), moab::IntxUtils::area2D(), moab::IntxAreaUtils::area_spherical_triangle(), 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, 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(), and main().

◆ 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(), and main().

◆ setup_tgt_cell()

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

Implements moab::Intx2Mesh.

Definition at line 38 of file Intx2MeshOnSphere.cpp.

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

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 522 of file Intx2MeshOnSphere.cpp.

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

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.

Member Data Documentation

◆ areaMethod

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

Definition at line 60 of file Intx2MeshOnSphere.hpp.

Referenced by update_tracer_data().

◆ plane

int moab::Intx2MeshOnSphere::plane
private

◆ Rdest

double moab::Intx2MeshOnSphere::Rdest
private

Definition at line 64 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: