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

#include <ReadParallel.hpp>

+ Collaboration diagram for moab::ReadParallel:

Public Types

enum  ParallelActions {
  PA_READ = 0 , PA_READ_PART = 1 , PA_BROADCAST = 2 , PA_DELETE_NONLOCAL = 3 ,
  PA_CHECK_GIDS_SERIAL = 4 , PA_GET_FILESET_ENTS = 5 , PA_RESOLVE_SHARED_ENTS = 6 , PA_EXCHANGE_GHOSTS = 7 ,
  PA_RESOLVE_SHARED_SETS = 8 , PA_AUGMENT_SETS_WITH_GHOSTS = 9 , PA_PRINT_PARALLEL = 10 , PA_CREATE_TRIVIAL_PARTITION = 11 ,
  PA_CORRECT_THIN_GHOSTS = 12
}
 
enum  ParallelOpts {
  POPT_NONE = 0 , POPT_BCAST , POPT_BCAST_DELETE , POPT_READ_DELETE ,
  POPT_READ_PART , POPT_DEFAULT
}
 

Public Member Functions

ErrorCode load_file (const char *file_name, const EntityHandle *file_set, const FileOptions &opts, const ReaderIface::SubsetList *subset_list=0, const Tag *file_id_tag=0)
 load a file More...
 
ErrorCode load_file (const char **file_names, const int num_files, const EntityHandle *file_set, const FileOptions &opts, const ReaderIface::SubsetList *subset_list=0, const Tag *file_id_tag=0)
 load multiple files More...
 
ErrorCode load_file (const char **file_names, const int num_files, const EntityHandle *file_set, int parallel_mode, std::string &partition_tag_name, std::vector< int > &partition_tag_vals, bool distrib, bool partition_by_rank, std::vector< int > &pa_vec, const FileOptions &opts, const ReaderIface::SubsetList *subset_list, const Tag *file_id_tag, const int reader_rank, const bool cputime, const int resolve_dim, const int shared_dim, const int ghost_dim, const int bridge_dim, const int num_layers, const int addl_ents)
 
 ReadParallel (Interface *impl=NULL, ParallelComm *pc=NULL)
 Constructor. More...
 
virtual ~ReadParallel ()
 Destructor. More...
 
ErrorCode delete_nonlocal_entities (std::string &ptag_name, std::vector< int > &ptag_vals, bool distribute, EntityHandle file_set)
 PUBLIC TO ALLOW TESTING. More...
 
ErrorCode delete_nonlocal_entities (EntityHandle file_set)
 

Static Public Member Functions

static ReaderIfacefactory (Interface *)
 

Static Public Attributes

static const char * parallelOptsNames [] = { "NONE", "BCAST", "BCAST_DELETE", "READ_DELETE", "READ_PART", "", 0 }
 
static const char * ParallelActionsNames []
 

Protected Member Functions

ErrorCode create_partition_sets (std::string &ptag_name, EntityHandle file_set)
 

Private Attributes

InterfacembImpl
 
ParallelCommmyPcomm
 
DebugOutput myDebug
 
ErrormError
 

Detailed Description

Definition at line 17 of file ReadParallel.hpp.

Member Enumeration Documentation

◆ ParallelActions

Enumerator
PA_READ 
PA_READ_PART 
PA_BROADCAST 
PA_DELETE_NONLOCAL 
PA_CHECK_GIDS_SERIAL 
PA_GET_FILESET_ENTS 
PA_RESOLVE_SHARED_ENTS 
PA_EXCHANGE_GHOSTS 
PA_RESOLVE_SHARED_SETS 
PA_AUGMENT_SETS_WITH_GHOSTS 
PA_PRINT_PARALLEL 
PA_CREATE_TRIVIAL_PARTITION 
PA_CORRECT_THIN_GHOSTS 

Definition at line 66 of file ReadParallel.hpp.

◆ ParallelOpts

Enumerator
POPT_NONE 
POPT_BCAST 
POPT_BCAST_DELETE 
POPT_READ_DELETE 
POPT_READ_PART 
POPT_DEFAULT 

Definition at line 85 of file ReadParallel.hpp.

86  {
87  POPT_NONE = 0,
88  POPT_BCAST,
93  };

Constructor & Destructor Documentation

◆ ReadParallel()

moab::ReadParallel::ReadParallel ( Interface impl = NULL,
ParallelComm pc = NULL 
)

Constructor.

Definition at line 39 of file ReadParallel.cpp.

40  : mbImpl( impl ), myPcomm( pc ), myDebug( "ReadPara", std::cerr )
41 {
42  if( !myPcomm )
43  {
45  if( NULL == myPcomm ) myPcomm = new ParallelComm( mbImpl, MPI_COMM_WORLD );
46  }
48  if( debug ) // For backwards compatibility, enable all debug output if constant is true
49  myDebug.set_verbosity( 10 );
50 
51  impl->query_interface( mError );
52 }

References moab::debug, moab::ParallelComm::get_pcomm(), mbImpl, mError, myDebug, myPcomm, moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::Interface::query_interface(), moab::DebugOutput::set_rank(), and moab::DebugOutput::set_verbosity().

◆ ~ReadParallel()

virtual moab::ReadParallel::~ReadParallel ( )
inlinevirtual

Destructor.

Definition at line 62 of file ReadParallel.hpp.

62 {}

Member Function Documentation

◆ create_partition_sets()

ErrorCode moab::ReadParallel::create_partition_sets ( std::string &  ptag_name,
EntityHandle  file_set 
)
protected

Definition at line 733 of file ReadParallel.cpp.

