Loading [MathJax]/extensions/tex2jax.js
Mesh Oriented datABase  (version 5.5.1)
An array-based unstructured mesh library
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
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 615 of file ParallelMergeMesh.cpp.

616 { 617  // The reset operation is now safe and avoids a double free() 618  myMatches.reset(); 619  myTup.reset(); 620  myCD.reset(); 621 }

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

Referenced by merge().

◆ GetGlobalBox()

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

Definition at line 141 of file ParallelMergeMesh.cpp.

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

References moab::BoundBox::bMax, moab::ParallelComm::comm(), ErrorCode, MB_CHK_ERR, MB_SUCCESS, myMB, myPcomm, mySkinEnts, size, 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  ErrorCode rval = PerformMerge( levelset, skip_local_merge, dim );MB_CHK_ERR( rval ); 31  CleanUp(); 32  return rval; 33 }

References CleanUp(), dim, ErrorCode, MB_CHK_ERR, 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 287 of file ParallelMergeMesh.cpp.

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

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 365 of file ParallelMergeMesh.cpp.

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

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

References moab::ParallelComm::comm(), dim, ErrorCode, 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(), size, 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 691 of file ParallelMergeMesh.cpp.

696 { 697  // If list size is only 1 or 0 return 698  if( left + 1 >= right ) 699  { 700  return; 701  } 702  unsigned long swap = left, tup_l = left * tup_mr, tup_t = tup_l + tup_mr; 703  704  // Swap the median with the left position for a (hopefully) better split 705  SwapTuples( tup, left, ( left + right ) / 2 ); 706  707  // Partition the data 708  for( unsigned long t = left + 1; t < right; t++ ) 709  { 710  // If the left value(pivot) is greater than t_val, swap it into swap 711  if( TupleGreaterThan( tup, tup_l, tup_t, eps, tup_mr ) ) 712  { 713  swap++; 714  SwapTuples( tup, swap, t ); 715  } 716  tup_t += tup_mr; 717  } 718  719  // Swap so that position swap is in the correct position 720  SwapTuples( tup, left, swap ); 721  722  // Sort left and right of swap 723  PerformRealSort( tup, left, swap, eps, tup_mr ); 724  PerformRealSort( tup, swap + 1, right, eps, tup_mr ); 725 }

References SwapTuples(), and TupleGreaterThan().

Referenced by SortTuplesByReal().

◆ PopulateMyMatches()

ErrorCode moab::ParallelMergeMesh::PopulateMyMatches ( )
private

Definition at line 441 of file ParallelMergeMesh.cpp.

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

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 100 of file ParallelMergeMesh.cpp.

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

References moab::Range::clear(), dim, 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 168 of file ParallelMergeMesh.cpp.

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

References moab::TupleList::disableWriteAccess(), moab::TupleList::enableWriteAccess(), ErrorCode, 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 518 of file ParallelMergeMesh.cpp.

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

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

Referenced by PerformMerge().

◆ SortTuplesByReal()

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

Definition at line 624 of file ParallelMergeMesh.cpp.

625 { 626  bool canWrite = tup.get_writeEnabled(); 627  if( !canWrite ) tup.enableWriteAccess(); 628  629  uint mi, ml, mul, mr; 630  tup.getTupleSize( mi, ml, mul, mr ); 631  PerformRealSort( tup, 0, tup.get_n(), eps, mr ); 632  633  if( !canWrite ) tup.disableWriteAccess(); 634 }

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 637 of file ParallelMergeMesh.cpp.

638 { 639  if( a == b ) return; 640  641  uint mi, ml, mul, mr; 642  tup.getTupleSize( mi, ml, mul, mr ); 643  644  // Swap mi 645  unsigned long a_val = a * mi, b_val = b * mi; 646  for( unsigned long i = 0; i < mi; i++ ) 647  { 648  sint t = tup.vi_rd[a_val]; 649  tup.vi_wr[a_val] = tup.vi_rd[b_val]; 650  tup.vi_wr[b_val] = t; 651  a_val++; 652  b_val++; 653  } 654  // Swap ml 655  a_val = a * ml; 656  b_val = b * ml; 657  for( unsigned long i = 0; i < ml; i++ ) 658  { 659  slong t = tup.vl_rd[a_val]; 660  tup.vl_wr[a_val] = tup.vl_rd[b_val]; 661  tup.vl_wr[b_val] = t; 662  a_val++; 663  b_val++; 664  } 665  // Swap mul 666  a_val = a * mul; 667  b_val = b * mul; 668  for( unsigned long i = 0; i < mul; i++ ) 669  { 670  Ulong t = tup.vul_rd[a_val]; 671  tup.vul_wr[a_val] = tup.vul_rd[b_val]; 672  tup.vul_wr[b_val] = t; 673  a_val++; 674  b_val++; 675  } 676  // Swap mr 677  a_val = a * mr; 678  b_val = b * mr; 679  for( unsigned long i = 0; i < mr; i++ ) 680  { 681  realType t = tup.vr_rd[a_val]; 682  tup.vr_wr[a_val] = tup.vr_rd[b_val]; 683  tup.vr_wr[b_val] = t; 684  a_val++; 685  b_val++; 686  } 687 }

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 533 of file ParallelMergeMesh.cpp.

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

References moab::Range::begin(), moab::ParallelComm::create_iface_pc_links(), moab::ParallelComm::create_interface_sets(), dim, moab::Interface::dimension_from_handle(), moab::Range::end(), moab::Range::erase(), ErrorCode, 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_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 728 of file ParallelMergeMesh.cpp.

733 { 734  unsigned check = 0; 735  while( check < tup_mr ) 736  { 737  // If the values are the same 738  if( fabs( tup.vr_rd[vrI + check] - tup.vr_rd[vrJ + check] ) <= eps ) 739  { 740  check++; 741  continue; 742  } 743  // If I greater than J 744  else if( tup.vr_rd[vrI + check] > tup.vr_rd[vrJ + check] ) 745  { 746  return true; 747  } 748  // If J greater than I 749  else 750  { 751  return false; 752  } 753  } 754  // All Values are the same 755  return false; 756 }

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: