def test_control_curve_interpolated(model): m = model m.scenarios.setup() si = ScenarioIndex(0, np.array([0], dtype=np.int32)) s = Storage(m, 'Storage', max_volume=100.0) cc = ConstantParameter(0.8) values = [20.0, 5.0, 0.0] s.cost = ControlCurveInterpolatedParameter(s, cc, values) s.setup(m) for v in (0.0, 10.0, 50.0, 80.0, 90.0, 100.0): s.initial_volume = v s.reset() assert_allclose(s.get_cost(m.timestepper.current, si), np.interp(v/100.0, [0.0, 0.8, 1.0], values[::-1])) # special case when control curve is 100% cc.update(np.array([1.0,])) s.initial_volume == 100.0 s.reset() assert_allclose(s.get_cost(m.timestepper.current, si), values[1]) # special case when control curve is 0% cc.update(np.array([0.0,])) s.initial_volume == 0.0 s.reset() assert_allclose(s.get_cost(m.timestepper.current, si), values[0])
def test_control_curve_interpolated(model): m = model m.timestepper.delta = 200 s = m.nodes['Storage'] o = m.nodes['Output'] s.connect(o) cc = ConstantParameter(model, 0.8) values = [20.0, 5.0, 0.0] s.cost = p = ControlCurveInterpolatedParameter(model, s, cc, values) @assert_rec(model, p) def expected_func(timestep, scenario_index): v = s.initial_volume c = cc.value(timestep, scenario_index) if c == 1.0 and v == 100.0: expected = values[1] elif c == 0.0 and v == 0.0: expected = values[1] else: expected = np.interp(v / 100.0, [0.0, c, 1.0], values[::-1]) return expected for control_curve in (0.0, 0.8, 1.0): cc.update(np.array([ control_curve, ])) for initial_volume in (0.0, 10.0, 50.0, 80.0, 90.0, 100.0): s.initial_volume = initial_volume model.run()
def test_control_curve_interpolated(model, use_parameters): m = model m.timestepper.delta = 200 s = m.nodes['Storage'] o = m.nodes['Output'] s.connect(o) cc = ConstantParameter(model, 0.8) values = [20.0, 5.0, 0.0] if use_parameters: # Create the parameter using parameters for the values parameters = [ConstantParameter(model, v) for v in values] s.cost = p = ControlCurveInterpolatedParameter(model, s, cc, parameters=parameters) else: # Create the parameter using a list of values s.cost = p = ControlCurveInterpolatedParameter(model, s, cc, values) @assert_rec(model, p) def expected_func(timestep, scenario_index): v = s.initial_volume c = cc.value(timestep, scenario_index) if c == 1.0 and v == 100.0: expected = values[1] elif c == 0.0 and v == 0.0: expected = values[1] else: expected = np.interp(v / 100.0, [0.0, c, 1.0], values[::-1]) return expected for control_curve in (0.0, 0.8, 1.0): cc.set_double_variables(np.array([ control_curve, ])) for initial_volume in (0.0, 10.0, 50.0, 80.0, 90.0, 100.0): s.initial_volume = initial_volume model.run()
def __init__(self, model, name, storage_node, release_values, scenario=None, **kwargs): if scenario is None: # Only one control curve should be defined. Get it explicitly control_curves = release_values['volume'].iloc[1:-1].astype( np.float64) values = release_values['value'].astype(np.float64) max_flow_param = ControlCurveInterpolatedParameter( model, storage_node, control_curves, values) else: # There should be multiple control curves defined. if release_values.shape[1] % 2 != 0: raise ValueError( "An even number of columns (i.e. pairs) is required for the release rules " "when using a scenario.") ncurves = release_values.shape[1] // 2 if ncurves != scenario.size: raise ValueError( f"The number of curves ({ncurves}) should equal the size of the " f"scenario ({scenario.size}).") curves = [] for i in range(ncurves): volume = release_values.iloc[1:-1, i * 2] values = release_values.iloc[:, i * 2 + 1] control_curve = ControlCurveInterpolatedParameter( model, storage_node, volume, values) curves.append(control_curve) max_flow_param = ScenarioWrapperParameter(model, scenario, curves) self.scenario = scenario super().__init__(model, name, max_flow=max_flow_param, **kwargs)