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

#include <ParallelMergeMesh.hpp>

+ Collaboration diagram for moab::ParallelMergeMesh:

Public Member Functions

 ParallelMergeMesh (ParallelComm *pc, const double epsilon)
 
ErrorCode merge (EntityHandle levelset=0, bool skip_local_merge=false, int dim=-1)
 

Private Member Functions

ErrorCode PerformMerge (EntityHandle levelset=0, bool skip_local_merge=false, int dim=-1)
 
ErrorCode PopulateMySkinEnts (const EntityHandle meshset, int dim, bool skip_local_merge=false)
 
ErrorCode GetGlobalBox (double *gbox)
 
ErrorCode PopulateMyTup (double *gbox)
 
ErrorCode PopulateMyMatches ()
 
ErrorCode SortMyMatches ()
 
ErrorCode TagSharedElements (int dim)
 
void CleanUp ()
 
ErrorCode PartitionGlobalBox (double *gbox, double *lengths, int *parts)
 

Static Private Member Functions

static int PartitionSide (double sideLeng, double restLen, unsigned numProcs, bool altRatio)
 
static void SwapTuples (TupleList &tup, unsigned long a, unsigned long b)
 
static void SortTuplesByReal (TupleList &tup, double eps2=0)
 
static void PerformRealSort (TupleList &tup, unsigned long left, unsigned long right, double eps2, uint tup_mr)
 
static bool TupleGreaterThan (TupleList &tup, unsigned long vrI, unsigned long vrJ, double eps2, uint tup_mr)
 

Private Attributes

ParallelCommmyPcomm
 
InterfacemyMB
 
std::vector< RangemySkinEnts
 
double myEps
 
TupleList myTup
 
TupleList myMatches
 
gs_data::crystal_data myCD
 

Detailed Description

Definition at line 24 of file ParallelMergeMesh.hpp.

Constructor & Destructor Documentation

◆ ParallelMergeMesh()

moab::ParallelMergeMesh::ParallelMergeMesh ( ParallelComm pc,
const double  epsilon 
)

Definition at line 20 of file ParallelMergeMesh.cpp.

20  : myPcomm( pc ), myEps( epsilon )
21 {
22  myMB = pc->get_moab();
23  mySkinEnts.resize( 4 );
24 }

References moab::ParallelComm::get_moab(), myMB, and mySkinEnts.

Member Function Documentation

◆ CleanUp()

void moab::ParallelMergeMesh::CleanUp ( )
private

Definition at line 585 of file ParallelMergeMesh.cpp.

586 {
587  // The reset operation is now safe and avoids a double free()
588  myMatches.reset();
589  myTup.reset();
590  myCD.reset();
591 }

References myCD, myMatches, myTup, and moab::TupleList::reset().

Referenced by merge().

◆ GetGlobalBox()

ErrorCode moab::ParallelMergeMesh::GetGlobalBox ( double *  gbox)
private

Definition at line 140 of file ParallelMergeMesh.cpp.

141 {
142  /*Get Bounding Box*/
143  BoundBox box;
144  if( mySkinEnts[0].size() != 0 )
145  {
146  MB_CHK_ERR( box.update( *myMB, mySkinEnts[0] ) );
147  }
148 
149  // Invert the max
150  box.bMax *= -1;
151 
152  /*Communicate to all processors*/
153  MPI_Allreduce( (void*)&box, gbox, 6, MPI_DOUBLE, MPI_MIN, myPcomm->comm() );
154 
155  /*Assemble Global Bounding Box*/
156  // Flip the max back
157  for( int i = 3; i < 6; i++ )
158  {
159  gbox[i] *= -1;
160  }
161  return MB_SUCCESS;
162 }

References moab::BoundBox::bMax, moab::ParallelComm::comm(), MB_CHK_ERR, MB_SUCCESS, myMB, myPcomm, mySkinEnts, and moab::BoundBox::update().

Referenced by PerformMerge().

◆ merge()

ErrorCode moab::ParallelMergeMesh::merge ( EntityHandle  levelset = 0,
bool  skip_local_merge = false,
int  dim = -1 
)

Definition at line 28 of file ParallelMergeMesh.cpp.

29 {
30  MB_CHK_ERR( PerformMerge( levelset, skip_local_merge, dim ) );
31  CleanUp();
32  return MB_SUCCESS;
33 }

References CleanUp(), MB_CHK_ERR, MB_SUCCESS, and PerformMerge().

Referenced by moab::MeshGeneration::BrickInstance(), moab::NCHelperDomain::create_mesh(), moab::NCHelperScrip::create_mesh(), iMOAB_MergeVertices(), and main().

