Commit 52c8dd68 authored by Uwe Schulzweida's avatar Uwe Schulzweida

Exprf: added support for same variable name with different number of levels.

parent 183023f7
Pipeline #5515 passed with stages
in 15 minutes and 49 seconds
...@@ -2,6 +2,10 @@ ...@@ -2,6 +2,10 @@
* Version 1.9.10 release * Version 1.9.10 release
2020-12-15 Uwe Schulzweida
* Exprf: added support for same variable name with different number of levels
2020-11-23 Uwe Schulzweida 2020-11-23 Uwe Schulzweida
* Ymonarith: failed with variables on different grids * Ymonarith: failed with variables on different grids
......
...@@ -222,6 +222,7 @@ params_init(std::vector<paramType> &params, const VarList &varList, int vlistID) ...@@ -222,6 +222,7 @@ params_init(std::vector<paramType> &params, const VarList &varList, int vlistID)
vlistInqVarUnits(vlistID, varID, units); vlistInqVarUnits(vlistID, varID, units);
params[varID].type = PARAM_VAR; params[varID].type = PARAM_VAR;
params[varID].isValid = true;
params[varID].select = false; params[varID].select = false;
params[varID].remove = false; params[varID].remove = false;
params[varID].lmiss = true; params[varID].lmiss = true;
...@@ -587,7 +588,7 @@ Expr(void *process) ...@@ -587,7 +588,7 @@ Expr(void *process)
{ {
if (parse_arg.coords[i].needed) if (parse_arg.coords[i].needed)
{ {
const int coord = parse_arg.coords[i].coord; const auto coord = parse_arg.coords[i].coord;
if (coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w') if (coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w')
{ {
auto gridID = parse_arg.coords[i].cdiID; auto gridID = parse_arg.coords[i].cdiID;
...@@ -643,7 +644,7 @@ Expr(void *process) ...@@ -643,7 +644,7 @@ Expr(void *process)
for (int varID = parse_arg.nvars1; varID < parse_arg.nparams; varID++) for (int varID = parse_arg.nvars1; varID < parse_arg.nparams; varID++)
{ {
const int coord = params[varID].coord; const auto coord = params[varID].coord;
if (coord) if (coord)
{ {
if (coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w') if (coord == 'x' || coord == 'y' || coord == 'a' || coord == 'w')
...@@ -704,6 +705,8 @@ Expr(void *process) ...@@ -704,6 +705,8 @@ Expr(void *process)
cdoDefTimestep(streamID2, tsID); cdoDefTimestep(streamID2, tsID);
//for (int varID = 0; varID < nvars1; varID++) printf(">>> %s %d\n", params[varID].name, params[varID].isValid);
for (int varID = 0; varID < nvars1; varID++) params[varID].isValid = true;
for (int varID = 0; varID < nvars1; varID++) for (int varID = 0; varID < nvars1; varID++)
if (tsID == 0 || params[varID].steptype != TIME_CONSTANT) params[varID].nmiss = 0; if (tsID == 0 || params[varID].steptype != TIME_CONSTANT) params[varID].nmiss = 0;
......
...@@ -55,9 +55,9 @@ static constexpr double COMPGE(const double x, const double y) noexcept { return ...@@ -55,9 +55,9 @@ static constexpr double COMPGE(const double x, const double y) noexcept { return
static constexpr double COMPNE(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, y); } static constexpr double COMPNE(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, y); }
static constexpr double COMPEQ(const double x, const double y) noexcept { return IS_EQUAL(x, y); } static constexpr double COMPEQ(const double x, const double y) noexcept { return IS_EQUAL(x, y); }
static constexpr double COMPLEG(const double x, const double y) noexcept { return (x < y) ? -1. : (x > y); } static constexpr double COMPLEG(const double x, const double y) noexcept { return (x < y) ? -1. : (x > y); }
static constexpr double COMPAND(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, 0) && IS_NOT_EQUAL(y, 0); } static constexpr double COMPAND(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, 0.0) && IS_NOT_EQUAL(y, 0.0); }
static constexpr double COMPOR(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, 0) || IS_NOT_EQUAL(y, 0); } static constexpr double COMPOR(const double x, const double y) noexcept { return IS_NOT_EQUAL(x, 0.0) || IS_NOT_EQUAL(y, 0.0); }
static constexpr double COMPNOT(const double x) noexcept { return IS_EQUAL(x, 0); } static constexpr double COMPNOT(const double x) noexcept { return IS_EQUAL(x, 0.0); }
static inline double MVCOMPLT(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPLT(x, y); } static inline double MVCOMPLT(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPLT(x, y); }
static inline double MVCOMPGT(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPGT(x, y); } static inline double MVCOMPGT(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPGT(x, y); }
static inline double MVCOMPLE(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPLE(x, y); } static inline double MVCOMPLE(const double x, const double y, const double m) noexcept { return DBL_IS_EQUAL(x, m) ? m : COMPLE(x, y); }
...@@ -73,9 +73,9 @@ static double f_int(const double x) { return (int) (x); } ...@@ -73,9 +73,9 @@ static double f_int(const double x) { return (int) (x); }
static double f_nint(const double x) { return std::round(x); } static double f_nint(const double x) { return std::round(x); }
static double f_rand(const double x) { (void)x; return ((double) std::rand()) / ((double) RAND_MAX); } static double f_rand(const double x) { (void)x; return ((double) std::rand()) / ((double) RAND_MAX); }
static double f_sqr(const double x) { return x * x; } static double f_sqr(const double x) { return x * x; }
static double f_rad(const double x) { return x * M_PI / 180.; } static double f_rad(const double x) { return x * M_PI / 180.0; }
static double f_deg(const double x) { return x * 180. / M_PI; } static double f_deg(const double x) { return x * 180.0 / M_PI; }
static double f_isMissval(const double x) { (void)x; return 0; } static double f_isMissval(const double x) { (void)x; return 0.0; }
static double pt_ngp(const paramType *const p) { return p->ngp; } static double pt_ngp(const paramType *const p) { return p->ngp; }
static double pt_nlev(const paramType *const p) { return p->nlev; } static double pt_nlev(const paramType *const p) { return p->nlev; }
static double pt_size(const paramType *const p) { return p->ngp * p->nlev; } static double pt_size(const paramType *const p) { return p->ngp * p->nlev; }
...@@ -1053,6 +1053,9 @@ fun1c(int init, int funcID, nodeType *p1, double value, parseParamType *parse_ar ...@@ -1053,6 +1053,9 @@ fun1c(int init, int funcID, nodeType *p1, double value, parseParamType *parse_ar
if (p1->type != typeVar) cdoAbort("Parameter of function %s() needs to be a variable!", funcname); if (p1->type != typeVar) cdoAbort("Parameter of function %s() needs to be a variable!", funcname);
if (p1->ltmpobj) cdoAbort("Temporary objects not allowed in function %s()!", funcname); if (p1->ltmpobj) cdoAbort("Temporary objects not allowed in function %s()!", funcname);
if (parse_arg->debug)
cdoPrint("\t%s\tfunc\t%s=%s(%s[N%zu][L%zu], %g)", ExIn[init], tmpvnm, funcname, p1->param.name, p1->param.ngp, p1->param.nlev, value);
const auto ngp = p1->param.ngp; const auto ngp = p1->param.ngp;
const auto nlev = p1->param.nlev; const auto nlev = p1->param.nlev;
auto nmiss = p1->param.nmiss; auto nmiss = p1->param.nmiss;
...@@ -1096,7 +1099,7 @@ fun1c(int init, int funcID, nodeType *p1, double value, parseParamType *parse_ar ...@@ -1096,7 +1099,7 @@ fun1c(int init, int funcID, nodeType *p1, double value, parseParamType *parse_ar
size_t levidx = 0; size_t levidx = 0;
if (cdo_cmpstr(funcname, "sellevidx")) if (cdo_cmpstr(funcname, "sellevidx"))
{ {
const long ilevidx = std::lround(value); const auto ilevidx = std::lround(value);
if (ilevidx < 1 || ilevidx > (long) nlev) if (ilevidx < 1 || ilevidx > (long) nlev)
cdoAbort("%s(): level index %ld out of range (range: 1-%zu)!", funcname, ilevidx, nlev); cdoAbort("%s(): level index %ld out of range (range: 1-%zu)!", funcname, ilevidx, nlev);
levidx = (size_t) ilevidx - 1; levidx = (size_t) ilevidx - 1;
...@@ -1138,6 +1141,9 @@ fun2c(int init, int funcID, nodeType *p1, double value1, double value2, parsePar ...@@ -1138,6 +1141,9 @@ fun2c(int init, int funcID, nodeType *p1, double value1, double value2, parsePar
if (p1->type != typeVar) cdoAbort("Parameter of function %s() needs to be a variable!", funcname); if (p1->type != typeVar) cdoAbort("Parameter of function %s() needs to be a variable!", funcname);
if (p1->ltmpobj) cdoAbort("Temporary objects not allowed in function %s()!", funcname); if (p1->ltmpobj) cdoAbort("Temporary objects not allowed in function %s()!", funcname);
if (parse_arg->debug)
cdoPrint("\t%s\tfunc\t%s=%s(%s[N%zu][L%zu], %g, %g)", ExIn[init], tmpvnm, funcname, p1->param.name, p1->param.ngp, p1->param.nlev, value1, value2);
const auto ngp = p1->param.ngp; const auto ngp = p1->param.ngp;
const auto nlev = p1->param.nlev; const auto nlev = p1->param.nlev;
auto nmiss = p1->param.nmiss; auto nmiss = p1->param.nmiss;
...@@ -1265,7 +1271,7 @@ coord_fun(const int init, const int funcID, nodeType *p1, parseParamType *parse_ ...@@ -1265,7 +1271,7 @@ coord_fun(const int init, const int funcID, nodeType *p1, parseParamType *parse_
double *restrict pdata = p->param.data; double *restrict pdata = p->param.data;
double *restrict p1data = p1->param.data; double *restrict p1data = p1->param.data;
for ( size_t i = 0; i < ngp*nlev; i++ ) pdata[i] = p1data[i]; for (size_t i = 0; i < ngp*nlev; i++) pdata[i] = p1data[i];
*/ */
} }
/* /*
...@@ -1614,7 +1620,7 @@ ex_ifelse(const int init, nodeType *p1, nodeType *p2, nodeType *p3) ...@@ -1614,7 +1620,7 @@ ex_ifelse(const int init, nodeType *p1, nodeType *p2, nodeType *p3)
if (nmiss1 && DBL_IS_EQUAL(ival1, missval1)) if (nmiss1 && DBL_IS_EQUAL(ival1, missval1))
odat[i] = missval1; odat[i] = missval1;
else if (IS_NOT_EQUAL(ival1, 0)) else if (IS_NOT_EQUAL(ival1, 0.0))
odat[i] = DBL_IS_EQUAL(ival2, missval2) ? missval1 : ival2; odat[i] = DBL_IS_EQUAL(ival2, missval2) ? missval1 : ival2;
else else
odat[i] = DBL_IS_EQUAL(ival3, missval3) ? missval1 : ival3; odat[i] = DBL_IS_EQUAL(ival3, missval3) ? missval1 : ival3;
...@@ -1657,23 +1663,29 @@ int exNode(nodeType *p, parseParamType *parse_arg) ...@@ -1657,23 +1663,29 @@ int exNode(nodeType *p, parseParamType *parse_arg)
static int static int
param_search_name(const int nparam, const paramType *params, const char *name) param_search_name(const int nparam, const paramType *params, const char *name)
{ {
// for (int varID = nparam - 1; varID >= 0; --varID)
for (int varID = 0; varID < nparam; ++varID) for (int varID = 0; varID < nparam; ++varID)
{ {
if (cdo_cmpstr(params[varID].name, name)) return varID; if (params[varID].isValid && cdo_cmpstr(params[varID].name, name)) return varID;
} }
return -1; return -1;
} }
static int static int
param_search_name_size(const int nparam, const paramType *params, const char *name, size_t ngp, size_t nlev) param_search_name_size(const int nparam, paramType *params, const char *name, size_t ngp, size_t nlev)
{ {
// for (int varID = nparam - 1; varID >= 0; --varID) if (ngp == 0) ngp = 1;
if (nlev == 0) nlev = 1;
for (int varID = 0; varID < nparam; ++varID) for (int varID = 0; varID < nparam; ++varID)
{ {
if (ngp == params[varID].ngp && nlev == params[varID].nlev) if (cdo_cmpstr(params[varID].name, name))
if (cdo_cmpstr(params[varID].name, name)) return varID; {
if (ngp == params[varID].ngp && nlev == params[varID].nlev)
return varID;
else
params[varID].isValid = false;
}
} }
return -1; return -1;
...@@ -1709,6 +1721,7 @@ add_new_constant(const char *varname, parseParamType *parse_arg, paramType *para ...@@ -1709,6 +1721,7 @@ add_new_constant(const char *varname, parseParamType *parse_arg, paramType *para
param_meta_copy(params[varID], param); param_meta_copy(params[varID], param);
params[varID].type = PARAM_CONST; params[varID].type = PARAM_CONST;
params[varID].isValid = true;
params[varID].ngp = 1; params[varID].ngp = 1;
params[varID].nlat = 1; params[varID].nlat = 1;
params[varID].nlev = 1; params[varID].nlev = 1;
...@@ -1722,11 +1735,11 @@ add_new_constant(const char *varname, parseParamType *parse_arg, paramType *para ...@@ -1722,11 +1735,11 @@ add_new_constant(const char *varname, parseParamType *parse_arg, paramType *para
static void static void
add_new_param(const char *varname, parseParamType *parse_arg, paramType *params, const paramType &param) add_new_param(const char *varname, parseParamType *parse_arg, paramType *params, const paramType &param)
{ {
// printf(" create %s\n", varname);
const auto varID = parse_arg->nparams; const auto varID = parse_arg->nparams;
if (varID >= parse_arg->maxparams) cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams); if (varID >= parse_arg->maxparams) cdoAbort("Too many parameter (limit=%d)", parse_arg->maxparams);
param_meta_copy(params[varID], param); param_meta_copy(params[varID], param);
params[varID].isValid = true;
params[varID].lmiss = param.lmiss; params[varID].lmiss = param.lmiss;
params[varID].name = strdup(varname); params[varID].name = strdup(varname);
params[varID].nmiss = param.nmiss; params[varID].nmiss = param.nmiss;
...@@ -1787,6 +1800,7 @@ expr_run_type_var_grid(const char *vnm, int coord, parseParamType *parse_arg) ...@@ -1787,6 +1800,7 @@ expr_run_type_var_grid(const char *vnm, int coord, parseParamType *parse_arg)
const auto units = parse_arg->coords[coordID].units.data(); const auto units = parse_arg->coords[coordID].units.data();
const auto longname = parse_arg->coords[coordID].longname.data(); const auto longname = parse_arg->coords[coordID].longname.data();
params[nvarID].isValid = true;
params[nvarID].coord = coord; params[nvarID].coord = coord;
params[nvarID].lmiss = false; params[nvarID].lmiss = false;
params[nvarID].name = strdup(vnm); params[nvarID].name = strdup(vnm);
...@@ -1826,6 +1840,7 @@ expr_run_type_var_zaxis(const char *vnm, int coord, parseParamType *parse_arg) ...@@ -1826,6 +1840,7 @@ expr_run_type_var_zaxis(const char *vnm, int coord, parseParamType *parse_arg)
const auto units = parse_arg->coords[coordID].units.data(); const auto units = parse_arg->coords[coordID].units.data();
const auto longname = parse_arg->coords[coordID].longname.data(); const auto longname = parse_arg->coords[coordID].longname.data();
params[nvarID].isValid = true;
params[nvarID].coord = coord; params[nvarID].coord = coord;
params[nvarID].lmiss = false; params[nvarID].lmiss = false;
params[nvarID].name = strdup(vnm); params[nvarID].name = strdup(vnm);
...@@ -1872,7 +1887,7 @@ expr_run_type_var(nodeType *p, parseParamType *parse_arg) ...@@ -1872,7 +1887,7 @@ expr_run_type_var(nodeType *p, parseParamType *parse_arg)
if (varID == -1) if (varID == -1)
{ {
cdoAbort("Variable >%s< not found!", p->u.var.nm); cdoAbort("Variable >%s< not found!", vnm);
} }
else if (init) else if (init)
{ {
...@@ -1937,7 +1952,7 @@ expr_run_type_fun2c(nodeType *p, parseParamType *parse_arg) ...@@ -1937,7 +1952,7 @@ expr_run_type_fun2c(nodeType *p, parseParamType *parse_arg)
} }
else else
{ {
cdoAbort("Syntax error in call to %s(), check number of parameter!\n", p->u.fun1c.name); cdoAbort("Syntax error in call to %s(), check number of parameter!\n", p->u.fun2c.name);
} }
return nullptr; return nullptr;
...@@ -2007,8 +2022,8 @@ expr_run_type_opr(nodeType *p, parseParamType *parse_arg) ...@@ -2007,8 +2022,8 @@ expr_run_type_opr(nodeType *p, parseParamType *parse_arg)
cdoPrint("\tpop\tconst\t%s", varname2); cdoPrint("\tpop\tconst\t%s", varname2);
} }
//auto varID = param_search_name_size(parse_arg->nparams, params, varname2, rnode->param.ngp, rnode->param.nlev); //auto varID = param_search_name(parse_arg->nparams, params, varname2);
auto varID = param_search_name(parse_arg->nparams, params, varname2); auto varID = param_search_name_size(parse_arg->nparams, params, varname2, rnode->param.ngp, rnode->param.nlev);
if (init) if (init)
{ {
if (varID >= 0) if (varID >= 0)
......
...@@ -107,6 +107,7 @@ enum ...@@ -107,6 +107,7 @@ enum
struct paramType struct paramType
{ {
int type; int type;
bool isValid;
bool select; bool select;
bool remove; bool remove;
bool lmiss; bool lmiss;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment