/** * The DAT format contains "datasets" and each dataset has N-outputs. One output * represents data for all vertices/faces for one timestep * * in TUFLOW results there could be also a special timestep (99999) with maximums * we will put it into a separate dataset with name suffixed with "/Maximums" * * In MDAL we convert one output to one MDAL dataset; * */ void MDAL::DriverBinaryDat::load( const std::string &datFile, MDAL::Mesh *mesh, MDAL_Status *status ) { mDatFile = datFile; if ( status ) *status = MDAL_Status::None; if ( !MDAL::fileExists( mDatFile ) ) { if ( status ) *status = MDAL_Status::Err_FileNotFound; return; } std::ifstream in( mDatFile, std::ifstream::in | std::ifstream::binary ); // implementation based on information from: // http://www.xmswiki.com/wiki/SMS:Binary_Dataset_Files_*.dat if ( !in ) EXIT_WITH_ERROR( MDAL_Status::Err_FileNotFound ); // Couldn't open the file size_t vertexCount = mesh->verticesCount(); size_t elemCount = mesh->facesCount(); int card = 0; int version; int objecttype; int sflt; int sflg = 0; int vectype; int objid; int numdata; int numcells; char name[40]; char istat; float time; if ( read( in, reinterpret_cast< char * >( &version ), 4 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); if ( version != CT_VERSION ) // Version should be 3000 EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); std::shared_ptr<DatasetGroup> group = std::make_shared< DatasetGroup >( mesh, mDatFile ); // DAT datasets group->setIsOnVertices( true ); // in TUFLOW results there could be also a special timestep (99999) with maximums // we will put it into a separate dataset std::shared_ptr<DatasetGroup> groupMax = std::make_shared< DatasetGroup >( mesh, mDatFile ); groupMax->setIsOnVertices( true ); while ( card != CT_ENDDS ) { if ( read( in, reinterpret_cast< char * >( &card ), 4 ) ) { // We've reached the end of the file and there was no ends card break; } switch ( card ) { case CT_OBJTYPE: // Object type if ( read( in, reinterpret_cast< char * >( &objecttype ), 4 ) || objecttype != CT_2D_MESHES ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; case CT_SFLT: // Float size if ( read( in, reinterpret_cast< char * >( &sflt ), 4 ) || sflt != CT_FLOAT_SIZE ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; case CT_SFLG: // Flag size if ( read( in, reinterpret_cast< char * >( &sflg ), 4 ) ) if ( sflg != CF_FLAG_SIZE && sflg != CF_FLAG_INT_SIZE ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; case CT_BEGSCL: group->setIsScalar( true ); groupMax->setIsScalar( true ); break; case CT_BEGVEC: group->setIsScalar( false ); groupMax->setIsScalar( false ); break; case CT_VECTYPE: // Vector type if ( read( in, reinterpret_cast< char * >( &vectype ), 4 ) || vectype != 0 ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; case CT_OBJID: // Object id if ( read( in, reinterpret_cast< char * >( &objid ), 4 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; case CT_NUMDATA: // Num data if ( read( in, reinterpret_cast< char * >( &numdata ), 4 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); if ( numdata != static_cast< int >( vertexCount ) ) EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh ); break; case CT_NUMCELLS: // Num data if ( read( in, reinterpret_cast< char * >( &numcells ), 4 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); if ( numcells != static_cast< int >( elemCount ) ) EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh ); break; case CT_NAME: // Name if ( read( in, reinterpret_cast< char * >( &name ), 40 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); if ( name[39] != 0 ) name[39] = 0; group->setName( trim( std::string( name ) ) ); groupMax->setName( group->name() + "/Maximums" ); break; case CT_TS: // Time step! if ( readIStat( in, sflg, &istat ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); if ( read( in, reinterpret_cast< char * >( &time ), 4 ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); double t = static_cast<double>( time ); if ( readVertexTimestep( mesh, group, groupMax, t, istat, sflg, in ) ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); break; } } if ( !group || group->datasets.size() == 0 ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); group->setStatistics( MDAL::calculateStatistics( group ) ); mesh->datasetGroups.push_back( group ); if ( groupMax && groupMax->datasets.size() > 0 ) { groupMax->setStatistics( MDAL::calculateStatistics( groupMax ) ); mesh->datasetGroups.push_back( groupMax ); } }
/** * The DAT format contains "datasets" and each dataset has N-outputs. One output * represents data for all vertices/faces for one timestep * * In MDAL we convert one output to one MDAL dataset; * */ void MDAL::LoaderAsciiDat::load( MDAL::Mesh *mesh, MDAL_Status *status ) { if ( status ) *status = MDAL_Status::None; if ( !MDAL::fileExists( mDatFile ) ) { if ( status ) *status = MDAL_Status::Err_FileNotFound; return; } std::ifstream in( mDatFile, std::ifstream::in ); std::string line; if ( !std::getline( in, line ) ) { if ( status ) *status = MDAL_Status::Err_UnknownFormat; return; } line = trim( line ); // http://www.xmswiki.com/xms/SMS:ASCII_Dataset_Files_*.dat // Apart from the format specified above, there is an older supported format used in BASEMENT (and SMS?) // which is simpler (has only one dataset in one file, no status flags etc) bool oldFormat; bool isVector = false; std::shared_ptr<DatasetGroup> group; // DAT outputs data std::string name( MDAL::baseName( mDatFile ) ); if ( line == "DATASET" ) oldFormat = false; else if ( line == "SCALAR" || line == "VECTOR" ) { oldFormat = true; isVector = ( line == "VECTOR" ); group.reset( new DatasetGroup() ); group->uri = mDatFile; group->setName( name ); group->isScalar = !isVector; } else EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); // see if it contains face-centered results - supported by BASEMENT bool faceCentered = false; if ( !oldFormat && contains( name, "_els_" ) ) faceCentered = true; if ( group ) group->isOnVertices = !faceCentered; while ( std::getline( in, line ) ) { std::vector<std::string> items = split( line, " ", SplitBehaviour::SkipEmptyParts ); if ( items.size() < 1 ) continue; // empty line?? let's skip it std::string cardType = items[0]; if ( cardType == "ND" && items.size() >= 2 ) { size_t fileNodeCount = toSizeT( items[1] ); if ( mesh->vertexIDtoIndex.size() != fileNodeCount ) EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh ); } else if ( !oldFormat && cardType == "NC" && items.size() >= 2 ) { size_t fileElemCount = toSizeT( items[1] ); if ( mesh->faceIDtoIndex.size() != fileElemCount ) EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh ); } else if ( !oldFormat && cardType == "OBJTYPE" ) { if ( items[1] != "mesh2d" && items[1] != "\"mesh2d\"" ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); } else if ( !oldFormat && ( cardType == "BEGSCL" || cardType == "BEGVEC" ) ) { if ( group ) { debug( "New dataset while previous one is still active!" ); EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); } isVector = cardType == "BEGVEC"; group.reset( new DatasetGroup() ); group->uri = mDatFile; group->setName( name ); group->isScalar = !isVector; group->isOnVertices = !faceCentered; } else if ( !oldFormat && cardType == "ENDDS" ) { if ( !group ) { debug( "ENDDS card for no active dataset!" ); EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); } mesh->datasetGroups.push_back( group ); group.reset(); } else if ( !oldFormat && cardType == "NAME" && items.size() >= 2 ) { if ( !group ) { debug( "NAME card for no active dataset!" ); EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); } size_t quoteIdx1 = line.find( '\"' ); size_t quoteIdx2 = line.find( '\"', quoteIdx1 + 1 ); if ( quoteIdx1 != std::string::npos && quoteIdx2 != std::string::npos ) group->setName( line.substr( quoteIdx1 + 1, quoteIdx2 - quoteIdx1 - 1 ) ); } else if ( oldFormat && ( cardType == "SCALAR" || cardType == "VECTOR" ) ) { // just ignore - we know the type from earlier... } else if ( cardType == "TS" && items.size() >= ( oldFormat ? 2 : 3 ) ) { double t = toDouble( items[oldFormat ? 1 : 2] ); if ( faceCentered ) { readFaceTimestep( mesh, group, t, isVector, in ); } else { bool hasStatus = ( oldFormat ? false : toBool( items[1] ) ); readVertexTimestep( mesh, group, t, isVector, hasStatus, in ); } } else { std::stringstream str; str << " Unknown card:" << line; debug( str.str() ); } } if ( oldFormat ) { if ( !group || group->datasets.size() == 0 ) EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat ); mesh->datasetGroups.push_back( group ); group.reset(); } }