2018-05-16 11:20:25 +02:00
|
|
|
/*
|
|
|
|
MDAL - Mesh Data Abstraction Library (MIT License)
|
|
|
|
Copyright (C) 2018 Lutra Consulting Ltd.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
#include <iosfwd>
|
|
|
|
#include <iostream>
|
|
|
|
#include <fstream>
|
|
|
|
#include <sstream>
|
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
|
|
|
#include <map>
|
|
|
|
#include <cassert>
|
|
|
|
#include <memory>
|
2019-04-17 11:22:45 +02:00
|
|
|
#include <limits>
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
#include "mdal_ascii_dat.hpp"
|
|
|
|
#include "mdal.h"
|
|
|
|
#include "mdal_utils.hpp"
|
2018-12-04 17:28:05 +01:00
|
|
|
#include "mdal_2dm.hpp"
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
#include <math.h>
|
|
|
|
|
|
|
|
#define EXIT_WITH_ERROR(error) { if (status) *status = (error); return; }
|
|
|
|
|
2018-12-14 14:59:53 +01:00
|
|
|
MDAL::DriverAsciiDat::DriverAsciiDat( ):
|
|
|
|
Driver( "ASCII_DAT",
|
|
|
|
"DAT",
|
|
|
|
"*.dat",
|
2019-11-29 15:15:01 +01:00
|
|
|
Capability::ReadDatasets | Capability::WriteDatasetsOnFaces2D | Capability::WriteDatasetsOnVertices2D
|
2018-12-14 14:59:53 +01:00
|
|
|
)
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2018-12-14 14:59:53 +01:00
|
|
|
MDAL::DriverAsciiDat *MDAL::DriverAsciiDat::create()
|
|
|
|
{
|
|
|
|
return new DriverAsciiDat();
|
|
|
|
}
|
|
|
|
|
|
|
|
MDAL::DriverAsciiDat::~DriverAsciiDat( ) = default;
|
|
|
|
|
2019-11-29 15:15:01 +01:00
|
|
|
bool MDAL::DriverAsciiDat::canReadDatasets( const std::string &uri )
|
2018-12-14 14:59:53 +01:00
|
|
|
{
|
|
|
|
std::ifstream in( uri, std::ifstream::in );
|
|
|
|
std::string line;
|
|
|
|
if ( !std::getline( in, line ) )
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
line = trim( line );
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
return canReadNewFormat( line ) || canReadOldFormat( line );
|
2018-12-14 14:59:53 +01:00
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
bool MDAL::DriverAsciiDat::canReadOldFormat( const std::string &line ) const
|
|
|
|
{
|
|
|
|
return MDAL::contains( line, "SCALAR" ) ||
|
|
|
|
MDAL::contains( line, "VECTOR" ) ||
|
|
|
|
MDAL::contains( line, "TS" );
|
|
|
|
}
|
2018-12-14 14:59:53 +01:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
bool MDAL::DriverAsciiDat::canReadNewFormat( const std::string &line ) const
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
return line == "DATASET";
|
|
|
|
}
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
void MDAL::DriverAsciiDat::loadOldFormat( std::ifstream &in,
|
|
|
|
Mesh *mesh,
|
|
|
|
MDAL_Status *status ) const
|
|
|
|
{
|
|
|
|
std::shared_ptr<DatasetGroup> group; // DAT outputs data
|
|
|
|
std::string groupName( MDAL::baseName( mDatFile ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
std::string line;
|
2019-01-22 10:29:53 +01:00
|
|
|
std::getline( in, line );
|
|
|
|
|
|
|
|
// Read the first line
|
|
|
|
bool isVector = MDAL::contains( line, "VECTOR" );
|
|
|
|
group = std::make_shared< DatasetGroup >(
|
|
|
|
name(),
|
|
|
|
mesh,
|
|
|
|
mDatFile,
|
|
|
|
groupName
|
|
|
|
);
|
|
|
|
group->setIsScalar( !isVector );
|
2019-11-29 15:15:01 +01:00
|
|
|
group->setDataLocation( MDAL_DataLocation::DataOnVertices2D );
|
2019-01-22 10:29:53 +01:00
|
|
|
|
|
|
|
do
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
// Replace tabs by spaces,
|
|
|
|
// since basement v.2.8 uses tabs instead of spaces (e.g. 'TS 0\t0.0')
|
|
|
|
line = replace( line, "\t", " " );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
// Trim string for cases when file has inconsistent new line symbols
|
|
|
|
line = MDAL::trim( line );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
// Split to tokens
|
2019-01-24 09:21:57 +01:00
|
|
|
std::vector<std::string> items = split( line, ' ' );
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( items.size() < 1 )
|
|
|
|
continue; // empty line?? let's skip it
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
std::string cardType = items[0];
|
|
|
|
if ( cardType == "ND" && items.size() >= 2 )
|
|
|
|
{
|
|
|
|
size_t fileNodeCount = toSizeT( items[1] );
|
2019-04-17 11:22:45 +02:00
|
|
|
size_t meshIdCount = maximumId( mesh ) + 1;
|
|
|
|
if ( meshIdCount != fileNodeCount )
|
2019-11-29 15:15:01 +01:00
|
|
|
{
|
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh )
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
}
|
|
|
|
else if ( cardType == "SCALAR" || cardType == "VECTOR" )
|
|
|
|
{
|
|
|
|
// just ignore - we know the type from earlier...
|
|
|
|
}
|
|
|
|
else if ( cardType == "TS" && items.size() >= 2 )
|
|
|
|
{
|
2019-12-13 09:33:23 +01:00
|
|
|
double rawTime = toDouble( items[ 1 ] );
|
|
|
|
MDAL::RelativeTimestamp t( rawTime, MDAL::RelativeTimestamp::hours );
|
2019-01-22 10:29:53 +01:00
|
|
|
readVertexTimestep( mesh, group, t, isVector, false, in );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::stringstream str;
|
|
|
|
str << " Unknown card:" << line;
|
|
|
|
debug( str.str() );
|
|
|
|
}
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
while ( std::getline( in, line ) );
|
|
|
|
|
|
|
|
if ( !group || group->datasets.size() == 0 )
|
2019-11-29 15:15:01 +01:00
|
|
|
{
|
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
|
|
|
}
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
group->setStatistics( MDAL::calculateStatistics( group ) );
|
|
|
|
mesh->datasetGroups.push_back( group );
|
|
|
|
group.reset();
|
|
|
|
}
|
|
|
|
|
2019-11-29 15:15:01 +01:00
|
|
|
void MDAL::DriverAsciiDat::loadNewFormat(
|
|
|
|
std::ifstream &in,
|
|
|
|
Mesh *mesh,
|
|
|
|
MDAL_Status *status ) const
|
2019-01-22 10:29:53 +01:00
|
|
|
{
|
|
|
|
bool isVector = false;
|
|
|
|
std::shared_ptr<DatasetGroup> group; // DAT outputs data
|
|
|
|
std::string groupName( MDAL::baseName( mDatFile ) );
|
|
|
|
std::string line;
|
2019-12-13 09:33:23 +01:00
|
|
|
MDAL::DateTime referenceTime;
|
2018-07-18 09:00:34 +02:00
|
|
|
// see if it contains face-centered results - supported by BASEMENT
|
|
|
|
bool faceCentered = false;
|
2019-11-29 15:15:01 +01:00
|
|
|
if ( contains( groupName, "_els" ) )
|
2018-07-18 09:00:34 +02:00
|
|
|
faceCentered = true;
|
|
|
|
|
2018-05-16 11:20:25 +02:00
|
|
|
while ( std::getline( in, line ) )
|
|
|
|
{
|
2018-12-04 17:28:05 +01:00
|
|
|
// Replace tabs by spaces,
|
|
|
|
// since basement v.2.8 uses tabs instead of spaces (e.g. 'TS 0\t0.0')
|
|
|
|
line = replace( line, "\t", " " );
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
// Trim string for cases when file has inconsistent new line symbols
|
|
|
|
line = MDAL::trim( line );
|
|
|
|
|
|
|
|
// Split to tokens
|
2019-01-24 09:21:57 +01:00
|
|
|
std::vector<std::string> items = split( line, ' ' );
|
2018-05-16 11:20:25 +02:00
|
|
|
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] );
|
2019-04-17 11:22:45 +02:00
|
|
|
size_t meshIdCount = maximumId( mesh ) + 1;
|
|
|
|
if ( meshIdCount != fileNodeCount )
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh )
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "NC" && items.size() >= 2 )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
size_t fileElemCount = toSizeT( items[1] );
|
2018-12-04 17:28:05 +01:00
|
|
|
if ( mesh->facesCount() != fileElemCount )
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_IncompatibleMesh )
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "OBJTYPE" )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
if ( items[1] != "mesh2d" && items[1] != "\"mesh2d\"" )
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "BEGSCL" || cardType == "BEGVEC" )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
if ( group )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
debug( "New dataset while previous one is still active!" );
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
isVector = cardType == "BEGVEC";
|
2018-07-18 09:00:34 +02:00
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
group = std::make_shared< DatasetGroup >(
|
2019-01-04 18:18:34 +01:00
|
|
|
name(),
|
2018-12-04 17:28:05 +01:00
|
|
|
mesh,
|
|
|
|
mDatFile,
|
2019-01-04 18:18:34 +01:00
|
|
|
groupName
|
2018-12-04 17:28:05 +01:00
|
|
|
);
|
|
|
|
group->setIsScalar( !isVector );
|
2019-11-29 15:15:01 +01:00
|
|
|
group->setDataLocation( faceCentered ? MDAL_DataLocation::DataOnFaces2D : MDAL_DataLocation::DataOnVertices2D );
|
2019-10-14 09:19:14 +02:00
|
|
|
group->setReferenceTime( referenceTime );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "ENDDS" )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
if ( !group )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
debug( "ENDDS card for no active dataset!" );
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2018-12-04 17:28:05 +01:00
|
|
|
group->setStatistics( MDAL::calculateStatistics( group ) );
|
2018-07-18 09:00:34 +02:00
|
|
|
mesh->datasetGroups.push_back( group );
|
|
|
|
group.reset();
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "NAME" && items.size() >= 2 )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
if ( !group )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
debug( "NAME card for no active dataset!" );
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
size_t quoteIdx1 = line.find( '\"' );
|
|
|
|
size_t quoteIdx2 = line.find( '\"', quoteIdx1 + 1 );
|
|
|
|
if ( quoteIdx1 != std::string::npos && quoteIdx2 != std::string::npos )
|
2018-07-18 09:00:34 +02:00
|
|
|
group->setName( line.substr( quoteIdx1 + 1, quoteIdx2 - quoteIdx1 - 1 ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2019-10-14 09:19:14 +02:00
|
|
|
else if ( cardType == "RT_JULIAN" && items.size() >= 2 )
|
|
|
|
{
|
2019-12-13 09:33:23 +01:00
|
|
|
referenceTime = DateTime( MDAL::toDouble( items[1] ), DateTime::JulianDay );
|
2019-10-14 09:19:14 +02:00
|
|
|
}
|
|
|
|
else if ( cardType == "TIMEUNITS" && items.size() >= 2 )
|
|
|
|
{
|
|
|
|
if ( !group )
|
|
|
|
{
|
|
|
|
debug( "TIMEUNITS card for no active dataset!" );
|
2019-11-29 15:15:01 +01:00
|
|
|
EXIT_WITH_ERROR( MDAL_Status::Err_UnknownFormat )
|
2019-10-14 09:19:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
group->setMetadata( "TIMEUNITS", items[1] );
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
else if ( cardType == "TS" && items.size() >= 3 )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2019-12-13 09:33:23 +01:00
|
|
|
double rawTime = toDouble( items[2] );
|
|
|
|
MDAL::RelativeTimestamp t( rawTime, MDAL::parseDurationTimeUnit( group->getMetadata( "TIMEUNITS" ) ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2018-07-18 09:00:34 +02:00
|
|
|
if ( faceCentered )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
readFaceTimestep( mesh, group, t, isVector, in );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
bool hasStatus = ( toBool( items[1] ) );
|
2018-07-18 09:00:34 +02:00
|
|
|
readVertexTimestep( mesh, group, t, isVector, hasStatus, in );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
std::stringstream str;
|
|
|
|
str << " Unknown card:" << line;
|
|
|
|
debug( str.str() );
|
|
|
|
}
|
|
|
|
}
|
2019-01-22 10:29:53 +01:00
|
|
|
}
|
|
|
|
|
2019-04-17 11:22:45 +02:00
|
|
|
size_t MDAL::DriverAsciiDat::maximumId( const MDAL::Mesh *mesh ) const
|
|
|
|
{
|
|
|
|
const Mesh2dm *m2dm = dynamic_cast<const Mesh2dm *>( mesh );
|
|
|
|
if ( m2dm )
|
|
|
|
return m2dm->maximumVertexId();
|
|
|
|
else
|
|
|
|
return mesh->verticesCount() - 1;
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
/**
|
|
|
|
* 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::DriverAsciiDat::load( const std::string &datFile, MDAL::Mesh *mesh, MDAL_Status *status )
|
|
|
|
{
|
|
|
|
mDatFile = datFile;
|
|
|
|
if ( status ) *status = MDAL_Status::None;
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( !MDAL::fileExists( mDatFile ) )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2019-01-22 10:29:53 +01:00
|
|
|
if ( status ) *status = MDAL_Status::Err_FileNotFound;
|
|
|
|
return;
|
|
|
|
}
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-04-17 11:22:45 +02:00
|
|
|
size_t mID = maximumId( mesh );
|
|
|
|
if ( mID == std::numeric_limits<size_t>::max() )
|
|
|
|
{
|
|
|
|
// This happens when mesh is 2DM and vertices are numbered from 0
|
|
|
|
if ( status ) *status = MDAL_Status::Err_IncompatibleMesh;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-01-22 10:29:53 +01:00
|
|
|
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 );
|
|
|
|
if ( canReadNewFormat( line ) )
|
|
|
|
{
|
|
|
|
// we do not need to parse first line again
|
|
|
|
loadNewFormat( in, mesh, status );
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we need to parse first line again to see
|
|
|
|
// scalar/vector flag or timestep flag
|
|
|
|
in.clear();
|
|
|
|
in.seekg( 0 );
|
|
|
|
loadOldFormat( in, mesh, status );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-14 14:59:53 +01:00
|
|
|
void MDAL::DriverAsciiDat::readVertexTimestep(
|
2018-07-18 09:00:34 +02:00
|
|
|
const MDAL::Mesh *mesh,
|
|
|
|
std::shared_ptr<DatasetGroup> group,
|
2019-12-13 09:33:23 +01:00
|
|
|
MDAL::RelativeTimestamp t,
|
2018-07-18 09:00:34 +02:00
|
|
|
bool isVector,
|
|
|
|
bool hasStatus,
|
2019-01-22 10:29:53 +01:00
|
|
|
std::ifstream &stream ) const
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
assert( group );
|
2018-12-04 17:28:05 +01:00
|
|
|
size_t faceCount = mesh->facesCount();
|
2019-11-29 15:15:01 +01:00
|
|
|
size_t vertexCount = mesh->verticesCount();
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-12-11 14:04:34 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> dataset = std::make_shared< MDAL::MemoryDataset2D >( group.get(), hasStatus );
|
2019-10-14 09:19:14 +02:00
|
|
|
dataset->setTime( t );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
// only for new format
|
|
|
|
for ( size_t i = 0; i < faceCount; ++i )
|
|
|
|
{
|
|
|
|
if ( hasStatus )
|
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
std::getline( stream, line );
|
2019-12-11 14:04:34 +01:00
|
|
|
dataset->setActive( i, toBool( line ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
const Mesh2dm *m2dm = dynamic_cast<const Mesh2dm *>( mesh );
|
2019-04-17 11:22:45 +02:00
|
|
|
size_t meshIdCount = maximumId( mesh ) + 1; // these are native format indexes (IDs). For formats without gaps it equals vertex array index
|
2019-11-29 15:15:01 +01:00
|
|
|
|
2019-04-17 11:22:45 +02:00
|
|
|
for ( size_t id = 0; id < meshIdCount; ++id )
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
std::getline( stream, line );
|
2019-01-24 09:21:57 +01:00
|
|
|
std::vector<std::string> tsItems = split( line, ' ' );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
size_t index;
|
|
|
|
if ( m2dm )
|
2019-04-17 11:22:45 +02:00
|
|
|
index = m2dm->vertexIndex( id ); //this index may be out of values array
|
2018-12-04 17:28:05 +01:00
|
|
|
else
|
2019-04-17 11:22:45 +02:00
|
|
|
index = id;
|
|
|
|
|
|
|
|
if ( index >= vertexCount ) continue;
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
if ( isVector )
|
|
|
|
{
|
|
|
|
if ( tsItems.size() >= 2 ) // BASEMENT files with vectors have 3 columns
|
|
|
|
{
|
2019-12-11 14:04:34 +01:00
|
|
|
dataset->setVectorValue( index, toDouble( tsItems[0] ), toDouble( tsItems[1] ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug( "invalid timestep line" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( tsItems.size() >= 1 )
|
2019-12-11 14:04:34 +01:00
|
|
|
dataset->setScalarValue( index, toDouble( tsItems[0] ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
debug( "invalid timestep line" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
dataset->setStatistics( MDAL::calculateStatistics( dataset ) );
|
2018-07-18 09:00:34 +02:00
|
|
|
group->datasets.push_back( dataset );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
|
2018-12-14 14:59:53 +01:00
|
|
|
void MDAL::DriverAsciiDat::readFaceTimestep(
|
2018-07-18 09:00:34 +02:00
|
|
|
const MDAL::Mesh *mesh,
|
|
|
|
std::shared_ptr<DatasetGroup> group,
|
2019-12-13 09:33:23 +01:00
|
|
|
MDAL::RelativeTimestamp t,
|
2018-07-18 09:00:34 +02:00
|
|
|
bool isVector,
|
2019-01-22 10:29:53 +01:00
|
|
|
std::ifstream &stream ) const
|
2018-05-16 11:20:25 +02:00
|
|
|
{
|
2018-07-18 09:00:34 +02:00
|
|
|
assert( group );
|
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
size_t faceCount = mesh->facesCount();
|
2018-05-16 11:20:25 +02:00
|
|
|
|
2019-11-29 15:15:01 +01:00
|
|
|
std::shared_ptr<MDAL::MemoryDataset2D> dataset = std::make_shared< MDAL::MemoryDataset2D >( group.get() );
|
2019-10-14 09:19:14 +02:00
|
|
|
dataset->setTime( t );
|
2018-05-16 11:20:25 +02:00
|
|
|
for ( size_t index = 0; index < faceCount; ++index )
|
|
|
|
{
|
|
|
|
std::string line;
|
|
|
|
std::getline( stream, line );
|
2019-01-24 09:21:57 +01:00
|
|
|
std::vector<std::string> tsItems = split( line, ' ' );
|
2018-05-16 11:20:25 +02:00
|
|
|
|
|
|
|
if ( isVector )
|
|
|
|
{
|
|
|
|
if ( tsItems.size() >= 2 ) // BASEMENT files with vectors have 3 columns
|
|
|
|
{
|
2019-12-11 14:04:34 +01:00
|
|
|
dataset->setVectorValue( index, toDouble( tsItems[0] ), toDouble( tsItems[1] ) );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
debug( "invalid timestep line" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if ( tsItems.size() >= 1 )
|
2019-12-11 14:04:34 +01:00
|
|
|
dataset->setScalarValue( index, toDouble( tsItems[0] ) ) ;
|
2018-05-16 11:20:25 +02:00
|
|
|
else
|
|
|
|
{
|
|
|
|
debug( "invalid timestep line" );
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-12-04 17:28:05 +01:00
|
|
|
dataset->setStatistics( MDAL::calculateStatistics( dataset ) );
|
2018-07-18 09:00:34 +02:00
|
|
|
group->datasets.push_back( dataset );
|
2018-05-16 11:20:25 +02:00
|
|
|
}
|
2019-10-14 09:19:14 +02:00
|
|
|
|
2019-11-29 15:15:01 +01:00
|
|
|
bool MDAL::DriverAsciiDat::persist( MDAL::DatasetGroup *group )
|
|
|
|
{
|
|
|
|
assert( ( group->dataLocation() == MDAL_DataLocation::DataOnFaces2D ) ||
|
|
|
|
( group->dataLocation() == MDAL_DataLocation::DataOnVertices2D ) );
|
|
|
|
|
|
|
|
const bool isScalar = group->isScalar();
|
|
|
|
const bool isOnVertices = group->dataLocation() == MDAL_DataLocation::DataOnVertices2D;
|
|
|
|
std::string uri = group->uri();
|
|
|
|
|
|
|
|
if ( !MDAL::contains( uri, "_els" ) && isOnVertices == false )
|
|
|
|
{
|
|
|
|
// Should contain _els in name but it does not
|
|
|
|
uri.insert( uri.size() - 4, "_els" );
|
|
|
|
}
|
|
|
|
|
|
|
|
std::ofstream out( uri, std::ofstream::out );
|
|
|
|
|
|
|
|
// implementation based on information from:
|
|
|
|
// https://www.xmswiki.com/wiki/SMS:ASCII_Dataset_Files_*.dat
|
|
|
|
if ( !out )
|
|
|
|
return true; // Couldn't open the file
|
|
|
|
|
|
|
|
const Mesh *mesh = group->mesh();
|
|
|
|
size_t nodeCount = mesh->verticesCount();
|
|
|
|
size_t elemCount = mesh->facesCount();
|
|
|
|
|
|
|
|
out << "DATASET\n";
|
|
|
|
out << "OBJTYPE \"mesh2d\"\n";
|
|
|
|
|
|
|
|
if ( isScalar )
|
|
|
|
out << "BEGSCL\n";
|
|
|
|
else
|
|
|
|
out << "BEGVEC\n";
|
|
|
|
|
|
|
|
out << "ND " << nodeCount << "\n";
|
|
|
|
out << "NC " << elemCount << "\n";
|
|
|
|
out << "NAME " "\"" << group->name() << "\"" "\n";
|
2019-12-13 09:33:23 +01:00
|
|
|
std::string referenceTimeStr = group->referenceTime().toJulianDayString();
|
2019-11-29 15:15:01 +01:00
|
|
|
|
|
|
|
if ( !referenceTimeStr.empty() )
|
|
|
|
{
|
2019-12-13 09:33:23 +01:00
|
|
|
out << "RT_JULIAN " << referenceTimeStr << "\n";
|
2019-11-29 15:15:01 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
out << "TIMEUNITS " << 0 << "\n";
|
|
|
|
|
|
|
|
for ( size_t time_index = 0; time_index < group->datasets.size(); ++ time_index )
|
|
|
|
{
|
|
|
|
const std::shared_ptr<MDAL::MemoryDataset2D> dataset
|
|
|
|
= std::dynamic_pointer_cast<MDAL::MemoryDataset2D>( group->datasets[time_index] );
|
|
|
|
|
2019-12-11 14:04:34 +01:00
|
|
|
bool hasActiveStatus = isOnVertices && dataset->supportsActiveFlag();
|
2019-12-13 09:33:23 +01:00
|
|
|
out << "TS " << hasActiveStatus << " " << std::to_string( dataset->time( RelativeTimestamp::hours ) ) << "\n";
|
2019-11-29 15:15:01 +01:00
|
|
|
|
|
|
|
if ( hasActiveStatus )
|
|
|
|
{
|
|
|
|
// Fill the active data
|
|
|
|
for ( size_t i = 0; i < elemCount; ++i )
|
|
|
|
{
|
2019-12-11 14:04:34 +01:00
|
|
|
int active = dataset->active( i );
|
2019-11-29 15:15:01 +01:00
|
|
|
out << ( active == 1 ? true : false ) << "\n";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
size_t valuesToWrite = isOnVertices ? nodeCount : elemCount;
|
|
|
|
|
|
|
|
for ( size_t i = 0; i < valuesToWrite; ++i )
|
|
|
|
{
|
|
|
|
// Read values flags
|
|
|
|
if ( isScalar )
|
2019-12-11 14:04:34 +01:00
|
|
|
out << dataset->scalarValue( i ) << "\n";
|
2019-11-29 15:15:01 +01:00
|
|
|
else
|
|
|
|
{
|
2019-12-11 14:04:34 +01:00
|
|
|
out << dataset->valueX( i ) << " " << dataset->valueY( i ) << "\n";
|
2019-11-29 15:15:01 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
out << "ENDDS";
|
|
|
|
|
|
|
|
return false;
|
|
|
|
}
|