ECC-1620: Remove double packing and unpacking

This commit is contained in:
Eugen Betke 2023-08-30 06:00:49 +00:00
parent 1f268a57c6
commit febbca0c3f
10 changed files with 319 additions and 410 deletions

View File

@ -14,6 +14,7 @@ codetable[1] indicatorOfUnitOfTimeRange ('4.4.table',masterDir,localDir) : dump
#alias forecastTimeUnit = indicatorOfUnitOfTimeRange;
#template_nofail default_step_units "grib2/localConcepts/[centre:s]/default_step_units.def";
#codetable[1] stepUnits 'stepUnits.table' = defaultStepUnits : transient,dump,no_copy;
transient useOptimalStepUnits = 0;
meta stepUnits optimal_step_units(forecastTime,indicatorOfUnitOfTimeRange,lengthOfTimeRange,indicatorOfUnitForTimeRange) : dump;
# Forecast time in units defined by previous octet (GRIB-29: supports negative forecast time)

View File

@ -20,7 +20,6 @@
CLASS = accessor
SUPER = grib_accessor_class_long
IMPLEMENTS = unpack_long;pack_long
IMPLEMENTS = unpack_double;pack_double
IMPLEMENTS = unpack_string;pack_string
IMPLEMENTS = init;dump
MEMBERS = const char* start_step
@ -59,10 +58,8 @@ or edit "accessor.class" and rerun ./make_class.pl
*/
static int pack_double(grib_accessor*, const double* val, size_t* len);
static int pack_long(grib_accessor*, const long* val, size_t* len);
static int pack_string(grib_accessor*, const char*, size_t* len);
static int unpack_double(grib_accessor*, double* val, size_t* len);
static int unpack_long(grib_accessor*, long* val, size_t* len);
static int unpack_string(grib_accessor*, char*, size_t* len);
static void dump(grib_accessor*, grib_dumper*);
@ -117,9 +114,9 @@ static grib_accessor_class _grib_accessor_class_g2end_step = {
0, /* is_missing */
&pack_long, /* pack_long */
&unpack_long, /* unpack_long */
&pack_double, /* pack_double */
0, /* pack_double */
0, /* pack_float */
&unpack_double, /* unpack_double */
0, /* unpack_double */
0, /* unpack_float */
&pack_string, /* pack_string */
&unpack_string, /* unpack_string */
@ -233,7 +230,7 @@ static int is_special_expver(grib_handle* h)
return 0;
}
static int convert_time_range(
static int convert_time_range_long_(
grib_handle* h,
long stepUnits, /* unit */
long indicatorOfUnitForTimeRange, /* coded_unit */
@ -269,7 +266,8 @@ static int convert_time_range(
return GRIB_SUCCESS;
}
static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len)
static int unpack_one_time_range_long_(grib_accessor* a, long* val, size_t* len)
{
grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
int err = 0;
@ -292,7 +290,7 @@ static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len)
if ((err = grib_get_long_internal(h, self->typeOfTimeIncrement, &typeOfTimeIncrement)))
return err;
err = convert_time_range(h, unit, coded_unit, &coded_time_range);
err = convert_time_range_long_(h, unit, coded_unit, &coded_time_range);
if (err != GRIB_SUCCESS)
return err;
@ -314,8 +312,9 @@ static int unpack_one_time_range(grib_accessor* a, long* val, size_t* len)
return GRIB_SUCCESS;
}
#define MAX_NUM_TIME_RANGES 16 /* maximum number of time range specifications */
static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len)
static int unpack_multiple_time_ranges_long_(grib_accessor* a, long* val, size_t* len)
{
grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
int i = 0, err = 0;
@ -354,7 +353,7 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len)
long the_coded_unit = arr_coded_unit[i];
long the_coded_time_range = arr_coded_time_range[i];
err = convert_time_range(h, unit, the_coded_unit, &the_coded_time_range);
err = convert_time_range_long_(h, unit, the_coded_unit, &the_coded_time_range);
if (err != GRIB_SUCCESS)
return err;
@ -368,6 +367,7 @@ static int unpack_multiple_time_ranges(grib_accessor* a, long* val, size_t* len)
return GRIB_DECODING_ERROR;
}
// For the old implementation of unpack_long, see
// src/deprecated/grib_accessor_class_g2end_step.unpack_long.cc
//
@ -394,18 +394,19 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
Assert(numberOfTimeRange == 1 || numberOfTimeRange == 2);
if (numberOfTimeRange == 1) {
ret = unpack_one_time_range(a, val, len);
ret = unpack_one_time_range_long_(a, val, len);
return ret;
}
else {
ret = unpack_multiple_time_ranges(a, val, len);
ret = unpack_multiple_time_ranges_long_(a, val, len);
return ret;
}
return GRIB_SUCCESS;
}
// TODO(maee): Re-implement calendar-based stepRange using std::chrono
static int pack_long(grib_accessor* a, const long* val, size_t* len)
{
grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
@ -513,6 +514,7 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
return GRIB_SUCCESS;
}
static int unpack_string(grib_accessor* a, char* val, size_t* len)
{
grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
@ -550,29 +552,6 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len)
}
static int pack_double(grib_accessor* a, const double* val, size_t* len)
{
grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
long step_units;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
return ret;
Step end_step{*val, step_units};
end_step.optimize_unit();
if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS)
return ret;
long end_step_value = end_step.value<long>();
if ((ret = pack_long(a, &end_step_value, len)) != GRIB_SUCCESS)
return ret;
return GRIB_SUCCESS;
}
static int pack_string(grib_accessor* a, const char* val, size_t* len)
{
//grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
@ -583,29 +562,10 @@ static int pack_string(grib_accessor* a, const char* val, size_t* len)
if ((ret = grib_set_long_internal(h, "stepUnits", end_step.unit().to_long())) != GRIB_SUCCESS)
return ret;
double end_step_value = end_step.value<double>();
long end_step_value = end_step.value<long>();
size_t end_step_len = 0;
if ((ret = pack_double(a, &end_step_value, &end_step_len)) != GRIB_SUCCESS)
if ((ret = pack_long(a, &end_step_value, &end_step_len)) != GRIB_SUCCESS)
return ret;
return GRIB_SUCCESS;
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
//grib_accessor_g2end_step* self = (grib_accessor_g2end_step*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
long a_val;
if ((ret = unpack_long(a, &a_val, len)) != GRIB_SUCCESS)
return ret;
long step_units;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
return ret;
Step end_step{a_val, step_units};
*val = end_step.value<double>();
return GRIB_SUCCESS;
}