734 {
735  int proc_rk = myPcomm->proc_config().proc_rank();
736  ErrorCode result = MB_SUCCESS;
737 
738  Tag ptag;
739 
740  // Tag the partition sets with a standard tag name
741  if( ptag_name.empty() ) ptag_name = PARALLEL_PARTITION_TAG_NAME;
742  bool tag_created = false;
743  result = mbImpl->tag_get_handle( ptag_name.c_str(), 1, MB_TYPE_INTEGER, ptag, MB_TAG_SPARSE | MB_TAG_CREAT, 0,
744  &tag_created );
745  MB_CHK_SET_ERR( result, "Trouble getting PARALLEL_PARTITION tag" );
746 
747  if( !tag_created )
748  {
749  // This tag already exists; better check to see that tagged sets
750  // agree with this partition
751  Range tagged_sets;
752  int* proc_rk_ptr = &proc_rk;
753  result = mbImpl->get_entities_by_type_and_tag( file_set, MBENTITYSET, &ptag, (const void* const*)&proc_rk_ptr,
754  1, tagged_sets );
755  MB_CHK_SET_ERR( result, "Trouble getting tagged sets" );
756  if( !tagged_sets.empty() && tagged_sets != myPcomm->partition_sets() )
757  {
758  result = mbImpl->tag_delete_data( ptag, tagged_sets );
759  MB_CHK_SET_ERR( result, "Trouble deleting data of PARALLEL_PARTITION tag" );
760  }
761  else if( tagged_sets == myPcomm->partition_sets() )
762  return MB_SUCCESS;
763  }
764 
765  // If we get here, we need to assign the tag
766  std::vector< int > values( myPcomm->partition_sets().size() );
767  for( unsigned int i = 0; i < myPcomm->partition_sets().size(); i++ )
768  values[i] = proc_rk;
769  result = mbImpl->tag_set_data( ptag, myPcomm->partition_sets(), values.data() );
770  MB_CHK_SET_ERR( result, "Trouble setting data to PARALLEL_PARTITION tag" );
771 
772  return MB_SUCCESS;
773 }

