예제 #1
0
    def build(self):
        super().build()

        self._tech_type = "aeration_basin"

        build_sido(self)
        constant_intensity(self)
예제 #2
0
    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)
예제 #3
0
    def build(self):
        super().build()

        self._tech_type = "clarifier"

        build_sido(self)
        constant_intensity(self)
예제 #4
0
    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)
예제 #6
0
    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)
예제 #8
0
    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
예제 #9
0
    def build(self):
        super().build()

        self._tech_type = "media_filtration"

        build_sido(self)
        constant_intensity(self)
예제 #10
0
    def build(self):
        super().build()

        self._tech_type = "primary_separator"

        build_sido(self)
        constant_intensity(self)
예제 #11
0
    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
예제 #12
0
    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)
예제 #14
0
    def build(self):
        super().build()

        self._tech_type = "walnut_shell_filter"

        build_sido(self)
        constant_intensity(self)
예제 #15
0
    def build(self):
        super().build()

        self._tech_type = "settling_pond"

        build_sido(self)
        constant_intensity(self)
예제 #16
0
    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)
예제 #18
0
    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
예제 #19
0
    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)
예제 #20
0
    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
예제 #21
0
    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."
                )
예제 #22
0
    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
예제 #23
0
    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
예제 #25
0
    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")
예제 #26
0
    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