def load(cls, data, model): mrf = load_parameter(model, data.pop("mrf", 0.0)) mrf_cost = load_parameter(model, data.pop("mrf_cost", 0.0)) unconstrained_cost = load_parameter(model, data.pop("unconstrained_cost", 0.0)) del data["type"] node = cls(model, mrf=mrf, mrf_cost=mrf_cost, unconstrained_cost=unconstrained_cost, **data) return node
def load(cls, data, model): mrf = load_parameter(model, data.pop("mrf")) mrf_cost = load_parameter(model, data.pop("mrf_cost")) cost = load_parameter(model, data.pop("cost", 0.0)) del (data["type"]) node = cls(model, mrf=mrf, mrf_cost=mrf_cost, cost=cost, **data) return node
def load(cls, data, model): # max_flow and cost should be lists of parameter definitions max_flow = [load_parameter(model, p) for p in data.pop('max_flow')] cost = [load_parameter(model, p) for p in data.pop('cost')] del (data["type"]) return cls(model, max_flow=max_flow, cost=cost, **data)
def load(cls, data, model): name = data.pop('name') cost = data.pop('cost', 0.0) min_flow = data.pop('min_flow', None) max_flow = data.pop('max_flow', None) data.pop('type') node = cls(model=model, name=name, **data) cost = load_parameter(model, cost) min_flow = load_parameter(model, min_flow) max_flow = load_parameter(model, max_flow) if cost is None: cost = 0.0 if min_flow is None: min_flow = 0.0 if max_flow is None: max_flow = np.inf node.cost = cost node.min_flow = min_flow node.max_flow = max_flow return node
def load(cls, data, model): name = data.pop('name') num_inputs = int(data.pop('inputs', 1)) num_outputs = int(data.pop('outputs', 1)) if 'initial_volume' not in data and 'initial_volume_pc' not in data: raise ValueError( 'Initial volume must be specified in absolute or relative terms.' ) initial_volume = data.pop('initial_volume', 0.0) initial_volume_pc = data.pop('initial_volume_pc', None) max_volume = data.pop('max_volume') min_volume = data.pop('min_volume', 0.0) level = data.pop('level', None) area = data.pop('area', None) cost = data.pop('cost', 0.0) data.pop('type', None) # Create the instance node = cls(model=model, name=name, num_inputs=num_inputs, num_outputs=num_outputs, **data) # Load the parameters after the instance has been created to prevent circular # loading errors # Try to coerce initial volume to float. try: initial_volume = float(initial_volume) except TypeError: initial_volume = load_parameter_values(model, initial_volume) node.initial_volume = initial_volume node.initial_volume_pc = initial_volume_pc max_volume = load_parameter(model, max_volume) if max_volume is not None: node.max_volume = max_volume min_volume = load_parameter(model, min_volume) if min_volume is not None: node.min_volume = min_volume cost = load_parameter(model, cost) if cost is None: cost = 0.0 node.cost = cost if level is not None: level = load_parameter(model, level) node.level = level if area is not None: area = load_parameter(model, area) node.area = area return node
def load(cls, data, model): name = data.pop('name') costs = data.pop('cost') max_flows = data.pop('max_flow') data.pop('type') costs = [load_parameter(model, c) for c in costs] max_flows = [load_parameter(model, mf) for mf in max_flows] return cls(model, name, cost=costs, max_flow=max_flows, **data)
def load(cls, data, model): cost = load_parameter(model, data.pop('cost', 0.0)) mrf_cost = load_parameter(model, data.pop('mrf_cost', 0.0)) mrf = load_parameter(model, data.pop('mrf', 0.0)) name = data.pop("name") data.pop("type", None) parameter = cls(model, name, mrf=mrf, cost=cost, mrf_cost=mrf_cost, **data) return parameter
def load(cls, data, model): base_flow = load_parameter(model, data.pop("base_flow", 0.0)) base_cost = load_parameter(model, data.pop("base_cost", 0.0)) excess_cost = load_parameter(model, data.pop("excess_cost", 0.0)) # turbine_capacity = load_parameter(model, data.pop("turbine_capacity", 0.0)) # unconstrained_cost = load_parameter(model, data.pop("unconstrained_cost", 0.0)) del (data["type"]) node = cls(model, base_flow=base_flow, base_cost=base_cost, excess_cost=excess_cost, **data) return node
def __init__(self, *args, **kwargs): """Initialise a new RiverSplit instance """ cost = load_parameter(self.model, kwargs.pop('cost', 0.0)) mrf_cost = load_parameter(self.model, kwargs.pop('mrf_cost', 0.0)) kwargs['cost'] = [mrf_cost, cost] mrf = load_parameter(self.model, kwargs.pop('mrf', 0.0)) kwargs['max_flow'] = [mrf, None] super(RiverSplitWithGauge, self).__init__(*args, **kwargs)
def load(cls, model, data): from pywr.parameters import load_parameter threshold = data.pop("threshold") try: threshold = load_parameter(model, threshold) except KeyError: threshold = load_recorder(model, threshold) tracked_param = data.pop("tracked_parameter", None) if tracked_param: tracked_param = load_parameter(model, tracked_param) return cls(model, threshold, tracked_parameter=tracked_param, **data)
def finalise_load(self): """Finish loading a node by converting parameter name references to instance references.""" for key, parameter_data in self.__parameters_to_load.items(): if isinstance(parameter_data, list): # List of parameter references parameter = [load_parameter(self.model, d) for d in parameter_data] else: parameter = load_parameter(self.model, parameter_data) setattr(self, key, parameter) del self.__parameters_to_load
def load(cls, data, model): # max_flow and cost should be lists of parameter definitions max_flow = [load_parameter(model, p) for p in data.pop('max_flow')] cost = [load_parameter(model, p) for p in data.pop('cost')] factors = AggregatedNode.load_factors(model, data) del (data["type"]) return cls(model, max_flow=max_flow, cost=cost, factors=factors, **data)
def load(cls, model, data): node = model._get_node_from_ref(model, data.pop("node")) water_elevation_reservoir = None water_elevation_parameter = None if node.water_elevation_reservoir: water_elevation_reservoir = model._get_node_from_ref( model, node.water_elevation_reservoir) elif node.water_elevation_parameter: water_elevation_parameter = load_parameter( model, node.water_elevation_parameter) else: water_elevation_parameter = node.head data['efficiency'] = node.efficiency data['tailwater_elevation'] = node.tailwater_elevation # For now, we add this flow unit conversion here # conversion is from mcm (model) to cms (energy calculation) data['flow_unit_conversion'] = 1 / 0.0864 # For now, we add the energy unit conversion here # conversion is from W (J/s) to MWh data['energy_unit_conversion'] = 24 / 1e6 return cls(model, node, water_elevation_parameter=water_elevation_parameter, water_elevation_reservoir=water_elevation_reservoir, **data)
def test_daily_profile_control_curve(simple_linear_model): """ Test `DailyProfileControlCurveParameter` """ model = simple_linear_model s = Storage(model, 'Storage', max_volume=100.0) l = Link(model, 'Link2') data = { 'type': 'dailyprofilecontrolcurve', 'control_curves': [0.8, 0.6], 'values': [[1.0] * 366, [0.7] * np.arange(366), [0.3] * 366], 'storage_node': 'Storage' } l.max_flow = p = load_parameter(model, data) model.setup() @assert_rec(model, p) def expected_func(timestep, scenario_index): v = s.initial_volume doy = timestep.dayofyear if v >= 80.0: expected = 1.0 elif v >= 60: expected = 0.7 * (doy - 1) else: expected = 0.3 return expected for initial_volume in (90, 70, 30): s.initial_volume = initial_volume model.run()
def test_load_wth_scaling(self, simple_storage_model): model = simple_storage_model stg = model.nodes['Storage'] x = 2.0 y = stg.initial_volume / stg.max_volume data = { "type": "polynomial2dstorage", "coefficients": [[0.5, np.pi], [2.5, 0.3]], "use_proportional_volume": True, "parameter": { "type": "constant", "value": x }, "storage_node": "Storage", "storage_scale": 1.3, "storage_offset": 0.75, "parameter_scale": 1.25, "parameter_offset": -0.5 } p1 = load_parameter(model, data) # Scaled parameters x = x * 1.25 - 0.5 y = y * 1.3 + 0.75 @assert_rec(model, p1) def expected_func(timestep, scenario_index): return 0.5 + np.pi * x + 2.5 * y + 0.3 * x * y model.setup() model.step()
def test_parameter_registry_overwrite(model): # define a parameter class NewParameter(Parameter): DATA = 42 def __init__(self, model, values, *args, **kwargs): super(NewParameter, self).__init__(model, *args, **kwargs) self.values = values NewParameter.register() # re-define a parameter class NewParameter(IndexParameter): DATA = 43 def __init__(self, model, values, *args, **kwargs): super(NewParameter, self).__init__(model, *args, **kwargs) self.values = values NewParameter.register() data = {"type": "new", "values": 0} parameter = load_parameter(model, data) # parameter is instance of new class, not old class assert (isinstance(parameter, NewParameter)) assert (parameter.DATA == 43)
def test_parameter_threshold_parameter(self, simple_linear_model, threshold): """ Test ParameterThresholdParameter """ m = simple_linear_model m.nodes['Input'].max_flow = 10.0 m.nodes['Output'].cost = -10.0 data = { "type": "parameterthreshold", "parameter": { "type": "constant", "value": 3.0 }, "threshold": threshold, "predicate": "<" } p1 = load_parameter(m, data) si = ScenarioIndex(0, np.array([0], dtype=np.int32)) m.setup() m.step() # value < 5 assert p1.index(m.timestepper.current, si) == 1 p1.param.update(np.array([ 8.0, ])) m.setup() m.step() # flow < 5 assert p1.index(m.timestepper.current, si) == 0
def test_binary_step(self, simple_linear_model, internal_value, max_output, upper_bounds): """Test the binary step profile parameter.""" m = simple_linear_model m.timestepper.start = '2015-01-01' m.timestepper.end = '2015-12-31' if internal_value <= 0.0: expected_values = np.zeros(365) else: expected_values = np.ones( 365) * max_output * internal_value / upper_bounds data = { 'type': 'rectifier', 'value': internal_value, 'max_output': max_output, 'upper_bounds': upper_bounds } p = load_parameter(m, data) @assert_rec(m, p) def expected_func(timestep, _scenario_index): return expected_values[timestep.index] m.run()
def load(cls, data, model): # accept plurals of max_flow and cost try: max_flow = data.pop("max_flows") except KeyError: pass else: data["max_flow"] = [load_parameter(p) for p in max_flow] try: cost = data.pop("costs") except KeyError: pass else: data["cost"] = [load_parameter(p) for p in cost] del(data["type"]) return cls(model, **data)
def test_parameters_load(self, model): """ Test load of parameter lists for 'control_curves' and 'parameters' keys. """ m = model s = m.nodes['Storage'] data = { "type": "controlcurve", "storage_node": "Storage", "control_curves": [{ "type": "constant", "value": 0.8 }, { "type": "monthlyprofile", "values": [0.6] * 12 }], "parameters": [{ "type": "constant", "value": 1.0, }, { "type": "constant", "value": 0.7 }, { "type": "constant", "value": 0.4 }] } s.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) self._assert_results(m, s)
def test_binary_step(self, simple_linear_model, internal_value, max_output, upper_bounds, min_output): """Test the binary step profile parameter.""" m = simple_linear_model m.timestepper.start = "2015-01-01" m.timestepper.end = "2015-12-31" if internal_value <= 0.0: expected_values = np.zeros(365) else: range = max_output - min_output expected_values = np.ones(365) * ( min_output + range * internal_value / upper_bounds) data = { "type": "rectifier", "value": internal_value, "max_output": max_output, "min_output": min_output, "upper_bounds": upper_bounds, } p = load_parameter(m, data) @assert_rec(m, p) def expected_func(timestep, _scenario_index): return expected_values[timestep.index] m.run()
def test_binary_step(self, simple_linear_model, internal_value, output): """Test the binary step profile parameter.""" m = simple_linear_model m.timestepper.start = "2015-01-01" m.timestepper.end = "2015-12-31" if internal_value <= 0.0: expected_values = np.zeros(365) else: expected_values = np.ones(365) * output data = { "type": "binarystep", "value": internal_value, "output": output, } p = load_parameter(m, data) @assert_rec(m, p) def expected_func(timestep, _scenario_index): return expected_values[timestep.index] m.run()
def test_single_cc_load(self, model): """ Test load from dict with 'control_curve' key This is different to the above test by using singular 'control_curve' key in the dict """ m = model m.scenarios.setup() s = Storage(m, 'Storage', max_volume=100.0) data = { "type": "controlcurve", "storage_node": "Storage", "control_curve": 0.8, } s.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) s.setup(m) # Init memory view on storage (bypasses usual `Model.setup`) si = ScenarioIndex(0, np.array([0], dtype=np.int32)) s.initial_volume = 90.0 m.reset() assert_allclose(s.get_cost(m.timestepper.current, si), 0) s.initial_volume = 70.0 m.reset() assert_allclose(s.get_cost(m.timestepper.current, si), 1)
def test_parameter(cls, simple_linear_model, ptype,profile): model = simple_linear_model model.timestepper.start = "2017-01-01" model.timestepper.end = "2017-01-15" data = { "type": ptype, "parameter": { "name": "raw", "type": "dailyprofile", "values": profile, } } if ptype in ("max", "min"): data["threshold"] = 3 func = {"min": min, "max": max, "negative": lambda t,x: -x, "negativemax": lambda t,x: max(t, -x)}[ptype] model.nodes["Input"].max_flow = parameter = load_parameter(model, data) model.nodes["Output"].max_flow = 9999 model.nodes["Output"].cost = -100 daily_profile = model.parameters["raw"] @assert_rec(model, parameter) def expected(timestep, scenario_index): value = daily_profile.get_value(scenario_index) return func(3, value) model.run()
def load(cls, data, model): flow = data.pop('flow', None) if flow is not None: flow = load_parameter(model, flow) node = super(Catchment, cls).load(data, model) node.flow = flow return node
def test_single_cc_load(self, model): """ Test load from dict with 'control_curve' key This is different to the above test by using singular 'control_curve' key in the dict """ m = model s = m.nodes['Storage'] data = { "type": "controlcurve", "storage_node": "Storage", "control_curve": 0.8, } s.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) @assert_rec(m, p) def expected_func(timestep, scenario_index): v = s.initial_volume if v >= 80.0: expected = 0 else: expected = 1 return expected for initial_volume in (90, 70): s.initial_volume = initial_volume m.run()
def test_with_nonstorage_load(self, model): """Test load from dict with 'storage_node' key.""" m = model s = m.nodes["Storage"] l = Link(m, "Link") # Connect the link node to the network to create a valid model o = m.nodes["Output"] s.connect(l) l.connect(o) data = { "type": "controlcurve", "control_curve": 0.8, "values": [10.0, 0.0], "storage_node": "Storage", } l.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) @assert_rec(m, l.cost) def expected_func(timestep, scenario_index): v = s.initial_volume if v >= 80.0: expected = 10.0 else: expected = 0.0 return expected for initial_volume in (90, 70): s.initial_volume = initial_volume m.run()
def test_with_nonstorage_load(self, model): """ Test load from dict with 'storage_node' key. """ m = model s = m.nodes['Storage'] l = Link(m, 'Link') data = { "type": "controlcurve", "control_curve": 0.8, "values": [10.0, 0.0], "storage_node": "Storage" } l.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) @assert_rec(m, l.cost) def expected_func(timestep, scenario_index): v = s.initial_volume if v >= 80.0: expected = 10.0 else: expected = 0.0 return expected for initial_volume in (90, 70): s.initial_volume = initial_volume m.run()
def test_with_nonstorage_load(self, model): """ Test load from dict with 'storage_node' key. """ m = model m.scenarios.setup() s = Storage(m, 'Storage', max_volume=100.0) l = Link(m, 'Link') data = { "type": "controlcurve", "control_curve": 0.8, "values": [10.0, 0.0], "storage_node": "Storage" } l.cost = p = load_parameter(model, data) assert isinstance(p, ControlCurveParameter) s.setup(m) # Init memory view on storage (bypasses usual `Model.setup`) si = ScenarioIndex(0, np.array([0], dtype=np.int32)) print(s.volume) assert_allclose(l.get_cost(m.timestepper.current, si), 0.0) # When storage volume changes, the cost of the link changes. s.initial_volume = 90.0 m.reset() assert_allclose(l.get_cost(m.timestepper.current, si), 10.0)
def test_divsion(self, simple_linear_model): model = simple_linear_model model.timestepper.start = "2017-01-01" model.timestepper.end = "2017-01-15" profile = list(range(1, 367)) data = { "type": "division", "numerator": { "name": "raw", "type": "dailyprofile", "values": profile, }, "denominator": { "type": "constant", "value": 123.456 } } model.nodes["Input"].max_flow = parameter = load_parameter(model, data) model.nodes["Output"].max_flow = 9999 model.nodes["Output"].cost = -100 daily_profile = model.parameters["raw"] @assert_rec(model, parameter) def expected(timestep, scenario_index): value = daily_profile.get_value(scenario_index) return value / 123.456 model.run()