◆ PartitionGlobalBox()

ErrorCode moab::ParallelMergeMesh::PartitionGlobalBox ( double *  gbox,
double *  lengths,
int *  parts 
)
private

Definition at line 283 of file ParallelMergeMesh.cpp.

284 {
285  // Determine the length of each side
286  double xLen = gbox[3] - gbox[0];
287  double yLen = gbox[4] - gbox[1];
288  double zLen = gbox[5] - gbox[2];
289  // avoid division by zero for deciding the way to partition the global box
290  // make all sides of the box at least myEps
291  // it can be zero in some cases, so not possible to compare the ratios :) for best division
292  if( xLen < myEps ) xLen = myEps;
293  if( yLen < myEps ) yLen = myEps;
294  if( zLen < myEps ) zLen = myEps;
295  unsigned numProcs = myPcomm->size();
296 
297  // Partition sides from the longest to shortest lengths
298  // If x is the longest side
299  if( xLen >= yLen && xLen >= zLen )
300  {
301  parts[0] = PartitionSide( xLen, yLen * zLen, numProcs, true );
302  numProcs /= parts[0];
303  // If y is second longest
304  if( yLen >= zLen )
305  {
306  parts[1] = PartitionSide( yLen, zLen, numProcs, false );
307  parts[2] = numProcs / parts[1];
308  }
309  // If z is the longer
310  else
311  {
312  parts[2] = PartitionSide( zLen, yLen, numProcs, false );
313  parts[1] = numProcs / parts[2];
314  }
315  }
316  // If y is the longest side
317  else if( yLen >= zLen )
318  {
319  parts[1] = PartitionSide( yLen, xLen * zLen, numProcs, true );
320  numProcs /= parts[1];
321  // If x is the second longest
322  if( xLen >= zLen )
323  {
324  parts[0] = PartitionSide( xLen, zLen, numProcs, false );
325  parts[2] = numProcs / parts[0];
326  }
327  // If z is the second longest
328  else
329  {
330  parts[2] = PartitionSide( zLen, xLen, numProcs, false );
331  parts[0] = numProcs / parts[2];
332  }
333  }
334  // If z is the longest side
335  else
336  {
337  parts[2] = PartitionSide( zLen, xLen * yLen, numProcs, true );
338  numProcs /= parts[2];
339  // If x is the second longest
340  if( xLen >= yLen )
341  {
342  parts[0] = PartitionSide( xLen, yLen, numProcs, false );
343  parts[1] = numProcs / parts[0];
344  }
345  // If y is the second longest
346  else
347  {
348  parts[1] = PartitionSide( yLen, xLen, numProcs, false );
349  parts[0] = numProcs / parts[1];
350  }
351  }
352 
353  // Divide up each side to give the lengths
354  lengths[0] = xLen / (double)parts[0];
355  lengths[1] = yLen / (double)parts[1];
356  lengths[2] = zLen / (double)parts[2];
357  return MB_SUCCESS;
358 }

References MB_SUCCESS, myEps, myPcomm, PartitionSide(), and moab::ParallelComm::size().

Referenced by PopulateMyTup().

◆ PartitionSide()

int moab::ParallelMergeMesh::PartitionSide ( double  sideLeng,
double  restLen,
unsigned  numProcs,
bool  altRatio 
)
staticprivate

Definition at line 361 of file ParallelMergeMesh.cpp.

