@ -1,16 +1,19 @@
# pragma once
# include "DataAdapters/ncfilealt.h"
# include "ParseArgs.h"
# include "mdatetime.h"
# include "simple2ddata.h"
# include "specfunc.h"
# include "vartype.h"
# include <memory>
# include <regex.h>
# include <set>
# include <stdlib.h>
# include <sys/types.h>
using michlib : : Ceil ;
using michlib : : errmessage ;
using michlib : : Floor ;
using michlib : : GPL ;
using michlib : : int2 ;
using michlib : : MDateTime ;
using michlib : : NCFileA ;
@ -26,11 +29,19 @@ class NEMOData
TYPE_NRT6
} ;
std : : vector < NCFileA > nc ;
struct Parameters : public BaseParameters
{
size_t xb , yb , xe , ye , layer ;
MString varname ;
virtual ~ Parameters ( ) override = default ;
} ;
std : : vector < NCFileA > nc ;
std : : vector < real > depths ;
std : : vector < MDateTime > times ;
size_t nx ;
size_t nx , ny ;
real lonb , latb , lone , late ;
real lonstep , latstep ;
Type type = TYPE_UNKNOWN ;
class EnvVar
@ -73,7 +84,7 @@ class NEMOData
using Data = Simple2DData ;
private :
template < class DataType > Data ReadVarRaw ( const NCFileA & f , const MString & name , size_t i , bool nodepth ) const
template < class DataType > Data ReadVarRaw ( const NCFileA & f , const MString & name , size_t i , bool nodepth , const Parameters * p ) const
{
real unitmul = 1.0 ;
DataType fill ;
@ -92,12 +103,12 @@ class NEMOData
auto unit = f . A < MString > ( name , " units " ) ;
if ( unit & & unit . Get ( ) = = " m s-1 " ) unitmul = 100.0 ;
Data data ( ( xb < xe ) ? ( xe - xb + 1 ) : ( nx + xe - xb + 1 ) , ye - yb + 1 , Lonb ( ) , Latb ( ) , 1.0 / 12.0 , 1.0 / 12.0 ) ;
Data data ( ( p - > xb < p - > xe ) ? ( p - > xe - p - > xb + 1 ) : ( nx + p - > xe - p - > xb + 1 ) , p - > ye - p - > yb + 1 , Lon ( p - > xb ) , Lat ( p - > yb ) , lonstep , latstep ) ;
if ( xb < xe )
if ( p - > xb < p - > xe )
{
auto var = nodepth ? f . V < DataType > ( name , { " longitude " , xb , xe - xb + 1 } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , xb , xe - xb + 1 } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } , { " depth " , layer , 1 } ) ;
auto var = nodepth ? f . V < DataType > ( name , { " longitude " , p - > xb , p - > xe - p - > xb + 1 } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , p - > xb , p - > xe - p - > xb + 1 } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } , { " depth " , p - > layer , 1 } ) ;
if ( ! var ) return Data ( ) ;
if ( var . DimLen ( 0 ) ! = data . Nx ( ) | | var . DimLen ( 1 ) ! = data . Ny ( ) ) return Data ( ) ;
@ -110,10 +121,10 @@ class NEMOData
}
else
{
auto var1 = nodepth ? f . V < DataType > ( name , { " longitude " , xb } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , xb } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } , { " depth " , layer , 1 } ) ;
auto var2 = nodepth ? f . V < DataType > ( name , { " longitude " , 0 , xe + 1 } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , 0 , xe + 1 } , { " latitude " , yb , ye - yb + 1 } , { " time " , i , 1 } , { " depth " , layer , 1 } ) ;
auto var1 = nodepth ? f . V < DataType > ( name , { " longitude " , p - > xb } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , p - > xb } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } , { " depth " , p - > layer , 1 } ) ;
auto var2 = nodepth ? f . V < DataType > ( name , { " longitude " , 0 , p - > xe + 1 } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } )
: f . V < DataType > ( name , { " longitude " , 0 , p - > xe + 1 } , { " latitude " , p - > yb , p - > ye - p - > yb + 1 } , { " time " , i , 1 } , { " depth " , p - > layer , 1 } ) ;
if ( ! ( var1 & & var2 ) ) return Data ( ) ;
if ( ( var1 . DimLen ( 0 ) + var2 . DimLen ( 0 ) ) ! = data . Nx ( ) | | var1 . DimLen ( 1 ) ! = data . Ny ( ) | | var2 . DimLen ( 1 ) ! = data . Ny ( ) ) return Data ( ) ;
for ( size_t ix = 0 ; ix < var1 . DimLen ( 0 ) ; ix + + )
@ -132,12 +143,24 @@ class NEMOData
return data ;
}
static MString VName2IName ( const MString & vname )
{
if ( vname = = " temp " ) return " thetao " ;
if ( vname = = " sal " ) return " so " ;
if ( vname = = " mld " ) return " mlotst " ;
if ( vname = = " ssh " ) return " zos " ;
if ( vname = = " w " ) return " wo " ;
return " " ;
}
public :
Data ReadVar ( const MString & name , size_t i ) const
Data Read ( const BaseParameters * ip , size_t i ) const
{
if ( ! isOk ( ) ) return Data ( ) ;
bool nodepth = false ;
auto p = dynamic_cast < const struct Parameters * > ( ip ) ;
MString name = VName2IName ( p - > varname ) ;
for ( const auto & f : nc )
{
auto head = f . Header ( ) ;
@ -145,88 +168,84 @@ class NEMOData
if ( v . Name ( ) = = name )
{
if ( v . Dimensions ( ) . size ( ) = = 3 ) nodepth = true ;
if ( v . Type ( ) . Id ( ) = = NC_SHORT ) return ReadVarRaw < int2 > ( f , name , i , nodepth ) ;
if ( v . Type ( ) . Id ( ) = = NC_FLOAT ) return ReadVarRaw < float > ( f , name , i , nodepth ) ;
if ( v . Type ( ) . Id ( ) = = NC_SHORT ) return ReadVarRaw < int2 > ( f , name , i , nodepth , p ) ;
if ( v . Type ( ) . Id ( ) = = NC_FLOAT ) return ReadVarRaw < float > ( f , name , i , nodepth , p ) ;
}
}
return Data ( ) ;
}
Data Read Var( const MString & name , const std : : vector < size_t > & tind ex ) const
bool Has Var( const MString vnam e ) const
{
Averager < Data > out ;
if ( tindex . size ( ) = = 0 | | ! isOk ( ) ) return out ;
MString name = VName2IName ( vname ) ;
if ( name = = " " ) return false ;
for ( size_t i = 0 ; i < tindex . size ( ) ; i + + )
for ( const auto & f : nc )
{
Data dat = ReadVar ( name , tindex [ i ] ) ;
if ( ! dat ) return Data ( ) ;
out . Add ( dat ) ;
auto head = f . Header ( ) ;
for ( const auto & v : head . Variables ( ) )
if ( v . Name ( ) = = name ) return true ;
}
out . Div ( ) ;
return out ;
return false ;
}
public :
NEMOData ( ) = default ;
// TODO: RetVal
bool Open ( const MString & stype , const MString & cred , const MSt rin g& proxyurl = " " )
MString Open ( const CLArgs & a rgs )
{
MString oldprefix = GPL . UsePrefix ( " AVISO " ) ;
MString dataset = args . contains ( " dataset " ) ? args . at ( " dataset " ) : " DT " ;
MString cred = GPL . ParameterSValue ( " COPERNICUS_USER " , " " ) ;
MString proxyurl = GPL . ParameterSValue ( " COPERNICUS_PROXY " , " " ) ;
GPL . UsePrefix ( oldprefix ) ;
nc . clear ( ) ;
if ( proxyurl . Exist ( ) ) proxy . Activate ( " all_proxy " , proxyurl ) ;
if ( stype = = " DT " )
std : : vector < MString > urls ;
if ( dataset = = " DT " )
{
NCFileA newnc ;
newnc . Reset ( " https:// " + cred + " @my.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_my_0.083_P1D-m " ) ;
if ( ! newnc ) return false ;
nc . push_back ( std : : move ( newnc ) ) ;
urls = { " https:// " + cred + " @my.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_my_0.083_P1D-m " } ;
type = TYPE_DT ;
}
if ( stype = = " NRT " )
else if ( dataset = = " NRT " )
{
std : : vector < MString > urls { " https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m " ,
urls = { " https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_P1D-m " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_P1D-m " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_P1D-m " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy_anfc_0.083deg_P1D-m " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-wcur_anfc_0.083deg_P1D-m " } ;
for ( const auto & url : urls )
{
NCFileA newnc ;
newnc . Reset ( url ) ;
if ( ! newnc )
{
nc . clear ( ) ;
return false ;
}
nc . push_back ( std : : move ( newnc ) ) ;
}
type = TYPE_NRT ;
}
if ( stype = = " NRT6 " )
else if ( dataset = = " NRT6 " )
{
std : : vector < MString > urls { " https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i " ,
urls = { " https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-cur_anfc_0.083deg_PT6H-i " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-thetao_anfc_0.083deg_PT6H-i " ,
" https:// " + cred + " @nrt.cmems-du.eu/thredds/dodsC/cmems_mod_glo_phy-so_anfc_0.083deg_PT6H-i " } ;
for ( const auto & url : urls )
type = TYPE_NRT6 ;
}
else
return " Unknown dataset: " + dataset ;
nc . resize ( urls . size ( ) ) ;
for ( size_t i = 0 ; i < urls . size ( ) ; i + + )
{
NCFileA newnc ;
newnc . Reset ( url ) ;
if ( ! newnc )
nc [ i ] . Reset ( urls [ i ] ) ;
if ( ! nc [ i ] )
{
nc . clear ( ) ;
return false ;
return " Can't connect to database " ;
}
nc . push_back ( std : : move ( newnc ) ) ;
}
type = TYPE_NRT6 ;
}
auto rdepths = nc [ 0 ] . V < float > ( " depth " ) ;
if ( ! rdepths )
{
nc . clear ( ) ;
return false ;
return " Can't read depths " ;
}
depths . resize ( rdepths . DimLen ( 0 ) ) ;
for ( size_t i = 0 ; i < depths . size ( ) ; i + + ) depths [ i ] = rdepths ( i ) ;
@ -236,21 +255,46 @@ class NEMOData
if ( ! ( timeD | | timeF ) )
{
nc . clear ( ) ;
return false ;
return " Can't read times " ;
}
MDateTime refdate ( " 1950-01-01 " ) ;
timeD ? times . resize ( timeD . DimLen ( 0 ) ) : times . resize ( timeF . DimLen ( 0 ) ) ;
for ( size_t i = 0 ; i < times . size ( ) ; i + + ) times [ i ] = refdate + static_cast < time_t > ( timeD ? timeD ( i ) : timeF ( i ) ) * 3600 ;
return true ;
auto nlon = nc [ 0 ] . D ( " longitude " ) ;
auto nlat = nc [ 0 ] . D ( " latitude " ) ;
if ( ! ( nlon & & nlat ) )
{
nc . clear ( ) ;
return " Can't get number of longitudes/latitudes " ;
}
nx = nlon ;
ny = nlat ;
auto lons = nc [ 0 ] . V < float > ( " longitude " ) ;
auto lats = nc [ 0 ] . V < float > ( " latitude " ) ;
if ( ! ( lons & & lats ) )
{
nc . clear ( ) ;
return " Can't get longitudes/latitudes " ;
}
lonb = lons ( 0 ) ;
latb = lats ( 0 ) ;
lone = lons ( nx - 1 ) ;
late = lats ( ny - 1 ) ;
lonstep = ( lone - lonb ) / ( nx - 1 ) ;
latstep = ( late - latb ) / ( ny - 1 ) ;
return " " ;
}
MString Info ( ) const
{
if ( ! isOk ( ) ) return " " ;
MString d ;
for ( size_t i = 0 ; i < NDepths ( ) ; i + + ) d + = MString ( " " ) + " ( " + i + " " + Depth ( i ) + " ) " ;
std : : set < VarType > vars ;
std : : set < MString > vars ;
for ( const auto & f : nc )
{
auto head = f . Header ( ) ;
@ -268,7 +312,7 @@ class NEMOData
bool first = true ;
for ( const auto & v : vars )
{
svars + = ( first ? " " : " , " ) + v . ShortName ( ) ;
svars + = ( first ? " " : " , " ) + v ;
first = false ;
}
}
@ -280,70 +324,81 @@ class NEMOData
" End date: " + Time ( NTimes ( ) - 1 ) . ToString ( ) + " \n " +
" Time step: " + Timestep ( ) + " seconds \n " +
" Time moments: " + NTimes ( ) + " \n " +
" Region: ( " + lonb + " : " + lone + " ) x ( " + latb + " : " + late + " ) \n " +
" Grid: " + nx + " x " + ny + " ( " + lonstep + " x " + latstep + " ) \n " +
" Depths: " + d + " \n " +
" Supported variables: " + svars ;
// clang-format on
}
MString Dump ( ) const
std : : pair < const BaseParameters * , MString > Parameters ( michlib_internal : : ParameterListEx & pars , const CLArgs & args ) const
{
// clang-format off
return
" Current settings: \n " + MString ( ) +
" Longitudes: from " + Lonb ( ) + " ( " + xb + " ) to " + Lone ( ) + " ( " + xe + " ) \n " +
" Latitudes: from " + Latb ( ) + " ( " + yb + " ) to " + Late ( ) + " ( " + ye + " ) \n " +
" Depth: layer " + layer + " , depth " + Depth ( ) + " m \n " ;
// clang-format on
}
std : : unique_ptr < struct Parameters > ppar { new struct Parameters } ;
if ( ! args . contains ( " var " ) ) return { nullptr , " Variable not specified " } ;
ppar - > varname = args . at ( " var " ) ;
if ( ! HasVar ( ppar - > varname ) ) return { nullptr , " Variable " + ppar - > varname + " not exists in this dataset " } ;
if ( args . contains ( " layer " ) ) ppar - > layer = args . at ( " layer " ) . ToInteger < size_t > ( ) ;
if ( ! args . contains ( " depth " ) & & ppar - > layer > = NDepths ( ) ) return { nullptr , MString ( " Layer " ) + ppar - > layer + " is too deep! " } ;
real depth = args . contains ( " depth " ) ? args . at ( " depth " ) . ToReal ( ) : Depth ( ppar - > layer ) ;
if ( ! ( args . contains ( " lonb " ) & & args . contains ( " lone " ) & & args . contains ( " latb " ) & & args . contains ( " late " ) ) ) return { nullptr , " Region not specified (lonb, lone, latb, late) " } ;
bool SetRegion ( real lonbin , real lonein , real latb , real late , real depth )
{
if ( ! isOk ( ) ) return false ;
real lonb = ToGeoDomainNeg ( lonbin ) , lone = ToGeoDomainNeg ( lonein ) ;
real lon1 = ToGeoDomainNeg ( args . at ( " lonb " ) . ToReal ( ) ) ;
real lon2 = ToGeoDomainNeg ( args . at ( " lone " ) . ToReal ( ) ) ;
real lat1 = ToGeoDomainNeg ( args . at ( " latb " ) . ToReal ( ) ) ;
real lat2 = ToGeoDomainNeg ( args . at ( " late " ) . ToReal ( ) ) ;
size_t xb_ , xe_ , yb_ , ye_ , layer_ = 0 ;
ppar - > yb = static_cast < size_t > ( Floor ( ( lat1 - latb ) / latstep ) ) ;
ppar - > ye = static_cast < size_t > ( Ceil ( ( lat2 - latb ) / latstep ) ) ;
if ( ppar - > ye > 2040 ) ppar - > ye = 2040 ;
if ( ppar - > yb > = ppar - > ye ) return { nullptr , " Latb must be lesser then late " } ;
yb_ = static_cast < size_t > ( Floor ( ( latb + 80.0 ) * 12.0 ) ) ;
ye_ = static_cast < size_t > ( Ceil ( ( late + 80.0 ) * 12.0 ) ) ;
if ( ye_ > 2040 ) ye_ = 2040 ;
if ( yb_ > = ye_ ) return false ;
ppar - > xb = static_cast < size_t > ( Floor ( ( lon1 - lonb ) / lonstep ) ) ;
ppar - > xe = static_cast < size_t > ( Ceil ( ( lon2 - lonb ) / lonstep ) ) ;
xb_ = static_cast < size_t > ( Floor ( ( lonb + 180.0 ) * 12.0 ) ) ;
xe_ = static_cast < size_t > ( Ceil ( ( lone + 180.0 ) * 12.0 ) ) ;
if ( xb_ = = xe_ ) return false ;
if ( ppar - > xb = = ppar - > xe ) return { nullptr , " Lonb must be not equal late " } ;
if ( depth < 0.0 | | depth > depths . back ( ) )
layer_ = ( depth < 0.0 ) ? 0 : ( depths . size ( ) - 1 ) ;
ppar - > layer = ( depth < 0.0 ) ? 0 : ( depths . size ( ) - 1 ) ;
else
for ( size_t i = 0 ; i < depths . size ( ) - 1 ; i + + )
{
if ( depth > = depths [ i ] & & depth < = depths [ i + 1 ] )
{
layer_ = ( depth - depths [ i ] < = depths [ i + 1 ] - depth ) ? i : ( i + 1 ) ;
ppar - > layer = ( depth - depths [ i ] < = depths [ i + 1 ] - depth ) ? i : ( i + 1 ) ;
break ;
}
}
xb = xb_ ;
xe = xe_ ;
yb = yb_ ;
ye = ye_ ;
layer = layer_ ;
return true ;
}
real Lonb ( ) const { return isOk ( ) ? ( - 180.0 + xb / 12.0 ) : - 1000.0 ; }
real Lone ( ) const { return isOk ( ) ? ( - 180.0 + xe / 12.0 ) : - 1000.0 ; }
real Latb ( ) const { return isOk ( ) ? ( - 80.0 + yb / 12.0 ) : - 1000.0 ; }
real Late ( ) const { return isOk ( ) ? ( - 80.0 + ye / 12.0 ) : - 1000.0 ; }
size_t Xb ( ) const { return isOk ( ) ? xb : 0 ; }
size_t Xe ( ) const { return isOk ( ) ? xe : 0 ; }
size_t Yb ( ) const { return isOk ( ) ? yb : 0 ; }
size_t Ye ( ) const { return isOk ( ) ? ye : 0 ; }
size_t Nx ( ) const { return isOk ( ) ? ( ( xb < xe ) ? ( xe - xb + 1 ) : ( nx + xe - xb + 1 ) ) : 0 ; }
size_t Ny ( ) const { return isOk ( ) ? ( ye - yb + 1 ) : 0 ; }
}
pars . SetParameter ( " variable " , ppar - > varname ) ;
pars . SetParameter ( " depth " , Depth ( ppar - > layer ) ) ;
pars . SetParameter ( " layer " , ppar - > layer ) ;
pars . SetParameter ( " dataset " , Title ( ) ) ;
pars . SetParameter ( " lonb " , Lon ( ppar - > xb ) ) ;
pars . SetParameter ( " latb " , Lat ( ppar - > yb ) ) ;
pars . SetParameter ( " lone " , Lon ( ppar - > xe ) ) ;
pars . SetParameter ( " late " , Lat ( ppar - > ye ) ) ;
return { ppar . release ( ) , " " } ;
}
MString Dump ( const struct Parameters * ppar ) const
{
// clang-format off
return
" Current settings: \n " + MString ( ) +
" Longitudes: from " + Lon ( ppar - > xb ) + " ( " + ppar - > xb + " ) to " + Lon ( ppar - > xe ) + " ( " + ppar - > xe + " ) \n " +
" Latitudes: from " + Lat ( ppar - > yb ) + " ( " + ppar - > yb + " ) to " + Lat ( ppar - > ye ) + " ( " + ppar - > ye + " ) \n " +
" Depth: layer " + ppar - > layer + " , depth " + Depth ( ppar - > layer ) + " m \n " ;
// clang-format on
}
real Lon ( size_t ix ) const { return isOk ( ) ? ( - 180.0 + ix / 12.0 ) : - 1000.0 ; }
real Lat ( size_t iy ) const { return isOk ( ) ? ( - 80.0 + iy / 12.0 ) : - 1000.0 ; }
real Depth ( size_t l ) const { return isOk ( ) ? depths [ l ] : - 1000.0 ; }
real Depth ( ) const { return Depth ( layer ) ; }
size_t Layer ( ) const { return layer ; }
time_t Timestep ( ) const { return isOk ( ) ? ( times [ 1 ] - times [ 0 ] ) : 0 ; }
MDateTime Time ( size_t i ) const
{
@ -357,10 +412,6 @@ class NEMOData
size_t NDepths ( ) const { return depths . size ( ) ; }
size_t NTimes ( ) const { return times . size ( ) ; }
template < vartype : : Vartype vt > Data Read ( size_t it ) const = delete ;
template < vartype : : Vartype vt > Data Read ( const std : : vector < size_t > & tindex ) const = delete ;
MString Title ( ) const
{
switch ( type )
@ -374,19 +425,3 @@ class NEMOData
static real Fillval ( ) { return Data : : Fillval ( ) ; }
} ;
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : U > ( size_t it ) const { return ReadVar ( " uo " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : V > ( size_t it ) const { return ReadVar ( " vo " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : TEMP > ( size_t it ) const { return ReadVar ( " thetao " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : SAL > ( size_t it ) const { return ReadVar ( " so " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : MLD > ( size_t it ) const { return ReadVar ( " mlotst " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : SSH > ( size_t it ) const { return ReadVar ( " zos " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : W > ( size_t it ) const { return ReadVar ( " wo " , it ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : U > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " uo " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : V > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " vo " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : TEMP > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " thetao " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : SAL > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " so " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : MLD > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " mlotst " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : SSH > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " zos " , tindex ) ; }
template < > inline NEMOData : : Data NEMOData : : Read < vartype : : Vartype : : W > ( const std : : vector < size_t > & tindex ) const { return ReadVar ( " wo " , tindex ) ; }