Exemplo n.º 1
0
    def test_case_sensitive_shortnamelabeler(self):
        m = self.m
        lbl = ShortNameLabeler(20, '_')
        self.assertEqual(lbl(m.mycomp), 'mycomp')
        self.assertEqual(lbl(m.that), 'that')
        self.assertEqual(lbl(self.long1), 'longcomponentname_1_')
        self.assertEqual(lbl(self.long2), 'nentnamerighthere_2_')
        self.assertEqual(lbl(self.long3), 'ngonebutdifferent_3_')
        self.assertEqual(lbl(self.long4), 'longcomponentname_4_')
        self.assertEqual(lbl(self.long5), 'gcomponentname_1__5_')
        self.assertEqual(lbl(m.myblock), 'myblock')
        self.assertEqual(lbl(m.myblock.mystreet), 'myblock_mystreet')
        self.assertEqual(lbl(m.ind[3]), 'ind_3_')
        self.assertEqual(lbl(m.ind[10]), 'ind_10_')
        self.assertEqual(lbl(m.ind[1]), 'ind_1_')
        self.assertEqual(lbl(self.thecopy), '_myblock_mystreet_')

        # Test name collision
        m._myblock = Block()
        m._myblock.mystreet_ = Var()
        self.assertEqual(lbl(m.mycomp), 'mycomp_6_')
        self.assertEqual(lbl(m._myblock.mystreet_), 'myblock_mystreet__7_')
        self.assertEqual(lbl(m.MyComp), 'MyComp')
Exemplo n.º 2
0
    def test_str(self):
        m = ConcreteModel()
        m.b = Block()
        # Note that we are testing the string representation of a slice,
        # not if the slice is valid
        s = m.b[...].x[:, 1:2, 1:5:2, ::1, 5, 'a'].component('foo', kwarg=1)
        self.assertEqual(
            str(s),
            "b[...].x[:, 1:2, 1:5:2, ::1, 5, 'a'].component('foo', kwarg=1)")

        # To test set / del, we want to form the IndexedComponent_slice
        # without evaluating it
        s = m.b[...]
        self.assertEqual(
            str(
                IndexedComponent_slice(
                    s, (IndexedComponent_slice.del_attribute, 'bogus'))),
            'del b[...].bogus')
        self.assertEqual(
            str(
                IndexedComponent_slice(
                    s, (IndexedComponent_slice.set_attribute, 'bogus', 10))),
            'b[...].bogus = 10')
Exemplo n.º 3
0
    def test_nested_reference_nonuniform_index_size(self):
        m = ConcreteModel()
        m.I = Set(initialize=[1, 2])
        m.J = Set(initialize=[3, 4])
        m.b = Block(m.I)
        m.b[1].x = Var([(3, 3), (3, 4), (4, 3), (4, 4)], bounds=(1, None))
        m.b[2].x = Var(m.J, m.J, bounds=(2, None))

        m.r = Reference(m.b[:].x[:, :])

        self.assertIs(m.r.ctype, Var)
        self.assertIs(type(m.r.index_set()), UnorderedSetOf)
        self.assertEqual(len(m.r), 2 * 2 * 2)
        self.assertEqual(m.r[1, 3, 3].lb, 1)
        self.assertEqual(m.r[2, 4, 3].lb, 2)
        self.assertIn((1, 3, 3), m.r)
        self.assertIn((2, 4, 4), m.r)
        self.assertNotIn(0, m.r)
        self.assertNotIn((1, 0), m.r)
        self.assertNotIn((1, 3, 0), m.r)
        self.assertNotIn((1, 3, 3, 0), m.r)
        with self.assertRaises(KeyError):
            m.r[0]
Exemplo n.º 4
0
 def test_solve_linear_GDP_unbounded(self):
     m = ConcreteModel()
     m.GDPopt_utils = Block()
     m.x = Var(bounds=(-1, 10))
     m.y = Var(bounds=(2, 3))
     m.z = Var()
     m.d = Disjunction(expr=[[m.x + m.y >= 5], [m.x - m.y <= 3]])
     m.o = Objective(expr=m.z)
     m.GDPopt_utils.variable_list = [m.x, m.y, m.z]
     m.GDPopt_utils.disjunct_list = [
         m.d._autodisjuncts[0], m.d._autodisjuncts[1]
     ]
     output = StringIO()
     with LoggingIntercept(output, 'pyomo.contrib.gdpopt', logging.WARNING):
         solver_data = GDPoptSolveData()
         solver_data.timing = Container()
         with time_code(solver_data.timing, 'main', is_main_timer=True):
             solve_linear_GDP(
                 m, solver_data,
                 GDPoptSolver.CONFIG(dict(mip_solver=mip_solver)))
         self.assertIn(
             "Linear GDP was unbounded. Resolving with arbitrary bound values",
             output.getvalue().strip())
Exemplo n.º 5
0
    def get_costing(self,
                    module=costing,
                    Mat_factor="stain_steel",
                    mover_type="compressor",
                    compressor_type="centrifugal",
                    driver_mover_type="electrical_motor",
                    pump_type="centrifugal",
                    pump_type_factor='1.4',
                    pump_motor_type_factor='open',
                    year=None):
        if not hasattr(self.flowsheet(), "costing"):
            self.flowsheet().get_costing(year=year)

        self.costing = Block()
        module.pressure_changer_costing(
            self.costing,
            Mat_factor=Mat_factor,
            mover_type=mover_type,
            compressor_type=compressor_type,
            driver_mover_type=driver_mover_type,
            pump_type=pump_type,
            pump_type_factor=pump_type_factor,
            pump_motor_type_factor=pump_motor_type_factor)
Exemplo n.º 6
0
def get_model():
    # Borrowed this test model from the trust region tests
    m = ConcreteModel()
    m.z = Var(range(3), domain=Reals, initialize=2.)
    m.x = Var(range(4), initialize=2.)
    m.x[1] = 1.0
    m.x[2] = 0.0
    m.x[3] = None

    m.b1 = Block()
    m.b1.e1 = Expression(expr=m.x[0] + m.x[1])
    m.b1.e2 = Expression(expr=m.x[0] / m.x[2])
    m.b1.e3 = Expression(expr=m.x[3] * m.x[1])
    m.b1.e4 = Expression(expr=log(m.x[2]))
    m.b1.e5 = Expression(expr=log(m.x[2] - 2))

    def blackbox(a, b):
        return sin(a - b)

    m.bb = ExternalFunction(blackbox)

    m.obj = Objective(
        expr=(m.z[0]-1.0)**2 + (m.z[0]-m.z[1])**2 + (m.z[2]-1.0)**2 \
            + (m.x[0]-1.0)**4 + (m.x[1]-1.0)**6 # + m.bb(m.x[0],m.x[1])
        )
    m.c1 = Constraint(expr=m.x[0] * m.z[0]**2 + m.bb(m.x[0], m.x[1]) == 2 *
                      sqrt(2.0))
    m.c2 = Constraint(expr=m.z[2]**4 * m.z[1]**2 + m.z[1] == 8 + sqrt(2.0))
    m.c3 = Constraint(expr=m.x[1] == 3)
    m.c4 = Constraint(expr=0 == 3 / m.x[2])
    m.c5 = Constraint(expr=0 == log(m.x[2]))
    m.c6 = Constraint(expr=0 == log(m.x[2] - 4))
    m.c7 = Constraint(expr=0 == log(m.x[3]))
    m.p1 = Param(mutable=True, initialize=1)
    m.c8 = Constraint(expr=m.x[1] <= 1 / m.p1)
    m.p1 = 0
    return m
Exemplo n.º 7
0
    def setUp(self):
        # Borrowed this test model from the trust region tests
        m = ConcreteModel(name="tm")
        m.z = Var(range(3), domain=Reals, initialize=2.)
        m.x = Var(range(2), initialize=2.)
        m.x[1] = 1.0

        m.b1 = Block()
        m.b1.e1 = Expression(expr=m.x[0] + m.x[1])

        def blackbox(a, b):
            return sin(a - b)

        self.bb = ExternalFunction(blackbox)

        m.obj = Objective(
            expr=(m.z[0]-1.0)**2 + (m.z[0]-m.z[1])**2 + (m.z[2]-1.0)**2 \
                + (m.x[0]-1.0)**4 + (m.x[1]-1.0)**6 # + m.bb(m.x[0],m.x[1])
            )
        m.c1 = Constraint(expr=m.x[0] * m.z[0]**2 +
                          self.bb(m.x[0], m.x[1]) == 2 * sqrt(2.0))
        m.c2 = Constraint(expr=m.z[2]**4 * m.z[1]**2 + m.z[1] == 8 + sqrt(2.0))

        self.m = m.clone()
Exemplo n.º 8
0
    def test_ctype_detection(self):
        m = ConcreteModel()
        m.js = Set(initialize=[1, (2, 3)], dimen=None)
        m.b = Block([1, 2])
        m.b[1].x = Var(m.js)
        m.b[1].y = Var()
        m.b[1].z = Var([1, 2])
        m.b[2].x = Param(initialize=0)
        m.b[2].y = Var()
        m.b[2].z = Var([1, 2])

        m.x = Reference(m.b[:].x[...])
        self.assertIs(type(m.x), IndexedComponent)

        m.y = Reference(m.b[:].y[...])
        self.assertIs(type(m.y), IndexedVar)
        self.assertIs(m.y.ctype, Var)
        m.y1 = Reference(m.b[:].y[...], ctype=None)
        self.assertIs(type(m.y1), IndexedComponent)
        self.assertIs(m.y1.ctype, IndexedComponent)

        m.z = Reference(m.b[:].z)
        self.assertIs(type(m.z), IndexedComponent)
        self.assertIs(m.z.ctype, IndexedComponent)
Exemplo n.º 9
0
 def test_stats3(self):
     model = ConcreteModel()
     model.x = Var([1,2])
     def obj_rule(model, i):
         return sum_product(model.x)
     model.obj = Objective([1,2], rule=obj_rule)
     def c_rule(model, i):
         expr = 0
         for j in [1,2]:
             expr += j*model.x[j]
         return expr == 0
     model.c = Constraint([1,2], rule=c_rule)
     #
     model.B = Block()
     model.B.x = Var([1,2])
     model.B.o = ObjectiveList()
     model.B.o.add(model.B.x[1])
     model.B.o.add(model.B.x[2])
     model.B.c = ConstraintList()
     model.B.c.add(model.x[1] == 0)
     model.B.c.add(model.x[2] == 0)
     self.assertEqual(model.nvariables(), 4)
     self.assertEqual(model.nobjectives(), 4)
     self.assertEqual(model.nconstraints(), 4)
