MOAB: Mesh Oriented datABase  (version 5.4.0)
parallel_hdf5_test.cpp
Go to the documentation of this file.
00001 #include "moab/Range.hpp"
00002 #include "TestUtil.hpp"
00003 
00004 #include "moab/Core.hpp"
00005 #include "moab/ParallelComm.hpp"
00006 #include "moab/Skinner.hpp"
00007 #include "MBTagConventions.hpp"
00008 #include "moab/CN.hpp"
00009 #include "MBParallelConventions.h"
00010 
00011 #include <iostream>
00012 #include <sstream>
00013 #include <algorithm>
00014 #include "moab_mpi.h"
00015 #include <unistd.h>
00016 #include <cfloat>
00017 #include <cstdio>
00018 #include <ctime>
00019 
00020 using namespace moab;
00021 
00022 #ifdef MESHDIR
00023 const char* InputFile    = STRINGIFY( MESHDIR ) "/ptest.cub";
00024 const char* InputMix     = STRINGIFY( MESHDIR ) "/io/mix.h5m";
00025 const char* InputOneSide = STRINGIFY( MESHDIR ) "/io/oneside.h5m";
00026 #else
00027 #error Specify MESHDIR to compile test
00028 #endif
00029 
00030 void load_and_partition( Interface& moab, const char* filename, bool print_debug = false );
00031 
00032 void save_and_load_on_root( Interface& moab, const char* tmp_filename );
00033 
00034 void check_identical_mesh( Interface& moab1, Interface& moab2 );
00035 
00036 void test_write_elements();
00037 void test_write_shared_sets();
00038 void test_var_length_parallel();
00039 
00040 void test_read_elements_common( bool by_rank, int intervals, bool print_time, const char* extra_opts = 0 );
00041 
00042 int ReadIntervals = 0;
00043 void test_read_elements()
00044 {
00045     test_read_elements_common( false, ReadIntervals, false );
00046 }
00047 void test_read_elements_by_rank()
00048 {
00049     test_read_elements_common( true, ReadIntervals, false );
00050 }
00051 void test_bcast_summary()
00052 {
00053     test_read_elements_common( false, ReadIntervals, false, "BCAST_SUMMARY=yes" );
00054 }
00055 void test_read_summary()
00056 {
00057     test_read_elements_common( false, ReadIntervals, false, "BCAST_SUMMARY=no" );
00058 }
00059 void test_read_time();
00060 
00061 void test_read_tags();
00062 void test_read_global_tags();
00063 void test_read_sets_common( const char* extra_opts = 0 );
00064 void test_read_sets()
00065 {
00066     test_read_sets_common();
00067 }
00068 void test_read_sets_bcast_dups()
00069 {
00070     test_read_sets_common( "BCAST_DUPLICATE_READS=yes" );
00071 }
00072 void test_read_sets_read_dups()
00073 {
00074     test_read_sets_common( "BCAST_DUPLICATE_READS=no" );
00075 }
00076 void test_read_bc_sets();
00077 
00078 void test_write_different_element_types();
00079 void test_write_different_tags();
00080 void test_write_polygons();
00081 void test_write_unbalanced();
00082 void test_write_dense_tags();
00083 void test_read_non_adjs_side();
00084 
00085 const char PARTITION_TAG[] = "PARTITION";
00086 
00087 bool KeepTmpFiles              = false;
00088 bool PauseOnStart              = false;
00089 bool HyperslabAppend           = false;
00090 const int DefaultReadIntervals = 2;
00091 int ReadDebugLevel             = 0;
00092 int WriteDebugLevel            = 0;
00093 int ReadBlocks                 = 1;
00094 
00095 enum Mode
00096 {
00097     READ_PART,
00098     READ_DELETE,
00099     BCAST_DELETE
00100 };
00101 const Mode DEFAULT_MODE    = READ_PART;
00102 const bool DEFAULT_BY_RANK = false;
00103 
00104 std::string get_read_options( bool by_rank = DEFAULT_BY_RANK, Mode mode = DEFAULT_MODE, const char* extra_opts = 0 );
00105 std::string get_read_options( const char* extra_opts )
00106 {
00107     return get_read_options( DEFAULT_BY_RANK, DEFAULT_MODE, extra_opts );
00108 }
00109 std::string get_read_options( bool by_rank, const char* extra_opts )
00110 {
00111     return get_read_options( by_rank, DEFAULT_MODE, extra_opts );
00112 }
00113 
00114 std::string get_read_options( bool by_rank, Mode mode, const char* extra_opts )
00115 {
00116     int numproc;
00117     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
00118 
00119     // do parallel read unless only one processor
00120     std::ostringstream str;
00121     if( numproc > 1 )
00122     {
00123         str << "PARALLEL=";
00124         switch( mode )
00125         {
00126             case READ_PART:
00127                 str << "READ_PART";
00128                 break;
00129             case READ_DELETE:
00130                 str << "READ_DELETE";
00131                 break;
00132             case BCAST_DELETE:
00133                 str << "BCAST_DELETE";
00134                 break;
00135         }
00136         str << ";PARTITION=" << PARTITION_TAG << ";";
00137         if( by_rank ) str << "PARTITION_BY_RANK;";
00138     }
00139 
00140     if( extra_opts ) str << extra_opts << ";";
00141 
00142     if( ReadDebugLevel ) str << "DEBUG_IO=" << ReadDebugLevel << ";";
00143 
00144     if( HyperslabAppend ) str << "HYPERSLAB_APPEND;HYPERSLAB_SELECT_LIMIT=2147483647";
00145 
00146     return str.str();
00147 }
00148 
00149 int main( int argc, char* argv[] )
00150 {
00151     int err = MPI_Init( &argc, &argv );
00152     CHECK( !err );
00153 
00154     for( int i = 1; i < argc; ++i )
00155     {
00156         if( !strcmp( argv[i], "-k" ) )
00157             KeepTmpFiles = true;
00158         else if( !strcmp( argv[i], "-p" ) )
00159             PauseOnStart = true;
00160         else if( !strcmp( argv[i], "-R" ) )
00161         {
00162             ++i;
00163             CHECK( i < argc );
00164             ReadIntervals = atoi( argv[i] );
00165             CHECK( ReadIntervals > 0 );
00166         }
00167         else if( !strcmp( argv[i], "-b" ) )
00168         {
00169             ++i;
00170             CHECK( i < argc );
00171             ReadBlocks = atoi( argv[i] );
00172             CHECK( ReadBlocks > 0 );
00173         }
00174         else if( !strcmp( argv[i], "-r" ) )
00175         {
00176             ++i;
00177             CHECK( i < argc );
00178             ReadDebugLevel = atoi( argv[i] );
00179             CHECK( ReadDebugLevel > 0 );
00180         }
00181         else if( !strcmp( argv[i], "-w" ) )
00182         {
00183             ++i;
00184             CHECK( i < argc );
00185             WriteDebugLevel = atoi( argv[i] );
00186             CHECK( WriteDebugLevel > 0 );
00187         }
00188         else if( !strcmp( argv[i], "-A" ) )
00189             HyperslabAppend = true;
00190         else
00191         {
00192             std::cerr << "Usage: " << argv[0]
00193                       << " [-k] [-p] [-R <intervals>] [-r <level>] [-w <level>] [-b <blocks>]  [-A]" << std::endl;
00194             return 1;
00195         }
00196     }
00197 
00198     if( PauseOnStart )
00199     {
00200         int rank;
00201         MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00202         printf( "Rank %2d PID %lu\n", rank, (unsigned long)getpid() );
00203         sleep( 30 );
00204     }
00205 
00206     int result = 0;
00207     if( ReadIntervals )
00208     {
00209         result = RUN_TEST( test_read_time );
00210     }
00211     else
00212     {
00213         ReadIntervals = DefaultReadIntervals;
00214         result += RUN_TEST( test_write_elements );
00215         MPI_Barrier( MPI_COMM_WORLD );
00216         result += RUN_TEST( test_write_shared_sets );
00217         MPI_Barrier( MPI_COMM_WORLD );
00218         result += RUN_TEST( test_var_length_parallel );
00219         MPI_Barrier( MPI_COMM_WORLD );
00220         result += RUN_TEST( test_read_elements );
00221         MPI_Barrier( MPI_COMM_WORLD );
00222         result += RUN_TEST( test_read_elements_by_rank );
00223         MPI_Barrier( MPI_COMM_WORLD );
00224         result += RUN_TEST( test_read_tags );
00225         MPI_Barrier( MPI_COMM_WORLD );
00226         result += RUN_TEST( test_read_global_tags );
00227         MPI_Barrier( MPI_COMM_WORLD );
00228         result += RUN_TEST( test_read_sets );
00229         MPI_Barrier( MPI_COMM_WORLD );
00230         result += RUN_TEST( test_read_sets_bcast_dups );
00231         MPI_Barrier( MPI_COMM_WORLD );
00232         result += RUN_TEST( test_read_sets_read_dups );
00233         MPI_Barrier( MPI_COMM_WORLD );
00234         result += RUN_TEST( test_read_bc_sets );
00235         MPI_Barrier( MPI_COMM_WORLD );
00236         result += RUN_TEST( test_write_different_element_types );
00237         MPI_Barrier( MPI_COMM_WORLD );
00238         result += RUN_TEST( test_write_different_tags );
00239         MPI_Barrier( MPI_COMM_WORLD );
00240         result += RUN_TEST( test_write_polygons );
00241         MPI_Barrier( MPI_COMM_WORLD );
00242         result += RUN_TEST( test_write_unbalanced );
00243         MPI_Barrier( MPI_COMM_WORLD );
00244         result += RUN_TEST( test_write_dense_tags );
00245         MPI_Barrier( MPI_COMM_WORLD );
00246         result += RUN_TEST( test_read_non_adjs_side );
00247         MPI_Barrier( MPI_COMM_WORLD );
00248     }
00249 
00250     MPI_Finalize();
00251     return result;
00252 }
00253 
00254 /* Assume geometric topology sets correspond to interface sets
00255  * in that the entities contained inclusively in a geometric
00256  * topology set must be shared by the same set of processors.
00257  * As we partition based on geometric volumes, this assumption
00258  * should aways be true.  Print for each geometric topology set
00259  * the list of processors it is shared with.
00260  */
00261 void print_partitioned_entities( Interface& moab, bool list_non_shared = false )
00262 {
00263     ErrorCode rval;
00264     int size, rank;
00265     std::vector< int > ent_procs( MAX_SHARING_PROCS ), tmp_ent_procs( MAX_SHARING_PROCS );
00266     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00267     MPI_Comm_size( MPI_COMM_WORLD, &size );
00268 
00269     // expect shared entities to correspond to geometric sets
00270 
00271     // get tags for parallel data
00272     Tag sharedp_tag, sharedps_tag, sharedh_tag, sharedhs_tag, pstatus_tag;
00273     rval = moab.tag_get_handle( PARALLEL_SHARED_PROC_TAG_NAME, 1, MB_TYPE_INTEGER, sharedp_tag );CHECK_ERR( rval );
00274     rval = moab.tag_get_handle( PARALLEL_SHARED_PROCS_TAG_NAME, MAX_SHARING_PROCS, MB_TYPE_INTEGER, sharedps_tag );CHECK_ERR( rval );
00275     rval = moab.tag_get_handle( PARALLEL_SHARED_HANDLE_TAG_NAME, 1, MB_TYPE_HANDLE, sharedh_tag );CHECK_ERR( rval );
00276     rval = moab.tag_get_handle( PARALLEL_SHARED_HANDLES_TAG_NAME, MAX_SHARING_PROCS, MB_TYPE_HANDLE, sharedhs_tag );CHECK_ERR( rval );
00277     rval = moab.tag_get_handle( PARALLEL_STATUS_TAG_NAME, 1, MB_TYPE_OPAQUE, pstatus_tag );CHECK_ERR( rval );
00278 
00279     // for each geometric entity, check which processor we are sharing
00280     // entities with
00281     Tag geom_tag, id_tag;
00282     rval = moab.tag_get_handle( GEOM_DIMENSION_TAG_NAME, 1, MB_TYPE_INTEGER, geom_tag );CHECK_ERR( rval );
00283     id_tag                     = moab.globalId_tag();
00284     const char* topo_names_s[] = { "Vertex", "Curve", "Surface", "Volume" };
00285     //  const char* topo_names_p[] = { "Vertices", "Curves", "Surfaces", "Volumes" };
00286     std::ostringstream buffer;  // buffer output in an attempt to prevent lines from different
00287                                 // processsors being mixed up.
00288     for( int t = 0; t < 4; ++t )
00289     {
00290         Range geom;
00291         int dim         = t;
00292         const void* ptr = &dim;
00293         rval            = moab.get_entities_by_type_and_tag( 0, MBENTITYSET, &geom_tag, &ptr, 1, geom );CHECK_ERR( rval );
00294 
00295         // for each geometric entity of dimension 't'
00296         for( Range::const_iterator i = geom.begin(); i != geom.end(); ++i )
00297         {
00298             EntityHandle set = *i;
00299             int id;
00300             rval = moab.tag_get_data( id_tag, &set, 1, &id );CHECK_ERR( rval );
00301 
00302             buffer.clear();
00303 
00304             // get entities contained in this set but not its children
00305             Range entities, tmp_entities, children, diff;
00306             rval = moab.get_entities_by_handle( set, entities );CHECK_ERR( rval );
00307             rval = moab.get_child_meshsets( set, children );CHECK_ERR( rval );
00308             for( Range::const_iterator j = children.begin(); j != children.end(); ++j )
00309             {
00310                 tmp_entities.clear();
00311                 rval = moab.get_entities_by_handle( *j, tmp_entities );CHECK_ERR( rval );
00312                 diff = subtract( entities, tmp_entities );
00313                 entities.swap( diff );
00314             }
00315 
00316             // for each entity, check owning processors
00317             std::vector< char > status_flags( entities.size(), 0 );
00318             std::vector< int > shared_procs( entities.size(), 0 );
00319             rval = moab.tag_get_data( pstatus_tag, entities, &status_flags[0] );
00320             if( MB_TAG_NOT_FOUND == rval )
00321             {
00322                 // keep default values of zero (not shared)
00323             }
00324             CHECK_ERR( rval );
00325             unsigned num_shared = 0, num_owned = 0;
00326             for( size_t j = 0; j < status_flags.size(); ++j )
00327             {
00328                 num_shared += !!( status_flags[j] & PSTATUS_SHARED );
00329                 num_owned += !( status_flags[j] & PSTATUS_NOT_OWNED );
00330             }
00331 
00332             if( !num_shared )
00333             {
00334                 if( list_non_shared )
00335                     buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00336                            << "not shared" << std::endl;
00337             }
00338             else if( num_shared != entities.size() )
00339             {
00340                 buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00341                        << "ERROR: " << num_shared << " of " << entities.size() << " entities marked as 'shared'"
00342                        << std::endl;
00343             }
00344             else if( num_owned && num_owned != entities.size() )
00345             {
00346                 buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00347                        << "ERROR: " << num_owned << " of " << entities.size() << " entities owned by this processor"
00348                        << std::endl;
00349             }
00350             else
00351             {
00352                 rval = moab.tag_get_data( sharedp_tag, entities, &shared_procs[0] );CHECK_ERR( rval );
00353                 int proc       = shared_procs[0];
00354                 bool all_match = true;
00355                 for( size_t j = 1; j < shared_procs.size(); ++j )
00356                     if( shared_procs[j] != proc ) all_match = false;
00357                 if( !all_match )
00358                 {
00359                     buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00360                            << "ERROR: processsor IDs do not match!" << std::endl;
00361                 }
00362                 else if( proc != -1 )
00363                 {
00364                     buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00365                            << "shared with processor " << proc;
00366                     if( num_owned ) buffer << " (owned by this processor)";
00367                     buffer << std::endl;
00368                 }
00369                 else if( entities.empty() )
00370                 {
00371                     buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00372                            << "ERROR: no entities!" << std::endl;
00373                 }
00374                 else
00375                 {
00376                     Range::const_iterator j = entities.begin();
00377                     rval                    = moab.tag_get_data( sharedps_tag, &*j, 1, &ent_procs[0] );CHECK_ERR( rval );
00378                     for( ++j; j != entities.end(); ++j )
00379                     {
00380                         rval = moab.tag_get_data( sharedps_tag, &*j, 1, &tmp_ent_procs[0] );CHECK_ERR( rval );
00381                         if( ent_procs != tmp_ent_procs ) all_match = false;
00382                     }
00383                     if( !all_match )
00384                     {
00385                         buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00386                                << "ERROR: processsor IDs do not match!" << std::endl;
00387                     }
00388                     else
00389                     {
00390                         buffer << rank << ":\t" << topo_names_s[t] << " " << id << ":\t"
00391                                << "processors ";
00392                         for( int k = 0; k < MAX_SHARING_PROCS; ++k )
00393                             if( ent_procs[k] != -1 ) buffer << ent_procs[k] << ", ";
00394                         if( num_owned ) buffer << " (owned by this processor)";
00395                         buffer << std::endl;
00396                     }
00397                 }
00398             }
00399         }
00400     }
00401     for( int i = 0; i < size; ++i )
00402     {
00403         MPI_Barrier( MPI_COMM_WORLD );
00404         if( i == rank )
00405         {
00406             std::cout << buffer.str();
00407             std::cout.flush();
00408         }
00409     }
00410 }
00411 
00412 void load_and_partition( Interface& moab, const char* filename, bool print )
00413 {
00414     ErrorCode rval;
00415 
00416     rval = moab.load_file( filename, 0,
00417                            "PARALLEL=READ_DELETE;"
00418                            "PARTITION=GEOM_DIMENSION;PARTITION_VAL=3;"
00419                            "PARTITION_DISTRIBUTE;"
00420                            "PARALLEL_RESOLVE_SHARED_ENTS" );
00421 
00422     if( print ) print_partitioned_entities( moab );
00423 
00424     CHECK_ERR( rval );
00425 }
00426 
00427 void save_and_load_on_root( Interface& moab, const char* tmp_filename )
00428 {
00429     ErrorCode rval;
00430     int procnum;
00431     MPI_Comm_rank( MPI_COMM_WORLD, &procnum );
00432 
00433     const char* opt = "PARALLEL=WRITE_PART";
00434     std::string str;
00435     if( WriteDebugLevel )
00436     {
00437         std::ostringstream s;
00438         s << opt << ";DEBUG_IO=" << WriteDebugLevel;
00439         str = s.str();
00440         opt = str.c_str();
00441     }
00442     rval = moab.write_file( tmp_filename, 0, opt );
00443     if( MB_SUCCESS != rval )
00444     {
00445         std::cerr << "Parallel write failed on processor " << procnum << std::endl;
00446         if( procnum == 0 && !KeepTmpFiles ) remove( tmp_filename );CHECK_ERR( rval );
00447     }
00448 
00449     if( procnum == 0 && KeepTmpFiles ) std::cout << "Wrote file: \"" << tmp_filename << "\"\n";
00450 
00451     // All created pcomm objects should be retrieved (with the pcomm tag) and
00452     // deleted at this time. Otherwise, the memory used by them will be leaked
00453     // as the pcomm tag will be deleted by moab.delete_mesh() below.
00454     std::vector< ParallelComm* > pc_list;
00455     ParallelComm::get_all_pcomm( &moab, pc_list );
00456     for( std::vector< ParallelComm* >::iterator vit = pc_list.begin(); vit != pc_list.end(); ++vit )
00457         delete *vit;
00458 
00459     moab.delete_mesh();
00460     std::vector< Tag > tags;
00461     rval = moab.tag_get_tags( tags );CHECK_ERR( rval );
00462     for( size_t i = 0; i < tags.size(); ++i )
00463     {
00464         rval = moab.tag_delete( tags[i] );CHECK_ERR( rval );
00465     }
00466 
00467     if( procnum == 0 )
00468     {
00469         rval = moab.load_file( tmp_filename );
00470         if( !KeepTmpFiles ) remove( tmp_filename );CHECK_ERR( rval );
00471     }
00472 }
00473 
00474 void count_owned_entities( Interface& moab, int counts[MBENTITYSET] )
00475 {
00476     ErrorCode rval;
00477     ParallelComm* pcomm = ParallelComm::get_pcomm( &moab, 0 );
00478     CHECK( 0 != pcomm );
00479     std::fill( counts, counts + MBENTITYSET, 0u );
00480 
00481     for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t )
00482     {
00483         Range range;
00484         rval = moab.get_entities_by_type( 0, t, range );CHECK_ERR( rval );
00485         if( !range.empty() ) rval = pcomm->filter_pstatus( range, PSTATUS_NOT_OWNED, PSTATUS_NOT );CHECK_ERR( rval );
00486         counts[t] = range.size();
00487     }
00488 }
00489 
00490 void check_identical_mesh( Interface& mb1, Interface& mb2 )
00491 {
00492     ErrorCode rval;
00493     std::map< EntityHandle, EntityHandle > entmap;
00494 
00495     // match vertices by coordinate
00496     Range r1, r2;
00497     Range::iterator i1, i2;
00498     rval = mb1.get_entities_by_type( 0, MBVERTEX, r1 );CHECK_ERR( rval );
00499     rval = mb2.get_entities_by_type( 0, MBVERTEX, r2 );CHECK_ERR( rval );
00500     CHECK_EQUAL( r1.size(), r2.size() );
00501     for( i1 = r1.begin(); i1 != r1.end(); ++i1 )
00502     {
00503         double coords1[3];
00504         rval = mb1.get_coords( &*i1, 1, coords1 );CHECK_ERR( rval );
00505         for( i2 = r2.begin(); i2 != r2.end(); ++i2 )
00506         {
00507             double coords2[3];
00508             rval = mb2.get_coords( &*i2, 1, coords2 );CHECK_ERR( rval );
00509             coords2[0] -= coords1[0];
00510             coords2[1] -= coords1[1];
00511             coords2[2] -= coords1[2];
00512             double lensqr = coords2[0] * coords2[0] + coords2[1] * coords2[1] + coords2[2] * coords2[2];
00513             if( lensqr < 1e-12 ) break;
00514         }
00515         CHECK( i2 != r2.end() );
00516         entmap[*i2] = *i1;
00517         r2.erase( i2 );
00518     }
00519 
00520     // match element connectivity
00521     std::vector< EntityHandle > conn1, conn2;
00522     for( EntityType t = MBEDGE; t < MBENTITYSET; ++t )
00523     {
00524         r1.clear();
00525         rval = mb1.get_entities_by_type( 0, t, r1 );CHECK_ERR( rval );
00526         r2.clear();
00527         rval = mb2.get_entities_by_type( 0, t, r2 );CHECK_ERR( rval );
00528         CHECK_EQUAL( r1.size(), r2.size() );
00529 
00530         for( i1 = r1.begin(); i1 != r1.end(); ++i1 )
00531         {
00532             conn1.clear();
00533             rval = mb1.get_connectivity( &*i1, 1, conn1 );CHECK_ERR( rval );
00534             for( i2 = r2.begin(); i2 != r2.end(); ++i2 )
00535             {
00536                 conn2.clear();
00537                 rval = mb2.get_connectivity( &*i2, 1, conn2 );CHECK_ERR( rval );
00538                 if( conn1.size() != conn2.size() ) continue;
00539                 for( std::vector< EntityHandle >::iterator j = conn2.begin(); j != conn2.end(); ++j )
00540                     *j = entmap[*j];
00541                 if( conn1 == conn2 ) break;
00542             }
00543 
00544             CHECK( i2 != r2.end() );
00545             entmap[*i2] = *i1;
00546             r2.erase( i2 );
00547         }
00548     }
00549 }
00550 
00551 void test_write_elements()
00552 {
00553     int proc_counts[MBENTITYSET], all_counts[MBENTITYSET], file_counts[MBENTITYSET];
00554     int err, rank;
00555     ErrorCode rval;
00556     err = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00557     CHECK( !err );
00558 
00559     // load and partition a .cub file
00560     Core moab_instance;
00561     Interface& moab = moab_instance;
00562     load_and_partition( moab, InputFile, false );
00563 
00564     // count number of owned entities of each type and sum over all procs
00565     count_owned_entities( moab, proc_counts );
00566     std::fill( all_counts, all_counts + MBENTITYSET, 0u );
00567     err = MPI_Allreduce( proc_counts, all_counts, MBENTITYSET, MPI_INT, MPI_SUM, MPI_COMM_WORLD );
00568     CHECK( !err );
00569 
00570     // do parallel write and on root proc do serial read of written file
00571     save_and_load_on_root( moab, "test_write_elements.h5m" );
00572     if( rank == 0 )
00573     {
00574         for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t )
00575         {
00576             rval = moab.get_number_entities_by_type( 0, t, file_counts[t] );CHECK_ERR( rval );
00577         }
00578     }
00579 
00580     // check that sum of owned entities equals number of entities from serial read
00581 
00582     err = MPI_Bcast( file_counts, MBENTITYSET, MPI_INT, 0, MPI_COMM_WORLD );
00583     CHECK( !err );
00584 
00585     bool all_equal = true;
00586     for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t )
00587         if( file_counts[t] != all_counts[t] ) all_equal = false;
00588 
00589     if( rank == 0 && !all_equal )
00590     {
00591         std::cerr << "Type\tPartnd\tWritten" << std::endl;
00592         for( EntityType t = MBVERTEX; t < MBENTITYSET; ++t )
00593             std::cerr << CN::EntityTypeName( t ) << '\t' << all_counts[t] << '\t' << file_counts[t] << std::endl;
00594     }
00595 
00596     CHECK( all_equal );
00597 
00598     // on root processor, do serial read of original .cub file and compare
00599 
00600     if( rank == 0 )
00601     {
00602         Core moab2;
00603         rval = moab2.load_file( InputFile );CHECK_ERR( rval );
00604         check_identical_mesh( moab, moab2 );
00605     }
00606 }
00607 
00608 bool check_sets_sizes( Interface& mb1, EntityHandle set1, Interface& mb2, EntityHandle set2 )
00609 {
00610     ErrorCode rval;
00611     bool result = true;
00612     for( EntityType t = MBVERTEX; t < MBMAXTYPE; ++t )
00613     {
00614         int count1, count2;
00615         rval = mb1.get_number_entities_by_type( set1, t, count1 );CHECK_ERR( rval );
00616         rval = mb2.get_number_entities_by_type( set2, t, count2 );CHECK_ERR( rval );
00617         if( count1 != count2 )
00618         {
00619             std::cerr << "Sets differ in number of " << CN::EntityTypeName( t ) << " : " << count1 << " vs. " << count2
00620                       << std::endl;
00621             result = false;
00622         }
00623     }
00624     return result;
00625 }
00626 
00627 void test_write_shared_sets()
00628 {
00629     int err, rank, size;
00630     ErrorCode rval;
00631     err = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00632     CHECK( !err );
00633     err = MPI_Comm_size( MPI_COMM_WORLD, &size );
00634     CHECK( !err );
00635 
00636     Core moab_instance;
00637     Interface& moab = moab_instance;
00638     load_and_partition( moab, InputFile );
00639     save_and_load_on_root( moab, "test_write_shared_sets.h5m" );
00640 
00641     if( rank != 0 ) return;
00642 
00643     Core moab2_instance;
00644     Interface& moab2 = moab2_instance;
00645     rval             = moab2.load_file( InputFile );CHECK_ERR( rval );
00646 
00647     Tag mattag1, mattag2;
00648     rval = moab.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mattag1 );CHECK_ERR( rval );
00649     rval = moab2.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, mattag2 );CHECK_ERR( rval );
00650 
00651     Range matsets;
00652     rval = moab2.get_entities_by_type_and_tag( 0, MBENTITYSET, &mattag2, 0, 1, matsets );CHECK_ERR( rval );
00653     for( Range::iterator i = matsets.begin(); i != matsets.end(); ++i )
00654     {
00655         int block_id;
00656         rval = moab2.tag_get_data( mattag2, &*i, 1, &block_id );CHECK_ERR( rval );
00657 
00658         Range tmpents;
00659         void* tagdata[] = { &block_id };
00660         rval            = moab.get_entities_by_type_and_tag( 0, MBENTITYSET, &mattag1, tagdata, 1, tmpents );
00661         if( tmpents.size() != 1 ) std::cerr << tmpents.size() << " sets with material set id " << block_id << std::endl;
00662         CHECK_EQUAL( (int)tmpents.size(), 1 );
00663 
00664         CHECK( check_sets_sizes( moab2, *i, moab, tmpents.front() ) );
00665     }
00666 }
00667 
00668 void test_var_length_parallel()
00669 {
00670     Range::const_iterator i;
00671     ErrorCode rval;
00672     Core moab;
00673     Interface& mb = moab;
00674     Range verts;
00675     Tag vartag;
00676     const char* filename = "var-len-para.h5m";
00677     const char* tagname  = "ParVar";
00678 
00679     // If this tag doesn't exist, writer will fail
00680     Tag junk_tag;
00681     mb.tag_get_handle( PARALLEL_GID_TAG_NAME, 1, MB_TYPE_INTEGER, junk_tag, MB_TAG_DENSE | MB_TAG_EXCL );
00682 
00683     int numproc, rank;
00684     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
00685     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00686 
00687     // Create N+1 vertices on each processor, where N is the rank
00688     std::vector< double > coords( 3 * rank + 3, (double)rank );
00689     rval = mb.create_vertices( &coords[0], rank + 1, verts );CHECK_ERR( rval );
00690 
00691     // Create a var-len tag
00692     rval = mb.tag_get_handle( tagname, 0, MB_TYPE_INTEGER, vartag, MB_TAG_DENSE | MB_TAG_VARLEN | MB_TAG_EXCL );CHECK_ERR( rval );
00693 
00694     // Write data on each vertex:
00695     // { n, rank, rank+1, ..., rank+n-1 } where n >= 1
00696     std::vector< int > data;
00697     rval = MB_SUCCESS;
00698     for( i = verts.begin(); i != verts.end(); ++i )
00699     {
00700         EntityHandle h = *i;
00701         const int n    = h % 7 + 1;
00702         data.resize( n + 1 );
00703         data[0] = n;
00704         for( int j = 0; j < n; ++j )
00705             data[j + 1] = rank + j;
00706         const int s          = ( n + 1 );
00707         const void* ptrarr[] = { &data[0] };
00708         ErrorCode tmperr     = mb.tag_set_by_ptr( vartag, &h, 1, ptrarr, &s );
00709         if( MB_SUCCESS != tmperr ) rval = tmperr;
00710     }
00711     CHECK_ERR( rval );
00712 
00713     // Write file
00714     const char* opt = "PARALLEL=WRITE_PART";
00715     std::string str;
00716     if( WriteDebugLevel )
00717     {
00718         std::ostringstream s;
00719         s << opt << ";DEBUG_IO=" << WriteDebugLevel;
00720         str = s.str();
00721         opt = str.c_str();
00722     }
00723     rval = mb.write_file( filename, "MOAB", opt );CHECK_ERR( rval );
00724 
00725     // Read file.  We only reset and re-read the file on the
00726     // root processor.  All other processors keep the pre-write
00727     // mesh.  This allows many of the tests to be run on all
00728     // processors.  Running the tests on the pre-write mesh on
00729     // non-root processors allows us to verify that any problems
00730     // are due to the file API rather than some other bug.
00731     ErrorCode rval2 = rval = MB_SUCCESS;
00732     if( !rank )
00733     {
00734         moab.~Core();
00735         new( &moab ) Core;
00736         rval = mb.load_mesh( filename );
00737         if( !KeepTmpFiles ) remove( filename );
00738         rval2 = mb.tag_get_handle( tagname, 0, MB_TYPE_INTEGER, vartag );
00739     }
00740     CHECK_ERR( rval );CHECK_ERR( rval2 );
00741 
00742     // Check that tag is correct
00743     int tag_size;
00744     rval = mb.tag_get_length( vartag, tag_size );
00745     CHECK_EQUAL( MB_VARIABLE_DATA_LENGTH, rval );
00746     TagType storage;
00747     rval = mb.tag_get_type( vartag, storage );CHECK_ERR( rval );
00748     CHECK_EQUAL( MB_TAG_DENSE, storage );
00749     DataType type;
00750     rval = mb.tag_get_data_type( vartag, type );CHECK_ERR( rval );
00751     CHECK_EQUAL( MB_TYPE_INTEGER, type );
00752 
00753     // get vertices
00754     verts.clear();
00755     rval = mb.get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
00756 
00757     // Check consistency of tag data on each vertex
00758     // and count the number of vertices for each rank.
00759     std::vector< int > vtx_counts( numproc, 0 );
00760     for( i = verts.begin(); i != verts.end(); ++i )
00761     {
00762         EntityHandle h        = *i;
00763         int size              = -1;
00764         const void* ptrarr[1] = { 0 };
00765         rval                  = mb.tag_get_by_ptr( vartag, &h, 1, ptrarr, &size );CHECK_ERR( rval );
00766         const int* tag_data = reinterpret_cast< const int* >( ptrarr[0] );
00767         CHECK( size >= 2 );
00768         CHECK( NULL != tag_data );
00769         CHECK_EQUAL( size - 1, tag_data[0] );
00770         CHECK( tag_data[1] >= 0 && tag_data[1] < numproc );
00771         ++vtx_counts[tag_data[1]];
00772         for( int j = 1; j < size - 1; ++j )
00773             CHECK_EQUAL( tag_data[1] + j, tag_data[1 + j] );
00774     }
00775 
00776     // Check number of vertices for each rank
00777     for( int j = 0; j < numproc; ++j )
00778     {
00779         // Only root should have data for other processors.
00780         if( rank == 0 || rank == j )
00781             CHECK_EQUAL( j + 1, vtx_counts[j] );
00782         else
00783             CHECK_EQUAL( 0, vtx_counts[j] );
00784     }
00785 }
00786 
00787 // create row of cubes of mesh
00788 void create_input_file( const char* file_name,
00789                         int intervals,
00790                         int num_cpu,
00791                         int blocks_per_cpu              = 1,
00792                         const char* ijk_vert_tag_name   = 0,
00793                         const char* ij_set_tag_name     = 0,
00794                         const char* global_tag_name     = 0,
00795                         const int* global_mesh_value    = 0,
00796                         const int* global_default_value = 0,
00797                         bool create_bcsets              = false )
00798 {
00799     Core moab;
00800     Interface& mb = moab;
00801     ErrorCode rval;
00802 
00803     Tag ijk_vert_tag = 0, ij_set_tag = 0, global_tag = 0;
00804     if( ijk_vert_tag_name )
00805     {
00806         rval = mb.tag_get_handle( ijk_vert_tag_name, 3, MB_TYPE_INTEGER, ijk_vert_tag, MB_TAG_EXCL | MB_TAG_DENSE );CHECK_ERR( rval );
00807     }
00808     if( ij_set_tag_name )
00809     {
00810         rval = mb.tag_get_handle( ij_set_tag_name, 2, MB_TYPE_INTEGER, ij_set_tag, MB_TAG_SPARSE | MB_TAG_EXCL );CHECK_ERR( rval );
00811     }
00812     if( global_tag_name )
00813     {
00814         rval = mb.tag_get_handle( global_tag_name, 1, MB_TYPE_INTEGER, global_tag, MB_TAG_DENSE | MB_TAG_EXCL,
00815                                   global_default_value );CHECK_ERR( rval );
00816         if( global_mesh_value )
00817         {
00818             EntityHandle root = 0;
00819             rval              = mb.tag_set_data( global_tag, &root, 1, global_mesh_value );CHECK_ERR( rval );
00820         }
00821     }
00822 
00823     const int num_blk = num_cpu * blocks_per_cpu;
00824     int iv = intervals + 1, ii = num_blk * intervals + 1;
00825     std::vector< EntityHandle > verts( iv * iv * ii );
00826     int idx = 0;
00827     for( int i = 0; i < ii; ++i )
00828     {
00829         for( int j = 0; j < iv; ++j )
00830         {
00831             int start = idx;
00832             for( int k = 0; k < iv; ++k )
00833             {
00834                 const double coords[3] = { static_cast< double >( i ), static_cast< double >( j ),
00835                                            static_cast< double >( k ) };
00836                 rval                   = mb.create_vertex( coords, verts[idx] );CHECK_ERR( rval );
00837                 if( ijk_vert_tag )
00838                 {
00839                     int vals[] = { i, j, k };
00840                     rval       = mb.tag_set_data( ijk_vert_tag, &verts[idx], 1, vals );CHECK_ERR( rval );
00841                 }
00842                 ++idx;
00843             }
00844 
00845             if( ij_set_tag )
00846             {
00847                 EntityHandle set;
00848                 rval = mb.create_meshset( MESHSET_SET, set );CHECK_ERR( rval );
00849                 rval = mb.add_entities( set, &verts[start], idx - start );CHECK_ERR( rval );
00850                 int vals[] = { i, j };
00851                 rval       = mb.tag_set_data( ij_set_tag, &set, 1, vals );CHECK_ERR( rval );
00852             }
00853         }
00854     }
00855 
00856     const int eb = intervals * intervals * intervals;
00857     std::vector< EntityHandle > elems( num_blk * eb );
00858     idx = 0;
00859     for( int c = 0; c < num_blk; ++c )
00860     {
00861         for( int i = c * intervals; i < ( c + 1 ) * intervals; ++i )
00862         {
00863             for( int j = 0; j < intervals; ++j )
00864             {
00865                 for( int k = 0; k < intervals; ++k )
00866                 {
00867                     EntityHandle conn[8] = { verts[iv * ( iv * i + j ) + k],
00868                                              verts[iv * ( iv * ( i + 1 ) + j ) + k],
00869                                              verts[iv * ( iv * ( i + 1 ) + j + 1 ) + k],
00870                                              verts[iv * ( iv * i + j + 1 ) + k],
00871                                              verts[iv * ( iv * i + j ) + k + 1],
00872                                              verts[iv * ( iv * ( i + 1 ) + j ) + k + 1],
00873                                              verts[iv * ( iv * ( i + 1 ) + j + 1 ) + k + 1],
00874                                              verts[iv * ( iv * i + j + 1 ) + k + 1] };
00875 
00876                     rval = mb.create_element( MBHEX, conn, 8, elems[idx++] );CHECK_ERR( rval );
00877                 }
00878             }
00879         }
00880     }
00881 
00882     Tag part_tag;
00883     rval = mb.tag_get_handle( PARTITION_TAG, 1, MB_TYPE_INTEGER, part_tag, MB_TAG_SPARSE | MB_TAG_EXCL );CHECK_ERR( rval );
00884 
00885     std::vector< EntityHandle > parts( num_cpu );
00886     for( int i = 0; i < num_cpu; ++i )
00887     {
00888         rval = mb.create_meshset( MESHSET_SET, parts[i] );CHECK_ERR( rval );
00889         for( int j = 0; j < blocks_per_cpu; ++j )
00890         {
00891             rval = mb.add_entities( parts[i], &elems[( num_cpu * j + i ) * eb], eb );CHECK_ERR( rval );
00892         }
00893         rval = mb.tag_set_data( part_tag, &parts[i], 1, &i );CHECK_ERR( rval );
00894     }
00895 
00896     if( create_bcsets )
00897     {
00898         // neumann set
00899         Range skin_ents;
00900         rval = Skinner( &mb ).find_skin( 0, &elems[0], elems.size(), false, skin_ents );CHECK_ERR( rval );
00901         EntityHandle bcset;
00902         rval = mb.create_meshset( MESHSET_SET, bcset );CHECK_ERR( rval );
00903         Tag bcset_tag;
00904         rval = mb.tag_get_handle( NEUMANN_SET_TAG_NAME, 1, MB_TYPE_INTEGER, bcset_tag, MB_TAG_SPARSE | MB_TAG_CREAT );CHECK_ERR( rval );
00905         int dum = 100;
00906         rval    = mb.tag_set_data( bcset_tag, &bcset, 1, &dum );CHECK_ERR( rval );
00907         rval = mb.add_entities( bcset, skin_ents );CHECK_ERR( rval );
00908 
00909         // dirichlet set
00910         rval = mb.create_meshset( MESHSET_SET, bcset );CHECK_ERR( rval );
00911         rval = mb.tag_get_handle( DIRICHLET_SET_TAG_NAME, 1, MB_TYPE_INTEGER, bcset_tag, MB_TAG_SPARSE | MB_TAG_CREAT );CHECK_ERR( rval );
00912         dum  = 200;
00913         rval = mb.tag_set_data( bcset_tag, &bcset, 1, &dum );CHECK_ERR( rval );
00914         Range nodes;
00915         rval = mb.get_adjacencies( skin_ents, 0, false, nodes, Interface::UNION );CHECK_ERR( rval );
00916         rval = mb.add_entities( bcset, nodes );CHECK_ERR( rval );
00917 
00918         // material set
00919         rval = mb.create_meshset( MESHSET_SET, bcset );CHECK_ERR( rval );
00920         rval = mb.tag_get_handle( MATERIAL_SET_TAG_NAME, 1, MB_TYPE_INTEGER, bcset_tag, MB_TAG_SPARSE | MB_TAG_CREAT );CHECK_ERR( rval );
00921         dum  = 300;
00922         rval = mb.tag_set_data( bcset_tag, &bcset, 1, &dum );CHECK_ERR( rval );
00923         rval = mb.add_entities( bcset, &elems[0], elems.size() );CHECK_ERR( rval );
00924     }
00925 
00926     rval = mb.write_file( file_name, "MOAB" );CHECK_ERR( rval );
00927 }
00928 
00929 void test_read_elements_common( bool by_rank, int intervals, bool /* print_time */, const char* extra_opts )
00930 {
00931     const char* file_name = by_rank ? "test_read_rank.h5m" : "test_read.h5m";
00932     int numproc, rank;
00933     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
00934     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00935     Core moab;
00936     Interface& mb = moab;
00937     ErrorCode rval;
00938 
00939     // if root processor, create hdf5 file for use in testing
00940     if( 0 == rank ) create_input_file( file_name, intervals, numproc );
00941     MPI_Barrier( MPI_COMM_WORLD );  // make sure root has completed writing the file
00942 
00943     // do parallel read unless only one processor
00944     std::string opt = get_read_options( by_rank, extra_opts );
00945     rval            = mb.load_file( file_name, 0, opt.c_str() );
00946 
00947     MPI_Barrier( MPI_COMM_WORLD );  // make sure all procs complete before removing file
00948     if( 0 == rank && !KeepTmpFiles ) remove( file_name );CHECK_ERR( rval );
00949 
00950     Tag part_tag;
00951     rval = mb.tag_get_handle( PARTITION_TAG, 1, MB_TYPE_INTEGER, part_tag );CHECK_ERR( rval );
00952 
00953     Range parts;
00954     rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &part_tag, 0, 1, parts );CHECK_ERR( rval );
00955     CHECK_EQUAL( 1, (int)parts.size() );
00956     EntityHandle part = parts.front();
00957     int id;
00958     rval = mb.tag_get_data( part_tag, &part, 1, &id );CHECK_ERR( rval );
00959     if( by_rank )
00960     {
00961         CHECK_EQUAL( rank, id );
00962     }
00963 
00964     // check that all of the elements in the mesh are in the part
00965     int npart, nall;
00966     rval = mb.get_number_entities_by_dimension( part, 3, npart );CHECK_ERR( rval );
00967     rval = mb.get_number_entities_by_dimension( 0, 3, nall );CHECK_ERR( rval );
00968     CHECK_EQUAL( npart, nall );
00969 
00970     // check that we have the correct vertices
00971     const double x_min = intervals * rank;
00972     const double x_max = intervals * ( rank + 1 );
00973     Range verts;
00974     rval = mb.get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
00975     std::vector< double > coords( verts.size() );
00976     rval = mb.get_coords( verts, &coords[0], 0, 0 );CHECK_ERR( rval );
00977     const double act_x_min = *std::min_element( coords.begin(), coords.end() );
00978     const double act_x_max = *std::max_element( coords.begin(), coords.end() );
00979     CHECK_REAL_EQUAL( x_min, act_x_min, DBL_EPSILON );
00980     CHECK_REAL_EQUAL( x_max, act_x_max, DBL_EPSILON );
00981 }
00982 
00983 void test_read_time()
00984 {
00985     const char file_name[] = "read_time.h5m";
00986     int numproc, rank;
00987     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
00988     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
00989     ErrorCode rval;
00990 
00991     // if root processor, create hdf5 file for use in testing
00992     if( 0 == rank ) create_input_file( file_name, ReadIntervals, numproc, ReadBlocks );
00993     MPI_Barrier( MPI_COMM_WORLD );
00994 
00995     // CPU Time for true paralle, wall time for true paralle,
00996     //   CPU time for read and delete, wall time for read and delete
00997     double times[6];
00998     clock_t tmp_t;
00999 
01000     // Time true parallel read
01001     Core moab;
01002     Interface& mb   = moab;
01003     times[0]        = MPI_Wtime();
01004     tmp_t           = clock();
01005     std::string opt = get_read_options( true, READ_PART );
01006     rval            = mb.load_file( file_name, 0, opt.c_str() );CHECK_ERR( rval );
01007     times[0] = MPI_Wtime() - times[0];
01008     times[1] = double( clock() - tmp_t ) / CLOCKS_PER_SEC;
01009     mb.delete_mesh();
01010 
01011     // Time read and delete
01012     Core moab2;
01013     Interface& mb2   = moab2;
01014     std::string opt2 = get_read_options( true, READ_DELETE );
01015     times[2]         = MPI_Wtime();
01016     tmp_t            = clock();
01017     rval             = mb2.load_file( file_name, 0, opt2.c_str() );CHECK_ERR( rval );
01018     times[2] = MPI_Wtime() - times[2];
01019     times[3] = double( clock() - tmp_t ) / CLOCKS_PER_SEC;
01020     mb2.delete_mesh();
01021 
01022     // Time broadcast and delete
01023     Core moab3;
01024     Interface& mb3   = moab3;
01025     std::string opt3 = get_read_options( true, BCAST_DELETE );
01026     times[4]         = MPI_Wtime();
01027     tmp_t            = clock();
01028     rval             = mb3.load_file( file_name, 0, opt3.c_str() );CHECK_ERR( rval );
01029     times[4] = MPI_Wtime() - times[4];
01030     times[5] = double( clock() - tmp_t ) / CLOCKS_PER_SEC;
01031     mb3.delete_mesh();
01032 
01033     double max_times[6] = { 0, 0, 0, 0, 0, 0 }, sum_times[6] = { 0, 0, 0, 0, 0, 0 };
01034     MPI_Reduce( times, max_times, 6, MPI_DOUBLE, MPI_MAX, 0, MPI_COMM_WORLD );
01035     MPI_Reduce( times, sum_times, 6, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD );
01036     MPI_Barrier( MPI_COMM_WORLD );
01037     if( 0 == rank )
01038     {
01039         printf( "%12s  %12s  %12s  %12s\n", "", "READ_PART", "READ_DELETE", "BCAST_DELETE" );
01040         printf( "%12s  %12g  %12g  %12g\n", "Max Wall", max_times[0], max_times[2], max_times[4] );
01041         printf( "%12s  %12g  %12g  %12g\n", "Total Wall", sum_times[0], sum_times[2], sum_times[4] );
01042         printf( "%12s  %12g  %12g  %12g\n", "Max CPU", max_times[1], max_times[3], max_times[5] );
01043         printf( "%12s  %12g  %12g  %12g\n", "Total CPU", sum_times[1], sum_times[3], sum_times[5] );
01044     }
01045 
01046     MPI_Barrier( MPI_COMM_WORLD );
01047     if( 0 == rank && !KeepTmpFiles ) remove( file_name );
01048 }
01049 
01050 void test_read_tags()
01051 {
01052     const char tag_name[]  = "test_tag_xx";
01053     const char file_name[] = "test_read_tags.h5m";
01054     int numproc, rank;
01055     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01056     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01057     Core moab;
01058     Interface& mb = moab;
01059     ErrorCode rval;
01060 
01061     // if root processor, create hdf5 file for use in testing
01062     if( 0 == rank ) create_input_file( file_name, DefaultReadIntervals, numproc, 1, tag_name );
01063     MPI_Barrier( MPI_COMM_WORLD );  // make sure root has completed writing the file
01064 
01065     // do parallel read unless only one processor
01066     std::string opt = get_read_options();
01067     rval            = mb.load_file( file_name, 0, opt.c_str() );
01068     MPI_Barrier( MPI_COMM_WORLD );  // make sure all procs complete before removing file
01069     if( 0 == rank && !KeepTmpFiles ) remove( file_name );CHECK_ERR( rval );
01070 
01071     Tag tag;
01072     rval = mb.tag_get_handle( tag_name, 3, MB_TYPE_INTEGER, tag );CHECK_ERR( rval );
01073 
01074     TagType storage;
01075     rval = mb.tag_get_type( tag, storage );CHECK_ERR( rval );
01076     CHECK_EQUAL( MB_TAG_DENSE, storage );
01077 
01078     Range verts, tagged;
01079     rval = mb.get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
01080     rval = mb.get_entities_by_type_and_tag( 0, MBVERTEX, &tag, 0, 1, tagged );CHECK_ERR( rval );
01081     CHECK_EQUAL( verts, tagged );
01082 
01083     for( Range::iterator i = verts.begin(); i != verts.end(); ++i )
01084     {
01085         double coords[3];
01086         rval = mb.get_coords( &*i, 1, coords );CHECK_ERR( rval );
01087         int ijk[3];
01088         rval = mb.tag_get_data( tag, &*i, 1, ijk );CHECK_ERR( rval );
01089 
01090         CHECK( ijk[0] >= DefaultReadIntervals * rank );
01091         CHECK( ijk[0] <= DefaultReadIntervals * ( rank + 1 ) );
01092         CHECK( ijk[1] >= 0 );
01093         CHECK( ijk[1] <= DefaultReadIntervals );
01094         CHECK( ijk[2] >= 0 );
01095         CHECK( ijk[2] <= DefaultReadIntervals );
01096 
01097         CHECK_REAL_EQUAL( coords[0], (double)ijk[0], 1e-100 );
01098         CHECK_REAL_EQUAL( coords[1], (double)ijk[1], 1e-100 );
01099         CHECK_REAL_EQUAL( coords[2], (double)ijk[2], 1e-100 );
01100     }
01101 }
01102 
01103 void test_read_global_tags()
01104 {
01105     const char tag_name[]  = "test_tag_g";
01106     const char file_name[] = "test_read_global_tags.h5m";
01107     int numproc, rank;
01108     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01109     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01110     Core moab;
01111     Interface& mb = moab;
01112     ErrorCode rval;
01113     const int def_val    = 0xdeadcad;
01114     const int global_val = -11;
01115 
01116     // if root processor, create hdf5 file for use in testing
01117     if( 0 == rank ) create_input_file( file_name, 1, numproc, 1, 0, 0, tag_name, &global_val, &def_val );
01118     MPI_Barrier( MPI_COMM_WORLD );  // make sure root has completed writing the file
01119 
01120     // do parallel read unless only one processor
01121     std::string opt = get_read_options();
01122     rval            = mb.load_file( file_name, 0, opt.c_str() );
01123     MPI_Barrier( MPI_COMM_WORLD );  // make sure all procs complete before removing file
01124     if( 0 == rank && !KeepTmpFiles ) remove( file_name );CHECK_ERR( rval );
01125 
01126     Tag tag;
01127     rval = mb.tag_get_handle( tag_name, 1, MB_TYPE_INTEGER, tag );CHECK_ERR( rval );
01128 
01129     TagType storage;
01130     rval = mb.tag_get_type( tag, storage );CHECK_ERR( rval );
01131     CHECK_EQUAL( MB_TAG_DENSE, storage );
01132 
01133     int mesh_def_val, mesh_gbl_val;
01134     rval = mb.tag_get_default_value( tag, &mesh_def_val );CHECK_ERR( rval );
01135     CHECK_EQUAL( def_val, mesh_def_val );
01136     EntityHandle root = 0;
01137     rval              = mb.tag_get_data( tag, &root, 1, &mesh_gbl_val );CHECK_ERR( rval );
01138     CHECK_EQUAL( global_val, mesh_gbl_val );
01139 }
01140 
01141 void test_read_sets_common( const char* extra_opts )
01142 {
01143     const char tag_name[]  = "test_tag_s";
01144     const char file_name[] = "test_read_sets.h5m";
01145     int numproc, rank;
01146     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01147     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01148     Core moab;
01149     Interface& mb = moab;
01150     ErrorCode rval;
01151 
01152     // if root processor, create hdf5 file for use in testing
01153     if( 0 == rank ) create_input_file( file_name, DefaultReadIntervals, numproc, 1, 0, tag_name );
01154     MPI_Barrier( MPI_COMM_WORLD );  // make sure root has completed writing the file
01155 
01156     // do parallel read unless only one processor
01157     std::string opt = get_read_options( extra_opts );
01158     rval            = mb.load_file( file_name, 0, opt.c_str() );
01159     MPI_Barrier( MPI_COMM_WORLD );  // make sure all procs complete before removing file
01160     if( 0 == rank && !KeepTmpFiles ) remove( file_name );CHECK_ERR( rval );
01161 
01162     Tag tag;
01163     rval = mb.tag_get_handle( tag_name, 2, MB_TYPE_INTEGER, tag );CHECK_ERR( rval );
01164 
01165     TagType storage;
01166     rval = mb.tag_get_type( tag, storage );CHECK_ERR( rval );
01167     CHECK_EQUAL( MB_TAG_SPARSE, storage );
01168 
01169     const int iv = DefaultReadIntervals + 1;
01170     Range sets;
01171     rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, sets );CHECK_ERR( rval );
01172     CHECK_EQUAL( ( iv * iv ), (int)sets.size() );
01173 
01174     for( Range::iterator i = sets.begin(); i != sets.end(); ++i )
01175     {
01176         int ij[2];
01177         rval = mb.tag_get_data( tag, &*i, 1, &ij );CHECK_ERR( rval );
01178 
01179         CHECK( ij[0] >= DefaultReadIntervals * rank );
01180         CHECK( ij[0] <= DefaultReadIntervals * ( rank + 1 ) );
01181         CHECK( ij[1] >= 0 );
01182         CHECK( ij[1] <= DefaultReadIntervals );
01183 
01184         Range contents;
01185         rval = mb.get_entities_by_handle( *i, contents );CHECK_ERR( rval );
01186         CHECK( contents.all_of_type( MBVERTEX ) );
01187         CHECK_EQUAL( iv, (int)contents.size() );
01188 
01189         for( Range::iterator v = contents.begin(); v != contents.end(); ++v )
01190         {
01191             double coords[3];
01192             rval = mb.get_coords( &*v, 1, coords );CHECK_ERR( rval );
01193             CHECK_REAL_EQUAL( coords[0], (double)ij[0], 1e-100 );
01194             CHECK_REAL_EQUAL( coords[1], (double)ij[1], 1e-100 );
01195         }
01196     }
01197 }
01198 
01199 void test_read_bc_sets()
01200 {
01201     // const char tag_name[] = "test_tag_s";
01202     const char file_name[] = "test_read_sets.h5m";
01203     int numproc, rank;
01204     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01205     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01206     Core moab;
01207     Interface& mb = moab;
01208     ErrorCode rval;
01209 
01210     // if root processor, create hdf5 file for use in testing
01211     if( 0 == rank )
01212         create_input_file( file_name, DefaultReadIntervals, numproc, 1, NULL, NULL, NULL, NULL, NULL, true );
01213     MPI_Barrier( MPI_COMM_WORLD );  // make sure root has completed writing the file
01214 
01215     // do parallel read unless only one processor
01216     std::string opt = get_read_options();
01217     rval            = mb.load_file( file_name, 0, opt.c_str() );
01218     MPI_Barrier( MPI_COMM_WORLD );  // make sure all procs complete before removing file
01219     if( 0 == rank && !KeepTmpFiles ) remove( file_name );CHECK_ERR( rval );
01220 
01221     Tag tag;
01222     int num_ents[3], global_num_ents[3] = { 0, 0, 0 };
01223     Range sets, contents;
01224     const char* names[]     = { NEUMANN_SET_TAG_NAME, DIRICHLET_SET_TAG_NAME, MATERIAL_SET_TAG_NAME };
01225     int vints               = DefaultReadIntervals + 1;
01226     int expected_num_ents[] = { ( numproc * 4 + 2 ) * DefaultReadIntervals * DefaultReadIntervals,
01227                                 ( ( numproc * 4 + 2 ) * ( vints - 2 ) * ( vints - 2 ) + 12 * numproc * ( vints - 2 ) +
01228                                   8 * numproc ),
01229                                 numproc * DefaultReadIntervals * DefaultReadIntervals * DefaultReadIntervals };
01230 
01231     for( int i = 0; i < 3; i++ )
01232     {
01233         rval = mb.tag_get_handle( names[i], 1, MB_TYPE_INTEGER, tag );CHECK_ERR( rval );
01234         rval = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &tag, 0, 1, sets );CHECK_ERR( rval );
01235         CHECK_EQUAL( 1, (int)sets.size() );
01236         rval = mb.get_entities_by_handle( *sets.begin(), contents, true );CHECK_ERR( rval );
01237         num_ents[i] = contents.size();
01238         sets.clear();
01239         contents.clear();
01240     }
01241 
01242     MPI_Reduce( num_ents, global_num_ents, 3, MPI_INT, MPI_SUM, 0, MPI_COMM_WORLD );
01243     if( 0 == rank )
01244     {
01245         //    std::cout << "Global:" << global_num_ents[0] << " " << global_num_ents[1] << " " <<
01246         //    global_num_ents[2] << " " << std::endl; std::cout << "Expected:" <<
01247         //    expected_num_ents[0] << " " << expected_num_ents[1] << " " << expected_num_ents[2] <<
01248         //    " " << std::endl;
01249 
01250         for( int i = 0; i < 3; i++ )
01251         {
01252             CHECK_EQUAL( global_num_ents[i], expected_num_ents[i] );
01253         }
01254     }
01255 }
01256 
01257 void test_write_different_element_types()
01258 {
01259     const char file_name[] = "test_write_different_element_types.h5m";
01260     int numproc, rank;
01261     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01262     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01263     Core moab;
01264     Interface& mb = moab;
01265     ErrorCode rval;
01266 
01267     const EntityType topos[] = { MBEDGE, MBEDGE, MBQUAD,  MBTRI,     MBQUAD, MBTRI,
01268                                  MBTET,  MBHEX,  MBPRISM, MBPYRAMID, MBHEX,  MBHEX };
01269     const int verts[]        = { 2, 3, 4, 3, 9, 6, 4, 8, 6, 5, 20, 27 };
01270     const int ntypes         = sizeof( topos ) / sizeof( topos[0] );
01271 
01272     const EntityType mtype = topos[rank % ntypes];
01273     const int nvert        = verts[rank % ntypes];
01274     std::vector< EntityHandle > conn( nvert );
01275     for( int i = 0; i < nvert; ++i )
01276     {
01277         const double coords[] = { static_cast< double >( rank ), static_cast< double >( i ), 0 };
01278         rval                  = mb.create_vertex( coords, conn[i] );CHECK_ERR( rval );
01279     }
01280     EntityHandle handle;
01281     rval = mb.create_element( mtype, &conn[0], nvert, handle );CHECK_ERR( rval );
01282 
01283     save_and_load_on_root( mb, file_name );
01284 
01285     if( rank ) return;
01286 
01287     for( int i = 0; i < ntypes; ++i )
01288     {
01289         const int num_exp = numproc / ntypes + ( i < ( numproc % ntypes ) ? 1 : 0 );
01290         Range ents;
01291         rval = mb.get_entities_by_type( 0, topos[i], ents );CHECK_ERR( rval );
01292         int num = 0;
01293         for( Range::iterator e = ents.begin(); e != ents.end(); ++e )
01294         {
01295             const EntityHandle* junk;
01296             int len;
01297             rval = mb.get_connectivity( *e, junk, len, false );
01298             if( len == verts[i] ) ++num;
01299         }
01300 
01301         CHECK_EQUAL( num_exp, num );
01302     }
01303 }
01304 
01305 Tag get_tag( Interface& mb, int rank, bool create )
01306 {
01307     DataType type   = (DataType)( rank % ( MB_MAX_DATA_TYPE + 1 ) );
01308     TagType storage = ( type == MB_TYPE_BIT ) ? MB_TAG_BIT : ( rank % 2 ) ? MB_TAG_DENSE : MB_TAG_SPARSE;
01309     int len         = rank % 3 + 1;
01310     TagType cbit    = create ? MB_TAG_EXCL : (TagType)0;
01311     TagType vbit    = rank % 4 == 1 && storage != MB_TAG_BIT ? MB_TAG_VARLEN : (TagType)0;
01312     std::ostringstream name;
01313     name << "TestTag" << rank;
01314     const void* defval = 0;
01315     const int defint[] = { static_cast< int >( rank ), static_cast< int >( rank / 2 ), static_cast< int >( rank + 1 ),
01316                            static_cast< int >( rank - 1 ) };
01317     const double defreal[] = { 0.1 * rank, 1.0 / rank, static_cast< double >( -rank ), static_cast< double >( rank ) };
01318     const int defhandle[]  = { 0, 0, 0, 0 };
01319     const unsigned char defbit = 0x1;
01320     const char defopq[]        = "Jason";
01321     if( rank % 4 < 2 )
01322     {
01323         switch( type )
01324         {
01325             case MB_TYPE_BIT:
01326                 defval = &defbit;
01327                 break;
01328             case MB_TYPE_INTEGER:
01329                 defval = defint;
01330                 break;
01331             case MB_TYPE_DOUBLE:
01332                 defval = defreal;
01333                 break;
01334             case MB_TYPE_HANDLE:
01335                 defval = defhandle;
01336                 break;
01337             case MB_TYPE_OPAQUE:
01338                 defval = defopq;
01339                 break;
01340         }
01341     }
01342 
01343     Tag result;
01344     ErrorCode rval = mb.tag_get_handle( name.str().c_str(), len, type, result, storage | cbit | vbit, defval );CHECK_ERR( rval );
01345     return result;
01346 }
01347 
01348 void test_write_different_tags()
01349 {
01350     const char file_name[] = "test_write_different_tags.h5m";
01351     int numproc, rank;
01352     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01353     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01354     Core moab;
01355     Interface& mb = moab;
01356 
01357     const int min_tags = 8;
01358     get_tag( mb, rank, true );
01359     for( int idx = rank + numproc; idx < min_tags; idx += numproc )
01360         get_tag( mb, idx, true );
01361 
01362     save_and_load_on_root( mb, file_name );
01363 
01364     if( 0 == rank )
01365     {
01366         for( int i = 0; i < std::max( min_tags, numproc ); ++i )
01367             get_tag( mb, i, false );
01368     }
01369 }
01370 
01371 void test_write_polygons()
01372 {
01373     const char file_name[] = "test_write_polygons.h5m";
01374     int numproc, rank;
01375     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01376     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01377     Core moab;
01378     Interface& mb = moab;
01379     ErrorCode rval;
01380 
01381     // create a polygon on each process
01382     const double r            = 0.70710678118654757;
01383     const double points[8][3] = {
01384         { 1, 0, static_cast< double >( rank ) },
01385         { static_cast< double >( r ), static_cast< double >( r ), static_cast< double >( rank ) },
01386         { 0, 1, static_cast< double >( rank ) },
01387         { static_cast< double >( -r ), static_cast< double >( r ), static_cast< double >( rank ) },
01388         { -1, 0, static_cast< double >( rank ) },
01389         { static_cast< double >( -r ), static_cast< double >( -r ), static_cast< double >( rank ) },
01390         { 0, -1, static_cast< double >( rank ) },
01391         { static_cast< double >( r ), static_cast< double >( -r ), static_cast< double >( rank ) } };
01392     const int nvtx = rank % 4 + 5;
01393     std::vector< EntityHandle > conn( nvtx );
01394     for( int i = 0; i < nvtx; ++i )
01395     {
01396         rval = mb.create_vertex( points[i], conn[i] );CHECK_ERR( rval );
01397     }
01398 
01399     EntityHandle h;
01400     rval = mb.create_element( MBPOLYGON, &conn[0], nvtx, h );CHECK_ERR( rval );
01401 
01402     save_and_load_on_root( mb, file_name );
01403 
01404     if( rank != 0 ) return;
01405 
01406     // check results on root process
01407 
01408     // determine which polygon was created by which proc by
01409     // looking at the z-coordinate of the vertices
01410     Range range;
01411     rval = mb.get_entities_by_type( 0, MBPOLYGON, range );
01412     std::vector< EntityHandle > poly( numproc, 0 );
01413     CHECK_EQUAL( numproc, (int)range.size() );
01414     for( Range::iterator it = range.begin(); it != range.end(); ++it )
01415     {
01416         const EntityHandle* conn_arr;
01417         int len;
01418         rval = mb.get_connectivity( *it, conn_arr, len );CHECK_ERR( rval );
01419         double coords[3];
01420         rval = mb.get_coords( conn_arr, 1, coords );CHECK_ERR( rval );
01421         int proc = (int)( coords[2] );
01422         CHECK_EQUAL( (EntityHandle)0, poly[proc] );
01423         poly[proc] = *it;
01424     }
01425 
01426     // check that each poly has the expected number of vertices
01427     for( int i = 0; i < numproc; ++i )
01428     {
01429         const EntityHandle* conn_arr;
01430         int len;
01431         rval = mb.get_connectivity( poly[i], conn_arr, len );CHECK_ERR( rval );
01432         CHECK_EQUAL( i % 4 + 5, len );
01433     }
01434 }
01435 
01436 // Some processes have no mesh to write
01437 void test_write_unbalanced()
01438 {
01439     const char file_name[] = "test_write_unbalanced.h5m";
01440     int numproc, rank;
01441     MPI_Comm_size( MPI_COMM_WORLD, &numproc );
01442     MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01443     Core moab;
01444     Interface& mb = moab;
01445     ErrorCode rval;
01446     Tag idtag = mb.globalId_tag();
01447 
01448     // create a shared set
01449     const int two = 2;
01450     Range entities, sets;
01451 
01452     EntityHandle set;
01453     rval = mb.create_meshset( MESHSET_SET, set );CHECK_ERR( rval );
01454     rval = mb.tag_set_data( idtag, &set, 1, &two );CHECK_ERR( rval );
01455     sets.insert( set );
01456 
01457     // create a quad on every odd processor
01458     if( rank % 2 )
01459     {
01460         const double coords[4][3] = { { static_cast< double >( rank ), 0, 0 },
01461                                       { static_cast< double >( rank + 2 ), 0, 0 },
01462                                       { static_cast< double >( rank + 2 ), 2, 0 },
01463                                       { static_cast< double >( rank ), 2, 0 } };
01464         EntityHandle conn[4], quad;
01465         for( int i = 0; i < 4; ++i )
01466             mb.create_vertex( coords[i], conn[i] );
01467         mb.create_element( MBQUAD, conn, 4, quad );
01468 
01469         const int ids[4] = { rank, rank + 2, rank + 3, rank + 1 };
01470         rval             = mb.tag_set_data( idtag, conn, 4, ids );CHECK_ERR( rval );
01471 
01472         rval = mb.add_entities( set, &quad, 1 );CHECK_ERR( rval );
01473 
01474         entities.insert( quad );
01475     }
01476 
01477     // set up sharing data
01478     ParallelComm* pcomm = ParallelComm::get_pcomm( &mb, 0 );
01479     if( 0 == pcomm ) pcomm = new ParallelComm( &mb, MPI_COMM_WORLD );
01480     rval = pcomm->resolve_shared_ents( 0, entities, 2, 0, NULL, &idtag );CHECK_ERR( rval );
01481     rval = pcomm->resolve_shared_sets( sets, idtag );CHECK_ERR( rval );
01482 
01483     // do parallel write and serial load
01484     save_and_load_on_root( mb, file_name );
01485 
01486     if( rank != 0 ) return;
01487 
01488     // check that we got what we expected
01489     Range quads, verts;
01490     rval = mb.get_entities_by_type( 0, MBQUAD, quads );CHECK_ERR( rval );
01491     rval = mb.get_entities_by_type( 0, MBVERTEX, verts );CHECK_ERR( rval );
01492 
01493     const size_t nquads = numproc / 2;
01494     const size_t nverts = nquads ? 2 + 2 * nquads : 0;
01495     CHECK_EQUAL( nquads, quads.size() );
01496     CHECK_EQUAL( nverts, verts.size() );
01497 
01498     rval = mb.tag_get_handle( GLOBAL_ID_TAG_NAME, 1, MB_TYPE_INTEGER, idtag );CHECK_ERR( rval );
01499     sets.clear();
01500     const void* vals[] = { &two };
01501     rval               = mb.get_entities_by_type_and_tag( 0, MBENTITYSET, &idtag, vals, 1, sets );CHECK_ERR( rval );
01502     CHECK_EQUAL( (size_t)1, sets.size() );
01503 
01504     entities.clear();
01505     rval = mb.get_entities_by_handle( sets.front(), entities );CHECK_ERR( rval );
01506     CHECK_EQUAL( nquads, entities.size() );
01507     CHECK_EQUAL( quads, entities );
01508 }
01509 
01510 // this test will load a file that has 2 partitions (mix.h5m)
01511 // one partition with triangles, and one with triangles and quads
01512 // a dense tag created on this should be dense in the file
01513 //
01514 void test_write_dense_tags()
01515 {
01516     int err, rank, size;
01517     ErrorCode rval;
01518     err = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01519     CHECK( !err );
01520     err = MPI_Comm_size( MPI_COMM_WORLD, &size );
01521     CHECK( !err );
01522 
01523     Core moab;
01524     rval = moab.load_file( InputMix, 0,
01525                            "PARALLEL=READ_PART;"
01526                            "PARTITION=PARALLEL_PARTITION;"
01527                            "PARALLEL_RESOLVE_SHARED_ENTS" );CHECK_ERR( rval );
01528 
01529     // create an dense tag, on all elements, then write the output in parallel
01530     // load the file again, and test the type of the tag
01531     Range elems;
01532     moab.get_entities_by_dimension( 0, 2, elems );
01533 
01534     const char* tagname = "element_tag";
01535     const double defVal = 0.;
01536     Tag fieldTag;
01537     rval = moab.tag_get_handle( tagname, 1, MB_TYPE_DOUBLE, fieldTag, MB_TAG_DENSE | MB_TAG_CREAT, &defVal );CHECK_ERR( rval );
01538 
01539     int numElems = (int)elems.size();
01540 
01541     for( int i = 0; i < numElems; i++ )
01542     {
01543         EntityHandle elem = elems[i];
01544         double xyz[3];
01545         moab.get_coords( &elem, 1, xyz );
01546         // some value
01547         double fieldValue = sqrt( xyz[0] * xyz[0] + xyz[1] * xyz[1] + xyz[2] * xyz[2] );
01548         moab.tag_set_data( fieldTag, &elem, 1, &fieldValue );
01549     }
01550 
01551     // write the file in parallel
01552     rval = moab.write_file( "newfile.h5m", 0, "PARALLEL=WRITE_PART" );CHECK_ERR( rval );
01553 
01554     // now read the new file, in a new instance, and test the tag type
01555 
01556     Core moab2;
01557     rval = moab2.load_file( "newfile.h5m", 0,
01558                             "PARALLEL=READ_PART;"
01559                             "PARTITION=PARALLEL_PARTITION;"
01560                             "PARALLEL_RESOLVE_SHARED_ENTS" );CHECK_ERR( rval );
01561 
01562     // find the element tag
01563     Tag found_tag;
01564     rval = moab2.tag_get_handle( tagname, 1, MB_TYPE_DOUBLE, found_tag );CHECK_ERR( rval );
01565     TagType tagt;
01566     rval = moab2.tag_get_type( found_tag, tagt );CHECK_ERR( rval );
01567     CHECK( tagt == MB_TAG_DENSE );
01568 }
01569 // this test will load a file that has 2 partitions (oneside.h5m)
01570 // and one side set, that is adjacent to one part only
01571 //
01572 void test_read_non_adjs_side()
01573 {
01574     int err, rank, size;
01575     ErrorCode rval;
01576     err = MPI_Comm_rank( MPI_COMM_WORLD, &rank );
01577     CHECK( !err );
01578     err = MPI_Comm_size( MPI_COMM_WORLD, &size );
01579     CHECK( !err );
01580 
01581     Core moab;
01582     rval = moab.load_file( InputOneSide, 0,
01583                            "PARALLEL=READ_PART;"
01584                            "PARTITION=PARALLEL_PARTITION;"
01585                            "PARALLEL_RESOLVE_SHARED_ENTS" );CHECK_ERR( rval );
01586 
01587     return;
01588 }
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines