示例#1
0
def solve_consistent_initial_conditions(model,
                                        time,
                                        solver,
                                        tee=False,
                                        allow_skip=True,
                                        suppress_warnings=False):
    """
    Solves a model with all Constraints and Blocks deactivated except
    at the initial value of the Set time. Reactivates Constraints and
    Blocks that got deactivated.

    Args:
        model: Model that will be solved
        time: Set whose initial conditions will remain active for solve
        solver: Something that implements a solve method that accepts
                a model and tee keyword as arguments
        tee: tee argument that will be sent to solver's solve method
        allow_skip: If True, KeyErrors due to Constraint.Skip being
                    used will be ignored
        suppress_warnings: If True, warnings due to ignored
                           KeyErrors will be suppressed

    Returns:
        The object returned by the solver's solve method
    """
    # Need to deactivate discretization equations, wrt time, at t == 0
    # This is challenging as the only way (to my knowledge) to do this
    # is to identify_variables in the expression, find the (assume only one?)
    # DerivativeVar, and access its get_continuousset_list
    # I would like a get_continuousset_list for discretization equations.
    # Possibly as a ComponentMap, possibly as an attribute of some new
    # DiscEquation subclass of Constraint
    # Until I have this, this function will only work for backward
    # discretization schemes

    # Also, would like to be able to check for zero degrees of freedom here

    scheme = time.get_discretization_info()['scheme']
    if scheme != 'LAGRANGE-RADAU' and scheme != 'BACKWARD Difference':
        raise NotImplementedError('%s discretization scheme is not supported' %
                                  scheme)

    t0 = time.first()
    timelist = list(time)[1:]
    deactivated_dict = deactivate_model_at(model,
                                           time,
                                           timelist,
                                           allow_skip=allow_skip,
                                           suppress_warnings=suppress_warnings)

    result = solver.solve(model, tee=tee)

    for t in timelist:
        for comp in deactivated_dict[t]:
            comp.activate()

    return result
示例#2
0
    def test_deactivate_model_at(self):
        m = make_model()

        deactivate_model_at(m, m.time, m.time[2])
        self.assertTrue(m.fs.con1[m.time[1]].active)
        self.assertFalse(m.fs.con1[m.time[2]].active)
        self.assertTrue(m.fs.con2[m.space[1]].active)
        self.assertFalse(m.fs.b1.con[m.time[2], m.space[1]].active)
        self.assertFalse(m.fs.b2[m.time[2], m.space.last()].active)
        self.assertTrue(m.fs.b2[m.time[2],
                                m.space.last()].b3['a'].con['e'].active)

        deactivate_model_at(m, m.time, [m.time[1], m.time[3]])
        # disc equations at time.first()
        self.assertFalse(m.fs.con1[m.time[1]].active)
        self.assertFalse(m.fs.con1[m.time[3]].active)
        self.assertFalse(m.fs.b1.con[m.time[1], m.space[1]].active)
        self.assertFalse(m.fs.b1.con[m.time[3], m.space[1]].active)

        with self.assertRaises(KeyError):
            deactivate_model_at(m,
                                m.time,
                                m.time[1],
                                allow_skip=False,
                                suppress_warnings=True)
示例#3
0
    def solve_setpoint(self, solver, **kwargs):
        """ This method performs a "real time optimization-type"
        solve on the model, using only the variables and constraints
        at the first point in time. The purpose is to calculate a
        (possibly steady state) setpoint.

        Parameters:
            solver: A Pyomo solver object that will be used to solve
                    the model with only variables and constraints at t0
                    active.
            require_steady: Whether derivatives should be fixed to zero
                            for the solve. Default is `True`.

        """
        require_steady = kwargs.pop('require_steady', True)
        config = self.CONFIG(kwargs)
        model = self.mod
        time = self.time
        t0 = time.first()

        was_originally_active = ComponentMap([
            (comp, comp.active)
            for comp in model.component_data_objects((Constraint, Block))
        ])
        non_initial_time = list(time)[1:]
        deactivated = deactivate_model_at(
            model,
            time,
            non_initial_time,
            allow_skip=True,
            suppress_warnings=True,
        )
        was_fixed = ComponentMap()

        # Cache "important" values to re-load after solve
        init_input = list(self.vectors.input[:, t0].value) \
                if VC.INPUT in self.categories else []
        init_meas = list(self.vectors.measurement[:, t0].value) \
                if VC.MEASUREMENT in self.categories else []

        # Fix/unfix variables as appropriate
        # Order matters here. If a derivative is used as an IC, we still want
        # it to be fixed if steady state is required.
        if VC.MEASUREMENT in self.categories:
            self.vectors.measurement[:, t0].unfix()

        if VC.INPUT in self.categories:
            input_vars = self.vectors.input
            was_fixed = ComponentMap(
                (var, var.fixed) for var in input_vars[:, t0])
            input_vars[:, t0].unfix()
        if VC.DERIVATIVE in self.categories:
            if require_steady == True:
                self.vectors.derivative[:, t0].fix(0.)

        self.setpoint_objective.activate()

        # Solve single-time point optimization problem
        #
        # If these sets do not necessarily exist, then I don't think
        # I can make any assertion about the number of degrees of freedom
        #dof = degrees_of_freedom(model)
        #if require_steady:
        #    assert dof == len(self.INPUT_SET)
        #else:
        #    assert dof == (len(self.INPUT_SET) +
        #            len(self.DIFFERENTIAL_SET))
        results = solver.solve(self, tee=config.tee)
        if results.solver.termination_condition == TerminationCondition.optimal:
            pass
        else:
            msg = 'Failed to solve for full state setpoint values'
            raise RuntimeError(msg)

        self.setpoint_objective.deactivate()

        # Revert changes. Again, order matters
        if VC.DERIVATIVE in self.categories:
            if require_steady == True:
                self.vectors.derivative[:, t0].unfix()
        if VC.MEASUREMENT in self.categories:
            self.vectors.measurement[:, t0].fix()

        # Reactivate components that were deactivated
        for t, complist in deactivated.items():
            for comp in complist:
                if was_originally_active[comp]:
                    comp.activate()

        # Fix inputs that were originally fixed
        if VC.INPUT in self.categories:
            for var in self.vectors.input[:, t0]:
                if was_fixed[var]:
                    var.fix()

        setpoint_ctype = (DiffVar, AlgVar, InputVar, FixedVar, DerivVar,
                          MeasuredVar)
        for var in self.component_objects(setpoint_ctype):
            var.setpoint = var[t0].value

        # Restore cached values
        if VC.INPUT in self.categories:
            self.vectors.input.values = init_input
        if VC.MEASUREMENT in self.categories:
            self.vectors.measurement.values = init_meas