Mesh Oriented datABase  (version 5.4.1)
Array-based unstructured mesh datastructure
moab::NCWriteHelper Class Reference

#include <NCWriteHelper.hpp>

+ Inheritance diagram for moab::NCWriteHelper:
+ Collaboration diagram for moab::NCWriteHelper:

Public Member Functions

 NCWriteHelper (WriteNC *writeNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
virtual ~NCWriteHelper ()
virtual ErrorCode collect_mesh_info ()=0
 Collect necessary info about local mesh (implemented in child classes)
virtual ErrorCode collect_variable_data (std::vector< std::string > &var_names, std::vector< int > &tstep_nums)
 Collect data for specified variables (partially implemented in child classes)
ErrorCode init_file (std::vector< std::string > &var_names, std::vector< std::string > &desired_names, bool _append)
 Initialize file: this is where all defines are done The VarData dimension ids are filled up after define.
ErrorCode write_values (std::vector< std::string > &var_names, std::vector< int > &tstep_nums)
 Take the info from VarData and write first non-set variables, then set variables.

Static Public Member Functions

static NCWriteHelperget_nc_helper (WriteNC *writeNC, int fileId, const FileOptions &opts, EntityHandle fileSet)
 Get appropriate helper instance for WriteNC class based on some info in the file set.

Protected Member Functions

virtual ErrorCode write_nonset_variables (std::vector< WriteNC::VarData > &vdatas, std::vector< int > &tstep_nums)=0

Protected Attributes

WriteNC_writeNC
 Allow NCWriteHelper to directly access members of WriteNC.
int _fileId
 Cache some information from WriteNC.
const FileOptions_opts
EntityHandle _fileSet
int nTimeSteps
 Dimensions of time and level.
int nLevels
int tDim
 Dimension numbers for time and level.
int levDim
Range localCellsOwned
 Local owned cells, edges and vertices.
Range localEdgesOwned
Range localVertsOwned
std::vector< double > timeStepVals
 Time values of output timesteps.

Private Member Functions

ErrorCode write_set_variables (std::vector< WriteNC::VarData > &vsetdatas, std::vector< int > &tstep_nums)

Detailed Description

Definition at line 22 of file NCWriteHelper.hpp.


Constructor & Destructor Documentation

moab::NCWriteHelper::NCWriteHelper ( WriteNC writeNC,
int  fileId,
const FileOptions opts,
EntityHandle  fileSet 
) [inline]

Definition at line 25 of file NCWriteHelper.hpp.

        : _writeNC( writeNC ), _fileId( fileId ), _opts( opts ), _fileSet( fileSet ), nTimeSteps( 0 ), nLevels( 1 ),
          tDim( -1 ), levDim( -1 )
    {
    }
virtual moab::NCWriteHelper::~NCWriteHelper ( ) [inline, virtual]

Definition at line 30 of file NCWriteHelper.hpp.

{};

Member Function Documentation

Collect necessary info about local mesh (implemented in child classes)

Implemented in moab::ScdNCWriteHelper, moab::NCWriteGCRM, moab::NCWriteHOMME, and moab::NCWriteMPAS.

Referenced by moab::WriteNC::write_file().

ErrorCode moab::NCWriteHelper::collect_variable_data ( std::vector< std::string > &  var_names,
std::vector< int > &  tstep_nums 
) [virtual]

Collect data for specified variables (partially implemented in child classes)

Reimplemented in moab::ScdNCWriteHelper, moab::NCWriteGCRM, moab::NCWriteHOMME, and moab::NCWriteMPAS.

Definition at line 51 of file NCWriteHelper.cpp.

References _fileSet, _writeNC, moab::WriteNC::dbgOut, moab::WriteNC::dimLens, moab::WriteNC::dimNames, moab::WriteNC::dummyVarNames, moab::WriteNC::VarData::entLoc, moab::WriteNC::ENTLOCSET, ErrorCode, moab::WriteNC::VarData::has_tsteps, levDim, MB_CHK_SET_ERR, MB_NOT_IMPLEMENTED, MB_SET_ERR, MB_SUCCESS, MB_TYPE_INTEGER, moab::WriteNC::mbImpl, moab::WriteNC::VarData::memoryHogs, nLevels, nTimeSteps, moab::WriteNC::VarData::numLev, size, moab::WriteNC::VarData::sz, t, moab::Interface::tag_get_by_ptr(), moab::Interface::tag_get_data_type(), moab::Interface::tag_get_handle(), tDim, timeStepVals, moab::DebugOutput::tprintf(), moab::WriteNC::usedCoordinates, moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varDims, moab::WriteNC::varInfo, moab::WriteNC::VarData::varTags, moab::WriteNC::VarData::writeCounts, and moab::WriteNC::VarData::writeStarts.

Referenced by moab::WriteNC::write_file().

{
    Interface*& mbImpl                                 = _writeNC->mbImpl;
    std::vector< std::string >& dimNames               = _writeNC->dimNames;
    std::vector< int >& dimLens                        = _writeNC->dimLens;
    std::set< std::string >& usedCoordinates           = _writeNC->usedCoordinates;
    std::set< std::string >& dummyVarNames             = _writeNC->dummyVarNames;
    std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;
    DebugOutput& dbgOut                                = _writeNC->dbgOut;

    ErrorCode rval;

    usedCoordinates.clear();

    if( tstep_nums.empty() && nTimeSteps > 0 )
    {
        // No timesteps input, get them all
        for( int i = 0; i < nTimeSteps; i++ )
            tstep_nums.push_back( i );
    }

    for( size_t i = 0; i < var_names.size(); i++ )
    {
        std::string varname                                     = var_names[i];
        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( varname );
        if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find variable " << varname );

        WriteNC::VarData& currentVarData = vit->second;

        dbgOut.tprintf( 2, "    for variable %s varDims.size %d \n", varname.c_str(),
                        (int)currentVarData.varDims.size() );
        for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
        {
            std::string dimName = dimNames[currentVarData.varDims[j]];
            vit                 = varInfo.find( dimName );
            if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << dimName );

            usedCoordinates.insert( dimName );  // Collect those used, we will need to write them to the file
            dbgOut.tprintf( 2, "    for variable %s need dimension %s with length %d\n", varname.c_str(),
                            dimName.c_str(), dimLens[currentVarData.varDims[j]] );
        }

        // Process coordinate variables later
        if( usedCoordinates.find( varname ) != usedCoordinates.end() ) continue;

        // Default has_tsteps is false
        if( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), tDim ) !=
            currentVarData.varDims.end() )
            currentVarData.has_tsteps = true;

        // Default numLev is 0
        if( ( std::find( currentVarData.varDims.begin(), currentVarData.varDims.end(), levDim ) !=
              currentVarData.varDims.end() ) )
            currentVarData.numLev = nLevels;

        // Process set variables
        if( WriteNC::ENTLOCSET == currentVarData.entLoc )
        {
            if( currentVarData.has_tsteps )
            {
                // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
                // TBD
                MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" );
            }
            else
            {
                // Get the tag with varname
                Tag tag = 0;
                rval    = mbImpl->tag_get_handle( varname.c_str(), tag );MB_CHK_SET_ERR( rval, "Can't find tag " << varname );
                currentVarData.varTags.push_back( tag );  // Really, only one for these
                const void* data;
                int size;
                rval = mbImpl->tag_get_by_ptr( tag, &_fileSet, 1, &data, &size );MB_CHK_SET_ERR( rval, "Can't get data of tag " << varname );

                // Find the type of tag, and use it
                DataType type;
                rval = mbImpl->tag_get_data_type( tag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << varname );

                currentVarData.varDataType = NC_DOUBLE;
                if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;

                assert( 0 == currentVarData.memoryHogs.size() );  // Nothing so far
                currentVarData.memoryHogs.push_back( (void*)data );

                if( currentVarData.varDims.empty() )
                {
                    // Scalar variable
                    currentVarData.writeStarts.push_back( 0 );
                    currentVarData.writeCounts.push_back( 1 );
                }
                else
                {
                    for( size_t j = 0; j < currentVarData.varDims.size(); j++ )
                    {
                        currentVarData.writeStarts.push_back( 0 );
                        currentVarData.writeCounts.push_back( dimLens[currentVarData.varDims[j]] );
                    }
                }

                // Get variable size
                currentVarData.sz = 1;
                for( std::size_t idx = 0; idx != currentVarData.writeCounts.size(); idx++ )
                    currentVarData.sz *= currentVarData.writeCounts[idx];
            }
        }  // if (WriteNC::ENTLOCSET == currentVarData.entLoc)
        // Process non-set variables
        else
        {
            Tag indexedTag = 0;

            if( currentVarData.has_tsteps )
            {
                for( unsigned int t = 0; t < tstep_nums.size(); t++ )
                {
                    std::stringstream ssTagNameWithIndex;
                    ssTagNameWithIndex << varname << tstep_nums[t];
                    rval = mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag );MB_CHK_SET_ERR( rval, "Can't find tag " << ssTagNameWithIndex.str() );
                    dbgOut.tprintf( 2, "    found indexed tag %d with name %s\n", tstep_nums[t],
                                    ssTagNameWithIndex.str().c_str() );
                    currentVarData.varTags.push_back( indexedTag );
                }
            }
            else
            {
                // This should be a user-created non-set variable without timesteps
                // Treat it like having one, 0th, timestep
                std::stringstream ssTagNameWithIndex;
                ssTagNameWithIndex << varname << 0;
                rval = mbImpl->tag_get_handle( ssTagNameWithIndex.str().c_str(), indexedTag );MB_CHK_SET_ERR( rval, "Can't find tag " << ssTagNameWithIndex.str() << " for a user-created variable" );
                dbgOut.tprintf( 2, "    found indexed tag 0 with name %s\n", ssTagNameWithIndex.str().c_str() );
                currentVarData.varTags.push_back( indexedTag );
            }

            // The type of the tag is fixed though
            DataType type;
            rval = mbImpl->tag_get_data_type( indexedTag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << varname );

            currentVarData.varDataType = NC_DOUBLE;
            if( MB_TYPE_INTEGER == type ) currentVarData.varDataType = NC_INT;
        }
    }  // for (size_t i = 0; i < var_names.size(); i++)

    // Process coordinate variables here
    // Check that for used coordinates we have found the tags
    for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
    {
        const std::string& coordName = *setIt;

        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
        if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );

        WriteNC::VarData& varCoordData = vit->second;
        Tag coordTag                   = 0;
        rval                           = mbImpl->tag_get_handle( coordName.c_str(), coordTag );MB_CHK_SET_ERR( rval, "Can't find tag " << coordName );
        varCoordData.varTags.push_back( coordTag );  // Really, only one for these

        const void* data;
        int sizeCoordinate;
        rval = mbImpl->tag_get_by_ptr( coordTag, &_fileSet, 1, &data, &sizeCoordinate );MB_CHK_SET_ERR( rval, "Can't get coordinate values of " << coordName );
        dbgOut.tprintf( 2, "    found coordinate tag with name %s and length %d\n", coordName.c_str(), sizeCoordinate );

        // Find the type of tag, and use it
        DataType type;
        rval = mbImpl->tag_get_data_type( coordTag, type );MB_CHK_SET_ERR( rval, "Can't get data type of tag " << coordName );
        varCoordData.varDataType = NC_DOUBLE;
        if( MB_TYPE_INTEGER == type ) varCoordData.varDataType = NC_INT;

        // Get dimension length (the only dimension of this coordinate variable, with the same name)
        assert( 1 == varCoordData.varDims.size() );
        int coordDimLen = dimLens[varCoordData.varDims[0]];

        if( dummyVarNames.find( coordName ) != dummyVarNames.end() )
        {
            // For a dummy coordinate variable, the tag size is always 1
            // The number of coordinates should be set to dimension length, instead of 1
            assert( 1 == sizeCoordinate );
            sizeCoordinate = coordDimLen;

            // No variable data to write
            data = NULL;
        }
        else
        {
            // The number of coordinates should be exactly the same as dimension length
            // However, if timesteps spread across files and time tag has been updated,
            // sizeCoordinate will be larger
            if( varCoordData.varDims[0] != tDim ) assert( sizeCoordinate == coordDimLen );
        }

        // For time, the actual output size and values are determined by tstep_nums
        if( varCoordData.varDims[0] == tDim )
        {
            // Does not apply to dummy time tag (e.g. 'Time' tag of MPAS), when timesteps
            // spread across files
            if( NULL != data ) assert( tstep_nums.size() > 0 && tstep_nums.size() <= (size_t)sizeCoordinate );

            sizeCoordinate = tstep_nums.size();

            if( NULL != data )
            {
                assert( NC_DOUBLE == varCoordData.varDataType );
                timeStepVals.resize( sizeCoordinate );
                for( unsigned int t = 0; t < tstep_nums.size(); t++ )
                    timeStepVals[t] = ( (double*)data )[tstep_nums[t]];

                data = &timeStepVals[0];
            }
        }

        // This is the length
        varCoordData.sz = sizeCoordinate;
        varCoordData.writeStarts.resize( 1 );
        varCoordData.writeStarts[0] = 0;
        varCoordData.writeCounts.resize( 1 );
        varCoordData.writeCounts[0] = sizeCoordinate;

        assert( 0 == varCoordData.memoryHogs.size() );  // Nothing so far
        varCoordData.memoryHogs.push_back( (void*)data );
    }  // for (std::set<std::string>::iterator setIt ...

    return MB_SUCCESS;
}
NCWriteHelper * moab::NCWriteHelper::get_nc_helper ( WriteNC writeNC,
int  fileId,
const FileOptions opts,
EntityHandle  fileSet 
) [static]

Get appropriate helper instance for WriteNC class based on some info in the file set.

Get appropriate helper instance for WriteNC class; based on some info in the file set.

Definition at line 30 of file NCWriteHelper.cpp.

References moab::WriteNC::grid_type.

Referenced by moab::WriteNC::write_file().

{
    std::string& grid_type = writeNC->grid_type;
    if( grid_type == "CAM_EUL" )
        return new( std::nothrow ) NCWriteEuler( writeNC, fileId, opts, fileSet );
    else if( grid_type == "CAM_FV" )
        return new( std::nothrow ) NCWriteFV( writeNC, fileId, opts, fileSet );
    else if( grid_type == "CAM_SE" )
        return new( std::nothrow ) NCWriteHOMME( writeNC, fileId, opts, fileSet );
    else if( grid_type == "MPAS" )
        return new( std::nothrow ) NCWriteMPAS( writeNC, fileId, opts, fileSet );
    else if( grid_type == "GCRM" )
        return new( std::nothrow ) NCWriteGCRM( writeNC, fileId, opts, fileSet );

    // Unknown NetCDF grid
    return NULL;
}
ErrorCode moab::NCWriteHelper::init_file ( std::vector< std::string > &  var_names,
std::vector< std::string > &  desired_names,
bool  _append 
)