362 {
363  // If theres only 1 processor, then just return 1
364  if( numProcs == 1 )
365  {
366  return 1;
367  }
368  // Initialize with the ratio of 1 proc
369  double ratio = -DBL_MAX;
370  unsigned factor = 1;
371  // We need to be able to save the last ratio and factor (for comparison)
372  double oldRatio = ratio;
373  double oldFactor = 1;
374 
375  // This is the ratio were shooting for
376  double goalRatio = sideLen / restLen;
377 
378  // Calculate the divisor and numerator power
379  // This avoid if statements in the loop and is useful since both calculations are similar
380  double divisor, p;
381  if( altRatio )
382  {
383  divisor = (double)numProcs * sideLen;
384  p = 3;
385  }
386  else
387  {
388  divisor = (double)numProcs;
389  p = 2;
390  }
391 
392  // Find each possible factor
393  for( unsigned i = 2; i <= numProcs / 2; i++ )
394  {
395  // If it is a factor...
396  if( numProcs % i == 0 )
397  {
398  // We need to save the past factor
399  oldRatio = ratio;
400  oldFactor = factor;
401  // There are 2 different ways to calculate the ratio:
402  // Comparing 1 side to 2 sides: (i*i*i)/(numProcs*x)
403  // Justification: We have a ratio x:y:z (side Lengths) == a:b:c (procs). So a=kx,
404  // b=ky, c=kz. Also, abc=n (numProcs) => bc = n/a. Also, a=kx => k=a/x => 1/k=x/a And so
405  // x/(yz) == (kx)/(kyz) == (kx)/(kykz(1/k)) == a/(bc(x/a)) == a/((n/a)(x/a)) == a^3/(nx).
406  // Comparing 1 side to 1 side: (i*i)/numprocs
407  // Justification: i/(n/i) == i^2/n
408  ratio = pow( (double)i, p ) / divisor;
409  factor = i;
410  // Once we have passed the goal ratio, we can break since we'll only move away from the
411  // goal ratio
412  if( ratio >= goalRatio )
413  {
414  break;
415  }
416  }
417  }
418  // If we haven't reached the goal ratio yet, check out factor = numProcs
419  if( ratio < goalRatio )
420  {
421  oldRatio = ratio;
422  oldFactor = factor;
423  factor = numProcs;
424  ratio = pow( (double)numProcs, p ) / divisor;
425  }
426 
427  // Figure out if our oldRatio is better than ratio
428  if( fabs( ratio - goalRatio ) > fabs( oldRatio - goalRatio ) )
429  {
430  factor = oldFactor;
431  }
432  // Return our findings
433  return factor;
434 }

Referenced by PartitionGlobalBox().

◆ PerformMerge()

ErrorCode moab::ParallelMergeMesh::PerformMerge ( EntityHandle  levelset = 0,
bool  skip_local_merge = false,
int  dim = -1 
)
private

Definition at line 36 of file ParallelMergeMesh.cpp.

37 {
38  // Get the mesh dimension
39  if( dim < 0 )
40  {
41  MB_CHK_ERR( myMB->get_dimension( dim ) );
42  }
43 
44  // Get the local skin elements
45  MB_CHK_ERR( PopulateMySkinEnts( levelset, dim, skip_local_merge ) );
46  // If there is only 1 proc, we can return now
47  if( myPcomm->size() == 1 )
48  {
49  return MB_SUCCESS;
50  }
51 
52  // Determine the global bounding box
53  double gbox[6];
54  MB_CHK_ERR( GetGlobalBox( gbox ) );
55 
56  /* Assemble The Destination Tuples */
57  // Get a list of tuples which contain (toProc, handle, x,y,z)
58  myTup.initialize( 1, 0, 1, 3, mySkinEnts[0].size() );
59  MB_CHK_ERR( PopulateMyTup( gbox ) );
60 
61  /* Gather-Scatter Tuple
62  -tup comes out as (remoteProc,handle,x,y,z) */
63  myCD.initialize( myPcomm->comm() );
64 
65  // 1 represents dynamic tuple, 0 represents index of the processor to send to
66  myCD.gs_transfer( 1, myTup, 0 );
67 
68  /* Sort By X,Y,Z
69  -Utilizes a custom quick sort incorporating epsilon*/
71 
72  // Initialize another tuple list for matches
73  myMatches.initialize( 2, 0, 2, 0, mySkinEnts[0].size() );
74 
75  // ID the matching tuples
77 
78  // We can free up the tuple myTup now
79  myTup.reset();
80 
81  /*Gather-Scatter Again*/
82  // 1 represents dynamic list, 0 represents proc index to send tuple to
83  myCD.gs_transfer( 1, myMatches, 0 );
84  // We can free up the crystal router now
85  myCD.reset();
86 
87  // Sort the matches tuple list
88  SortMyMatches();
89 
90  // Tag the shared elements
91  MB_CHK_ERR( TagSharedElements( dim ) );
92 
93  // Free up the matches tuples
94  myMatches.reset();
95  return MB_SUCCESS;
96 }

References moab::ParallelComm::comm(), moab::Interface::get_dimension(), GetGlobalBox(), moab::TupleList::initialize(), MB_CHK_ERR, MB_SUCCESS, myCD, myEps, myMatches, myMB, myPcomm, mySkinEnts, myTup, PopulateMyMatches(), PopulateMySkinEnts(), PopulateMyTup(), moab::TupleList::reset(), moab::ParallelComm::size(), SortMyMatches(), SortTuplesByReal(), and TagSharedElements().

Referenced by merge().

◆ PerformRealSort()

void moab::ParallelMergeMesh::PerformRealSort ( TupleList tup,
unsigned long  left,
unsigned long  right,
double  eps2,
uint  tup_mr 
)
staticprivate

