예제 #1
0
파일: power.py 프로젝트: apalom/OPF
 def powerflow(self):
     try:
         pp.runpp(self.net)
         return self._results()
     except pp.LoadflowNotConverged:
         pp.diagnostic(self.net)
         return None, None
예제 #2
0
def test_no_issues(diag_params, diag_errors, report_methods):
    net = nw.example_simple()
    diag_results = pp.diagnostic(net, report_style=None)
    assert diag_results == {}
    for bool_value in [True, False]:
        for check_function in report_methods.keys():
            diag_report = DiagnosticReports(net, diag_results, diag_errors, diag_params, compact_report=bool_value)
            report_check = None
            try:
                eval(report_methods[check_function])
                report_check = True
            except:
                report_check = False
            assert report_check
예제 #3
0
def test_diagnostic_report():
    net = nw.example_multivoltage()
    net.line.loc[7, 'length_km'] = -1
    net.gen.bus.at[0] = 0
    net.load.p_kw.at[4] *= 1000
    net.switch.closed.at[0] = 0
    net.switch.closed.at[2] = 0
    pp.create_switch(net, 41, 45, et='b')
    net.line.r_ohm_per_km.at[1] = 0
    net.load.p_kw.at[0] = -1
    net.switch.closed.loc[37, 38] = False
    net.line.x_ohm_per_km.loc[6] -= 1
    net.line.from_bus.iloc[0] = 10000
    pp.create_switch(net, 1, 2, et='b')

    diag_results = pp.diagnostic(net)
    diag_params = {
        "overload_scaling_factor": 0.001,
        "lines_min_length_km": 0,
        "lines_min_z_ohm": 0,
        "nom_voltage_tolerance": 0.3,
        "numba_tolerance": 1e-5
    }
    diag_report = DiagnosticReports(net,
                                    diag_results,
                                    diag_params,
                                    compact_report=False)
    report_methods = {
        "missing_bus_indeces": diag_report.report_missing_bus_indeces,
        "disconnected_elements": diag_report.report_disconnected_elements,
        "different_voltage_levels_connected":
        diag_report.report_different_voltage_levels_connected,
        "lines_with_impedance_close_to_zero":
        diag_report.report_lines_with_impedance_close_to_zero,
        "nominal_voltages_dont_match":
        diag_report.report_nominal_voltages_dont_match,
        "invalid_values": diag_report.report_invalid_values,
        "overload": diag_report.report_overload,
        "multiple_voltage_controlling_elements_per_bus":
        diag_report.report_multiple_voltage_controlling_elements_per_bus,
        "wrong_switch_configuration":
        diag_report.report_wrong_switch_configuration,
        "no_ext_grid": diag_report.report_no_ext_grid,
        "wrong_reference_system": diag_report.report_wrong_reference_system,
        "deviation_from_std_type": diag_report.report_deviation_from_std_type,
        "numba_comparison": diag_report.report_numba_comparison,
        "parallel_switches": diag_report.report_parallel_switches
    }

    for key in diag_results:
        report_check = None
        try:
            report_methods[key]()
            report_check = True
        except:
            report_check = False
        assert report_check

    diag_report = DiagnosticReports(net,
                                    diag_results,
                                    diag_params,
                                    compact_report=True)
    for key in diag_results:
        report_check = None
        try:
            report_methods[key]()
            report_check = True
        except:
            report_check = False
        assert report_check
예제 #4
0
def test_runpp_errors(test_net, diag_params, diag_errors, report_methods):
    net = copy.deepcopy(test_net)
    net.load.p_mw *= 100
    diag = pp.diagnostic(net, report_style=None)
def diag():
    net = faulty_example_network()
    # pp.runpp(net)
    # pplt.simple_plot(net, plot_line_switches=True)
    pp.diagnostic(net)
예제 #6
0
def sim_request(data):
    is_three_phase = utils.get_or_error("3phase", data)
    elements_dict = utils.get_or_error("elements", data)
    buses = {} # Used for matching bus UUIDs to index

    def process_potential_bus(key, value):
        """ Inner method for processing a positional argument that could be a bus
            This function checks if the value is in the bus keys. This should never cause issues so long as UUID's aren't used for
            any other purpose except for bus identification and as long as there are no UUID collisions. Both of those cases seem
            exceptionally unlikely, so this should work fine.
        """
        if value in buses.keys():
            return buses[value]
        else:
            return value

    bus_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) == "bus"]
    element_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) != "bus" and utils.get_or_error("etype", element) != "switch"]
    switch_list = [(uuid, element) for uuid, element in elements_dict.items() if utils.get_or_error("etype", element) == "switch"]

    net = pp.create_empty_network()

    for uuid, bus in bus_list:
        element_type = "bus"
        req_props = utils.required_props[element_type]
        positional_args = [ value for key, value in bus.items() if key in req_props ]
        optional_args = { key: value for key, value in bus.items() if (not key in req_props) and (not key == "etype")}
        index = pp.create_bus(net, *positional_args, **optional_args, name=uuid)
        buses[uuid] = index
    
    for uuid, element in element_list:
        element_type = utils.get_or_error("etype", element)
        req_props = utils.required_props[element_type]
        positional_args = [process_potential_bus(key, value) for key, value in element.items() if key in req_props]
        optional_args = { key: value for key, value in element.items() if (not key in req_props) and (not key == "etype")}
        
        if element_type == "load":
            pp.create_load(net, *positional_args, **optional_args, name=uuid)
        elif element_type == "gen":
            pp.create_gen(net, *positional_args, **optional_args, name=uuid)
        elif element_type == "ext_grid":
            pp.create_ext_grid(net, *positional_args, **optional_args, name=uuid)
        elif element_type == "line":
            pp.create_line(net, *positional_args, *optional_args, name=uuid)
        elif element_type == "trafo":
            pp.create_transformer_from_parameters(net, *positional_args, **optional_args, name=uuid)
        elif element_type == "storage":
            pp.create_storage(net, *positional_args, **optional_args, name=uuid)
        else:
            raise InvalidError(f"Element type {element_type} is invalid or not implemented!")

    for uuid, switch in switch_list:
        element_type = "switch"
        req_props = utils.required_props[element_type]
        positional_args = [process_potential_bus(key, value) for key, value in element.items() if key in req_props]
        optional_args = { key: value for key, value in element.items() if (not key in req_props) and (not key == "etype")}
        et = positional_args[2]
        if et == "b":
            pass # This is handled by process_potential_buses
        if et == "l":
            positional_args[1] = pp.get_element_index(net, "line", positional_args[1])
        elif et == "t":
            positional_args[1] = pp.get_element_index(net, "trafo", positional_args[1])
        elif et == "t3":
            positional_args[1] = pp.get_element_index(net, "trafo3w", positional_args[1])
        else:
            raise InvalidError(f"Invalid element type {et}. Must be b,l,t, or t3.")
        pp.create_switch(net, *positional_args, **optional_args, name=uuid)
            
    try:
        if is_three_phase:
            pp.runpp_3ph(net)
        else:
            pp.runpp(net)
    except LoadflowNotConverged:
        report = pp.diagnostic(net, report_style="compact", warnings_only=True)
        raise ConvError("Load flow did not converge.")
    except (KeyError, ValueError) as e:
        raise PPError(str(e))
    except Exception as e:
        raise PPError("Unknown exception has occured: " + str(e))

    message = {}
    message["status"] = "SIM_RESULT"
    results = {}

    for uuid,element in elements_dict.items():
        element_type = elements_dict[uuid]["etype"]
        if element_type == "switch": continue
        net["res_" + element_type] = net["res_" + element_type].fillna(0)
        results[uuid] = {}
        results[uuid]["etype"] = element_type
        index = pp.get_element_index(net, element_type, uuid, exact_match=True)
        results[uuid].update(net["res_" + element_type].iloc[index].to_dict())

    message["elements"] = results
    return json.dumps(message)
예제 #7
0
for pq in pqs.itertuples(index=True, name='Pandas'):
    bus_num = getattr(pq, "bus_num")
    p_mw = getattr(pq, "active_power")
    q_mvar = getattr(pq, "reactive_power")
    pq_num = getattr(pq, "Index")
    pp.create_load(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, name='Load %s' % pq_num)
print(net.load) # show loads table

### PQgen ###
pqgens = pd.read_csv('data/PQgen.csv',names=['bus_num','power_rating','voltage_rating','active_power','reactive_power',
                                            'v_max','v_min','conv_imp','area'],index_col=False)
for pqgen in pqgens.itertuples(index=True, name='Pandas'):
    bus_num = getattr(pqgen, "bus_num")
    try:
        mask=pqs[pqs['bus_num']==bus_num].index.tolist()[0]
        raise ValueError("Attention static gens and loads at the same bus. Manually modify database")
    except:
        p_mw = getattr(pqgen, "active_power")
        q_mvar = getattr(pqgen, "reactive_power")
        sn_mva = getattr(pqgen, "power_rating")
        pqgen_num = getattr(pqgen, "Index")
        pp.create_sgen(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, sn_mva=sn_mva, name='StatGen %s' % pqgen_num)
        #pp.create_load(net, bus_num-1, p_mw=p_mw, q_mvar=q_mvar, name='StatGen %s' % pqgen_num)
print(net.sgen) # show static gen table

### Diagnosis ###
pp.diagnostic(net, report_style='detailed', warnings_only=False, return_result_dict=True, overload_scaling_factor=0.001, min_r_ohm=0.001, min_x_ohm=0.001, min_r_pu=1e-05, min_x_pu=1e-05, nom_voltage_tolerance=0.3, numba_tolerance=1e-05)

### Run Power Flow ###
pp.runpp(net, algorithm="iwamoto_nr", calculate_voltage_angles="auto", init="dc", check_connectivity=True, v_debug=True) #, init_vm_pu=True, init_va_degree=True
print(net)
예제 #8
0
def test_no_issues(test_net):
    net = copy.deepcopy(test_net)
    assert pp.diagnostic(net, report_style=None) == {}