Exemplo n.º 10
0
    def extensive_recycle_model(self):
        def build_in_out(b):
            b.flow_in = Var(m.comps)
            b.mass_in = Var()
            b.temperature_in = Var()
            b.pressure_in = Var()

            b.expr_var_idx_in = Var(m.comps)

            @b.Expression(m.comps)
            def expr_idx_in(b, i):
                return -b.expr_var_idx_in[i]

            b.expr_var_in = Var()
            b.expr_in = -b.expr_var_in

            b.flow_out = Var(m.comps)
            b.mass_out = Var()
            b.temperature_out = Var()
            b.pressure_out = Var()

            b.expr_var_idx_out = Var(m.comps)

            @b.Expression(m.comps)
            def expr_idx_out(b, i):
                return -b.expr_var_idx_out[i]

            b.expr_var_out = Var()
            b.expr_out = -b.expr_var_out

            b.inlet = Port(rule=inlet)
            b.outlet = Port(rule=outlet)

            b.initialize = MethodType(initialize, b)

        def inlet(b):
            return dict(flow=(b.flow_in, Port.Extensive),
                        mass=(b.mass_in, Port.Extensive),
                        temperature=b.temperature_in,
                        pressure=b.pressure_in,
                        expr_idx=(b.expr_idx_in, Port.Extensive),
                        expr=(b.expr_in, Port.Extensive))

        def outlet(b):
            return dict(flow=(b.flow_out, Port.Extensive),
                        mass=(b.mass_out, Port.Extensive),
                        temperature=b.temperature_out,
                        pressure=b.pressure_out,
                        expr_idx=(b.expr_idx_out, Port.Extensive),
                        expr=(b.expr_out, Port.Extensive))

        def initialize(self):
            for i in self.flow_out:
                self.flow_out[i].value = value(self.flow_in[i])
            self.mass_out.value = value(self.mass_in)
            for i in self.expr_var_idx_out:
                self.expr_var_idx_out[i].value = value(self.expr_var_idx_in[i])
            self.expr_var_out.value = value(self.expr_var_in)
            self.temperature_out.value = value(self.temperature_in)
            self.pressure_out.value = value(self.pressure_in)

        def nop(self):
            pass

        m = ConcreteModel()
        m.comps = Set(initialize=["A", "B", "C"])

        # Feed
        m.feed = Block()

        m.feed.flow_out = Var(m.comps)
        m.feed.mass_out = Var()
        m.feed.temperature_out = Var()
        m.feed.pressure_out = Var()

        m.feed.expr_var_idx_out = Var(m.comps)

        @m.feed.Expression(m.comps)
        def expr_idx_out(b, i):
            return -b.expr_var_idx_out[i]

        m.feed.expr_var_out = Var()
        m.feed.expr_out = -m.feed.expr_var_out

        m.feed.outlet = Port(rule=outlet)

        m.feed.initialize = MethodType(nop, m.feed)

        # Mixer
        m.mixer = Block()
        build_in_out(m.mixer)

        # Pass through
        m.unit = Block()
        build_in_out(m.unit)

        # Splitter
        m.splitter = Block()
        build_in_out(m.splitter)

        # Prod
        m.prod = Block()

        m.prod.flow_in = Var(m.comps)
        m.prod.mass_in = Var()
        m.prod.temperature_in = Var()
        m.prod.pressure_in = Var()

        m.prod.actual_var_idx_in = Var(m.comps)
        m.prod.actual_var_in = Var()

        @m.prod.Port()
        def inlet(b):
            return dict(flow=(b.flow_in, Port.Extensive),
                        mass=(b.mass_in, Port.Extensive),
                        temperature=b.temperature_in,
                        pressure=b.pressure_in,
                        expr_idx=(b.actual_var_idx_in, Port.Extensive),
                        expr=(b.actual_var_in, Port.Extensive))

        m.prod.initialize = MethodType(nop, m.prod)

        # Arcs
        @m.Arc(directed=True)
        def stream_feed_to_mixer(m):
            return (m.feed.outlet, m.mixer.inlet)

        @m.Arc(directed=True)
        def stream_mixer_to_unit(m):
            return (m.mixer.outlet, m.unit.inlet)

        @m.Arc(directed=True)
        def stream_unit_to_splitter(m):
            return (m.unit.outlet, m.splitter.inlet)

        @m.Arc(directed=True)
        def stream_splitter_to_mixer(m):
            return (m.splitter.outlet, m.mixer.inlet)

        @m.Arc(directed=True)
        def stream_splitter_to_prod(m):
            return (m.splitter.outlet, m.prod.inlet)

        # Split Fraction
        rec = 0.1
        prod = 1 - rec
        m.splitter.outlet.set_split_fraction(m.stream_splitter_to_mixer, rec)
        m.splitter.outlet.set_split_fraction(m.stream_splitter_to_prod, prod)

        # Expand Arcs
        TransformationFactory("network.expand_arcs").apply_to(m)

        # Fix Feed
        m.feed.flow_out['A'].fix(100)
        m.feed.flow_out['B'].fix(200)
        m.feed.flow_out['C'].fix(300)
        m.feed.mass_out.fix(400)
        m.feed.expr_var_idx_out['A'].fix(10)
        m.feed.expr_var_idx_out['B'].fix(20)
        m.feed.expr_var_idx_out['C'].fix(30)
        m.feed.expr_var_out.fix(40)
        m.feed.temperature_out.fix(450)
        m.feed.pressure_out.fix(128)

        return m
Exemplo n.º 11
0
def test_power_law_equil_no_order():
    m = ConcreteModel()

    # # Add a test thermo package for validation
    m.pparams = PhysicalParameterTestBlock()

    # Add a solid phase for testing
    m.pparams.sol = SolidPhase()

    m.thermo = m.pparams.build_state_block([1])

    # Create a dummy reaction parameter block
    m.rparams = GenericReactionParameterBlock(
        default={
            "property_package": m.pparams,
            "base_units": {
                "time": pyunits.s,
                "mass": pyunits.kg,
                "amount": pyunits.mol,
                "length": pyunits.m,
                "temperature": pyunits.K
            },
            "equilibrium_reactions": {
                "r1": {
                    "stoichiometry": {
                        ("p1", "c1"): -1,
                        ("p1", "c2"): 2,
                        ("sol", "c1"): -3,
                        ("sol", "c2"): 4
                    },
                    "equilibrium_form": power_law_equil,
                    "concentration_form": ConcentrationForm.moleFraction
                }
            }
        })

    # Create a dummy state block
    m.rxn = Block([1])
    add_object_reference(m.rxn[1], "phase_component_set",
                         m.pparams._phase_component_set)
    add_object_reference(m.rxn[1], "params", m.rparams)
    add_object_reference(m.rxn[1], "state_ref", m.thermo[1])

    m.rxn[1].k_eq = Var(["r1"], initialize=1)

    power_law_equil.build_parameters(
        m.rparams.reaction_r1, m.rparams.config.equilibrium_reactions["r1"])

    # Check parameter construction
    assert isinstance(m.rparams.reaction_r1.reaction_order, Var)
    assert len(m.rparams.reaction_r1.reaction_order) == 6

    assert m.rparams.reaction_r1.reaction_order["p1", "c1"].value == -1
    assert m.rparams.reaction_r1.reaction_order["p1", "c2"].value == 2
    assert m.rparams.reaction_r1.reaction_order["p2", "c1"].value == 0
    assert m.rparams.reaction_r1.reaction_order["p2", "c2"].value == 0
    # Solids should have zero order, as they are excluded
    assert m.rparams.reaction_r1.reaction_order["sol", "c1"].value == 0
    assert m.rparams.reaction_r1.reaction_order["sol", "c2"].value == 0

    # Check reaction form
    rform = power_law_equil.return_expression(m.rxn[1], m.rparams.reaction_r1,
                                              "r1", 300)

    assert str(rform) == str(m.rxn[1].k_eq["r1"] == (
        m.thermo[1].mole_frac_phase_comp[
            "p1", "c1"]**m.rparams.reaction_r1.reaction_order["p1", "c1"] *
        m.thermo[1].mole_frac_phase_comp[
            "p1", "c2"]**m.rparams.reaction_r1.reaction_order["p1", "c2"]))
Exemplo n.º 12
0
def test_power_law_rate_with_order():
    m = ConcreteModel()

    # # Add a test thermo package for validation
    m.pparams = PhysicalParameterTestBlock()
    m.thermo = m.pparams.build_state_block([1])

    m.rparams = GenericReactionParameterBlock(
        default={
            "property_package": m.pparams,
            "base_units": {
                "time": pyunits.s,
                "mass": pyunits.kg,
                "amount": pyunits.mol,
                "length": pyunits.m,
                "temperature": pyunits.K
            },
            "rate_reactions": {
                "r1": {
                    "stoichiometry": {
                        ("p1", "c1"): -1,
                        ("p1", "c2"): 2
                    },
                    "rate_form": power_law_rate,
                    "concentration_form": ConcentrationForm.moleFraction,
                    "parameter_data": {
                        "reaction_order": {
                            ("p1", "c1"): 1,
                            ("p1", "c2"): 2,
                            ("p2", "c1"): 3,
                            ("p2", "c2"): 4
                        }
                    }
                }
            }
        })

    # Create a dummy state block
    m.rxn = Block([1])
    add_object_reference(m.rxn[1], "phase_component_set",
                         m.pparams._phase_component_set)
    add_object_reference(m.rxn[1], "params", m.rparams)
    add_object_reference(m.rxn[1], "state_ref", m.thermo[1])

    m.rxn[1].k_rxn = Var(["r1"], initialize=1)

    power_law_rate.build_parameters(m.rparams.reaction_r1,
                                    m.rparams.config.rate_reactions["r1"])

    # Check parameter construction
    assert isinstance(m.rparams.reaction_r1.reaction_order, Var)
    assert len(m.rparams.reaction_r1.reaction_order) == 4
    assert m.rparams.reaction_r1.reaction_order["p1", "c1"].value == 1
    assert m.rparams.reaction_r1.reaction_order["p1", "c2"].value == 2
    assert m.rparams.reaction_r1.reaction_order["p2", "c1"].value == 3
    assert m.rparams.reaction_r1.reaction_order["p2", "c2"].value == 4

    # Check reaction form
    rform = power_law_rate.return_expression(m.rxn[1], m.rparams.reaction_r1,
                                             "r1", 300)

    assert str(rform) == str(
        m.rxn[1].k_rxn["r1"] *
        (m.thermo[1].mole_frac_phase_comp["p1", "c1"]**
         m.rparams.reaction_r1.reaction_order["p1", "c1"] *
         m.thermo[1].mole_frac_phase_comp["p1", "c2"]**
         m.rparams.reaction_r1.reaction_order["p1", "c2"] *
         m.thermo[1].mole_frac_phase_comp["p2", "c1"]**
         m.rparams.reaction_r1.reaction_order["p2", "c1"] *
         m.thermo[1].mole_frac_phase_comp["p2", "c2"]**
         m.rparams.reaction_r1.reaction_order["p2", "c2"]))
Exemplo n.º 13
0
 def construct(self, data=None):
     Block.construct(self, data)
Exemplo n.º 14
0
 class Foo(Block().__class__):
     def __init__(self, *args, **kwds):
         kwds.setdefault('ctype', Foo)
         super(Foo, self).__init__(*args, **kwds)