Definition at line 661 of file ParallelMergeMesh.cpp.

666 {
667  // If list size is only 1 or 0 return
668  if( left + 1 >= right )
669  {
670  return;
671  }
672  unsigned long swap = left, tup_l = left * tup_mr, tup_t = tup_l + tup_mr;
673 
674  // Swap the median with the left position for a (hopefully) better split
675  SwapTuples( tup, left, ( left + right ) / 2 );
676 
677  // Partition the data
678  for( unsigned long t = left + 1; t < right; t++ )
679  {
680  // If the left value(pivot) is greater than t_val, swap it into swap
681  if( TupleGreaterThan( tup, tup_l, tup_t, eps, tup_mr ) )
682  {
683  swap++;
684  SwapTuples( tup, swap, t );
685  }
686  tup_t += tup_mr;
687  }
688 
689  // Swap so that position swap is in the correct position
690  SwapTuples( tup, left, swap );
691 
692  // Sort left and right of swap
693  PerformRealSort( tup, left, swap, eps, tup_mr );
694  PerformRealSort( tup, swap + 1, right, eps, tup_mr );
695 }

References SwapTuples(), and TupleGreaterThan().

Referenced by SortTuplesByReal().

◆ PopulateMyMatches()

ErrorCode moab::ParallelMergeMesh::PopulateMyMatches ( )
private

Definition at line 437 of file ParallelMergeMesh.cpp.

438 {
439  // Counters for accessing tuples more efficiently
440  unsigned long i = 0, mat_i = 0, mat_ul = 0, j = 0, tup_r = 0;
441  double eps2 = myEps * myEps;
442 
443  uint tup_mi, tup_ml, tup_mul, tup_mr;
444  myTup.getTupleSize( tup_mi, tup_ml, tup_mul, tup_mr );
445 
446  bool canWrite = myMatches.get_writeEnabled();
447  if( !canWrite ) myMatches.enableWriteAccess();
448 
449  while( ( i + 1 ) < myTup.get_n() )
450  {
451  // Proximity Comparison
452  double xi = myTup.vr_rd[tup_r], yi = myTup.vr_rd[tup_r + 1], zi = myTup.vr_rd[tup_r + 2];
453 
454  bool done = false;
455  while( !done )
456  {
457  j++;
458  tup_r += tup_mr;
459  if( j >= myTup.get_n() )
460  {
461  break;
462  }
463  CartVect cv( myTup.vr_rd[tup_r] - xi, myTup.vr_rd[tup_r + 1] - yi, myTup.vr_rd[tup_r + 2] - zi );
464  if( cv.length_squared() > eps2 )
465  {
466  done = true;
467  }
468  }
469  // Allocate the tuple list before adding matches
470  while( myMatches.get_n() + ( j - i ) * ( j - i - 1 ) >= myMatches.get_max() )
471  {
473  }
474 
475  // We now know that tuples [i to j) exclusive match.
476  // If n tuples match, n*(n-1) match tuples will be made
477  // tuples are of the form (proc1,proc2,handle1,handle2)
478  if( i + 1 < j )
479  {
480  int kproc = i * tup_mi;
481  unsigned long khand = i * tup_mul;
482  for( unsigned long k = i; k < j; k++ )
483  {
484  int lproc = kproc + tup_mi;
485  unsigned long lhand = khand + tup_mul;
486  for( unsigned long l = k + 1; l < j; l++ )
487  {
488  myMatches.vi_wr[mat_i++] = myTup.vi_rd[kproc]; // proc1
489  myMatches.vi_wr[mat_i++] = myTup.vi_rd[lproc]; // proc2
490  myMatches.vul_wr[mat_ul++] = myTup.vul_rd[khand]; // handle1
491  myMatches.vul_wr[mat_ul++] = myTup.vul_rd[lhand]; // handle2
492  myMatches.inc_n();
493 
494  myMatches.vi_wr[mat_i++] = myTup.vi_rd[lproc]; // proc1
495  myMatches.vi_wr[mat_i++] = myTup.vi_rd[kproc]; // proc2
496  myMatches.vul_wr[mat_ul++] = myTup.vul_rd[lhand]; // handle1
497  myMatches.vul_wr[mat_ul++] = myTup.vul_rd[khand]; // handle2
498  myMatches.inc_n();
499  lproc += tup_mi;
500  lhand += tup_mul;
501  }
502  kproc += tup_mi;
503  khand += tup_mul;
504  } // End for(int k...
505  }
506  i = j;
507  } // End while(i+1<tup.n)
508 
509  if( !canWrite ) myMatches.disableWriteAccess();
510  return MB_SUCCESS;
511 }

