def test_Separator_3(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.params = PropertyInterrogatorBlock() m.fs.S01 = Separator( default={ "property_package": m.fs.params, "material_balance_type": MaterialBalanceType.componentPhase, "split_basis": SplittingType.componentFlow, "outlet_list": ["a", "B", "c"], "ideal_separation": False, "has_phase_equilibrium": False }) assert len(m.fs.params.required_properties) == 3 for k in m.fs.params.required_properties.keys(): assert k in ["material flow terms", "pressure", "temperature"]
def test_ideal_Separator_3(): m = ConcreteModel() m.fs = FlowsheetBlock(default={"dynamic": False}) m.fs.params = PropertyInterrogatorBlock() m.fs.S01 = Separator( default={ "property_package": m.fs.params, "num_outlets": 2, "ideal_separation": True, "split_basis": SplittingType.componentFlow, "ideal_split_map": { ("A"): "outlet_1", ("B"): "outlet_2" } }) # Ideal Separator should require no property calls # Only dummy state variables are required assert len(m.fs.params.required_properties) == 0
def build_boiler(fs): # Add property packages to flowsheet library fs.prop_fluegas = FlueGasParameterBlock() # Create unit models # Boiler Economizer fs.ECON = BoilerHeatExchanger( default={ "side_1_property_package": fs.prop_water, "side_2_property_package": fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Liq", "has_radiation": False }) # Primary Superheater fs.PrSH = BoilerHeatExchanger( default={ "side_1_property_package": fs.prop_water, "side_2_property_package": fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Vap", "has_radiation": True }) # Finishing Superheater fs.FSH = BoilerHeatExchanger( default={ "side_1_property_package": fs.prop_water, "side_2_property_package": fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Vap", "has_radiation": True }) # Reheater fs.RH = BoilerHeatExchanger( default={ "side_1_property_package": fs.prop_water, "side_2_property_package": fs.prop_fluegas, "has_pressure_change": True, "has_holdup": False, "delta_T_method": DeltaTMethod.counterCurrent, "tube_arrangement": TubeArrangement.inLine, "side_1_water_phase": "Vap", "has_radiation": True }) # Platen Superheater fs.PlSH = Heater(default={"property_package": fs.prop_water}) # Boiler Water Wall fs.Water_wall = Heater(default={"property_package": fs.prop_water}) # Boiler Splitter (splits FSH flue gas outlet to Reheater and PrSH) fs.Spl1 = Separator( default={ "property_package": fs.prop_fluegas, "split_basis": SplittingType.totalFlow, "energy_split_basis": EnergySplittingType.equal_temperature }) # Flue gas mixer (mixing FG from Reheater and Primary SH, inlet to ECON) fs.mix1 = Mixer( default={ "property_package": fs.prop_fluegas, "inlet_list": ['Reheat_out', 'PrSH_out'], "dynamic": False }) # Mixer for Attemperator #1 (between PrSH and PlSH) fs.ATMP1 = Mixer( default={ "property_package": fs.prop_water, "inlet_list": ['Steam', 'SprayWater'], "dynamic": False }) # Build connections (streams) # Steam Route (side 1 = tube side = steam/water side) # Boiler feed water to Economizer (to be imported in full plant model) # fs.bfw2econ = Arc(source=fs.FWH8.outlet, # destination=fs.ECON.side_1_inlet) fs.econ2ww = Arc(source=fs.ECON.side_1_outlet, destination=fs.Water_wall.inlet) fs.ww2prsh = Arc(source=fs.Water_wall.outlet, destination=fs.PrSH.side_1_inlet) fs.prsh2plsh = Arc(source=fs.PrSH.side_1_outlet, destination=fs.PlSH.inlet) fs.plsh2fsh = Arc(source=fs.PlSH.outlet, destination=fs.FSH.side_1_inlet) fs.FSHtoATMP1 = Arc(source=fs.FSH.side_1_outlet, destination=fs.ATMP1.Steam) # fs.fsh2hpturbine=Arc(source=fs.ATMP1.outlet, # destination=fs.HPTinlet) # (to be imported in full plant model) # Flue gas route --------------------------------------------------------- # water wall connected with boiler block (to fix the heat duty) # platen SH connected with boiler block (to fix the heat duty) # Finishing superheater connected with a flowsheet level constraint fs.fg_fsh2_separator = Arc(source=fs.FSH.side_2_outlet, destination=fs.Spl1.inlet) fs.fg_fsh2rh = Arc(source=fs.Spl1.outlet_1, destination=fs.RH.side_2_inlet) fs.fg_fsh2PrSH = Arc(source=fs.Spl1.outlet_2, destination=fs.PrSH.side_2_inlet) fs.fg_rhtomix = Arc(source=fs.RH.side_2_outlet, destination=fs.mix1.Reheat_out) fs.fg_prsh2mix = Arc(source=fs.PrSH.side_2_outlet, destination=fs.mix1.PrSH_out) fs.fg_mix2econ = Arc(source=fs.mix1.outlet, destination=fs.ECON.side_2_inlet)
def build(self): """ Begin building model (pre-DAE transformation). Args: None Returns: None """ # Call UnitModel.build to setup dynamics super(FlashData, self).build() # Build Control Volume self.control_volume = ControlVolume0DBlock( default={ "dynamic": self.config.dynamic, "has_holdup": self.config.has_holdup, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args }) self.control_volume.add_state_blocks(has_phase_equilibrium=True) self.control_volume.add_material_balances( balance_type=self.config.material_balance_type, has_phase_equilibrium=True) self.control_volume.add_energy_balances( balance_type=self.config.energy_balance_type, has_heat_transfer=self.config.has_heat_transfer) self.control_volume.add_momentum_balances( balance_type=self.config.momentum_balance_type, has_pressure_change=self.config.has_pressure_change) # Add Ports self.add_inlet_port() split_map = {} for p in self.control_volume.properties_in.phase_list: p_obj = self.config.property_package.get_phase(p) if p_obj.is_vapor_phase(): # Vapor leaves through Vap outlet split_map[p] = "Vap" else: # All other phases leave through Liq outlet split_map[p] = "Liq" self.split = Separator( default={ "property_package": self.config.property_package, "property_package_args": self.config.property_package_args, "outlet_list": ["Vap", "Liq"], "split_basis": SplittingType.phaseFlow, "ideal_separation": self.config.ideal_separation, "ideal_split_map": split_map, "mixed_state_block": self.control_volume.properties_out, "has_phase_equilibrium": not self.config.ideal_separation, "energy_split_basis": self.config.energy_split_basis }) if not self.config.ideal_separation: def split_frac_rule(b, t, o): return b.split.split_fraction[t, o, o] == 1 self.split_fraction_eq = Constraint(self.flowsheet().config.time, self.split.outlet_idx, rule=split_frac_rule) self.vap_outlet = Port(extends=self.split.Vap) self.liq_outlet = Port(extends=self.split.Liq) # Add references if (self.config.has_heat_transfer is True and self.config.energy_balance_type != EnergyBalanceType.none): self.heat_duty = Reference(self.control_volume.heat[:]) if (self.config.has_pressure_change is True and self.config.momentum_balance_type != MomentumBalanceType.none): self.deltaP = Reference(self.control_volume.deltaP[:])
def build(self): """ Begin building model (pre-DAE transformation). Args: None Returns: None """ # Call UnitModel.build to setup dynamics super(WaterFlashData, self).build() # Build Control Volume self.control_volume = ControlVolume0DBlock( default={ "dynamic": self.config.dynamic, "has_holdup": self.config.has_holdup, "property_package": self.config.property_package, "property_package_args": self.config.property_package_args }) self.control_volume.add_state_blocks( has_phase_equilibrium=self.config.has_phase_equilibrium) self.control_volume.add_material_balances( balance_type=self.config.material_balance_type, has_phase_equilibrium=self.config.has_phase_equilibrium) self.control_volume.add_energy_balances( balance_type=self.config.energy_balance_type, has_heat_transfer=self.config.has_heat_transfer) self.control_volume.add_momentum_balances( balance_type=self.config.momentum_balance_type, has_pressure_change=self.config.has_pressure_change) # Add Ports self.add_inlet_port() #split_map = {} #for p in self.config.property_package.phase_list: # split_map[p] = p self.split = Separator( default={ "property_package": self.config.property_package, "property_package_args": self.config.property_package_args, "outlet_list": ["Vap", "Liq"], "split_basis": SplittingType.totalFlow, "ideal_separation": False, "mixed_state_block": self.control_volume.properties_out }) add_object_reference(self, "vap_outlet", self.split.Vap) add_object_reference(self, "liq_outlet", self.split.Liq) # Add references if (self.config.has_heat_transfer is True and self.config.energy_balance_type != 'none'): add_object_reference(self, "heat_duty", self.control_volume.heat) if (self.config.has_pressure_change is True and self.config.momentum_balance_type != 'none'): add_object_reference(self, "deltaP", self.control_volume.deltaP) # Specify split fraction add_object_reference(self, "split_fraction", self.split.split_fraction) @self.Constraint(self.flowsheet().config.time, doc="mol flow rate for vapor outlet") def flow_mol_vapor_eqn(b, t): return b.split_fraction[t, "Vap"] == \ b.control_volume.properties_in[t].vapor_frac # it seems that the temperature_splitting equation is defined in ports as default self.split.temperature_equality_eqn.deactivate() @self.Constraint(self.flowsheet().config.time, doc="mol enthalpy for vapor outlet") def enth_mol_vapor_eqn(b, t): return b.vap_outlet.enth_mol[t] == b.control_volume.properties_in[ t].enth_mol_sat_phase["Vap"] @self.Constraint(self.flowsheet().config.time, doc="mol enthalpy for liquid outlet") def enth_mol_liquid_eqn(b, t): return b.liq_outlet.enth_mol[t] == b.control_volume.properties_in[ t].enth_mol_sat_phase["Liq"]