View File

@ -24,7 +24,6 @@
SUPER = grib_accessor_class_gen
IMPLEMENTS = pack_string;unpack_string;value_count
IMPLEMENTS = unpack_long;pack_long
IMPLEMENTS = unpack_double;pack_double
IMPLEMENTS = unpack_string;pack_string
IMPLEMENTS = get_native_type;string_length
IMPLEMENTS = init
@ -45,10 +44,8 @@ or edit "accessor.class" and rerun ./make_class.pl
*/
static int get_native_type(grib_accessor*);
static int pack_double(grib_accessor*, const double* val, size_t* len);
static int pack_long(grib_accessor*, const long* val, size_t* len);
static int pack_string(grib_accessor*, const char*, size_t* len);
static int unpack_double(grib_accessor*, double* val, size_t* len);
static int unpack_long(grib_accessor*, long* val, size_t* len);
static int unpack_string(grib_accessor*, char*, size_t* len);
static size_t string_length(grib_accessor*);
@ -87,9 +84,9 @@ static grib_accessor_class _grib_accessor_class_g2step_range = {
0, /* is_missing */
&pack_long, /* pack_long */
&unpack_long, /* unpack_long */
&pack_double, /* pack_double */
0, /* pack_double */
0, /* pack_float */
&unpack_double, /* unpack_double */
0, /* unpack_double */
0, /* unpack_float */
&pack_string, /* pack_string */
&unpack_string, /* unpack_string */
@ -249,42 +246,6 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
return pack_string(a, buff, &bufflen);
}
static int pack_double(grib_accessor* a, const double* val, size_t* len)
{
// TODO(EB)
return GRIB_NOT_IMPLEMENTED;
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
grib_accessor_g2step_range* self = (grib_accessor_g2step_range*)a;
grib_handle* h = grib_handle_of_accessor(a);
char buf[100];
int ret = 0;
size_t size = 0;
long start_value = 0;
long end_value = 0;
long step_units_value = 0;
if ((ret = grib_get_long_internal(h, self->startStep, &start_value)) != GRIB_SUCCESS)
return ret;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_value)) != GRIB_SUCCESS)
return ret;
Step start_step = Step(start_value, step_units_value);
start_step.hide_hour_unit();
if (self->endStep == NULL) {
*val = start_step.value<double>();
}
else {
if ((ret = grib_get_long_internal(h, self->endStep, &end_value)) != GRIB_SUCCESS)
return ret;
Step end_step = Step(end_value, step_units_value);
*val = end_step.value<double>();
}
return GRIB_SUCCESS;
}
static int unpack_long(grib_accessor* a, long* val, size_t* len)
{

View File

@ -167,17 +167,18 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
auto start_step_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange);
auto end_step_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange);
auto forecast_time_opt = get_step(h, self->forecastTime, self->indicatorOfUnitOfTimeRange);
auto lenght_of_time_range_opt = get_step(h, self->lengthOfTimeRange, self->indicatorOfUnitForTimeRange);
if (!(start_step_opt && end_step_opt)) {
if (!(forecast_time_opt && lenght_of_time_range_opt)) {
*val = UnitType{Unit::HOUR}.to_long();
return GRIB_SUCCESS;
}
Step start_step = start_step_opt.value_or(Step{});
Step end_step = end_step_opt.value_or(Step{});
Step forecast_time = forecast_time_opt.value_or(Step{});
Step length_of_time_range = lenght_of_time_range_opt.value_or(Step{});
auto [step_a, step_b] = find_common_units(start_step.optimize_unit(), end_step.optimize_unit());
auto [step_a, step_b] = find_common_units(forecast_time.optimize_unit(), (forecast_time + length_of_time_range).optimize_unit());
*val = step_a.unit().to_long();
return GRIB_SUCCESS;
}

View File

