Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
NCHelper.cpp
Go to the documentation of this file.
00001 #include "NCHelper.hpp"
00002 #include "NCHelperEuler.hpp"
00003 #include "NCHelperFV.hpp"
00004 #include "NCHelperDomain.hpp"
00005 #include "NCHelperScrip.hpp"
00006 #include "NCHelperHOMME.hpp"
00007 #include "NCHelperMPAS.hpp"
00008 #include "NCHelperGCRM.hpp"
00009 
00010 #include <sstream>
00011 
00012 #include "MBTagConventions.hpp"
00013 
00014 #ifdef WIN32
00015 #ifdef size_t
00016 #undef size_t
00017 #endif
00018 #endif
00019 
00020 namespace moab
00021 {
00022 
00023 NCHelper* NCHelper::get_nc_helper( ReadNC* readNC, int fileId, const FileOptions& opts, EntityHandle fileSet )
00024 {
00025     // Check if CF convention is being followed
00026     bool is_CF = false;
00027 
00028     std::map< std::string, ReadNC::AttData >& globalAtts     = readNC->globalAtts;
00029     std::map< std::string, ReadNC::AttData >::iterator attIt = globalAtts.find( "conventions" );
00030     if( attIt == globalAtts.end() ) attIt = globalAtts.find( "Conventions" );
00031 
00032     if( attIt != globalAtts.end() )
00033     {
00034         unsigned int sz = attIt->second.attLen;
00035         std::string att_data;
00036         att_data.resize( sz + 1 );
00037         att_data[sz] = '\000';
00038         int success =
00039             NCFUNC( get_att_text )( fileId, attIt->second.attVarId, attIt->second.attName.c_str(), &att_data[0] );
00040         if( 0 == success && att_data.find( "CF" ) != std::string::npos ) is_CF = true;
00041     }
00042 
00043     if( is_CF )
00044     {
00045         if( NCHelperEuler::can_read_file( readNC, fileId ) )
00046             return new( std::nothrow ) NCHelperEuler( readNC, fileId, opts, fileSet );
00047         else if( NCHelperFV::can_read_file( readNC, fileId ) )
00048             return new( std::nothrow ) NCHelperFV( readNC, fileId, opts, fileSet );
00049         else if( NCHelperHOMME::can_read_file( readNC, fileId ) )
00050             return new( std::nothrow ) NCHelperHOMME( readNC, fileId, opts, fileSet );
00051         else if( NCHelperDomain::can_read_file( readNC, fileId ) )
00052             return new( std::nothrow ) NCHelperDomain( readNC, fileId, opts, fileSet );
00053     }
00054     else
00055     {
00056         if( NCHelperMPAS::can_read_file( readNC ) )
00057             return new( std::nothrow ) NCHelperMPAS( readNC, fileId, opts, fileSet );
00058         // For a HOMME connectivity file, there might be no CF convention
00059         else if( NCHelperHOMME::can_read_file( readNC, fileId ) )
00060             return new( std::nothrow ) NCHelperHOMME( readNC, fileId, opts, fileSet );
00061         // gcrm reader
00062         else if( NCHelperGCRM::can_read_file( readNC ) )
00063             return new( std::nothrow ) NCHelperGCRM( readNC, fileId, opts, fileSet );
00064     }
00065     // SCRIP can be CF or non CF, if it comes from MPAS :)
00066     if( NCHelperScrip::can_read_file( readNC, fileId ) )
00067         return new( std::nothrow ) NCHelperScrip( readNC, fileId, opts, fileSet );
00068 
00069     // Unknown NetCDF grid (will fill this in later for POP, CICE and CLM)
00070     return NULL;
00071 }
00072 
00073 ErrorCode NCHelper::create_conventional_tags( const std::vector< int >& tstep_nums )
00074 {
00075     Interface*& mbImpl                                   = _readNC->mbImpl;
00076     std::vector< std::string >& dimNames                 = _readNC->dimNames;
00077     std::vector< int >& dimLens                          = _readNC->dimLens;
00078     std::map< std::string, ReadNC::AttData >& globalAtts = _readNC->globalAtts;
00079     std::map< std::string, ReadNC::VarData >& varInfo    = _readNC->varInfo;
00080     DebugOutput& dbgOut                                  = _readNC->dbgOut;
00081     int& partMethod                                      = _readNC->partMethod;
00082     ScdInterface* scdi                                   = _readNC->scdi;
00083 
00084     ErrorCode rval;
00085     std::string tag_name;
00086 
00087     // <__NUM_DIMS>
00088     Tag numDimsTag = 0;
00089     tag_name       = "__NUM_DIMS";
00090     int numDims    = dimNames.size();
00091     rval = mbImpl->tag_get_handle( tag_name.c_str(), 1, MB_TYPE_INTEGER, numDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00092     rval = mbImpl->tag_set_data( numDimsTag, &_fileSet, 1, &numDims );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00093     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00094 
00095     // <__NUM_VARS>
00096     Tag numVarsTag = 0;
00097     tag_name       = "__NUM_VARS";
00098     int numVars    = varInfo.size();
00099     rval = mbImpl->tag_get_handle( tag_name.c_str(), 1, MB_TYPE_INTEGER, numVarsTag, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00100     rval = mbImpl->tag_set_data( numVarsTag, &_fileSet, 1, &numVars );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00101     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00102 
00103     // <__DIM_NAMES>
00104     Tag dimNamesTag = 0;
00105     tag_name        = "__DIM_NAMES";
00106     std::string dimnames;
00107     unsigned int dimNamesSz = dimNames.size();
00108     for( unsigned int i = 0; i != dimNamesSz; i++ )
00109     {
00110         dimnames.append( dimNames[i] );
00111         dimnames.push_back( '\0' );
00112     }
00113     int dimnamesSz = dimnames.size();
00114     rval           = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, dimNamesTag,
00115                                              MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00116     const void* ptr = dimnames.c_str();
00117     rval            = mbImpl->tag_set_by_ptr( dimNamesTag, &_fileSet, 1, &ptr, &dimnamesSz );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00118     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00119 
00120     // <__DIM_LENS>
00121     Tag dimLensTag = 0;
00122     tag_name       = "__DIM_LENS";
00123     int dimLensSz  = dimLens.size();
00124     rval           = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_INTEGER, dimLensTag,
00125                                              MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00126     ptr  = &( dimLens[0] );
00127     rval = mbImpl->tag_set_by_ptr( dimLensTag, &_fileSet, 1, &ptr, &dimLensSz );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00128     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00129 
00130     // <__VAR_NAMES>
00131     Tag varNamesTag = 0;
00132     tag_name        = "__VAR_NAMES";
00133     std::string varnames;
00134     std::map< std::string, ReadNC::VarData >::iterator mapIter;
00135     for( mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter )
00136     {
00137         varnames.append( mapIter->first );
00138         varnames.push_back( '\0' );
00139     }
00140     int varnamesSz = varnames.size();
00141     rval           = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varNamesTag,
00142                                              MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00143     ptr  = varnames.c_str();
00144     rval = mbImpl->tag_set_by_ptr( varNamesTag, &_fileSet, 1, &ptr, &varnamesSz );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00145     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00146 
00147     // __<dim_name>_LOC_MINMAX (for time)
00148     for( unsigned int i = 0; i != dimNamesSz; i++ )
00149     {
00150         if( dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t" )
00151         {
00152             // some files might have Time dimension as 0, it will not appear in any
00153             // variables, so skip it
00154             if( nTimeSteps == 0 ) continue;
00155             std::stringstream ss_tag_name;
00156             ss_tag_name << "__" << dimNames[i] << "_LOC_MINMAX";
00157             tag_name = ss_tag_name.str();
00158             Tag tagh = 0;
00159             std::vector< int > val( 2, 0 );
00160             val[0] = 0;
00161             val[1] = nTimeSteps - 1;
00162             rval   = mbImpl->tag_get_handle( tag_name.c_str(), 2, MB_TYPE_INTEGER, tagh, MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00163             rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00164             dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00165         }
00166     }
00167 
00168     // __<dim_name>_LOC_VALS (for time)
00169     for( unsigned int i = 0; i != dimNamesSz; i++ )
00170     {
00171         if( dimNames[i] == "time" || dimNames[i] == "Time" || dimNames[i] == "t" )
00172         {
00173             std::vector< int > val;
00174             if( !tstep_nums.empty() )
00175                 val = tstep_nums;
00176             else
00177             {
00178                 // some files might have Time dimension as 0, it will not appear in any
00179                 // variables, so skip it
00180                 if( tVals.empty() ) continue;
00181                 val.resize( tVals.size() );
00182                 for( unsigned int j = 0; j != tVals.size(); j++ )
00183                     val[j] = j;
00184             }
00185             Tag tagh = 0;
00186             std::stringstream ss_tag_name;
00187             ss_tag_name << "__" << dimNames[i] << "_LOC_VALS";
00188             tag_name = ss_tag_name.str();
00189             rval     = mbImpl->tag_get_handle( tag_name.c_str(), val.size(), MB_TYPE_INTEGER, tagh,
00190                                                MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00191             rval = mbImpl->tag_set_data( tagh, &_fileSet, 1, &val[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00192             dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00193         }
00194     }
00195 
00196     // __<var_name>_DIMS
00197     for( mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter )
00198     {
00199         Tag varNamesDimsTag = 0;
00200         std::stringstream ss_tag_name;
00201         ss_tag_name << "__" << mapIter->first << "_DIMS";
00202         tag_name              = ss_tag_name.str();
00203         unsigned int varDimSz = varInfo[mapIter->first].varDims.size();
00204         if( varDimSz == 0 ) continue;
00205         std::vector< Tag > varDimTags( varDimSz );
00206         for( unsigned int i = 0; i != varDimSz; i++ )
00207         {
00208             Tag tmptag             = 0;
00209             std::string tmptagname = dimNames[varInfo[mapIter->first].varDims[i]];
00210             rval = mbImpl->tag_get_handle( tmptagname.c_str(), 0, MB_TYPE_OPAQUE, tmptag, MB_TAG_ANY );MB_CHK_SET_ERR( rval, "Trouble getting tag " << tmptagname );
00211             varDimTags[i] = tmptag;
00212         }
00213         // rval = mbImpl->tag_get_handle(tag_name.c_str(), varDimSz, MB_TYPE_HANDLE,
00214         // varNamesDimsTag, MB_TAG_SPARSE | MB_TAG_CREAT); We should not use MB_TYPE_HANDLE for Tag
00215         // here. Tag is a pointer, which is 4 bytes on 32 bit machines and 8 bytes on 64 bit
00216         // machines. Normally, entity handle is 8 bytes on 64 bit machines, but it can also be
00217         // configured to 4 bytes.
00218         rval = mbImpl->tag_get_handle( tag_name.c_str(), varDimSz * sizeof( Tag ), MB_TYPE_OPAQUE, varNamesDimsTag,
00219                                        MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00220         rval = mbImpl->tag_set_data( varNamesDimsTag, &_fileSet, 1, &( varDimTags[0] ) );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00221         dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00222     }
00223 
00224     // <PARTITION_METHOD>
00225     Tag part_tag = scdi->part_method_tag();
00226     if( !part_tag ) MB_SET_ERR( MB_FAILURE, "Trouble getting PARTITION_METHOD tag" );
00227     rval = mbImpl->tag_set_data( part_tag, &_fileSet, 1, &partMethod );MB_CHK_SET_ERR( rval, "Trouble setting data to PARTITION_METHOD tag" );
00228     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00229 
00230     // <__GLOBAL_ATTRIBS>
00231     tag_name         = "__GLOBAL_ATTRIBS";
00232     Tag globalAttTag = 0;
00233     rval             = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, globalAttTag,
00234                                                MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00235     std::string gattVal;
00236     std::vector< int > gattLen;
00237     rval = create_attrib_string( globalAtts, gattVal, gattLen );MB_CHK_SET_ERR( rval, "Trouble creating global attribute string" );
00238     const void* gattptr = gattVal.c_str();
00239     int globalAttSz     = gattVal.size();
00240     rval                = mbImpl->tag_set_by_ptr( globalAttTag, &_fileSet, 1, &gattptr, &globalAttSz );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00241     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00242 
00243     // <__GLOBAL_ATTRIBS_LEN>
00244     tag_name            = "__GLOBAL_ATTRIBS_LEN";
00245     Tag globalAttLenTag = 0;
00246     if( gattLen.size() == 0 ) gattLen.push_back( 0 );
00247     rval = mbImpl->tag_get_handle( tag_name.c_str(), gattLen.size(), MB_TYPE_INTEGER, globalAttLenTag,
00248                                    MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00249     rval = mbImpl->tag_set_data( globalAttLenTag, &_fileSet, 1, &gattLen[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00250     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00251 
00252     // __<var_name>_ATTRIBS and __<var_name>_ATTRIBS_LEN
00253     for( mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter )
00254     {
00255         std::stringstream ssTagName;
00256         ssTagName << "__" << mapIter->first << "_ATTRIBS";
00257         tag_name      = ssTagName.str();
00258         Tag varAttTag = 0;
00259         rval          = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, varAttTag,
00260                                                 MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00261 
00262         std::string varAttVal;
00263         std::vector< int > varAttLen;
00264         if( mapIter->second.numAtts < 1 )
00265         {
00266             if( dummyVarNames.find( mapIter->first ) != dummyVarNames.end() )
00267             {
00268                 // This variable is a dummy coordinate variable
00269                 varAttVal = "DUMMY_VAR";
00270             }
00271             else
00272             {
00273                 // This variable has no attributes
00274                 varAttVal = "NO_ATTRIBS";
00275             }
00276         }
00277         else
00278         {
00279             rval = create_attrib_string( mapIter->second.varAtts, varAttVal, varAttLen );MB_CHK_SET_ERR( rval, "Trouble creating attribute string for variable " << mapIter->first );
00280         }
00281         const void* varAttPtr = varAttVal.c_str();
00282         int varAttSz          = varAttVal.size();
00283         if( 0 == varAttSz ) varAttSz = 1;
00284         rval = mbImpl->tag_set_by_ptr( varAttTag, &_fileSet, 1, &varAttPtr, &varAttSz );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00285         dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00286 
00287         ssTagName << "_LEN";
00288         tag_name         = ssTagName.str();
00289         Tag varAttLenTag = 0;
00290         if( 0 == varAttLen.size() ) varAttLen.push_back( 0 );
00291         rval = mbImpl->tag_get_handle( tag_name.c_str(), varAttLen.size(), MB_TYPE_INTEGER, varAttLenTag,
00292                                        MB_TAG_SPARSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00293         rval = mbImpl->tag_set_data( varAttLenTag, &_fileSet, 1, &varAttLen[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00294         dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00295     }
00296 
00297     // <__VAR_NAMES_LOCATIONS>
00298     tag_name            = "__VAR_NAMES_LOCATIONS";
00299     Tag varNamesLocsTag = 0;
00300     std::vector< int > varNamesLocs( varInfo.size() );
00301     rval = mbImpl->tag_get_handle( tag_name.c_str(), varNamesLocs.size(), MB_TYPE_INTEGER, varNamesLocsTag,
00302                                    MB_TAG_CREAT | MB_TAG_SPARSE );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00303     for( mapIter = varInfo.begin(); mapIter != varInfo.end(); ++mapIter )
00304     {
00305         varNamesLocs[std::distance( varInfo.begin(), mapIter )] = mapIter->second.entLoc;
00306     }
00307     rval = mbImpl->tag_set_data( varNamesLocsTag, &_fileSet, 1, &varNamesLocs[0] );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00308     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00309 
00310     // <__MESH_TYPE>
00311     Tag meshTypeTag          = 0;
00312     tag_name                 = "__MESH_TYPE";
00313     std::string meshTypeName = get_mesh_type_name();
00314 
00315     rval = mbImpl->tag_get_handle( tag_name.c_str(), 0, MB_TYPE_OPAQUE, meshTypeTag,
00316                                    MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating conventional tag " << tag_name );
00317     ptr      = meshTypeName.c_str();
00318     int leng = meshTypeName.size();
00319     rval     = mbImpl->tag_set_by_ptr( meshTypeTag, &_fileSet, 1, &ptr, &leng );MB_CHK_SET_ERR( rval, "Trouble setting data to conventional tag " << tag_name );
00320     dbgOut.tprintf( 2, "Conventional tag %s created\n", tag_name.c_str() );
00321 
00322     return MB_SUCCESS;
00323 }
00324 
00325 ErrorCode NCHelper::update_time_tag_vals()
00326 {
00327     Interface*& mbImpl                   = _readNC->mbImpl;
00328     std::vector< std::string >& dimNames = _readNC->dimNames;
00329 
00330     ErrorCode rval;
00331 
00332     // The time tag might be a dummy one (e.g. 'Time' for MPAS)
00333     std::string time_tag_name = dimNames[tDim];
00334     if( dummyVarNames.find( time_tag_name ) != dummyVarNames.end() ) return MB_SUCCESS;
00335 
00336     Tag time_tag      = 0;
00337     const void* data  = NULL;
00338     int time_tag_size = 0;
00339     rval              = mbImpl->tag_get_handle( time_tag_name.c_str(), 0, MB_TYPE_DOUBLE, time_tag, MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble getting tag " << time_tag_name );
00340     rval = mbImpl->tag_get_by_ptr( time_tag, &_fileSet, 1, &data, &time_tag_size );MB_CHK_SET_ERR( rval, "Trouble getting data of tag " << time_tag_name );
00341     const double* time_tag_vals = static_cast< const double* >( data );
00342 
00343     // Merge tVals (read from current file) to existing time tag
00344     // Assume that time_tag_vals and tVals are both sorted
00345     std::vector< double > merged_time_vals;
00346     merged_time_vals.reserve( time_tag_size + nTimeSteps );
00347     int i = 0;
00348     int j = 0;
00349 
00350     // Merge time values from time_tag_vals and tVals
00351     while( i < time_tag_size && j < nTimeSteps )
00352     {
00353         if( time_tag_vals[i] < tVals[j] )
00354             merged_time_vals.push_back( time_tag_vals[i++] );
00355         else
00356             merged_time_vals.push_back( tVals[j++] );
00357     }
00358 
00359     // Append remaining time values of time_tag_vals (if any)
00360     while( i < time_tag_size )
00361         merged_time_vals.push_back( time_tag_vals[i++] );
00362 
00363     // Append remaining time values of tVals (if any)
00364     while( j < nTimeSteps )
00365         merged_time_vals.push_back( tVals[j++] );
00366 
00367     data          = &merged_time_vals[0];
00368     time_tag_size = merged_time_vals.size();
00369     rval          = mbImpl->tag_set_by_ptr( time_tag, &_fileSet, 1, &data, &time_tag_size );MB_CHK_SET_ERR( rval, "Trouble setting data to tag " << time_tag_name );
00370 
00371     return MB_SUCCESS;
00372 }
00373 
00374 ErrorCode NCHelper::read_variables_setup( std::vector< std::string >& var_names,
00375                                           std::vector< int >& tstep_nums,
00376                                           std::vector< ReadNC::VarData >& vdatas,
00377                                           std::vector< ReadNC::VarData >& vsetdatas )
00378 {
00379     std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
00380     std::vector< std::string >& dimNames              = _readNC->dimNames;
00381 
00382     std::map< std::string, ReadNC::VarData >::iterator mit;
00383 
00384     // If empty read them all (except ignored variables)
00385     if( var_names.empty() )
00386     {
00387         for( mit = varInfo.begin(); mit != varInfo.end(); ++mit )
00388         {
00389             ReadNC::VarData vd = ( *mit ).second;
00390 
00391             // If read all variables at once, skip ignored ones
00392             if( ignoredVarNames.find( vd.varName ) != ignoredVarNames.end() ) continue;
00393 
00394             // Coordinate variables (include dummy ones) were read to the file set by default
00395             if( std::find( dimNames.begin(), dimNames.end(), vd.varName ) != dimNames.end() ) continue;
00396 
00397             if( vd.entLoc == ReadNC::ENTLOCSET )
00398                 vsetdatas.push_back( vd );
00399             else
00400                 vdatas.push_back( vd );
00401         }
00402     }
00403     else
00404     {
00405         // Read specified variables (might include ignored ones)
00406         for( unsigned int i = 0; i < var_names.size(); i++ )
00407         {
00408             mit = varInfo.find( var_names[i] );
00409             if( mit != varInfo.end() )
00410             {
00411                 ReadNC::VarData vd = ( *mit ).second;
00412 
00413                 // Upon creation of dummy coordinate variables, tag values have already been set
00414                 if( dummyVarNames.find( vd.varName ) != dummyVarNames.end() ) continue;
00415 
00416                 if( vd.entLoc == ReadNC::ENTLOCSET )
00417                     vsetdatas.push_back( vd );
00418                 else
00419                     vdatas.push_back( vd );
00420             }
00421             else
00422             {
00423                 MB_SET_ERR( MB_FAILURE, "Couldn't find specified variable " << var_names[i] );
00424             }
00425         }
00426     }
00427 
00428     if( tstep_nums.empty() && nTimeSteps > 0 )
00429     {
00430         // No timesteps input, get them all
00431         for( int i = 0; i < nTimeSteps; i++ )
00432             tstep_nums.push_back( i );
00433     }
00434 
00435     if( !tstep_nums.empty() )
00436     {
00437         for( unsigned int i = 0; i < vdatas.size(); i++ )
00438         {
00439             vdatas[i].varTags.resize( tstep_nums.size(), 0 );
00440             vdatas[i].varDatas.resize( tstep_nums.size() );
00441             // NC reader assumes that non-set variables always have timesteps
00442             assert( std::find( vdatas[i].varDims.begin(), vdatas[i].varDims.end(), tDim ) != vdatas[i].varDims.end() );
00443             vdatas[i].has_tsteps = true;
00444         }
00445 
00446         for( unsigned int i = 0; i < vsetdatas.size(); i++ )
00447         {
00448             if( ( std::find( vsetdatas[i].varDims.begin(), vsetdatas[i].varDims.end(), tDim ) !=
00449                   vsetdatas[i].varDims.end() ) &&
00450                 ( vsetdatas[i].varName != dimNames[tDim] ) )
00451             {
00452                 // Set variables with timesteps: e.g. xtime(Time) or xtime(Time, StrLen)
00453                 vsetdatas[i].varTags.resize( tstep_nums.size(), 0 );
00454                 vsetdatas[i].varDatas.resize( tstep_nums.size() );
00455                 vsetdatas[i].has_tsteps = true;
00456             }
00457             else
00458             {
00459                 // Set variables without timesteps: no time dimension, or time itself
00460                 vsetdatas[i].varTags.resize( 1, 0 );
00461                 vsetdatas[i].varDatas.resize( 1 );
00462                 vsetdatas[i].has_tsteps = false;
00463             }
00464         }
00465     }
00466 
00467     return MB_SUCCESS;
00468 }
00469 
00470 ErrorCode NCHelper::read_variables_to_set( std::vector< ReadNC::VarData >& vdatas, std::vector< int >& tstep_nums )
00471 {
00472     Interface*& mbImpl  = _readNC->mbImpl;
00473     DebugOutput& dbgOut = _readNC->dbgOut;
00474 
00475     ErrorCode rval = read_variables_to_set_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read set variables" );
00476 
00477     // Finally, read into that space
00478     int success;
00479     for( unsigned int i = 0; i < vdatas.size(); i++ )
00480     {
00481         // Note, for set variables without timesteps, loop one time and then break
00482         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
00483         {
00484             void* data = vdatas[i].varDatas[t];
00485 
00486             // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
00487             if( vdatas[i].has_tsteps )
00488             {
00489                 // Set readStart for each timestep along time dimension
00490                 vdatas[i].readStarts[0] = tstep_nums[t];
00491             }
00492 
00493             switch( vdatas[i].varDataType )
00494             {
00495                 case NC_BYTE:
00496                 case NC_CHAR:
00497                     success = NCFUNCAG( _vara_text )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
00498                                                       &vdatas[i].readCounts[0], (char*)data );
00499                     if( success )
00500                         MB_SET_ERR( MB_FAILURE, "Failed to read byte/char data for variable " << vdatas[i].varName );
00501                     break;
00502                 case NC_SHORT:
00503                 case NC_INT:
00504                     success = NCFUNCAG( _vara_int )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
00505                                                      &vdatas[i].readCounts[0], (int*)data );
00506                     if( success )
00507                         MB_SET_ERR( MB_FAILURE, "Failed to read short/int data for variable " << vdatas[i].varName );
00508                     break;
00509                 case NC_FLOAT:
00510                 case NC_DOUBLE:
00511                     success = NCFUNCAG( _vara_double )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
00512                                                         &vdatas[i].readCounts[0], (double*)data );
00513                     if( success )
00514                         MB_SET_ERR( MB_FAILURE, "Failed to read float/double data for variable " << vdatas[i].varName );
00515                     break;
00516                 default:
00517                     MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
00518             }
00519 
00520             dbgOut.tprintf( 2, "Setting data for variable %s, time step %d\n", vdatas[i].varName.c_str(),
00521                             tstep_nums[t] );
00522             rval = mbImpl->tag_set_by_ptr( vdatas[i].varTags[t], &_fileSet, 1, &data, &vdatas[i].sz );MB_CHK_SET_ERR( rval, "Trouble setting tag data for variable " << vdatas[i].varName );
00523 
00524             // Memory pointed by pointer data can be deleted, as tag_set_by_ptr() has already copied
00525             // the tag values
00526             switch( vdatas[i].varDataType )
00527             {
00528                 case NC_BYTE:
00529                 case NC_CHAR:
00530                     delete[]( char* ) data;
00531                     break;
00532                 case NC_SHORT:
00533                 case NC_INT:
00534                     delete[]( int* ) data;
00535                     break;
00536                 case NC_FLOAT:
00537                 case NC_DOUBLE:
00538                     delete[]( double* ) data;
00539                     break;
00540                 default:
00541                     break;
00542             }
00543             vdatas[i].varDatas[t] = NULL;
00544 
00545             // Loop continues only for set variables with timesteps, e.g. xtime(Time) or xtime(Time,
00546             // StrLen)
00547             if( !vdatas[i].has_tsteps ) break;
00548         }
00549     }
00550 
00551     // Debug output, if requested
00552     if( 1 == dbgOut.get_verbosity() )
00553     {
00554         dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
00555         for( unsigned int i = 1; i < vdatas.size(); i++ )
00556             dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
00557         dbgOut.tprintf( 1, "\n" );
00558     }
00559 
00560     return rval;
00561 }
00562 
00563 ErrorCode NCHelper::read_coordinate( const char* var_name, int lmin, int lmax, std::vector< double >& cvals )
00564 {
00565     std::map< std::string, ReadNC::VarData >& varInfo       = _readNC->varInfo;
00566     std::map< std::string, ReadNC::VarData >::iterator vmit = varInfo.find( var_name );
00567     if( varInfo.end() == vmit ) MB_SET_ERR( MB_FAILURE, "Couldn't find variable " << var_name );
00568 
00569     assert( lmin >= 0 && lmax >= lmin );
00570     NCDF_SIZE tstart     = lmin;
00571     NCDF_SIZE tcount     = lmax - lmin + 1;
00572     NCDF_DIFF dum_stride = 1;
00573     int success;
00574 
00575     // Check size
00576     if( (std::size_t)tcount != cvals.size() ) cvals.resize( tcount );
00577 
00578     // Check to make sure it's a float or double
00579     switch( ( *vmit ).second.varDataType )
00580     {
00581         case NC_FLOAT:
00582         case NC_DOUBLE:
00583             // Read float as double
00584             success =
00585                 NCFUNCAG( _vars_double )( _fileId, ( *vmit ).second.varId, &tstart, &tcount, &dum_stride, &cvals[0] );
00586             if( success ) MB_SET_ERR( MB_FAILURE, "Failed to read float/double data for variable " << var_name );
00587             break;
00588         default:
00589             MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << var_name );
00590     }
00591 
00592     return MB_SUCCESS;
00593 }
00594 
00595 ErrorCode NCHelper::get_tag_to_set( ReadNC::VarData& var_data, int tstep_num, Tag& tagh )
00596 {
00597     Interface*& mbImpl  = _readNC->mbImpl;
00598     DebugOutput& dbgOut = _readNC->dbgOut;
00599     int& tStepBase      = _readNC->tStepBase;
00600 
00601     if( tStepBase > 0 ) tstep_num += tStepBase;
00602 
00603     std::ostringstream tag_name;
00604     if( var_data.has_tsteps )
00605         tag_name << var_data.varName << tstep_num;
00606     else
00607         tag_name << var_data.varName;
00608 
00609     ErrorCode rval = MB_SUCCESS;
00610     tagh           = 0;
00611     switch( var_data.varDataType )
00612     {
00613         case NC_BYTE:
00614         case NC_CHAR:
00615             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), 0, MB_TYPE_OPAQUE, tagh,
00616                                            MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00617             break;
00618         case NC_SHORT:
00619         case NC_INT:
00620             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), 0, MB_TYPE_INTEGER, tagh,
00621                                            MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00622             break;
00623         case NC_FLOAT:
00624         case NC_DOUBLE:
00625             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), 0, MB_TYPE_DOUBLE, tagh,
00626                                            MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00627             break;
00628         default:
00629             MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << var_data.varName );
00630     }
00631 
00632     dbgOut.tprintf( 2, "Tag %s created\n", tag_name.str().c_str() );
00633 
00634     return rval;
00635 }
00636 
00637 ErrorCode NCHelper::get_tag_to_nonset( ReadNC::VarData& var_data, int tstep_num, Tag& tagh, int num_lev )
00638 {
00639     Interface*& mbImpl  = _readNC->mbImpl;
00640     DebugOutput& dbgOut = _readNC->dbgOut;
00641     int& tStepBase      = _readNC->tStepBase;
00642 
00643     if( tStepBase > 0 ) tstep_num += tStepBase;
00644 
00645     std::ostringstream tag_name;
00646     tag_name << var_data.varName << tstep_num;
00647 
00648     ErrorCode rval = MB_SUCCESS;
00649     tagh           = 0;
00650     switch( var_data.varDataType )
00651     {
00652         case NC_BYTE:
00653         case NC_CHAR:
00654             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), num_lev, MB_TYPE_OPAQUE, tagh,
00655                                            MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00656             break;
00657         case NC_SHORT:
00658         case NC_INT:
00659             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), num_lev, MB_TYPE_INTEGER, tagh,
00660                                            MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00661             break;
00662         case NC_FLOAT:
00663         case NC_DOUBLE:
00664             rval = mbImpl->tag_get_handle( tag_name.str().c_str(), num_lev, MB_TYPE_DOUBLE, tagh,
00665                                            MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating tag " << tag_name.str() );
00666             break;
00667         default:
00668             MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << var_data.varName );
00669     }
00670 
00671     dbgOut.tprintf( 2, "Tag %s created\n", tag_name.str().c_str() );
00672 
00673     return rval;
00674 }
00675 
00676 ErrorCode NCHelper::create_attrib_string( const std::map< std::string, ReadNC::AttData >& attMap,
00677                                           std::string& attVal,
00678                                           std::vector< int >& attLen )
00679 {
00680     int success;
00681     std::stringstream ssAtt;
00682     unsigned int sz                                                = 0;
00683     std::map< std::string, ReadNC::AttData >::const_iterator attIt = attMap.begin();
00684     for( ; attIt != attMap.end(); ++attIt )
00685     {
00686         ssAtt << attIt->second.attName;
00687         ssAtt << '\0';
00688         void* attData = NULL;
00689         switch( attIt->second.attDataType )
00690         {
00691             case NC_BYTE:
00692             case NC_CHAR:
00693                 sz      = attIt->second.attLen;
00694                 attData = (char*)malloc( sz );
00695                 success = NCFUNC( get_att_text )( _fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
00696                                                   (char*)attData );
00697                 if( success )
00698                     MB_SET_ERR( MB_FAILURE, "Failed to read byte/char data for attribute " << attIt->second.attName );
00699                 ssAtt << "char;";
00700                 break;
00701             case NC_SHORT:
00702                 sz      = attIt->second.attLen * sizeof( short );
00703                 attData = (short*)malloc( sz );
00704                 success = NCFUNC( get_att_short )( _fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
00705                                                    (short*)attData );
00706                 if( success )
00707                     MB_SET_ERR( MB_FAILURE, "Failed to read short data for attribute " << attIt->second.attName );
00708                 ssAtt << "short;";
00709                 break;
00710             case NC_INT:
00711                 sz      = attIt->second.attLen * sizeof( int );
00712                 attData = (int*)malloc( sz );
00713                 success = NCFUNC( get_att_int )( _fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
00714                                                  (int*)attData );
00715                 if( success )
00716                     MB_SET_ERR( MB_FAILURE, "Failed to read int data for attribute " << attIt->second.attName );
00717                 ssAtt << "int;";
00718                 break;
00719             case NC_FLOAT:
00720                 sz      = attIt->second.attLen * sizeof( float );
00721                 attData = (float*)malloc( sz );
00722                 success = NCFUNC( get_att_float )( _fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
00723                                                    (float*)attData );
00724                 if( success )
00725                     MB_SET_ERR( MB_FAILURE, "Failed to read float data for attribute " << attIt->second.attName );
00726                 ssAtt << "float;";
00727                 break;
00728             case NC_DOUBLE:
00729                 sz      = attIt->second.attLen * sizeof( double );
00730                 attData = (double*)malloc( sz );
00731                 success = NCFUNC( get_att_double )( _fileId, attIt->second.attVarId, attIt->second.attName.c_str(),
00732                                                     (double*)attData );
00733                 if( success )
00734                     MB_SET_ERR( MB_FAILURE, "Failed to read double data for attribute " << attIt->second.attName );
00735                 ssAtt << "double;";
00736                 break;
00737             default:
00738                 MB_SET_ERR( MB_FAILURE, "Unexpected data type for attribute " << attIt->second.attName );
00739         }
00740         char* tmpc = (char*)attData;
00741         for( unsigned int counter = 0; counter != sz; ++counter )
00742             ssAtt << tmpc[counter];
00743         free( attData );
00744         ssAtt << ';';
00745         attLen.push_back( ssAtt.str().size() - 1 );
00746     }
00747     attVal = ssAtt.str();
00748 
00749     return MB_SUCCESS;
00750 }
00751 
00752 ErrorCode NCHelper::create_dummy_variables()
00753 {
00754     Interface*& mbImpl                                = _readNC->mbImpl;
00755     std::vector< std::string >& dimNames              = _readNC->dimNames;
00756     std::vector< int >& dimLens                       = _readNC->dimLens;
00757     std::map< std::string, ReadNC::VarData >& varInfo = _readNC->varInfo;
00758     DebugOutput& dbgOut                               = _readNC->dbgOut;
00759 
00760     // Hack: look at all dimensions, and see if we have one that does not appear in the list of
00761     // varInfo names Right now, candidates are from unstructured meshes, such as ncol (HOMME) and
00762     // nCells (MPAS) For each of them, create a dummy coordinate variable with a sparse tag to store
00763     // the dimension length
00764     for( unsigned int i = 0; i < dimNames.size(); i++ )
00765     {
00766         // If there is a variable with this dimension name, skip
00767         if( varInfo.find( dimNames[i] ) != varInfo.end() ) continue;
00768 
00769         // Create a dummy coordinate variable
00770         int sizeTotalVar = varInfo.size();
00771         std::string var_name( dimNames[i] );
00772         ReadNC::VarData& data = varInfo[var_name];
00773         data.varName          = var_name;
00774         data.varId            = sizeTotalVar;
00775         data.varTags.resize( 1, 0 );
00776         data.varDataType = NC_INT;
00777         data.varDims.resize( 1 );
00778         data.varDims[0] = (int)i;
00779         data.numAtts    = 0;
00780         data.entLoc     = ReadNC::ENTLOCSET;
00781         dummyVarNames.insert( var_name );
00782         dbgOut.tprintf( 2, "Dummy coordinate variable created for dimension %s\n", var_name.c_str() );
00783 
00784         // Create a corresponding sparse tag
00785         Tag tagh;
00786         ErrorCode rval = mbImpl->tag_get_handle( var_name.c_str(), 0, MB_TYPE_INTEGER, tagh,
00787                                                  MB_TAG_CREAT | MB_TAG_SPARSE | MB_TAG_VARLEN );MB_CHK_SET_ERR( rval, "Trouble creating tag for dummy coordinate variable " << var_name );
00788 
00789         // Tag value is the dimension length
00790         const void* ptr = &dimLens[i];
00791         // Tag size is 1
00792         int size = 1;
00793         rval     = mbImpl->tag_set_by_ptr( tagh, &_fileSet, 1, &ptr, &size );MB_CHK_SET_ERR( rval, "Trouble setting tag data for dummy coordinate variable " << var_name );
00794 
00795         dbgOut.tprintf( 2, "Sparse tag created for dimension %s\n", var_name.c_str() );
00796     }
00797 
00798     return MB_SUCCESS;
00799 }
00800 
00801 ErrorCode NCHelper::read_variables_to_set_allocate( std::vector< ReadNC::VarData >& vdatas,
00802                                                     std::vector< int >& tstep_nums )
00803 {
00804     std::vector< int >& dimLens = _readNC->dimLens;
00805     DebugOutput& dbgOut         = _readNC->dbgOut;
00806 
00807     ErrorCode rval = MB_SUCCESS;
00808 
00809     for( unsigned int i = 0; i < vdatas.size(); i++ )
00810     {
00811         // Set up readStarts and readCounts
00812         if( vdatas[i].has_tsteps )
00813         {
00814             // First: time
00815             vdatas[i].readStarts.push_back( 0 );  // This value is timestep dependent, will be set later
00816             vdatas[i].readCounts.push_back( 1 );
00817 
00818             // Next: other dimensions
00819             for( unsigned int idx = 1; idx != vdatas[i].varDims.size(); idx++ )
00820             {
00821                 vdatas[i].readStarts.push_back( 0 );
00822                 vdatas[i].readCounts.push_back( dimLens[vdatas[i].varDims[idx]] );
00823             }
00824         }
00825         else
00826         {
00827             if( vdatas[i].varDims.empty() )
00828             {
00829                 // Scalar variable
00830                 vdatas[i].readStarts.push_back( 0 );
00831                 vdatas[i].readCounts.push_back( 1 );
00832             }
00833             else
00834             {
00835                 for( unsigned int idx = 0; idx != vdatas[i].varDims.size(); idx++ )
00836                 {
00837                     vdatas[i].readStarts.push_back( 0 );
00838                     vdatas[i].readCounts.push_back( dimLens[vdatas[i].varDims[idx]] );
00839                 }
00840             }
00841         }
00842 
00843         // Get variable size
00844         vdatas[i].sz = 1;
00845         for( std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++ )
00846             vdatas[i].sz *= vdatas[i].readCounts[idx];
00847 
00848         // Note, for set variables without timesteps, loop one time and then break
00849         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
00850         {
00851             dbgOut.tprintf( 2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t] );
00852 
00853             if( tstep_nums[t] >= dimLens[tDim] )
00854             {
00855                 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t] );
00856             }
00857 
00858             // Get the tag to read into
00859             if( !vdatas[i].varTags[t] )
00860             {
00861                 rval = get_tag_to_set( vdatas[i], tstep_nums[t], vdatas[i].varTags[t] );MB_CHK_SET_ERR( rval, "Trouble getting tag to set variable " << vdatas[i].varName );
00862             }
00863 
00864             switch( vdatas[i].varDataType )
00865             {
00866                 case NC_BYTE:
00867                 case NC_CHAR:
00868                     vdatas[i].varDatas[t] = new char[vdatas[i].sz];
00869                     break;
00870                 case NC_SHORT:
00871                 case NC_INT:
00872                     vdatas[i].varDatas[t] = new int[vdatas[i].sz];
00873                     break;
00874                 case NC_FLOAT:
00875                 case NC_DOUBLE:
00876                     vdatas[i].varDatas[t] = new double[vdatas[i].sz];
00877                     break;
00878                 default:
00879                     MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
00880             }
00881 
00882             // Loop continues only for set variables with timesteps, e.g. xtime(Time) or xtime(Time,
00883             // StrLen)
00884             if( !vdatas[i].has_tsteps ) break;
00885         }
00886     }
00887 
00888     return rval;
00889 }
00890 
00891 ErrorCode ScdNCHelper::check_existing_mesh()
00892 {
00893     Interface*& mbImpl = _readNC->mbImpl;
00894 
00895     // Get the number of vertices
00896     int num_verts;
00897     ErrorCode rval = mbImpl->get_number_entities_by_dimension( _fileSet, 0, num_verts );MB_CHK_SET_ERR( rval, "Trouble getting number of vertices" );
00898 
00899     /*
00900     // Check against parameters
00901     // When ghosting is used, this check might fail (to be updated later)
00902     if (num_verts > 0) {
00903       int expected_verts = (lDims[3] - lDims[0] + 1) * (lDims[4] - lDims[1] + 1) * (-1 == lDims[2] ?
00904     1 : lDims[5] - lDims[2] + 1); if (num_verts != expected_verts) { MB_SET_ERR(MB_FAILURE, "Number
00905     of vertices doesn't match");
00906       }
00907     }
00908     */
00909 
00910     // Check the number of elements too
00911     int num_elems;
00912     rval = mbImpl->get_number_entities_by_dimension( _fileSet, ( -1 == lCDims[2] ? 2 : 3 ), num_elems );MB_CHK_SET_ERR( rval, "Trouble getting number of elements" );
00913 
00914     /*
00915     // Check against parameters
00916     // When ghosting is used, this check might fail (to be updated later)
00917     if (num_elems > 0) {
00918       int expected_elems = (lCDims[3] - lCDims[0] + 1) * (lCDims[4] - lCDims[1] + 1) * (-1 ==
00919     lCDims[2] ? 1 : (lCDims[5] - lCDims[2] + 1)); if (num_elems != expected_elems) {
00920         MB_SET_ERR(MB_FAILURE, "Number of elements doesn't match");
00921       }
00922     }
00923     */
00924 
00925     return MB_SUCCESS;
00926 }
00927 
00928 ErrorCode ScdNCHelper::create_mesh( Range& faces )
00929 {
00930     Interface*& mbImpl      = _readNC->mbImpl;
00931     Tag& mGlobalIdTag       = _readNC->mGlobalIdTag;
00932     const Tag*& mpFileIdTag = _readNC->mpFileIdTag;
00933     DebugOutput& dbgOut     = _readNC->dbgOut;
00934     ScdInterface* scdi      = _readNC->scdi;
00935     ScdParData& parData     = _readNC->parData;
00936 
00937     Range tmp_range;
00938     ScdBox* scd_box;
00939 
00940     ErrorCode rval =
00941         scdi->construct_box( HomCoord( lDims[0], lDims[1], lDims[2], 1 ), HomCoord( lDims[3], lDims[4], lDims[5], 1 ),
00942                              NULL, 0, scd_box, locallyPeriodic, &parData, true );MB_CHK_SET_ERR( rval, "Trouble creating scd vertex sequence" );
00943 
00944     // Add verts to tmp_range first, so we can duplicate global ids in vertex ids
00945     tmp_range.insert( scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1 );
00946 
00947     if( mpFileIdTag )
00948     {
00949         int count;
00950         void* data;
00951         rval = mbImpl->tag_iterate( *mpFileIdTag, tmp_range.begin(), tmp_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate file ID tag on local vertices" );
00952         assert( count == scd_box->num_vertices() );
00953         int* fid_data = (int*)data;
00954         rval          = mbImpl->tag_iterate( mGlobalIdTag, tmp_range.begin(), tmp_range.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate global ID tag on local vertices" );
00955         assert( count == scd_box->num_vertices() );
00956         int* gid_data = (int*)data;
00957         for( int i = 0; i < count; i++ )
00958             fid_data[i] = gid_data[i];
00959     }
00960 
00961     // Then add box set and elements to the range, then to the file set
00962     tmp_range.insert( scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1 );
00963     tmp_range.insert( scd_box->box_set() );
00964     rval = mbImpl->add_entities( _fileSet, tmp_range );MB_CHK_SET_ERR( rval, "Couldn't add new vertices to current file set" );
00965 
00966     dbgOut.tprintf( 1, "scdbox %d quads, %d vertices\n", scd_box->num_elements(), scd_box->num_vertices() );
00967 
00968     // Set the vertex coordinates
00969     double *xc, *yc, *zc;
00970     rval = scd_box->get_coordinate_arrays( xc, yc, zc );MB_CHK_SET_ERR( rval, "Couldn't get vertex coordinate arrays" );
00971 
00972     int i, j, k, il, jl, kl;
00973     int dil = lDims[3] - lDims[0] + 1;
00974     int djl = lDims[4] - lDims[1] + 1;
00975     assert( dil == (int)ilVals.size() && djl == (int)jlVals.size() &&
00976             ( -1 == lDims[2] || lDims[5] - lDims[2] + 1 == (int)levVals.size() ) );
00977 
00978     for( kl = lDims[2]; kl <= lDims[5]; kl++ )
00979     {
00980         k = kl - lDims[2];
00981         for( jl = lDims[1]; jl <= lDims[4]; jl++ )
00982         {
00983             j = jl - lDims[1];
00984             for( il = lDims[0]; il <= lDims[3]; il++ )
00985             {
00986                 i                = il - lDims[0];
00987                 unsigned int pos = i + j * dil + k * dil * djl;
00988                 xc[pos]          = ilVals[i];
00989                 yc[pos]          = jlVals[j];
00990                 zc[pos]          = ( -1 == lDims[2] ? 0.0 : levVals[k] );
00991             }
00992         }
00993     }
00994 
00995 #ifndef NDEBUG
00996     int num_verts =
00997         ( lDims[3] - lDims[0] + 1 ) * ( lDims[4] - lDims[1] + 1 ) * ( -1 == lDims[2] ? 1 : lDims[5] - lDims[2] + 1 );
00998     std::vector< int > gids( num_verts );
00999     Range verts( scd_box->start_vertex(), scd_box->start_vertex() + scd_box->num_vertices() - 1 );
01000     rval = mbImpl->tag_get_data( mGlobalIdTag, verts, &gids[0] );MB_CHK_SET_ERR( rval, "Trouble getting local gid values of vertices" );
01001     int vmin = *( std::min_element( gids.begin(), gids.end() ) ),
01002         vmax = *( std::max_element( gids.begin(), gids.end() ) );
01003     dbgOut.tprintf( 1, "Vertex gids %d-%d\n", vmin, vmax );
01004 #endif
01005 
01006     // Add elements to the range passed in
01007     faces.insert( scd_box->start_element(), scd_box->start_element() + scd_box->num_elements() - 1 );
01008 
01009     if( 2 <= dbgOut.get_verbosity() )
01010     {
01011         assert( scd_box->boundary_complete() );
01012         EntityHandle dum_ent = scd_box->start_element();
01013         rval                 = mbImpl->list_entities( &dum_ent, 1 );MB_CHK_SET_ERR( rval, "Trouble listing first hex" );
01014 
01015         std::vector< EntityHandle > connect;
01016         rval = mbImpl->get_connectivity( &dum_ent, 1, connect );MB_CHK_SET_ERR( rval, "Trouble getting connectivity" );
01017 
01018         rval = mbImpl->list_entities( &connect[0], connect.size() );MB_CHK_SET_ERR( rval, "Trouble listing element connectivity" );
01019     }
01020 
01021     Range edges;
01022     mbImpl->get_adjacencies( faces, 1, true, edges, Interface::UNION );
01023 
01024     // Create COORDS tag for quads
01025     rval = create_quad_coordinate_tag();MB_CHK_SET_ERR( rval, "Trouble creating COORDS tag for quads" );
01026 
01027     return MB_SUCCESS;
01028 }
01029 
01030 ErrorCode ScdNCHelper::read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums )
01031 {
01032     std::vector< ReadNC::VarData > vdatas;
01033     std::vector< ReadNC::VarData > vsetdatas;
01034 
01035     ErrorCode rval = read_variables_setup( var_names, tstep_nums, vdatas, vsetdatas );MB_CHK_SET_ERR( rval, "Trouble setting up to read variables" );
01036 
01037     if( !vsetdatas.empty() )
01038     {
01039         rval = read_variables_to_set( vsetdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble reading variables to set" );
01040     }
01041 
01042     if( !vdatas.empty() )
01043     {
01044         rval = read_scd_variables_to_nonset( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble reading variables to verts/edges/faces" );
01045     }
01046 
01047     return MB_SUCCESS;
01048 }
01049 
01050 ErrorCode ScdNCHelper::read_scd_variables_to_nonset_allocate( std::vector< ReadNC::VarData >& vdatas,
01051                                                               std::vector< int >& tstep_nums )
01052 {
01053     Interface*& mbImpl          = _readNC->mbImpl;
01054     std::vector< int >& dimLens = _readNC->dimLens;
01055     DebugOutput& dbgOut         = _readNC->dbgOut;
01056 
01057     Range* range = NULL;
01058 
01059     // Get vertices
01060     Range verts;
01061     ErrorCode rval = mbImpl->get_entities_by_dimension( _fileSet, 0, verts );MB_CHK_SET_ERR( rval, "Trouble getting vertices in current file set" );
01062     assert( "Should only have a single vertex subrange, since they were read in one shot" && verts.psize() == 1 );
01063 
01064     Range edges;
01065     rval = mbImpl->get_entities_by_dimension( _fileSet, 1, edges );MB_CHK_SET_ERR( rval, "Trouble getting edges in current file set" );
01066 
01067     // Get faces
01068     Range faces;
01069     rval = mbImpl->get_entities_by_dimension( _fileSet, 2, faces );MB_CHK_SET_ERR( rval, "Trouble getting faces in current file set" );
01070     assert( "Should only have a single face subrange, since they were read in one shot" && faces.psize() == 1 );
01071 
01072 #ifdef MOAB_HAVE_MPI
01073     moab::Range faces_owned;
01074     bool& isParallel = _readNC->isParallel;
01075     if( isParallel )
01076     {
01077         ParallelComm*& myPcomm = _readNC->myPcomm;
01078         rval                   = myPcomm->filter_pstatus( faces, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &faces_owned );MB_CHK_SET_ERR( rval, "Trouble getting owned faces in current file set" );
01079     }
01080     else
01081         faces_owned = faces;  // Not running in parallel, but still with MPI
01082 #endif
01083 
01084     for( unsigned int i = 0; i < vdatas.size(); i++ )
01085     {
01086         // Support non-set variables with 4 dimensions like (time, lev, lat, lon)
01087         assert( 4 == vdatas[i].varDims.size() );
01088 
01089         // For a non-set variable, time should be the first dimension
01090         assert( tDim == vdatas[i].varDims[0] );
01091 
01092         // Set up readStarts and readCounts
01093         vdatas[i].readStarts.resize( 4 );
01094         vdatas[i].readCounts.resize( 4 );
01095 
01096         // First: time
01097         vdatas[i].readStarts[0] = 0;  // This value is timestep dependent, will be set later
01098         vdatas[i].readCounts[0] = 1;
01099 
01100         // Next: lev
01101         vdatas[i].readStarts[1] = 0;
01102         vdatas[i].readCounts[1] = vdatas[i].numLev;
01103 
01104         // Finally: lat (or slat) and lon (or slon)
01105         switch( vdatas[i].entLoc )
01106         {
01107             case ReadNC::ENTLOCVERT:
01108                 // Vertices
01109                 vdatas[i].readStarts[2] = lDims[1];
01110                 vdatas[i].readCounts[2] = lDims[4] - lDims[1] + 1;
01111                 vdatas[i].readStarts[3] = lDims[0];
01112                 vdatas[i].readCounts[3] = lDims[3] - lDims[0] + 1;
01113                 range                   = &verts;
01114                 break;
01115             case ReadNC::ENTLOCNSEDGE:
01116             case ReadNC::ENTLOCEWEDGE:
01117             case ReadNC::ENTLOCEDGE:
01118                 // Not implemented yet, set a global error
01119                 MB_SET_GLB_ERR( MB_NOT_IMPLEMENTED, "Reading edge data is not implemented yet" );
01120             case ReadNC::ENTLOCFACE:
01121                 // Faces
01122                 vdatas[i].readStarts[2] = lCDims[1];
01123                 vdatas[i].readCounts[2] = lCDims[4] - lCDims[1] + 1;
01124                 vdatas[i].readStarts[3] = lCDims[0];
01125                 vdatas[i].readCounts[3] = lCDims[3] - lCDims[0] + 1;
01126 #ifdef MOAB_HAVE_MPI
01127                 range = &faces_owned;
01128 #else
01129                 range = &faces;
01130 #endif
01131                 break;
01132             default:
01133                 MB_SET_ERR( MB_FAILURE, "Unexpected entity location type for variable " << vdatas[i].varName );
01134         }
01135 
01136         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
01137         {
01138             dbgOut.tprintf( 2, "Reading variable %s, time step %d\n", vdatas[i].varName.c_str(), tstep_nums[t] );
01139 
01140             if( tstep_nums[t] >= dimLens[tDim] )
01141             {
01142                 MB_SET_ERR( MB_INDEX_OUT_OF_RANGE, "Wrong value for timestep number " << tstep_nums[t] );
01143             }
01144 
01145             // Get the tag to read into
01146             if( !vdatas[i].varTags[t] )
01147             {
01148                 rval = get_tag_to_nonset( vdatas[i], tstep_nums[t], vdatas[i].varTags[t], vdatas[i].numLev );MB_CHK_SET_ERR( rval, "Trouble getting tag to non-set variable " << vdatas[i].varName );
01149             }
01150 
01151             // Get ptr to tag space
01152             void* data;
01153             int count;
01154             rval = mbImpl->tag_iterate( vdatas[i].varTags[t], range->begin(), range->end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate tag for non-set variable " << vdatas[i].varName );
01155             assert( (unsigned)count == range->size() );
01156             vdatas[i].varDatas[t] = data;
01157         }
01158 
01159         // Get variable size
01160         vdatas[i].sz = 1;
01161         for( std::size_t idx = 0; idx != vdatas[i].readCounts.size(); idx++ )
01162             vdatas[i].sz *= vdatas[i].readCounts[idx];
01163     }
01164 
01165     return rval;
01166 }
01167 
01168 ErrorCode ScdNCHelper::read_scd_variables_to_nonset( std::vector< ReadNC::VarData >& vdatas,
01169                                                      std::vector< int >& tstep_nums )
01170 {
01171     DebugOutput& dbgOut = _readNC->dbgOut;
01172 
01173     ErrorCode rval = read_scd_variables_to_nonset_allocate( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble allocating space to read non-set variables" );
01174 
01175     // Finally, read into that space
01176     int success;
01177     for( unsigned int i = 0; i < vdatas.size(); i++ )
01178     {
01179         std::size_t sz = vdatas[i].sz;
01180 
01181         // A typical supported variable: float T(time, lev, lat, lon)
01182         // For tag values, need transpose (lev, lat, lon) to (lat, lon, lev)
01183         size_t ni = vdatas[i].readCounts[3];  // lon or slon
01184         size_t nj = vdatas[i].readCounts[2];  // lat or slat
01185         size_t nk = vdatas[i].readCounts[1];  // lev
01186 
01187         for( unsigned int t = 0; t < tstep_nums.size(); t++ )
01188         {
01189             // Tag data for this timestep
01190             void* data = vdatas[i].varDatas[t];
01191 
01192             // Set readStart for each timestep along time dimension
01193             vdatas[i].readStarts[0] = tstep_nums[t];
01194 
01195             switch( vdatas[i].varDataType )
01196             {
01197                 case NC_BYTE:
01198                 case NC_CHAR: {
01199                     std::vector< char > tmpchardata( sz );
01200                     success = NCFUNCAG( _vara_text )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
01201                                                       &vdatas[i].readCounts[0], &tmpchardata[0] );
01202                     if( success )
01203                         MB_SET_ERR( MB_FAILURE, "Failed to read byte/char data for variable " << vdatas[i].varName );
01204                     if( vdatas[i].numLev > 1 )
01205                         // Transpose (lev, lat, lon) to (lat, lon, lev)
01206                         kji_to_jik( ni, nj, nk, data, &tmpchardata[0] );
01207                     else
01208                     {
01209                         for( std::size_t idx = 0; idx != tmpchardata.size(); idx++ )
01210                             ( (char*)data )[idx] = tmpchardata[idx];
01211                     }
01212                     break;
01213                 }
01214                 case NC_SHORT:
01215                 case NC_INT: {
01216                     std::vector< int > tmpintdata( sz );
01217                     success = NCFUNCAG( _vara_int )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
01218                                                      &vdatas[i].readCounts[0], &tmpintdata[0] );
01219                     if( success )
01220                         MB_SET_ERR( MB_FAILURE, "Failed to read short/int data for variable " << vdatas[i].varName );
01221                     if( vdatas[i].numLev > 1 )
01222                         // Transpose (lev, lat, lon) to (lat, lon, lev)
01223                         kji_to_jik( ni, nj, nk, data, &tmpintdata[0] );
01224                     else
01225                     {
01226                         for( std::size_t idx = 0; idx != tmpintdata.size(); idx++ )
01227                             ( (int*)data )[idx] = tmpintdata[idx];
01228                     }
01229                     break;
01230                 }
01231                 case NC_FLOAT:
01232                 case NC_DOUBLE: {
01233                     std::vector< double > tmpdoubledata( sz );
01234                     success = NCFUNCAG( _vara_double )( _fileId, vdatas[i].varId, &vdatas[i].readStarts[0],
01235                                                         &vdatas[i].readCounts[0], &tmpdoubledata[0] );
01236                     if( success )
01237                         MB_SET_ERR( MB_FAILURE, "Failed to read float/double data for variable " << vdatas[i].varName );
01238                     if( vdatas[i].numLev > 1 )
01239                         // Transpose (lev, lat, lon) to (lat, lon, lev)
01240                         kji_to_jik( ni, nj, nk, data, &tmpdoubledata[0] );
01241                     else
01242                     {
01243                         for( std::size_t idx = 0; idx != tmpdoubledata.size(); idx++ )
01244                             ( (double*)data )[idx] = tmpdoubledata[idx];
01245                     }
01246                     break;
01247                 }
01248                 default:
01249                     MB_SET_ERR( MB_FAILURE, "Unexpected data type for variable " << vdatas[i].varName );
01250             }
01251         }
01252     }
01253 
01254     // Debug output, if requested
01255     if( 1 == dbgOut.get_verbosity() )
01256     {
01257         dbgOut.printf( 1, "Read variables: %s", vdatas.begin()->varName.c_str() );
01258         for( unsigned int i = 1; i < vdatas.size(); i++ )
01259             dbgOut.printf( 1, ", %s ", vdatas[i].varName.c_str() );
01260         dbgOut.tprintf( 1, "\n" );
01261     }
01262 
01263     return rval;
01264 }
01265 
01266 ErrorCode ScdNCHelper::create_quad_coordinate_tag()
01267 {
01268     Interface*& mbImpl = _readNC->mbImpl;
01269 
01270     Range ents;
01271     ErrorCode rval = mbImpl->get_entities_by_type( _fileSet, moab::MBQUAD, ents );MB_CHK_SET_ERR( rval, "Trouble getting quads" );
01272 
01273     std::size_t numOwnedEnts = 0;
01274 #ifdef MOAB_HAVE_MPI
01275     Range ents_owned;
01276     bool& isParallel = _readNC->isParallel;
01277     if( isParallel )
01278     {
01279         ParallelComm*& myPcomm = _readNC->myPcomm;
01280         rval                   = myPcomm->filter_pstatus( ents, PSTATUS_NOT_OWNED, PSTATUS_NOT, -1, &ents_owned );MB_CHK_SET_ERR( rval, "Trouble getting owned quads" );
01281         numOwnedEnts = ents_owned.size();
01282     }
01283     else
01284     {
01285         numOwnedEnts = ents.size();
01286         ents_owned   = ents;
01287     }
01288 #else
01289     numOwnedEnts = ents.size();
01290 #endif
01291 
01292     if( numOwnedEnts == 0 ) return MB_SUCCESS;
01293 
01294     assert( numOwnedEnts == ilCVals.size() * jlCVals.size() );
01295     std::vector< double > coords( numOwnedEnts * 3 );
01296     std::size_t pos = 0;
01297     for( std::size_t j = 0; j != jlCVals.size(); ++j )
01298     {
01299         for( std::size_t i = 0; i != ilCVals.size(); ++i )
01300         {
01301             pos             = j * ilCVals.size() * 3 + i * 3;
01302             coords[pos]     = ilCVals[i];
01303             coords[pos + 1] = jlCVals[j];
01304             coords[pos + 2] = 0.0;
01305         }
01306     }
01307     std::string tag_name = "COORDS";
01308     Tag tagh             = 0;
01309     rval = mbImpl->tag_get_handle( tag_name.c_str(), 3, MB_TYPE_DOUBLE, tagh, MB_TAG_DENSE | MB_TAG_CREAT );MB_CHK_SET_ERR( rval, "Trouble creating COORDS tag" );
01310 
01311     void* data;
01312     int count;
01313 #ifdef MOAB_HAVE_MPI
01314     rval = mbImpl->tag_iterate( tagh, ents_owned.begin(), ents_owned.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate COORDS tag on quads" );
01315 #else
01316     rval = mbImpl->tag_iterate( tagh, ents.begin(), ents.end(), count, data );MB_CHK_SET_ERR( rval, "Failed to iterate COORDS tag on quads" );
01317 #endif
01318     assert( count == (int)numOwnedEnts );
01319     double* quad_data = (double*)data;
01320     std::copy( coords.begin(), coords.end(), quad_data );
01321 
01322     return MB_SUCCESS;
01323 }
01324 
01325 ErrorCode UcdNCHelper::read_variables( std::vector< std::string >& var_names, std::vector< int >& tstep_nums )
01326 {
01327     std::vector< ReadNC::VarData > vdatas;
01328     std::vector< ReadNC::VarData > vsetdatas;
01329 
01330     ErrorCode rval = read_variables_setup( var_names, tstep_nums, vdatas, vsetdatas );MB_CHK_SET_ERR( rval, "Trouble setting up to read variables" );
01331 
01332     if( !vsetdatas.empty() )
01333     {
01334         rval = read_variables_to_set( vsetdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble reading variables to set" );
01335     }
01336 
01337     if( !vdatas.empty() )
01338     {
01339 #ifdef MOAB_HAVE_PNETCDF
01340         // With pnetcdf support, we will use async read
01341         rval = read_ucd_variables_to_nonset_async( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble reading variables to verts/edges/faces" );
01342 #else
01343         // Without pnetcdf support, we will use old read
01344         rval = read_ucd_variables_to_nonset( vdatas, tstep_nums );MB_CHK_SET_ERR( rval, "Trouble reading variables to verts/edges/faces" );
01345 #endif
01346     }
01347 
01348     return MB_SUCCESS;
01349 }
01350 
01351 static double tolerance = 1.e-12;
01352 // Used to put points in an STL tree-based container
01353 bool NCHelper::Node3D::operator<( const NCHelper::Node3D& other ) const
01354 {
01355     if( coords[0] <= other.coords[0] - tolerance )
01356         return true;
01357     else if( coords[0] >= other.coords[0] + tolerance )
01358         return false;
01359     if( coords[1] <= other.coords[1] - tolerance )
01360         return true;
01361     else if( coords[1] >= other.coords[1] + tolerance )
01362         return false;
01363     if( coords[2] <= other.coords[2] - tolerance )
01364         return true;
01365     else if( coords[0] >= other.coords[0] + tolerance )
01366         return false;
01367 
01368     return false;
01369 }
01370 /*bool NCHelper::Node3D::operator == ( const NCHelper::Node3D& other ) const
01371      return ( !(*this < other) && ! ( other < *this) ) ;*/
01372 }  // namespace moab
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines