You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
3.3 KiB

#pragma once
#include "actiondep.h"
#include "ncfilew.h"
#include "ncfuncs.h"
class GradMethods
{
public:
using DataType = float;
static DataType ToNum(const MString& str) { return michlib_internal::RealType<sizeof(DataType)>::String2Real(str.Buf()); }
struct MinMax
{
bool automin, automax, log;
DataType min, max;
DataType fill;
};
class Matrix;
class NCFileW;
};
class GradMethods::Matrix
{
public:
using MDataType = michlib::uint2;
private:
size_t nx, ny;
std::vector<MDataType> data;
public:
Matrix(const std::vector<DataType>& in, size_t nx_, size_t ny_, struct MinMax minmax);
void Grad();
auto Nx() const { return nx; }
auto Ny() const { return ny; }
const auto& V(size_t ix, size_t iy) const { return data[iy * nx + ix]; }
auto& V(size_t ix, size_t iy) { return data[iy * nx + ix]; }
const auto& Data() const { return data; }
};
class GradMethods::NCFileW
{
bool opened;
int ncid;
public:
NCFileW(): opened(false) {}
MString Create(const MString& name, const MString& history, const std::vector<MString>& vnames, const std::vector<MString>& lnames, const std::vector<GradMethods::DataType>& lons,
const std::vector<GradMethods::DataType>& lats, int compress);
MString WriteVar(const MString& name, const std::vector<GradMethods::Matrix::MDataType>& data);
~NCFileW() { Close(); }
void Close()
{
if(opened) nc_close(ncid);
opened = false;
}
};
template<class T>
concept GradSupported = requires(T t, const MString& vname) {
{
t.ReadVar(vname)
} -> std::same_as<std::vector<GradMethods::DataType>>;
};
ADD_ACTION(GRAD, grad, GradSupported<Source>, GradMethods);
template<class D> MString ActionGRAD::DoAction(const CLArgs& args, D& ds)
{
auto resop = ds.Open(args);
if(resop.Exist()) return "Can't open source: " + resop;
MString name = args.contains("out") ? args.at("out") : "out.nc";
MString min = args.contains("min") ? args.at("min") : "auto";
MString max = args.contains("max") ? args.at("max") : "auto";
int compress = args.contains("compress") ? args.at("compress").ToInt() : 3;
std::vector<Matrix> data;
std::vector<MString> lnames;
// Read data
for(size_t i = 0; i < ds.NVar(); i++)
{
const MString& name = ds.VarNames()[i];
const MString& lname = ds.LongNames()[i];
bool hmin = args.contains(name + "_min");
bool hmax = args.contains(name + "_max");
struct MinMax minmax;
minmax.log = args.contains(name + "_log");
if(hmin)
{
MString vmin = args.at(name + "_min");
minmax.automin = (vmin == "auto");
minmax.min = ToNum(vmin);
}
else
{
minmax.automin = (min == "auto");
minmax.min = ToNum(min);
}
if(hmax)
{
MString vmax = args.at(name + "_max");
minmax.automax = (vmax == "auto");
minmax.max = ToNum(vmax);
}
else
{
minmax.automax = (max == "auto");
minmax.max = ToNum(max);
}
minmax.fill = ds.FillVal(name);
data.emplace_back(ds.ReadVar(name), ds.Nx(), ds.Ny(), minmax);
lnames.emplace_back(lname + ", gradient");
}
NCFileW fw;
fw.Create(name, (ds.History().Exist() ? (ds.History() + "; ") : "") + args.at("_cmdline"), ds.VarNames(), lnames, ds.ReadLons(), ds.ReadLats(), compress);
for(size_t i = 0; i < ds.NVar(); i++)
{
const MString& name = ds.VarNames()[i];
data[i].Grad();
fw.WriteVar(name, data[i].Data());
}
return "";
};