Exemplo n.º 15
0
def build_multiperiod_design(m,
                             flowsheet,
                             initialization=None,
                             unfix_dof=None,
                             flowsheet_options={},
                             initialization_options={},
                             unfix_dof_options={},
                             solver=None,
                             verbose=True,
                             stochastic=False,
                             multiyear=False,
                             multiple_days=False,
                             **kwargs):
    """
    This function constructs multiperiod optimization model
    """

    # Create timer object
    timer = TicTocTimer()
    timer.tic("Processing input information.")

    if stochastic:
        # If True, set_scenarios must either be passed as an argument,
        # or it should defined as an attribute of the model
        if "set_scenarios" in kwargs:
            set_scenarios = kwargs["set_scenarios"]
        elif hasattr(m, "set_scenarios"):
            set_scenarios = m.set_scenarios
        else:
            raise Exception(f"stochastic option is set to True, but set_scenarios has "
                            f"not been defined. Either pass set_scenarios as an argument "
                            f"or define it as an attribute of the model.")

    if multiyear:
        # If True, set_years must either be passed as an argument,
        # or it should defined as an attribute of the model
        if "set_years" in kwargs:
            set_years = kwargs["set_years"]
        elif hasattr(m, "set_years"):
            set_years = m.set_years
        else:
            raise Exception(f"multiyear option is set to True, but set_years has "
                            f"not been defined. Either pass set_years as an argument "
                            f"or define it as an attribute of the model.")

    if multiple_days:
        # If True, set_days must either be passed as an argument,
        # or it should defined as an attribute of the model
        if "set_days" in kwargs:
            set_days = kwargs["set_days"]
        elif hasattr(m, "set_days"):
            set_days = m.set_days
        else:
            raise Exception(f"multiple_days option is set to True, but set_days has "
                            f"not been defined. Either pass set_days as an argument "
                            f"or define it as an attribute of the model.")

    # Set of time periods
    if "set_time" in kwargs:
        set_time = kwargs["set_time"]
    elif hasattr(m, "set_time"):
        set_time = m.set_time
    else:
        raise Exception(f"set_time is a required option. Either pass set_time as "
                        f"an argument or define it as an attribute of the model.")

    # Set solver object
    if solver is None:
        solver = get_solver()

    # Construct the set of time periods
    if multiyear and multiple_days:
        set_period = [(t, d, y) for y in set_years for d in set_days for t in set_time]
    elif multiple_days:
        set_period = [(t, d) for d in set_days for t in set_time]
    else:
        set_period = [t for t in set_time]

    """
    Period rule
    """
    timer.toc("Beginning the formulation of the multiperiod problem.")

    def _period_model_rule(options, verbose_flag):

        def _period_model(blk):
            if verbose_flag:
                print("Constructing flowsheet model for ", blk.name)

            flowsheet(blk, options=options)

        return _period_model

    def _build_scenario_model(blk):
        blk.period = Block(set_period, rule=_period_model_rule(flowsheet_options, verbose))

        return blk

    # Construct the multiperiod model
    if stochastic:
        m.scenario = Block(set_scenarios, rule=_build_scenario_model)
    else:
        _build_scenario_model(m)

    timer.toc("Completed the formulation of the multiperiod problem")
    """
    Initialization routine
    """
    if initialization is None:
        print("*** WARNING *** Initialization function is not provided. "
              "Returning the multiperiod model without initialization.")
        return

    b = ConcreteModel()
    flowsheet(b, options=flowsheet_options)
    initialization(b, options=initialization_options)

    result = solver.solve(b)

    try:
        assert check_optimal_termination(result)
    except AssertionError:
        print(f"Flowsheet did not converge to optimality "
              f"after fixing the degrees of freedom.")
        raise

    # Save the solution in json file
    to_json(b, fname="temp_initialized_model.json")
    timer.toc("Created an instance of the flowsheet and initialized it.")

    # Initialize the multiperiod optimization model
    if stochastic:
        for s in set_scenarios:
            for p in set_period:
                from_json(m.scenario[s].period[p], fname="temp_initialized_model.json")

    else:
        for p in set_period:
            from_json(m.period[p], fname="temp_initialized_model.json")

    timer.toc("Initialized the entire multiperiod optimization model.")

    """
    Unfix the degrees of freedom in each period model for optimization model
    """
    if unfix_dof is None:
        print("*** WARNING *** unfix_dof function is not provided. "
              "Returning the model without unfixing degrees of freedom")
        return

    if stochastic:
        for s in set_scenarios:
            for p in set_period:
                unfix_dof(m.scenario[s].period[p], options=unfix_dof_options)

    else:
        for p in set_period:
            unfix_dof(m.period[p], options=unfix_dof_options)

    timer.toc("Unfixed the degrees of freedom from each period model.")
Exemplo n.º 16
0
def test_propagate_state():
    m = ConcreteModel()

    def block_rule(b):
        b.s = Set(initialize=[1, 2])
        b.v1 = Var()
        b.v2 = Var(b.s)
        b.e1 = Expression(expr=b.v1)

        @b.Expression(b.s)
        def e2(blk, i):
            return b.v2[i] * b.v1

        b.p1 = Param(mutable=True, initialize=5)
        b.p2 = Param(b.s, mutable=True, initialize=6)

        b.port1 = Port()
        b.port1.add(b.v1, "V1")
        b.port1.add(b.v2, "V2")

        b.port2 = Port()
        b.port2.add(b.v1, "V1")
        b.port2.add(b.e2, "V2")

        b.port3 = Port()
        b.port3.add(b.e1, "V1")
        b.port3.add(b.v2, "V2")

        b.port4 = Port()
        b.port4.add(b.p1, "V1")
        b.port4.add(b.v2, "V2")

        b.port5 = Port()
        b.port5.add(b.v1, "V1")
        b.port5.add(b.p2, "V2")

        b.port6 = Port()
        b.port6.add(b.v1, "V1")
        b.port6.add(b.v1, "V2")
        return

    m.b1 = Block(rule=block_rule)
    m.b2 = Block(rule=block_rule)

    m.s1 = Arc(source=m.b1.port1, destination=m.b2.port1)
    m.s2 = Arc(source=m.b1.port1, destination=m.b2.port2)
    m.s3 = Arc(source=m.b1.port1, destination=m.b2.port3)
    m.s4 = Arc(source=m.b1.port1, destination=m.b2.port4)
    m.s5 = Arc(source=m.b1.port1, destination=m.b2.port5)
    m.s6 = Arc(source=m.b1.port2, destination=m.b2.port1)
    m.s7 = Arc(source=m.b1.port3, destination=m.b2.port1)
    m.s8 = Arc(source=m.b1.port4, destination=m.b2.port1)
    m.s9 = Arc(source=m.b1.port5, destination=m.b2.port1)
    m.s10 = Arc(source=m.b1.port6, destination=m.b2.port1)
    m.s11 = Arc(source=m.b2.port6, destination=m.b1.port1)

    # Set values on first block
    m.b1.v1.value = 10
    m.b1.v2[1].value = 20
    m.b1.v2[2].value = 30

    # Make sure vars in block 2 haven't been changed accidentally
    assert m.b2.v1.value is None
    assert m.b2.v2[1].value is None
    assert m.b2.v2[2].value is None

    propagate_state(m.s1)

    # Check that values were propagated correctly
    assert m.b2.v1.value == m.b1.v1.value
    assert m.b2.v2[1].value == m.b1.v2[1].value
    assert m.b2.v2[2].value == m.b1.v2[2].value

    assert m.b1.v1.fixed is False
    assert m.b1.v2[1].fixed is False
    assert m.b1.v2[2].fixed is False
    assert m.b2.v1.fixed is False
    assert m.b2.v2[1].fixed is False
    assert m.b2.v2[2].fixed is False

    with pytest.raises(TypeError):
        propagate_state(m.s2)

    with pytest.raises(TypeError):
        propagate_state(m.s3)

    with pytest.raises(TypeError):
        propagate_state(m.s4)

    with pytest.raises(TypeError):
        propagate_state(m.s5)

    propagate_state(m.s6)
    assert value(m.b1.v1) == value(m.b2.v1)
    assert value(m.b1.e2[1]) == value(m.b2.v2[1])
    assert value(m.b1.e2[2]) == value(m.b2.v2[2])

    propagate_state(m.s7)
    assert value(m.b1.e1) == value(m.b2.v1)
    assert value(m.b1.v2[1]) == value(m.b2.v2[1])
    assert value(m.b1.v2[2]) == value(m.b2.v2[2])

    propagate_state(m.s8)
    assert value(m.b1.p1) == value(m.b2.v1)
    assert value(m.b1.v2[1]) == value(m.b2.v2[1])
    assert value(m.b1.v2[2]) == value(m.b2.v2[2])

    propagate_state(m.s9)
    assert value(m.b1.v1) == value(m.b2.v1)
    assert value(m.b1.p2[1]) == value(m.b2.v2[1])
    assert value(m.b1.p2[2]) == value(m.b2.v2[2])

    with pytest.raises(KeyError):
        propagate_state(m.s10)

    with pytest.raises(KeyError):
        propagate_state(m.s11)
Exemplo n.º 17
0
    def get_costing(self, module=costing):
        if not hasattr(self.flowsheet(), 'costing'):
            self.flowsheet().get_costing()
        self.costing = Block()

        module.hx_costing(self.costing)
Exemplo n.º 18
0
    def test_solve_with_pickle_then_clone(self):
        # This tests github issue Pyomo-#65
        model = ConcreteModel()
        model.A = RangeSet(1, 4)
        model.b = Block()
        model.b.x = Var(model.A, bounds=(-1, 1))
        model.b.obj = Objective(expr=sum_product(model.b.x))
        model.c = Constraint(expr=model.b.x[1] >= 0)
        opt = SolverFactory('glpk')
        self.assertEqual(len(model.solutions), 0)
        results = opt.solve(model, symbolic_solver_labels=True)
        self.assertEqual(len(model.solutions), 1)
        #
        self.assertEqual(model.solutions[0].gap, 0.0)
        #self.assertEqual(model.solutions[0].status, SolutionStatus.feasible)
        self.assertEqual(model.solutions[0].message, None)
        #
        buf = pickle.dumps(model)
        tmodel = pickle.loads(buf)
        self.assertEqual(len(tmodel.solutions), 1)
        self.assertEqual(tmodel.solutions[0].gap, 0.0)
        #self.assertEqual(tmodel.solutions[0].status, SolutionStatus.feasible)
        self.assertEqual(tmodel.solutions[0].message, None)
        self.assertIn(id(tmodel.b.obj),
                      tmodel.solutions[0]._entry['objective'])
        self.assertIs(
            tmodel.b.obj,
            tmodel.solutions[0]._entry['objective'][id(tmodel.b.obj)][0]())

        inst = tmodel.clone()

        # make sure the clone has all the attributes
        self.assertTrue(hasattr(inst, 'A'))
        self.assertTrue(hasattr(inst, 'b'))
        self.assertTrue(hasattr(inst.b, 'x'))
        self.assertTrue(hasattr(inst.b, 'obj'))
        self.assertTrue(hasattr(inst, 'c'))
        # and that they were all copied
        self.assertIsNot(inst.A, tmodel.A)
        self.assertIsNot(inst.b, tmodel.b)
        self.assertIsNot(inst.b.x, tmodel.b.x)
        self.assertIsNot(inst.b.obj, tmodel.b.obj)
        self.assertIsNot(inst.c, tmodel.c)

        # Make sure the solution is on the new model
        self.assertTrue(hasattr(inst, 'solutions'))
        self.assertEqual(len(inst.solutions), 1)
        self.assertEqual(inst.solutions[0].gap, 0.0)
        #self.assertEqual(inst.solutions[0].status, SolutionStatus.feasible)
        self.assertEqual(inst.solutions[0].message, None)

        # Spot-check some components and make sure all the weakrefs in
        # the ModelSOlution got updated
        self.assertIn(id(inst.b.obj), inst.solutions[0]._entry['objective'])
        _obj = inst.solutions[0]._entry['objective'][id(inst.b.obj)]
        self.assertIs(_obj[0](), inst.b.obj)

        for v in [1, 2, 3, 4]:
            self.assertIn(id(inst.b.x[v]),
                          inst.solutions[0]._entry['variable'])
            _v = inst.solutions[0]._entry['variable'][id(inst.b.x[v])]
            self.assertIs(_v[0](), inst.b.x[v])
