def build(self): super().build() self._tech_type = "aeration_basin" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "sedimentation" build_sido(self) constant_intensity(self) # TODO: Does it really make sense for this to be indexed by time? self.basin_surface_area = Var(self.flowsheet().config.time, units=pyunits.ft**2, doc="Surface area of sedimentation tank") self.settling_velocity = Var(self.flowsheet().config.time, units=pyunits.m/pyunits.s) self._fixed_perf_vars.append(self.settling_velocity) self._perf_var_dict["Basin Surface Area (ft^2)"] = self.basin_surface_area self._perf_var_dict["Settling Velocity (m/s)"] = self.settling_velocity def rule_basin_surface_area(b, t): return (b.basin_surface_area[t] == pyunits.convert( b.properties_in[t].flow_vol / b.settling_velocity[t], to_units=pyunits.ft**2)) self.basin_surface_area_constraint = Constraint( self.flowsheet().time, rule=rule_basin_surface_area)
def build(self): super().build() self._tech_type = "clarifier" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "vfa_recovery" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "conventional_activated_sludge" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "screen" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "secondary_treatment_wwtp" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "nanofiltration" build_sido(self) if (self.config.process_subtype == "default" or self.config.process_subtype is None): constant_intensity(self) else: self.rejection_comp = Var( self.flowsheet().time, self.config.property_package.config.solute_list, units=pyunits.dimensionless, doc="Component rejection", ) self.water_permeability_coefficient = Var( self.flowsheet().time, units=pyunits.L / pyunits.m**2 / pyunits.hour / pyunits.bar, doc="Membrane water permeability coefficient, A", ) self.applied_pressure = Var( self.flowsheet().time, units=pyunits.bar, doc="Net driving pressure across membrane", ) self.area = Var(units=pyunits.m**2, doc="Membrane area") self._fixed_perf_vars.append(self.applied_pressure) self._fixed_perf_vars.append(self.water_permeability_coefficient) @self.Constraint(self.flowsheet().time, doc="Water permeance constraint") def water_permeance_constraint(b, t): return b.properties_treated[t].flow_vol == pyunits.convert( b.water_permeability_coefficient[t] * b.area * b.applied_pressure[t], to_units=pyunits.m**3 / pyunits.s, ) @self.Constraint( self.flowsheet().time, self.config.property_package.config.solute_list, doc="Solute [observed] rejection constraint", ) def rejection_constraint(b, t, j): return (b.rejection_comp[t, j] == 1 - b.properties_treated[t].conc_mass_comp[j] / b.properties_in[t].conc_mass_comp[j]) self._perf_var_dict["Membrane Area (m^2)"] = self.area self._perf_var_dict[ "Net Driving Pressure (bar)"] = self.applied_pressure self._perf_var_dict[ "Water Permeability Coefficient (LMH/bar)"] = self.water_permeability_coefficient self._perf_var_dict[f"Rejection"] = self.rejection_comp
def build(self): super().build() self._tech_type = "media_filtration" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "primary_separator" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "cooling_tower" build_sido(self) constant_intensity(self) self.cycles = Var(units=pyunits.dimensionless, doc="Cycles of concentration") self.blowdown = Var( self.flowsheet().time, units=pyunits.m**3 / pyunits.hour, doc="Flowrate of blowdown", ) self._fixed_perf_vars.append(self.cycles) @self.Constraint(self.flowsheet().time, doc="Blowdown constraint") def blowdown_constraint(b, t): q_in = pyunits.convert(b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour) return b.blowdown[t] == pyunits.convert(q_in * b.cycles, to_units=pyunits.m**3 / pyunits.hour) self._perf_var_dict["Cycles"] = self.cycles self._perf_var_dict["Blowdown flowrate (m^3/hr)"] = self.blowdown
def build(self): super().build() self._tech_type = "sludge_tank" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "anaerobic_digestion_oxidation" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "walnut_shell_filter" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "settling_pond" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "air_flotation" build_sido(self) constant_intensity(self)
def build(self): super().build() self._tech_type = "backwash_solids_handling" build_sido(self) self._Q = Reference(self.properties_in[:].flow_vol) pump_electricity(self, self._Q)
def build(self): super().build() self._tech_type = "electrodialysis_reversal" build_sido(self) if "tds" not in self.config.property_package.solute_set: raise KeyError( "TDS must be included in the solute list for determining" " electricity intensity and power consumption of the electrodialysis " "reversal unit.") self.elec_coeff_1 = Var( units=pyunits.kWh / pyunits.m**3, doc="Constant 1 in electricity intensity equation", ) self.elec_coeff_2 = Var( units=pyunits.L / pyunits.mg * pyunits.kWh / pyunits.m**3, doc="Constant 2 in electricity intensity equation", ) self._fixed_perf_vars.append(self.elec_coeff_1) self._fixed_perf_vars.append(self.elec_coeff_2) self.electricity = Var( self.flowsheet().config.time, units=pyunits.kW, bounds=(0, None), doc="Power consumption of brine concentrator", ) self.electricity_intensity = Var( self.flowsheet().config.time, units=pyunits.kWh / pyunits.m**3, doc="Specific energy consumption with respect to feed flowrate", ) @self.Constraint(self.flowsheet().config.time, doc="Electricity intensity constraint") def electricity_intensity_constraint(b, t): tds_in = pyunits.convert( b.properties_in[t].conc_mass_comp["tds"], to_units=pyunits.mg / pyunits.L, ) return (b.electricity_intensity[t] == b.elec_coeff_1 + b.elec_coeff_2 * tds_in) @self.Constraint(self.flowsheet().config.time, doc="Power consumption constraint") def electricity_constraint(b, t): q_in = pyunits.convert(b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour) return b.electricity[t] == b.electricity_intensity[t] * q_in self._perf_var_dict["Power Consumption (kW)"] = self.electricity self._perf_var_dict[ "Electricity intensity per Inlet Flowrate (kWh/m3)"] = self.electricity_intensity
def build(self): super().build() self._tech_type = "gac" build_sido(self) self._Q = Reference(self.properties_in[:].flow_vol) # TODO: incorporate a*Q**b relationship for electricity consumption based on EPA data fitting; # apply pump electricity consumption in the meantime pump_electricity(self, self._Q)
def build(self): super().build() build_sido(self) self._tech_type = "evaporation_pond" self.air_temperature = Var( self.flowsheet().time, initialize=298, units=pyunits.kelvin, doc="Air temperature", ) self.solar_radiation = Var( self.flowsheet().time, units=pyunits.mJ / pyunits.m**2, doc="Daily solar radiation incident", ) self.dike_height = Var(self.flowsheet().time, units=pyunits.ft, doc="Pond dike height") self.evaporation_rate_adj_factor = Var( self.flowsheet().time, units=pyunits.dimensionless, doc="Factor to adjust evaporation rate of pure water", ) self.evap_rate_calc_a_parameter = Var( self.flowsheet().time, units=pyunits.mm / pyunits.d, doc="Evaporation rate calculation parameter A", ) self.evap_rate_calc_b_parameter = Var( self.flowsheet().time, units=pyunits.m**2 / pyunits.mJ, doc="Evaporation rate calculation parameter B", ) self.evap_rate_calc_c_parameter = Var( self.flowsheet().time, units=pyunits.m**2 / pyunits.mJ, doc="Evaporation rate calculation parameter C", ) self.adj_area_calc_a_parameter = Var( self.flowsheet().time, units=pyunits.acres, doc="Adjusted area calculation parameter A", ) self.adj_area_calc_b_parameter = Var( self.flowsheet().time, units=pyunits.dimensionless, doc="Adjusted area calculation parameter B", ) self._fixed_perf_vars.append(self.air_temperature) self._fixed_perf_vars.append(self.solar_radiation) self._fixed_perf_vars.append(self.dike_height) self._fixed_perf_vars.append(self.evaporation_rate_adj_factor) self._fixed_perf_vars.append(self.evap_rate_calc_a_parameter) self._fixed_perf_vars.append(self.evap_rate_calc_b_parameter) self._fixed_perf_vars.append(self.evap_rate_calc_c_parameter) self._fixed_perf_vars.append(self.adj_area_calc_a_parameter) self._fixed_perf_vars.append(self.adj_area_calc_b_parameter) self.area = Var( self.flowsheet().time, initialize=1, units=pyunits.acres, bounds=(0, None), doc="Pond area needed based on evaporation rate", ) self.adj_area = Var(self.flowsheet().time, units=pyunits.acres, doc="Adjusted pond area needed") self.evaporation_rate_pure = Var( self.flowsheet().time, units=pyunits.mm / pyunits.d, doc="Calculated evaporation rate of pure water", ) self.evaporation_rate_salt = Var( self.flowsheet().time, units=(pyunits.gallons / pyunits.minute / pyunits.acre), doc="Pure water evaporation rate adjusted for salinity", ) @self.Constraint(self.flowsheet().time, doc="Evaporation rate of pure water constraint") def evap_rate_pure_constraint(b, t): air_temperature_C = pyunits.convert_temp_K_to_C( value(b.air_temperature[t])) return ( b.evaporation_rate_pure[t] == b.evap_rate_calc_a_parameter[t] * (b.evap_rate_calc_b_parameter[t] * air_temperature_C + b.evap_rate_calc_c_parameter[t]) * b.solar_radiation[t]) @self.Constraint( self.flowsheet().time, doc="Adjusted evaporation rate for salinity constraint", ) def evap_rate_salt_constraint(b, t): evap_rate_gal_min_acre = pyunits.convert( b.evaporation_rate_pure[t], to_units=(pyunits.gallons / pyunits.minute / pyunits.acre), ) return (b.evaporation_rate_salt[t] == evap_rate_gal_min_acre * b.evaporation_rate_adj_factor[t]) @self.Constraint(self.flowsheet().time, doc="Base area constraint") def area_constraint(b, t): q_out = pyunits.convert( self.properties_byproduct[t].flow_vol, to_units=pyunits.gallon / pyunits.minute, ) return q_out == b.evaporation_rate_salt[t] * b.area[t] @self.Constraint(self.flowsheet().time, doc="Adjusted area constraint") def area_adj_constraint(b, t): area = b.area[t] / pyunits.acres dike_ht = b.dike_height[t] / pyunits.ft return b.adj_area[t] == b.adj_area_calc_a_parameter[t] * area * ( 1 + (b.adj_area_calc_b_parameter[t] * dike_ht) / area**0.5) self._perf_var_dict[ "Evaporation rate (mm/d)"] = self.evaporation_rate_pure self._perf_var_dict["Pond area (acres)"] = self.adj_area self._perf_var_dict["Pond dike height (ft)"] = self.dike_height
def build(self): super().build() self._tech_type = "ion_exchange" build_sido(self) self._Q = Reference(self.properties_in[:].flow_vol) pump_electricity(self, self._Q) # mutable parameter; default value found in WT3 for anion exchange self.eta_pump.set_value(0.8) # mutable parameter; default value of 2 bar converted to feet head self.lift_height.set_value(69.91052 * pyunits.feet) # Add variables and constraints for material requirements self.NaCl_flowrate = Var( self.flowsheet().time, initialize=1, units=pyunits.kg / pyunits.s, bounds=(0, None), doc="Flowrate of NaCl addition", ) self.NaCl_dose = Var( units=pyunits.kg / pyunits.m**3, bounds=(0, None), doc="Dosage of NaCl addition", ) self._fixed_perf_vars.append(self.NaCl_dose) self._perf_var_dict["NaCl Addition"] = self.NaCl_flowrate @self.Constraint(self.flowsheet().time) def NaCl_constraint(blk, t): return blk.NaCl_flowrate[t] == blk.NaCl_dose * blk.properties_in[t].flow_vol self.resin_demand = Var( self.flowsheet().time, initialize=1, units=pyunits.kg / pyunits.s, bounds=(0, None), doc="Replacement rate of ion exchange resin", ) self.resin_replacement = Var( units=pyunits.kg / pyunits.m**3, bounds=(0, None), doc="Resin replacement as a function of flow", ) self._fixed_perf_vars.append(self.resin_replacement) self._perf_var_dict["Resin Demand"] = self.resin_demand @self.Constraint(self.flowsheet().time) def resin_constraint(blk, t): return ( blk.resin_demand[t] == blk.resin_replacement * blk.properties_in[t].flow_vol ) if self.config.process_subtype == "clinoptilolite": if "ammonium_as_nitrogen" in self.config.property_package.solute_set: self.nitrogen_clay_ratio = Var( self.flowsheet().config.time, units=pyunits.dimensionless, doc="Mass fraction of nitrogen in clay mixture", ) self._fixed_perf_vars.append(self.nitrogen_clay_ratio) self.final_solids_mass = Var( self.flowsheet().config.time, units=pyunits.kg / pyunits.s, doc="Solids mass flow in byproduct stream", ) @self.Constraint( self.flowsheet().time, doc="Solids mass flow in byproduct stream constraint", ) def solids_mass_flow_constraint(b, t): return ( b.final_solids_mass[t] == b.properties_byproduct[t].flow_mass_comp[ "ammonium_as_nitrogen" ] / b.nitrogen_clay_ratio[t] ) self._perf_var_dict[ "Nitrogen-Clay Mixture Ratio (kg/kg)" ] = self.nitrogen_clay_ratio self._perf_var_dict[ "Final mass flow of clay and nitrogen (kg/s)" ] = self.final_solids_mass else: raise KeyError( "ammonium_as_nitrogen should be defined in solute_list for this subtype." )
def build(self): super().build() self._tech_type = "gac" build_sido(self) # Empty Bed Contact Time self.empty_bed_contact_time = Var(units=pyunits.hour, bounds=(0, None), doc="Empty bed contact time of unit") self._fixed_perf_vars.append(self.empty_bed_contact_time) self._perf_var_dict[ "Empty Bed Contact Time"] = self.empty_bed_contact_time # Electricity Demand self.electricity = Var( self.flowsheet().time, units=pyunits.kW, bounds=(0, None), doc="Electricity consumption of unit", ) self.electricity_intensity_parameter = Var( units=pyunits.kW / pyunits.m**3, doc="Parameter for calculating electricity base on empty bed " "contacting time", ) self.energy_electric_flow_vol_inlet = Var( units=pyunits.kWh / pyunits.m**3, doc="Electricity intensity with respect to inlet flowrate of unit", ) @self.Constraint( doc="Electricity intensity based on empty bed contact time.") def electricity_intensity_constraint(b): return (b.energy_electric_flow_vol_inlet == b.electricity_intensity_parameter * b.empty_bed_contact_time) @self.Constraint( self.flowsheet().time, doc="Constraint for electricity consumption based on " "feed flowrate.", ) def electricity_consumption(b, t): return b.electricity[t] == ( b.energy_electric_flow_vol_inlet * pyunits.convert( b.get_inlet_flow(t), to_units=pyunits.m**3 / pyunits.hour)) self._fixed_perf_vars.append(self.electricity_intensity_parameter) self._perf_var_dict["Electricity Demand"] = self.electricity self._perf_var_dict[ "Electricity Intensity"] = self.energy_electric_flow_vol_inlet # Demand for activated carbon self.activated_carbon_replacement = Var( units=pyunits.kg / pyunits.m**3, bounds=(0, None), doc="Replacement rate of activated carbon", ) self.activated_carbon_demand = Var( self.flowsheet().time, units=pyunits.kg / pyunits.hour, bounds=(0, None), doc="Demand for activated carbon", ) @self.Constraint(self.flowsheet().time, doc="Constraint for activated carbon consumption.") def activated_carbon_equation(b, t): return b.activated_carbon_demand[t] == ( b.activated_carbon_replacement * pyunits.convert( b.get_inlet_flow(t), to_units=pyunits.m**3 / pyunits.hour)) self._fixed_perf_vars.append(self.activated_carbon_replacement) self._perf_var_dict[ "Activated Carbon Demand"] = self.activated_carbon_demand
def build(self): super().build() self._tech_type = "brine_concentrator" build_sido(self) if "tds" not in self.config.property_package.solute_set: raise KeyError( "TDS must be included in the solute list for determining" " electricity intensity and power consumption of the brine " "concentrator unit." ) # Fitting parameters based on regressions for capital and electricity # developed from data in Table 5.1, Table A2.3 in: # Survey of High-Recovery and Zero Liquid Discharge Technologies for # Water Utilities (2008). WateReuse Foundation: # https://www.waterboards.ca.gov/water_issues/programs/grants_loans/water_recycling/research/02_006a_01.pdf # Capital = f(TDS, recovery, flow) # Electricity = f(TDS, recovery, flow) self.elec_coeff_1 = Var( units=pyunits.kWh / pyunits.m**3, doc="Constant 1 in electricity intensity equation", ) self.elec_coeff_2 = Var( units=pyunits.L / pyunits.mg * pyunits.kWh / pyunits.m**3, doc="Constant 2 in electricity intensity equation", ) self.elec_coeff_3 = Var( units=pyunits.kWh / pyunits.m**3, doc="Constant 3 in electricity intensity equation", ) self.elec_coeff_4 = Var( units=pyunits.kWh / pyunits.m**6 * pyunits.hour, doc="Constant 4 in electricity intensity equation", ) self._fixed_perf_vars.append(self.elec_coeff_1) self._fixed_perf_vars.append(self.elec_coeff_2) self._fixed_perf_vars.append(self.elec_coeff_3) self._fixed_perf_vars.append(self.elec_coeff_4) self.electricity = Var( self.flowsheet().config.time, units=pyunits.kW, bounds=(0, None), doc="Power consumption of brine concentrator", ) self.electricity_intensity = Var( self.flowsheet().config.time, units=pyunits.kWh / pyunits.m**3, doc="Specific energy consumption with respect to feed flowrate", ) @self.Constraint( self.flowsheet().config.time, doc="Electricity intensity constraint" ) def electricity_intensity_constraint(b, t): q_in = pyunits.convert( b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour ) tds_in = pyunits.convert( b.properties_in[t].conc_mass_comp["tds"], to_units=pyunits.mg / pyunits.L, ) return ( b.electricity_intensity[t] == b.elec_coeff_1 + b.elec_coeff_2 * tds_in + b.elec_coeff_3 * b.recovery_frac_mass_H2O[t] + b.elec_coeff_4 * q_in ) @self.Constraint( self.flowsheet().config.time, doc="Power consumption constraint" ) def electricity_constraint(b, t): q_in = pyunits.convert( b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour ) return b.electricity[t] == b.electricity_intensity[t] * q_in self._perf_var_dict["Power Consumption (kW)"] = self.electricity self._perf_var_dict[ "Electricity intensity per Inlet Flowrate (kWh/m3)" ] = self.electricity_intensity
def build(self): super().build() self._tech_type = "iron_and_manganese_removal" build_sido(self) self.air_water_ratio = Var( self.flowsheet().time, units=pyunits.dimensionless, doc="Ratio of air to water", ) self.flow_basis = Var(self.flowsheet().time, units=pyunits.m**3 / pyunits.hour, doc="Flow basis") self.air_flow_rate = Var( self.flowsheet().time, units=pyunits.m**3 / pyunits.hour, doc="Air flow rate", ) self.electricity_intensity_parameter = Var( units=pyunits.hp / (pyunits.m**3 / pyunits.hour), doc="Constant in electricity intensity equation", ) self.filter_surf_area = Var(units=pyunits.m**2, doc="Dual media filter surface area") self.num_filter_units = Var(units=pyunits.dimensionless, doc="Number of dual media filter units") self.electricity = Var( self.flowsheet().config.time, units=pyunits.kW, bounds=(0, None), doc="Power consumption of iron and manganese removal", ) self.electricity_intensity = Var( self.flowsheet().config.time, units=pyunits.kWh / pyunits.m**3, doc="Specific energy consumption with respect to feed flowrate", ) self._fixed_perf_vars.append(self.air_water_ratio) self._fixed_perf_vars.append(self.flow_basis) self._fixed_perf_vars.append(self.electricity_intensity_parameter) self._fixed_perf_vars.append(self.filter_surf_area) self._fixed_perf_vars.append(self.num_filter_units) @self.Constraint(self.flowsheet().config.time, doc="Air flow rate constraint") def air_flow_rate_constraint(b, t): q_in = pyunits.convert(b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour) return b.air_flow_rate[t] == b.air_water_ratio[t] * q_in @self.Constraint(self.flowsheet().config.time, doc="Electricity intensity constraint") def electricity_intensity_constraint(b, t): return b.electricity_intensity[t] == pyunits.convert( b.electricity_intensity_parameter * b.air_water_ratio[t], to_units=pyunits.kWh / pyunits.m**3, ) @self.Constraint(self.flowsheet().config.time, doc="Power consumption constraint") def electricity_constraint(b, t): q_in = pyunits.convert(b.properties_in[t].flow_vol, to_units=pyunits.m**3 / pyunits.hour) return b.electricity[t] == b.electricity_intensity[t] * q_in self._perf_var_dict["Power Consumption (kW)"] = self.electricity self._perf_var_dict[ "Electricity intensity per Inlet Flowrate (kWh/m3)"] = self.electricity_intensity
def build(self): super().build() self._tech_type = "sedimentation" build_sido(self) constant_intensity(self) # TODO: Does it really make sense for this to be indexed by time? self.basin_surface_area = Var( self.flowsheet().config.time, units=pyunits.ft**2, doc="Surface area of sedimentation tank", ) self.settling_velocity = Var( self.flowsheet().config.time, units=pyunits.m / pyunits.s, doc="Particle settling velocity", ) self._fixed_perf_vars.append(self.settling_velocity) self._perf_var_dict[ "Basin Surface Area (ft^2)"] = self.basin_surface_area self._perf_var_dict["Settling Velocity (m/s)"] = self.settling_velocity def rule_basin_surface_area(b, t): return b.basin_surface_area[t] == pyunits.convert( b.properties_in[t].flow_vol / b.settling_velocity[t], to_units=pyunits.ft**2, ) self.basin_surface_area_constraint = Constraint( self.flowsheet().time, rule=rule_basin_surface_area) if self.config.process_subtype == "phosphorus_capture": self.phosphorus_solids_ratio = Var( self.flowsheet().config.time, units=pyunits.dimensionless, doc="Mass fraction of phosphorus in settleable solids", ) self._fixed_perf_vars.append(self.phosphorus_solids_ratio) self._perf_var_dict[ "Phosphorus-Solids Ratio (kg/kg)"] = self.phosphorus_solids_ratio # This subtype is intended to be used explicitly for phosphorous capture. # If the user provides TSS, the amount of settled phosphate would be determined based on # an assumed fraction of phosphate in TSS. Alternatively, the user could provide phosphates # as the species, and the amount of solids + phosphate settled would be reported. # However, the user cannot provide both TSS and phosphates. if ("phosphates" in self.config.property_package.solute_set and "tss" in self.config.property_package.solute_set): raise KeyError( "tss and phosphates cannot both be defined in the solute_list. " "Please choose one.") elif "phosphates" in self.config.property_package.solute_set: self.final_solids_mass = Var( self.flowsheet().config.time, units=pyunits.kg / pyunits.s, doc="Solids mass flow in byproduct stream", ) @self.Constraint( self.flowsheet().time, doc="Solids mass flow in byproduct stream constraint", ) def solids_mass_flow_constraint(b, t): return (b.final_solids_mass[t] == b.properties_byproduct[t] .flow_mass_comp["phosphates"] / b.phosphorus_solids_ratio[t]) self._perf_var_dict[ "Final mass flow of settled solids (kg/s)"] = self.final_solids_mass elif "tss" in self.config.property_package.solute_set: self.final_phosphate_mass = Var( self.flowsheet().config.time, units=pyunits.kg / pyunits.s, doc="Phosphate mass flow in byproduct stream", ) @self.Constraint( self.flowsheet().time, doc="Phosphate mass flow in byproduct stream constraint", ) def phosphate_mass_flow_constraint(b, t): return (b.final_phosphate_mass[t] == b.properties_byproduct[t].flow_mass_comp["tss"] * b.phosphorus_solids_ratio[t]) self._perf_var_dict[ "Final mass flow of settled phosphate (kg/s)"] = self.final_phosphate_mass else: # Raise this error in case the user is intended to make use of the subtype but entered # the wrong component names. raise KeyError( "One of the following should be specified in the solute_list: " "tss or phosphates")
def build(self): super().build() self._tech_type = "filter_press" build_sido(self) self.hours_per_day_operation = Var( self.flowsheet().time, units=pyunits.hour / pyunits.day, doc="Hours per day of filter press operation", ) self.cycle_time = Var( self.flowsheet().time, units=pyunits.hours, doc="Filter press cycle time" ) self.electricity_a_parameter = Var( self.flowsheet().time, units=pyunits.kWh / (pyunits.year * pyunits.ft**3), doc="Parameter A for electricity calculation", ) self.electricity_b_parameter = Var( self.flowsheet().time, units=pyunits.dimensionless, doc="Parameter B for electricity calculation", ) self._fixed_perf_vars.append(self.hours_per_day_operation) self._fixed_perf_vars.append(self.cycle_time) self._fixed_perf_vars.append(self.electricity_a_parameter) self._fixed_perf_vars.append(self.electricity_b_parameter) self.filter_press_capacity = Var( self.flowsheet().time, initialize=10, units=pyunits.ft**3, doc="Filter press capacity", ) self.electricity = Var( self.flowsheet().time, units=pyunits.kW, bounds=(0, None), doc="Filter press power", ) @self.Constraint(self.flowsheet().time, doc="Filter press capacity constraint") def fp_capacity(b, t): Q = b.properties_in[t].flow_vol return b.filter_press_capacity[t] == pyunits.convert( Q, to_units=pyunits.ft**3 / pyunits.day ) / (b.hours_per_day_operation[t] / b.cycle_time[t]) @self.Constraint( self.flowsheet().time, doc="Filter press electricity constraint" ) def fp_electricity(b, t): Q = b.properties_in[t].flow_vol A = pyunits.convert( b.electricity_a_parameter[t] / (pyunits.kWh / (pyunits.year * pyunits.ft**3)), to_units=pyunits.dimensionless, ) fp_cap = pyunits.convert( b.filter_press_capacity[t] / pyunits.ft**3, to_units=pyunits.dimensionless, ) return b.electricity[t] == (A * fp_cap ** b.electricity_b_parameter[t]) * ( pyunits.kWh / pyunits.year ) / pyunits.convert( Q, to_units=pyunits.m**3 / pyunits.yr ) * pyunits.convert( Q, to_units=pyunits.m**3 / pyunits.hr ) self._perf_var_dict["Filter Press Capacity (ft3)"] = self.filter_press_capacity self._perf_var_dict["Filter Press Power (kW)"] = self.electricity