Beispiel #1
0
    def _Combine(port, name, index_set):
        port_parent = port.parent_block()
        var = port.vars[name]
        in_vars = []
        sources = port.sources(active=True)

        if not len(sources):
            return in_vars

        if len(sources) == 1 and len(sources[0].source.dests(active=True)) == 1:
            # This is a 1-to-1 connection, no need for evar, just equality.
            arc = sources[0]
            Port._add_equality_constraint(arc, name, index_set)
            return in_vars

        for arc in sources:
            eblock = arc.expanded_block

            # Make and record new variables for every arc with this member.
            evar = Port._create_evar(port.vars[name], name, eblock, index_set)
            in_vars.append(evar)

        # Create constraint: var == sum of evars
        # Same logic as Port._Split
        cname = unique_component_name(port_parent, "%s_%s_insum" %
            (alphanum_label_from_name(port.local_name), name))
        def rule(m, *args):
            if len(args):
                return sum(evar[args] for evar in in_vars) == var[args]
            else:
                return sum(evar for evar in in_vars) == var
        con = Constraint(index_set, rule=rule)
        port_parent.add_component(cname, con)

        return in_vars
Beispiel #2
0
    def _Split(port, name, index_set, include_splitfrac=False,
            write_var_sum=True):
        port_parent = port.parent_block()
        var = port.vars[name]
        out_vars = []
        no_splitfrac = False
        dests = port.dests(active=True)

        if not len(dests):
            return out_vars

        if len(dests) == 1:
            # No need for splitting on one outlet.
            # Make sure they do not try to fix splitfrac not at 1.
            splitfracspec = port.get_split_fraction(dests[0])
            if splitfracspec is not None:
                if splitfracspec[0] != 1 and splitfracspec[1] == True:
                    raise ValueError(
                        "Cannot fix splitfrac not at 1 for port '%s' with a "
                        "single dest '%s'" % (port.name, dests[0].name))

            no_splitfrac = True

            if len(dests[0].destination.sources(active=True)) == 1:
                # This is a 1-to-1 connection, no need for evar, just equality.
                arc = dests[0]
                Port._add_equality_constraint(arc, name, index_set)
                return out_vars

        for arc in dests:
            eblock = arc.expanded_block

            # Make and record new variables for every arc with this member.
            evar = Port._create_evar(port.vars[name], name, eblock, index_set)
            out_vars.append(evar)

            if no_splitfrac:
                continue

            # Create and potentially initialize split fraction variables.
            # This function will be called for every Extensive member of this
            # port, but we only need one splitfrac variable per arc, so check
            # if it already exists before making a new one. However, we do not
            # need a splitfrac if there is only one Extensive data object,
            # so first check whether or not we need it.

            if eblock.component("splitfrac") is None:
                if not include_splitfrac:
                    num_data_objs = 0
                    for k, v in iteritems(port.vars):
                        if port.is_extensive(k):
                            if v.is_indexed():
                                num_data_objs += len(v)
                            else:
                                num_data_objs += 1
                            if num_data_objs > 1:
                                break

                    if num_data_objs <= 1:
                        # Do not make splitfrac, do not make split constraints.
                        # Make sure they didn't specify splitfracs.
                        # This inner loop will only run once.
                        for arc in dests:
                            if port.get_split_fraction(arc) is not None:
                                raise ValueError(
                                    "Cannot specify splitfracs for port '%s' "
                                    "(found arc '%s') because this port only "
                                    "has one variable. To have control over "
                                    "splitfracs, please pass the "
                                    " include_splitfrac=True argument." %
                                    (port.name, arc.name))
                        no_splitfrac = True
                        continue

                eblock.splitfrac = Var()
                splitfracspec = port.get_split_fraction(arc)
                if splitfracspec is not None:
                    eblock.splitfrac = splitfracspec[0]
                    if splitfracspec[1]:
                        eblock.splitfrac.fix()

            # Create constraint for this member using splitfrac.
            cname = "%s_split" % name
            def rule(m, *args):
                if len(args):
                    return evar[args] == eblock.splitfrac * var[args]
                else:
                    return evar == eblock.splitfrac * var
            con = Constraint(index_set, rule=rule)
            eblock.add_component(cname, con)

        if write_var_sum:
            # Create var total sum constraint: var == sum of evars
            # Need to alphanum port name in case it is indexed.
            cname = unique_component_name(port_parent, "%s_%s_outsum" %
                (alphanum_label_from_name(port.local_name), name))
            def rule(m, *args):
                if len(args):
                    return sum(evar[args] for evar in out_vars) == var[args]
                else:
                    return sum(evar for evar in out_vars) == var
            con = Constraint(index_set, rule=rule)
            port_parent.add_component(cname, con)
        else:
            # OR create constraint on splitfrac vars: sum == 1
            if no_splitfrac:
                raise ValueError(
                    "Cannot choose to write split fraction sum constraint for "
                    "ports with a single destination or a single Extensive "
                    "variable.\nSplit fractions are skipped in this case to "
                    "simplify the model.\nPlease use write_var_sum=True on "
                    "this port (the default).")
            cname = unique_component_name(port_parent,
                "%s_frac_sum" % alphanum_label_from_name(port.local_name))
            con = Constraint(expr=
                sum(a.expanded_block.splitfrac for a in dests) == 1)
            port_parent.add_component(cname, con)

        return out_vars