Commit de21eba2 authored by Uwe Schulzweida's avatar Uwe Schulzweida
Browse files

Merge develop.

parents 5e6ca0ff 875136a5
2021-01-29 Uwe Schulzweida
* Using CDI library version 1.9.10
* Version 1.9.10 release
2021-01-11 Uwe Schulzweida
* EOF: data race, wrong result with multiple OpenMP threads (bug fix)
2021-01-05 Uwe Schulzweida
* Added option --ignore_time_bounds to ignore time bounds for time range statistics
* Isosurface: Added memory support for 32-bit float data.
2020-12-17 Uwe Schulzweida
* Added warning message if a non-thread-safe NetCDF4/HDF5 library is used
2020-12-15 Uwe Schulzweida
* Exprf: added support for same variable name with different number of levels
2020-11-23 Uwe Schulzweida
* Ymonarith: failed with variables on different grids
2020-11-20 Uwe Schulzweida
* timselmean: failed with variables on different grids [Bug #9978]
2020-11-18 Uwe Schulzweida
* Detrend: wrong result with parameter equal=false [Bug #9961]
* subtrend: added parameter equal=false
2020-11-12 Uwe Schulzweida
* Fldstat: optional parameter weights failed (bug fix)
* Wind: check that numLPE is > 0 (bug fix)
2020-10-29 Uwe Schulzweida 2020-10-29 Uwe Schulzweida
* Using CDI library version 1.9.9 * Using CDI library version 1.9.9
......
...@@ -3,6 +3,18 @@ CDO NEWS ...@@ -3,6 +3,18 @@ CDO NEWS
Improvement Improvement
Version 1.9.10 (29 January 2021):
New features:
* Added option --ignore_time_bounds to ignore time bounds for time range statistics
Fixed bugs:
* EOF: fix wrong result with multiple OpenMP threads (data race)
* timselmean: failed with variables on different grids [Bug #9978]
* Ymonarith: failed with variables on different grids
* Detrend: wrong result with parameter equal=false [Bug #9961]
* Fldstat: optional parameter weights failed
* Wind: check that numLPE is > 0
Version 1.9.9 (29 October 2020): Version 1.9.9 (29 October 2020):
New features: New features:
......
...@@ -5,7 +5,7 @@ ...@@ -5,7 +5,7 @@
# libtool 2.4.2 # libtool 2.4.2
AC_PREREQ([2.68]) AC_PREREQ([2.68])
AC_INIT([cdo], [1.9.9], [https://mpimet.mpg.de/cdo]) AC_INIT([cdo], [1.9.10], [https://mpimet.mpg.de/cdo])
AC_DEFINE_UNQUOTED(CDO, ["$PACKAGE_VERSION"], [CDO version]) AC_DEFINE_UNQUOTED(CDO, ["$PACKAGE_VERSION"], [CDO version])
...@@ -168,7 +168,7 @@ AS_IF([test x$acx_cv_cfortran_works = 'xno'],[AC_SUBST([FORTRAN_WORKS],[no])],[A ...@@ -168,7 +168,7 @@ AS_IF([test x$acx_cv_cfortran_works = 'xno'],[AC_SUBST([FORTRAN_WORKS],[no])],[A
# ---------------------------------------------------------------------- # ----------------------------------------------------------------------
CFLAGS="$CFLAGS ${OPENMP_CFLAGS}" CFLAGS="$CFLAGS ${OPENMP_CFLAGS}"
CXXFLAGS="$CXXFLAGS ${OPENMP_CFLAGS}" CXXFLAGS="$CXXFLAGS ${OPENMP_CFLAGS}"
---------------------------------------------------------------------- # ----------------------------------------------------------------------
# Add configure options # Add configure options
ACX_CDO_OPTIONS ACX_CDO_OPTIONS
ACX_CDI_OPTIONS ACX_CDI_OPTIONS
...@@ -215,6 +215,7 @@ AC_CONFIG_FILES([ ...@@ -215,6 +215,7 @@ AC_CONFIG_FILES([
test/Filter.test test/Filter.test
test/Fldpctl.test test/Fldpctl.test
test/Fldstat.test test/Fldstat.test
test/Fldstat2.test
test/Genweights.test test/Genweights.test
test/Gradsdes.test test/Gradsdes.test
test/Gridarea.test test/Gridarea.test
...@@ -222,6 +223,7 @@ AC_CONFIG_FILES([ ...@@ -222,6 +223,7 @@ AC_CONFIG_FILES([
test/Inttime.test test/Inttime.test
test/Isosurface.test test/Isosurface.test
test/MapReduce.test test/MapReduce.test
test/Merge.test
test/Mergetime.test test/Mergetime.test
test/Merstat.test test/Merstat.test
test/Monarith.test test/Monarith.test
......
...@@ -82,7 +82,7 @@ INTEGER Comma-separated list or first/last[/inc] range of years. ...@@ -82,7 +82,7 @@ INTEGER Comma-separated list or first/last[/inc] range of years.
@Item = dom @Item = dom
STRING Comma-separated list of the day of month (e.g. 29feb). STRING Comma-separated list of the day of month (e.g. 29feb).
@Item = timestep @Item = timestep
INTEGER Comma-separated list or first/last[/inc] range of timesteps. Negative values selects timesteps from the end (NetCDF only). INTEGER Comma-separated list or first/last[/inc] range of timesteps. Negative values select timesteps from the end (NetCDF only).
@Item = timestep_of_year @Item = timestep_of_year
INTEGER Comma-separated list or first/last[/inc] range of timesteps of year. INTEGER Comma-separated list or first/last[/inc] range of timesteps of year.
@Item = timestepmask @Item = timestepmask
......
...@@ -107,7 +107,7 @@ Selects a month and optional an arbitrary number of timesteps before and after t ...@@ -107,7 +107,7 @@ Selects a month and optional an arbitrary number of timesteps before and after t
@BeginParameter @BeginParameter
@Item = timesteps @Item = timesteps
INTEGER Comma-separated list or first/last[/inc] range of timesteps. Negative values selects timesteps from the end (NetCDF only). INTEGER Comma-separated list or first/last[/inc] range of timesteps. Negative values select timesteps from the end (NetCDF only).
@Item = times @Item = times
STRING Comma-separated list of times (format hh:mm:ss). STRING Comma-separated list of times (format hh:mm:ss).
@Item = hours @Item = hours
......
@BeginModule @BeginModule
@NewPage
@Name = Trend @Name = Trend
@Title = Trend of time series @Title = Trend of time series
@Section = Regression @Section = Regression
......
...@@ -15,6 +15,7 @@ This module is for adding or subtracting a trend computed by the operator @mod{t ...@@ -15,6 +15,7 @@ This module is for adding or subtracting a trend computed by the operator @mod{t
@BeginOperator_addtrend @BeginOperator_addtrend
@Title = Add trend @Title = Add trend
@Parameter = [equal]
@BeginDescription @BeginDescription
@IfMan @IfMan
...@@ -35,6 +36,7 @@ where t is the timesteps. ...@@ -35,6 +36,7 @@ where t is the timesteps.
@BeginOperator_subtrend @BeginOperator_subtrend
@Title = Subtract trend @Title = Subtract trend
@Parameter = [equal]
@BeginDescription @BeginDescription
@IfMan @IfMan
...@@ -53,6 +55,12 @@ where t is the timesteps. ...@@ -53,6 +55,12 @@ where t is the timesteps.
@EndOperator @EndOperator
@BeginParameter
@Item = equal
BOOL Set to false for unequal distributed timesteps (default: true)
@EndParameter
@BeginExample @BeginExample
The typical call for detrending the data in @file{infile} and storing the detrended data in @file{outfile} is: The typical call for detrending the data in @file{infile} and storing the detrended data in @file{outfile} is:
@BeginVerbatim @BeginVerbatim
......
...@@ -25,8 +25,9 @@ Supported parameter tables are: WMO standard table number 2 and ECMWF local tabl ...@@ -25,8 +25,9 @@ Supported parameter tables are: WMO standard table number 2 and ECMWF local tabl
geopotential_height & m & 156 geopotential_height & m & 156
@EndTable @EndTable
Use the alias @bold{ml2plx}/@bold{ml2hlx} or the environment variable @env{EXTRAPOLATE} Use the alias @bold{ml2plx}/@bold{ml2hlx} or the environment variable @env{EXTRAPOLATE} to extrapolate
to extrapolate missing values. This operator requires all variables on the same horizontal grid. missing values. This operator requires all variables on the same horizontal grid.
Missing values in the input data are not supported.
@EndDescription @EndDescription
@EndModule @EndModule
......
...@@ -48,6 +48,7 @@ ...@@ -48,6 +48,7 @@
#include "cdo_options.h" #include "cdo_options.h"
#include "mpmo_color.h" #include "mpmo_color.h"
#include "cdi_lockedIO.h" #include "cdi_lockedIO.h"
#include "gaussian_latitudes.h"
int scan_par_obsolete(char *namelist, const char *name, int def); int scan_par_obsolete(char *namelist, const char *name, int def);
int scan_par(int verbose, char *namelist, const char *name, int def); int scan_par(int verbose, char *namelist, const char *name, int def);
...@@ -1018,7 +1019,7 @@ after_defineGrid(const AfterControl &globs, struct Variable *vars) ...@@ -1018,7 +1019,7 @@ after_defineGrid(const AfterControl &globs, struct Variable *vars)
const size_t nlat = globs.Latitudes; const size_t nlat = globs.Latitudes;
std::vector<double> lats(nlat), latw(nlat); std::vector<double> lats(nlat), latw(nlat);
gaussianLatitudes(lats.data(), latw.data(), nlat); gaussian_latitudes(nlat, lats.data(), latw.data());
for (size_t j = 0; j < nlat; ++j) lats[j] = 180. / M_PI * std::asin(lats[j]); for (size_t j = 0; j < nlat; ++j) lats[j] = 180. / M_PI * std::asin(lats[j]);
gridDefYvals(gaussGridID, lats.data()); gridDefYvals(gaussGridID, lats.data());
} }
......
...@@ -98,6 +98,9 @@ Arithdays(void *process) ...@@ -98,6 +98,9 @@ Arithdays(void *process)
const auto streamID2 = cdoOpenWrite(1); const auto streamID2 = cdoOpenWrite(1);
cdoDefVlist(streamID2, vlistID2); cdoDefVlist(streamID2, vlistID2);
VarList varList1;
varListInit(varList1, vlistID1);
const auto gridsizemax = vlistGridsizeMax(vlistID1); const auto gridsizemax = vlistGridsizeMax(vlistID1);
Field field; Field field;
...@@ -126,9 +129,9 @@ Arithdays(void *process) ...@@ -126,9 +129,9 @@ Arithdays(void *process)
{ {
cdoInqRecord(streamID1, &varID, &levelID); cdoInqRecord(streamID1, &varID, &levelID);
cdoReadRecord(streamID1, field.vec_d.data(), &field.nmiss); cdoReadRecord(streamID1, field.vec_d.data(), &field.nmiss);
field.size = varList1[varID].gridsize;
field.grid = vlistInqVarGrid(vlistID1, varID); field.grid = varList1[varID].gridID;
field.missval = vlistInqVarMissval(vlistID1, varID); field.missval = varList1[varID].missval;
vfarcfun(field, rconst, operfunc); vfarcfun(field, rconst, operfunc);
......
...@@ -54,7 +54,7 @@ detrend(const long nts, const Varray<double> &deltaTS0, const double missval1, c ...@@ -54,7 +54,7 @@ detrend(const long nts, const Varray<double> &deltaTS0, const double missval1, c
const auto work1 = DIVMN(SUBMN(sumjx, DIVMN(MULMN(sumj, sumx), n)), SUBMN(sumjj, DIVMN(MULMN(sumj, sumj), n))); const auto work1 = DIVMN(SUBMN(sumjx, DIVMN(MULMN(sumj, sumx), n)), SUBMN(sumjj, DIVMN(MULMN(sumj, sumj), n)));
const auto work2 = SUBMN(DIVMN(sumx, n), MULMN(DIVMN(sumj, n), work1)); const auto work2 = SUBMN(DIVMN(sumx, n), MULMN(DIVMN(sumj, n), work1));
for (long j = 0; j < nts; j++) array2[j] = SUBMN(array1[j], ADDMN(work2, MULMN(j, work1))); for (long j = 0; j < nts; j++) array2[j] = SUBMN(array1[j], ADDMN(work2, MULMN(work1, deltaTS0[j])));
} }
static void static void
......
...@@ -44,7 +44,7 @@ ...@@ -44,7 +44,7 @@
#include "datetime.h" #include "datetime.h"
#include "eof_mode.h" #include "eof_mode.h"
// NO MISSING VALUE SUPPORT ADDED SO FAR // No missing value support added so far!
static void static void
scale_eigvec_grid(Varray<double> &out, int tsID, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight, scale_eigvec_grid(Varray<double> &out, int tsID, size_t npack, const std::vector<size_t> &pack, const Varray<double> &weight,
...@@ -169,9 +169,9 @@ EOFs(void *process) ...@@ -169,9 +169,9 @@ EOFs(void *process)
for (int index = 1; index < ngrids; index++) for (int index = 1; index < ngrids; index++)
if (vlistGrid(vlistID1, 0) != vlistGrid(vlistID1, index)) cdoAbort("Too many different grids!"); if (vlistGrid(vlistID1, 0) != vlistGrid(vlistID1, index)) cdoAbort("Too many different grids!");
/* eigenvalues */ // eigenvalues
/* COUNT NUMBER OF TIMESTEPS if EOF_ or EOF_TIME */ // Count number of timesteps if EOF_ or EOF_TIME
if (operfunc == EOF_ || operfunc == EOF_TIME) if (operfunc == EOF_ || operfunc == EOF_TIME)
{ {
if (Options::cdoVerbose) cdoPrint("Counting timesteps in ifile"); if (Options::cdoVerbose) cdoPrint("Counting timesteps in ifile");
...@@ -471,13 +471,13 @@ EOFs(void *process) ...@@ -471,13 +471,13 @@ EOFs(void *process)
eofdata[varID][levelID].eig_val.resize(nts); eofdata[varID][levelID].eig_val.resize(nts);
#ifdef _OPENMP
#pragma omp parallel for default(shared) schedule(dynamic)
#endif
for (int j1 = 0; j1 < nts; j1++) for (int j1 = 0; j1 < nts; j1++)
{ {
const auto &df1p = data[j1]; const auto &df1p = data[j1];
for (int j2 = 0; j2 < j1; j2++) covar[j1][j2] = covar[j2][j1]; for (int j2 = 0; j2 < j1; j2++) covar[j1][j2] = covar[j2][j1];
#ifdef _OPENMP
#pragma omp parallel for default(shared) schedule(dynamic)
#endif
for (int j2 = j1; j2 < nts; j2++) for (int j2 = j1; j2 < nts; j2++)
{ {
const auto &df2p = data[j2]; const auto &df2p = data[j2];
...@@ -492,7 +492,7 @@ EOFs(void *process) ...@@ -492,7 +492,7 @@ EOFs(void *process)
if (Options::Timer) timer_stop(timer_cov); if (Options::Timer) timer_stop(timer_cov);
// SOLVE THE EIGEN PROBLEM // Solve the eigen problem
if (Options::Timer) timer_start(timer_eig); if (Options::Timer) timer_start(timer_eig);
auto &eig_val = eofdata[varID][levelID].eig_val; auto &eig_val = eofdata[varID][levelID].eig_val;
......
...@@ -144,7 +144,7 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in ...@@ -144,7 +144,7 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in
if (cdoAssertFilesOnly() == false) if (cdoAssertFilesOnly() == false)
cdoAbort("infile1 cannot be a pipe"); cdoAbort("infile1 cannot be a pipe");
const auto maxrecs = vlistNrecs(vlistID1); const auto maxrecs = vlistNrecs(vlistID1);
CdiStreamID cdiStream = streamOpenRead(cdoGetStreamName(0)); auto cdiStream = streamOpenRead(cdoGetStreamName(0));
const auto cdiVlistID = streamInqVlist(cdiStream); const auto cdiVlistID = streamInqVlist(cdiStream);
const auto cdiTaxisID = vlistInqTaxis(cdiVlistID); const auto cdiTaxisID = vlistInqTaxis(cdiVlistID);
...@@ -152,14 +152,17 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in ...@@ -152,14 +152,17 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in
int tempdpy = 0; int tempdpy = 0;
for ( int i = 0; i<MaxMonths; i++) for ( int i = 0; i<MaxMonths; i++)
tempdpm[i] = 0; tempdpm[i] = 0;
int year, month, day, tsID = 0, nrecs = 0, varID, levelID; int year, month, day, tsID = 0, varID, levelID;
bool lHasStarted = false; bool lHasStarted = false;
if (Options::cdoVerbose) cdoPrint("Start to process variables"); if (Options::cdoVerbose) cdoPrint("Start to process variables");
while ( ( nrecs = streamInqTimestep(cdiStream, tsID++) ) ) while (true)
{ {
int64_t vdate = taxisInqVdate(cdiTaxisID); const auto nrecs = streamInqTimestep(cdiStream, tsID++);
if (nrecs == 0) break;
auto vdate = taxisInqVdate(cdiTaxisID);
cdiDecodeDate(vdate, &year, &month, &day); cdiDecodeDate(vdate, &year, &month, &day);
if ( !lHasStarted && year != recentYear ) if ( !lHasStarted && year != recentYear )
continue; continue;
...@@ -180,14 +183,13 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in ...@@ -180,14 +183,13 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in
fieldFill(cei[loopmonth][0][0], 0.); fieldFill(cei[loopmonth][0][0], 0.);
} }
} }
if ( year == endOfCalc && func2 == func_avg ) if (year == endOfCalc && func2 == func_avg) break;
break;
tempdpy++; tempdpy++;
int dayoy = (month >= 1 && month <= 12) ? (month - 1) * 31 + day : 0; int dayoy = (month >= 1 && month <= 12) ? (month - 1) * 31 + day : 0;
tempdpm[month-1]++; tempdpm[month-1]++;
if ( func2 == func_sum ) if ( func2 == func_sum ) dayoy = 1;
dayoy = 1;
for (int recID = 0; recID < nrecs; recID++) for (int recID = 0; recID < nrecs; recID++)
{ {
streamInqRecord(cdiStream, &varID, &levelID); streamInqRecord(cdiStream, &varID, &levelID);
...@@ -217,7 +219,7 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in ...@@ -217,7 +219,7 @@ static void calculateOuterPeriod(Field &field, int MaxMonths, int recentYear, in
fieldFill(cei[0][0][0], 0.); fieldFill(cei[0][0][0], 0.);
if ( frequency == 8 ) if ( frequency == 8 )
for ( int loopmonth = 1; loopmonth < MaxMonths; loopmonth++) for (int loopmonth = 1; loopmonth < MaxMonths; loopmonth++)
{ {
tempdpm[loopmonth] = 0; tempdpm[loopmonth] = 0;
fieldFill(cei[loopmonth][0][0], 0.); fieldFill(cei[loopmonth][0][0], 0.);
...@@ -232,7 +234,6 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -232,7 +234,6 @@ etccdi_op(ETCCDI_REQUEST *request)
constexpr int MaxDays = 373; constexpr int MaxDays = 373;
constexpr int MaxMonths = 12; constexpr int MaxMonths = 12;
int varID; int varID;
int nrecs;
int levelID; int levelID;
size_t nmiss; size_t nmiss;
int year, month, day, dayoy; int year, month, day, dayoy;
...@@ -336,8 +337,11 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -336,8 +337,11 @@ etccdi_op(ETCCDI_REQUEST *request)
int tsID = 0; int tsID = 0;
while ((nrecs = cdoStreamInqTimestep(streamID2, tsID))) while (true)
{ {
const auto nrecs = cdoStreamInqTimestep(streamID2, tsID);
if (nrecs == 0) break;
if (nrecs != cdoStreamInqTimestep(streamID3, tsID)) if (nrecs != cdoStreamInqTimestep(streamID3, tsID))
cdoAbort("Number of records at time step %d of %s and %s differ!", tsID + 1, cdoGetStreamName(1), cdoAbort("Number of records at time step %d of %s and %s differ!", tsID + 1, cdoGetStreamName(1),
cdoGetStreamName(2)); cdoGetStreamName(2));
...@@ -396,6 +400,7 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -396,6 +400,7 @@ etccdi_op(ETCCDI_REQUEST *request)
else else
cdoReadRecord(streamID3, field.vec_d.data(), &nmiss); cdoReadRecord(streamID3, field.vec_d.data(), &nmiss);
field.nmiss = nmiss; field.nmiss = nmiss;
field.size = vars2[dayoy][varID][levelID].size;
field.grid = vars2[dayoy][varID][levelID].grid; field.grid = vars2[dayoy][varID][levelID].grid;
field.missval = vars2[dayoy][varID][levelID].missval; field.missval = vars2[dayoy][varID][levelID].missval;
...@@ -414,8 +419,11 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -414,8 +419,11 @@ etccdi_op(ETCCDI_REQUEST *request)
tsID = 0; tsID = 0;
bool lOnlyRefPeriod = true; bool lOnlyRefPeriod = true;
int firstYear = 0, lastYear = 0; int firstYear = 0, lastYear = 0;
while ( (nrecs = cdoStreamInqTimestep(streamID1, tsID++) ) ) while (true)
{ {
const auto nrecs = cdoStreamInqTimestep(streamID1, tsID++);
if (nrecs == 0) break;
vdate = taxisInqVdate(taxisID1); vdate = taxisInqVdate(taxisID1);
vtime = taxisInqVtime(taxisID1); vtime = taxisInqVtime(taxisID1);
...@@ -434,7 +442,7 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -434,7 +442,7 @@ etccdi_op(ETCCDI_REQUEST *request)
if (dayoy < 0 || dayoy >= MaxDays) cdoAbort("Day %d out of range!", dayoy); if (dayoy < 0 || dayoy >= MaxDays) cdoAbort("Day %d out of range!", dayoy);
if (wdaysSrc[dayoy] || request->func2 == func_sum ) if (wdaysSrc[dayoy] || request->func2 == func_sum )
{ {
/* Variable independent ? */ /* Variable independent ? */
wdaysRead[dayoy+(year-request->startboot)*(MaxDays-1)] = dayoy+(year-request->startboot)*(MaxDays-1); wdaysRead[dayoy+(year-request->startboot)*(MaxDays-1)] = dayoy+(year-request->startboot)*(MaxDays-1);
dpy[year-request->startboot]++; dpy[year-request->startboot]++;
dpm[(year-request->startboot)*MaxMonths+(int)((dayoy-1)/31.)]++; dpm[(year-request->startboot)*MaxMonths+(int)((dayoy-1)/31.)]++;
...@@ -792,6 +800,7 @@ etccdi_op(ETCCDI_REQUEST *request) ...@@ -792,6 +800,7 @@ etccdi_op(ETCCDI_REQUEST *request)
} }
field.resize(gridsizemax); field.resize(gridsizemax);
field.missval = vars1[1][0][0].missval; field.missval = vars1[1][0][0].missval;
field.size = vars1[1][0][0].size;
field.grid = vars1[1][0][0].grid; field.grid = vars1[1][0][0].grid;
calculateOuterPeriod(field, MaxMonths, request->endboot+1, lastYear+1, cei, varsPtemp, frequency, taxisID4, streamID4, &otsID, vlistID1, recinfo, selection, request->func2); calculateOuterPeriod(field, MaxMonths, request->endboot+1, lastYear+1, cei, varsPtemp, frequency, taxisID4, streamID4, &otsID, vlistID1, recinfo, selection, request->func2);
} }
......
...@@ -104,7 +104,7 @@ exprsFromFile(const std::vector<std::string> &exprArgv) ...@@ -104,7 +104,7 @@ exprsFromFile(const std::vector<std::string> &exprArgv)
if (exprArgc != 1) operatorCheckArgc(1); if (exprArgc != 1) operatorCheckArgc(1);
auto exprf = exprArgv[0].c_str(); auto exprf = exprArgv[0].c_str();
/* Open expr script file for reading */ // Open expr script file for reading
auto fp = fopen(exprf, "r"); auto fp = fopen(exprf, "r");
if (!fp) cdoAbort("Open failed on %s", exprf); if (!fp) cdoAbort("Open failed on %s", exprf);
...@@ -136,7 +136,7 @@ str_replace(char *target, const char *needle, const char *replacement) ...@@ -136,7 +136,7 @@ str_replace(char *target, const char *needle, const char *replacement)
const auto needle_len = strlen(needle); const auto needle_len = strlen(needle);
const auto repl_len = strlen(replacement); const auto repl_len = strlen(replacement);
while (1) while (true)
{ {
char *p = strstr(tmp, needle); char *p = strstr(tmp, needle);
...@@ -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;
...@@ -329,29 +330,26 @@ params_add_coordinates(int vlistID, parseParamType &parse_arg) ...@@ -329,29 +330,26 @@ params_add_coordinates(int vlistID, parseParamType &parse_arg)
static int static int
params_add_ts(parseParamType &parse_arg) params_add_ts(parseParamType &parse_arg)
{ {
int varID = -1; auto &params = parse_arg.params;
auto params = parse_arg.params;
if (params) auto varID = parse_arg.nparams;
{ if (varID >= parse_arg.maxparams) cdoAbort("Too many parameter (limit=%d)", parse_arg.maxparams);
varID = parse_arg.nparams;
if (varID >= parse_arg.maxparams) cdoAbort("Too many parameter (limit=%d)", parse_arg.maxparams); params[varID].name = strdup("_ts");
params[varID].gridID = parse_arg.pointID;
params[varID].name = strdup("_ts"); params[varID].zaxisID = parse_arg.surfaceID;
params[varID].gridID = parse_arg.pointID; params[varID].steptype = TIME_VARYING;
params[varID].zaxisID = parse_arg.surfaceID; params[varID].ngp = CLEN;
params[varID].steptype = TIME_VARYING; params[varID].nlev = 1;
params[varID].ngp = CLEN;
params[varID].nlev = 1; parse_arg.nparams++;
parse_arg.cnparams++;
parse_arg.nparams++;
parse_arg.cnparams++;