Compare commits

...

3 Commits

  1. 6
      include/AVISO.h
  2. 4
      include/AVISOLOCAL.h
  3. 6
      include/HYCOM.h
  4. 6
      include/NEMO.h
  5. 101
      include/actiongenintfile.h
  6. 50
      include/actions.h
  7. 26
      include/odm.h
  8. 30
      include/traits.h
  9. 17
      include/uvdata.h
  10. 2
      src/AVISOLOCAL.cpp
  11. 10
      src/odm.cpp

6
include/AVISO.h

@ -14,6 +14,9 @@ class AVISOData: public LayeredData
Type type = TYPE_UNKNOWN;
public:
AVISOData() = default;
MString DataTitle() const
{
switch(type)
@ -26,9 +29,6 @@ class AVISOData: public LayeredData
}
}
public:
AVISOData() = default;
// TODO: RetVal
MString Open(const CLArgs& args)
{

4
include/AVISOLOCAL.h

@ -24,13 +24,13 @@ class AVISOLOCALData: public NCFuncs
virtual ~Parameters() override = default;
};
static MString Title() { return "AVISO local mirror"; }
public:
using Data = Simple2DData;
AVISOLOCALData() = default;
static MString DataTitle() { return "AVISO local mirror"; }
MString Info() const;
// TODO: RetVal
MString Open(const CLArgs& args);

6
include/HYCOM.h

@ -13,6 +13,9 @@ class HYCOMData: public LayeredData
Type type = TYPE_UNKNOWN;
public:
HYCOMData() = default;
MString DataTitle() const
{
switch(type)
@ -24,9 +27,6 @@ class HYCOMData: public LayeredData
}
}
public:
HYCOMData() = default;
// TODO: RetVal
MString Open(const CLArgs& args)
{

6
include/NEMO.h

@ -13,6 +13,9 @@ class NEMOData: public LayeredData
Type type = TYPE_UNKNOWN;
public:
NEMOData() = default;
MString DataTitle() const
{
switch(type)
@ -24,9 +27,6 @@ class NEMOData: public LayeredData
}
}
public:
NEMOData() = default;
// TODO: RetVal
MString Open(const CLArgs& args)
{

101
include/actiongenintfile.h

@ -0,0 +1,101 @@
#pragma once
#include "actions.h"
using michlib::Cos;
template<class D> struct DoAction_<D, ActionID::GENINTFILE>
{
static MString DoAction(const CLArgs& args, D& data);
};
template<class D> MString DoAction_<D, ActionID::GENINTFILE>::DoAction(const CLArgs& args, D& ds)
{
michlib_internal::ParameterListEx pars;
pars.UsePrefix("");
pars.SetParameter("source", args.at("source"));
if(!args.contains("out")) return "Output file name not specified";
auto [tindexes, err] = GetTIndexes(ds, args, pars);
if(err.Exist()) return err;
if(tindexes.size() < 10) return "Too few time moments";
// Check isotropy
for(size_t it = 0; it < tindexes.size() - 1; it++)
if(ds.Time(tindexes[it + 1]) - ds.Time(tindexes[it]) != ds.Time(tindexes[1]) - ds.Time(tindexes[0])) return "The time step is not isotropic";
std::unique_ptr<const BaseParameters> sourcepars;
if constexpr(ParametersSupported<D>)
{
auto [p, err] = ds.Parameters(pars, args);
if(err.Exist()) return err;
sourcepars.reset(p);
}
auto p = sourcepars.get();
MString name = args.at("out");
BFileW fw;
fw.Create(name, 2);
fw.SetColumnName(1, "u");
fw.SetColumnName(2, "v");
for(size_t it = 0; it < tindexes.size(); it++)
{
auto data = ReadUV(ds, p, tindexes[it]);
if(!data) return "Can't read data";
if(it == 0)
{
real lonb = data.Lon(0, 0), latb = data.Lat(0, 0), lone = data.Lon(data.Nx() - 1, data.Ny() - 1), late = data.Lat(data.Nx() - 1, data.Ny() - 1);
fw.UsePrefix("");
fw.SetParameter("nx", data.Nx());
fw.SetParameter("ny", data.Ny());
fw.SetParameter("dx", data.XStep() * 60.0);
fw.SetParameter("dy", data.YStep() * 60.0);
fw.SetParameter("nt", tindexes.size());
fw.SetParameter("dt", (ds.Time(tindexes[1]) - ds.Time(tindexes[0])) / 86400.0);
fw.SetParameter("FillValue", data.Fillval());
fw.UsePrefix("Info");
fw.SetParameter("lonb", lonb);
fw.SetParameter("latb", latb);
fw.SetParameter("lone", lone);
fw.SetParameter("late", late);
fw.SetParameter("DataSource", ds.DataTitle());
fw.SetParameter("xy2lon", MString(lonb) + "+%x/60");
fw.SetParameter("xy2lon_rp", MString("POP 60 DIV ") + lonb + " ADD");
fw.SetParameter("lonlat2x", MString("(%lon-") + lonb + ")*60");
fw.SetParameter("xy2lat", MString(latb) + "+%y/60");
fw.SetParameter("xy2lat_rp", MString("EXCH POP 60 DIV ") + latb + " ADD");
fw.SetParameter("lonlat2y", MString("(%lat-") + latb + ")*60");
fw.SetParameter("lonlatuv2dotx", "%u*(0.864/1.852)/Cos(%lat*M_PI/180)");
fw.SetParameter("lonlatuv2doty", "%v*(0.864/1.852)");
fw.SetParameter("dotxdotylonlat2u_rp", "EXCH POP EXCH POP COSD 1.852 0.864 DIV MUL MUL");
fw.SetParameter("dotxdotylonlat2v_rp", "POP POP 1.852 0.864 DIV MUL EXCH POP");
fw.SetParameter("dotxdotylonlat2u", "(1.852/0.864)*Cos(%lat*M_PI/180)*%dotx");
fw.SetParameter("dotxdotylonlat2v", "(1.852/0.864)*%doty");
fw.SetParameter("BeginDate", ds.Time(tindexes.front()).ToTString());
fw.SetParameter("EndDate", ds.Time(tindexes.back()).ToTString());
fw.SetParameter("Timestep", ds.Time(tindexes[1]) - ds.Time(tindexes[0]));
fw.SetParameter("DataID", michlib::UniqueId());
}
for(size_t ilat = 0; ilat < data.Ny(); ilat++)
{
for(size_t ilon = 0; ilon < data.Nx(); ilon++)
{
if(data.IsCoast(ilon, ilat))
{
fw.Write(data.Fillval());
fw.Write(data.Fillval());
}
else
{
fw.Write(data.U(ilon, ilat) * (0.864 / 1.852) / Cos(data.Lat(ilon, ilat) * M_PI / 180.0));
fw.Write(data.V(ilon, ilat) * (0.864 / 1.852));
}
}
}
}
fw.Finalize();
fw.Close();
return "";
};

50
include/actions.h

@ -14,7 +14,8 @@ enum class ActionID
{
INFO,
TSC,
UV
UV,
GENINTFILE
};
template<ActionID id> struct ActionCarrier
@ -39,10 +40,14 @@ template<class T> struct IsActionSupportedTest<T, ActionID::UV>
{
static constexpr bool ans = ReadPSupported<T> || ReadSupported<T>;
};
template<class T> struct IsActionSupportedTest<T, ActionID::GENINTFILE>
{
static constexpr bool ans = ReadIsGrid<T>;
};
template<class T, ActionID id> constexpr bool IsActionSupported = IsActionSupportedTest<T, id>::ans;
using ActionVariants = std::variant<ActionCarrier<ActionID::INFO>, ActionCarrier<ActionID::TSC>, ActionCarrier<ActionID::UV>>;
using ActionVariants = std::variant<ActionCarrier<ActionID::INFO>, ActionCarrier<ActionID::TSC>, ActionCarrier<ActionID::UV>, ActionCarrier<ActionID::GENINTFILE>>;
class Action: public ActionVariants
{
@ -58,6 +63,8 @@ class Action: public ActionVariants
*this = ActionVariants(ActionCarrier<ActionID::TSC>());
else if(act == "uv")
*this = ActionVariants(ActionCarrier<ActionID::UV>());
else if(act == "genintfile")
*this = ActionVariants(ActionCarrier<ActionID::GENINTFILE>());
else
return "Unknown action: " + act;
return "";
@ -192,32 +199,37 @@ template<class D> BaseData Read(const D& data, const MString& vname, const BaseP
return BaseData();
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, const TIndex& tindex)
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, size_t ind)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
size_t ind;
if(tindex.size() == 1)
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
ind = tindex[0];
michlib::message("Time: " + data.Time(ind).ToTString());
RT u, v;
if constexpr(ReadPSupported<D>)
{
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
return UV(u, v);
u = data.Read("u", p, ind);
v = data.Read("v", p, ind);
}
else if constexpr(ReadSupported<D>)
{
u = data.Read("u", ind);
v = data.Read("v", ind);
}
return UV(u, v);
}
template<class D> UVData<ReadType<D>> ReadUV(const D& data, const BaseParameters* p, const TIndex& tindex)
{
using RT = ReadType<D>;
using UV = UVData<RT>;
if(tindex.size() == 1)
return ReadUV(data, p, tindex[0]);
else
{
Averager<UV> out;
bool ok = true;
size_t ind;
for(size_t i = 0; i < tindex.size(); i++)
{
if(!ok) break;

26
include/odm.h

@ -1,4 +1,5 @@
#pragma once
#include "actiongenintfile.h"
#include "actioninfo.h"
#include "actiontsc.h"
#include "actionuv.h"
@ -6,14 +7,27 @@
using michlib::errmessage;
template<class T, ActionID id> consteval bool MustSupported()
template<class T, ActionID id> consteval bool MustSup()
{
static_assert(IsActionSupported<T, id>);
return true;
};
constexpr bool supported = MustSupported<NEMOData, ActionID::INFO>() && MustSupported<NEMOData, ActionID::TSC>() && MustSupported<NEMOData, ActionID::UV>() &&
MustSupported<HYCOMData, ActionID::INFO>() && MustSupported<HYCOMData, ActionID::TSC>() && MustSupported<HYCOMData, ActionID::UV>() &&
MustSupported<AVISOData, ActionID::INFO>() && MustSupported<AVISOData, ActionID::TSC>() && MustSupported<AVISOData, ActionID::UV>() &&
MustSupported<AVISOLOCALData, ActionID::INFO>() && MustSupported<AVISOLOCALData, ActionID::TSC>() && MustSupported<AVISOLOCALData, ActionID::UV>() &&
MustSupported<BINFILEData, ActionID::INFO>() && MustSupported<BINFILEData, ActionID::TSC>() && MustSupported<BINFILEData, ActionID::UV>();
constexpr bool NEMOsup =
MustSup<NEMOData, ActionID::INFO>() && MustSup<NEMOData, ActionID::TSC>() && MustSup<NEMOData, ActionID::UV>() && MustSup<NEMOData, ActionID::GENINTFILE>();
constexpr bool HYCOMsup =
MustSup<HYCOMData, ActionID::INFO>() && MustSup<HYCOMData, ActionID::TSC>() && MustSup<HYCOMData, ActionID::UV>() && MustSup<HYCOMData, ActionID::GENINTFILE>();
constexpr bool AVISOsup =
MustSup<AVISOData, ActionID::INFO>() && MustSup<AVISOData, ActionID::TSC>() && MustSup<AVISOData, ActionID::UV>() && MustSup<AVISOData, ActionID::GENINTFILE>();
constexpr bool AVISOLsup = MustSup<AVISOLOCALData, ActionID::INFO>() && MustSup<AVISOLOCALData, ActionID::TSC>() && MustSup<AVISOLOCALData, ActionID::UV>() &&
MustSup<AVISOLOCALData, ActionID::GENINTFILE>();
constexpr bool BINFILEsup = MustSup<BINFILEData, ActionID::INFO>() && MustSup<BINFILEData, ActionID::TSC>() && MustSup<BINFILEData, ActionID::UV>();
template<class T, ActionID id> static constexpr bool DisableAction = false;
// Exceptions
template<> constexpr bool DisableAction<BINFILEData, ActionID::GENINTFILE> = true;

30
include/traits.h

@ -32,13 +32,6 @@ concept ReadSupported = requires(T t, const MString& vname, size_t i) {
} -> std::convertible_to<real>;
};
template<class T>
concept ReadUVPSupported = requires(T t, const BaseParameters* ip, size_t i) {
{
t.ReadUV(ip, i).U(0, 0) + t.template ReadUV(ip, i).V(0, 0)
} -> std::convertible_to<real>;
};
template<class T>
concept IsUVData = requires(T t) {
{
@ -52,6 +45,19 @@ concept IsUVData = requires(T t) {
} -> std::convertible_to<real>;
};
namespace internal
{
template<class T>
concept HaveXYStep = requires(T t) {
{
t.XStep()
} -> std::convertible_to<real>;
{
t.YStep()
} -> std::convertible_to<real>;
};
}
namespace internal
{
template<typename...> using void_ = void;
@ -72,3 +78,13 @@ template<class D> struct GetReadType_<D, false, true>
} // namespace internal
template<class D> using ReadType = internal::GetReadType_<D, ReadPSupported<D>, ReadSupported<D>>::type;
template<class T>
concept ReadIsGrid = requires {
{
ReadType<T>().XStep()
} -> std::convertible_to<real>;
{
ReadType<T>().YStep()
} -> std::convertible_to<real>;
};

17
include/uvdata.h

@ -1,24 +1,12 @@
#pragma once
#include "geohelpers.h"
#include "traits.h"
#include <vector>
using michlib::M_PI;
using michlib::real;
using michlib::Sqrt;
namespace internal
{
template<class T>
concept HaveXYStep = requires(T t) {
{
t.XStep()
} -> std::convertible_to<real>;
{
t.YStep()
} -> std::convertible_to<real>;
};
}
enum class Metric
{
EUCLID,
@ -147,6 +135,9 @@ template<class OneVarData> class UVDataDims<OneVarData, true>: public UVDataStor
real Lat([[maybe_unused]] size_t ix, size_t iy) const { return y0 + iy * ystep; }
real Lon(size_t i) const { return Lon(i % nx, i / nx); }
real Lat(size_t i) const { return Lat(i % nx, i / nx); }
real XStep() const { return xstep; }
real YStep() const { return ystep; }
};
template<class OneVarData> class UVDataDims<OneVarData, false>: public UVDataStorage

2
src/AVISOLOCAL.cpp

@ -39,7 +39,7 @@ MString AVISOLOCALData::Info() const
// clang-format off
return
"Dataset: " + Title() + "\n" +
"Dataset: " + DataTitle() + "\n" +
" Begin date: " + Time(0).ToString() + "\n" +
" End date: " + Time(NTimes()-1).ToString() + "\n" +
" Time step: " + Timestep() + " seconds\n" +

10
src/odm.cpp

@ -4,7 +4,7 @@ inline void Usage(const MString& arg0)
{
message(arg0 + " (<key>=<value>...)");
message("Keys are:");
message(" action. What the program should do. May be: info, tsc, uv. Default: info.");
message(" action. What the program should do. May be: info, tsc, uv, genintfile. Default: info.");
message(" Keys for action=info. Print some information about dataset.");
message(" source. Required. May be: NEMO, HYCOM, AVISO, AVISOLOCAL, BINFILE");
message(" Keys for source=NEMO");
@ -41,6 +41,12 @@ inline void Usage(const MString& arg0)
message(" skipx, skipy. How many poinst skipped in the sparsed grid. Used only if velout parameter is present. Default: 1, output each point");
message(" stpout. Output file for stationary points. If absent, this data not calculated.");
message(" Keys for specific sources see in the section action=tsc.");
message(" Keys for action=genintfile. Create file with velocity field for interpolation.");
message(" source. Required. May be: NEMO, HYCOM, AVISO, AVISOLOCAL");
message(" time. Time moment or regular expression. If present, timeb and timee must be absent");
message(" timeb, timee. Time interval. If present, time must be absent");
message(" out. Output file, required.");
message(" Keys for specific sources see in the section action=tsc.");
}
int main(int argc, char** argv)
@ -81,7 +87,7 @@ int main(int argc, char** argv)
[&data = arg, &args = std::as_const(args)](const auto& arg)
{
using AT = std::decay_t<decltype(arg)>;
if constexpr(IsActionSupported<DT, AT::action>)
if constexpr(IsActionSupported<DT, AT::action> && !DisableAction<DT,AT::action>)
return DoAction<AT::action>(args, data);
else
return MString("Unsupported combination of action and source");

Loading…
Cancel
Save