Example #1
0
    def test_update_block_derived_override_construct_withfcn2(self):
        class Foo(Block):
            updated = False

            def construct(self, data=None):
                Block.construct(self, data)

            def update_after_discretization(self):
                self.updated = True

        m = ConcreteModel()
        m.t = ContinuousSet(bounds=(0, 10))
        m.s = Set(initialize=[1, 2, 3])

        def _block_rule(b, t, s):
            m = b.model()

            def _init(m, j):
                return j * 2

            b.p1 = Param(m.t, default=_init)
            b.v1 = Var(m.t, initialize=5)

        m.foo = Foo(m.t, m.s, rule=_block_rule)

        generate_finite_elements(m.t, 5)
        expand_components(m)

        self.assertTrue(m.foo.updated)
        self.assertEqual(len(m.foo), 6)
        self.assertEqual(len(m.foo[0, 1].v1), 6)
Example #2
0
    def test_update_block_derived2(self):
        class Foo(Block):
            pass

        m = ConcreteModel()
        m.t = ContinuousSet(bounds=(0, 10))
        m.s = Set(initialize=[1, 2, 3])

        def _block_rule(b, t, s):
            m = b.model()

            def _init(m, j):
                return j * 2

            b.p1 = Param(m.t, default=_init)
            b.v1 = Var(m.t, initialize=5)

        m.foo = Foo(m.t, m.s, rule=_block_rule)

        generate_finite_elements(m.t, 5)
        expand_components(m)

        self.assertEqual(len(m.foo), 18)
        self.assertEqual(len(m.foo[0, 1].p1), 6)
        self.assertEqual(len(m.foo[2, 2].v1), 6)
        self.assertEqual(m.foo[0, 3].p1[6], 12)
Example #3
0
    def test_update_block_derived_override_construct_nofcn2(self):
        class Foo(Block):
            def construct(self, data=None):
                Block.construct(self, data)

        m = ConcreteModel()
        m.t = ContinuousSet(bounds=(0, 10))
        m.s = Set(initialize=[1, 2, 3])

        def _block_rule(b, t, s):
            m = b.model()

            def _init(m, j):
                return j * 2

            b.p1 = Param(m.t, default=_init)
            b.v1 = Var(m.t, initialize=5)

        m.foo = Foo(m.t, m.s, rule=_block_rule)

        generate_finite_elements(m.t, 5)

        OUTPUT = StringIO()
        with LoggingIntercept(OUTPUT, 'pyomo.dae'):
            expand_components(m)
        self.assertIn('transformation to the Block-derived component',
                      OUTPUT.getvalue())
        self.assertEqual(len(m.foo), 18)
        self.assertEqual(len(m.foo[0, 1].p1), 6)
        self.assertEqual(len(m.foo[2, 2].v1), 6)
        self.assertEqual(m.foo[0, 3].p1[6], 12)
Example #4
0
    def test_hierarchical_blocks(self):
        m = ConcreteModel()

        m.b = Block()
        m.b.t = ContinuousSet(bounds=(0, 10))

        m.b.c = Block()

        def _d_rule(d, t):
            m = d.model()
            d.x = Var()
            return d

        m.b.c.d = Block(m.b.t, rule=_d_rule)

        m.b.y = Var(m.b.t)

        def _con_rule(b, t):
            return b.y[t] <= b.c.d[t].x

        m.b.con = Constraint(m.b.t, rule=_con_rule)

        generate_finite_elements(m.b.t, 5)
        expand_components(m)

        self.assertEqual(len(m.b.c.d), 6)
        self.assertEqual(len(m.b.con), 6)
        self.assertEqual(len(m.b.y), 6)
Example #5
0
    def test_external_function(self):
        m = ConcreteModel()
        m.t = ContinuousSet(bounds=(0, 10))

        def _fun(x):
            return x**2

        m.x_func = ExternalFunction(_fun)

        m.y = Var(m.t, initialize=3)
        m.dy = DerivativeVar(m.y, initialize=3)

        def _con(m, t):
            return m.dy[t] == m.x_func(m.y[t])

        m.con = Constraint(m.t, rule=_con)

        generate_finite_elements(m.t, 5)
        expand_components(m)

        self.assertEqual(len(m.y), 6)
        self.assertEqual(len(m.con), 6)