References moab::TupleList::disableWriteAccess(), moab::TupleList::enableWriteAccess(), moab::TupleList::get_max(), moab::TupleList::get_n(), moab::TupleList::get_writeEnabled(), moab::TupleList::getTupleSize(), moab::TupleList::inc_n(), moab::CartVect::length_squared(), MB_SUCCESS, myEps, myMatches, myTup, moab::TupleList::resize(), moab::TupleList::vi_rd, moab::TupleList::vi_wr, moab::TupleList::vr_rd, moab::TupleList::vul_rd, and moab::TupleList::vul_wr.

Referenced by PerformMerge().

◆ PopulateMySkinEnts()

ErrorCode moab::ParallelMergeMesh::PopulateMySkinEnts ( const EntityHandle  meshset,
int  dim,
bool  skip_local_merge = false 
)
private

Definition at line 99 of file ParallelMergeMesh.cpp.

100 {
101  /*Merge Mesh Locally*/
102  // Get all dim dimensional entities
103  Range ents;
104  MB_CHK_ERR( myMB->get_entities_by_dimension( meshset, dim, ents ) );
105 
106  if( ents.empty() && dim == 3 )
107  {
108  dim--;
109  MB_CHK_ERR( myMB->get_entities_by_dimension( meshset, dim, ents ) ); // maybe dimension 2
110  }
111 
112  // Merge Mesh Locally
113  if( !skip_local_merge )
114  {
115  MergeMesh merger( myMB, false );
116  ErrorCode merge_result = merger.merge_entities( ents, myEps );
117  // We can return if there is only 1 proc
118  if( merge_result != MB_SUCCESS || myPcomm->size() == 1 )
119  {
120  return merge_result;
121  }
122 
123  // Rebuild the ents range
124  ents.clear();
125  MB_CHK_ERR( myMB->get_entities_by_dimension( meshset, dim, ents ) );
126  }
127 
128  /*Get Skin
129  -Get Range of all dimensional entities
130  -skinEnts[i] is the skin entities of dimension i*/
131  Skinner skinner( myMB );
132  for( int skin_dim = dim; skin_dim >= 0; skin_dim-- )
133  {
134  MB_CHK_ERR( skinner.find_skin( meshset, ents, skin_dim, mySkinEnts[skin_dim] ) );
135  }
136  return MB_SUCCESS;
137 }

References moab::Range::clear(), moab::Range::empty(), ErrorCode, moab::Skinner::find_skin(), moab::Interface::get_entities_by_dimension(), MB_CHK_ERR, MB_SUCCESS, moab::MergeMesh::merge_entities(), myEps, myMB, myPcomm, mySkinEnts, and moab::ParallelComm::size().

Referenced by PerformMerge().

◆ PopulateMyTup()

ErrorCode moab::ParallelMergeMesh::PopulateMyTup ( double *  gbox)
private

Definition at line 165 of file ParallelMergeMesh.cpp.

