Example #1
0
def toggle_iflims(ppc, on_off):
    """Enable or disable set of interface flow constraints.

    Enables or disables a set of OPF userfcn callbacks to implement
    interface flow limits based on a DC flow model.

    These callbacks expect to find an 'if' field in the input C{ppc}, where
    C{ppc['if']} is a dict with the following fields:
        - C{map}     C{n x 2}, defines each interface in terms of a set of
        branch indices and directions. Interface I is defined
        by the set of rows whose 1st col is equal to I. The
        2nd column is a branch index multiplied by 1 or -1
        respectively for lines whose orientation is the same
        as or opposite to that of the interface.
        - C{lims}    C{nif x 3}, defines the DC model flow limits in MW
        for specified interfaces. The 2nd and 3rd columns specify
        the lower and upper limits on the (DC model) flow
        across the interface, respectively. Normally, the lower
        limit is negative, indicating a flow in the opposite
        direction.

    The 'int2ext' callback also packages up results and stores them in
    the following output fields of C{results['if']}:
        - C{P}       - C{nif x 1}, actual flow across each interface in MW
        - C{mu.l}    - C{nif x 1}, shadow price on lower flow limit, ($/MW)
        - C{mu.u}    - C{nif x 1}, shadow price on upper flow limit, ($/MW)

    @see: L{add_userfcn}, L{remove_userfcn}, L{run_userfcn},
        L{t.t_case30_userfcns}.

    @author: Ray Zimmerman (PSERC Cornell)
    """
    if on_off == 'on':
        ## check for proper reserve inputs
        if ('if' not in ppc) | (not isinstance(ppc['if'], dict)) | \
                ('map' not in ppc['if']) | \
                ('lims' not in ppc['if']):
            stderr.write(
                'toggle_iflims: case must contain an \'if\' field, a struct defining \'map\' and \'lims\''
            )

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_iflims_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_iflims_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_iflims_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_iflims_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_iflims_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_iflims_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_iflims_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_iflims_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_iflims_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_iflims_ext2int)
    else:
        stderr.write(
            'toggle_iflims: 2nd argument must be either \'on\' or \'off\'')

    return ppc