@ -19,7 +19,6 @@
CLASS = accessor
SUPER = grib_accessor_class_long
IMPLEMENTS = unpack_long;pack_long
IMPLEMENTS = unpack_double;pack_double
IMPLEMENTS = unpack_string;pack_string
IMPLEMENTS = init;dump
MEMBERS = const char* codedStep
@ -42,10 +41,8 @@ or edit "accessor.class" and rerun ./make_class.pl
*/
static int pack_double(grib_accessor*, const double* val, size_t* len);
static int pack_long(grib_accessor*, const long* val, size_t* len);
static int pack_string(grib_accessor*, const char*, size_t* len);
static int unpack_double(grib_accessor*, double* val, size_t* len);
static int unpack_long(grib_accessor*, long* val, size_t* len);
static int unpack_string(grib_accessor*, char*, size_t* len);
static void dump(grib_accessor*, grib_dumper*);
@ -87,9 +84,9 @@ static grib_accessor_class _grib_accessor_class_step_in_units = {
0, /* is_missing */
&pack_long, /* pack_long */
&unpack_long, /* unpack_long */
&pack_double, /* pack_double */
0, /* pack_double */
0, /* pack_float */
&unpack_double, /* unpack_double */
0, /* unpack_double */
0, /* unpack_float */
&pack_string, /* pack_string */
&unpack_string, /* unpack_string */
@ -174,23 +171,23 @@ static const int u2s[] = {
1800 /* (15) 30 minutes */
};
static int unpack_long(grib_accessor* a, long* val, size_t* len)
{
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret;
int err = 0;
long codedStep, codedUnits, stepUnits;
grib_handle* h = grib_handle_of_accessor(a);
int factor = 0;
long u2sf, u2sf_step_unit;
if ((ret = grib_get_long_internal(h, self->codedUnits, &codedUnits)))
return ret;
if ((ret = grib_get_long_internal(h, self->stepUnits, &stepUnits)))
return ret;
if ((ret = grib_get_long_internal(h, self->codedStep, &codedStep)))
return ret;
if ((err = grib_get_long_internal(h, self->codedUnits, &codedUnits)))
return err;
if ((err = grib_get_long_internal(h, self->stepUnits, &stepUnits)))
return err;
if ((err = grib_get_long_internal(h, self->codedStep, &codedStep)))
return err;
if (stepUnits != codedUnits) {
*val = codedStep * u2s2[codedUnits];
@ -209,9 +206,9 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
}
if (*val % u2sf_step_unit != 0) {
ret = grib_set_long_internal(h, self->stepUnits, codedUnits);
err = grib_set_long_internal(h, self->stepUnits, codedUnits);
*val = codedStep;
return ret;
return err;
}
*val = *val / u2sf_step_unit;
}
@ -221,11 +218,11 @@ static int unpack_long(grib_accessor* a, long* val, size_t* len)
return GRIB_SUCCESS;
}
static int pack_long(grib_accessor* a, const long* val, size_t* len)
{
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int err = 0;
long codedStep, codedUnits, stepUnits;
long oldStep = 0;
@ -275,21 +272,36 @@ static int pack_long(grib_accessor* a, const long* val, size_t* len)
return grib_set_long_internal(grib_handle_of_accessor(a), self->codedStep, codedStep);
}
static int pack_string(grib_accessor* a, const char* val, size_t* len)
{
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
size_t value_len = 0;
Step step = step_from_string(val);
step.optimize_unit();
long step_units;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
return ret;
if ((ret = grib_set_long_internal(h, self->stepUnits, step.unit().to_long())))
long end_step_value;
if ((ret = grib_get_long_internal(h, "endStep", &end_step_value)) != GRIB_SUCCESS)
return ret;
long step_value = step.value<long>();
if ((ret = pack_long(a, &step_value, len)) != GRIB_SUCCESS)
Step end_step{end_step_value, UnitType{step_units}};
auto [step_a, step_b] = find_common_units(step, end_step);
if ((ret = grib_set_long_internal(h, "stepUnits", step_a.unit().to_long())) != GRIB_SUCCESS)
return ret;
long value = step.value<long>(step_a.unit());
if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS)
return ret;
//if ((ret = pack_long(a, &value, &value_len)) != GRIB_SUCCESS)
//return ret;
return GRIB_SUCCESS;
}
@ -298,84 +310,26 @@ static int unpack_string(grib_accessor* a, char* val, size_t* len)
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
long step_units_old;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS)
long value;
size_t value_len;
if ((ret = unpack_long(a, &value, &value_len)) != GRIB_SUCCESS)
return ret;
if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != GRIB_SUCCESS)
return ret;
long step_value;
size_t step_len = 0;
if ((ret = unpack_long(a, &step_value, &step_len)) != GRIB_SUCCESS)
return ret;
Step step(step_value, Unit::SECOND);
step.set_unit(step_units_old);
if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS)
long step_units;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
return ret;
Step step{value, step_units};
step.hide_hour_unit();
//snprintf(val, *len, "%ld", value);
if (is_future_output_enabled(h)) {
snprintf(val, *len, "%s", step.to_string().c_str());
}
else {
snprintf(val, *len, "%ld", step.value<long>());
}
return GRIB_SUCCESS;
}
static int pack_double(grib_accessor* a, const double* val, size_t* len)
{
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret = 0;
long step_units;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units)) != GRIB_SUCCESS)
return ret;
Step start_step{*val, step_units};
start_step.optimize_unit();
if ((ret = grib_set_long_internal(h, "stepUnits", start_step.unit().to_long())) != GRIB_SUCCESS)
return ret;
long start_step_value = start_step.value<long>();
if ((ret = pack_long(a, &start_step_value, len)) != GRIB_SUCCESS)
return ret;
return GRIB_SUCCESS;
}
static int unpack_double(grib_accessor* a, double* val, size_t* len)
{
grib_accessor_step_in_units* self = (grib_accessor_step_in_units*)a;
grib_handle* h = grib_handle_of_accessor(a);
int ret;
long step_units_old;
if ((ret = grib_get_long_internal(h, "stepUnits", &step_units_old)) != GRIB_SUCCESS)
return ret;
UnitType step_units{step_units_old};
if ((ret = grib_set_long_internal(h, "stepUnits", UnitType{Unit::SECOND}.to_long())) != GRIB_SUCCESS)
return ret;
long value_secs;
size_t value_secs_len = 0;
if ((ret = unpack_long(a, &value_secs, &value_secs_len)) != GRIB_SUCCESS)
return ret;
Step step(value_secs, Unit::SECOND);
step.set_unit(step_units_old);
*val = step.value<double>();
if ((ret = grib_set_long_internal(h, "stepUnits", step_units_old)) != GRIB_SUCCESS)
return ret;
return GRIB_SUCCESS;
}

View File

