39 #error "Please build MOAB with MPI..."
51 #define dbgprint( MSG ) \
54 if( context.proc_id == 0 ) std::cout << MSG << std::endl; \
57 #define runchk( CODE, MSG ) \
60 moab::ErrorCode err = CODE; \
61 MB_CHK_SET_ERR( err, MSG ); \
64 #define runchk_cont( CODE, MSG ) \
67 moab::ErrorCode err = CODE; \
68 MB_CHK_ERR_CONT( err ); \
69 if( err ) std::cout << "Error:: " << MSG << std::endl; \
83 int ghost_layers{ 3 };
86 int vector_length{ 3 };
87 int num_max_exchange{ 10 };
88 bool debug_output{
false };
91 double last_counter{ 0.0 };
108 void ParseCLOptions(
int argc,
char* argv[] );
112 inline void timer_push(
const std::string& operation );
116 void timer_pop(
const int nruns = 1 );
120 inline double last_elapsed()
const;
142 inline double evaluate_function(
double lon,
double lat,
int type = 1,
double multiplier = 1.0 )
const
147 return ( 2.0 + std::pow( sin( 2.0 * lat ), 16.0 ) * cos( 16.0 * lon ) ) * multiplier;
149 return ( 2.0 + cos( lon ) * cos( lon ) * cos( 2.0 * lat ) ) * multiplier;
160 double mTimerOps{ 0.0 };
167 int main(
int argc,
char** argv )
170 MPI_Init( &argc, &argv );
175 dbgprint(
"********** Exchange halos example **********\n" );
178 context.ParseCLOptions( argc, argv );
182 dbgprint(
" -- Input Parameters -- " );
192 double elapsed_times[4];
196 context.timer_push(
"Read input file" );
199 runchk(
context.load_file(
false ),
"MOAB::load_file failed for filename: " <<
context.input_filename );
202 elapsed_times[0] =
context.last_elapsed();
205 dbgprint(
"\n- Starting execution -\n" );
209 context.timer_push(
"Setup ghost layers" );
212 for(
int ighost = 0; ighost <
context.ghost_layers; ++ighost )
215 int ghost_dimension =
context.dimension;
216 int bridge_dimension =
context.dimension - 1;
219 ghost_dimension, bridge_dimension, ( ighost + 1 ), 0,
true ,
221 "Exchange ghost cells failed" );
225 if( ighost <
context.ghost_layers - 1 )
226 runchk(
context.parallel_communicator->correct_thin_ghost_layers(),
227 "Thin layer correction failed" );
231 elapsed_times[1] =
context.last_elapsed();
238 "Getting 2D entities failed" );
242 "Filtering pstatus failed" );
245 auto numEntities = dimEnts.
size();
246 int numTotalEntities = 0;
247 MPI_Reduce( &numEntities, &numTotalEntities, 1, MPI_INT, MPI_SUM, 0,
248 context.parallel_communicator->proc_config().proc_comm() );
252 dbgprint(
"Total number of " <<
context.dimension <<
"D elements in the mesh = " << numTotalEntities );
255 Tag tagScalar =
nullptr;
256 Tag tagVector =
nullptr;
260 runchk(
context.create_sv_tags( tagScalar, tagVector, dimEnts ),
"Unable to create scalar and vector tags" );
266 dbgprint(
"> Writing to file *before* ghost exchange " );
267 runchk(
context.moab_interface.write_file(
"exchangeHalos_output_rank0_pre.h5m",
"H5M",
"" ),
268 "Writing to disk failed" );
272 dbgprint(
"> Exchanging tags between processors " );
273 context.timer_push(
"Exchange scalar tag data" );
274 for(
auto irun = 0; irun <
context.num_max_exchange; ++irun )
277 runchk(
context.parallel_communicator->exchange_tags( tagScalar, dimEnts ),
278 "Exchanging scalar tag between processors failed" );
281 elapsed_times[2] =
context.last_elapsed();
283 context.timer_push(
"Exchange vector tag data" );
284 for(
auto irun = 0; irun <
context.num_max_exchange; ++irun )
287 runchk(
context.parallel_communicator->exchange_tags( tagVector, dimEnts ),
288 "Exchanging vector tag between processors failed" );
291 elapsed_times[3] =
context.last_elapsed();
297 dbgprint(
"> Writing to file *after* ghost exchange " );
298 runchk(
context.moab_interface.write_file(
"exchangeHalos_output_rank0_post.h5m",
"H5M",
"" ),
299 "Writing to disk failed" );
305 dbgprint(
"> Writing out the final mesh and data in MOAB h5m format. File = " <<
context.output_filename );
306 string write_options = (
context.num_procs > 1 ?
"PARALLEL=WRITE_PART;DEBUG_IO=0;" :
"" );
308 runchk(
context.moab_interface.write_file(
context.output_filename.c_str(),
"H5M", write_options.c_str() ),
309 "File write failed" );
315 dbgprint(
"\n> Consolidated: [" <<
context.num_procs <<
", " <<
context.ghost_layers <<
", " << elapsed_times[0]
316 <<
", " << elapsed_times[1] <<
", " << elapsed_times[2] <<
", "
317 << elapsed_times[3] <<
"]," );
320 dbgprint(
"\n********** ExchangeHalos Example DONE! **********" );
332 : input_filename( std::string(
MESH_DIR ) + std::string(
"/io/mpasx1.642.t.2.nc" ) ),
333 output_filename(
"exchangeHalos_output.h5m" ), scalar_tagname(
"scalar_variable" ),
334 vector_tagname(
"vector_variable" )
356 opts.
addOpt< std::string >(
"input",
"Input mesh filename to load in parallel. Default=data/default_mesh_holes.h5m",
359 opts.
addOpt<
void >(
"debug",
"Should we write output file? Default=false", &
debug_output );
360 opts.
addOpt< std::string >(
"output",
361 "Output mesh filename for verification (use --debug). Default=exchangeHalos_output.h5m",
365 opts.
addOpt<
int >(
"vtaglength",
"Size of vector components per each entity. Default=3", &
vector_length );
367 opts.
addOpt<
int >(
"nghosts",
"Number of ghost layers (halos) to exchange. Default=3", &
ghost_layers );
369 opts.
addOpt<
int >(
"nexchanges",
"Number of ghost-halo exchange iterations to perform. Default=10",
384 double avgElapsed = 0;
385 double maxElapsed = 0;
392 std::cout <<
"[LOG] Time taken to " <<
mOpName.c_str() <<
", averaged over " << nruns
393 <<
" runs : max = " << maxElapsed / nruns <<
", avg = " << avgElapsed / nruns <<
"\n";
395 std::cout <<
"[LOG] Time taken to " <<
mOpName.c_str() <<
" : max = " << maxElapsed
396 <<
", avg = " << avgElapsed <<
"\n";
413 if(
proc_id == 0 ) std::cout <<
"> Getting scalar tag handle " <<
scalar_tagname <<
"..." << std::endl;
414 double defSTagValue = -1.0;
415 bool createdTScalar =
false;
420 "Retrieving scalar tag handle failed" );
423 assert( createdTScalar );
426 std::vector< double > tagValues(
entities.size(), -1.0 );
427 std::generate( tagValues.begin(), tagValues.end(), [=, &entCoords]() {
428 static int index = 0;
429 const int offset = index++ * 2;
430 return evaluate_function( entCoords[offset], entCoords[offset + 1] );
434 "Setting scalar tag data failed" );
437 if(
proc_id == 0 ) std::cout <<
"> Getting vector tag handle " <<
vector_tagname <<
"..." << std::endl;
439 bool createdTVector =
false;
445 "Retrieving vector tag handle failed" );
448 assert( createdTVector );
453 std::vector< double > tagValues(
entities.size() * veclength, -1.0 );
454 std::generate( tagValues.begin(), tagValues.end(), [=, &entCoords]() {
455 static int index = 0;
456 const int offset = ( index++ / veclength ) * 2;
457 return this->evaluate_function( entCoords[offset], entCoords[offset + 1], 2, ( index % veclength + 1.0 ) );
461 "Setting vector tag data failed" );
479 std::string read_options =
"DEBUG_IO=0;";
481 if(
num_procs > 1 && idx != std::string::npos )
484 if( !extension.compare(
"nc" ) )
486 read_options +=
"PARALLEL=READ_PART;PARTITION_METHOD=RCBZOLTAN;"
487 "PARALLEL_RESOLVE_SHARED_ENTS;NO_EDGES;NO_MIXED_ELEMENTS;VARIABLE=;";
488 else if( !extension.compare(
"h5m" ) )
490 "PARALLEL=READ_PART;PARTITION=PARALLEL_PARTITION;"
491 "PARALLEL_RESOLVE_SHARED_ENTS;" +
492 ( load_ghosts ?
"PARALLEL_THIN_GHOST_LAYER;PARALLEL_GHOSTS=2.1." + std::to_string(
ghost_layers ) +
";"
496 std::cout <<
"Error unsupported file type (only h5m and nc) for this example: " <<
input_filename
509 std::vector< double > eCentroids(
entities.size() * 2 );
517 double magnitude = std::sqrt( node[0] * node[0] + node[1] * node[1] + node[2] * node[2] );
518 node[0] /= magnitude;
519 node[1] /= magnitude;
520 node[2] /= magnitude;
523 eCentroids[offset] = atan2( node[1], node[0] );
524 if( eCentroids[offset] < 0.0 ) eCentroids[offset] += 2.0 * M_PI;
525 eCentroids[offset + 1] = asin( node[2] );