def toggle_iflims(ppc, on_off):
    """Enable or disable set of interface flow constraints.

    Enables or disables a set of OPF userfcn callbacks to implement
    interface flow limits based on a DC flow model.

    These callbacks expect to find an 'if' field in the input C{ppc}, where
    C{ppc['if']} is a dict with the following fields:
        - C{map}     C{n x 2}, defines each interface in terms of a set of
        branch indices and directions. Interface I is defined
        by the set of rows whose 1st col is equal to I. The
        2nd column is a branch index multiplied by 1 or -1
        respectively for lines whose orientation is the same
        as or opposite to that of the interface.
        - C{lims}    C{nif x 3}, defines the DC model flow limits in MW
        for specified interfaces. The 2nd and 3rd columns specify
        the lower and upper limits on the (DC model) flow
        across the interface, respectively. Normally, the lower
        limit is negative, indicating a flow in the opposite
        direction.

    The 'int2ext' callback also packages up results and stores them in
    the following output fields of C{results['if']}:
        - C{P}       - C{nif x 1}, actual flow across each interface in MW
        - C{mu.l}    - C{nif x 1}, shadow price on lower flow limit, ($/MW)
        - C{mu.u}    - C{nif x 1}, shadow price on upper flow limit, ($/MW)

    @see: L{add_userfcn}, L{remove_userfcn}, L{run_userfcn},
        L{t.t_case30_userfcns}.

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    if on_off == 'on':
        ## check for proper reserve inputs
        if ('if' not in ppc) | (not isinstance(ppc['if'], dict)) | \
                ('map' not in ppc['if']) | \
                ('lims' not in ppc['if']):
            stderr.write('toggle_iflims: case must contain an \'if\' field, a struct defining \'map\' and \'lims\'')

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_iflims_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_iflims_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_iflims_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_iflims_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_iflims_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_iflims_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_iflims_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_iflims_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_iflims_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_iflims_ext2int)
    else:
        stderr.write('toggle_iflims: 2nd argument must be either \'on\' or \'off\'')

    return ppc
Example #3
0
def toggle_dcline(ppc, on_off):
    """Enable or disable DC line modeling.

    Enables or disables a set of OPF userfcn callbacks to implement
    DC lines as a pair of linked generators. While it uses the OPF
    extension mechanism, this implementation works for simple power
    flow as well as OPF problems.

    These callbacks expect to find a 'dcline' field in the input MPC,
    where MPC.dcline is an ndc x 17 matrix with columns as defined
    in IDX_DCLINE, where ndc is the number of DC lines.

    The 'int2ext' callback also packages up flow results and stores them
    in appropriate columns of MPC.dcline.

    NOTE: Because of the way this extension modifies the number of
    rows in the gen and gencost matrices, caution must be taken
    when using it with other extensions that deal with generators.

    Examples:
        ppc = loadcase('t_case9_dcline')
        ppc = toggle_dcline(ppc, 'on')
        results1 = runpf(ppc)
        results2 = runopf(ppc)

    @see: L{idx_dcline}, L{add_userfcn}, L{remove_userfcn}, L{run_userfcn}.
    """
    if on_off == 'on':
        ## define named indices into data matrices
        c = idx_dcline.c

        ## check for proper input data

        if 'dcline' not in ppc or ppc['dcline'].shape[1] < c["LOSS1"] + 1:
            raise ValueError(
                'toggle_dcline: case must contain a '
                '\'dcline\' field, an ndc x %d matrix.', c["LOSS1"])

        if 'dclinecost' in ppc and ppc['dcline'].shape[0] != ppc[
                'dclinecost'].shape[0]:
            raise ValueError(
                'toggle_dcline: number of rows in \'dcline\''
                ' field (%d) and \'dclinecost\' field (%d) do not match.' %
                (ppc['dcline'].shape[0], ppc['dclinecost'].shape[0]))

        k = find(ppc['dcline'][:, c["LOSS1"]] < 0)
        if len(k) > 0:
            warn('toggle_dcline: linear loss term is negative for DC line '
                 'from bus %d to %d\n' %
                 ppc['dcline'][k, c['F_BUS']:c['T_BUS'] + 1].T)

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
    else:
        raise ValueError('toggle_dcline: 2nd argument must be either '
                         '\'on\' or \'off\'')

    return ppc
Example #4
0
def toggle_dcline(ppc, on_off):
    """Enable or disable DC line modeling.

    Enables or disables a set of OPF userfcn callbacks to implement
    DC lines as a pair of linked generators. While it uses the OPF
    extension mechanism, this implementation works for simple power
    flow as well as OPF problems.

    These callbacks expect to find a 'dcline' field in the input MPC,
    where MPC.dcline is an ndc x 17 matrix with columns as defined
    in IDX_DCLINE, where ndc is the number of DC lines.

    The 'int2ext' callback also packages up flow results and stores them
    in appropriate columns of MPC.dcline.

    NOTE: Because of the way this extension modifies the number of
    rows in the gen and gencost matrices, caution must be taken
    when using it with other extensions that deal with generators.

    Examples:
        ppc = loadcase('t_case9_dcline')
        ppc = toggle_dcline(ppc, 'on')
        results1 = runpf(ppc)
        results2 = runopf(ppc)

    @see: L{idx_dcline}, L{add_userfcn}, L{remove_userfcn}, L{run_userfcn}.
    """
    if on_off == 'on':
        ## define named indices into data matrices
        c = idx_dcline.c

        ## check for proper input data
        if 'dcline' not in ppc or ppc['dcline'].shape[1] < c.LOSS1 + 1:
            raise ValueError, ('toggle_dcline: case must contain a '
                    '\'dcline\' field, an ndc x %d matrix.', c.LOSS1)

        if 'dclinecost' in ppc and ppc['dcline'].shape[0] != ppc['dclinecost'].shape[0]:
            raise ValueError, ('toggle_dcline: number of rows in \'dcline\''
                    ' field (%d) and \'dclinecost\' field (%d) do not match.' %
                (ppc['dcline'].shape[0], ppc['dclinecost'].shape[0]))

        k = find(ppc['dcline'][:, c.LOSS1] < 0)
        if len(k) > 0:
            warn('toggle_dcline: linear loss term is negative for DC line '
                   'from bus %d to %d\n' %
                  ppc['dcline'][k, c.F_BUS:c.T_BUS + 1].T)

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_dcline_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_dcline_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_dcline_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_dcline_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_dcline_ext2int)
    else:
        raise ValueError, ('toggle_dcline: 2nd argument must be either '
                '\'on\' or \'off\'')

    return ppc
Example #5
0
def toggle_reserves(ppc, on_off):
    """Enable or disable fixed reserve requirements.

    Enables or disables a set of OPF userfcn callbacks to implement
    co-optimization of reserves with fixed zonal reserve requirements.

    These callbacks expect to find a 'reserves' field in the input C{ppc},
    where C{ppc['reserves']} is a dict with the following fields:
        - C{zones}   C{nrz x ng}, C{zone(i, j) = 1}, if gen C{j} belongs
        to zone C{i} 0, otherwise
        - C{req}     C{nrz x 1}, zonal reserve requirement in MW
        - C{cost}    (C{ng} or C{ngr}) C{x 1}, cost of reserves in $/MW
        - C{qty}     (C{ng} or C{ngr}) C{x 1}, max quantity of reserves
        in MW (optional)
    where C{nrz} is the number of reserve zones and C{ngr} is the number of
    generators belonging to at least one reserve zone and C{ng} is the total
    number of generators.

    The 'int2ext' callback also packages up results and stores them in
    the following output fields of C{results['reserves']}:
        - C{R}       - C{ng x 1}, reserves provided by each gen in MW
        - C{Rmin}    - C{ng x 1}, lower limit on reserves provided by
        each gen, (MW)
        - C{Rmax}    - C{ng x 1}, upper limit on reserves provided by
        each gen, (MW)
        - C{mu.l}    - C{ng x 1}, shadow price on reserve lower limit, ($/MW)
        - C{mu.u}    - C{ng x 1}, shadow price on reserve upper limit, ($/MW)
        - C{mu.Pmax} - C{ng x 1}, shadow price on C{Pg + R <= Pmax}
        constraint, ($/MW)
        - C{prc}     - C{ng x 1}, reserve price for each gen equal to
        maximum of the shadow prices on the zonal requirement constraint
        for each zone the generator belongs to

    @see: L{runopf_w_res}, L{add_userfcn}, L{remove_userfcn}, L{run_userfcn},
        L{t.t_case30_userfcns}

    @author: Ray Zimmerman (PSERC Cornell)
    @author: Richard Lincoln
    """
    if on_off == 'on':
        ## check for proper reserve inputs
        if ('reserves' not in ppc) | (not isinstance(ppc['reserves'], dict)) | \
                ('zones' not in ppc['reserves']) | \
                ('req' not in ppc['reserves']) | \
                ('cost' not in ppc['reserves']):
            stderr.write('toggle_reserves: case must contain a \'reserves\' field, a struct defining \'zones\', \'req\' and \'cost\'\n')

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_reserves_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_reserves_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_reserves_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_reserves_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_reserves_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_reserves_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_reserves_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_reserves_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_reserves_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_reserves_ext2int)
    else:
        stderr.write('toggle_reserves: 2nd argument must be either ''on'' or ''off''')

    return ppc
def toggle_reserves(ppc, on_off):
    """Enable or disable fixed reserve requirements.

    Enables or disables a set of OPF userfcn callbacks to implement
    co-optimization of reserves with fixed zonal reserve requirements.

    These callbacks expect to find a 'reserves' field in the input C{ppc},
    where C{ppc['reserves']} is a dict with the following fields:
        - C{zones}   C{nrz x ng}, C{zone(i, j) = 1}, if gen C{j} belongs
        to zone C{i} 0, otherwise
        - C{req}     C{nrz x 1}, zonal reserve requirement in MW
        - C{cost}    (C{ng} or C{ngr}) C{x 1}, cost of reserves in $/MW
        - C{qty}     (C{ng} or C{ngr}) C{x 1}, max quantity of reserves
        in MW (optional)
    where C{nrz} is the number of reserve zones and C{ngr} is the number of
    generators belonging to at least one reserve zone and C{ng} is the total
    number of generators.

    The 'int2ext' callback also packages up results and stores them in
    the following output fields of C{results['reserves']}:
        - C{R}       - C{ng x 1}, reserves provided by each gen in MW
        - C{Rmin}    - C{ng x 1}, lower limit on reserves provided by
        each gen, (MW)
        - C{Rmax}    - C{ng x 1}, upper limit on reserves provided by
        each gen, (MW)
        - C{mu.l}    - C{ng x 1}, shadow price on reserve lower limit, ($/MW)
        - C{mu.u}    - C{ng x 1}, shadow price on reserve upper limit, ($/MW)
        - C{mu.Pmax} - C{ng x 1}, shadow price on C{Pg + R <= Pmax}
        constraint, ($/MW)
        - C{prc}     - C{ng x 1}, reserve price for each gen equal to
        maximum of the shadow prices on the zonal requirement constraint
        for each zone the generator belongs to

    @see: L{runopf_w_res}, L{add_userfcn}, L{remove_userfcn}, L{run_userfcn},
        L{t.t_case30_userfcns}

    @author: Ray Zimmerman (PSERC Cornell)
    """
    if on_off == 'on':
        ## check for proper reserve inputs
        if ('reserves' not in ppc) | (not isinstance(ppc['reserves'], dict)) | \
                ('zones' not in ppc['reserves']) | \
                ('req' not in ppc['reserves']) | \
                ('cost' not in ppc['reserves']):
            stderr.write(
                'toggle_reserves: case must contain a \'reserves\' field, a struct defining \'zones\', \'req\' and \'cost\'\n'
            )

        ## add callback functions
        ## note: assumes all necessary data included in 1st arg (ppc, om, results)
        ##       so, no additional explicit args are needed
        ppc = add_userfcn(ppc, 'ext2int', userfcn_reserves_ext2int)
        ppc = add_userfcn(ppc, 'formulation', userfcn_reserves_formulation)
        ppc = add_userfcn(ppc, 'int2ext', userfcn_reserves_int2ext)
        ppc = add_userfcn(ppc, 'printpf', userfcn_reserves_printpf)
        ppc = add_userfcn(ppc, 'savecase', userfcn_reserves_savecase)
    elif on_off == 'off':
        ppc = remove_userfcn(ppc, 'savecase', userfcn_reserves_savecase)
        ppc = remove_userfcn(ppc, 'printpf', userfcn_reserves_printpf)
        ppc = remove_userfcn(ppc, 'int2ext', userfcn_reserves_int2ext)
        ppc = remove_userfcn(ppc, 'formulation', userfcn_reserves_formulation)
        ppc = remove_userfcn(ppc, 'ext2int', userfcn_reserves_ext2int)
    else:
        stderr.write('toggle_reserves: 2nd argument must be either '
                     'on'
                     ' or '
                     'off'
                     '')

    return ppc