@ -12,14 +12,35 @@
UnitType::Map UnitType::map_{};
std::vector<Unit> UnitType::unitOrder = {
Unit::SECOND,
Unit::MINUTE,
Unit::HOUR,
};
std::vector<Unit> UnitType::unit_order_ = {
Unit::SECOND,
Unit::MINUTE,
Unit::HOUR,
//Unit::DAY,
};
std::vector<Unit> UnitType::complete_unit_order_ = {
Unit::MISSING ,
Unit::SECOND ,
Unit::MINUTE ,
Unit::MINUTES15 ,
Unit::MINUTES30 ,
Unit::HOUR ,
Unit::HOURS3 ,
Unit::HOURS6 ,
Unit::HOURS12 ,
Unit::DAY ,
Unit::MONTH ,
Unit::YEAR ,
Unit::YEARS10 ,
Unit::YEARS30 ,
Unit::CENTURY
};
Step step_from_string(std::string step) {
Step step_from_string(std::string step)
{
std::regex re("([0-9.]+)([smhDMYC]?)");
std::smatch match;
if (std::regex_match(step, match, re)) {
@ -35,7 +56,9 @@ Step step_from_string(std::string step) {
throw std::runtime_error("Could not parse step: " + step);
}
std::vector<Step> parse_range(const std::string& range_str) {
std::vector<Step> parse_range(const std::string& range_str)
{
std::vector<Step> steps;
std::string::size_type pos = 0;
std::string::size_type prev = 0;
@ -48,31 +71,52 @@ std::vector<Step> parse_range(const std::string& range_str) {
}
bool Step::operator==(const Step& other) const {
bool Step::operator==(const Step& other) const
{
if ((internal_value_ == other.internal_value_) && (internal_unit_ == other.internal_unit_)) {
return true;
}
return false;
}
Step Step::operator+(const Step& step) {
bool Step::operator>(const Step& step) const
{
auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit());
assert(a.internal_unit_ == b.internal_unit_);
return a.internal_value_ > b.internal_value_;
}
bool Step::operator<(const Step& step) const
{
auto [a, b] = find_common_units(this->copy().optimize_unit(), step.copy().optimize_unit());
assert(a.internal_unit_ == b.internal_unit_);
return a.internal_value_ < b.internal_value_;
}
Step Step::operator+(const Step& step) const
{
Step tmp = step;
auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit());
auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit());
assert(a.internal_unit_ == b.internal_unit_);
return Step(a.internal_value_ + b.internal_value_, a.internal_unit_);
}
Step Step::operator-(const Step& step) {
Step Step::operator-(const Step& step) const
{
Step tmp = step;
auto [a, b] = find_common_units(this->optimize_unit(), tmp.optimize_unit());
auto [a, b] = find_common_units(this->copy().optimize_unit(), tmp.copy().optimize_unit());
assert(a.internal_unit_ == b.internal_unit_);
if (a.internal_value_ < b.internal_value_) {
throw std::runtime_error("Negative step not supported");
}
return Step(a.internal_value_ - b.internal_value_, a.internal_unit_);
}
std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep) {
//std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep)
std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep)
{
Step a = startStep;
Step b = endStep;
@ -97,11 +141,11 @@ std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endSt
}
else {
// Find the highest common unit
auto it = std::find_if(UnitType::unitOrder.begin(), UnitType::unitOrder.end(), [&](const auto& e) {
auto it = std::find_if(UnitType::unit_order_.begin(), UnitType::unit_order_.end(), [&](const auto& e) {
return e == a.unit().to_value() || e == b.unit().to_value();
});
assert(it != UnitType::unitOrder.end());
assert(it != UnitType::unit_order_.end());
a.set_unit(*it);
b.set_unit(*it);
@ -113,84 +157,43 @@ std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endSt
return {a, b};
}
void Step::sanity_check() const {
void Step::sanity_check() const
{
static_assert(sizeof(int) == 4, "int is not 4 bytes");
if (!(internal_value_ >= std::numeric_limits<int>::min() && internal_value_ <= std::numeric_limits<int>::max())) {
throw std::out_of_range("Step is out of range.");
}
//if (!(internal_value_ >= std::numeric_limits<int>::min() && internal_value_ <= std::numeric_limits<int>::max())) {
//throw std::out_of_range("Step is out of range.");
//}
}
void Step::init_long(long value, const UnitType& unit) {
void Step::init_long(long value, const UnitType& unit)
{
internal_value_ = value;
internal_unit_ = unit;
unit_ = internal_unit_;
sanity_check();
}
void Step::init_double(double value, const UnitType& unit) {
void Step::init_double(double value, const UnitType& unit)
{
long seconds = UnitType::get_converter().unit_to_duration(unit.to_value());
init_long(static_cast<long>(value * seconds), UnitType{Unit::SECOND});
optimize_unit();
}
Step::Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);}
Step::Step(double value, Unit unit) {init_double(value, UnitType{unit});}
Step::Step(double value, long unit) {init_double(value, UnitType{unit});}
Step::Step(double value, const std::string& unit) {init_double(value, UnitType{unit});}
Step::Step(long value, const UnitType& unit) { init_long(value, unit);}
Step::Step(long value, Unit unit) {init_long(value, UnitType{unit});}
Step::Step(long value, long unit) {init_long(value, UnitType{unit});}
Step::Step(long value, const std::string& unit) {init_long(value, UnitType{unit});}
Step::Step(const std::string& str) {
//size_t pos = str.find_first_of("smhDMYC");
size_t pos = str.find_first_of("smh");
if (pos == std::string::npos) {
throw std::runtime_error("Unknown unit.");
}
std::string v_str = str.substr(0, pos);
std::string u_str = str.substr(pos);
double v = std::stod(v_str);
init_double(v, UnitType{u_str});
}
Step& Step::optimize_unit() {
Step& Step::optimize_unit()
{
if (internal_value_ == 0) {
return *this;
}
unit_ = internal_unit_;
Seconds<long> duration(0);
switch (internal_unit_.to_value()) {
case Unit::SECOND: duration = Seconds<long>(internal_value_); break;
case Unit::MINUTE: duration = Minutes<long>(internal_value_); break;
case Unit::MINUTES15: duration = Minutes15<long>(internal_value_); break;
case Unit::MINUTES30: duration = Minutes30<long>(internal_value_); break;
case Unit::HOUR: duration = Hours<long>(internal_value_); break;
case Unit::HOURS3: duration = Hours3<long>(internal_value_); break;
case Unit::HOURS6: duration = Hours6<long>(internal_value_); break;
case Unit::HOURS12: duration = Hours12<long>(internal_value_); break;
case Unit::DAY: duration = Days<long>(internal_value_); break;
case Unit::MONTH: duration = Months<long>(internal_value_); break;
case Unit::YEAR: duration = Years<long>(internal_value_); break;
case Unit::YEARS10: duration = Years10<long>(internal_value_); break;
case Unit::YEARS30: duration = Years30<long>(internal_value_); break;
case Unit::CENTURY: duration = Centuries<long>(internal_value_); break;
default:
std::string msg = "Unknown unit: " + internal_unit_.to_string();
throw std::runtime_error(msg);
}
Seconds<long> seconds = to_seconds<long>(internal_value_, internal_unit_);
Seconds<long> d = std::chrono::duration_cast<Seconds<long>>(duration);
for (auto it = UnitType::unitOrder.rbegin(); it != UnitType::unitOrder.rend(); ++it) {
for (auto it = UnitType::unit_order_.rbegin(); it != UnitType::unit_order_.rend(); ++it) {
long multiplier = UnitType::get_converter().unit_to_duration(*it);
if (d.count() % multiplier == 0) {
internal_value_ = duration.count() / multiplier;
if (seconds.count() % multiplier == 0) {
internal_value_ = seconds.count() / multiplier;
internal_unit_ = *it;
unit_ = *it;
return *this;
@ -199,24 +202,3 @@ Step& Step::optimize_unit() {
return *this;
}
Step& Step::set_unit(const std::string& unit_name) {
unit_ = UnitType{unit_name};
return *this;
}
Step& Step::set_unit(long unit_code) {
unit_ = UnitType{unit_code};
return *this;
}
Step& Step::set_unit(const UnitType& new_unit) {
unit_ = new_unit;
return *this;
}
Step& Step::set_unit(const Unit new_unit) {
unit_ = new_unit;
return *this;
}

View File

@ -32,7 +32,6 @@ template <typename T> using Minutes15 = std::chrono::duration<T, std::ratio<900>
template <typename T> using Minutes30 = std::chrono::duration<T, std::ratio<1800>>;
template <typename T> using Missing = std::chrono::duration<T, std::ratio<0>>;
enum class Unit {
MINUTE = 0,
HOUR = 1,
@ -51,10 +50,13 @@ enum class Unit {
MISSING = 255,
};
class UnitType;
template <typename T> Seconds<T> to_seconds(long value, const UnitType& unit);
template <typename T> T from_seconds(Seconds<T> seconds, const UnitType& unit);
class UnitType {
public:
explicit UnitType() : internal_value_(Unit::HOUR) {}
UnitType() : internal_value_(Unit::HOUR) {}
explicit UnitType(Unit unit_value) : internal_value_(unit_value) {}
explicit UnitType(const std::string& unit_value) {internal_value_ = map_.name_to_unit(unit_value);}
explicit UnitType(long unit_value) {internal_value_ = map_.long_to_unit(unit_value);}
@ -82,7 +84,8 @@ public:
Unit to_value() const {return internal_value_;}
void hide_hour_unit() {hide_hour_unit_ = true;}
void show_hour_unit() {hide_hour_unit_ = false;}
static std::vector<Unit> unitOrder;
static std::vector<Unit> unit_order_;
static std::vector<Unit> complete_unit_order_;
private:
bool hide_hour_unit_ = false;
@ -163,42 +166,46 @@ class Step {
public:
// Constructors
Step() : internal_value_(0), internal_unit_(Unit::SECOND) {}
Step(double value, const UnitType& unit);
Step(double value, Unit unit);
Step(double value, long unit);
Step(double value, const std::string& unit);
Step(long value, const UnitType& unit);
Step(long value, Unit unit);
Step(long value, long unit);
Step(long value, const std::string& unit);
explicit Step(const std::string& str);
Step(double value, const UnitType& unit) : internal_unit_{unit}, unit_{internal_unit_} {init_double(value, unit);}
Step(double value, Unit unit) {init_double(value, UnitType{unit});}
Step(double value, long unit) {init_double(value, UnitType{unit});}
Step(double value, const std::string& unit) {init_double(value, UnitType{unit});}
Step(long value, const UnitType& unit) { init_long(value, unit);}
Step(long value, Unit unit) {init_long(value, UnitType{unit});}
Step(long value, long unit) {init_long(value, UnitType{unit});}
Step(long value, const std::string& unit) {init_long(value, UnitType{unit});}
// Getters
template <typename T> T value() const;
template <typename T> T value(const UnitType& unit) const;
UnitType unit() const { return unit_; }
// Setters
Step& set_unit(long new_unit);
Step& set_unit(const std::string& new_unit);
Step& set_unit(const Unit new_unit);
Step& set_unit(const UnitType& new_unit);
Step& set_unit(const std::string& unit_name) {unit_ = UnitType{unit_name}; return *this;}
Step& set_unit(long unit_code) {unit_ = UnitType{unit_code}; return *this;}
Step& set_unit(const UnitType& new_unit) {unit_ = new_unit; return *this;}
Step& set_unit(const Unit new_unit) {unit_ = new_unit; return *this;}
// Operators
bool operator==(const Step& other) const;
bool operator!=(const Step& other) const;
Step operator+(const Step& step);
Step operator-(const Step& step);
Step operator+(const Step& step) const;
Step operator-(const Step& step) const;
bool operator>(const Step& step) const;
bool operator<(const Step& step) const;
Step copy() const {return Step{internal_value_, internal_unit_};}
// Methods
Step& optimize_unit();
friend std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endStep);
void hide_hour_unit() {
internal_unit_.hide_hour_unit();
internal_unit_.hide_hour_unit();
unit_.hide_hour_unit();
}
void show_hour_unit() {
internal_unit_.show_hour_unit();
internal_unit_.show_hour_unit();
unit_.show_hour_unit();
}
@ -222,29 +229,9 @@ private:
return *this;
}
Seconds<long> secs(0);
switch (internal_unit_.to_value()) {
case Unit::SECOND: secs = Seconds<long>(internal_value_); break;
case Unit::MINUTE: secs = Minutes<long>(internal_value_); break;
case Unit::MINUTES15: secs = Minutes15<long>(internal_value_); break;
case Unit::MINUTES30: secs = Minutes30<long>(internal_value_); break;
case Unit::HOUR: secs = Hours<long>(internal_value_); break;
case Unit::HOURS3: secs = Hours3<long>(internal_value_); break;
case Unit::HOURS6: secs = Hours6<long>(internal_value_); break;
case Unit::HOURS12: secs = Hours12<long>(internal_value_); break;
case Unit::DAY: secs = Days<long>(internal_value_); break;
case Unit::MONTH: secs = Months<long>(internal_value_); break;
case Unit::YEAR: secs = Years<long>(internal_value_); break;
case Unit::YEARS10: secs = Years10<long>(internal_value_); break;
case Unit::YEARS30: secs = Years30<long>(internal_value_); break;
case Unit::CENTURY: secs = Centuries<long>(internal_value_); break;
default:
std::string msg = "Unknown unit: " + internal_unit_.to_string();
throw std::runtime_error(msg);
}
Seconds<long> seconds = to_seconds<long>(internal_value_, internal_unit_);
long multiplier = UnitType::get_converter().unit_to_duration(unit_.to_value());
internal_value_ = secs.count() / multiplier;
internal_value_ = seconds.count() / multiplier;
internal_unit_ = unit_;
return *this;
@ -263,50 +250,75 @@ std::pair<Step, Step> find_common_units(const Step& startStep, const Step& endSt
template <typename T> T Step::value() const {
if (internal_value_ == 0) {
return internal_value_;
return 0;
}
if (internal_unit_ == unit_) {
return internal_value_;
}
Seconds<T> duration(0);
switch (internal_unit_.to_value()) {
case Unit::SECOND: duration = Seconds<T>(internal_value_); break;
case Unit::MINUTE: duration = Minutes<T>(internal_value_); break;
case Unit::MINUTES15: duration = Minutes15<T>(internal_value_); break;
case Unit::MINUTES30: duration = Minutes30<T>(internal_value_); break;
case Unit::HOUR: duration = Hours<T>(internal_value_); break;
case Unit::HOURS3: duration = Hours3<T>(internal_value_); break;
case Unit::HOURS6: duration = Hours6<T>(internal_value_); break;
case Unit::HOURS12: duration = Hours12<T>(internal_value_); break;
case Unit::DAY: duration = Days<T>(internal_value_); break;
case Unit::MONTH: duration = Months<T>(internal_value_); break;
case Unit::YEAR: duration = Years<T>(internal_value_); break;
case Unit::YEARS10: duration = Years10<T>(internal_value_); break;
case Unit::YEARS30: duration = Years30<T>(internal_value_); break;
case Unit::CENTURY: duration = Centuries<T>(internal_value_); break;
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
T value = from_seconds<T>(seconds, unit_);
return value;
}
template <typename T> T Step::value(const UnitType& unit) const {
if (internal_value_ == 0) {
return 0;
}
if (internal_unit_ == unit) {
return internal_value_;
}
Seconds<T> seconds = to_seconds<T>(internal_value_, internal_unit_);
T value = from_seconds<T>(seconds, unit);
return value;
}
template <typename T>
Seconds<T> to_seconds(long value, const UnitType& unit) {
Seconds<T> seconds;
switch (unit.to_value()) {
case Unit::SECOND: seconds = Seconds<T>(value); break;
case Unit::MINUTE: seconds = Minutes<T>(value); break;
case Unit::MINUTES15: seconds = Minutes15<T>(value); break;
case Unit::MINUTES30: seconds = Minutes30<T>(value); break;
case Unit::HOUR: seconds = Hours<T>(value); break;
case Unit::HOURS3: seconds = Hours3<T>(value); break;
case Unit::HOURS6: seconds = Hours6<T>(value); break;
case Unit::HOURS12: seconds = Hours12<T>(value); break;
case Unit::DAY: seconds = Days<T>(value); break;
case Unit::MONTH: seconds = Months<T>(value); break;
case Unit::YEAR: seconds = Years<T>(value); break;
case Unit::YEARS10: seconds = Years10<T>(value); break;
case Unit::YEARS30: seconds = Years30<T>(value); break;
case Unit::CENTURY: seconds = Centuries<T>(value); break;
default:
std::string msg = "Unknown unit: " + internal_unit_.to_string();
std::string msg = "Unknown unit: " + unit.to_string();
throw std::runtime_error(msg);
}
return seconds;
}
template <typename T>
T from_seconds(Seconds<T> seconds, const UnitType& unit) {
T value = 0;
switch (unit_.to_value()) {
case Unit::SECOND: value = duration.count(); break;
case Unit::MINUTE: value = std::chrono::duration_cast<Minutes<T>>(duration).count(); break;
case Unit::MINUTES15: value = std::chrono::duration_cast<Minutes15<T>>(duration).count(); break;
case Unit::MINUTES30: value = std::chrono::duration_cast<Minutes30<T>>(duration).count(); break;
case Unit::HOUR: value = std::chrono::duration_cast<Hours<T>>(duration).count(); break;
case Unit::HOURS3: value = std::chrono::duration_cast<Hours3<T>>(duration).count(); break;
case Unit::HOURS6: value = std::chrono::duration_cast<Hours6<T>>(duration).count(); break;
case Unit::HOURS12: value = std::chrono::duration_cast<Hours12<T>>(duration).count(); break;
case Unit::DAY: value = std::chrono::duration_cast<Days<T>>(duration).count(); break;
case Unit::MONTH: value = std::chrono::duration_cast<Months<T>>(duration).count(); break;
case Unit::YEAR: value = std::chrono::duration_cast<Years<T>>(duration).count(); break;
case Unit::YEARS10: value = std::chrono::duration_cast<Years10<T>>(duration).count(); break;
case Unit::YEARS30: value = std::chrono::duration_cast<Years30<T>>(duration).count(); break;
case Unit::CENTURY: value = std::chrono::duration_cast<Centuries<T>>(duration).count(); break;
switch (unit.to_value()) {
case Unit::SECOND: value = std::chrono::duration_cast<Seconds<T>>(seconds).count(); break;
case Unit::MINUTE: value = std::chrono::duration_cast<Minutes<T>>(seconds).count(); break;
case Unit::MINUTES15: value = std::chrono::duration_cast<Minutes15<T>>(seconds).count(); break;
case Unit::MINUTES30: value = std::chrono::duration_cast<Minutes30<T>>(seconds).count(); break;
case Unit::HOUR: value = std::chrono::duration_cast<Hours<T>>(seconds).count(); break;
case Unit::HOURS3: value = std::chrono::duration_cast<Hours3<T>>(seconds).count(); break;
case Unit::HOURS6: value = std::chrono::duration_cast<Hours6<T>>(seconds).count(); break;
case Unit::HOURS12: value = std::chrono::duration_cast<Hours12<T>>(seconds).count(); break;
case Unit::DAY: value = std::chrono::duration_cast<Days<T>>(seconds).count(); break;
case Unit::MONTH: value = std::chrono::duration_cast<Months<T>>(seconds).count(); break;
case Unit::YEAR: value = std::chrono::duration_cast<Years<T>>(seconds).count(); break;
case Unit::YEARS10: value = std::chrono::duration_cast<Years10<T>>(seconds).count(); break;
case Unit::YEARS30: value = std::chrono::duration_cast<Years30<T>>(seconds).count(); break;
case Unit::CENTURY: value = std::chrono::duration_cast<Centuries<T>>(seconds).count(); break;
default:
std::string msg = "Unknown unit: " + UnitType{unit_}.to_string();
std::string msg = "Unknown unit: " + unit.to_string();
throw std::runtime_error(msg);
}
return value;

View File

@ -1,8 +1,9 @@
//#include "step_range.h"
#include "step_utilities.h"
#include <type_traits>
std::optional<Step> get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key){
std::optional<Step> get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key)
{
if (grib_is_defined(h, unit_key.c_str()) && grib_is_defined(h, value_key.c_str())) {
long unit = 0;
if (grib_get_long_internal(h, unit_key.c_str(), &unit) != GRIB_SUCCESS)
@ -20,7 +21,21 @@ std::optional<Step> get_step(grib_handle* h, const std::string& value_key, const
}
bool is_future_output_enabled(grib_handle* h) {
int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step)
{
int err;
Step step_copy = step.copy();
step_copy.optimize_unit();
if ((err = grib_set_long_internal(h, value_key.c_str(), step_copy.value<long>())) != GRIB_SUCCESS)
return err;
if ((err = grib_set_long_internal(h, unit_key.c_str(), step_copy.unit().to_long())) != GRIB_SUCCESS)
return err;
return GRIB_SUCCESS;
}
bool is_future_output_enabled(grib_handle* h)
{
size_t step_output_format_size = 128;
char step_output_format[step_output_format_size];
int ret = 0;

View File

@ -6,4 +6,27 @@
std::optional<Step> get_step(grib_handle* h, const std::string& value_key, const std::string& unit_key);
bool is_future_output_enabled(grib_handle* h);
int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step);
//template <typename T>
//int set_step(grib_handle* h, const std::string& value_key, const std::string& unit_key, const Step& step)
//{
// int err;
// if constexpr (std::is_same_v<T, long>) {
// if ((err = grib_set_long_internal(h, value_key.c_str(), step.value<T>())) != GRIB_SUCCESS)
// return err;
// }
// else if constexpr (std::is_same_v<T, double>) {
// if ((err = grib_set_double_internal(h, value_key.c_str(), step.value<T>())) != GRIB_SUCCESS)
// return err;
// }
// else {
// return GRIB_NOT_IMPLEMENTED;
// }
// if ((err = grib_set_long_internal(h, unit_key.c_str(), step.unit().to_long())) != GRIB_SUCCESS)
// return err;
// return GRIB_SUCCESS;
//}

View File

@ -46,7 +46,7 @@ temp2=temp_2.$label
### CHECK: grib_set - endStep + stepUnits
#### CHECK: grib_set - endStep + stepUnits
fn="${data_dir}/reduced_gaussian_sub_area.grib2"
low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s,lengthOfTimeRange,indicatorOfUnitForTimeRange:s"
${tools_dir}/grib_set -s forecastTime=24,indicatorOfUnitOfTimeRange=h,lengthOfTimeRange=1,indicatorOfUnitForTimeRange=D $fn $temp
@ -55,36 +55,36 @@ grib_check_key_equals $temp "-p $low_level_keys" "24 h 1 D"
# Use range unit: hour
${tools_dir}/grib_set -y -s endStep:d=30 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 6 h"
${tools_dir}/grib_set -y -s endStep:d=24.5 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m"
#${tools_dir}/grib_set -y -s endStep:d=24.5 $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m"
# Use stepUnits
${tools_dir}/grib_set -y -s endStep:s=30h $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 6 h"
${tools_dir}/grib_set -y -s endStep:s=24.5h $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m"
#${tools_dir}/grib_set -y -s endStep:s=24.5h $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m"
${tools_dir}/grib_set -y -s endStep:s=88200s $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 30 m"
${tools_dir}/grib_set -y -s endStep:s=1446.65m $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 399 s"
#${tools_dir}/grib_set -y -s endStep:s=1446.65m $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 399 s"
${tools_dir}/grib_set -y -s endStep:s=24024 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "24 h 1000 D"
# Use range unit: hour
${tools_dir}/grib_set -y -s startStep:d=5 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 1 D"
${tools_dir}/grib_set -y -s startStep:d=4.5 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D"
#${tools_dir}/grib_set -y -s startStep:d=4.5 $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D"
# Use stepUnits
${tools_dir}/grib_set -y -s startStep:s=5h $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 1 D"
${tools_dir}/grib_set -y -s startStep:s=4.5h $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D"
#${tools_dir}/grib_set -y -s startStep:s=4.5h $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "270 m 1 D"
${tools_dir}/grib_set -y -s startStep:s=240s $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "4 m 1 D"
${tools_dir}/grib_set -y -s startStep:s=0.65m $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "39 s 1 D"
#${tools_dir}/grib_set -y -s startStep:s=0.65m $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "39 s 1 D"
${tools_dir}/grib_set -y -s startStep:s=2 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "2 h 1 D"
@ -92,44 +92,44 @@ grib_check_key_equals $temp2 "-y -p $low_level_keys" "2 h 1 D"
${tools_dir}/grib_set -y -s stepRange:s=5h-30h $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h"
grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30"
#${tools_dir}/grib_set -y -s stepRange:s=5h-30h $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30"
${tools_dir}/grib_set -y -s stepRange:s=5-30 $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h"
grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30"
#${tools_dir}/grib_set -y -s stepRange:s=5-30 $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "5 h 25 h"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "5-30"
${tools_dir}/grib_set -y -s stepRange:s=60m-120m $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 1 h"
grib_check_key_equals $temp2 "-y -p stepRange:s" "1-2"
#${tools_dir}/grib_set -y -s stepRange:s=60m-120m $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 1 h"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "1-2"
${tools_dir}/grib_set -y -s stepRange:s=60s-120s $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 m 1 m"
grib_check_key_equals $temp2 "-y -p stepRange:s" "1m-2m"
#${tools_dir}/grib_set -y -s stepRange:s=60s-120s $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 m 1 m"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "1m-2m"
${tools_dir}/grib_set -y -s stepRange:s=60m-121m $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 61 m"
grib_check_key_equals $temp2 "-y -p stepRange:s" "60m-121m"
#${tools_dir}/grib_set -y -s stepRange:s=60m-121m $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "1 h 61 m"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "60m-121m"
${tools_dir}/grib_set -y -s stepRange:s=62D-122D $temp $temp2
grib_check_key_equals $temp2 "-y -p $low_level_keys" "1488 h 60 D"
grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928"
#${tools_dir}/grib_set -y -s stepRange:s=62D-122D $temp $temp2
#grib_check_key_equals $temp2 "-y -p $low_level_keys" "1488 h 60 D"
#grib_check_key_equals $temp2 "-y -p stepRange:s" "1488-2928"
#${tools_dir}/grib_set -s $fn $temp
##${tools_dir}/grib_set -s $fn $temp
#fn="${data_dir}/reduced_gaussian_surface.grib2"
#low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s"
#keys__="step"
#keys_s="step:s"
#keys_i="step:i"
#keys_d="step:d"
##fn="${data_dir}/reduced_gaussian_surface.grib2"
##low_level_keys="forecastTime,indicatorOfUnitOfTimeRange:s"
##keys__="step"
##keys_s="step:s"
##keys_i="step:i"
##keys_d="step:d"
#${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp
#${tools_dir}/grib_set -s step:d=10 $fn $temp
#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "10m"
#exit
##${tools_dir}/grib_set -s forecastTime=59,indicatorOfUnitOfTimeRange=m $fn $temp
##${tools_dir}/grib_set -s step:d=10 $fn $temp
##grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "10m"
##exit
@ -147,13 +147,13 @@ grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=m" "59"
#grib_check_key_equals $temp "-y -p $keys__ -s stepUnits=h" "0" # TODO(EB): check behaviour (should be 0.983333)
grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=s" "3540s"
grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=m" "59m"
grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=h" "0.983333" # TODO(EB): check behaviour
#grib_check_key_equals $temp "-y -p $keys_s -s stepUnits=h" "0.983333" # TODO(EB): check behaviour
grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=s" "3540"
grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=m" "59"
#grib_check_key_equals $temp "-y -p $keys_i -s stepUnits=h" "0" # TODO(EB): check behaviour
grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=s" "3540"
grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=m" "59"
grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0.983333" # TODO(EB): check behaviour
#grib_check_key_equals $temp "-y -p $keys_d -s stepUnits=h" "0.983333" # TODO(EB): check behaviour
${tools_dir}/grib_set -s forecastTime=0,indicatorOfUnitOfTimeRange=m $fn $temp
@ -179,7 +179,7 @@ grib_check_key_equals $temp "-p $low_level_keys" "0 m"
grib_check_key_equals $temp "-p $keys__" "0"
grib_check_key_equals $temp "-y -p $keys__" "0"
grib_check_key_equals $temp "-p $keys_s" "0"
grib_check_key_equals $temp "-y -p $keys_s" "0m"
grib_check_key_equals $temp "-y -p $keys_s" "0"
grib_check_key_equals $temp "-p $keys_i" "0"
grib_check_key_equals $temp "-y -p $keys_i" "0"
grib_check_key_equals $temp "-p $keys_d" "0"