Exemplo n.º 19
0
 def test_inactive_target(self):
     m = ConcreteModel()
     m.b = Block()
     m.b.deactivate()
     TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
Exemplo n.º 20
0
    def initialize(self,
                   state_args_feed=None,
                   state_args_liq=None,
                   state_args_vap=None,
                   solver=None,
                   optarg=None,
                   outlvl=idaeslog.NOTSET):

        init_log = idaeslog.getInitLogger(self.name, outlvl, tag="unit")
        solve_log = idaeslog.getSolveLogger(self.name, outlvl, tag="unit")

        init_log.info("Begin initialization.")

        solverobj = get_solver(solver, optarg)

        feed_flags = self.feed_tray.initialize(solver=solver,
                                               optarg=optarg,
                                               outlvl=outlvl)

        self.propagate_stream_state(source=self.feed_tray.vap_out,
                                    destination=self.condenser.inlet)

        self.condenser.initialize(solver=solver, optarg=optarg, outlvl=outlvl)

        self.propagate_stream_state(source=self.feed_tray.liq_out,
                                    destination=self.reboiler.inlet)

        self.reboiler.initialize(solver=solver, optarg=optarg, outlvl=outlvl)

        # initialize the rectification section
        for i in self._rectification_index:
            self.propagate_stream_state(
                source=self.condenser.reflux,
                destination=self.rectification_section[i].liq_in)
            self.propagate_stream_state(
                source=self.feed_tray.vap_out,
                destination=self.rectification_section[i].vap_in)
            if i == 1:
                rect_liq_flags = self.rectification_section[i]. \
                    initialize(hold_state_liq=True,
                               hold_state_vap=False,
                               solver=solver,
                               optarg=optarg,
                               outlvl=outlvl)
            elif i == len(self._rectification_index):
                rect_vap_flags = \
                    self.rectification_section[i]. \
                    initialize(hold_state_liq=False,
                               hold_state_vap=True,
                               solver=solver,
                               optarg=optarg,
                               outlvl=outlvl)
            else:
                self.rectification_section[i].initialize(solver=solver,
                                                         optarg=optarg,
                                                         outlvl=outlvl)

        # initialize the stripping section
        for i in self._stripping_index:
            self.propagate_stream_state(
                source=self.feed_tray.liq_out,
                destination=self.stripping_section[i].liq_in)
            self.propagate_stream_state(
                source=self.reboiler.vapor_reboil,
                destination=self.stripping_section[i].vap_in)
            if i == self.config.feed_tray_location + 1:
                strip_liq_flags = self.stripping_section[i]. \
                    initialize(hold_state_liq=True,
                               hold_state_vap=False,
                               solver=solver,
                               optarg=optarg,
                               outlvl=outlvl)
            elif i == self.config.number_of_trays:
                strip_vap_flags = self.stripping_section[i]. \
                    initialize(hold_state_liq=False,
                               hold_state_vap=True,
                               solver=solver,
                               optarg=optarg,
                               outlvl=outlvl)
            else:
                self.stripping_section[i].initialize(solver=None,
                                                     optarg=optarg,
                                                     outlvl=outlvl)

        # For initialization purposes and to enable solving individual sections
        # creating a temp block. Note that this temp block is a reference to
        # the rectification, stripping, and feed sections. Also, expanded arcs
        # are added to the temp block as the initialization solve proceeds.
        self._temp_block = Block()

        self._temp_block.rectification = Block()

        # adding reference to the rectification section and the expanded
        # vapor and liquid arcs
        self._temp_block.rectification.trays = Reference(
            self.rectification_section)
        self._temp_block.rectification.expanded_liq_stream = Reference(
            self.rectification_liq_stream[:].expanded_block)
        self._temp_block.rectification.expanded_vap_stream = Reference(
            self.rectification_vap_stream[:].expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solverobj.solve(self._temp_block.rectification, tee=slc.tee)
        init_log.info("Rectification section initialization status {}.".format(
            idaeslog.condition(res)))

        self._temp_block.stripping = Block()

        # adding reference to the stripping section and the expanded
        # vapor and liquid arcs
        self._temp_block.stripping.trays = Reference(self.stripping_section)
        self._temp_block.stripping.expanded_liq_stream = Reference(
            self.stripping_liq_stream[:].expanded_block)
        self._temp_block.stripping.expanded_vap_stream = Reference(
            self.stripping_vap_stream[:].expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solverobj.solve(self._temp_block.stripping, tee=slc.tee)
        init_log.info("Stripping section initialization status {}.".format(
            idaeslog.condition(res)))

        # releasing the fixed inlets for the vap in to the rectification
        # to enable connection with the feed tray vap out
        self.rectification_section[len(self._rectification_index)]. \
            properties_in_vap. \
            release_state(flags=rect_vap_flags, outlvl=outlvl)

        # releasing the fixed inlets for the liq in to the stripping
        # to enable connection with the feed tray liq out
        self.stripping_section[self.config.feed_tray_location + 1]. \
            properties_in_liq. \
            release_state(flags=strip_liq_flags, outlvl=outlvl)

        # Adding the feed tray to temp block solve
        self._temp_block.feed_tray = Reference(self.feed_tray)
        self._temp_block.expanded_feed_liq_stream_in = Reference(
            self.feed_liq_in.expanded_block)
        self._temp_block.expanded_feed_liq_stream_out = Reference(
            self.feed_liq_out.expanded_block)
        self._temp_block.expanded_feed_vap_stream_in = Reference(
            self.feed_vap_in.expanded_block)
        self._temp_block.expanded_feed_vap_stream_out = Reference(
            self.feed_vap_out.expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solverobj.solve(self._temp_block, tee=slc.tee)
        init_log.info("Column section initialization status {}.".format(
            idaeslog.condition(res)))

        self.rectification_section[1]. \
            properties_in_liq. \
            release_state(flags=rect_liq_flags, outlvl=outlvl)

        # Adding the condenser to the temp block solve
        self._temp_block.condenser = Reference(self.condenser)
        self._temp_block.expanded_condenser_vap_in = Reference(
            self.condenser_vap_in.expanded_block)
        self._temp_block.expanded_condenser_reflux_out = Reference(
            self.condenser_reflux_out.expanded_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solverobj.solve(self._temp_block, tee=slc.tee)
        init_log.info(
            "Column section + Condenser initialization status {}.".format(
                idaeslog.condition(res)))

        self.stripping_section[self.config.number_of_trays]. \
            properties_in_vap. \
            release_state(flags=strip_vap_flags, outlvl=outlvl)

        # Delete the _temp_block as next solve is solving the entire column.
        # If we add the reboiler to the temp block, it will be similar to
        # solving the original block. This ensures that if
        # initialize is triggered twice, there is no implicit replacing
        # component error.
        self.del_component(self._temp_block)

        with idaeslog.solver_log(solve_log, idaeslog.DEBUG) as slc:
            res = solverobj.solve(self, tee=slc.tee)
        init_log.info(
            "Column section + Condenser + Reboiler initialization status {}.".
            format(idaeslog.condition(res)))

        # release feed tray state once initialization is complete
        self.feed_tray.properties_in_feed.\
            release_state(flags=feed_flags, outlvl=outlvl)
Exemplo n.º 21
0
 def b_rule(b, c):
     b.bb = Block(m.time, rule=bb_rule)
Exemplo n.º 22
0
def build(m, section='desalination', pretrt_type='NF', **kwargs):
    if section == 'desalination':
        m.fs.desal_saturation = Block()
        m.fs.desal_saturation.properties = m.fs.prop_eNRTL.build_state_block([0], default={})
        sb_eNRTL = m.fs.desal_saturation.properties[0]
    elif section == 'pretreatment':
        m.fs.pretrt_saturation = Block()
        m.fs.pretrt_saturation.properties = m.fs.prop_eNRTL.build_state_block([0], default={})
        sb_eNRTL = m.fs.pretrt_saturation.properties[0]
    else:
        raise ValueError('{section} is not an expected section for building the saturation index'
                         ''.format(section=section))

    # populate initial values
    populate_eNRTL_state_vars(sb_eNRTL, base='FpcTP')

    # ksp = 3.9e-9  # Gibbs energy gives 3.9e-8, but this fits expectations better
    ksp = 3.2e-9  # This fits expectations even better

    # constraints
    if section == 'desalination':
        sb_dilute = m.fs.tb_pretrt_to_desal.properties_in[0]
        if kwargs['is_twostage']:
            sb_perm = m.fs.mixer_permeate.mixed_state[0]
            sb_conc = m.fs.RO2.feed_side.properties[0, 1]
            sb_conc_inter = m.fs.RO2.feed_side.properties_interface[0, 1]
        else:
            sb_perm = m.fs.RO.mixed_permeate[0]
            sb_conc = m.fs.RO.feed_side.properties[0, 1]
            sb_conc_inter = m.fs.RO.feed_side.properties_interface[0, 1]

        m.fs.desal_saturation.cp_modulus = Expression(
            expr=sb_conc_inter.conc_mass_phase_comp['Liq', 'TDS'] / sb_conc.conc_mass_phase_comp['Liq', 'TDS'])

        # constraints
        m.fs.desal_saturation.eq_temperature = Constraint(
            expr=sb_eNRTL.temperature == sb_conc.temperature)
        m.fs.desal_saturation.eq_pressure = Constraint(
            expr=sb_eNRTL.pressure == sb_conc.pressure)

        if pretrt_type == 'NF':
            # assumes pretreatment uses the ion property basis
            comp_match_dict = {'Na_+': 'Na',
                               'Ca_2+': 'Ca',
                               'Mg_2+': 'Mg',
                               'SO4_2-': 'SO4',
                               'Cl_-': 'Cl',
                               'H2O': 'H2O'}

            @m.fs.desal_saturation.Constraint(comp_match_dict.keys())
            def eq_flow_mol_balance(b, j):
                if j in ['Cl_-', 'Na_+']:
                    bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]]
                                 - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol))
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j]
                            == bulk_flow * m.fs.desal_saturation.cp_modulus)
                elif j in ['Ca_2+', 'Mg_2+', 'SO4_2-']:
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j]
                            == sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]]
                            * m.fs.desal_saturation.cp_modulus)
                elif j == 'H2O':
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j] ==
                            sb_conc.flow_mol_phase_comp['Liq', 'H2O'])
        elif pretrt_type == 'softening':
            # assumes pretreatment uses the softening property basis
            comp_match_dict = {'Na_+': 'NaCl',
                               'Ca_2+': 'Ca(HCO3)2',
                               'Mg_2+': 'Mg(HCO3)2',
                               'SO4_2-': 'SO4_2-',
                               'Cl_-': 'Cl_-',
                               'H2O': 'H2O'}

            @m.fs.desal_saturation.Constraint(comp_match_dict.keys())
            def eq_flow_mol_balance(b, j):
                if j == 'Na_+':
                    bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', 'NaCl']
                                 - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol))
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j]
                            == bulk_flow * m.fs.desal_saturation.cp_modulus)
                if j in 'Cl_-':
                    bulk_flow = (sb_dilute.flow_mol_phase_comp['Liq', 'Cl_-']
                            + sb_dilute.flow_mol_phase_comp['Liq', 'NaCl']
                            - sb_perm.flow_mass_phase_comp['Liq', 'TDS'] / (58.44e-3 * pyunits.kg / pyunits.mol))
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j]
                            == bulk_flow * m.fs.desal_saturation.cp_modulus)
                elif j in ['Ca_2+', 'Mg_2+', 'SO4_2-']:
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j]
                            == sb_dilute.flow_mol_phase_comp['Liq', comp_match_dict[j]]
                            * m.fs.desal_saturation.cp_modulus)
                elif j == 'H2O':
                    return (sb_eNRTL.flow_mol_phase_comp['Liq', j] ==
                            sb_conc.flow_mol_phase_comp['Liq', 'H2O'])

        m.fs.desal_saturation.saturation_index = Var(
            initialize=0.5,
            bounds=(1e-8, 10),
            units=pyunits.dimensionless,
            doc="Gypsum saturation index")

        m.fs.desal_saturation.eq_saturation_index = Constraint(
            expr=m.fs.desal_saturation.saturation_index
                 == sb_eNRTL.act_phase_comp["Liq", "Ca_2+"]
                 * sb_eNRTL.act_phase_comp["Liq", "SO4_2-"]
                 * sb_eNRTL.act_phase_comp["Liq", "H2O"] ** 2
                 / ksp)

    elif section == 'pretreatment':
        comp_match_dict = {'Na_+': 'Na',
                           'Ca_2+': 'Ca',
                           'Mg_2+': 'Mg',
                           'SO4_2-': 'SO4',
                           'Cl_-': 'Cl',
                           'H2O': 'H2O'}

        sb_conc = m.fs.NF.feed_side.properties_out[0]

        m.fs.pretrt_saturation.eq_temperature = Constraint(
            expr=sb_eNRTL.temperature == sb_conc.temperature)
        m.fs.pretrt_saturation.eq_pressure = Constraint(
            expr=sb_eNRTL.pressure == sb_conc.pressure)

        @m.fs.pretrt_saturation.Constraint(comp_match_dict.keys())
        def eq_flow_mol_balance(b, j):
                return (sb_eNRTL.flow_mol_phase_comp['Liq', j] ==
                        sb_conc.flow_mol_phase_comp['Liq', comp_match_dict[j]])

        m.fs.pretrt_saturation.saturation_index = Var(
            initialize=0.5,
            bounds=(1e-8, 1e6),
            units=pyunits.dimensionless,
            doc="Gypsum saturation index")

        m.fs.pretrt_saturation.eq_saturation_index = Constraint(
            expr=m.fs.pretrt_saturation.saturation_index
                 == sb_eNRTL.act_phase_comp["Liq", "Ca_2+"]
                 * sb_eNRTL.act_phase_comp["Liq", "SO4_2-"]
                 * sb_eNRTL.act_phase_comp["Liq", "H2O"] ** 2
                 / ksp)
Exemplo n.º 23
0
 def test_indexed_target(self):
     m = ConcreteModel()
     m.s = RangeSet(2)
     m.b = Block(m.s)
     m.b[1].bb = Block()
     TransformationFactory('gdp.fix_disjuncts').apply_to(m.b)
Exemplo n.º 24
0
    def simple_recycle_model(self):
        m = ConcreteModel()
        m.comps = Set(initialize=["A", "B", "C"])

        # Feed
        m.feed = Block()

        m.feed.flow_out = Var(m.comps)
        m.feed.temperature_out = Var()
        m.feed.pressure_out = Var()

        m.feed.expr_var_idx_out = Var(m.comps)

        @m.feed.Expression(m.comps)
        def expr_idx_out(b, i):
            return -b.expr_var_idx_out[i]

        m.feed.expr_var_out = Var()
        m.feed.expr_out = -m.feed.expr_var_out

        @m.feed.Port()
        def outlet(b):
            return dict(flow=b.flow_out,
                        temperature=b.temperature_out,
                        pressure=b.pressure_out,
                        expr_idx=b.expr_idx_out,
                        expr=b.expr_out)

        def initialize_feed(self):
            pass

        m.feed.initialize = MethodType(initialize_feed, m.feed)

        # Mixer
        m.mixer = Block()

        m.mixer.flow_in_side_1 = Var(m.comps)
        m.mixer.temperature_in_side_1 = Var()
        m.mixer.pressure_in_side_1 = Var()

        m.mixer.expr_var_idx_in_side_1 = Var(m.comps)

        @m.mixer.Expression(m.comps)
        def expr_idx_in_side_1(b, i):
            return -b.expr_var_idx_in_side_1[i]

        m.mixer.expr_var_in_side_1 = Var()
        m.mixer.expr_in_side_1 = -m.mixer.expr_var_in_side_1

        m.mixer.flow_in_side_2 = Var(m.comps)
        m.mixer.temperature_in_side_2 = Var()
        m.mixer.pressure_in_side_2 = Var()

        m.mixer.expr_var_idx_in_side_2 = Var(m.comps)

        @m.mixer.Expression(m.comps)
        def expr_idx_in_side_2(b, i):
            return -b.expr_var_idx_in_side_2[i]

        m.mixer.expr_var_in_side_2 = Var()
        m.mixer.expr_in_side_2 = -m.mixer.expr_var_in_side_2

        m.mixer.flow_out = Var(m.comps)
        m.mixer.temperature_out = Var()
        m.mixer.pressure_out = Var()

        m.mixer.expr_var_idx_out = Var(m.comps)

        @m.mixer.Expression(m.comps)
        def expr_idx_out(b, i):
            return -b.expr_var_idx_out[i]

        m.mixer.expr_var_out = Var()
        m.mixer.expr_out = -m.mixer.expr_var_out

        @m.mixer.Port()
        def inlet_side_1(b):
            return dict(flow=b.flow_in_side_1,
                        temperature=b.temperature_in_side_1,
                        pressure=b.pressure_in_side_1,
                        expr_idx=b.expr_idx_in_side_1,
                        expr=b.expr_in_side_1)

        @m.mixer.Port()
        def inlet_side_2(b):
            return dict(flow=b.flow_in_side_2,
                        temperature=b.temperature_in_side_2,
                        pressure=b.pressure_in_side_2,
                        expr_idx=b.expr_idx_in_side_2,
                        expr=b.expr_in_side_2)

        @m.mixer.Port()
        def outlet(b):
            return dict(flow=b.flow_out,
                        temperature=b.temperature_out,
                        pressure=b.pressure_out,
                        expr_idx=b.expr_idx_out,
                        expr=b.expr_out)

        def initialize_mixer(self):
            for i in self.flow_out:
                self.flow_out[i].value = \
                    value(self.flow_in_side_1[i] + self.flow_in_side_2[i])
            for i in self.expr_var_idx_out:
                self.expr_var_idx_out[i].value = \
                    value(self.expr_var_idx_in_side_1[i] +
                        self.expr_var_idx_in_side_2[i])
            self.expr_var_out.value = \
                value(self.expr_var_in_side_1 + self.expr_var_in_side_2)
            assert self.temperature_in_side_1 == self.temperature_in_side_2
            self.temperature_out.value = value(self.temperature_in_side_1)
            assert self.pressure_in_side_1 == self.pressure_in_side_2
            self.pressure_out.value = value(self.pressure_in_side_1)

        m.mixer.initialize = MethodType(initialize_mixer, m.mixer)

        # Pass through
        m.unit = Block()

        m.unit.flow_in = Var(m.comps)
        m.unit.temperature_in = Var()
        m.unit.pressure_in = Var()

        m.unit.expr_var_idx_in = Var(m.comps)

        @m.unit.Expression(m.comps)
        def expr_idx_in(b, i):
            return -b.expr_var_idx_in[i]

        m.unit.expr_var_in = Var()
        m.unit.expr_in = -m.unit.expr_var_in

        m.unit.flow_out = Var(m.comps)
        m.unit.temperature_out = Var()
        m.unit.pressure_out = Var()

        m.unit.expr_var_idx_out = Var(m.comps)

        @m.unit.Expression(m.comps)
        def expr_idx_out(b, i):
            return -b.expr_var_idx_out[i]

        m.unit.expr_var_out = Var()
        m.unit.expr_out = -m.unit.expr_var_out

        @m.unit.Port()
        def inlet(b):
            return dict(flow=b.flow_in,
                        temperature=b.temperature_in,
                        pressure=b.pressure_in,
                        expr_idx=b.expr_idx_in,
                        expr=b.expr_in)

        @m.unit.Port()
        def outlet(b):
            return dict(flow=b.flow_out,
                        temperature=b.temperature_out,
                        pressure=b.pressure_out,
                        expr_idx=b.expr_idx_out,
                        expr=b.expr_out)

        def initialize_unit(self):
            for i in self.flow_out:
                self.flow_out[i].value = value(self.flow_in[i])
            for i in self.expr_var_idx_out:
                self.expr_var_idx_out[i].value = value(self.expr_var_idx_in[i])
            self.expr_var_out.value = value(self.expr_var_in)
            self.temperature_out.value = value(self.temperature_in)
            self.pressure_out.value = value(self.pressure_in)

        m.unit.initialize = MethodType(initialize_unit, m.unit)

        # Splitter
        m.splitter = Block()

        @m.splitter.Block(m.comps)
        def flow_in(b, i):
            b.flow = Var()

        m.splitter.temperature_in = Var()
        m.splitter.pressure_in = Var()

        m.splitter.expr_var_idx_in = Var(m.comps)

        @m.splitter.Expression(m.comps)
        def expr_idx_in(b, i):
            return -b.expr_var_idx_in[i]

        m.splitter.expr_var_in = Var()
        m.splitter.expr_in = -m.splitter.expr_var_in

        m.splitter.flow_out_side_1 = Var(m.comps)
        m.splitter.temperature_out_side_1 = Var()
        m.splitter.pressure_out_side_1 = Var()

        m.splitter.expr_var_idx_out_side_1 = Var(m.comps)

        @m.splitter.Expression(m.comps)
        def expr_idx_out_side_1(b, i):
            return -b.expr_var_idx_out_side_1[i]

        m.splitter.expr_var_out_side_1 = Var()
        m.splitter.expr_out_side_1 = -m.splitter.expr_var_out_side_1

        m.splitter.flow_out_side_2 = Var(m.comps)
        m.splitter.temperature_out_side_2 = Var()
        m.splitter.pressure_out_side_2 = Var()

        m.splitter.expr_var_idx_out_side_2 = Var(m.comps)

        @m.splitter.Expression(m.comps)
        def expr_idx_out_side_2(b, i):
            return -b.expr_var_idx_out_side_2[i]

        m.splitter.expr_var_out_side_2 = Var()
        m.splitter.expr_out_side_2 = -m.splitter.expr_var_out_side_2

        @m.splitter.Port()
        def inlet(b):
            return dict(flow=Reference(b.flow_in[:].flow),
                        temperature=b.temperature_in,
                        pressure=b.pressure_in,
                        expr_idx=b.expr_idx_in,
                        expr=b.expr_in)

        @m.splitter.Port()
        def outlet_side_1(b):
            return dict(flow=b.flow_out_side_1,
                        temperature=b.temperature_out_side_1,
                        pressure=b.pressure_out_side_1,
                        expr_idx=b.expr_idx_out_side_1,
                        expr=b.expr_out_side_1)

        @m.splitter.Port()
        def outlet_side_2(b):
            return dict(flow=b.flow_out_side_2,
                        temperature=b.temperature_out_side_2,
                        pressure=b.pressure_out_side_2,
                        expr_idx=b.expr_idx_out_side_2,
                        expr=b.expr_out_side_2)

        def initialize_splitter(self):
            recycle = 0.1
            prod = 1 - recycle
            for i in self.flow_in:
                self.flow_out_side_1[i].value \
                    = prod * value(self.flow_in[i].flow)
                self.flow_out_side_2[i].value \
                    = recycle * value(self.flow_in[i].flow)
            for i in self.expr_var_idx_in:
                self.expr_var_idx_out_side_1[i].value = \
                    prod * value(self.expr_var_idx_in[i])
                self.expr_var_idx_out_side_2[i].value = \
                    recycle * value(self.expr_var_idx_in[i])
            self.expr_var_out_side_1.value = prod * value(self.expr_var_in)
            self.expr_var_out_side_2.value = recycle * value(self.expr_var_in)
            self.temperature_out_side_1.value = value(self.temperature_in)
            self.temperature_out_side_2.value = value(self.temperature_in)
            self.pressure_out_side_1.value = value(self.pressure_in)
            self.pressure_out_side_2.value = value(self.pressure_in)

        m.splitter.initialize = MethodType(initialize_splitter, m.splitter)

        # Prod
        m.prod = Block()

        m.prod.flow_in = Var(m.comps)
        m.prod.temperature_in = Var()
        m.prod.pressure_in = Var()

        m.prod.actual_var_idx_in = Var(m.comps)
        m.prod.actual_var_in = Var()

        @m.prod.Port()
        def inlet(b):
            return dict(flow=b.flow_in,
                        temperature=b.temperature_in,
                        pressure=b.pressure_in,
                        expr_idx=b.actual_var_idx_in,
                        expr=b.actual_var_in)

        def initialize_prod(self):
            pass

        m.prod.initialize = MethodType(initialize_prod, m.prod)

        # Arcs
        @m.Arc(directed=True)
        def stream_feed_to_mixer(m):
            return (m.feed.outlet, m.mixer.inlet_side_1)

        @m.Arc(directed=True)
        def stream_mixer_to_unit(m):
            return (m.mixer.outlet, m.unit.inlet)

        @m.Arc(directed=True)
        def stream_unit_to_splitter(m):
            return (m.unit.outlet, m.splitter.inlet)

        @m.Arc(directed=True)
        def stream_splitter_to_mixer(m):
            return (m.splitter.outlet_side_2, m.mixer.inlet_side_2)

        @m.Arc(directed=True)
        def stream_splitter_to_prod(m):
            return (m.splitter.outlet_side_1, m.prod.inlet)

        # Expand Arcs
        TransformationFactory("network.expand_arcs").apply_to(m)

        # Fix Feed
        m.feed.flow_out['A'].fix(100)
        m.feed.flow_out['B'].fix(200)
        m.feed.flow_out['C'].fix(300)
        m.feed.expr_var_idx_out['A'].fix(10)
        m.feed.expr_var_idx_out['B'].fix(20)
        m.feed.expr_var_idx_out['C'].fix(30)
        m.feed.expr_var_out.fix(40)
        m.feed.temperature_out.fix(450)
        m.feed.pressure_out.fix(128)

        return m
