Example demonstrating parallel mesh reading and writing with performance timing.This example shows how to:
The example is designed for stress testing of MOAB's parallel reader/writer capabilities and provides timing information for performance analysis.
#include <iostream>
#include <chrono>
#include <string>
#include <memory>
#include <cstdlib>
#ifdef MOAB_HAVE_MPI
#include <mpi.h>
#endif
namespace
{
struct Config
{
std::string output_file;
std::string read_opts;
std::string write_opts;
bool use_defaults = false;
};
{
std::cout << "Usage: mpiexec -np <num_procs> " << program_name << " [input_file] [output_file] [options]\n"
<< "Options:\n"
<< " -O <read_opts> Options for reading the input file\n"
<< " -o <write_opts> Options for writing the output file\n"
<< "\nExample:\n"
<< " mpiexec -np 4 " << program_name << " input.nc output.h5m \\\n"
<< " -O \"PARALLEL=READ_PART;PARTITION_METHOD=SQIJ\" \\n"
<< " -o \"PARALLEL=WRITE_PART\"\n";
}
{
Config config;
#ifdef MOAB_HAVE_NETCDF
config.input_file = std::string(
MESH_DIR ) +
"/io/fv3x46x72.t.3.nc";
config.output_file = "ReadWriteTestOut.h5m";
config.read_opts = "PARALLEL=READ_PART;PARTITION_METHOD=SQIJ;PARALLEL_RESOLVE_SHARED_ENTS;VARIABLE=T,U";
config.write_opts = "PARALLEL=WRITE_PART";
config.use_defaults = true;
#else
if( argc < 3 )
{
std::exit( 1 );
}
#endif
if( argc >= 3 )
{
config.input_file = argv[1];
config.output_file = argv[2];
config.use_defaults = false;
}
for( int i = 3; i < argc; ++i )
{
std::string arg = argv[i];
if( arg == "-O" && i + 1 < argc )
{
config.read_opts = argv[++i];
}
else if( arg == "-o" && i + 1 < argc )
{
config.write_opts = argv[++i];
}
else if( arg == "-h" || arg == "--help" )
{
std::exit( 0 );
}
}
return config;
}
void print_config(
const Config& config,
int rank,
int nprocs )
{
if( rank == 0 )
{
std::cout << "\n=== MOAB Parallel Read/Write Test ===\n"
<< "Input file: " << config.input_file << "\n"
<< "Output file: " << config.output_file << "\n"
<< "Read options: " << ( config.read_opts.empty() ? "(default)" : config.read_opts ) << "\n"
<< "Write options: " << ( config.write_opts.empty() ? "(default)" : config.write_opts ) << "\n"
<< "Running on " << nprocs << " MPI processes\n"
<< std::endl;
}
}
}
int main(
int argc,
char** argv )
{
int mpi_initialized = 0;
MPI_Initialized( &mpi_initialized );
if( !mpi_initialized )
{
MPI_Init( &argc, &argv );
}
int rank = 0;
int nprocs = 1;
MPI_Comm_rank( MPI_COMM_WORLD, &rank );
MPI_Comm_size( MPI_COMM_WORLD, &nprocs );
try
{
if( rank == 0 )
{
}
auto moab = std::make_unique< Core >();
{
std::cerr << "Error: Failed to create MOAB instance" << std::endl;
MPI_Abort( MPI_COMM_WORLD, 1 );
}
auto pcomm = std::make_unique< ParallelComm >(
moab.get(), MPI_COMM_WORLD );
auto read_start = std::chrono::high_resolution_clock::now();
if( rank == 0 )
{
std::cout << "Reading mesh file..." << std::endl;
}
MB_CHK_SET_ERR(
moab->load_file( config.input_file.c_str(), &mesh_set, config.read_opts.c_str() ),
"Failed to read input file: " << config.input_file );
auto read_end = std::chrono::high_resolution_clock::now();
std::chrono::duration< double > read_elapsed = read_end - read_start;
if( rank == 0 )
{
std::cout << "Read completed in " << read_elapsed.count() << " seconds" << std::endl;
std::cout << "Writing mesh file..." << std::endl;
}
auto write_start = std::chrono::high_resolution_clock::now();
MB_CHK_SET_ERR(
moab->write_file( config.output_file.c_str(),
nullptr, config.write_opts.c_str(), &mesh_set,
1 ),
"Failed to write output file: " << config.output_file );
auto write_end = std::chrono::high_resolution_clock::now();
std::chrono::duration< double > write_elapsed = write_end - write_start;
if( rank == 0 )
{
std::cout << "Write completed in " << write_elapsed.count() << " seconds" << std::endl;
std::cout << "\n=== Test completed successfully ===" << std::endl;
}
pcomm.reset();
if( !mpi_initialized )
{
MPI_Finalize();
}
return 0;
}
catch( const std::exception& e )
{
std::cerr << "Error on rank " << rank << ": " << e.what() << std::endl;
MPI_Abort( MPI_COMM_WORLD, 1 );
return 1;
}
catch( ... )
{
std::cerr << "Unknown error occurred on rank " << rank << std::endl;
MPI_Abort( MPI_COMM_WORLD, 1 );
return 1;
}
}