2018-12-14 14:59:53 +01:00
|
|
|
/*
|
|
|
|
MDAL - mMesh Data Abstraction Library (MIT License)
|
|
|
|
Copyright (C) 2016 Lutra Consulting
|
|
|
|
Copyright (C) 2018 Peter Petrik (zilolv at gmail dot com)
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <string>
|
|
|
|
#include <string.h>
|
|
|
|
#include <vector>
|
2019-01-22 10:29:53 +01:00
|
|
|
#include <netcdf.h>
|
|
|
|
#include <set>
|
2018-12-14 14:59:53 +01:00
|
|
|
|
|
|
|
#include "mdal_sww.hpp"
|
2019-01-22 10:29:53 +01:00
|
|
|
#include "mdal_utils.hpp"
|
2018-12-14 14:59:53 +01:00
|
|
|
|
|
|
|
MDAL::DriverSWW::DriverSWW()
|
|
|
|
: Driver( "SWW",
|
|
|
|
"AnuGA",
|
|
|
|
"*.sww",
|
2019-01-04 18:18:34 +01:00
|
|
|
Capability::ReadMesh )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
MDAL::DriverSWW *MDAL::DriverSWW::create()
|
|
|
|
{
|
|
|
|
return new DriverSWW();
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
size_t MDAL::DriverSWW::getVertexCount( const NetCDFFile &ncFile ) const
|
|
|
|
{
|
|
|
|
int nPointsId;
|
|
|
|
size_t res;
|
|
|
|
ncFile.getDimension( "number_of_points", &res, &nPointsId );
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2019-11-29 15:15:01 +01:00
|
|
|
bool MDAL::DriverSWW::canReadMesh( const std::string &uri )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
NetCDFFile ncFile;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
try
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
ncFile.openFile( uri );
|
|
|
|
getVertexCount( ncFile );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
catch ( MDAL_Status )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::vector<double> MDAL::DriverSWW::readZCoords( const NetCDFFile &ncFile ) const
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
size_t nPoints = getVertexCount( ncFile );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::vector<double> pz;
|
|
|
|
// newer sww files does have elevation array that is time-dependent
|
|
|
|
if ( ncFile.hasArr( "z" ) )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
pz = ncFile.readDoubleArr( "z", nPoints );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( ncFile.hasArr( "elevation" ) )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
int zDims = 0;
|
|
|
|
int zid;
|
|
|
|
if ( nc_inq_varid( ncFile.handle(), "elevation", &zid ) == NC_NOERR &&
|
|
|
|
nc_inq_varndims( ncFile.handle(), zid, &zDims ) == NC_NOERR )
|
|
|
|
{
|
|
|
|
if ( zDims == 1 )
|
|
|
|
{
|
|
|
|
// just one elevation for all times, treat as z coord
|
|
|
|
pz = ncFile.readDoubleArr( "elevation", nPoints );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
pz.resize( nPoints );
|
|
|
|
// fetching "elevation" data for the first timestep,
|
|
|
|
// and threat it as z coord
|
|
|
|
size_t start[2], count[2];
|
|
|
|
const ptrdiff_t stride[2] = {1, 1};
|
|
|
|
start[0] = 0; // t = 0
|
|
|
|
start[1] = 0;
|
|
|
|
count[0] = 1;
|
|
|
|
count[1] = nPoints;
|
|
|
|
nc_get_vars_double( ncFile.handle(), zid, start, count, stride, pz.data() );
|
|
|
|
}
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
return pz;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MDAL::DriverSWW::addBedElevation( const NetCDFFile &ncFile,
|
|
|
|
MDAL::MemoryMesh *mesh,
|
|
|
|
const std::vector<double> ×
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
if ( ncFile.hasArr( "elevation" ) )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
std::shared_ptr<MDAL::DatasetGroup> grp = readScalarGroup( ncFile,
|
|
|
|
mesh,
|
|
|
|
times,
|
|
|
|
"Bed Elevation",
|
|
|
|
"elevation" );
|
|
|
|
mesh->datasetGroups.push_back( grp );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
MDAL::addBedElevationDatasetGroup( mesh, mesh->vertices );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
MDAL::Vertices MDAL::DriverSWW::readVertices( const NetCDFFile &ncFile ) const
|
|
|
|
{
|
|
|
|
size_t nPoints = getVertexCount( ncFile );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
|
|
|
// load mesh data
|
2019-01-22 10:29:53 +01:00
|
|
|
std::vector<double> px = ncFile.readDoubleArr( "x", nPoints );
|
|
|
|
std::vector<double> py = ncFile.readDoubleArr( "y", nPoints );
|
|
|
|
std::vector<double> pz = readZCoords( ncFile );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
|
|
|
// we may need to apply a shift to the X,Y coordinates
|
2019-01-22 10:29:53 +01:00
|
|
|
double xLLcorner = ncFile.getAttrDouble( NC_GLOBAL, "xllcorner" );
|
|
|
|
double yLLcorner = ncFile.getAttrDouble( NC_GLOBAL, "yllcorner" );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
MDAL::Vertices vertices( nPoints );
|
|
|
|
Vertex *vertexPtr = vertices.data();
|
|
|
|
for ( size_t i = 0; i < nPoints; ++i, ++vertexPtr )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
vertexPtr->x = px[i] + xLLcorner ;
|
|
|
|
vertexPtr->y = py[i] + yLLcorner ;
|
|
|
|
if ( !pz.empty() ) // missing both "z" and "elevation"
|
|
|
|
vertexPtr->z = pz[i];
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
return vertices;
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
MDAL::Faces MDAL::DriverSWW::readFaces( const NetCDFFile &ncFile ) const
|
|
|
|
{
|
|
|
|
// get dimensions
|
|
|
|
int nVolumesId, nVerticesId;
|
|
|
|
size_t nVolumes, nVertices;
|
|
|
|
ncFile.getDimension( "number_of_volumes", &nVolumes, &nVolumesId );
|
|
|
|
ncFile.getDimension( "number_of_vertices", &nVertices, &nVerticesId );
|
2019-03-18 14:05:41 +01:00
|
|
|
if ( nVertices != 3 ) throw MDAL_Status::Err_UnknownFormat;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::vector<int> pvolumes = ncFile.readIntArr( "volumes", nVertices * nVolumes );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
MDAL::Faces faces( nVolumes );
|
2018-12-14 14:59:53 +01:00
|
|
|
for ( size_t i = 0; i < nVolumes; ++i )
|
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
faces[i].resize( 3 );
|
|
|
|
faces[i][0] = static_cast<size_t>( pvolumes[3 * i + 0] );
|
|
|
|
faces[i][1] = static_cast<size_t>( pvolumes[3 * i + 1] );
|
|
|
|
faces[i][2] = static_cast<size_t>( pvolumes[3 * i + 2] );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
return faces;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::vector<double> MDAL::DriverSWW::readTimes( const NetCDFFile &ncFile ) const
|
|
|
|
{
|
|
|
|
size_t nTimesteps;
|
|
|
|
int nTimestepsId;
|
|
|
|
ncFile.getDimension( "number_of_timesteps", &nTimesteps, &nTimestepsId );
|
|
|
|
std::vector<double> times = ncFile.readDoubleArr( "time", nTimesteps );
|
|
|
|
return times;
|
|
|
|
}
|
|
|
|
|
|
|
|
void MDAL::DriverSWW::readDatasetGroups(
|
|
|
|
const NetCDFFile &ncFile,
|
|
|
|
MDAL::MemoryMesh *mesh,
|
|
|
|
const std::vector<double> ×
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
std::set<std::string> parsedVariableNames; // already parsed arrays somewhere else
|
|
|
|
parsedVariableNames.insert( "x" );
|
|
|
|
parsedVariableNames.insert( "y" );
|
|
|
|
parsedVariableNames.insert( "z" );
|
|
|
|
parsedVariableNames.insert( "volumes" );
|
|
|
|
parsedVariableNames.insert( "time" );
|
|
|
|
|
|
|
|
std::vector<std::string> names = ncFile.readArrNames();
|
|
|
|
std::set<std::string> namesSet( names.begin(), names.end() );
|
|
|
|
|
|
|
|
// Add bed elevation group
|
|
|
|
parsedVariableNames.insert( "elevations" );
|
|
|
|
addBedElevation( ncFile, mesh, times );
|
|
|
|
|
|
|
|
for ( const std::string &name : names )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-10-14 09:19:14 +02:00
|
|
|
// currently we do not support variables like elevation_c, friction_c, stage_c, xmomentum_c, ymomentum_c
|
|
|
|
// which contain values per volume instead of per vertex
|
|
|
|
if ( MDAL::endsWith( name, "_c" ) )
|
|
|
|
continue;
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
// skip already parsed variables
|
|
|
|
if ( parsedVariableNames.find( name ) == parsedVariableNames.cend() )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
std::string xName, yName, groupName( name );
|
|
|
|
bool isVector = parseGroupName( groupName, xName, yName );
|
|
|
|
|
|
|
|
std::shared_ptr<MDAL::DatasetGroup> grp;
|
|
|
|
if ( isVector && ncFile.hasArr( xName ) && ncFile.hasArr( yName ) )
|
|
|
|
{
|
|
|
|
// vector dataset group
|
|
|
|
grp = readVectorGroup(
|
|
|
|
ncFile,
|
|
|
|
mesh,
|
|
|
|
times,
|
|
|
|
groupName,
|
|
|
|
xName,
|
|
|
|
yName );
|
|
|
|
parsedVariableNames.insert( xName );
|
|
|
|
parsedVariableNames.insert( yName );
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// scalar dataset group
|
|
|
|
grp = readScalarGroup(
|
|
|
|
ncFile,
|
|
|
|
mesh,
|
|
|
|
times,
|
|
|
|
groupName,
|
|
|
|
name );
|
|
|
|
parsedVariableNames.insert( name );
|
|
|
|
}
|
|
|
|
if ( grp )
|
|
|
|
mesh->datasetGroups.push_back( grp );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
bool MDAL::DriverSWW::parseGroupName( std::string &groupName,
|
|
|
|
std::string &xName,
|
|
|
|
std::string &yName ) const
|
|
|
|
{
|
|
|
|
bool isVector = false;
|
|
|
|
std::string baseName( groupName );
|
|
|
|
|
|
|
|
// X and Y variables
|
|
|
|
if ( groupName.size() > 1 )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( MDAL::startsWith( groupName, "x" ) )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
baseName = groupName.substr( 1, groupName.size() - 1 );
|
|
|
|
xName = groupName;
|
|
|
|
yName = "y" + baseName;
|
|
|
|
isVector = true;
|
|
|
|
}
|
|
|
|
else if ( MDAL::startsWith( groupName, "y" ) )
|
|
|
|
{
|
|
|
|
baseName = groupName.substr( 1, groupName.size() - 1 );
|
|
|
|
xName = "x" + baseName;
|
|
|
|
yName = groupName;
|
|
|
|
isVector = true;
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
// Maximums
|
|
|
|
groupName = baseName;
|
|
|
|
if ( MDAL::endsWith( baseName, "_range" ) )
|
|
|
|
{
|
|
|
|
groupName = groupName.substr( 0, baseName.size() - 6 ) + "/Maximums";
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
return isVector;
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverSWW::readScalarGroup(
|
|
|
|
const NetCDFFile &ncFile,
|
|
|
|
MDAL::MemoryMesh *mesh,
|
|
|
|
const std::vector<double> ×,
|
|
|
|
const std::string groupName,
|
|
|
|
const std::string arrName
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
size_t nPoints = getVertexCount( ncFile );
|
|
|
|
std::shared_ptr<MDAL::DatasetGroup> mds;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
int varxid;
|
|
|
|
if ( nc_inq_varid( ncFile.handle(), arrName.c_str(), &varxid ) == NC_NOERR )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
mds = std::make_shared<MDAL::DatasetGroup> (
|
|
|
|
name(),
|
|
|
|
mesh,
|
|
|
|
mFileName,
|
|
|
|
groupName );
|
2019-11-29 15:15:01 +01:00
|
|
|
mds->setDataLocation( MDAL_DataLocation::DataOnVertices2D );
|
2019-01-22 10:29:53 +01:00
|
|
|
mds->setIsScalar( true );
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
int zDimsX = 0;
|
|
|
|
if ( nc_inq_varndims( ncFile.handle(), varxid, &zDimsX ) != NC_NOERR )
|
|
|
|
throw MDAL_Status::Err_UnknownFormat;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( zDimsX == 1 )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
// TIME INDEPENDENT
|
2019-11-29 15:15:01 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> o = std::make_shared<MDAL::MemoryDataset2D>( mds.get() );
|
2019-01-22 10:29:53 +01:00
|
|
|
o->setTime( 0.0 );
|
|
|
|
double *values = o->values();
|
|
|
|
std::vector<double> valuesX = ncFile.readDoubleArr( arrName, nPoints );
|
|
|
|
for ( size_t i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
values[i] = valuesX[i];
|
|
|
|
}
|
|
|
|
o->setStatistics( MDAL::calculateStatistics( o ) );
|
|
|
|
mds->datasets.push_back( o );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// TIME DEPENDENT
|
|
|
|
for ( size_t t = 0; t < times.size(); ++t )
|
|
|
|
{
|
2019-11-29 15:15:01 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> mto = std::make_shared<MDAL::MemoryDataset2D>( mds.get() );
|
2019-01-22 10:29:53 +01:00
|
|
|
mto->setTime( static_cast<double>( times[t] ) / 3600. );
|
|
|
|
double *values = mto->values();
|
|
|
|
|
|
|
|
// fetching data for one timestep
|
|
|
|
size_t start[2], count[2];
|
|
|
|
const ptrdiff_t stride[2] = {1, 1};
|
|
|
|
start[0] = t;
|
|
|
|
start[1] = 0;
|
|
|
|
count[0] = 1;
|
|
|
|
count[1] = nPoints;
|
|
|
|
nc_get_vars_double( ncFile.handle(), varxid, start, count, stride, values );
|
|
|
|
mto->setStatistics( MDAL::calculateStatistics( mto ) );
|
|
|
|
mds->datasets.push_back( mto );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
mds->setStatistics( MDAL::calculateStatistics( mds ) );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
return mds;
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::shared_ptr<MDAL::DatasetGroup> MDAL::DriverSWW::readVectorGroup(
|
|
|
|
const NetCDFFile &ncFile,
|
|
|
|
MDAL::MemoryMesh *mesh,
|
|
|
|
const std::vector<double> ×,
|
|
|
|
const std::string groupName,
|
|
|
|
const std::string arrXName,
|
|
|
|
const std::string arrYName
|
|
|
|
) const
|
|
|
|
{
|
|
|
|
size_t nPoints = getVertexCount( ncFile );
|
|
|
|
std::shared_ptr<MDAL::DatasetGroup> mds;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
int varxid, varyid;
|
|
|
|
if ( nc_inq_varid( ncFile.handle(), arrXName.c_str(), &varxid ) == NC_NOERR &&
|
|
|
|
nc_inq_varid( ncFile.handle(), arrYName.c_str(), &varyid ) == NC_NOERR )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
mds = std::make_shared<MDAL::DatasetGroup> (
|
|
|
|
name(),
|
|
|
|
mesh,
|
|
|
|
mFileName,
|
|
|
|
groupName );
|
2019-11-29 15:15:01 +01:00
|
|
|
mds->setDataLocation( MDAL_DataLocation::DataOnVertices2D );
|
2018-12-14 14:59:53 +01:00
|
|
|
mds->setIsScalar( false );
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
int zDimsX = 0;
|
|
|
|
int zDimsY = 0;
|
|
|
|
if ( nc_inq_varndims( ncFile.handle(), varxid, &zDimsX ) != NC_NOERR )
|
|
|
|
throw MDAL_Status::Err_UnknownFormat;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( nc_inq_varndims( ncFile.handle(), varyid, &zDimsY ) != NC_NOERR )
|
|
|
|
throw MDAL_Status::Err_UnknownFormat;
|
|
|
|
|
|
|
|
if ( zDimsX != zDimsY )
|
|
|
|
throw MDAL_Status::Err_UnknownFormat;
|
|
|
|
|
|
|
|
std::vector<double> valuesX( nPoints ), valuesY( nPoints );
|
|
|
|
|
|
|
|
if ( zDimsX == 1 )
|
|
|
|
{
|
|
|
|
// TIME INDEPENDENT
|
2019-11-29 15:15:01 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> o = std::make_shared<MDAL::MemoryDataset2D>( mds.get() );
|
2019-01-22 10:29:53 +01:00
|
|
|
o->setTime( 0.0 );
|
|
|
|
double *values = o->values();
|
|
|
|
std::vector<double> valuesX = ncFile.readDoubleArr( arrXName, nPoints );
|
|
|
|
std::vector<double> valuesY = ncFile.readDoubleArr( arrYName, nPoints );
|
2018-12-14 14:59:53 +01:00
|
|
|
for ( size_t i = 0; i < nPoints; ++i )
|
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
values[2 * i] = valuesX[i];
|
|
|
|
values[2 * i + 1] = valuesY[i];
|
|
|
|
}
|
|
|
|
o->setStatistics( MDAL::calculateStatistics( o ) );
|
|
|
|
mds->datasets.push_back( o );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// TIME DEPENDENT
|
|
|
|
for ( size_t t = 0; t < times.size(); ++t )
|
|
|
|
{
|
2019-11-29 15:15:01 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> mto = std::make_shared<MDAL::MemoryDataset2D>( mds.get() );
|
2019-01-22 10:29:53 +01:00
|
|
|
mto->setTime( static_cast<double>( times[t] ) / 3600. );
|
|
|
|
double *values = mto->values();
|
|
|
|
|
|
|
|
// fetching data for one timestep
|
|
|
|
size_t start[2], count[2];
|
|
|
|
const ptrdiff_t stride[2] = {1, 1};
|
|
|
|
start[0] = t;
|
|
|
|
start[1] = 0;
|
|
|
|
count[0] = 1;
|
|
|
|
count[1] = nPoints;
|
|
|
|
nc_get_vars_double( ncFile.handle(), varxid, start, count, stride, valuesX.data() );
|
|
|
|
nc_get_vars_double( ncFile.handle(), varyid, start, count, stride, valuesY.data() );
|
|
|
|
|
|
|
|
for ( size_t i = 0; i < nPoints; ++i )
|
|
|
|
{
|
|
|
|
values[2 * i] = static_cast<double>( valuesX[i] );
|
|
|
|
values[2 * i + 1] = static_cast<double>( valuesY[i] );
|
|
|
|
}
|
|
|
|
|
|
|
|
mto->setStatistics( MDAL::calculateStatistics( mto ) );
|
|
|
|
mds->datasets.push_back( mto );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
mds->setStatistics( MDAL::calculateStatistics( mds ) );
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
return mds;
|
|
|
|
}
|
|
|
|
|
|
|
|
std::unique_ptr<MDAL::Mesh> MDAL::DriverSWW::load(
|
|
|
|
const std::string &resultsFile,
|
|
|
|
MDAL_Status *status )
|
|
|
|
{
|
|
|
|
mFileName = resultsFile;
|
|
|
|
if ( status ) *status = MDAL_Status::None;
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
NetCDFFile ncFile;
|
|
|
|
|
|
|
|
try
|
|
|
|
{
|
|
|
|
// Open file for reading
|
|
|
|
ncFile.openFile( mFileName );
|
|
|
|
|
|
|
|
// Read mesh
|
|
|
|
MDAL::Vertices vertices = readVertices( ncFile );
|
|
|
|
MDAL::Faces faces = readFaces( ncFile );
|
|
|
|
std::unique_ptr< MDAL::MemoryMesh > mesh(
|
|
|
|
new MemoryMesh(
|
|
|
|
name(),
|
|
|
|
vertices.size(),
|
|
|
|
faces.size(),
|
|
|
|
3, // triangles
|
|
|
|
computeExtent( vertices ),
|
|
|
|
mFileName
|
|
|
|
)
|
|
|
|
);
|
|
|
|
mesh->faces = faces;
|
|
|
|
mesh->vertices = vertices;
|
|
|
|
|
|
|
|
// Read times
|
|
|
|
std::vector<double> times = readTimes( ncFile );
|
|
|
|
|
|
|
|
// Create a dataset(s)
|
|
|
|
readDatasetGroups( ncFile, mesh.get(), times );
|
|
|
|
|
|
|
|
// Success!
|
|
|
|
return std::unique_ptr<Mesh>( mesh.release() );
|
|
|
|
}
|
|
|
|
catch ( MDAL_Status err )
|
|
|
|
{
|
|
|
|
if ( status ) *status = err;
|
|
|
|
return std::unique_ptr< MDAL::Mesh >();
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|