Initialize file: this is where all defines are done The VarData dimension ids are filled up after define.

Definition at line 274 of file NCWriteHelper.cpp.

References _fileId, _writeNC, moab::WriteNC::AttData::attDataType, moab::WriteNC::AttData::attLen, moab::WriteNC::AttData::attValue, moab::WriteNC::dbgOut, moab::WriteNC::dimNames, moab::WriteNC::dummyVarNames, moab::WriteNC::globalAtts, levDim, MB_SET_ERR, MB_SUCCESS, NCDF_SIZE, NCFUNC, moab::WriteNC::VarData::sz, tDim, moab::DebugOutput::tprintf(), moab::WriteNC::usedCoordinates, moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varDims, moab::WriteNC::VarData::varId, and moab::WriteNC::varInfo.

Referenced by moab::WriteNC::write_file().

{
    std::vector< std::string >& dimNames                  = _writeNC->dimNames;
    std::set< std::string >& usedCoordinates              = _writeNC->usedCoordinates;
    std::set< std::string >& dummyVarNames                = _writeNC->dummyVarNames;
    std::map< std::string, WriteNC::VarData >& varInfo    = _writeNC->varInfo;
    std::map< std::string, WriteNC::AttData >& globalAtts = _writeNC->globalAtts;
    DebugOutput& dbgOut                                   = _writeNC->dbgOut;

    int tDim_in_dimNames   = tDim;
    int levDim_in_dimNames = levDim;

    // If append mode, make sure we are in define mode; a simple open will not allow creation of new
    // variables
    if( append )
    {
        int errcode = NCFUNC( redef )( _fileId );
        if( errcode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Can't open file in redefine mode" );
    }

    // First initialize all coordinates, then fill VarData for actual variables (and dimensions)
    // Check that for used coordinates we have found the tags
    for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
    {
        const std::string& coordName = *setIt;

        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
        if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );

        WriteNC::VarData& varCoordData = vit->second;
        varCoordData.varDims.resize( 1 );

        // If not append, create it for sure
        // If append, we might already have it, including the tag / variable with the same name
        /*
         * int ncmpi_inq_dimid(int ncid, const char *name, int *idp);
         */
        if( append )
        {
            int dimId;
            if( NCFUNC( inq_dimid )( _fileId, coordName.c_str(), &dimId ) == NC_NOERR )
            {  // If not found, create it later
                varCoordData.varDims[0] = dimId;
                dbgOut.tprintf( 2, "    file already has coordName %s dim id is %d \n", coordName.c_str(),
                                (int)varCoordData.varDims[0] );

                // Update tDim and levDim to actual dimension id
                if( coordName == dimNames[tDim_in_dimNames] )
                    tDim = varCoordData.varDims[0];
                else if( coordName == dimNames[levDim_in_dimNames] )
                    levDim = varCoordData.varDims[0];

                // Skip dummy coordinate variables (e.g. ncol)
                if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;

                // Check that the coordinate is a variable too
                // Inquire for a variable with the same name
                int varId;
                if( NCFUNC( inq_varid )( _fileId, coordName.c_str(), &varId ) != NC_NOERR )
                    MB_SET_ERR( MB_FAILURE, "We do not have a variable with the same name " << coordName );
                // We should also check that this variable has one dimension, and it is dimId
                varCoordData.varId = varId;
                dbgOut.tprintf( 2, "    file already has coordinate %s and varId is %d \n", coordName.c_str(), varId );

                continue;  // Maybe more checks are needed here
            }
        }

        /* int nc_def_dim (int ncid, const char *name, size_t len, int *dimidp);
         * example:  status = nc_def_dim(fileId, "lat", 18L, &latid);
         */

        // Actually define a dimension
        if( NCFUNC( def_dim )( _fileId, coordName.c_str(), (size_t)varCoordData.sz, &varCoordData.varDims[0] ) !=
            NC_NOERR )
            MB_SET_ERR( MB_FAILURE, "Failed to generate dimension " << coordName );
        dbgOut.tprintf( 2, "    for coordName %s dim id is %d \n", coordName.c_str(), (int)varCoordData.varDims[0] );

        // Update tDim and levDim to actual dimension id
        if( coordName == dimNames[tDim_in_dimNames] )
            tDim = varCoordData.varDims[0];
        else if( coordName == dimNames[levDim_in_dimNames] )
            levDim = varCoordData.varDims[0];

        // Create a variable with the same name, and its only dimension the one we just defined
        /*
         * int nc_def_var (int ncid, const char *name, nc_type xtype,
                           int ndims, const int dimids[], int *varidp);
           example:
         http://www.unidata.ucar.edu/software/netcdf/docs/netcdf-c/nc_005fdef_005fvar.html#nc_005fdef_005fvar
         */

        // Skip dummy coordinate variables (e.g. ncol)
        if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;

        // Define a coordinate variable
        if( NCFUNC( def_var )( _fileId, coordName.c_str(), varCoordData.varDataType, 1, &( varCoordData.varDims[0] ),
                               &varCoordData.varId ) != NC_NOERR )
            MB_SET_ERR( MB_FAILURE, "Failed to create coordinate variable " << coordName );

        dbgOut.tprintf( 2, "    for coordName %s variable id is %d \n", coordName.c_str(), varCoordData.varId );
    }

    // Now look at requested variables, and update from the index in dimNames to the actual
    // dimension id
    for( size_t i = 0; i < var_names.size(); i++ )
    {
        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
        if( vit == varInfo.end() ) MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] );

        // Skip coordinate variables
        if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;

        WriteNC::VarData& variableData = vit->second;

        // The index is for dimNames; we need to find out the actual dimension id (from above)
        int numDims = (int)variableData.varDims.size();
        for( int j = 0; j < numDims; j++ )
        {
            std::string dimName                                      = dimNames[variableData.varDims[j]];
            std::map< std::string, WriteNC::VarData >::iterator vit2 = varInfo.find( dimName );
            if( vit2 == varInfo.end() )
                MB_SET_ERR( MB_FAILURE, "Can't find requested coordinate variable " << dimName );

            WriteNC::VarData& coordData = vit2->second;
            // Index in dimNames to actual dimension id
            variableData.varDims[j] = coordData.varDims[0];  // This one, being a coordinate, is the only one
            dbgOut.tprintf( 2, "          dimension with index %d name %s has ID %d \n", j, dimName.c_str(),
                            variableData.varDims[j] );
        }

        // Define the variable now:
        int errCode =
            NCFUNC( def_var )( _fileId, desired_names[i].c_str(), variableData.varDataType,
                               (int)variableData.varDims.size(), &( variableData.varDims[0] ), &variableData.varId );
        if( errCode != NC_NOERR ) MB_SET_ERR( MB_FAILURE, "Failed to create requested variable " << desired_names[i] );

        dbgOut.tprintf( 2, "    for variable %s with desired name %s variable id is %d \n", var_names[i].c_str(),
                        desired_names[i].c_str(), variableData.varId );
        // Now define the variable, with all dimensions
    }

    // Define global attributes (exactly copied from the original file for the time being)
    // Should we modify some of them (e.g. revision_Id) later?
    std::map< std::string, WriteNC::AttData >::iterator attIt;
    for( attIt = globalAtts.begin(); attIt != globalAtts.end(); ++attIt )
    {
        const std::string& attName  = attIt->first;
        WriteNC::AttData& attData   = attIt->second;
        NCDF_SIZE& attLen           = attData.attLen;
        nc_type& attDataType        = attData.attDataType;
        const std::string& attValue = attData.attValue;

        switch( attDataType )
        {
            case NC_BYTE:
            case NC_CHAR:
                if( NC_NOERR !=
                    NCFUNC( put_att_text )( _fileId, NC_GLOBAL, attName.c_str(), attLen, attValue.c_str() ) )
                    MB_SET_ERR( MB_FAILURE, "Failed to define text type attribute" );
                break;
            case NC_DOUBLE:
                if( NC_NOERR != NCFUNC( put_att_double )( _fileId, NC_GLOBAL, attName.c_str(), NC_DOUBLE, 1,
                                                          (double*)attValue.c_str() ) )
                    MB_SET_ERR( MB_FAILURE, "Failed to define double type attribute" );
                break;
            case NC_FLOAT:
                if( NC_NOERR != NCFUNC( put_att_float )( _fileId, NC_GLOBAL, attName.c_str(), NC_FLOAT, 1,
                                                         (float*)attValue.c_str() ) )
                    MB_SET_ERR( MB_FAILURE, "Failed to define float type attribute" );
                break;
            case NC_INT:
                if( NC_NOERR !=
                    NCFUNC( put_att_int )( _fileId, NC_GLOBAL, attName.c_str(), NC_INT, 1, (int*)attValue.c_str() ) )
                    MB_SET_ERR( MB_FAILURE, "Failed to define int type attribute" );
                break;
            case NC_SHORT:
                if( NC_NOERR != NCFUNC( put_att_short )( _fileId, NC_GLOBAL, attName.c_str(), NC_SHORT, 1,
                                                         (short*)attValue.c_str() ) )
                    MB_SET_ERR( MB_FAILURE, "Failed to define short type attribute" );
                break;
            default:
                MB_SET_ERR( MB_FAILURE, "Unknown attribute data type" );
        }
    }

    // Take it out of define mode
    if( NC_NOERR != NCFUNC( enddef )( _fileId ) ) MB_SET_ERR( MB_FAILURE, "Failed to close define mode" );

    return MB_SUCCESS;
}
virtual ErrorCode moab::NCWriteHelper::write_nonset_variables ( std::vector< WriteNC::VarData > &  vdatas,
std::vector< int > &  tstep_nums 
) [protected, pure virtual]
ErrorCode moab::NCWriteHelper::write_set_variables ( std::vector< WriteNC::VarData > &  vsetdatas,
std::vector< int > &  tstep_nums 
) [private]

