def test_hysteresis(self, simple_linear_model, minimum_length): """ Test the minimum_event_length keyword of EventRecorder """ m = simple_linear_model flow = np.zeros(len(m.timestepper)) flow[:10] = [0, 0, 10, 0, 10, 10, 10, 0, 0, 0] # With min event length of 1. There are two events with lengths (1, 3) # |---| |---------| # With min event length up to 4. There is one event with length 3 # |---------| # Min event length >= 4 gives no events inpt = m.nodes['Input'] inpt.max_flow = ArrayIndexedParameter(m, flow) # Force through whatever flow Input can provide otpt = m.nodes['Output'] otpt.max_flow = 100 otpt.cost = -100 # Create the trigger using a threhsold parameter trigger = NodeThresholdRecorder(m, otpt, 4.0, predicate='>') evt_rec = EventRecorder(m, trigger, minimum_event_length=minimum_length) m.run() if minimum_length == 1: assert len(evt_rec.events) == 2 assert_equal([1, 3], [e.duration for e in evt_rec.events]) elif minimum_length < 4: assert len(evt_rec.events) == 1 assert_equal([3, ], [e.duration for e in evt_rec.events]) else: assert len(evt_rec.events) == 0
def test_parameter_array_indexed(simple_linear_model): """ Test ArrayIndexedParameter """ model = simple_linear_model A = np.arange(len(model.timestepper), dtype=np.float64) p = ArrayIndexedParameter(model, A) model.setup() # scenario indices (not used for this test) si = ScenarioIndex(0, np.array([0], dtype=np.int32)) for v, ts in zip(A, model.timestepper): np.testing.assert_allclose(p.value(ts, si), v) # Now check that IndexError is raised if an out of bounds Timestep is given. ts = Timestep(datetime.datetime(2016, 1, 1), 366, 1.0) with pytest.raises(IndexError): p.value(ts, si)
def test_interpolated_parameter(simple_linear_model): model = simple_linear_model model.timestepper.start = "1920-01-01" model.timestepper.end = "1920-01-12" p1 = ArrayIndexedParameter(model, [0,1,2,3,4,5,6,7,8,9,10,11]) p2 = InterpolatedParameter(model, p1, [0, 5, 10, 11], [0, 5*2, 10*3, 2]) @assert_rec(model, p2) def expected_func(timestep, scenario_index): values = [0, 2, 4, 6, 8, 10, 14, 18, 22, 26, 30, 2] return values[timestep.index] model.run()
def test_node_threshold_parameter2(self, simple_linear_model): model = simple_linear_model model.nodes["Input"].max_flow = ArrayIndexedParameter( model, np.arange(0, 20)) model.nodes["Output"].cost = -10.0 model.timestepper.start = "1920-01-01" model.timestepper.end = "1920-01-15" model.timestepper.delta = 1 threshold = 5.0 parameters = {} for predicate in (">", "<", "="): data = { "type": "nodethreshold", "node": "Output", "threshold": 5.0, "predicate": predicate, # we need to define values so AssertionRecorder can be used "values": [0.0, 1.0], } parameter = load_parameter(model, data) parameter.name = "nodethresold {}".format(predicate) parameters[predicate] = parameter if predicate == ">": expected_data = (np.arange(-1, 20) > threshold).astype(int) elif predicate == "<": expected_data = (np.arange(-1, 20) < threshold).astype(int) else: expected_data = (np.arange(-1, 20) == threshold).astype(int) expected_data[ 0] = 0 # previous flow in initial timestep is undefined expected_data = expected_data[:, np.newaxis] rec = AssertionRecorder( model, parameter, expected_data=expected_data, name="assertion recorder {}".format(predicate)) model.run()
def add_value_to_node(res_attr_idx, type_name, attr_name): pywr_param = None constant = constants.pop(res_attr_idx, None) if constant: pywr_param = ConstantParameter(model, constant) elif variables: variable = variables.pop(res_attr_idx, None) if variable: values = list(variable['values'].values()) pywr_param = ArrayIndexedParameter(model, values) elif policies: policy = policies.pop(res_attr_idx, None) if policy: pywr_param = self.create_register_policy(policy) if pywr_param is not None: type_name = type_name.lower() attr_name = attr_name.lower() (resource_type, resource_id, attr_id) = res_attr_idx try: self.update_param(resource_type, resource_id, type_name, attr_name, value=pywr_param) except: raise
def create_model(harmonic=True): # import flow timeseries for catchments flow = pd.read_csv(os.path.join('data', 'thames_stochastic_flow.gz')) flow['Date'] = flow['Date'].apply(pd.to_datetime) flow.set_index('Date', inplace=True) # resample input to weekly average flow = flow.resample('7D', how='mean') model = InspyredOptimisationModel( solver='glpk', start=flow.index[0], end=flow.index[365*10], # roughly 10 years timestep=datetime.timedelta(7), # weekly time-step ) flow_parameter = ArrayIndexedParameter(model, flow['flow'].values) catchment1 = Input(model, 'catchment1', min_flow=flow_parameter, max_flow=flow_parameter) catchment2 = Input(model, 'catchment2', min_flow=flow_parameter, max_flow=flow_parameter) reservoir1 = Storage(model, 'reservoir1', min_volume=3000, max_volume=20000, initial_volume=16000) reservoir2 = Storage(model, 'reservoir2', min_volume=3000, max_volume=20000, initial_volume=16000) if harmonic: control_curve = AnnualHarmonicSeriesParameter(model, 0.5, [0.5], [0.0], mean_upper_bounds=1.0, amplitude_upper_bounds=1.0) else: control_curve = MonthlyProfileParameter(model, np.array([0.0]*12), lower_bounds=0.0, upper_bounds=1.0) control_curve.is_variable = True controller = ControlCurveParameter(model, reservoir1, control_curve, [0.0, 10.0]) transfer = Link(model, 'transfer', max_flow=controller, cost=-500) demand1 = Output(model, 'demand1', max_flow=45.0, cost=-101) demand2 = Output(model, 'demand2', max_flow=20.0, cost=-100) river1 = Link(model, 'river1') river2 = Link(model, 'river2') # compensation flows from reservoirs compensation1 = Link(model, 'compensation1', max_flow=5.0, cost=-9999) compensation2 = Link(model, 'compensation2', max_flow=5.0, cost=-9998) terminator = Output(model, 'terminator', cost=1.0) catchment1.connect(reservoir1) catchment2.connect(reservoir2) reservoir1.connect(demand1) reservoir2.connect(demand2) reservoir2.connect(transfer) transfer.connect(reservoir1) reservoir1.connect(river1) reservoir2.connect(river2) river1.connect(terminator) river2.connect(terminator) reservoir1.connect(compensation1) reservoir2.connect(compensation2) compensation1.connect(terminator) compensation2.connect(terminator) r1 = TotalDeficitNodeRecorder(model, demand1) r2 = TotalDeficitNodeRecorder(model, demand2) r3 = AggregatedRecorder(model, [r1, r2], agg_func="mean") r3.is_objective = 'minimise' r4 = TotalFlowNodeRecorder(model, transfer) r4.is_objective = 'minimise' return model