Example #6
0
    def _transformBlock(self, block, currentds):

        self._fe = {}
        for ds in block.component_objects(ContinuousSet, descend_into=True):
            if currentds is None or currentds == ds.name:
                if 'scheme' in ds.get_discretization_info():
                    raise DAE_Error(
                        "Attempting to discretize ContinuousSet "
                        "'%s' after it has already been discretized. " %
                        ds.name)
                generate_finite_elements(ds, self._nfe[currentds])
                if not ds.get_changed():
                    if len(ds) - 1 > self._nfe[currentds]:
                        logger.warning(
                            "More finite elements were found in "
                            "ContinuousSet '%s' than the number of "
                            "finite elements specified in apply. The "
                            "larger number of finite elements will be "
                            "used." % ds.name)

                self._nfe[ds.name] = len(ds) - 1
                self._fe[ds.name] = list(ds)
                generate_colloc_points(ds, self._tau[currentds])
                # Adding discretization information to the continuousset
                # object itself so that it can be accessed outside of the
                # discretization object
                disc_info = ds.get_discretization_info()
                disc_info['nfe'] = self._nfe[ds.name]
                disc_info['ncp'] = self._ncp[currentds]
                disc_info['tau_points'] = self._tau[currentds]
                disc_info['adot'] = self._adot[currentds]
                disc_info['adotdot'] = self._adotdot[currentds]
                disc_info['afinal'] = self._afinal[currentds]
                disc_info['scheme'] = self._scheme_name

        expand_components(block)

        for d in block.component_objects(DerivativeVar, descend_into=True):
            dsets = d.get_continuousset_list()
            for i in ComponentSet(dsets):
                if currentds is None or i.name == currentds:
                    oldexpr = d.get_derivative_expression()
                    loc = d.get_state_var()._contset[i]
                    count = dsets.count(i)
                    if count >= 3:
                        raise DAE_Error(
                            "Error discretizing '%s' with respect to '%s'. "
                            "Current implementation only allows for taking the"
                            " first or second derivative with respect to a "
                            "particular ContinuousSet" % (d.name, i.name))
                    scheme = self._scheme[count - 1]

                    newexpr = create_partial_expression(
                        scheme, oldexpr, i, loc)
                    d.set_derivative_expression(newexpr)
                    if self._scheme_name == 'LAGRANGE-LEGENDRE':
                        # Add continuity equations to DerivativeVar's parent
                        #  block
                        add_continuity_equations(d.parent_block(), d, i, loc)

            # Reclassify DerivativeVar if all indexing ContinuousSets have
            # been discretized. Add discretization equations to the
            # DerivativeVar's parent block.
            if d.is_fully_discretized():
                add_discretization_equations(d.parent_block(), d)
                d.parent_block().reclassify_component_type(d, Var)

                # Keep track of any reclassified DerivativeVar components so
                # that the Simulator can easily identify them if the model
                # is simulated after discretization
                # TODO: Update the discretization transformations to use
                # a Block to add things to the model and store discretization
                # information. Using a list for now because the simulator
                # does not yet support models containing active Blocks
                reclassified_list = getattr(
                    block, '_pyomo_dae_reclassified_derivativevars', None)
                if reclassified_list is None:
                    block._pyomo_dae_reclassified_derivativevars = list()
                    reclassified_list = \
                        block._pyomo_dae_reclassified_derivativevars

                reclassified_list.append(d)

        # Reclassify Integrals if all ContinuousSets have been discretized
        if block_fully_discretized(block):

            if block.contains_component(Integral):
                for i in block.component_objects(Integral, descend_into=True):
                    i.parent_block().reclassify_component_type(i, Expression)
                    # TODO: The following reproduces the old behavior of
                    # "reconstruct()".  We should come up with an
                    # implementation that does not rely on manipulating
                    # private attributes
                    i.clear()
                    i._constructed = False
                    i.construct()
                # If a model contains integrals they are most likely to appear
                # in the objective function which will need to be reconstructed
                # after the model is discretized.
                for k in block.component_objects(Objective, descend_into=True):
                    # TODO: check this, reconstruct might not work
                    # TODO: The following reproduces the old behavior of
                    # "reconstruct()".  We should come up with an
                    # implementation that does not rely on manipulating
                    # private attributes
                    k.clear()
                    k._constructed = False
                    k.construct()
