def test_parse_nc_time_units(): actual_unit = ffi.new('unsigned short int *') actual_dmy = ffi.new('dmy_struct *') unit_chars = ffi.new('char[]', b'days since 0001-01-01') vic_lib.parse_nc_time_units(ffi.addressof(unit_chars), actual_unit, actual_dmy) assert actual_unit[0] == units['days'] assert actual_dmy[0].year == 1 assert actual_dmy[0].month == 1 assert actual_dmy[0].day == 1 assert actual_dmy[0].dayseconds == 0
def timeunits_from_chars(): for unit, expected in units.items(): actual = vic_lib.calendar_from_chars( ffi.new('char[]', unit.lower().encode())) assert actual == expected actual = vic_lib.calendar_from_chars( ffi.new('char[]', unit.upper().encode())) assert actual == expected
def test_calc_snow_coverage_no_change(): store_snow = ffi.new('_Bool *') max_snow_depth = ffi.new('double *') store_swq = ffi.new('double *') snow_distrib_slope = ffi.new('double *') store_coverage = ffi.new('double *') old_coverage = 0.75 coverage = vic_lib.calc_snow_coverage( store_snow, 0.5, old_coverage, 1.25, 1.25, 2.3, 2.3, 0., max_snow_depth, 0., store_swq, snow_distrib_slope, store_coverage) assert coverage == old_coverage
def test_calc_snow_coverage_no_change(): store_snow = ffi.new('_Bool *') max_snow_depth = ffi.new('double *') store_swq = ffi.new('double *') snow_distrib_slope = ffi.new('double *') store_coverage = ffi.new('double *') old_coverage = 0.75 coverage = vic_lib.calc_snow_coverage(store_snow, 0.5, old_coverage, 1.25, 1.25, 2.3, 2.3, 0., max_snow_depth, 0., store_swq, snow_distrib_slope, store_coverage) assert coverage == old_coverage
def test_timedelta(): dmy = ffi.new('dmy_struct *') dmy[0].year = 2015 dmy[0].month = 1 dmy[0].day = 1 dmy[0].dayseconds = 0 dmy[0].day_in_year = 1 # First check the easy (sub)daily time deltas for n in range(1, 61, 5): for freq in ['seconds', 'minutes', 'hours', 'days']: print(freq, freqs[freq], n) expected = pd.Timedelta(**{freq: n}).total_seconds() / 86400. actual = vic_lib.time_delta(dmy, freqs[freq], n) # [days] np.testing.assert_allclose(actual, expected) # Now, spot check a few of the harder ones vic_lib.global_param.calendar = calendars['standard'] actual = vic_lib.time_delta(dmy, freqs['months'], 1) assert actual == 31 vic_lib.global_param.calendar = calendars['noleap'] actual = vic_lib.time_delta(dmy, freqs['years'], 1) assert actual == 365 vic_lib.global_param.calendar = calendars['all_leap'] actual = vic_lib.time_delta(dmy, freqs['years'], 1) assert actual == 366
def test_vic_timers(): timer = ffi.new('timer_struct *') sleeptime = 1.5 delta = 0.1 # init sets delta to zero vic_lib.timer_init(timer) # start gets current time vic_lib.timer_start(timer) # sleep time.sleep(sleeptime) # stop pauses the timer vic_lib.timer_stop(timer) assert timer[0].delta_wall >= sleeptime assert timer[0].delta_wall < sleeptime + delta assert timer[0].delta_cpu >= 0. # start the timer again vic_lib.timer_continue(timer) # sleep again time.sleep(sleeptime) # stop after the lap time sleep vic_lib.timer_stop(timer) assert timer[0].delta_wall >= 2 * sleeptime assert timer[0].delta_wall < 2 * (sleeptime + delta)
def test_dmy_all_30_day(feb3_noon): dmy_struct = ffi.new("dmy_struct *") expected = feb3_noon expected_jd = _360DayFromDate(expected) vic_lib.dmy_all_30_day(expected_jd, dmy_struct) actual = dmy_to_datetime(dmy_struct) # assert that the difference is less than one second assert abs(expected - actual) < datetime.timedelta(seconds=1)
def test_calc_snow_coverage_increased(): store_snow = ffi.new('_Bool *') store_snow[0] = True max_snow_depth = ffi.new('double *') max_snow_depth[0] = 3. store_swq = ffi.new('double *') store_swq[0] = 0.5 snow_distrib_slope = ffi.new('double *') snow_distrib_slope[0] = 0.5 store_coverage = ffi.new('double *') store_coverage[0] = 0.75 old_coverage = 0.75 coverage = vic_lib.calc_snow_coverage( store_snow, 0.5, old_coverage, 1.25, 1.5, 2.3, 3., 0., max_snow_depth, 0.25, store_swq, snow_distrib_slope, store_coverage) assert coverage > old_coverage
def dmy_too_many_seconds(feb3_noon, scope='module'): dmy = ffi.new('dmy_struct *') dmy[0].year = feb3_noon.year dmy[0].month = feb3_noon.month dmy[0].day = feb3_noon.day dmy[0].dayseconds = 86400 dmy[0].day_in_year = feb3_noon.timetuple().tm_yday return dmy
def dmy_june31(scope='module'): dmy = ffi.new('dmy_struct *') dmy[0].year = 1984 dmy[0].month = 6 dmy[0].day = 31 dmy[0].dayseconds = 0 dmy[0].day_in_year = 180 return dmy
def datetime_to_dmy(dt): dmy = ffi.new('dmy_struct *') dmy[0].year = dt.year dmy[0].month = dt.month dmy[0].day = dt.day dmy[0].dayseconds = int(dt.hour * 3600 + dt.minute * 60 + dt.second + dt.microsecond / 100000) dmy[0].day_in_year = dt.timetuple().tm_yday return dmy
def test_dmy_julian_day(feb3_noon): dmy_struct = ffi.new("dmy_struct *") expected = feb3_noon for cal in ['julian', 'standard', 'gregorian', 'proleptic_gregorian']: expected_jd = JulianDayFromDate(expected, calendar=cal) vic_lib.dmy_julian_day(expected_jd, calendars[cal], dmy_struct) actual = dmy_to_datetime(dmy_struct) # assert that the difference is less than one second assert abs(expected - actual) < datetime.timedelta(seconds=1)
def test_calc_snow_coverage_increased(): store_snow = ffi.new('_Bool *') store_snow[0] = True max_snow_depth = ffi.new('double *') max_snow_depth[0] = 3. store_swq = ffi.new('double *') store_swq[0] = 0.5 snow_distrib_slope = ffi.new('double *') snow_distrib_slope[0] = 0.5 store_coverage = ffi.new('double *') store_coverage[0] = 0.75 old_coverage = 0.75 coverage = vic_lib.calc_snow_coverage(store_snow, 0.5, old_coverage, 1.25, 1.5, 2.3, 3., 0., max_snow_depth, 0.25, store_swq, snow_distrib_slope, store_coverage) assert coverage > old_coverage
def test_strpdmy(): dmy = ffi.new("dmy_struct *") dates = pd.date_range('2015-12-18', '2016-12-22', freq='1D') date_format = '%Y-%m-%d' for date in dates: date_str = date.strftime(date_format) vic_lib.strpdmy(date_str.encode(), date_format.encode(), dmy) expected = date.to_datetime() actual = dmy_to_datetime(dmy) assert abs(expected - actual) < datetime.timedelta(seconds=1)
def test_dmy_julian_day_timeseries(): # Regression test for GH298, updated to handle all standard calendars dmy_struct = ffi.new("dmy_struct *") for cal in ['standard', 'gregorian', 'proleptic_gregorian']: dates = pd.date_range('1970-01-01', '1975-12-31', freq='6H').to_pydatetime() for expected in dates: expected_jday = JulianDayFromDate(expected) vic_lib.dmy_julian_day(expected_jday, calendars[cal], dmy_struct) actual = dmy_to_datetime(dmy_struct) print(cal, expected_jday, expected, actual) # assert that the difference is less than one second assert abs(expected - actual) < datetime.timedelta(seconds=1)
def test_num2date(): # Test dates_sets: # 1) monthly frequency that covers typical VIC simulation dates. # 2) 20min frequency with small subsecond positive offset # 3) 20min frequency with small subsecond negative offset date_sets = (pd.date_range(start="1900-01-01", end="2100-12-31", freq='MS').to_pydatetime(), pd.date_range(start='1948-09-01 00:00:00.010000', periods=200, freq='20min').to_pydatetime(), pd.date_range(start='1948-09-02 23:59:59.09000', periods=200, freq='20min').to_pydatetime()) dmy_struct = ffi.new("dmy_struct *") for cal, cal_num in calendars.items(): ut = utime(vic_default_units, calendar=cal) for dates in date_sets: for date in dates: num = ut.date2num(date) vic_lib.num2date(ut._jd0, num, 0., cal_num, units['days'], dmy_struct) actual = dmy_to_datetime(dmy_struct) assert abs(date - actual) < datetime.timedelta(seconds=1)
def test_make_lastday(): # wasn't able to map lastday to a numpy array, don't know why... lastday = ffi.new('unsigned short int [12]', [0] * 12) for year in np.arange(1900, 2100): for cal in ['standard', 'gregorian', 'proleptic_gregorian']: vic_lib.make_lastday(calendars[cal], year, lastday) cal_dpm = [calendar.monthrange(year, month)[1] for month in np.arange(1, 13)] np.testing.assert_equal(cal_dpm, list(lastday)) for cal in ['noleap', '365_day']: vic_lib.make_lastday(calendars[cal], year, lastday) cal_dpm = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] np.testing.assert_equal(cal_dpm, list(lastday)) for cal in ['all_leap', '366_day']: vic_lib.make_lastday(calendars[cal], year, lastday) cal_dpm = [31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] np.testing.assert_equal(cal_dpm, list(lastday)) for cal in ['360_day']: vic_lib.make_lastday(calendars[cal], year, lastday) cal_dpm = [30] * 12 np.testing.assert_equal(cal_dpm, list(lastday))
def test_dt_seconds_to_time_units(): dt_time_units = ffi.new('double *') for tu in units: dt_time_units[0] = 0. vic_lib.dt_seconds_to_time_units(units[tu], 3600, dt_time_units) assert dt_time_units[0] > 0.
def test_calc_atmos_energy_bal(): # note that this test uses default options in_over_sensible = 15. # (double) in_under_sensible = 5. # (double) latent_heat_over = 15. # (double) latent_heat_under = 5. # (double) latent_heat_sub_over = 5. # (double) latent_heat_sub_under = 1. # (double) net_long_over = 50. # (double) net_long_under = 30. # (double) net_short_over = 0. # (double) net_short_under = 0. # (double) r_a = 500. # (double) t_air = 2. # (double) atmos_density = 1.225 # (double) error = ffi.new('double *') error[0] = 0 # (* double) latent_heat = ffi.new('double *') latent_heat[0] = 0 # (* double) latent_heat_sub = ffi.new('double *') latent_heat_sub[0] = 0 # (* double) net_long_atmos = ffi.new('double *') net_long_atmos[0] = 0 # (* double) net_short_atmos = ffi.new('double *') net_short_atmos[0] = 0 # (* double) sensible_heat = ffi.new('double *') sensible_heat[0] = 0 # (* double) tcanopy_fbflag = ffi.new('_Bool *') tcanopy_fbflag[0] = 0 # (* bool) tcanopy_fbcount = ffi.new('unsigned *') tcanopy_fbcount[0] = 0 # (* unsigned) vic_lib.calc_atmos_energy_bal(in_over_sensible, in_under_sensible, latent_heat_over, latent_heat_under, latent_heat_sub_over, latent_heat_sub_under, net_long_over, net_long_under, net_short_over, net_short_under, r_a, t_air, atmos_density, error, latent_heat, latent_heat_sub, net_long_atmos, net_short_atmos, sensible_heat, tcanopy_fbflag, tcanopy_fbcount) assert error[0] != 0. assert latent_heat[0] != 0. assert latent_heat_sub[0] != 0. assert net_long_atmos[0] != 0. assert net_short_atmos[0] == 0. assert sensible_heat[0] == 0. assert not tcanopy_fbflag[0] assert tcanopy_fbcount[0] == 0.
def timeunits_from_chars(): for unit, expected in units.items(): actual = vic_lib.calendar_from_chars(ffi.new('char[]', unit.lower().encode())) assert actual == expected actual = vic_lib.calendar_from_chars(ffi.new('char[]', unit.upper().encode())) assert actual == expected