Definition at line 525 of file NCWriteHelper.cpp.

References _fileId, _writeNC, moab::WriteNC::VarData::has_tsteps, moab::WriteNC::isParallel, MB_NOT_IMPLEMENTED, MB_SET_ERR, MB_SUCCESS, moab::WriteNC::VarData::memoryHogs, NCFUNC, NCFUNCP, moab::ParallelComm::proc_config(), moab::ProcConfig::proc_rank(), moab::WriteNC::VarData::varDataType, moab::WriteNC::VarData::varId, moab::WriteNC::VarData::varName, moab::WriteNC::VarData::writeCounts, and moab::WriteNC::VarData::writeStarts.

Referenced by write_values().

{
    int success;

    // CAUTION: if the NetCDF ID is from a previous call to ncmpi_create rather than ncmpi_open,
    // all processors need to call ncmpi_begin_indep_data(). If only the root processor does so,
    // ncmpi_begin_indep_data() call will be blocked forever :(
#ifdef MOAB_HAVE_PNETCDF
    // Enter independent I/O mode
    success = NCFUNC( begin_indep_data )( _fileId );
    if( success ) MB_SET_ERR( MB_FAILURE, "Failed to begin independent I/O mode" );
#endif

    int rank = 0;
#ifdef MOAB_HAVE_MPI
    bool& isParallel = _writeNC->isParallel;
    if( isParallel )
    {
        ParallelComm*& myPcomm = _writeNC->myPcomm;
        rank                   = myPcomm->proc_config().proc_rank();
    }
#endif
    if( 0 == rank )
    {
        for( unsigned int i = 0; i < vsetdatas.size(); i++ )
        {
            WriteNC::VarData& variableData = vsetdatas[i];

            // Set variables with timesteps, e.g. xtime(Time) or xtime(Time, StrLen)
            if( variableData.has_tsteps )
            {
                MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing set variables with timesteps is not implemented yet" );
            }

            switch( variableData.varDataType )
            {
                case NC_DOUBLE:
                    // Independent I/O mode put
                    success = NCFUNCP( _vara_double )( _fileId, variableData.varId, &variableData.writeStarts[0],
                                                       &variableData.writeCounts[0],
                                                       (double*)( variableData.memoryHogs[0] ) );
                    if( success )
                        MB_SET_ERR( MB_FAILURE, "Failed to write double data for variable " << variableData.varName );
                    break;
                case NC_INT:
                    // Independent I/O mode put
                    success =
                        NCFUNCP( _vara_int )( _fileId, variableData.varId, &variableData.writeStarts[0],
                                              &variableData.writeCounts[0], (int*)( variableData.memoryHogs[0] ) );
                    if( success )
                        MB_SET_ERR( MB_FAILURE, "Failed to write int data for variable " << variableData.varName );
                    break;
                default:
                    MB_SET_ERR( MB_NOT_IMPLEMENTED, "Writing non-double or non-int data is not implemented yet" );
            }
        }
    }

#ifdef MOAB_HAVE_PNETCDF
    // End independent I/O mode
    success = NCFUNC( end_indep_data )( _fileId );
    if( success ) MB_SET_ERR( MB_FAILURE, "Failed to end independent I/O mode" );
#endif

    return MB_SUCCESS;
}
ErrorCode moab::NCWriteHelper::write_values ( std::vector< std::string > &  var_names,
std::vector< int > &  tstep_nums 
)