166 {
167  /*Figure out how do partition the global box*/
168  double lengths[3];
169  int parts[3];
170  MB_CHK_ERR( PartitionGlobalBox( gbox, lengths, parts ) );
171 
172  /* Get Skin Coordinates, Vertices */
173  double* x = new double[mySkinEnts[0].size()];
174  double* y = new double[mySkinEnts[0].size()];
175  double* z = new double[mySkinEnts[0].size()];
176  if( myMB->get_coords( mySkinEnts[0], x, y, z ) != MB_SUCCESS )
177  {
178  // Prevent Memory Leak
179  delete[] x;
180  delete[] y;
181  delete[] z;
182  return moab::MB_FAILURE;
183  }
184 
185  // Initialize variable to be used in the loops
186  std::vector< int > toProcs;
187  int xPart, yPart, zPart, xEps, yEps, zEps, baseProc;
188  unsigned long long tup_i = 0, tup_ul = 0, tup_r = 0, count = 0;
189  // These are boolean to determine if the vertex is on close enough to a given border
190  bool xDup, yDup, zDup;
191  bool canWrite = myTup.get_writeEnabled();
192  if( !canWrite ) myTup.enableWriteAccess();
193  // Go through each vertex
194  for( Range::iterator it = mySkinEnts[0].begin(); it != mySkinEnts[0].end(); ++it )
195  {
196  xDup = false;
197  yDup = false;
198  zDup = false;
199  // Figure out which x,y,z partition the element is in.
200  xPart = static_cast< int >( floor( ( x[count] - gbox[0] ) / lengths[0] ) );
201  xPart = ( xPart < parts[0] ? xPart : parts[0] - 1 ); // Make sure it stays within the bounds
202 
203  yPart = static_cast< int >( floor( ( y[count] - gbox[1] ) / lengths[1] ) );
204  yPart = ( yPart < parts[1] ? yPart : parts[1] - 1 ); // Make sure it stays within the bounds
205 
206  zPart = static_cast< int >( floor( ( z[count] - gbox[2] ) / lengths[2] ) );
207  zPart = ( zPart < parts[2] ? zPart : parts[2] - 1 ); // Make sure it stays within the bounds
208 
209  // Figure out the partition with the addition of Epsilon
210  xEps = static_cast< int >( floor( ( x[count] - gbox[0] + myEps ) / lengths[0] ) );
211  yEps = static_cast< int >( floor( ( y[count] - gbox[1] + myEps ) / lengths[1] ) );
212  zEps = static_cast< int >( floor( ( z[count] - gbox[2] + myEps ) / lengths[2] ) );
213 
214  // Figure out if the vertex needs to be sent to multiple procs
215  xDup = ( xPart != xEps && xEps < parts[0] );
216  yDup = ( yPart != yEps && yEps < parts[1] );
217  zDup = ( zPart != zEps && zEps < parts[2] );
218 
219  // Add appropriate processors to the vector
220  baseProc = xPart + yPart * parts[0] + zPart * parts[0] * parts[1];
221  toProcs.push_back( baseProc );
222  if( xDup )
223  {
224  toProcs.push_back( baseProc + 1 ); // Get partition to the right
225  }
226  if( yDup )
227  {
228  // Partition up 1
229  toProcs.push_back( baseProc + parts[0] );
230  }
231  if( zDup )
232  {
233  // Partition above 1
234  toProcs.push_back( baseProc + parts[0] * parts[1] );
235  }
236  if( xDup && yDup )
237  {
238  // Partition up 1 and right 1
239  toProcs.push_back( baseProc + parts[0] + 1 );
240  }
241  if( xDup && zDup )
242  {
243  // Partition right 1 and above 1
244  toProcs.push_back( baseProc + parts[0] * parts[1] + 1 );
245  }
246  if( yDup && zDup )
247  {
248  // Partition up 1 and above 1
249  toProcs.push_back( baseProc + parts[0] * parts[1] + parts[0] );
250  }
251  if( xDup && yDup && zDup )
252  {
253  // Partition right 1, up 1, and above 1
254  toProcs.push_back( baseProc + parts[0] * parts[1] + parts[0] + 1 );
255  }
256  // Grow the tuple list if necessary
257  while( myTup.get_n() + toProcs.size() >= myTup.get_max() )
258  {
259  myTup.resize( myTup.get_max() ? myTup.get_max() + myTup.get_max() / 2 + 1 : 2 );
260  }
261 
262  // Add each proc as a tuple
263  for( std::vector< int >::iterator proc = toProcs.begin(); proc != toProcs.end(); ++proc )
264  {
265  myTup.vi_wr[tup_i++] = *proc;
266  myTup.vul_wr[tup_ul++] = *it;
267  myTup.vr_wr[tup_r++] = x[count];
268  myTup.vr_wr[tup_r++] = y[count];
269  myTup.vr_wr[tup_r++] = z[count];
270  myTup.inc_n();
271  }
272  count++;
273  toProcs.clear();
274  }
275  delete[] x;
276  delete[] y;
277  delete[] z;
278  if( !canWrite ) myTup.disableWriteAccess();
279  return MB_SUCCESS;
280 }

References moab::TupleList::disableWriteAccess(), moab::TupleList::enableWriteAccess(), moab::Interface::get_coords(), moab::TupleList::get_max(), moab::TupleList::get_n(), moab::TupleList::get_writeEnabled(), moab::TupleList::inc_n(), MB_CHK_ERR, MB_SUCCESS, myEps, myMB, mySkinEnts, myTup, PartitionGlobalBox(), moab::TupleList::resize(), moab::TupleList::vi_wr, moab::TupleList::vr_wr, and moab::TupleList::vul_wr.

Referenced by PerformMerge().

◆ SortMyMatches()

ErrorCode moab::ParallelMergeMesh::SortMyMatches ( )
private

Definition at line 514 of file ParallelMergeMesh.cpp.

515 {
516  TupleList::buffer buf( mySkinEnts[0].size() );
517  // Sorts are necessary to check for doubles
518  // Sort by remote handle
519  myMatches.sort( 3, &buf );
520  // Sort by matching proc
521  myMatches.sort( 1, &buf );
522  // Sort by local handle
523  myMatches.sort( 2, &buf );
524  buf.reset();
525  return MB_SUCCESS;
526 }

References MB_SUCCESS, myMatches, mySkinEnts, moab::TupleList::buffer::reset(), and moab::TupleList::sort().

Referenced by PerformMerge().

◆ SortTuplesByReal()

void moab::ParallelMergeMesh::SortTuplesByReal ( TupleList tup,
double  eps2 = 0 
)
staticprivate

Definition at line 594 of file ParallelMergeMesh.cpp.

595 {
596  bool canWrite = tup.get_writeEnabled();
597  if( !canWrite ) tup.enableWriteAccess();
598 
599  uint mi, ml, mul, mr;
600  tup.getTupleSize( mi, ml, mul, mr );
601  PerformRealSort( tup, 0, tup.get_n(), eps, mr );
602 
603  if( !canWrite ) tup.disableWriteAccess();
604 }

References moab::TupleList::disableWriteAccess(), moab::TupleList::enableWriteAccess(), moab::TupleList::get_n(), moab::TupleList::get_writeEnabled(), moab::TupleList::getTupleSize(), and PerformRealSort().

Referenced by PerformMerge().

◆ SwapTuples()

void moab::ParallelMergeMesh::SwapTuples ( TupleList tup,
unsigned long  a,
unsigned long  b 
)
staticprivate

Definition at line 607 of file ParallelMergeMesh.cpp.

608 {
609  if( a == b ) return;
610 
611  uint mi, ml, mul, mr;
612  tup.getTupleSize( mi, ml, mul, mr );
613 
614  // Swap mi
615  unsigned long a_val = a * mi, b_val = b * mi;
616  for( unsigned long i = 0; i < mi; i++ )
617  {
618  sint t = tup.vi_rd[a_val];
619  tup.vi_wr[a_val] = tup.vi_rd[b_val];
620  tup.vi_wr[b_val] = t;
621  a_val++;
622  b_val++;
623  }
624  // Swap ml
625  a_val = a * ml;
626  b_val = b * ml;
627  for( unsigned long i = 0; i < ml; i++ )
628  {
629  slong t = tup.vl_rd[a_val];
630  tup.vl_wr[a_val] = tup.vl_rd[b_val];
631  tup.vl_wr[b_val] = t;
632  a_val++;
633  b_val++;
634  }
635  // Swap mul
636  a_val = a * mul;
637  b_val = b * mul;
638  for( unsigned long i = 0; i < mul; i++ )
639  {
640  Ulong t = tup.vul_rd[a_val];
641  tup.vul_wr[a_val] = tup.vul_rd[b_val];
642  tup.vul_wr[b_val] = t;
643  a_val++;
644  b_val++;
645  }
646  // Swap mr
647  a_val = a * mr;
648  b_val = b * mr;
649  for( unsigned long i = 0; i < mr; i++ )
650  {
651  realType t = tup.vr_rd[a_val];
652  tup.vr_wr[a_val] = tup.vr_rd[b_val];
653  tup.vr_wr[b_val] = t;
654  a_val++;
655  b_val++;
656  }
657 }

References moab::TupleList::getTupleSize(), moab::TupleList::vi_rd, moab::TupleList::vi_wr, moab::TupleList::vl_rd, moab::TupleList::vl_wr, moab::TupleList::vr_rd, moab::TupleList::vr_wr, moab::TupleList::vul_rd, and moab::TupleList::vul_wr.

Referenced by PerformRealSort().

◆ TagSharedElements()

ErrorCode moab::ParallelMergeMesh::TagSharedElements ( int  dim)
private

Definition at line 529 of file ParallelMergeMesh.cpp.