Example #7
0
    def _transformBlock(self, block, currentds):

        self._fe = {}
        for ds in block.component_objects(ContinuousSet, descend_into=True):
            if currentds is None or currentds == ds.name:
                if 'scheme' in ds.get_discretization_info():
                    raise DAE_Error("Attempting to discretize ContinuousSet "
                                    "'%s' after it has already been discretized. "
                                    % ds.name)
                generate_finite_elements(ds, self._nfe[currentds])
                if not ds.get_changed():
                    if len(ds) - 1 > self._nfe[currentds]:
                        logger.warn("More finite elements were found in "
                                    "ContinuousSet '%s' than the number of "
                                    "finite elements specified in apply. The "
                                    "larger number of finite elements will be "
                                    "used." % ds.name)

                self._nfe[ds.name] = len(ds) - 1
                self._fe[ds.name] = sorted(ds)
                generate_colloc_points(ds, self._tau[currentds])
                # Adding discretization information to the continuousset
                # object itself so that it can be accessed outside of the
                # discretization object
                disc_info = ds.get_discretization_info()
                disc_info['nfe'] = self._nfe[ds.name]
                disc_info['ncp'] = self._ncp[currentds]
                disc_info['tau_points'] = self._tau[currentds]
                disc_info['adot'] = self._adot[currentds]
                disc_info['adotdot'] = self._adotdot[currentds]
                disc_info['afinal'] = self._afinal[currentds]
                disc_info['scheme'] = self._scheme_name

        expand_components(block)

        for d in block.component_objects(DerivativeVar, descend_into=True):
            dsets = d.get_continuousset_list()
            for i in set(dsets):
                if currentds is None or i.name == currentds:
                    oldexpr = d.get_derivative_expression()
                    loc = d.get_state_var()._contset[i]
                    count = dsets.count(i)
                    if count >= 3:
                        raise DAE_Error(
                            "Error discretizing '%s' with respect to '%s'. "
                            "Current implementation only allows for taking the"
                            " first or second derivative with respect to a "
                            "particular ContinuousSet" % (d.name, i.name))
                    scheme = self._scheme[count - 1]

                    newexpr = create_partial_expression(scheme, oldexpr, i,
                                                        loc)
                    d.set_derivative_expression(newexpr)
                    if self._scheme_name == 'LAGRANGE-LEGENDRE':
                        # Add continuity equations to DerivativeVar's parent
                        #  block
                        add_continuity_equations(d.parent_block(), d, i, loc)

            # Reclassify DerivativeVar if all indexing ContinuousSets have
            # been discretized. Add discretization equations to the
            # DerivativeVar's parent block.
            if d.is_fully_discretized():
                add_discretization_equations(d.parent_block(), d)
                d.parent_block().reclassify_component_type(d, Var)

                # Keep track of any reclassified DerivativeVar components so
                # that the Simulator can easily identify them if the model
                # is simulated after discretization
                # TODO: Update the discretization transformations to use
                # a Block to add things to the model and store discretization
                # information. Using a list for now because the simulator
                # does not yet support models containing active Blocks
                reclassified_list = getattr(block,
                                            '_pyomo_dae_reclassified_derivativevars',
                                            None)
                if reclassified_list is None:
                    block._pyomo_dae_reclassified_derivativevars = list()
                    reclassified_list = \
                        block._pyomo_dae_reclassified_derivativevars

                reclassified_list.append(d)

        # Reclassify Integrals if all ContinuousSets have been discretized
        if block_fully_discretized(block):

            if block.contains_component(Integral):
                for i in block.component_objects(Integral, descend_into=True):
                    i.reconstruct()
                    i.parent_block().reclassify_component_type(i, Expression)
                # If a model contains integrals they are most likely to appear
                # in the objective function which will need to be reconstructed
                # after the model is discretized.
                for k in block.component_objects(Objective, descend_into=True):
                    # TODO: check this, reconstruct might not work
                    k.reconstruct()
Example #8
0
    def _transformBlock(self, block, currentds):

        self._fe = {}
        for ds in block.component_objects(ContinuousSet):
            if currentds is None or currentds == ds.name or currentds is ds:
                generate_finite_elements(ds, self._nfe[currentds])
                if not ds.get_changed():
                    if len(ds) - 1 > self._nfe[currentds]:
                        print("***WARNING: More finite elements were found in "
                              "ContinuousSet '%s' than the number of finite "
                              "elements specified in apply. The larger number "
                              "of finite elements will be used." % ds.name)

                self._nfe[ds.name] = len(ds) - 1
                self._fe[ds.name] = sorted(ds)
                # Adding discretization information to the differentialset
                # object itself so that it can be accessed outside of the
                # discretization object
                disc_info = ds.get_discretization_info()
                disc_info['nfe'] = self._nfe[ds.name]
                disc_info['scheme'] = self._scheme_name + ' Difference'

        # Maybe check to see if any of the ContinuousSets have been changed,
        # if they haven't then the model components need not be updated
        # or even iterated through
        expand_components(block)

        for d in block.component_objects(DerivativeVar, descend_into=True):
            dsets = d.get_continuousset_list()
            for i in set(dsets):
                if currentds is None or i.name == currentds:
                    oldexpr = d.get_derivative_expression()
                    loc = d.get_state_var()._contset[i]
                    count = dsets.count(i)
                    if count >= 3:
                        raise DAE_Error(
                            "Error discretizing '%s' with respect to '%s'. "
                            "Current implementation only allows for taking the"
                            " first or second derivative with respect to "
                            "a particular ContinuousSet" % (d.name, i.name))
                    scheme = self._scheme[count - 1]
                    newexpr = create_partial_expression(
                        scheme, oldexpr, i, loc)
                    d.set_derivative_expression(newexpr)

            # Reclassify DerivativeVar if all indexing ContinuousSets have
            # been discretized. Add discretization equations to the
            # DerivativeVar's parent block.
            if d.is_fully_discretized():
                add_discretization_equations(d.parent_block(), d)
                d.parent_block().reclassify_component_type(d, Var)

        # Reclassify Integrals if all ContinuousSets have been discretized
        if block_fully_discretized(block):

            if block.contains_component(Integral):
                for i in block.component_objects(Integral, descend_into=True):
                    i.reconstruct()
                    i.parent_block().reclassify_component_type(i, Expression)
                # If a model contains integrals they are most likely to
                # appear in the objective function which will need to be
                # reconstructed after the model is discretized.
                for k in block.component_objects(Objective, descend_into=True):
                    # TODO: check this, reconstruct might not work
                    k.reconstruct()
