def setUpClass(cls): cls.wn = wn = wntr.network.WaterNetworkModel() wn.add_tank('t1', 0, 10, 0, 20, 15) wn.add_junction('j1', 0.01) wn.add_pipe('p1', 't1', 'j1', minor_loss=10.0) wn.add_curve('curve1', 'HEAD', [(0.0, 10.0), (0.05, 5.0), (0.1, 0.0)]) wn.add_curve('curve2', 'HEAD', [(0.0, 10.0), (0.03, 5.0), (0.1, 0.0)]) wn.add_curve('curve3', 'HEAD', [(0.0, 10.0), (0.07, 5.0), (0.1, 0.0)]) wn.add_pump('pump1', 't1', 'j1', 'HEAD', 'curve1') wn.add_pump('pump2', 't1', 'j1', 'POWER', 50.0) cls.m = m = wntr.sim.aml.Model() cls.updater = updater = ModelUpdater() wntr.sim.models.constants.hazen_williams_constants(m) wntr.sim.models.param.hw_resistance_param.build(m, wn, updater) wntr.sim.models.param.minor_loss_param.build(m, wn, updater) wntr.sim.models.param.source_head_param(m, wn) wntr.sim.models.var.flow_var(m, wn) wntr.sim.models.var.head_var(m, wn) wntr.sim.models.constraint.piecewise_hazen_williams_headloss_constraint.build( m, wn, updater) wntr.sim.models.constants.head_pump_constants(m) wntr.sim.models.constraint.head_pump_headloss_constraint.build( m, wn, updater) wntr.sim.models.param.pump_power_param.build(m, wn, updater) wntr.sim.models.constraint.power_pump_headloss_constraint.build( m, wn, updater)
def setUpClass(cls): cls.wn = wn = wntr.network.WaterNetworkModel() wn.add_tank("t1", 0, 10, 0, 20, 15) wn.add_junction("j1", 0.01) wn.add_pipe("p1", "t1", "j1", minor_loss=10.0) wn.add_curve("curve1", "HEAD", [(0.0, 10.0), (0.05, 5.0), (0.1, 0.0)]) wn.add_curve("curve2", "HEAD", [(0.0, 10.0), (0.03, 5.0), (0.1, 0.0)]) wn.add_curve("curve3", "HEAD", [(0.0, 10.0), (0.07, 5.0), (0.1, 0.0)]) # add a single point, 2-point, and a set of multi-point curves to test wn.add_curve("curve4", "HEAD", [(0.05, 5.0)]) wn.add_curve("curve5", "HEAD", [(0.0, 10.0), (0.1, 0.0)]) # multi_point_pump_curves = pump_curves_for_testing() # change to read in a csv file df = pd.read_csv(join(test_data_dir, "pump_practice_curves.csv"), skiprows=5) multi_point_pump_curves = [] for i in range(11): multi_point_pump_curves.append(df[df["curve number"] == i].iloc[:, 1:3]) for i, curve in enumerate(multi_point_pump_curves): curve_name = "curve{0:d}".format(i + 6) wn.add_curve(curve_name, "HEAD", curve.values) wn.add_pump("pump1", "t1", "j1", "HEAD", "curve1") wn.add_pump("pump2", "t1", "j1", "POWER", 50.0) cls.m = m = wntr.sim.aml.Model() cls.updater = updater = ModelUpdater() wntr.sim.models.constants.hazen_williams_constants(m) wntr.sim.models.param.hw_resistance_param.build(m, wn, updater) wntr.sim.models.param.minor_loss_param.build(m, wn, updater) wntr.sim.models.param.source_head_param(m, wn) wntr.sim.models.var.flow_var(m, wn) wntr.sim.models.var.head_var(m, wn) wntr.sim.models.constraint.piecewise_hazen_williams_headloss_constraint.build( m, wn, updater ) wntr.sim.models.constants.head_pump_constants(m) wntr.sim.models.constraint.head_pump_headloss_constraint.build(m, wn, updater) wntr.sim.models.param.pump_power_param.build(m, wn, updater) wntr.sim.models.constraint.power_pump_headloss_constraint.build(m, wn, updater)
def test_pdd(self): wn = self.wn # Changed to handle the specific heads_to_test range, which is bad node = wn.get_node('j1') node.required_pressure = 20.0 node.minimum_pressure = 0.0 m = wntr.sim.aml.Model() updater = ModelUpdater() wntr.sim.models.constants.pdd_constants(m) wntr.sim.models.param.expected_demand_param(m, wn) wntr.sim.models.param.elevation_param.build(m, wn, updater) wntr.sim.models.param.pdd_poly_coeffs_param.build(m, wn, updater) wntr.sim.models.param.pmin_param.build(m, wn, updater) wntr.sim.models.param.pnom_param.build(m, wn, updater) wntr.sim.models.var.head_var(m, wn) wntr.sim.models.var.demand_var(m, wn) wntr.sim.models.constraint.pdd_constraint.build(m, wn, updater) node = wn.get_node('j1') pmin = node.minimum_pressure pnom = node.required_pressure h0 = node.elevation + pmin h1 = node.elevation + pnom delta = m.pdd_smoothing_delta heads_to_test = [h0 - 1, h0, h0 + delta/2, h0 + delta, h0 + (pmin + pnom)/2, h1 - delta, h1 - delta/2, h1, h1 + 1] d_expected = node.demand_timeseries_list.at(wn.sim_time, multiplier=wn.options.hydraulic.demand_multiplier) d = 0.01 m.demand['j1'].value = d a1 = m.pdd_poly1_coeffs_a['j1'].value b1 = m.pdd_poly1_coeffs_b['j1'].value c1 = m.pdd_poly1_coeffs_c['j1'].value d1 = m.pdd_poly1_coeffs_d['j1'].value a2 = m.pdd_poly2_coeffs_a['j1'].value b2 = m.pdd_poly2_coeffs_b['j1'].value c2 = m.pdd_poly2_coeffs_c['j1'].value d2 = m.pdd_poly2_coeffs_d['j1'].value delta = m.pdd_smoothing_delta slope = m.pdd_slope for h in heads_to_test: m.head['j1'].value = h r1 = m.pdd['j1'].evaluate() p = h - node.elevation if p <= pmin: r2 = d - d_expected * slope * (p - pmin) elif p <= pmin + delta: r2 = d - d_expected * (a1*p**3 + b1*p**2 + c1*p + d1) elif p <= pnom - delta: r2 = d - d_expected * ((p - pmin)/(pnom - pmin))**0.5 elif p <= pnom: r2 = d - d_expected * (a2*p**3 + b2*p**2 + c2*p + d2) else: r2 = d - d_expected * (slope*(p - pnom) + 1.0) # print(p, r1, r2, abs(r1 - r2)) self.assertAlmostEqual(r1, r2, 12) der1 = m.pdd['j1'].reverse_ad()[m.head['j1']] der2 = m.pdd['j1'].reverse_ad()[m.head['j1']] der3 = approximate_derivative(m.pdd['j1'], m.head['j1'], 1e-6) self.assertAlmostEqual(der1, der2, 7) self.assertAlmostEqual(der1, der3, 6)
def create_hydraulic_model(wn, HW_approx='default'): """ Parameters ---------- wn: WaterNetworkModel mode: str HW_approx: str Specifies which Hazen-Williams headloss approximation to use. Options are 'default' and 'piecewise'. Please see the WNTR documentation on hydraulics for details. Returns ------- m: wntr.aml.Model model_updater: wntr.models.utils.ModelUpdater """ m = aml.Model() model_updater = ModelUpdater() # Global constants constants.hazen_williams_constants(m) constants.head_pump_constants(m) constants.leak_constants(m) constants.pdd_constants(m) param.source_head_param(m, wn) param.expected_demand_param(m, wn) mode = wn.options.hydraulic.demand_model if mode in ['DD', 'DDA']: pass elif mode in ['PDD', 'PDA']: param.pmin_param.build(m, wn, model_updater) param.pnom_param.build(m, wn, model_updater) param.pdd_poly_coeffs_param.build(m, wn, model_updater) param.leak_coeff_param.build(m, wn, model_updater) param.leak_area_param.build(m, wn, model_updater) param.leak_poly_coeffs_param.build(m, wn, model_updater) param.elevation_param.build(m, wn, model_updater) param.hw_resistance_param.build(m, wn, model_updater) param.minor_loss_param.build(m, wn, model_updater) param.tcv_resistance_param.build(m, wn, model_updater) param.pump_power_param.build(m, wn, model_updater) param.valve_setting_param.build(m, wn, model_updater) if mode in ['DD','DDA']: pass elif mode in ['PDD','PDA']: var.demand_var(m, wn) var.flow_var(m, wn) var.head_var(m, wn) var.leak_rate_var(m, wn) if mode in ['DD','DDA']: constraint.mass_balance_constraint.build(m, wn, model_updater) elif mode in ['PDD','PDA']: constraint.pdd_mass_balance_constraint.build(m, wn, model_updater) constraint.pdd_constraint.build(m, wn, model_updater) else: raise ValueError('mode not recognized: ' + str(mode)) if HW_approx == 'default': constraint.approx_hazen_williams_headloss_constraint.build(m, wn, model_updater) elif HW_approx == 'piecewise': constraint.piecewise_hazen_williams_headloss_constraint.build(m, wn, model_updater) else: raise ValueError('Unexpected value for HW_approx: ' + str(HW_approx)) constraint.head_pump_headloss_constraint.build(m, wn, model_updater) constraint.power_pump_headloss_constraint.build(m, wn, model_updater) constraint.prv_headloss_constraint.build(m, wn, model_updater) constraint.psv_headloss_constraint.build(m, wn, model_updater) constraint.tcv_headloss_constraint.build(m, wn, model_updater) constraint.fcv_headloss_constraint.build(m, wn, model_updater) if len(wn.pbv_name_list) > 0: raise NotImplementedError('PBV valves are not currently supported in the WNTRSimulator') if len(wn.gpv_name_list) > 0: raise NotImplementedError('GPV valves are not currently supported in the WNTRSimulator') constraint.leak_constraint.build(m, wn, model_updater) # TODO: Document that changing a curve with controls does not do anything; you have to change the pump_curve_name attribute on the pump return m, model_updater