530 {
531  // Manipulate the matches list to tag vertices and entities
532  // Set up proc ents
533  Range proc_ents;
534 
535  // get the entities in the partition sets
536  for( Range::iterator rit = myPcomm->partitionSets.begin(); rit != myPcomm->partitionSets.end(); ++rit )
537  {
538  Range tmp_ents;
539  MB_CHK_ERR( myMB->get_entities_by_handle( *rit, tmp_ents, true ) );
540  proc_ents.merge( tmp_ents );
541  }
542  if( myMB->dimension_from_handle( *proc_ents.rbegin() ) != myMB->dimension_from_handle( *proc_ents.begin() ) )
543  {
544  Range::iterator lower = proc_ents.lower_bound( CN::TypeDimensionMap[0].first ),
545  upper = proc_ents.upper_bound( CN::TypeDimensionMap[dim - 1].second );
546  proc_ents.erase( lower, upper );
547  }
548 
549  // This vector doesn't appear to be used but its in resolve_shared_ents
550  int maxp = -1;
551  std::vector< int > sharing_procs( MAX_SHARING_PROCS );
552  std::fill( sharing_procs.begin(), sharing_procs.end(), maxp );
553 
554  // get ents shared by 1 or n procs
555  std::map< std::vector< int >, std::vector< EntityHandle > > proc_nranges;
556  Range proc_verts;
557  MB_CHK_ERR( myMB->get_adjacencies( proc_ents, 0, false, proc_verts, Interface::UNION ) );
558 
559  MB_CHK_ERR( myPcomm->tag_shared_verts( myMatches, proc_nranges, proc_verts ) );
560 
561  // get entities shared by 1 or n procs
562  MB_CHK_ERR( myPcomm->get_proc_nvecs( dim, dim - 1, mySkinEnts.data(), proc_nranges ) );
563 
564  // create the sets for each interface; store them as tags on
565  // the interface instance
566  Range iface_sets;
567  MB_CHK_ERR( myPcomm->create_interface_sets( proc_nranges ) );
568 
569  // establish comm procs and buffers for them
570  std::set< unsigned int > procs;
571  MB_CHK_ERR( myPcomm->get_interface_procs( procs, true ) );
572 
573  // resolve shared entity remote handles; implemented in ghost cell exchange
574  // code because it's so similar
575  MB_CHK_ERR( myPcomm->exchange_ghost_cells( -1, -1, 0, true, true ) );
576 
577  // now build parent/child links for interface sets
579 
580  return MB_SUCCESS;
581 }

References moab::Range::begin(), moab::ParallelComm::create_iface_pc_links(), moab::ParallelComm::create_interface_sets(), moab::Interface::dimension_from_handle(), moab::Range::end(), moab::Range::erase(), moab::ParallelComm::exchange_ghost_cells(), moab::GeomUtil::first(), moab::Interface::get_adjacencies(), moab::Interface::get_entities_by_handle(), moab::ParallelComm::get_interface_procs(), moab::ParallelComm::get_proc_nvecs(), moab::Range::lower_bound(), MAX_SHARING_PROCS, MB_CHK_ERR, MB_SUCCESS, moab::Range::merge(), myMatches, myMB, myPcomm, mySkinEnts, moab::ParallelComm::partitionSets, moab::Range::rbegin(), moab::ParallelComm::tag_shared_verts(), moab::CN::TypeDimensionMap, moab::Interface::UNION, and moab::Range::upper_bound().

Referenced by PerformMerge().

◆ TupleGreaterThan()

bool moab::ParallelMergeMesh::TupleGreaterThan ( TupleList tup,
unsigned long  vrI,
unsigned long  vrJ,
double  eps2,
uint  tup_mr 
)
staticprivate

Definition at line 698 of file ParallelMergeMesh.cpp.

703 {
704  unsigned check = 0;
705  while( check < tup_mr )
706  {
707  // If the values are the same
708  if( fabs( tup.vr_rd[vrI + check] - tup.vr_rd[vrJ + check] ) <= eps )
709  {
710  check++;
711  continue;
712  }
713  // If I greater than J
714  else if( tup.vr_rd[vrI + check] > tup.vr_rd[vrJ + check] )
715  {
716  return true;
717  }
718  // If J greater than I
719  else
720  {
721  return false;
722  }
723  }
724  // All Values are the same
725  return false;
726 }

References check(), and moab::TupleList::vr_rd.

Referenced by PerformRealSort().

Member Data Documentation

◆ myCD

gs_data::crystal_data moab::ParallelMergeMesh::myCD
private

Definition at line 38 of file ParallelMergeMesh.hpp.

Referenced by CleanUp(), and PerformMerge().

◆ myEps

double moab::ParallelMergeMesh::myEps
private

◆ myMatches

TupleList moab::ParallelMergeMesh::myMatches
private

◆ myMB

Interface* moab::ParallelMergeMesh::myMB
private

◆ myPcomm

ParallelComm* moab::ParallelMergeMesh::myPcomm
private

◆ mySkinEnts

std::vector< Range > moab::ParallelMergeMesh::mySkinEnts
private

◆ myTup

TupleList moab::ParallelMergeMesh::myTup
private

Definition at line 37 of file ParallelMergeMesh.hpp.

Referenced by CleanUp(), PerformMerge(), PopulateMyMatches(), and PopulateMyTup().


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