References moab::Range::empty(), ErrorCode, moab::Interface::get_entities_by_type_and_tag(), MB_CHK_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_SPARSE, MB_TYPE_INTEGER, MBENTITYSET, mbImpl, myPcomm, PARALLEL_PARTITION_TAG_NAME, moab::ParallelComm::partition_sets(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::Range::size(), moab::Interface::tag_delete_data(), moab::Interface::tag_get_handle(), and moab::Interface::tag_set_data().

Referenced by load_file().

◆ delete_nonlocal_entities() [1/2]

ErrorCode moab::ReadParallel::delete_nonlocal_entities ( EntityHandle  file_set)

Definition at line 775 of file ReadParallel.cpp.

776 {
777  // Get partition entities and ents related to/used by those
778  // get ents in the partition
779  ReadUtilIface* read_iface;
780  mbImpl->query_interface( read_iface );
781  Range partition_ents, all_sets;
782 
783  myDebug.tprint( 2, "Gathering related entities.\n" );
784 
785  ErrorCode result = read_iface->gather_related_ents( myPcomm->partition_sets(), partition_ents, &file_set );
786  MB_CHK_SET_ERR( result, "Failure gathering related entities" );
787 
788  // Get pre-existing entities
789  Range file_ents;
790  result = mbImpl->get_entities_by_handle( file_set, file_ents );
791  MB_CHK_SET_ERR( result, "Couldn't get pre-existing entities" );
792 
793  if( 0 == myPcomm->proc_config().proc_rank() )
794  {
795  myDebug.print( 2, "File entities: ", file_ents );
796  }
797 
798  // Get deletable entities by subtracting partition ents from file ents
799  Range deletable_ents = subtract( file_ents, partition_ents );
800 
801  // Cache deletable vs. keepable sets
802  Range deletable_sets = deletable_ents.subset_by_type( MBENTITYSET );
803  Range keepable_sets = subtract( file_ents.subset_by_type( MBENTITYSET ), deletable_sets );
804 
805  myDebug.tprint( 2, "Removing deletable entities from keepable sets.\n" );
806 
807  // Remove deletable ents from all keepable sets
808  for( Range::iterator rit = keepable_sets.begin(); rit != keepable_sets.end(); ++rit )
809  {
810  result = mbImpl->remove_entities( *rit, deletable_ents );
811  MB_CHK_SET_ERR( result, "Failure removing deletable entities" );
812  }
813  result = mbImpl->remove_entities( file_set, deletable_ents );
814  MB_CHK_SET_ERR( result, "Failure removing deletable entities" );
815 
816  myDebug.tprint( 2, "Deleting deletable entities.\n" );
817 
818  if( 0 == myPcomm->proc_config().proc_rank() )
819  {
820  myDebug.print( 2, "Deletable sets: ", deletable_sets );
821  }
822 
823  // Delete sets, then ents
824  if( !deletable_sets.empty() )
825  {
826  result = mbImpl->delete_entities( deletable_sets );
827  MB_CHK_SET_ERR( result, "Failure deleting sets in delete_nonlocal_entities" );
828  }
829 
830  deletable_ents -= deletable_sets;
831 
832  if( 0 == myPcomm->proc_config().proc_rank() )
833  {
834  myDebug.print( 2, "Deletable entities: ", deletable_ents );
835  }
836 
837  if( !deletable_ents.empty() )
838  {
839  result = mbImpl->delete_entities( deletable_ents );
840  MB_CHK_SET_ERR( result, "Failure deleting entities in delete_nonlocal_entities" );
841  }
842 
843  return MB_SUCCESS;
844 }

References moab::Range::begin(), moab::Interface::delete_entities(), moab::Range::empty(), moab::Range::end(), ErrorCode, moab::ReadUtilIface::gather_related_ents(), moab::Interface::get_entities_by_handle(), MB_CHK_SET_ERR, MB_SUCCESS, MBENTITYSET, mbImpl, myDebug, myPcomm, moab::ParallelComm::partition_sets(), moab::DebugOutput::print(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::Interface::query_interface(), moab::Interface::remove_entities(), moab::Range::subset_by_type(), moab::subtract(), and moab::DebugOutput::tprint().

◆ delete_nonlocal_entities() [2/2]

ErrorCode moab::ReadParallel::delete_nonlocal_entities ( std::string &  ptag_name,
std::vector< int > &  ptag_vals,
bool  distribute,
EntityHandle  file_set 
)

PUBLIC TO ALLOW TESTING.

Definition at line 663 of file ReadParallel.cpp.

667 {
668  Range partition_sets;
669 
670  Tag ptag;
671  ErrorCode result = mbImpl->tag_get_handle( ptag_name.c_str(), 1, MB_TYPE_INTEGER, ptag );
672  MB_CHK_SET_ERR( result, "Failed getting tag handle in delete_nonlocal_entities" );
673 
674  result = mbImpl->get_entities_by_type_and_tag( file_set, MBENTITYSET, &ptag, NULL, 1, myPcomm->partition_sets() );
675  MB_CHK_SET_ERR( result, "Failed to get sets with partition-type tag" );
676 
677  int proc_sz = myPcomm->proc_config().proc_size();
678  int proc_rk = myPcomm->proc_config().proc_rank();
679 
680  if( !ptag_vals.empty() )
681  {
682  // Values input, get sets with those values
683  Range tmp_sets;
684  std::vector< int > tag_vals( myPcomm->partition_sets().size() );
685  result = mbImpl->tag_get_data( ptag, myPcomm->partition_sets(), tag_vals.data() );
686  MB_CHK_SET_ERR( result, "Failed to get tag data for partition vals tag" );
687  for( std::vector< int >::iterator pit = tag_vals.begin(); pit != tag_vals.end(); ++pit )
688  {
689  std::vector< int >::iterator pit2 = std::find( ptag_vals.begin(), ptag_vals.end(), *pit );
690  if( pit2 != ptag_vals.end() ) tmp_sets.insert( myPcomm->partition_sets()[pit - tag_vals.begin()] );
691  }
692 
693  myPcomm->partition_sets().swap( tmp_sets );
694  }
695 
696  if( distribute )
697  {
698  // For now, require that number of partition sets be greater
699  // than number of procs
700  if( myPcomm->partition_sets().size() < (unsigned int)proc_sz )
701  {
702  MB_SET_ERR( MB_FAILURE, "Too few parts; P = " << proc_rk << ", tag = " << ptag
703  << ", # sets = " << myPcomm->partition_sets().size() );
704  }
705 
706  Range tmp_sets;
707  // Distribute the partition sets
708  unsigned int num_sets = myPcomm->partition_sets().size() / proc_sz;
709  unsigned int num_leftover = myPcomm->partition_sets().size() % proc_sz;
710  int begin_set = 0;
711  if( proc_rk < (int)num_leftover )
712  {
713  num_sets++;
714  begin_set = num_sets * proc_rk;
715  }
716  else
717  begin_set = proc_rk * num_sets + num_leftover;
718 
719  for( unsigned int i = 0; i < num_sets; i++ )
720  tmp_sets.insert( myPcomm->partition_sets()[begin_set + i] );
721 
722  myPcomm->partition_sets().swap( tmp_sets );
723  }
724 
725  myDebug.print( 1, "My partition sets: ", myPcomm->partition_sets() );
726 
727  result = delete_nonlocal_entities( file_set );
728  MB_CHK_ERR( result );
729 
730  return MB_SUCCESS;
731 }

References ErrorCode, moab::Interface::get_entities_by_type_and_tag(), moab::Range::insert(), MB_CHK_ERR, MB_CHK_SET_ERR, MB_SET_ERR, MB_SUCCESS, MB_TYPE_INTEGER, MBENTITYSET, mbImpl, myDebug, myPcomm, moab::ParallelComm::partition_sets(), moab::DebugOutput::print(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::ProcConfig::proc_size(), moab::Range::size(), moab::Range::swap(), moab::Interface::tag_get_data(), and moab::Interface::tag_get_handle().

Referenced by load_file().

◆ factory()

static ReaderIface* moab::ReadParallel::factory ( Interface )
static

◆ load_file() [1/3]

ErrorCode moab::ReadParallel::load_file ( const char **  file_names,
const int  num_files,
const EntityHandle file_set,
const FileOptions opts,
const ReaderIface::SubsetList subset_list = 0,
const Tag file_id_tag = 0 
)

load multiple files

Definition at line 54 of file ReadParallel.cpp.

60 {
61  int tmpval;
62  if( MB_SUCCESS == opts.get_int_option( "DEBUG_PIO", 1, tmpval ) )
63  {
64  myDebug.set_verbosity( tmpval );
65  myPcomm->set_debug_verbosity( tmpval );
66  }
67  myDebug.tprint( 1, "Setting up...\n" );
68 
69  // Get parallel settings
70  int parallel_mode;
71  ErrorCode result = opts.match_option( "PARALLEL", parallelOptsNames, parallel_mode );
72  if( MB_FAILURE == result )
73  {
74  MB_SET_ERR( MB_FAILURE, "Unexpected value for 'PARALLEL' option" );
75  }
76  else if( MB_ENTITY_NOT_FOUND == result )
77  {
78  parallel_mode = 0;
79  }
80 
81  // Get partition setting
82  bool distrib;
83  std::string partition_tag_name;
84  result = opts.get_option( "PARTITION", partition_tag_name );
85  if( MB_ENTITY_NOT_FOUND == result )
86  {
87  distrib = false;
88  partition_tag_name = "";
89  }
90  else
91  {
92  distrib = true;
93  if( partition_tag_name.empty() ) partition_tag_name = PARALLEL_PARTITION_TAG_NAME;
94 
95  // Also get deprecated PARTITION_DISTRIBUTE option
96  // so that higher-level code doesn't return an error
97  // due to an unrecognized option
98  opts.get_null_option( "PARTITION_DISTRIBUTE" );
99  }
100 
101  // Get partition tag value(s), if any, and whether they're to be
102  // distributed or assigned
103  std::vector< int > partition_tag_vals;
104  opts.get_ints_option( "PARTITION_VAL", partition_tag_vals );
105 
106  // see if partition tag name is "TRIVIAL", if the tag exists
107  bool create_trivial_partition = false;
108  if( partition_tag_name == std::string( "TRIVIAL" ) )
109  {
110  Tag ttag; // see if the trivial tag exists
111  result = mbImpl->tag_get_handle( partition_tag_name.c_str(), ttag );
112  if( MB_TAG_NOT_FOUND == result ) create_trivial_partition = true;
113  }
114  // See if we need to report times
115  bool cputime = false;
116  result = opts.get_null_option( "CPUTIME" );
117  if( MB_SUCCESS == result ) cputime = true;
118 
119  // See if we need to report times
120  bool print_parallel = false;
121  result = opts.get_null_option( "PRINT_PARALLEL" );
122  if( MB_SUCCESS == result ) print_parallel = true;
123 
124  // Get ghosting options
125  std::string ghost_str;
126  int bridge_dim, ghost_dim = -1, num_layers, addl_ents = 0;
127  result = opts.get_str_option( "PARALLEL_GHOSTS", ghost_str );
128  if( MB_TYPE_OUT_OF_RANGE == result )
129  {
130  ghost_dim = 3;
131  bridge_dim = 0;
132  num_layers = 1;
133  }
134  else if( MB_SUCCESS == result )
135  {
136  int num_fields = sscanf( ghost_str.c_str(), "%d.%d.%d.%d", &ghost_dim, &bridge_dim, &num_layers, &addl_ents );
137  if( 3 > num_fields )
138  {
139  MB_SET_ERR( MB_FAILURE, "Didn't read 3 fields from PARALLEL_GHOSTS string" );
140  }
141  }
142 
143  // Get resolve_shared_ents option
144  std::string shared_str;
145  int resolve_dim = -2, shared_dim = -1;
146  result = opts.get_str_option( "PARALLEL_RESOLVE_SHARED_ENTS", shared_str );
147  if( MB_TYPE_OUT_OF_RANGE == result )
148  {
149  resolve_dim = -1;
150  shared_dim = -1;
151  }
152  else if( MB_SUCCESS == result )
153  {
154  int num_fields = sscanf( shared_str.c_str(), "%d.%d", &resolve_dim, &shared_dim );
155  if( 2 != num_fields )
156  {
157  MB_SET_ERR( MB_FAILURE, "Didn't read 2 fields from PARALLEL_RESOLVE_SHARED_ENTS string" );
158  }
159  }
160 
161  // Get skip augmenting with ghosts option
162  bool skip_augment = false;
163  result = opts.get_null_option( "SKIP_AUGMENT_WITH_GHOSTS" );
164  if( MB_SUCCESS == result ) skip_augment = true;
165 
166  bool correct_thin_ghosts = false;
167  result = opts.get_null_option( "PARALLEL_THIN_GHOST_LAYER" );
168  if( MB_SUCCESS == result ) correct_thin_ghosts = true;
169 
170  // Get MPI IO processor rank
171  int reader_rank;
172  result = opts.get_int_option( "MPI_IO_RANK", reader_rank );
173  if( MB_ENTITY_NOT_FOUND == result )
174  reader_rank = 0;
175  else if( MB_SUCCESS != result )
176  {
177  MB_SET_ERR( MB_FAILURE, "Unexpected value for 'MPI_IO_RANK' option" );
178  }
179 
180  // Now that we've parsed all the parallel options, make an instruction queue
181  std::vector< int > pa_vec;
182  bool is_reader = ( reader_rank == (int)myPcomm->proc_config().proc_rank() );
183 
184  bool partition_by_rank = false;
185  if( MB_SUCCESS == opts.get_null_option( "PARTITION_BY_RANK" ) )
186  {
187  partition_by_rank = true;
188  if( !partition_tag_vals.empty() )
189  {
190  MB_SET_ERR( MB_FAILURE, "Cannot specify both PARTITION_VALS and PARTITION_BY_RANK" );
191  }
192  }
193 
194  double factor_seq;
195  if( MB_SUCCESS == opts.get_real_option( "PARALLEL_SEQUENCE_FACTOR", factor_seq ) )
196  {
197  if( factor_seq < 1. ) MB_SET_ERR( MB_FAILURE, "cannot have sequence factor less than 1." );
198  mbImpl->set_sequence_multiplier( factor_seq );
199  }
200  switch( parallel_mode )
201  {
202  case POPT_BCAST:
203  myDebug.print( 1, "Read mode is BCAST\n" );
204  if( is_reader )
205  {
206  pa_vec.push_back( PA_READ );
207  pa_vec.push_back( PA_CHECK_GIDS_SERIAL );
208  pa_vec.push_back( PA_GET_FILESET_ENTS );
209  }
210  pa_vec.push_back( PA_BROADCAST );
211  if( !is_reader ) pa_vec.push_back( PA_GET_FILESET_ENTS );
212  break;
213 
214  case POPT_BCAST_DELETE:
215  myDebug.print( 1, "Read mode is BCAST_DELETE\n" );
216  if( is_reader )
217  {
218  pa_vec.push_back( PA_READ );
219  pa_vec.push_back( PA_CHECK_GIDS_SERIAL );
220  pa_vec.push_back( PA_GET_FILESET_ENTS );
221  if( create_trivial_partition ) pa_vec.push_back( PA_CREATE_TRIVIAL_PARTITION );
222  }
223  pa_vec.push_back( PA_BROADCAST );
224  if( !is_reader ) pa_vec.push_back( PA_GET_FILESET_ENTS );
225  pa_vec.push_back( PA_DELETE_NONLOCAL );
226  break;
227 
228  case POPT_DEFAULT:
229  case POPT_READ_DELETE:
230  myDebug.print( 1, "Read mode is READ_DELETE\n" );
231  pa_vec.push_back( PA_READ );
232  pa_vec.push_back( PA_CHECK_GIDS_SERIAL );
233  pa_vec.push_back( PA_GET_FILESET_ENTS );
234  pa_vec.push_back( PA_DELETE_NONLOCAL );
235  break;
236 
237  case POPT_READ_PART:
238  myDebug.print( 1, "Read mode is READ_PART\n" );
239  pa_vec.push_back( PA_READ_PART );
240  break;
241 
242  default:
243  MB_SET_ERR( MB_FAILURE, "Unexpected parallel read mode" );
244  }
245 
246  if( -2 != resolve_dim ) pa_vec.push_back( PA_RESOLVE_SHARED_ENTS );
247 
248  if( -1 != ghost_dim ) pa_vec.push_back( PA_EXCHANGE_GHOSTS );
249 
250  if( -2 != resolve_dim )
251  {
252  pa_vec.push_back( PA_RESOLVE_SHARED_SETS );
253  if( -1 != ghost_dim && !skip_augment ) pa_vec.push_back( PA_AUGMENT_SETS_WITH_GHOSTS );
254  if( -1 != ghost_dim && correct_thin_ghosts ) pa_vec.push_back( PA_CORRECT_THIN_GHOSTS );
255  }
256 
257  if( print_parallel ) pa_vec.push_back( PA_PRINT_PARALLEL );
258 
259  result = load_file( file_names, num_files, file_set, parallel_mode, partition_tag_name, partition_tag_vals, distrib,
260  partition_by_rank, pa_vec, opts, subset_list, file_id_tag, reader_rank, cputime, resolve_dim,
261  shared_dim, ghost_dim, bridge_dim, num_layers, addl_ents );
262  MB_CHK_ERR( result );
263 
264  if( parallel_mode == POPT_BCAST_DELETE && !is_reader ) opts.mark_all_seen();
265 
266  return MB_SUCCESS;
267 }

References ErrorCode, moab::FileOptions::get_int_option(), moab::FileOptions::get_ints_option(), moab::FileOptions::get_null_option(), moab::FileOptions::get_option(), moab::FileOptions::get_real_option(), moab::FileOptions::get_str_option(), load_file(), moab::FileOptions::mark_all_seen(), moab::FileOptions::match_option(), MB_CHK_ERR, MB_ENTITY_NOT_FOUND, MB_SET_ERR, MB_SUCCESS, MB_TAG_NOT_FOUND, MB_TYPE_OUT_OF_RANGE, mbImpl, myDebug, myPcomm, PA_AUGMENT_SETS_WITH_GHOSTS, PA_BROADCAST, PA_CHECK_GIDS_SERIAL, PA_CORRECT_THIN_GHOSTS, PA_CREATE_TRIVIAL_PARTITION, PA_DELETE_NONLOCAL, PA_EXCHANGE_GHOSTS, PA_GET_FILESET_ENTS, PA_PRINT_PARALLEL, PA_READ, PA_READ_PART, PA_RESOLVE_SHARED_ENTS, PA_RESOLVE_SHARED_SETS, PARALLEL_PARTITION_TAG_NAME, parallelOptsNames, POPT_BCAST, POPT_BCAST_DELETE, POPT_DEFAULT, POPT_READ_DELETE, POPT_READ_PART, moab::DebugOutput::print(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::ParallelComm::set_debug_verbosity(), moab::Interface::set_sequence_multiplier(), moab::DebugOutput::set_verbosity(), moab::Interface::tag_get_handle(), and moab::DebugOutput::tprint().

◆ load_file() [2/3]

ErrorCode moab::ReadParallel::load_file ( const char **  file_names,
const int  num_files,
const EntityHandle file_set,
int  parallel_mode,
std::string &  partition_tag_name,
std::vector< int > &  partition_tag_vals,
bool  distrib,
bool  partition_by_rank,
std::vector< int > &  pa_vec,
const FileOptions opts,
const ReaderIface::SubsetList subset_list,
const Tag file_id_tag,
const int  reader_rank,
const bool  cputime,
const int  resolve_dim,
const int  shared_dim,
const int  ghost_dim,
const int  bridge_dim,
const int  num_layers,
const int  addl_ents 
)

Definition at line 269 of file ReadParallel.cpp.

289 {
290  ErrorCode result = MB_SUCCESS;
291  if( myPcomm == NULL ) myPcomm = new ParallelComm( mbImpl, MPI_COMM_WORLD );
292 
293  Range entities;
294  Tag file_set_tag = 0;
295  int other_sets = 0;
297  Range other_file_sets, file_sets;
298  Core* impl = dynamic_cast< Core* >( mbImpl );
299 
300  std::vector< double > act_times( pa_vec.size() + 1 );
301  std::vector< int >::iterator vit;
302  int i, j;
303  act_times[0] = MPI_Wtime();
304 
305  // Make a new set for the parallel read
306  EntityHandle file_set;
307  if( !file_set_ptr || !( *file_set_ptr ) )
308  {
309  result = mbImpl->create_meshset( MESHSET_SET, file_set );
310  MB_CHK_SET_ERR( result, "Trouble creating file set" );
311  }
312  else
313  file_set = *file_set_ptr;
314 
315  bool i_read = false;
316  Tag id_tag = 0;
317  bool use_id_tag = false;
318  Range ents;
319 
320  for( i = 1, vit = pa_vec.begin(); vit != pa_vec.end(); ++vit, i++ )
321  {
322  ErrorCode tmp_result = MB_SUCCESS;
323  switch( *vit )
324  {
325  //==================
326  case PA_READ:
327  i_read = true;
328 
329  for( j = 0; j < num_files; j++ )
330  {
331  myDebug.tprintf( 1, "Reading file: \"%s\"\n", file_names[j] );
332 
333  EntityHandle new_file_set;
334  result = mbImpl->create_meshset( MESHSET_SET, new_file_set );
335  MB_CHK_SET_ERR( result, "Trouble creating file set" );
336  tmp_result = impl->serial_load_file( file_names[j], &new_file_set, opts, subset_list, file_id_tag );
337  if( MB_SUCCESS != tmp_result ) break;
338 
339  // Put the contents of each file set for the reader into the
340  // file set for the parallel read
341  assert( 0 != new_file_set );
342  Range all_ents;
343  tmp_result = mbImpl->get_entities_by_handle( new_file_set, all_ents );
344  if( MB_SUCCESS != tmp_result ) break;
345  all_ents.insert( new_file_set );
346  tmp_result = mbImpl->add_entities( file_set, all_ents );
347  if( MB_SUCCESS != tmp_result ) break;
348  }
349  if( MB_SUCCESS != tmp_result ) break;
350 
351  // Mark the file set for this parallel reader
352  tmp_result = mbImpl->tag_get_handle( "__file_set", 1, MB_TYPE_INTEGER, file_set_tag,
354  if( MB_SUCCESS != tmp_result ) break;
355 
356  tmp_result = mbImpl->tag_set_data( file_set_tag, &file_set, 1, &other_sets );
357  break;
358 
359  //==================
360  case PA_READ_PART: {
361  myDebug.tprintf( 1, "Reading file: \"%s\"\n", file_names[0] );
362 
363  i_read = true;
364  if( num_files != 1 )
365  {
366  MB_SET_ERR( MB_NOT_IMPLEMENTED, "Multiple file read not supported for READ_PART" );
367  }
368 
369  // If we're going to resolve shared entities, then we need
370  // to ask the file reader to populate a tag with unique ids
371  // (typically file ids/indices/whatever.)
372  if( std::find( pa_vec.begin(), pa_vec.end(), PA_RESOLVE_SHARED_ENTS ) != pa_vec.end() )
373  {
374  use_id_tag = true;
375  if( !file_id_tag )
376  {
377  // This tag is really used for resolving shared entities with crystal router
378  // In the end, this is an identifier that gets converted to long
379  // In hdf5 file reader, we also convert from hdf5 file id type to long
380  tmp_result = mbImpl->tag_get_handle( "", sizeof( long ), MB_TYPE_OPAQUE, id_tag,
382  if( MB_SUCCESS != tmp_result ) break;
383  file_id_tag = &id_tag;
384  }
385  }
386 
387  ReaderIface::IDTag parts = { partition_tag_name.c_str(), 0, 0 };
388  ReaderIface::SubsetList sl;
389  sl.num_parts = 0;
390  int rank = myPcomm->rank();
391  if( partition_by_rank )
392  {
393  assert( partition_tag_vals.empty() );
394  parts.tag_values = &rank;
395  parts.num_tag_values = 1;
396  }
397  else
398  {
399  sl.num_parts = myPcomm->size();
400  sl.part_number = myPcomm->rank();
401  if( !partition_tag_vals.empty() )
402  {
403  parts.tag_values = partition_tag_vals.data();
404  parts.num_tag_values = partition_tag_vals.size();
405  }
406  }
407  std::vector< ReaderIface::IDTag > subset;
408  if( subset_list )
409  {
410  std::vector< ReaderIface::IDTag > tmplist( subset_list->tag_list,
411  subset_list->tag_list + subset_list->tag_list_length );
412  tmplist.push_back( parts );
413  subset.swap( tmplist );
414  sl.tag_list = subset.data();
415  sl.tag_list_length = subset.size();
416  }
417  else
418  {
419  sl.tag_list = &parts;
420  sl.tag_list_length = 1;
421  }
422  tmp_result = impl->serial_load_file( *file_names, &file_set, opts, &sl, file_id_tag );
423  if( MB_SUCCESS != tmp_result ) break;
424 
425  if( !partition_tag_name.empty() )
426  {
427  Tag part_tag;
428  tmp_result = impl->tag_get_handle( partition_tag_name.c_str(), 1, MB_TYPE_INTEGER, part_tag );
429  if( MB_SUCCESS != tmp_result ) break;
430 
431  tmp_result = impl->get_entities_by_type_and_tag( file_set, MBENTITYSET, &part_tag, 0, 1,
432  myPcomm->partition_sets() );
433  }
434  }
435  break;
436 
437  //==================
438  case PA_GET_FILESET_ENTS:
439  myDebug.tprint( 1, "Getting fileset entities.\n" );
440 
441  // Get entities in the file set, and add actual file set to it;
442  // mark the file set to make sure any receiving procs know which it is
443  tmp_result = mbImpl->get_entities_by_handle( file_set, entities );
444  if( MB_SUCCESS != tmp_result )
445  {
446  entities.clear();
447  break;
448  }
449 
450  // Add actual file set to entities too
451  entities.insert( file_set );
452  break;
453  //==================
455  myDebug.tprint( 1, "create trivial partition, for higher dim entities.\n" );
456  // get high dim entities (2 or 3)
457  Range hi_dim_ents = entities.subset_by_dimension( 3 );
458  if( hi_dim_ents.empty() ) hi_dim_ents = entities.subset_by_dimension( 2 );
459  if( hi_dim_ents.empty() ) hi_dim_ents = entities.subset_by_dimension( 1 );
460  if( hi_dim_ents.empty() ) MB_SET_ERR( MB_FAILURE, "there are no elements of dim 1-3" );
461 
462  size_t num_hi_ents = hi_dim_ents.size();
463  unsigned int num_parts = myPcomm->size();
464 
465  // create first the trivial partition tag
466  int dum_id = -1;
467  Tag ttag; // trivial tag
468  tmp_result = mbImpl->tag_get_handle( partition_tag_name.c_str(), 1, MB_TYPE_INTEGER, ttag,
469  MB_TAG_CREAT | MB_TAG_SPARSE, &dum_id );
470  MB_CHK_SET_ERR( tmp_result, "Can't create trivial partition tag" );
471 
472  // Compute the number of high dim entities on each part
473  size_t nPartEnts = num_hi_ents / num_parts;
474 
475  // Number of extra entities after equal split over parts
476  int iextra = num_hi_ents % num_parts;
477  Range::iterator itr = hi_dim_ents.begin();
478  for( int k = 0; k < (int)num_parts; k++ )
479  {
480  // create a mesh set, insert a subrange of entities
481  EntityHandle part_set;
482  tmp_result = mbImpl->create_meshset( MESHSET_SET, part_set );
483  MB_CHK_SET_ERR( tmp_result, "Can't create part set" );
484  entities.insert( part_set );
485 
486  tmp_result = mbImpl->tag_set_data( ttag, &part_set, 1, &k );
487  MB_CHK_SET_ERR( tmp_result, "Can't set trivial partition tag" );
488  Range subrange;
489  size_t num_ents_in_part = nPartEnts;
490  if( i < iextra ) num_ents_in_part++;
491  for( size_t i1 = 0; i1 < num_ents_in_part; i1++, itr++ )
492  subrange.insert( *itr );
493  tmp_result = mbImpl->add_entities( part_set, subrange );
494  MB_CHK_SET_ERR( tmp_result, "Can't add entities to trivial part " << k );
495  myDebug.tprintf( 1, "create trivial part %d with %lu entities \n", k, num_ents_in_part );
496  tmp_result = mbImpl->add_entities( file_set, &part_set, 1 );
497  MB_CHK_SET_ERR( tmp_result, "Can't add trivial part to file set " << k );
498  }
499  }
500 
501  break;
502  //==================
503  case PA_BROADCAST:
504  // Do the actual broadcast; if single-processor, ignore error
505  myDebug.tprint( 1, "Broadcasting mesh.\n" );
506 
507  if( myPcomm->proc_config().proc_size() > 1 )
508  {
509  tmp_result = myPcomm->broadcast_entities( reader_rank, entities );
510  if( MB_SUCCESS != tmp_result ) break;
511  }
512 
513  if( debug )
514  {
515  std::cerr << "Bcast done; entities:" << std::endl;
516  mbImpl->list_entities( 0, 0 );
517  }
518 
519  // Add the received entities to this fileset if I wasn't the reader
520  if( !i_read && MB_SUCCESS == tmp_result ) tmp_result = mbImpl->add_entities( file_set, entities );
521 
522  break;
523 
524  //==================
525  case PA_DELETE_NONLOCAL:
526  myDebug.tprint( 1, "Deleting nonlocal entities.\n" );
527 
528  tmp_result = delete_nonlocal_entities( partition_tag_name, partition_tag_vals, distrib, file_set );
529  if( debug )
530  {
531  std::cerr << "Delete nonlocal done; entities:" << std::endl;
532  mbImpl->list_entities( 0, 0 );
533  }
534 
535  if( MB_SUCCESS == tmp_result ) tmp_result = create_partition_sets( partition_tag_name, file_set );
536 
537  break;
538 
539  //==================
541  myDebug.tprint( 1, "Checking global IDs.\n" );
542 
543  tmp_result = myPcomm->check_global_ids( file_set, 0, 1, true, false );
544  break;
545 
546  //==================
548  myDebug.tprint( 1, "Resolving shared entities.\n" );
549 
550  if( 1 == myPcomm->size() )
551  tmp_result = MB_SUCCESS;
552  else
553  tmp_result =
554  myPcomm->resolve_shared_ents( file_set, resolve_dim, shared_dim, use_id_tag ? file_id_tag : 0 );
555  if( MB_SUCCESS != tmp_result ) break;
556 
557 #ifndef NDEBUG
558  // check number of owned vertices through pcomm's public interface
559  tmp_result = mbImpl->get_entities_by_type( 0, MBVERTEX, ents );
560  if( MB_SUCCESS == tmp_result )
561  tmp_result = myPcomm->filter_pstatus( ents, PSTATUS_NOT_OWNED, PSTATUS_NOT );
562  if( MB_SUCCESS == tmp_result )
563  myDebug.tprintf( 1, "Proc %u reports %lu owned vertices.\n", myPcomm->proc_config().proc_rank(),
564  ents.size() );
565 #endif
566  break;
567 
568  //==================
569  case PA_EXCHANGE_GHOSTS:
570  myDebug.tprint( 1, "Exchanging ghost entities.\n" );
571 
572  tmp_result = myPcomm->exchange_ghost_cells( ghost_dim, bridge_dim, num_layers, addl_ents, true, true,
573  &file_set );
574  break;
575 
576  //==================
578  myDebug.tprint( 1, "Resolving shared sets.\n" );
579 
580  if( 1 == myPcomm->size() )
581  tmp_result = MB_SUCCESS;
582  else
583  tmp_result = myPcomm->resolve_shared_sets( file_set, use_id_tag ? file_id_tag : 0 );
584  break;
585 
586  //==================
588  myDebug.tprint( 1, "Augmenting sets with ghost entities.\n" );
589 
590  if( 1 == myPcomm->size() )
591  tmp_result = MB_SUCCESS;
592  else
593  tmp_result = myPcomm->augment_default_sets_with_ghosts( file_set );
594  break;
595  //==================
597  myDebug.tprint( 1, "correcting thin ghost layers.\n" );
598  if( 2 >= myPcomm->size() ) // it is a problem only for multi-shared entities
599  tmp_result = MB_SUCCESS;
600  else
601  tmp_result = myPcomm->correct_thin_ghost_layers();
602  break;
603  case PA_PRINT_PARALLEL:
604  myDebug.tprint( 1, "Printing parallel information.\n" );
605 
606  tmp_result = myPcomm->list_entities( 0, -1 );
607  break;
608 
609  //==================
610  default:
611  MB_SET_ERR( MB_FAILURE, "Unexpected parallel action" );
612  } // switch (*vit)
613 
614  if( MB_SUCCESS != tmp_result )
615  {
616  MB_SET_ERR( MB_FAILURE, "Failed in step " << ParallelActionsNames[*vit] );
617  }
618 
619  if( cputime ) act_times[i] = MPI_Wtime();
620  } // for (i = 1, vit = pa_vec.begin(); vit != pa_vec.end(); ++vit, i++)
621 
622  if( use_id_tag )
623  {
624  result = mbImpl->tag_delete( id_tag );
625  MB_CHK_SET_ERR( result, "Trouble deleting id tag" );
626  }
627 
628  if( cputime )
629  {
630  for( i = pa_vec.size(); i > 0; i-- )
631  act_times[i] -= act_times[i - 1];
632 
633  // Replace initial time with overall time
634  act_times[0] = MPI_Wtime() - act_times[0];
635  // Get the maximum over all procs
636  if( 0 != myPcomm->proc_config().proc_rank() )
637  {
638  MPI_Reduce( act_times.data(), 0, pa_vec.size() + 1, MPI_DOUBLE, MPI_MAX, 0,
640  }
641  else
642  {
643 #if ( MPI_VERSION >= 2 )
644  MPI_Reduce( MPI_IN_PLACE, act_times.data(), pa_vec.size() + 1, MPI_DOUBLE, MPI_MAX, 0,
646 #else
647  // Note, extra comm-size allocation is required
648  std::vector< double > act_times_tmp( pa_vec.size() + 1 );
649  MPI_Reduce( act_times.data(), act_times_tmp.data(), pa_vec.size() + 1, MPI_DOUBLE, MPI_MAX, 0,
651  act_times = act_times_tmp; // extra copy here too
652 #endif
653  std::cout << "Parallel Read times: " << std::endl;
654  for( i = 1, vit = pa_vec.begin(); vit != pa_vec.end(); ++vit, i++ )
655  std::cout << " " << act_times[i] << " " << ParallelActionsNames[*vit] << std::endl;
656  std::cout << " " << act_times[0] << " PARALLEL TOTAL" << std::endl;
657  }
658  }
659 
660  return MB_SUCCESS;
661 }

References moab::Interface::add_entities(), moab::ParallelComm::augment_default_sets_with_ghosts(), moab::Range::begin(), moab::ParallelComm::broadcast_entities(), moab::ParallelComm::check_global_ids(), moab::Range::clear(), moab::ParallelComm::correct_thin_ghost_layers(), moab::Interface::create_meshset(), create_partition_sets(), moab::debug, delete_nonlocal_entities(), moab::Range::empty(), ErrorCode, moab::ParallelComm::exchange_ghost_cells(), moab::ParallelComm::filter_pstatus(), moab::Interface::get_entities_by_handle(), moab::Interface::get_entities_by_type(), moab::Core::get_entities_by_type_and_tag(), moab::Range::insert(), moab::ParallelComm::list_entities(), moab::Interface::list_entities(), MB_CHK_SET_ERR, MB_NOT_IMPLEMENTED, MB_SET_ERR, MB_SUCCESS, MB_TAG_CREAT, MB_TAG_DENSE, MB_TAG_SPARSE, MB_TYPE_INTEGER, MB_TYPE_OPAQUE, MBENTITYSET, mbImpl, MBVERTEX, MESHSET_SET, myDebug, myPcomm, moab::ReaderIface::SubsetList::num_parts, moab::ReaderIface::IDTag::num_tag_values, PA_AUGMENT_SETS_WITH_GHOSTS, PA_BROADCAST, PA_CHECK_GIDS_SERIAL, PA_CORRECT_THIN_GHOSTS, PA_CREATE_TRIVIAL_PARTITION, PA_DELETE_NONLOCAL, PA_EXCHANGE_GHOSTS, PA_GET_FILESET_ENTS, PA_PRINT_PARALLEL, PA_READ, PA_READ_PART, PA_RESOLVE_SHARED_ENTS, PA_RESOLVE_SHARED_SETS, ParallelActionsNames, moab::ReaderIface::SubsetList::part_number, moab::ParallelComm::partition_sets(), moab::ProcConfig::proc_comm(), moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::ProcConfig::proc_size(), PSTATUS_NOT, PSTATUS_NOT_OWNED, moab::ParallelComm::rank(), moab::ParallelComm::resolve_shared_ents(), moab::ParallelComm::resolve_shared_sets(), moab::Core::serial_load_file(), moab::Range::size(), moab::ParallelComm::size(), moab::Range::subset_by_dimension(), moab::Interface::tag_delete(), moab::Core::tag_get_handle(), moab::Interface::tag_get_handle(), moab::ReaderIface::SubsetList::tag_list, moab::ReaderIface::SubsetList::tag_list_length, moab::Interface::tag_set_data(), moab::ReaderIface::IDTag::tag_values, moab::DebugOutput::tprint(), and moab::DebugOutput::tprintf().

◆ load_file() [3/3]

ErrorCode moab::ReadParallel::load_file ( const char *  file_name,
const EntityHandle file_set,
const FileOptions opts,
const ReaderIface::SubsetList subset_list = 0,
const Tag file_id_tag = 0 
)
inline

load a file

Definition at line 117 of file ReadParallel.hpp.

122 {
123  return load_file( &file_name, 1, file_set, opts, subset_list, file_id_tag );
124 }

Referenced by load_file().

Member Data Documentation

◆ mbImpl

Interface* moab::ReadParallel::mbImpl
private

◆ mError

Error* moab::ReadParallel::mError
private

Definition at line 114 of file ReadParallel.hpp.

Referenced by ReadParallel().

◆ myDebug

DebugOutput moab::ReadParallel::myDebug
private

Definition at line 112 of file ReadParallel.hpp.

Referenced by delete_nonlocal_entities(), load_file(), and ReadParallel().

◆ myPcomm

ParallelComm* moab::ReadParallel::myPcomm
private

◆ ParallelActionsNames

const char * moab::ReadParallel::ParallelActionsNames
static
Initial value:
= { "PARALLEL READ",
"PARALLEL READ PART",
"PARALLEL BROADCAST",
"PARALLEL DELETE NONLOCAL",
"PARALLEL CHECK_GIDS_SERIAL",
"PARALLEL GET_FILESET_ENTS",
"PARALLEL RESOLVE_SHARED_ENTS",
"PARALLEL EXCHANGE_GHOSTS",
"PARALLEL RESOLVE_SHARED_SETS",
"PARALLEL_AUGMENT_SETS_WITH_GHOSTS",
"PARALLEL PRINT_PARALLEL",
"PARALLEL_CREATE_TRIVIAL_PARTITION",
"PARALLEL_CORRECT_THIN_GHOST_LAYERS" }

Definition at line 83 of file ReadParallel.hpp.

Referenced by load_file().

◆ parallelOptsNames

const char * moab::ReadParallel::parallelOptsNames = { "NONE", "BCAST", "BCAST_DELETE", "READ_DELETE", "READ_PART", "", 0 }
static

Definition at line 64 of file ReadParallel.hpp.

Referenced by load_file().


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