def build_watertank_vert_cylin(): # Create a Concrete Model as the top level object m = pyo.ConcreteModel() # Add a flowsheet object to the model m.fs = FlowsheetBlock(default={"dynamic": False}) # Add property packages to flowsheet library m.fs.prop_water = iapws95.Iapws95ParameterBlock() m.fs.unit = WaterTank( default={ "tank_type": "vertical_cylindrical_tank", "property_package": m.fs.prop_water, "has_holdup": False, "has_heat_transfer": True, "has_pressure_change": True }) # fix inputs for horizontal cylindrical tank m.fs.unit.tank_diameter.fix(1.2) # tank diameter m.fs.unit.tank_level[:].fix(0.6) # tank level m.fs.unit.heat_duty[:].fix(0.0) # assume no heat loss return m
def get_model(dynamic=False): m = pyo.ConcreteModel(name="Testing PID controller model") if dynamic: m.dynamic = True m.fs = FlowsheetBlock(default={ "dynamic": True, "time_set": [0, 50, 1000], "time_units": pyo.units.s }) else: m.dynamic = False m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.prop_water = iapws95.Iapws95ParameterBlock() # water pump m.fs.pump = WaterPump(default={ "dynamic": False, "property_package": m.fs.prop_water, }) # water tank m.fs.tank = WaterTank( default={ "tank_type": "simple_tank", "has_holdup": True, "property_package": m.fs.prop_water, }) m.fs.valve = WaterValve( default={ "dynamic": False, "has_holdup": False, "phase": "Liq", "property_package": m.fs.prop_water }) if dynamic: m.fs.controller = PIDController( default={ "pv": m.fs.tank.tank_level, "mv": m.fs.valve.valve_opening, "type": 'PI', "bounded_output": False }) m.discretizer = pyo.TransformationFactory('dae.finite_difference') m.discretizer.apply_to(m, nfe=20, wrt=m.fs.time, scheme="BACKWARD") m.fs.controller.gain_p.fix(-1e-1) m.fs.controller.gain_i.fix(-1e-2) m.fs.controller.setpoint.fix(5) m.fs.controller.mv_ref.fix(0.5) m.fs.controller.integral_of_error[0].fix(0) m.fs.pump_to_tank = Arc(source=m.fs.pump.outlet, destination=m.fs.tank.inlet) m.fs.tank_to_valve = Arc(source=m.fs.tank.outlet, destination=m.fs.valve.inlet) pyo.TransformationFactory('network.expand_arcs').apply_to(m.fs) m.fs.pump.efficiency_isentropic.fix(0.8) m.fs.pump.deltaP.fix(5e4) m.fs.tank.tank_cross_sect_area.fix(20) m.fs.tank.tank_level[:].fix(5) m.fs.valve.Cv.fix(63.4676) m.fs.valve.valve_opening.fix(0.5) m.fs.pump.inlet.flow_mol[:].fix(7000) m.fs.pump.inlet.enth_mol[:].fix(3924) m.fs.pump.inlet.pressure[:].fix(1e7) m.fs.valve.outlet.pressure[:].fix(10050000) set_scaling_factors(m) if dynamic: m.fs.tank.set_initial_condition() if not dynamic: m.fs.pump.initialize() m.fs.tank.inlet.flow_mol[:].value = m.fs.pump.outlet.flow_mol[0].value m.fs.tank.inlet.enth_mol[:].value = m.fs.pump.outlet.enth_mol[0].value m.fs.tank.inlet.pressure[:].value = m.fs.pump.outlet.pressure[0].value m.fs.tank.initialize() m.fs.valve.inlet.flow_mol[:].value = m.fs.tank.outlet.flow_mol[0].value m.fs.valve.inlet.enth_mol[:].value = m.fs.tank.outlet.enth_mol[0].value m.fs.valve.inlet.pressure[:].value = m.fs.tank.outlet.pressure[0].value # Solve for outlet pressure m.fs.valve.initialize() m.fs.valve.valve_opening.unfix() dof = degrees_of_freedom(m) assert dof == 0 solver = pyo.SolverFactory("ipopt") solver.options = { "tol": 1e-7, "linear_solver": "ma27", "max_iter": 100, } solver.solve(m, tee=True) else: m.fs.tank.tank_level.unfix() m.fs.tank.tank_level[0].fix() m.fs.valve.valve_opening.unfix() return m