Example #9
0
    def _transformBlock(self, block, currentds):

        self._fe = {}
        for ds in block.component_objects(ContinuousSet):
            if currentds is None or currentds == ds.name or currentds is ds:
                if 'scheme' in ds.get_discretization_info():
                    raise DAE_Error(
                        "Attempting to discretize ContinuousSet "
                        "'%s' after it has already been discretized. " %
                        ds.name)
                generate_finite_elements(ds, self._nfe[currentds])
                if not ds.get_changed():
                    if len(ds) - 1 > self._nfe[currentds]:
                        logger.warn("More finite elements were found in "
                                    "ContinuousSet '%s' than the number of "
                                    "finite elements specified in apply. The "
                                    "larger number of finite elements will be "
                                    "used." % ds.name)

                self._nfe[ds.name] = len(ds) - 1
                self._fe[ds.name] = sorted(ds)
                # Adding discretization information to the ContinuousSet
                # object itself so that it can be accessed outside of the
                # discretization object
                disc_info = ds.get_discretization_info()
                disc_info['nfe'] = self._nfe[ds.name]
                disc_info['scheme'] = self._scheme_name + ' Difference'

        # Maybe check to see if any of the ContinuousSets have been changed,
        # if they haven't then the model components need not be updated
        # or even iterated through
        expand_components(block)

        for d in block.component_objects(DerivativeVar, descend_into=True):
            dsets = d.get_continuousset_list()
            for i in ComponentSet(dsets):
                if currentds is None or i.name == currentds:
                    oldexpr = d.get_derivative_expression()
                    loc = d.get_state_var()._contset[i]
                    count = dsets.count(i)
                    if count >= 3:
                        raise DAE_Error(
                            "Error discretizing '%s' with respect to '%s'. "
                            "Current implementation only allows for taking the"
                            " first or second derivative with respect to "
                            "a particular ContinuousSet" % (d.name, i.name))
                    scheme = self._scheme[count - 1]
                    newexpr = create_partial_expression(
                        scheme, oldexpr, i, loc)
                    d.set_derivative_expression(newexpr)

            # Reclassify DerivativeVar if all indexing ContinuousSets have
            # been discretized. Add discretization equations to the
            # DerivativeVar's parent block.
            if d.is_fully_discretized():
                add_discretization_equations(d.parent_block(), d)
                d.parent_block().reclassify_component_type(d, Var)

                # Keep track of any reclassified DerivativeVar components so
                # that the Simulator can easily identify them if the model
                # is simulated after discretization
                # TODO: Update the discretization transformations to use
                # a Block to add things to the model and store discretization
                # information. Using a list for now because the simulator
                # does not yet support models containing active Blocks
                reclassified_list = getattr(
                    block, '_pyomo_dae_reclassified_derivativevars', None)
                if reclassified_list is None:
                    block._pyomo_dae_reclassified_derivativevars = list()
                    reclassified_list = \
                        block._pyomo_dae_reclassified_derivativevars

                reclassified_list.append(d)

        # Reclassify Integrals if all ContinuousSets have been discretized
        if block_fully_discretized(block):

            if block.contains_component(Integral):
                for i in block.component_objects(Integral, descend_into=True):
                    i.reconstruct()
                    i.parent_block().reclassify_component_type(i, Expression)
                # If a model contains integrals they are most likely to
                # appear in the objective function which will need to be
                # reconstructed after the model is discretized.
                for k in block.component_objects(Objective, descend_into=True):
                    # TODO: check this, reconstruct might not work
                    k.reconstruct()