Exemplo n.º 25
0
 def test_trans_block_name_collision(self):
     m = self.makeModel()
     m._core_add_slack_variables = Block()
     TransformationFactory('core.add_slack_variables').apply_to(m)
     xblock = m.component("_core_add_slack_variables_4")
     self.assertIsInstance(xblock, Block)
Exemplo n.º 26
0
    def build(self):
        '''
        Callable method for Block construction.
        '''
        # Call super.build() to initialize Block
        # In this case we are replicating the super.build to get around a
        # chicken-and-egg problem
        # The super.build tries to validate units, but they have not been set
        # and cannot be set until the config block is created by super.build
        super(ReactionParameterBlock, self).build()

        # Validate and set base units of measurement
        self.get_metadata().add_default_units(self.config.base_units)
        units_meta = self.get_metadata().default_units

        for key, unit in self.config.base_units.items():
            if key in [
                    'time', 'length', 'mass', 'amount', 'temperature',
                    "current", "luminous intensity"
            ]:
                if not isinstance(unit, _PyomoUnit):
                    raise ConfigurationError(
                        "{} recieved unexpected units for quantity {}: {}. "
                        "Units must be instances of a Pyomo unit object.".
                        format(self.name, key, unit))
            else:
                raise ConfigurationError(
                    "{} defined units for an unexpected quantity {}. "
                    "Generic reaction packages only support units for the 7 "
                    "base SI quantities.".format(self.name, key))

        # Check that main 5 base units are assigned
        for k in ['time', 'length', 'mass', 'amount', 'temperature']:
            if not isinstance(units_meta[k], _PyomoUnit):
                raise ConfigurationError(
                    "{} units for quantity {} were not assigned. "
                    "Please make sure to provide units for all base units "
                    "when configuring the reaction package.".format(
                        self.name, k))

        # TODO: Need way to tie reaction package to a specfic property package
        self._validate_property_parameter_units()
        self._validate_property_parameter_properties()

        # Call configure method to set construction arguments
        self.configure()

        # Build core components
        self._reaction_block_class = GenericReactionBlock

        # Alias associated property package to keep line length down
        ppack = self.config.property_package

        # Construct rate reaction attributes if required
        if len(self.config.rate_reactions) > 0:
            # Construct rate reaction index
            self.rate_reaction_idx = Set(
                initialize=self.config.rate_reactions.keys())

            # Construct rate reaction stoichiometry dict
            self.rate_reaction_stoichiometry = {}
            for r, rxn in self.config.rate_reactions.items():
                for p, j in ppack._phase_component_set:
                    self.rate_reaction_stoichiometry[(r, p, j)] = 0

                if rxn.stoichiometry is None:
                    raise ConfigurationError(
                        "{} rate reaction {} was not provided with a "
                        "stoichiometry configuration argument.".format(
                            self.name, r))
                else:
                    for k, v in rxn.stoichiometry.items():
                        if k[0] not in ppack.phase_list:
                            raise ConfigurationError(
                                "{} stoichiometry for rate reaction {} "
                                "included unrecognised phase {}.".format(
                                    self.name, r, k[0]))
                        if k[1] not in ppack.component_list:
                            raise ConfigurationError(
                                "{} stoichiometry for rate reaction {} "
                                "included unrecognised component {}.".format(
                                    self.name, r, k[1]))
                        self.rate_reaction_stoichiometry[(r, k[0], k[1])] = v

                # Check that a method was provided for the rate form
                if rxn.rate_form is None:
                    raise ConfigurationError(
                        "{} rate reaction {} was not provided with a "
                        "rate_form configuration argument.".format(
                            self.name, r))

        # Construct equilibrium reaction attributes if required
        if len(self.config.equilibrium_reactions) > 0:
            # Construct rate reaction index
            self.equilibrium_reaction_idx = Set(
                initialize=self.config.equilibrium_reactions.keys())

            # Construct equilibrium reaction stoichiometry dict
            self.equilibrium_reaction_stoichiometry = {}
            for r, rxn in self.config.equilibrium_reactions.items():
                for p, j in ppack._phase_component_set:
                    self.equilibrium_reaction_stoichiometry[(r, p, j)] = 0

                if rxn.stoichiometry is None:
                    raise ConfigurationError(
                        "{} equilibrium reaction {} was not provided with a "
                        "stoichiometry configuration argument.".format(
                            self.name, r))
                else:
                    for k, v in rxn.stoichiometry.items():
                        if k[0] not in ppack.phase_list:
                            raise ConfigurationError(
                                "{} stoichiometry for equilibrium reaction {} "
                                "included unrecognised phase {}.".format(
                                    self.name, r, k[0]))
                        if k[1] not in ppack.component_list:
                            raise ConfigurationError(
                                "{} stoichiometry for equilibrium reaction {} "
                                "included unrecognised component {}.".format(
                                    self.name, r, k[1]))
                        self.equilibrium_reaction_stoichiometry[(r, k[0],
                                                                 k[1])] = v

                # Check that a method was provided for the equilibrium form
                if rxn.equilibrium_form is None:
                    raise ConfigurationError(
                        "{} equilibrium reaction {} was not provided with a "
                        "equilibrium_form configuration argument.".format(
                            self.name, r))

        # Add a master reaction index which includes both types of reactions
        if (len(self.config.rate_reactions) > 0
                and len(self.config.equilibrium_reactions) > 0):
            self.reaction_idx = Set(
                initialize=(self.rate_reaction_idx
                            | self.equilibrium_reaction_idx))
        elif len(self.config.rate_reactions) > 0:
            self.reaction_idx = Set(initialize=self.rate_reaction_idx)
        elif len(self.config.equilibrium_reactions) > 0:
            self.reaction_idx = Set(initialize=self.equilibrium_reaction_idx)
        else:
            raise BurntToast("{} Generic property package failed to construct "
                             "master reaction Set. This should not happen. "
                             "Please contact the IDAES developers with this "
                             "bug".format(self.name))

        # Construct blocks to contain parameters for each reaction
        for r in self.reaction_idx:
            self.add_component("reaction_" + str(r), Block())

        # Build parameters
        if len(self.config.rate_reactions) > 0:
            for r in self.rate_reaction_idx:
                rblock = getattr(self, "reaction_" + r)
                r_config = self.config.rate_reactions[r]

                order_init = {}
                for p, j in ppack._phase_component_set:
                    if "reaction_order" in r_config.parameter_data:
                        try:
                            order_init[p, j] = r_config.parameter_data[
                                "reaction_order"][p, j]
                        except KeyError:
                            order_init[p, j] = 0
                    else:
                        # Assume elementary reaction and use stoichiometry
                        try:
                            if r_config.stoichiometry[p, j] < 0:
                                # These are reactants, but order is -ve stoic
                                order_init[p,
                                           j] = -r_config.stoichiometry[p, j]
                            else:
                                # Anything else is a product, not be included
                                order_init[p, j] = 0
                        except KeyError:
                            order_init[p, j] = 0

                rblock.reaction_order = Var(ppack._phase_component_set,
                                            initialize=order_init,
                                            doc="Reaction order",
                                            units=None)

                for val in self.config.rate_reactions[r].values():
                    try:
                        val.build_parameters(rblock,
                                             self.config.rate_reactions[r])
                    except AttributeError:
                        pass

        if len(self.config.equilibrium_reactions) > 0:
            for r in self.equilibrium_reaction_idx:
                rblock = getattr(self, "reaction_" + r)
                r_config = self.config.equilibrium_reactions[r]

                order_init = {}
                for p, j in ppack._phase_component_set:
                    if "reaction_order" in r_config.parameter_data:
                        try:
                            order_init[p, j] = r_config.parameter_data[
                                "reaction_order"][p, j]
                        except KeyError:
                            order_init[p, j] = 0
                    else:
                        # Assume elementary reaction and use stoichiometry
                        try:
                            # Here we use the stoic. coeff. directly
                            # However, solids should be excluded as they
                            # normally do not appear in the equilibrium
                            # relationship
                            pobj = ppack.get_phase(p)
                            if not pobj.is_solid_phase():
                                order_init[p, j] = r_config.stoichiometry[p, j]
                            else:
                                order_init[p, j] = 0
                        except KeyError:
                            order_init[p, j] = 0

                rblock.reaction_order = Var(ppack._phase_component_set,
                                            initialize=order_init,
                                            doc="Reaction order",
                                            units=None)

                for val in self.config.equilibrium_reactions[r].values():
                    try:
                        val.build_parameters(
                            rblock, self.config.equilibrium_reactions[r])
                    except AttributeError:
                        pass

        # As a safety check, make sure all Vars in reaction blocks are fixed
        for v in self.component_objects(Var, descend_into=True):
            for i in v:
                if v[i].value is None:
                    raise ConfigurationError(
                        "{} parameter {} was not assigned"
                        " a value. Please check your configuration "
                        "arguments.".format(self.name, v.local_name))
                v[i].fix()
Exemplo n.º 27
0
    def build(self):
        super().build()

        if self.config.property_package_feed is None:
            raise ConfigurationError(
                "Users must provide a feed property package to the evaporator unit model"
            )
        if self.config.property_package_vapor is None:
            raise ConfigurationError(
                "Users must provide a vapor property package to the evaporator unit model"
            )

        # this creates blank scaling factors, which are populated later
        self.scaling_factor = Suffix(direction=Suffix.EXPORT)

        # Next, get the base units of measurement from the property definition
        units_meta_feed = (
            self.config.property_package_feed.get_metadata().get_derived_units)

        # Add shared unit model variables
        self.U = Var(
            initialize=1e3,
            bounds=(10, 1e4),
            units=pyunits.J * pyunits.s**-1 * pyunits.m**-2 * pyunits.K**-1,
        )

        self.area = Var(initialize=1e2, bounds=(1e-1, 1e4), units=pyunits.m**2)

        self.delta_temperature_in = Var(initialize=1e1,
                                        bounds=(1e-8, 1e3),
                                        units=pyunits.K)

        self.delta_temperature_out = Var(initialize=1e1,
                                         bounds=(1e-8, 1e3),
                                         units=pyunits.K)

        self.lmtd = Var(initialize=1e1, bounds=(1e-8, 1e3), units=pyunits.K)

        # Add feed_side block
        self.feed_side = Block()

        # Add unit variables to feed
        self.feed_side.heat_transfer = Var(initialize=1e4,
                                           bounds=(1, 1e10),
                                           units=pyunits.J * pyunits.s**-1)

        # Add feed_side state blocks
        # Feed state block
        tmp_dict = dict(**self.config.property_package_args_feed)
        tmp_dict["has_phase_equilibrium"] = False
        tmp_dict["parameters"] = self.config.property_package_feed
        tmp_dict["defined_state"] = True  # feed inlet defined
        self.feed_side.properties_feed = (
            self.config.property_package_feed.state_block_class(
                self.flowsheet().config.time,
                doc="Material properties of feed inlet",
                default=tmp_dict,
            ))

        # Brine state block
        tmp_dict["defined_state"] = False  # brine outlet not yet defined
        self.feed_side.properties_brine = (
            self.config.property_package_feed.state_block_class(
                self.flowsheet().config.time,
                doc="Material properties of brine outlet",
                default=tmp_dict,
            ))

        # Vapor state block
        tmp_dict = dict(**self.config.property_package_args_vapor)
        tmp_dict["has_phase_equilibrium"] = False
        tmp_dict["parameters"] = self.config.property_package_vapor
        tmp_dict["defined_state"] = False  # vapor outlet not yet defined
        self.feed_side.properties_vapor = (
            self.config.property_package_vapor.state_block_class(
                self.flowsheet().config.time,
                doc="Material properties of vapor outlet",
                default=tmp_dict,
            ))

        # Add condenser
        self.condenser = Condenser(
            default={"property_package": self.config.property_package_vapor})

        # Add ports - oftentimes users interact with these rather than the state blocks
        self.add_port(name="inlet_feed", block=self.feed_side.properties_feed)
        self.add_port(name="outlet_brine",
                      block=self.feed_side.properties_brine)
        self.add_port(name="outlet_vapor",
                      block=self.feed_side.properties_vapor)
        self.add_port(name="inlet_condenser",
                      block=self.condenser.control_volume.properties_in)
        self.add_port(name="outlet_condenser",
                      block=self.condenser.control_volume.properties_out)

        ### FEED SIDE CONSTRAINTS ###
        # Mass balance
        @self.feed_side.Constraint(
            self.flowsheet().time,
            self.config.property_package_feed.component_list,
            doc="Mass balance",
        )
        def eq_mass_balance(b, t, j):
            lb = b.properties_vapor[t].flow_mass_phase_comp["Liq", "H2O"].lb
            b.properties_vapor[t].flow_mass_phase_comp["Liq", "H2O"].fix(lb)
            if j == "H2O":
                return (
                    b.properties_feed[t].flow_mass_phase_comp["Liq", "H2O"] ==
                    b.properties_brine[t].flow_mass_phase_comp["Liq", "H2O"] +
                    b.properties_vapor[t].flow_mass_phase_comp["Vap", "H2O"])
            else:
                return (b.properties_feed[t].flow_mass_phase_comp["Liq", j] ==
                        b.properties_brine[t].flow_mass_phase_comp["Liq", j])

        # Energy balance
        @self.feed_side.Constraint(self.flowsheet().time, doc="Energy balance")
        def eq_energy_balance(b, t):
            return (b.heat_transfer + b.properties_feed[t].enth_flow ==
                    b.properties_brine[t].enth_flow +
                    b.properties_vapor[t].enth_flow_phase["Vap"])

        # Brine pressure
        @self.feed_side.Constraint(self.flowsheet().time, doc="Brine pressure")
        def eq_brine_pressure(b, t):
            return b.properties_brine[t].pressure == b.properties_brine[
                t].pressure_sat

        # Vapor pressure
        @self.feed_side.Constraint(self.flowsheet().time, doc="Vapor pressure")
        def eq_vapor_pressure(b, t):
            return b.properties_vapor[t].pressure == b.properties_brine[
                t].pressure

        # Vapor temperature
        @self.feed_side.Constraint(self.flowsheet().time,
                                   doc="Vapor temperature")
        def eq_vapor_temperature(b, t):
            return (b.properties_vapor[t].temperature ==
                    b.properties_brine[t].temperature)
            # return b.properties_vapor[t].temperature == 0.5*(b.properties_out[t].temperature + b.properties_in[t].temperature)

        ### EVAPORATOR CONSTRAINTS ###
        # Temperature difference in
        @self.Constraint(self.flowsheet().time,
                         doc="Temperature difference in")
        def eq_delta_temperature_in(b, t):
            return (b.delta_temperature_in ==
                    b.condenser.control_volume.properties_in[t].temperature -
                    b.feed_side.properties_brine[t].temperature)

        # Temperature difference out
        @self.Constraint(self.flowsheet().time,
                         doc="Temperature difference out")
        def eq_delta_temperature_out(b, t):
            return (b.delta_temperature_out ==
                    b.condenser.control_volume.properties_out[t].temperature -
                    b.feed_side.properties_brine[t].temperature)

        # log mean temperature
        @self.Constraint(self.flowsheet().time,
                         doc="Log mean temperature difference")
        def eq_lmtd(b, t):
            dT_in = b.delta_temperature_in
            dT_out = b.delta_temperature_out
            temp_units = pyunits.get_units(dT_in)
            dT_avg = (dT_in + dT_out) / 2
            # external function that ruturns the real root, for the cuberoot of negitive
            # numbers, so it will return without error for positive and negitive dT.
            b.cbrt = ExternalFunction(library=functions_lib(),
                                      function="cbrt",
                                      arg_units=[temp_units**3])
            return b.lmtd == b.cbrt((dT_in * dT_out * dT_avg)) * temp_units

        # Heat transfer between feed side and condenser
        @self.Constraint(self.flowsheet().time, doc="Heat transfer balance")
        def eq_heat_balance(b, t):
            return b.feed_side.heat_transfer == -b.condenser.control_volume.heat[
                t]

        # Evaporator heat transfer
        @self.Constraint(self.flowsheet().time, doc="Evaporator heat transfer")
        def eq_evaporator_heat(b, t):
            return b.feed_side.heat_transfer == b.U * b.area * b.lmtd
Exemplo n.º 28
0
    def get_costing(self, module=costing, year=None, **kwargs):
        if not hasattr(self.flowsheet(), "costing"):
            self.flowsheet().get_costing(year=year)

        self.costing = Block()
        module.hx_costing(self.costing, **kwargs)