Take the info from VarData and write first non-set variables, then set variables.

Definition at line 468 of file NCWriteHelper.cpp.

References _writeNC, moab::WriteNC::dummyVarNames, moab::WriteNC::VarData::entLoc, moab::WriteNC::ENTLOCSET, MB_SET_ERR, MB_SUCCESS, moab::WriteNC::usedCoordinates, moab::WriteNC::varInfo, write_nonset_variables(), and write_set_variables().

Referenced by moab::WriteNC::write_file().

{
    std::set< std::string >& usedCoordinates           = _writeNC->usedCoordinates;
    std::set< std::string >& dummyVarNames             = _writeNC->dummyVarNames;
    std::map< std::string, WriteNC::VarData >& varInfo = _writeNC->varInfo;

    std::vector< WriteNC::VarData > vdatas;
    std::vector< WriteNC::VarData > vsetdatas;

    // For set variables, include coordinates used by requested var_names
    for( std::set< std::string >::iterator setIt = usedCoordinates.begin(); setIt != usedCoordinates.end(); ++setIt )
    {
        const std::string& coordName = *setIt;

        // Skip dummy coordinate variables (if any)
        if( dummyVarNames.find( coordName ) != dummyVarNames.end() ) continue;

        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( coordName );
        if( vit == varInfo.end() )
        {
            MB_SET_ERR( MB_FAILURE, "Can't find coordinate variable " << coordName );
        }

        vsetdatas.push_back( vit->second );
    }

    // Collect non-set and set variables from requested var_names
    for( unsigned int i = 0; i < var_names.size(); i++ )
    {
        std::map< std::string, WriteNC::VarData >::iterator vit = varInfo.find( var_names[i] );
        if( vit == varInfo.end() )
        {
            MB_SET_ERR( MB_FAILURE, "Can't find requested variable " << var_names[i] );
        }

        WriteNC::VarData& variableData = vit->second;
        if( WriteNC::ENTLOCSET == variableData.entLoc )
        {
            // Used coordinates has all ready been included
            if( usedCoordinates.find( var_names[i] ) != usedCoordinates.end() ) continue;

            vsetdatas.push_back( variableData );
        }
        else
            vdatas.push_back( variableData );
    }

    // Assume that the data ranges do not overlap across processors
    // While overlapped writing might still work, we should better not take that risk
    write_nonset_variables( vdatas, tstep_nums );

    // Use independent I/O mode put, since this write is only for the root processor
    write_set_variables( vsetdatas, tstep_nums );

    return MB_SUCCESS;
}

Member Data Documentation

Definition at line 64 of file NCWriteHelper.hpp.

std::vector< double > moab::NCWriteHelper::timeStepVals [protected]

Time values of output timesteps.

Definition at line 77 of file NCWriteHelper.hpp.

Referenced by collect_variable_data().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines