35 #include <sys/times.h>
44 #ifdef MOAB_HAVE_TEMPESTREMAP
47 constexpr
bool offlineGenerator =
true;
57 #define ENT_NOT_FOUND 5
61 static void print_usage(
const char* name, std::ostream& stream )
63 stream <<
"Usage: " << name
64 <<
" [-a <sat_file>|-A] [-t] [subset options] [-f format] <input_file> [<input_file2> "
67 <<
"\t-f <format> - Specify output file format" << std::endl
68 <<
"\t-a <acis_file> - ACIS SAT file dumped by .cub reader (same as \"-o "
69 "SAT_FILE=acis_file\""
71 <<
"\t-A - .cub file reader should not dump a SAT file (depricated default)" << std::endl
72 <<
"\t-o option - Specify write option." << std::endl
73 <<
"\t-O option - Specify read option." << std::endl
74 <<
"\t-t - Time read and write of files." << std::endl
75 <<
"\t-g - Enable verbose/debug output." << std::endl
76 <<
"\t-h - Print this help text and exit." << std::endl
77 <<
"\t-l - List available file formats and exit." << std::endl
78 <<
"\t-I dim - Generate internal entities of specified dimension." << std::endl
80 <<
"\t-P - Append processor ID to output file name" << std::endl
81 <<
"\t-p - Replace '%' with processor ID in input and output file name" << std::endl
82 <<
"\t-M[0|1|2] - Read/write in parallel, optionally also doing "
83 "resolve_shared_ents (1) and exchange_ghosts (2)"
85 <<
"\t-z <file> - Read metis partition information corresponding to an MPAS grid "
86 "file and create h5m partition file"
90 #ifdef MOAB_HAVE_TEMPESTREMAP
91 <<
"\t-B - Use TempestRemap exodus file reader and convert to MOAB format" << std::endl
92 <<
"\t-b - Convert MOAB mesh to TempestRemap exodus file writer" << std::endl
93 <<
"\t-S - Scale climate mesh to unit sphere" << std::endl
94 <<
"\t-i - Name of the global DoF tag to use with mbtempest" << std::endl
95 <<
"\t-r - Order of field DoF (discretization) data; FV=1,SE=[1,N]" << std::endl
97 <<
"\t-- - treat all subsequent options as file names" << std::endl
98 <<
"\t (allows file names beginning with '-')" << std::endl
99 <<
" subset options: " << std::endl
100 <<
"\tEach of the following options should be followed by " << std::endl
101 <<
"\ta list of ids. IDs may be separated with commas. " << std::endl
102 <<
"\tRanges of IDs may be specified with a '-' between " << std::endl
103 <<
"\ttwo values. The list may not contain spaces." << std::endl
104 <<
"\t-v - Volume" << std::endl
105 <<
"\t-s - Surface" << std::endl
106 <<
"\t-c - Curve" << std::endl
107 <<
"\t-V - Vertex" << std::endl
108 <<
"\t-m - Material set (block)" << std::endl
109 <<
"\t-d - Dirichlet set (nodeset)" << std::endl
110 <<
"\t-n - Neumann set (sideset)" << std::endl
111 <<
"\t-D - Parallel partitioning set (PARALLEL_PARTITION)" << std::endl
112 <<
"\tThe presence of one or more of the following flags limits " << std::endl
113 <<
"\tthe exported mesh to only elements of the corresponding " << std::endl
114 <<
"\tdimension. Vertices are always exported." << std::endl
115 <<
"\t-1 - Edges " << std::endl
116 <<
"\t-2 - Tri, Quad, Polygon " << std::endl
117 <<
"\t-3 - Tet, Hex, Prism, etc. " << std::endl;
122 std::cout <<
" This program can be used to convert between mesh file\n"
123 " formats, extract a subset of a mesh file to a separate\n"
124 " file, or both. The type of file to write is determined\n"
125 " from the file extension (e.g. \".vtk\") portion of the\n"
126 " output file name.\n"
128 " While MOAB strives to export and import all data from\n"
129 " each supported file format, most file formats do\n"
130 " not support MOAB's entire data model. Thus MOAB cannot\n"
131 " guarantee lossless conversion for any file formats\n"
132 " other than the native HDF5 representation.\n"
149 static bool parse_id_list(
const char*
string, std::set< int >& );
150 static void print_id_list(
const char*, std::ostream& stream,
const std::set< int >& list );
155 static bool make_opts_string( std::vector< std::string > options, std::string& result );
156 static std::string
percent_subst(
const std::string& s,
int val );
160 int main(
int argc,
char* argv[] )
164 MPI_Init( &argc, &argv );
165 MPI_Comm_rank( MPI_COMM_WORLD, &proc_id );
168 #ifdef MOAB_HAVE_TEMPESTREMAP
169 bool tempestin =
false, tempestout =
false;
177 #if ( defined( MOAB_HAVE_MPI ) && defined( MOAB_HAVE_TEMPESTREMAP ) )
181 bool append_rank =
false;
182 bool percent_rank_subst =
false;
183 bool file_written =
false;
185 std::list< std::string >::iterator j;
186 bool dims[4] = {
false,
false,
false,
false };
187 const char* format = NULL;
188 std::list< std::string > in;
191 std::set< int > geom[4], mesh[4];
192 std::vector< EntityHandle > set_list;
193 std::vector< std::string > write_opts, read_opts;
194 std::string metis_partition_file;
195 #ifdef MOAB_HAVE_TEMPESTREMAP
196 std::string globalid_tag_name;
197 int spectral_order = 1;
198 bool unitscaling =
false;
203 const char*
const geom_names[] = {
"VERTEX",
"CURVE",
"SURFACE",
"VOLUME" };
207 bool print_times =
false;
208 bool generate[] = {
false,
false,
false };
210 bool parallel =
false, resolve_shared =
false, exchange_ghosts =
false;
211 for( i = 1; i < argc; i++ )
215 if( do_flag && argv[i][0] ==
'-' )
217 if( !argv[i][1] || ( argv[i][1] !=
'M' && argv[i][2] ) )
usage_error( argv[0] );
245 percent_rank_subst =
true;
249 if( argv[i][2] ==
'1' || argv[i][2] ==
'2' ) resolve_shared =
true;
250 if( argv[i][2] ==
'2' ) exchange_ghosts =
true;
253 #ifdef MOAB_HAVE_TEMPESTREMAP
267 dims[argv[i][1] -
'0'] =
true;
272 if( i == argc || argv[i][0] ==
'-' )
274 std::cerr <<
"Expected argument following " << argv[i - 1] << std::endl;
277 if( argv[i - 1][1] ==
'I' )
279 dim = atoi( argv[i] );
280 if( dim < 1 || dim > 2 )
282 std::cerr <<
"Invalid dimension value following -I" << std::endl;
285 generate[dim] =
true;
289 switch( argv[i - 1][1] )
292 read_opts.push_back( std::string(
"SAT_FILE=" ) + argv[i] );
300 write_opts.push_back( argv[i] );
304 read_opts.push_back( argv[i] );
307 #ifdef MOAB_HAVE_TEMPESTREMAP
309 globalid_tag_name = std::string( argv[i] );
313 spectral_order = atoi( argv[i] );
342 metis_partition_file = argv[i];
346 std::cerr <<
"Invalid option: " << argv[i] << std::endl;
351 std::cerr <<
"Invalid flag or flag value: " << argv[i - 1] <<
" " << argv[i] << std::endl;
359 in.push_back( argv[i] );
364 std::cerr <<
"No output file name specified." << std::endl;
373 std::ostringstream mod;
374 mod << out <<
"." << proc_id;
378 if( percent_rank_subst )
380 for( j = in.begin(); j != in.end(); ++j )
386 std::string read_options, write_options;
389 read_opts.push_back(
"PARALLEL=READ_PART" );
390 read_opts.push_back(
"PARTITION=PARALLEL_PARTITION" );
391 if( !append_rank && !percent_rank_subst ) write_opts.push_back(
"PARALLEL=WRITE_PART" );
393 if( resolve_shared ) read_opts.push_back(
"PARALLEL_RESOLVE_SHARED_ENTS" );
394 if( exchange_ghosts ) read_opts.push_back(
"PARALLEL_GHOSTS=3.0.1" );
404 if( !metis_partition_file.empty() )
406 if( ( in.size() != 1 ) || ( proc_id != 0 ) )
408 std::cerr <<
" mpas partition allows only one input file, in serial conversion\n";
419 #ifdef MOAB_HAVE_TEMPESTREMAP
420 if( tempestin && in.size() > 1 )
422 std::cerr <<
" we can read only one tempest files at a time\n";
429 if( tempestin or tempestout )
438 bool use_overlap_context =
false;
439 Tag srcParentTag, tgtParentTag;
442 for( j = in.begin(); j != in.end(); ++j )
444 std::string inFileName = *j;
448 #ifdef MOAB_HAVE_TEMPESTREMAP
464 tempestMesh->RemoveZeroEdges();
465 tempestMesh->RemoveCoincidentNodes();
477 NcFile ncInput( inFileName.c_str(), NcFile::ReadOnly );
479 NcError error_temp( NcError::silent_nonfatal );
481 NcAtt* attRectilinear = ncInput.get_att(
"rectilinear" );
482 NcVar* varGridDims = ncInput.get_var(
"grid_dims" );
485 std::vector< int > vecDimSizes( 3, 0 );
494 if( attRectilinear !=
nullptr )
497 NcAtt* attRectilinearDim0Size = ncInput.get_att(
"rectilinear_dim0_size" );
498 NcAtt* attRectilinearDim1Size = ncInput.get_att(
"rectilinear_dim1_size" );
500 if( attRectilinearDim0Size ==
nullptr )
502 _EXCEPTIONT(
"Missing attribute \"rectilinear_dim0_size\"" );
504 if( attRectilinearDim1Size ==
nullptr )
506 _EXCEPTIONT(
"Missing attribute \"rectilinear_dim1_size\"" );
509 int nDim0Size = attRectilinearDim0Size->as_int( 0 );
510 int nDim1Size = attRectilinearDim1Size->as_int( 0 );
513 NcAtt* attRectilinearDim0Name = ncInput.get_att(
"rectilinear_dim0_name" );
514 NcAtt* attRectilinearDim1Name = ncInput.get_att(
"rectilinear_dim1_name" );
516 if( attRectilinearDim0Name ==
nullptr )
518 _EXCEPTIONT(
"Missing attribute \"rectilinear_dim0_name\"" );
520 if( attRectilinearDim1Name ==
nullptr )
522 _EXCEPTIONT(
"Missing attribute \"rectilinear_dim1_name\"" );
525 std::string strDim0Name = attRectilinearDim0Name->as_string( 0 );
526 std::string strDim1Name = attRectilinearDim1Name->as_string( 0 );
528 std::map< std::string, int > vecDimNameSizes;
530 vecDimNameSizes[strDim0Name] = nDim0Size;
531 vecDimNameSizes[strDim1Name] = nDim1Size;
533 vecDimSizes[1] = vecDimNameSizes[
"lat"];
534 vecDimSizes[2] = vecDimNameSizes[
"lon"];
536 else if( varGridDims !=
nullptr )
539 NcDim* dimGridRank = varGridDims->get_dim( 0 );
540 if( dimGridRank == NULL )
542 _EXCEPTIONT(
"Variable \"grid_dims\" has no dimensions" );
545 int gridrank = dimGridRank->size();
548 varGridDims->get( &( gridsizes[0] ), dimGridRank->size() );
559 vecDimSizes[1] = elems.
size();
565 vecDimSizes[1] = gridsizes[0];
566 vecDimSizes[2] = gridsizes[1];
578 vecDimSizes[1] = elems.
size();
583 result =
gMB->
tag_set_data( rectilinearTag, &mSet, 1, vecDimSizes.data() );
586 switch( vecDimSizes[0] )
589 printf(
"Cubed-Sphere mesh: %d (elements), %d (vertices)\n", vecDimSizes[1], vecDimSizes[2] );
592 printf(
"Rectilinear RLL mesh: (lon) %d X (lat) %d\n", vecDimSizes[2], vecDimSizes[1] );
595 printf(
"Icosahedral (triangular) mesh: %d (elements), %d (vertices)\n", vecDimSizes[1],
600 printf(
"Polygonal mesh: %d (elements), %d (vertices)\n", vecDimSizes[1], vecDimSizes[2] );
606 const size_t nOverlapFaces = tempestMesh->faces.size();
607 if( tempestMesh->vecSourceFaceIx.size() == nOverlapFaces &&
608 tempestMesh->vecSourceFaceIx.size() == nOverlapFaces )
611 use_overlap_context =
true;
624 std::vector< int > gids( faces.
size() ), srcpar( faces.
size() ), tgtpar( faces.
size() );
628 for(
unsigned ii = 0; ii < faces.
size(); ++ii )
630 srcpar[ii] = tempestMesh->vecSourceFaceIx[gids[ii] - 1];
631 tgtpar[ii] = tempestMesh->vecTargetFaceIx[gids[ii] - 1];
644 else if( tempestout )
650 std::vector< int > metadata( 2 );
666 use_overlap_context =
true;
689 assert( metadata.size() );
690 std::cout <<
"Converting a RLL mesh with rectilinear dimension: " << metadata[0] <<
" X "
691 << metadata[1] << std::endl;
701 result =
gMB->
load_file( j->c_str(), 0, read_options.c_str() );
703 result =
gMB->
load_file( j->c_str(), 0, read_options.c_str() );
707 std::cerr <<
"Failed to load \"" << *j <<
"\"." << std::endl;
708 std::cerr <<
"Error code: " <<
gMB->
get_error_string( result ) <<
" (" << result <<
")" << std::endl;
711 std::cerr <<
"Error message: " << message << std::endl;
717 if( !proc_id ) std::cerr <<
"Read \"" << *j <<
"\"" << std::endl;
718 if( print_times && !proc_id )
write_times( std::cout );
722 bool have_geom =
false;
723 for( dim = 0; dim <= 3; ++dim )
725 if( !geom[dim].empty() ) have_geom =
true;
730 bool have_sets = have_geom;
738 std::cerr <<
"No ID tag defined." << std::endl;
744 std::cerr <<
"No geometry tag defined." << std::endl;
753 Tag tags[] = { id_tag, dim_tag };
754 const void* vals[] = { &id_val, &dim };
755 for( dim = 0; dim <= 3; ++dim )
757 int init_count = set_list.size();
758 for( std::set< int >::iterator iter = geom[dim].begin(); iter != geom[dim].end(); ++iter )
766 std::cerr << geom_names[dim] <<
" " << id_val <<
" not found.\n";
768 std::copy( range.
begin(), range.
end(), std::back_inserter( set_list ) );
772 std::cout <<
"Found " << ( set_list.size() - init_count ) <<
' ' << geom_names[dim] <<
" sets"
778 for( i = 0; i < 4; ++i )
782 if( mesh[i].empty() )
continue;
790 std::cerr <<
"Tag not found: " << mesh_tag_names[i] << std::endl;
795 int init_count = set_list.size();
796 for( std::set< int >::iterator iter = mesh[i].begin(); iter != mesh[i].end(); ++iter )
799 const void* vals[] = { &*iter };
804 std::cerr << mesh_tag_names[i] <<
" " << *iter <<
" not found.\n";
806 std::copy( range.
begin(), range.
end(), std::back_inserter( set_list ) );
810 std::cout <<
"Found " << ( set_list.size() - init_count ) <<
' ' << mesh_tag_names[i] <<
" sets"
816 for( dim = 1; dim < 4; ++dim )
817 if( dims[dim] ) bydim =
true;
822 if( generate[1] && !dims[1] )
824 std::cerr <<
"Warning: Request to generate 1D internal entities but not export them." << std::endl;
827 if( generate[2] && !dims[2] )
829 std::cerr <<
"Warning: Request to generate 2D internal entities but not export them." << std::endl;
835 if( generate[1] || generate[2] )
842 num_sets = set_list.size();
845 for( i = 0; i < num_sets; ++i )
847 Range dim3, dim2, adj;
867 Range dead_entities, tmp_range;
868 for( dim = 1; dim <= 3; ++dim )
870 if( dims[dim] )
continue;
872 dead_entities.
merge( tmp_range );
878 while( !empty_sets.
empty() )
881 dead_entities.
merge( empty_sets );
884 empty_sets =
subtract( tmp_range, dead_entities );
891 if( have_sets && set_list.empty() )
893 std::cerr <<
"Nothing to write." << std::endl;
901 if( !metis_partition_file.empty() )
906 std::cerr <<
"Failed to process partition file \"" << metis_partition_file <<
"\"." << std::endl;
916 std::cout <<
"Found " << set_list.size() <<
" specified sets to write (total)." << std::endl;
918 std::cout <<
"No sets specifed. Writing entire mesh." << std::endl;
923 #ifdef MOAB_HAVE_TEMPESTREMAP
933 int ntot_elements = 0, nelements = faces.
size();
935 int ierr = MPI_Allreduce( &nelements, &ntot_elements, 1, MPI_INT, MPI_SUM, pcomm->
comm() );
936 if( ierr != 0 )
MB_CHK_SET_ERR( MB_FAILURE,
"MPI_Allreduce failed to get total source elements" );
938 ntot_elements = nelements;
942 std::vector< int > gids( faces.
size() );
946 if( faces.
size() > 1 && gids[0] == gids[1] && !use_overlap_context )
962 if( spectral_order > 1 && globalid_tag_name.size() > 1 )
964 result = remapper->
GenerateMeshMetadata( *tempestMesh, ntot_elements, faces, NULL, globalid_tag_name,
973 if( use_overlap_context &&
false )
975 const int nOverlapFaces = faces.
size();
977 tempestMesh->vecSourceFaceIx.resize( nOverlapFaces );
978 tempestMesh->vecTargetFaceIx.resize( nOverlapFaces );
979 result =
gMB->
tag_get_data( srcParentTag, faces, &tempestMesh->vecSourceFaceIx[0] );
981 result =
gMB->
tag_get_data( tgtParentTag, faces, &tempestMesh->vecTargetFaceIx[0] );
985 tempestMesh->Write( out, NcFile::Netcdf4 );
995 result =
gMB->
write_file( out.c_str(), format, write_options.c_str(), &set_list[0], set_list.size() );
997 result =
gMB->
write_file( out.c_str(), format, write_options.c_str() );
1000 std::cerr <<
"Failed to write \"" << out <<
"\"." << std::endl;
1001 std::cerr <<
"Error code: " <<
gMB->
get_error_string( result ) <<
" (" << result <<
")" << std::endl;
1002 std::string message;
1004 std::cerr <<
"Error message: " << message << std::endl;
1005 #ifdef MOAB_HAVE_MPI
1012 if( !proc_id ) std::cerr <<
"Wrote \"" << out <<
"\"" << std::endl;
1013 if( print_times && !proc_id )
write_times( std::cout );
1015 #ifdef MOAB_HAVE_MPI
1024 char* mystr = strdup(
string );
1025 for(
const char* ptr = strtok( mystr,
"," ); ptr; ptr = strtok( 0,
"," ) )
1028 long val = strtol( ptr, &endptr, 0 );
1029 if( endptr == ptr || val <= 0 )
1031 std::cerr <<
"Not a valid id: " << ptr << std::endl;
1037 if( *endptr ==
'-' )
1039 const char* sptr = endptr + 1;
1040 val2 = strtol( sptr, &endptr, 0 );
1041 if( endptr == sptr || val2 <= 0 )
1043 std::cerr <<
"Not a valid id: " << sptr << std::endl;
1049 std::cerr <<
"Invalid id range: " << ptr << std::endl;
1057 std::cerr <<
"Unexpected character: " << *endptr << std::endl;
1062 for( ; val <= val2; ++val )
1063 if( !results.insert( (
int)val ).second ) std::cerr <<
"Warning: duplicate Id: " << val << std::endl;
1070 void print_id_list(
const char* head, std::ostream& stream,
const std::set< int >& list )
1072 stream << head <<
": ";
1076 stream <<
"(none)" << std::endl;
1081 std::set< int >::const_iterator iter = list.begin();
1082 start = prev = *( iter++ );
1085 if( iter == list.end() || *iter != 1 + prev )
1088 if( prev != start ) stream <<
'-' << prev;
1089 if( iter == list.end() )
break;
1096 stream << std::endl;
1099 static void print_time(
int clk_per_sec,
const char* prefix, clock_t ticks, std::ostream& stream )
1101 ticks *= clk_per_sec / 100;
1102 clock_t centi = ticks % 100;
1103 clock_t seconds = ticks / 100;
1107 stream << ( ticks / 100 ) <<
"." << centi <<
"s" << std::endl;
1111 clock_t minutes = ( seconds / 60 ) % 60;
1112 clock_t hours = ( seconds / 3600 );
1114 if( hours ) stream << hours <<
"h";
1115 if( minutes ) stream << minutes <<
"m";
1116 if( seconds || centi ) stream << seconds <<
"." << centi <<
"s";
1117 stream <<
" (" << ( ticks / 100 ) <<
"." << centi <<
"s)" << std::endl;
1132 clock_t abs_tm = clock();
1149 clock_t usr_tm, sys_tm, abs_tm;
1151 abs_tm = times( &timebuf );
1152 usr_tm = timebuf.tms_utime;
1153 sys_tm = timebuf.tms_stime;
1167 if( options.empty() )
return true;
1170 std::vector< std::string >::const_iterator i;
1171 char separator =
'\0';
1172 const char* alt_separators =
";+,:\t\n";
1173 for(
const char* sep_ptr = alt_separators; *sep_ptr; ++sep_ptr )
1176 for( i = options.begin(); i != options.end(); ++i )
1177 if( i->find( *sep_ptr, 0 ) != std::string::npos )
1184 separator = *sep_ptr;
1190 std::cerr <<
"Error: cannot find separator character for options string" << std::endl;
1193 if( separator !=
';' )
1200 i = options.begin();
1202 for( ++i; i != options.end(); ++i )
1213 const char iface_name[] =
"ReaderWriterSet";
1217 std::ostream& str = std::cout;
1223 std::cerr <<
"Internal error: Interface \"" << iface_name <<
"\" not available.\n";
1229 for( i = set->
begin(); i != set->
end(); ++i )
1230 if( i->description().length() > w ) w = i->description().length();
1233 str <<
"Format " << std::setw( w ) << std::left <<
"Description" <<
" Read Write File Name Suffixes\n"
1234 <<
"------ " << std::setw( w ) << std::setfill(
'-' ) <<
"" << std::setfill(
' ' )
1235 <<
" ---- ----- ------------------\n";
1238 for( i = set->
begin(); i != set->
end(); ++i )
1240 std::vector< std::string > ext;
1241 i->get_extensions( ext );
1242 str << std::setw( 6 ) << i->name() <<
" " << std::setw( w ) << std::left << i->description() <<
" "
1243 << ( i->have_reader() ?
" yes" :
" no" ) <<
" " << ( i->have_writer() ?
" yes" :
" no" ) <<
" ";
1244 for( std::vector< std::string >::iterator j = ext.begin(); j != ext.end(); ++j )
1263 set_contents =
intersect( set_contents, dead_entities );
1265 set_contents.
clear();
1267 if( set_contents.
empty() ) empty_sets.
insert( *i );
1274 std::vector< EntityHandle >::iterator j;
1275 for( i = ents_to_remove.
begin(); i != ents_to_remove.
end(); ++i )
1277 j = std::find( vect.begin(), vect.end(), *i );
1278 if( j != vect.end() ) vect.erase( j );
1284 if( s.empty() )
return s;
1286 size_t j = s.find(
'%' );
1287 if( j == std::string::npos )
return s;
1289 std::ostringstream st;
1290 st << s.substr( 0, j );
1294 while( ( i = s.find(
'%', j + 1 ) ) != std::string::npos )
1296 st << s.substr( j, i - j );
1300 st << s.substr( j + 1 );
1311 std::cout <<
" MPAS model has " << faces.
size() <<
" polygons\n";
1314 std::ifstream partfile;
1315 partfile.open( metis_partition_file.c_str() );
1317 std::vector< int > parts;
1318 parts.resize( faces.
size(), -1 );
1320 if( partfile.is_open() )
1322 while( getline( partfile, line ) )
1325 parts[i++] = atoi( line.c_str() );
1326 if( i > (
int)faces.
size() )
1328 std::cerr <<
" too many lines in partition file \n. bail out \n";
1334 std::vector< int >::iterator pmax = max_element( parts.begin(), parts.end() );
1335 std::vector< int >::iterator pmin = min_element( parts.begin(), parts.end() );
1338 std::cerr <<
" partition file is incomplete, *pmin is -1 !! \n";
1341 std::cout <<
" partitions range: " << *pmin <<
" " << *pmax <<
"\n";
1352 if( !tagged_sets.
empty() )
1359 int num_sets = *pmax + 1;
1362 std::cout <<
" problem reading parts; min is not 0 \n";
1365 for( i = 0; i < num_sets; i++ )
1369 tagged_sets.
insert( new_set );
1371 int* dum_ids =
new int[num_sets];
1372 for( i = 0; i < num_sets; i++ )
1378 std::vector< int > gids;
1379 int num_faces = (int)faces.
size();
1380 gids.resize( num_faces );
1383 for(
int j = 0; j < num_faces; j++ )
1387 int partition = parts[eid - 1];
1388 if( partition < 0 || partition >= num_sets )
1390 std::cout <<
" wrong partition number \n";