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
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
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
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