예제 #9
0
def validate_pf_conversion(net, is_unbalanced=False, **kwargs):
    """
    Trys to run a Loadflow with the converted pandapower network. If the loadflow converges, \
    PowerFactory and pandapower loadflow results will be compared. Note that a pf validation can \
    only be done if there are pf results available.

    INPUT:

        - **net** (PandapowerNetwork) - converted pandapower network

    OUTPUT:
        - **all_diffs** (list) - returns a list with the difference in all validated values.
                                 If all values are zero -> results are equal

    """
    logger.debug('starting verification')
    toolbox.replace_zero_branches_with_switches(net)
    pf_results = _get_pf_results(net, is_unbalanced=is_unbalanced)
    if "controller" not in net.keys() or len(net.controller) == 0:
        try:
            for arg in 'trafo_model check_connectivity'.split():
                if arg in kwargs:
                    kwargs.pop(arg)
            if is_unbalanced:
                logger.info("running pandapower 3ph loadflow")
                pp.runpp_3ph(net,
                             trafo_model="t",
                             check_connectivity=True,
                             **kwargs)
            else:
                logger.info("running pandapower loadflow")
                pp.runpp(net,
                         trafo_model="t",
                         check_connectivity=True,
                         **kwargs)
        except Exception as err:
            logger.error('pandapower load flow failed: %s' % err,
                         exc_info=True)
            diagnostic(net)
            raise err
    else:
        import pandapower.control as control
        try:
            control.run_control(net,
                                max_iter=50,
                                trafo_model="t",
                                check_connectivity=True,
                                **kwargs)
        except Exception as err:
            logger.error('pandapower load flow with converter failed: %s' %
                         err)
            diagnostic(net)
            raise err

    all_diffs = dict()
    logger.info('pandapower net converged: %s' % net.converged)
    _set_pf_results(net, pf_results, is_unbalanced=is_unbalanced)

    net.bus.name.fillna("", inplace=True)
    only_in_pandapower = set(net.bus[net.bus.name.str.endswith("_aux")].index) | \
                           set(net.bus[net.bus.type == "ls"].index)
    in_both = set(net.bus.index) - only_in_pandapower

    pf_closed = pf_results['pf_switch_status']
    wrong_switches = net.res_switch.loc[pf_closed != net.switch.loc[
        pf_closed.index,
        'closed']].index.values if 'res_switch' in net.keys() else []
    if len(net.switch) > 0:
        logger.info('%d switches are wrong: %s' %
                    (len(wrong_switches), wrong_switches))

    if len(net.trafo3w[net.trafo3w.in_service]) > 0:
        trafo3w_idx = net.trafo3w.query('in_service').index
        trafo3w_diff = net.res_trafo3w.loc[
            trafo3w_idx].pf_loading - net.res_trafo3w.loc[
                trafo3w_idx].loading_percent
        trafo3w_id = abs(trafo3w_diff).idxmax()
        logger.info(
            "Maximum trafo3w loading difference between pandapower and powerfactory: %.1f "
            "percent at trafo3w %d (%s)" %
            (max(abs(trafo3w_diff)), trafo3w_id, net.trafo3w.at[trafo3w_id,
                                                                'name']))
        all_diffs["trafo3w_diff"] = trafo3w_diff

    if len(net.sgen[net.sgen.in_service]) > 0:
        logger.debug('verifying sgen')
        sgen_p_diff = net.res_sgen.pf_p.replace(np.nan, 0) - net.res_sgen.p_mw
        sgen_q_diff = net.res_sgen.pf_q.replace(np.nan,
                                                0) - net.res_sgen.q_mvar
        sgen_p_diff_is = net.res_sgen.pf_p.replace(np.nan, 0) * net.sgen.loc[
            net.res_sgen.index, 'in_service'] - net.res_sgen.p_mw
        sgen_q_diff_is = net.res_sgen.pf_q.replace(np.nan, 0) * net.sgen.loc[
            net.res_sgen.index, 'in_service'] - net.res_sgen.q_mvar
        logger.info(
            "Maximum sgen active power difference between pandapower and powerfactory: "
            "%.1f MW, in service only: %.1f MW" %
            (max(abs(sgen_p_diff)), max(abs(sgen_p_diff_is))))
        logger.info(
            "Maximum sgen reactive power difference between pandapower and powerfactory: "
            "%.1f Mvar, in service only: %.1f Mvar" %
            (max(abs(sgen_q_diff)), max(abs(sgen_q_diff_is))))
        all_diffs["sgen_p_diff_is"] = sgen_p_diff_is
        all_diffs["sgen_q_diff_is"] = sgen_q_diff_is

    if len(net.gen[net.gen.in_service]) > 0:
        logger.debug('verifying gen')
        gen_p_diff = net.res_gen.pf_p.replace(np.nan, 0) - net.res_gen.p_mw
        gen_q_diff = net.res_gen.pf_q.replace(np.nan, 0) - net.res_gen.q_mvar
        gen_p_diff_is = net.res_gen.pf_p.replace(np.nan, 0) * net.gen.loc[
            net.res_gen.index, 'in_service'] - net.res_gen.p_mw
        gen_q_diff_is = net.res_gen.pf_q.replace(np.nan, 0) * net.gen.loc[
            net.res_gen.index, 'in_service'] - net.res_gen.q_mvar
        logger.info(
            "Maximum gen active power difference between pandapower and powerfactory: "
            "%.1f MW, in service only: %.1f MW" %
            (max(abs(gen_p_diff)), max(abs(gen_p_diff_is))))
        logger.info(
            "Maximum gen reactive power difference between pandapower and powerfactory: "
            "%.1f Mvar, in service only: %.1f Mvar" %
            (max(abs(gen_q_diff)), max(abs(gen_q_diff_is))))
        all_diffs["gen_p_diff_is"] = gen_p_diff_is
        all_diffs["gen_q_diff_is"] = gen_q_diff_is

    if len(net.ward[net.ward.in_service]) > 0:
        logger.debug('verifying ward')
        ward_p_diff = net.res_ward.pf_p.replace(np.nan, 0) - net.res_ward.p_mw
        ward_q_diff = net.res_ward.pf_q.replace(np.nan,
                                                0) - net.res_ward.q_mvar
        ward_p_diff_is = net.res_ward.pf_p.replace(np.nan, 0) * net.ward.loc[
            net.res_ward.index, 'in_service'] - net.res_ward.p_mw
        ward_q_diff_is = net.res_ward.pf_q.replace(np.nan, 0) * net.ward.loc[
            net.res_ward.index, 'in_service'] - net.res_ward.q_mvar
        logger.info(
            "Maximum ward active power difference between pandapower and powerfactory: "
            "%.1f MW, in service only: %.1f MW" %
            (max(abs(ward_p_diff)), max(abs(ward_p_diff_is))))
        logger.info(
            "Maximum ward reactive power difference between pandapower and powerfactory: "
            "%.1f Mvar, in service only: %.1f Mvar" %
            (max(abs(ward_q_diff)), max(abs(ward_q_diff_is))))
        all_diffs["ward_p_diff_is"] = ward_p_diff_is
        all_diffs["ward_q_diff_is"] = ward_q_diff_is

    if is_unbalanced:
        _validate_pf_conversion_unbalanced(net, in_both, all_diffs)
    else:
        _validate_pf_conversion_balanced(net, in_both, all_diffs)

    return all_diffs