Exemplo n.º 29
0
    def build(self):
        '''
        Callable method for Block construction.
        '''
        # Call super.build() to initialize Block
        # In this case we are replicating the super.build to get around a
        # chicken-and-egg problem
        # The super.build tries to validate units, but they have not been set
        # and cannot be set until the config block is created by super.build
        super(ReactionParameterBlock, self).build()
        self.default_scaling_factor = {}

        # Set base units of measurement
        self.get_metadata().add_default_units(self.config.base_units)

        # TODO: Need way to tie reaction package to a specfic property package
        self._validate_property_parameter_units()
        self._validate_property_parameter_properties()

        # Call configure method to set construction arguments
        self.configure()

        # Build core components
        self._reaction_block_class = GenericReactionBlock

        # Alias associated property package to keep line length down
        ppack = self.config.property_package

        if not hasattr(ppack, "_electrolyte") or not ppack._electrolyte:
            pc_set = ppack._phase_component_set
        elif ppack.config.state_components.name == "true":
            pc_set = ppack.true_phase_component_set
        elif ppack.config.state_components.name == "apparent":
            pc_set = ppack.apparent_phase_component_set
        else:
            raise BurntToast()

        # Construct rate reaction attributes if required
        if len(self.config.rate_reactions) > 0:
            # Construct rate reaction index
            self.rate_reaction_idx = Set(
                initialize=self.config.rate_reactions.keys())

            # Construct rate reaction stoichiometry dict
            self.rate_reaction_stoichiometry = {}
            for r, rxn in self.config.rate_reactions.items():
                for p, j in pc_set:
                    self.rate_reaction_stoichiometry[(r, p, j)] = 0

                if rxn.stoichiometry is None:
                    raise ConfigurationError(
                        "{} rate reaction {} was not provided with a "
                        "stoichiometry configuration argument.".format(
                            self.name, r))
                else:
                    for k, v in rxn.stoichiometry.items():
                        if k[0] not in ppack.phase_list:
                            raise ConfigurationError(
                                "{} stoichiometry for rate reaction {} "
                                "included unrecognised phase {}.".format(
                                    self.name, r, k[0]))
                        if k[1] not in ppack.component_list:
                            raise ConfigurationError(
                                "{} stoichiometry for rate reaction {} "
                                "included unrecognised component {}.".format(
                                    self.name, r, k[1]))
                        self.rate_reaction_stoichiometry[(r, k[0], k[1])] = v

                # Check that a method was provided for the rate form
                if rxn.rate_form is None:
                    _log.debug(
                        "{} rate reaction {} was not provided with a "
                        "rate_form configuration argument. This is suitable "
                        "for processes using stoichiometric reactors, but not "
                        "for those using unit operations which rely on "
                        "reaction rate.".format(self.name, r))

        # Construct equilibrium reaction attributes if required
        if len(self.config.equilibrium_reactions) > 0:
            # Construct equilibrium reaction index
            self.equilibrium_reaction_idx = Set(
                initialize=self.config.equilibrium_reactions.keys())

            # Construct equilibrium reaction stoichiometry dict
            self.equilibrium_reaction_stoichiometry = {}
            for r, rxn in self.config.equilibrium_reactions.items():
                for p, j in pc_set:
                    self.equilibrium_reaction_stoichiometry[(r, p, j)] = 0

                if rxn.stoichiometry is None:
                    raise ConfigurationError(
                        "{} equilibrium reaction {} was not provided with a "
                        "stoichiometry configuration argument.".format(
                            self.name, r))
                else:
                    for k, v in rxn.stoichiometry.items():
                        if k[0] not in ppack.phase_list:
                            raise ConfigurationError(
                                "{} stoichiometry for equilibrium reaction {} "
                                "included unrecognised phase {}.".format(
                                    self.name, r, k[0]))
                        if k[1] not in ppack.component_list:
                            raise ConfigurationError(
                                "{} stoichiometry for equilibrium reaction {} "
                                "included unrecognised component {}.".format(
                                    self.name, r, k[1]))
                        self.equilibrium_reaction_stoichiometry[(r, k[0],
                                                                 k[1])] = v

                # Check that a method was provided for the equilibrium form
                if rxn.equilibrium_form is None:
                    raise ConfigurationError(
                        "{} equilibrium reaction {} was not provided with a "
                        "equilibrium_form configuration argument.".format(
                            self.name, r))

        # Add a master reaction index which includes both types of reactions
        if (len(self.config.rate_reactions) > 0
                and len(self.config.equilibrium_reactions) > 0):
            self.reaction_idx = Set(
                initialize=(self.rate_reaction_idx
                            | self.equilibrium_reaction_idx))
        elif len(self.config.rate_reactions) > 0:
            self.reaction_idx = Set(initialize=self.rate_reaction_idx)
        elif len(self.config.equilibrium_reactions) > 0:
            self.reaction_idx = Set(initialize=self.equilibrium_reaction_idx)
        else:
            raise BurntToast("{} Generic property package failed to construct "
                             "master reaction Set. This should not happen. "
                             "Please contact the IDAES developers with this "
                             "bug".format(self.name))

        # Construct blocks to contain parameters for each reaction
        for r in self.reaction_idx:
            self.add_component("reaction_" + str(r), Block())

        # Build parameters
        if len(self.config.rate_reactions) > 0:
            for r in self.rate_reaction_idx:
                rblock = getattr(self, "reaction_" + r)
                r_config = self.config.rate_reactions[r]

                order_init = {}
                for p, j in pc_set:
                    if "reaction_order" in r_config.parameter_data:
                        try:
                            order_init[p, j] = r_config.parameter_data[
                                "reaction_order"][p, j]
                        except KeyError:
                            order_init[p, j] = 0
                    else:
                        # Assume elementary reaction and use stoichiometry
                        try:
                            if r_config.stoichiometry[p, j] < 0:
                                # These are reactants, but order is -ve stoic
                                order_init[p,
                                           j] = -r_config.stoichiometry[p, j]
                            else:
                                # Anything else is a product, not be included
                                order_init[p, j] = 0
                        except KeyError:
                            order_init[p, j] = 0

                rblock.reaction_order = Var(pc_set,
                                            initialize=order_init,
                                            doc="Reaction order",
                                            units=None)

                for val in self.config.rate_reactions[r].values():
                    try:
                        val.build_parameters(rblock,
                                             self.config.rate_reactions[r])
                    except AttributeError:
                        pass

        if len(self.config.equilibrium_reactions) > 0:
            for r in self.equilibrium_reaction_idx:
                rblock = getattr(self, "reaction_" + r)
                r_config = self.config.equilibrium_reactions[r]

                order_init = {}
                for p, j in pc_set:
                    if "reaction_order" in r_config.parameter_data:
                        try:
                            order_init[p, j] = r_config.parameter_data[
                                "reaction_order"][p, j]
                        except KeyError:
                            order_init[p, j] = 0
                    else:
                        # Assume elementary reaction and use stoichiometry
                        try:
                            # Here we use the stoic. coeff. directly
                            # However, solids should be excluded as they
                            # normally do not appear in the equilibrium
                            # relationship
                            pobj = ppack.get_phase(p)
                            if not pobj.is_solid_phase():
                                order_init[p, j] = r_config.stoichiometry[p, j]
                            else:
                                order_init[p, j] = 0
                        except KeyError:
                            order_init[p, j] = 0

                rblock.reaction_order = Var(pc_set,
                                            initialize=order_init,
                                            doc="Reaction order",
                                            units=None)

                for val in self.config.equilibrium_reactions[r].values():
                    try:
                        val.build_parameters(
                            rblock, self.config.equilibrium_reactions[r])
                    except AttributeError:
                        pass
                    except KeyError as err:
                        # This likely arises from mismatched true and apparent
                        # species sets. Reaction packages must use the same
                        # basis as the associated thermo properties
                        # Raise an exception to inform the user
                        raise PropertyPackageError(
                            "{} KeyError encountered whilst constructing "
                            "reaction parameters. This may be due to "
                            "mismatched state_components between the "
                            "Reaction Package and the associated Physical "
                            "Property Package - Reaction Packages must use the"
                            "same basis (true or apparent species) as the "
                            "Physical Property Package.".format(self.name),
                            err)

        # As a safety check, make sure all Vars in reaction blocks are fixed
        for v in self.component_objects(Var, descend_into=True):
            for i in v:
                if v[i].value is None:
                    raise ConfigurationError(
                        "{} parameter {} was not assigned"
                        " a value. Please check your configuration "
                        "arguments.".format(self.name, v.local_name))
                v[i].fix()

        # Set default scaling factors
        if self.config.default_scaling_factors is not None:
            self.default_scaling_factor.update(
                self.config.default_scaling_factors)
        # Finally, call populate_default_scaling_factors method to fill blanks
        iscale.populate_default_scaling_factors(self)
Exemplo n.º 30
0
    def _reformulate(self, c, param, uncset, counterpart, root=False):
        """
        Reformulate an uncertain constraint or objective

            c: Constraint or Objective
            param: UncParam
            uncset: UncSet
            counterpart: Block

        """

        # Check constraint/objective
        repn = self.generate_repn_param(c)
        assert repn.is_linear(), (
                "Constraint {} should be linear in "
                "unc. parameters".format(c.name))

        # Generate robust counterpart
        det = quicksum(x[0]*x[1].nominal for x in zip(repn.linear_coefs,
                                                      repn.linear_vars))
        det += repn.constant
        param_var_dict = {id(param): var
                          for param, var
                          in zip(repn.linear_vars, repn.linear_coefs)}
        # padding = sqrt( var^T * cov^-1 * var )
        padding = quicksum(param_var_dict[id(param[ind_i])]
                           * uncset.cov[i][j]
                           * param_var_dict[id(param[ind_j])]
                           for i, ind_i in enumerate(param)
                           for j, ind_j in enumerate(param))
        if c.ctype is Constraint:
            # For upper bound: det + padding <= b
            if c.has_ub():
                counterpart.upper = Block()
                if root:
                    expr = det + sqrt(padding) <= c.upper
                    robust = Constraint(expr=expr)
                else:
                    counterpart.upper.padding = Var(bounds=(0, float('inf')))
                    pvar = counterpart.upper.padding
                    robust = Constraint(expr=det + pvar <= c.upper())
                    deterministic = Constraint(expr=padding <= pvar**2)
                    counterpart.upper.det = deterministic
                counterpart.upper.rob = robust
            # For lower bound: det - padding >= b
            if c.has_lb():
                counterpart.lower = Block()
                if root:
                    expr = det - sqrt(padding) >= c.lower
                    robust = Constraint(expr=expr)
                else:
                    counterpart.lower.padding = Var(bounds=(0, float('inf')))
                    pvar = counterpart.lower.padding
                    robust = Constraint(expr=c.lower() <= det - pvar)
                    deterministic = Constraint(expr=padding <= pvar**2)
                    counterpart.lower.det = deterministic
                counterpart.lower.rob = robust
        else:
            # For minimization: min det + padding
            # For maximization: max det - padding
            sense = c.sense
            if root:
                expr = det + c.sense*sqrt(padding)
                robust = Objective(expr=expr, sense=sense)
            else:
                counterpart.padding = Var(bounds=(0, float('inf')))
                pvar = counterpart.padding
                robust = Objective(expr=det + sense*pvar, sense=sense)
                deterministic = Constraint(expr=padding <= pvar**2)
                counterpart.det = deterministic
            counterpart.rob = robust