Exemple #1
0
def _add_trafo_sc_impedance_zero(net, ppc, trafo_df=None):
    if trafo_df is None:
        trafo_df = net["trafo"]
    branch_lookup = net["_pd2ppc_lookups"]["branch"]
    if not "trafo" in branch_lookup:
        return
    bus_lookup = net["_pd2ppc_lookups"]["bus"]
    mode = net["_options"]["mode"]
    f, t = branch_lookup["trafo"]
    trafo_df["_ppc_idx"] = range(f, t)
    bus_lookup = net["_pd2ppc_lookups"]["bus"]
    buses_all, gs_all, bs_all = np.array([],
                                         dtype=int), np.array([]), np.array([])
    for vector_group, trafos in trafo_df.groupby("vector_group"):
        ppc_idx = trafos["_ppc_idx"].values.astype(int)
        ppc["branch"][ppc_idx, BR_STATUS] = 0

        if vector_group in ["Yy", "Yd", "Dy", "Dd"]:
            continue

        vk_percent = trafos["vk_percent"].values.astype(float)
        vkr_percent = trafos["vkr_percent"].values.astype(float)
        sn_mva = trafos["sn_mva"].values.astype(float)
        vk0_percent = trafos["vk0_percent"].values.astype(float)
        vkr0_percent = trafos["vkr0_percent"].values.astype(float)
        lv_buses = trafos["lv_bus"].values.astype(int)
        hv_buses = trafos["hv_bus"].values.astype(int)
        lv_buses_ppc = bus_lookup[lv_buses]
        hv_buses_ppc = bus_lookup[hv_buses]
        mag0_percent = trafos.mag0_percent.values.astype(float)
        mag0_rx = trafos["mag0_rx"].values.astype(float)
        si0_hv_partial = trafos.si0_hv_partial.values.astype(float)
        parallel = trafos.parallel.values.astype(float)
        in_service = trafos["in_service"].astype(int)

        ppc["branch"][ppc_idx, F_BUS] = hv_buses_ppc
        ppc["branch"][ppc_idx, T_BUS] = lv_buses_ppc

        vn_trafo_hv, vn_trafo_lv, shift = _calc_tap_from_dataframe(net, trafos)
        vn_lv = ppc["bus"][lv_buses_ppc, BASE_KV]
        ratio = _calc_nominal_ratio_from_dataframe(ppc, trafos, vn_trafo_hv,
                                                   vn_trafo_lv, bus_lookup)
        ppc["branch"][ppc_idx, TAP] = ratio
        ppc["branch"][ppc_idx, SHIFT] = shift

        # zero seq. transformer impedance
        tap_lv = np.square(
            vn_trafo_lv / vn_lv
        ) * net.sn_mva  # adjust for low voltage side voltage converter
        z_sc = vk0_percent / 100. / sn_mva * tap_lv
        r_sc = vkr0_percent / 100. / sn_mva * tap_lv
        z_sc = z_sc.astype(float)
        r_sc = r_sc.astype(float)
        x_sc = np.sign(z_sc) * np.sqrt(z_sc**2 - r_sc**2)
        z0_k = (r_sc + x_sc * 1j) / parallel
        if mode == "sc":
            from pandapower.shortcircuit.idx_bus import C_MAX
            cmax = net._ppc["bus"][lv_buses_ppc, C_MAX]
            kt = _transformer_correction_factor(vk_percent, vkr_percent,
                                                sn_mva, cmax)
            z0_k *= kt
        y0_k = 1 / z0_k
        # zero sequence transformer magnetising impedance
        z_m = vk0_percent * mag0_percent / 100. / sn_mva * tap_lv
        x_m = z_m / np.sqrt(mag0_rx**2 + 1)
        r_m = x_m * mag0_rx
        r0_trafo_mag = r_m / parallel
        x0_trafo_mag = x_m / parallel
        z0_mag = r0_trafo_mag + x0_trafo_mag * 1j

        if vector_group == "Dyn":
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            gs_all = np.hstack([gs_all, y0_k.real * in_service])
            bs_all = np.hstack([bs_all, y0_k.imag * in_service])

        elif vector_group == "YNd":
            buses_all = np.hstack([buses_all, hv_buses_ppc])
            gs_all = np.hstack([gs_all, y0_k.real * in_service])
            bs_all = np.hstack([bs_all, y0_k.imag * in_service])

        elif vector_group == "Yyn":
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            y = 1 / (z0_mag + z0_k).astype(complex)
            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])

        elif vector_group == "YNyn":
            ppc["branch"][ppc_idx, BR_STATUS] = in_service
            # convert the t model to pi model
            z1 = si0_hv_partial * z0_k
            z2 = (1 - si0_hv_partial) * z0_k
            z3 = z0_mag

            z_temp = z1 * z2 + z2 * z3 + z1 * z3
            za = z_temp / z2
            zb = z_temp / z1
            zc = z_temp / z3

            ppc["branch"][ppc_idx, BR_R] = zc.real
            ppc["branch"][ppc_idx, BR_X] = zc.imag
            y = 2 / za
            ppc["branch"][ppc_idx, BR_B] = y.imag - y.real * 1j
            # add a shunt element parallel to zb if the leakage impedance distribution is unequal
            #TODO: this only necessary if si0_hv_partial!=0.5 --> test
            zs = (za * zb) / (za - zb)
            ys = 1 / zs.astype(complex)
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            gs_all = np.hstack([gs_all, ys.real * in_service])
            bs_all = np.hstack([bs_all, ys.imag * in_service])
        elif vector_group == "YNy":
            buses_all = np.hstack([buses_all, hv_buses_ppc])
            y = 1 / (z0_mag + z0_k).astype(complex)
            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])
        elif vector_group[-1].isdigit():
            raise ValueError(
                "Unknown transformer vector group %s - please specify vector group without phase shift number. Phase shift can be specified in net.trafo.shift_degree"
                % vector_group)
        else:
            raise ValueError(
                "Transformer vector group %s is unknown / not implemented" %
                vector_group)

    buses, gs, bs = aux._sum_by_group(buses_all, gs_all, bs_all)
    ppc["bus"][buses, GS] += gs
    ppc["bus"][buses, BS] += bs
    del net.trafo["_ppc_idx"]
    if False:
        # case_name = "test_case6495rte.json"
        bus_lv = 6195
        trafo_bug = pp_net.trafo.loc[pp_net.trafo["lv_bus"] == bus_lv]
        shunt_bug = pp_net.shunt.loc[pp_net.shunt["bus"] == bus_lv]
        bus_hv = int(trafo_bug["hv_bus"])
        me_val_hv_hv = Y_me[bus_hv, bus_hv]
        me_val_lv_lv = Y_me[bus_lv, bus_lv]
        pp_val_hv_hv = Y_pp_right_order[bus_hv, bus_hv]
        pp_val_lv_lv = Y_pp_right_order[bus_lv, bus_lv]
        np.abs(me_val_lv_lv / pp_val_lv_lv)
        np.abs(me_val_hv_hv / pp_val_hv_hv)

        # TODO add the first two lines (the function _calc_tap_from_dataframe) to the converter !
        from pandapower.build_branch import _calc_tap_from_dataframe
        vn_trafo_hv, vn_trafo_lv, shift = _calc_tap_from_dataframe(
            pp_net, pp_net.trafo)
        tap_angles = np.deg2rad(trafo_bug["tap_step_degree"].values)
        if ~np.isfinite(tap_angles):
            tap_angles = 0.
        vn = trafo_bug["vn_lv_kv"].values
        u1 = vn
        tap_steps = (trafo_bug["tap_pos"].values -
                     trafo_bug["tap_neutral"].values
                     ) * trafo_bug["tap_step_percent"].values / 100.
        du = u1 * tap_steps
        np.sqrt((u1 + du * np.cos(tap_angles))**2 +
                (du * np.sin(tap_angles))**2)
        pdb.set_trace()

    if False:
        if case_name == 'test_case2848rte.json':
Exemple #3
0
def _add_trafo_sc_impedance_zero(net, ppc, trafo_df=None):
    if trafo_df is None:
        trafo_df = net["trafo"]
    branch_lookup = net["_pd2ppc_lookups"]["branch"]
    if not "trafo" in branch_lookup:
        return
    bus_lookup = net["_pd2ppc_lookups"]["bus"]
    mode = net["_options"]["mode"]
    trafo_model = net["_options"]["trafo_model"]
    f, t = branch_lookup["trafo"]
    trafo_df["_ppc_idx"] = range(f, t)
    bus_lookup = net["_pd2ppc_lookups"]["bus"]
    buses_all, gs_all, bs_all = np.array([], dtype=int), np.array([]), \
                                np.array([])
    if not "vector_group" in trafo_df:
        raise ValueError(
            "Vector Group of transformer needs to be specified for zero \
                         sequence modelling \n Try : net.trafo[\"vector_group\"] = 'Dyn'"
        )

    for vector_group, trafos in trafo_df.groupby("vector_group"):
        ppc_idx = trafos["_ppc_idx"].values.astype(int)
        ppc["branch"][ppc_idx, BR_STATUS] = 0

        if vector_group in ["Yy", "Yd", "Dy", "Dd"]:
            continue

        vk_percent = trafos["vk_percent"].values.astype(float)
        vkr_percent = trafos["vkr_percent"].values.astype(float)
        sn_mva = trafos["sn_mva"].values.astype(float)
        # Just put pos seq parameter if zero seq parameter is zero
        if not "vk0_percent" in trafos:
            raise ValueError(
                "Short circuit voltage of transformer Vk0 needs to be specified for zero \
                             sequence modelling \n Try : net.trafo[\"vk0_percent\"] = net.trafo[\"vk_percent\"]"
            )
        vk0_percent = trafos["vk0_percent"].values.astype(float) if \
            trafos["vk0_percent"].values.astype(float).all() != 0. else \
            trafos["vk_percent"].values.astype(float)
        # Just put pos seq parameter if zero seq parameter is zero
        if not "vkr0_percent" in trafos:
            raise ValueError(
                "Real part of short circuit voltage Vk0(Real) needs to be specified for transformer \
                             modelling \n Try : net.trafo[\"vkr0_percent\"] = net.trafo[\"vkr_percent\"]"
            )
        vkr0_percent = trafos["vkr0_percent"].values.astype(float) if \
            trafos["vkr0_percent"].values.astype(float).all() != 0. else \
            trafos["vkr_percent"].values.astype(float)
        lv_buses = trafos["lv_bus"].values.astype(int)
        hv_buses = trafos["hv_bus"].values.astype(int)
        lv_buses_ppc = bus_lookup[lv_buses]
        hv_buses_ppc = bus_lookup[hv_buses]
        if not "mag0_percent" in trafos:
            # For Shell Type transformers vk0 = vk * 1
            #        and mag0_percent = 10 ... 100  Zm0/ Zsc0
            # --pg 50 DigSilent Power Factory Transformer manual
            raise ValueError(
                "Magnetizing impedance to vk0 ratio needs to be specified for transformer \
                             modelling  \n Try : net.trafo[\"mag0_percent\"] = 100"
            )
        mag0_ratio = trafos.mag0_percent.values.astype(float)
        if not "mag0_rx" in trafos:
            raise ValueError(
                "Magnetizing impedance R/X ratio needs to be specified for transformer \
                             modelling \n Try : net.trafo[\"mag0_rx\"] = 0 ")
        mag0_rx = trafos["mag0_rx"].values.astype(float)
        if not "si0_hv_partial" in trafos:
            raise ValueError(
                "Zero sequence short circuit impedance partition towards HV side needs to be specified for transformer \
                             modelling \n Try : net.trafo[\"si0_hv_partial\"] = 0.9 "
            )
        si0_hv_partial = trafos.si0_hv_partial.values.astype(float)
        parallel = trafos.parallel.values.astype(float)
        in_service = trafos["in_service"].astype(int)

        ppc["branch"][ppc_idx, F_BUS] = hv_buses_ppc
        ppc["branch"][ppc_idx, T_BUS] = lv_buses_ppc

        vn_trafo_hv, vn_trafo_lv, shift = _calc_tap_from_dataframe(net, trafos)
        vn_lv = ppc["bus"][lv_buses_ppc, BASE_KV]
        ratio = _calc_nominal_ratio_from_dataframe(ppc, trafos, vn_trafo_hv, \
                                                   vn_trafo_lv, bus_lookup)
        ppc["branch"][ppc_idx, TAP] = ratio
        ppc["branch"][ppc_idx, SHIFT] = shift

        # zero seq. transformer impedance
        tap_lv = np.square(vn_trafo_lv / vn_lv) * net.sn_mva
        if mode == 'pf_3ph':
            # =============================================================================
            #     Changing base from transformer base to Network base to get Zpu(Net)
            #     Zbase = (kV).squared/S_mva
            #     Zpu(Net)={Zpu(trafo) * Zb(trafo)} / {Zb(Net)}
            #        Note:
            #             Network base voltage is Line-Neutral voltage in each phase
            #             Line-Neutral voltage= Line-Line Voltage(vn_lv) divided by sq.root(3)
            # =============================================================================
            tap_lv = np.square(vn_trafo_lv / vn_lv) * (3 * net.sn_mva)

        z_sc = vk0_percent / 100. / sn_mva * tap_lv
        r_sc = vkr0_percent / 100. / sn_mva * tap_lv
        z_sc = z_sc.astype(float)
        r_sc = r_sc.astype(float)
        x_sc = np.sign(z_sc) * np.sqrt(z_sc**2 - r_sc**2)
        z0_k = (r_sc + x_sc * 1j) / parallel
        y0_k = 1 / z0_k  #adding admittance for "pi" model
        if mode == "sc":  # or trafo_model == "pi":
            from pandapower.shortcircuit.idx_bus import C_MAX
            cmax = net._ppc["bus"][lv_buses_ppc, C_MAX]
            kt = _transformer_correction_factor(vk_percent, vkr_percent, \
                                                sn_mva, cmax)
            z0_k *= kt
            y0_k = 1 / z0_k
        # =============================================================================
        #       Transformer magnetising impedance for zero sequence
        # =============================================================================
        z_m = z_sc * mag0_ratio
        x_m = z_m / np.sqrt(mag0_rx**2 + 1)
        r_m = x_m * mag0_rx
        r0_trafo_mag = r_m / parallel
        x0_trafo_mag = x_m / parallel
        z0_mag = r0_trafo_mag + x0_trafo_mag * 1j
        # =============================================================================
        #         Star - Delta conversion ( T model to Pi Model)
        #      ----------- |__zc=ZAB__|-----------------
        #            _|                   _|
        #     za=ZAN|_|                  |_| zb=ZBN
        #            |                    |
        # =============================================================================
        z1 = si0_hv_partial * z0_k
        z2 = (1 - si0_hv_partial) * z0_k
        z3 = z0_mag
        z_temp = z1 * z2 + z2 * z3 + z1 * z3
        za = z_temp / z2
        #        za = z_temp / (z2+z3)
        zb = z_temp / z1
        #        zb = z_temp / (z1+z3)
        zc = z_temp / z3  # ZAB  Transfer impedance
        #        zc = z_temp / (z1+z2)  # ZAB  Transfer impedance
        YAB = 1 / zc.astype(complex)
        YAN = 1 / za.astype(complex)
        YBN = 1 / zb.astype(complex)

        #        YAB_AN = (zc + za) /(zc * za).astype(complex)  # Series conn YAB and YAN
        #        YAB_BN = (zc + zb) / (zc * zb).astype(complex)  # Series conn YAB and YBN

        YAB_AN = 1 / (zc + za).astype(complex)  # Series conn YAB and YAN
        YAB_BN = 1 / (zc + zb).astype(complex)  # Series conn YAB and YBN

        if vector_group == "Dyn":
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            if trafo_model == "pi":
                y = y0_k  # pi model
            else:
                y = (YAB + YBN).astype(complex) * int(
                    ppc["baseMVA"])  # T model
            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])

        elif vector_group == "YNd":
            buses_all = np.hstack([buses_all, hv_buses_ppc])
            if trafo_model == "pi":
                y = y0_k  # pi model
            else:
                y = (YAB_BN + YAN).astype(complex) * int(
                    ppc["baseMVA"])  #T model
            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])

        elif vector_group == "Yyn":
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            if trafo_model == "pi":
                y = 1 / (z0_mag + z0_k).astype(complex) * int(
                    ppc["baseMVA"])  #pi model
            else:
                #                y = (YAB_AN + YBN).astype(complex) * int(ppc["baseMVA"]) #T model
                print(YAB, YAB_AN, YAB_BN, YBN)
                y = (YAB + YAB_BN + YBN).astype(complex) * int(
                    ppc["baseMVA"])  # T model

            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])

        elif vector_group == "YNyn":
            ppc["branch"][ppc_idx, BR_STATUS] = in_service
            # zc = ZAB
            ppc["branch"][ppc_idx, BR_R] = zc.real
            ppc["branch"][ppc_idx, BR_X] = zc.imag

            buses_all = np.hstack([buses_all, hv_buses_ppc])
            gs_all = np.hstack([gs_all, YAN.real * in_service \
                                * int(ppc["baseMVA"])])
            bs_all = np.hstack([bs_all, YAN.imag * in_service \
                                * int(ppc["baseMVA"])])

            buses_all = np.hstack([buses_all, lv_buses_ppc])
            gs_all = np.hstack([gs_all, YBN.real * in_service \
                                * int(ppc["baseMVA"])])
            bs_all = np.hstack([bs_all, YBN.imag * in_service \
                                * int(ppc["baseMVA"])])

        elif vector_group == "YNy":
            buses_all = np.hstack([buses_all, hv_buses_ppc])
            if trafo_model == "pi":
                y = 1 / (z0_mag + z0_k).astype(complex) * int(
                    ppc["baseMVA"])  #pi model
            else:
                y = (YAB_BN + YAN).astype(complex) * int(
                    ppc["baseMVA"])  #T model
            gs_all = np.hstack([gs_all, y.real * in_service])
            bs_all = np.hstack([bs_all, y.imag * in_service])

        elif vector_group == "Yzn":
            buses_all = np.hstack([buses_all, lv_buses_ppc])
            #            y = 1/(z0_mag+z0_k).astype(complex)* int(ppc["baseMVA"])#T model
            #            y= (za+zb+zc)/((za+zc)*zb).astype(complex)* int(ppc["baseMVA"])#pi model
            y = (YAB_AN + YBN).astype(complex) * int(ppc["baseMVA"])  #T model
            gs_all = np.hstack([gs_all, (1.1547) * y.real * in_service \
                                * int(ppc["baseMVA"])])
            bs_all = np.hstack([bs_all, (1.1547) * y.imag * in_service \
                                * int(ppc["baseMVA"])])

        elif vector_group[-1].isdigit():
            raise ValueError("Unknown transformer vector group %s -\
                             please specify vector group without \
                             phase shift number. Phase shift can be \
                             specified in net.trafo.shift_degree" %
                             vector_group)
        else:
            raise ValueError("Transformer vector group %s is unknown\
                    / not implemented for three phase load flow" %
                             vector_group)

    buses, gs, bs = aux._sum_by_group(buses_all, gs_all, bs_all)
    ppc["bus"][buses, GS] += gs
    ppc["bus"][buses, BS] += bs
    del net.trafo["_ppc_idx"]
    def _aux_test(self, pn_net):
        with tempfile.TemporaryDirectory() as path:
            case_name = os.path.join(path, "this_case.json")
            pp.to_json(pn_net, case_name)

            real_init_file = pp.from_json(case_name)
            backend = LightSimBackend()
            with warnings.catch_warnings():
                warnings.filterwarnings("ignore")
                backend.load_grid(case_name)

        nb_sub = backend.n_sub
        pp_net = backend.init_pp_backend._grid
        # first i deactivate all slack bus in pp that are connected but not handled in ls
        pp_net.ext_grid["in_service"].loc[:] = False
        pp_net.ext_grid["in_service"].iloc[0] = True
        conv = backend.runpf()
        conv_pp = backend.init_pp_backend.runpf()

        assert conv_pp, "Error: pandapower do not converge, impossible to perform the necessary checks"
        assert conv, "Error: lightsim do not converge"

        por_pp, qor_pp, vor_pp, aor_pp = copy.deepcopy(
            backend.init_pp_backend.lines_or_info())
        pex_pp, qex_pp, vex_pp, aex_pp = copy.deepcopy(
            backend.init_pp_backend.lines_ex_info())

        # I- Check for divergence and equality of flows"
        por_ls, qor_ls, vor_ls, aor_ls = backend.lines_or_info()
        max_mis = np.max(np.abs(por_ls - por_pp))
        assert max_mis <= self.tol, f"Error: por do not match, maximum absolute error is {max_mis:.5f} MW"
        max_mis = np.max(np.abs(qor_ls - qor_pp))
        assert max_mis <= self.tol, f"Error: qor do not match, maximum absolute error is {max_mis:.5f} MVAr"
        max_mis = np.max(np.abs(vor_ls - vor_pp))
        assert max_mis <= self.tol, f"Error: vor do not match, maximum absolute error is {max_mis:.5f} kV"
        max_mis = np.max(np.abs(aor_ls - aor_pp))
        assert max_mis <= self.tol, f"Error: aor do not match, maximum absolute error is {max_mis:.5f} A"

        # "II - Check for possible solver issues"
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore")
            pp.runpp(backend.init_pp_backend._grid, v_debug=True)
        v_tmp = backend.init_pp_backend._grid.res_bus[
            "vm_pu"].values[:nb_sub] + 0j
        v_tmp *= np.exp(
            1j * np.pi / 180. *
            backend.init_pp_backend._grid.res_bus["va_degree"].values[:nb_sub])
        v_tmp = np.concatenate((v_tmp, v_tmp))
        backend._grid.ac_pf(v_tmp, 1000, 1e-5)

        Y_pp = backend.init_pp_backend._grid._ppc["internal"]["Ybus"]
        Sbus = backend.init_pp_backend._grid._ppc["internal"]["Sbus"]
        pv_ = backend.init_pp_backend._grid._ppc["internal"]["pv"]
        pq_ = backend.init_pp_backend._grid._ppc["internal"]["pq"]
        max_iter = 10
        tol_this = 1e-8
        All_Vms = backend.init_pp_backend._grid._ppc["internal"]["Vm_it"]
        AllVas = backend.init_pp_backend._grid._ppc["internal"]["Va_it"]

        for index_V in range(All_Vms.shape[1] - 1, -1, -1):
            nb_iter = All_Vms.shape[1] - 1
            # i check from easiest to hardest, so from the last iteartion of pandapower to the first iteration of pandapower
            # take the same V as pandapower
            V_init = All_Vms[:, index_V] * (np.cos(AllVas[:, index_V]) +
                                            1j * np.sin(AllVas[:, index_V]))
            # V_init *= np.exp(1j * AllVas[:, 0])
            V_init_ref = copy.deepcopy(V_init)
            solver = ClassSolver()
            solver.solve(scipy.sparse.csc_matrix(Y_pp), V_init, Sbus, pv_, pq_,
                         max_iter, tol_this)
            time_for_nr = solver.get_timers()[3]
            if TIMER_INFO:
                print(
                    f"\t Info: Time to perform {nb_iter - index_V} NR iterations for a grid with {nb_sub} "
                    f"buses: {1000. * time_for_nr:.2f}ms")
            error_va = np.abs(
                solver.get_Va() -
                np.angle(backend.init_pp_backend._grid._ppc["internal"]["V"]))
            assert np.max(error_va) <= self.tol, f"Error: VA do not match for iteration {index_V}, maximum absolute " \
                                                 f"error is {np.max(error_va):.5f} rad"

            error_vm = np.abs(
                np.abs(solver.get_Vm() - np.abs(
                    backend.init_pp_backend._grid._ppc["internal"]["V"])))
            assert np.max(error_vm) <= self.tol, f"\t Error: VM do not match for iteration {index_V}, maximum absolute " \
                                                 f"error  is {np.max(error_vm):.5f} pu"
            solver.reset()

        if TIMER_INFO:
            print("")

        # 'III - Check the data conversion'
        pp_vect_converter = backend.init_pp_backend._grid._pd2ppc_lookups[
            "bus"][:nb_sub]
        pp_net = backend.init_pp_backend._grid

        # 1) Checking Sbus conversion
        Sbus_pp = backend.init_pp_backend._grid._ppc["internal"]["Sbus"]
        Sbus_pp_right_order = Sbus_pp[pp_vect_converter]
        Sbus_me = backend._grid.get_Sbus()
        error_p = np.abs(np.real(Sbus_me) - np.real(Sbus_pp_right_order))
        assert np.max(error_p) <= self.tol, f"\t Error: P do not match for Sbus, maximum absolute error is " \
                                            f"{np.max(error_p):.5f} MW, \t Error: significative difference for bus " \
                                            f"index (lightsim): {np.where(error_p > self.tol)[0]}"

        error_q = np.abs(np.imag(Sbus_me) - np.imag(Sbus_pp_right_order))
        assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Sbus, maximum absolute error is " \
                                            f"{np.max(error_q):.5f} MVAr, \t Error: significative difference for bus " \
                                            f"index (lightsim): {np.where(error_q > self.tol)[0]}"

        # 2)  Checking Ybus conversion"
        Y_me = backend._grid.get_Ybus()
        Y_pp = backend.init_pp_backend._grid._ppc["internal"]["Ybus"]
        Y_pp_right_order = Y_pp[pp_vect_converter.reshape(nb_sub, 1),
                                pp_vect_converter.reshape(1, nb_sub)]
        error_p = np.abs(np.real(Y_me) - np.real(Y_pp_right_order))
        assert np.max(error_p) <= self.tol, f"Error: P do not match for Ybus, maximum absolute error " \
                                            f"is {np.max(error_p):.5f}"

        error_q = np.abs(np.imag(Y_me) - np.imag(Y_pp_right_order))
        assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Ybus, maximum absolute error is " \
                                            f"{np.max(error_q):.5f}"

        # "IV - Check for the initialization (dc powerflow)"
        # 1) check that the results are same for dc lightsim and dc pandapower
        Vinit = np.ones(backend.nb_bus_total,
                        dtype=np.complex_) * pp_net["_options"]["init_vm_pu"]
        backend._grid.deactivate_result_computation()
        Vdc = backend._grid.dc_pf(Vinit, max_iter, tol_this)
        backend._grid.reactivate_result_computation()
        Ydc_me = backend._grid.get_Ybus()
        Sdc_me = backend._grid.get_Sbus()
        assert np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])) <= 100.*self.tol,\
            f"\t Error for the DC approximation: resulting voltages are different " \
            f"{np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])):.5f}pu"

        if np.max(np.abs(V_init_ref[pp_vect_converter] -
                         Vdc[:nb_sub])) >= self.tol:
            warnings.warn(
                "\t Warning: maximum difference after DC approximation is "
                "{np.max(np.abs(V_init_ref[pp_vect_converter] - Vdc[:nb_sub])):.5f} which is higher than "
                "the tolerance (this is just a warning because we noticed this could happen even if the "
                "results match perfectly. Probably some conversion issue with complex number and "
                "radian / degree.")
        # "2) check that the Sbus vector is same for PP and lightisim in DC"
        from pandapower.pd2ppc import _pd2ppc
        from pandapower.pf.run_newton_raphson_pf import _get_pf_variables_from_ppci
        from pandapower.pypower.idx_brch import F_BUS, T_BUS, BR_X, TAP, SHIFT, BR_STATUS
        from pandapower.pypower.idx_bus import VA, GS
        from pandapower.pypower.makeBdc import makeBdc
        from pandapower.pypower.makeSbus import makeSbus

        pp_net._pd2ppc_lookups = {
            "bus": np.array([], dtype=int),
            "ext_grid": np.array([], dtype=int),
            "gen": np.array([], dtype=int),
            "branch": np.array([], dtype=int)
        }
        # convert pandapower net to ppc
        ppc, ppci = _pd2ppc(pp_net)
        baseMVA, bus, gen, branch, ref, pv, pq, on, gbus, _, refgen = _get_pf_variables_from_ppci(
            ppci)
        Va0 = bus[:, VA] * (np.pi / 180.)
        B, Bf, Pbusinj, Pfinj = makeBdc(bus, branch)

        Pbus = makeSbus(baseMVA, bus, gen) - Pbusinj - bus[:, GS] / baseMVA
        Pbus_pp_ro = Pbus[pp_vect_converter]
        error_p = np.abs(np.real(Sdc_me) - np.real(Pbus_pp_ro))
        test_ok = True

        #### pandapower DC algo (yet another one)
        Va = copy.deepcopy(Va0)
        pvpq = np.r_[pv, pq]
        pvpq_matrix = B[pvpq.T, :].tocsc()[:, pvpq]
        ref_matrix = np.transpose(Pbus[pvpq] -
                                  B[pvpq.T, :].tocsc()[:, ref] * Va0[ref])
        Va[pvpq] = np.real(scipy.sparse.linalg.spsolve(pvpq_matrix,
                                                       ref_matrix))
        ####

        assert np.max(error_p) <= self.tol, f"\t Error: P do not match for Sbus (dc), maximum absolute error is " \
                                            f"{np.max(error_p):.5f} MW, \nError: significative difference for bus " \
                                            f"index (lightsim): {np.where(error_p > self.tol)[0]}"

        error_q = np.abs(np.imag(Sdc_me) - np.imag(Pbus_pp_ro))
        assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Sbus (dc), maximum absolute error is " \
                                            f"{np.max(error_q):.5f} MVAr, \n\t Error: significative difference for " \
                                            f"bus index (lightsim): {np.where(error_q > self.tol)[0]}"

        # "3) check that the Ybus matrix is same for PP and lightisim in DC"
        with warnings.catch_warnings():
            warnings.filterwarnings("ignore")
            pp.rundcpp(pp_net)
        Ydc_pp = backend.init_pp_backend._grid._ppc["internal"]["Bbus"]
        Ydc_pp_right_order = Ydc_pp[pp_vect_converter.reshape(nb_sub, 1),
                                    pp_vect_converter.reshape(1, nb_sub)]
        error_p = np.abs(np.real(Ydc_me) - np.real(Ydc_pp_right_order))
        assert np.max(error_p) <= self.tol, f"Error: P do not match for Ybus (dc mode), maximum absolute error " \
                                            f"is {np.max(error_p):.5f}"
        error_q = np.abs(np.imag(Ydc_me) - np.imag(Ydc_pp_right_order))
        assert np.max(error_q) <= self.tol, f"\t Error: Q do not match for Ybus (dc mdoe), maximum absolute error " \
                                            f"is {np.max(error_q):.5f}"

        # "3) check that lightsim ac pf init with pp dc pf give same results (than pp)"
        Vinit = np.ones(backend.nb_bus_total,
                        dtype=np.complex_) * pp_net["_options"]["init_vm_pu"]
        Vinit[:nb_sub] = V_init_ref[pp_vect_converter]
        conv = backend._grid.ac_pf(Vinit, max_iter, tol_this)
        assert conv.shape[
            0] > 0, "\t Error: the lightsim diverge when initialized with pandapower Vinit_dc"
        lpor, lqor, lvor, laor = backend._grid.get_lineor_res()
        tpor, tqor, tvor, taor = backend._grid.get_trafohv_res()
        tpex, tqex, tvex, taex = backend._grid.get_trafolv_res()
        nb_trafo = tpor.shape[0]
        nb_powerline = lpor.shape[0]
        p_or_me2 = np.concatenate((lpor, tpor))
        q_or_me2 = np.concatenate((lqor, tqor))
        v_or_me2 = np.concatenate((lvor, tvor))
        a_or_me2 = 1000. * np.concatenate((laor, taor))
        test_ok = True
        # pdb.set_trace()
        max_mis = np.max(np.abs(p_or_me2 - por_pp))
        assert np.max(
            error_q
        ) <= self.tol, f"\t Error: por do not match, maximum absolute error is {max_mis:.5f} MW"
        max_mis = np.max(np.abs(q_or_me2 - qor_pp))
        assert np.max(
            error_q
        ) <= self.tol, f"\t Error: qor do not match, maximum absolute error is {max_mis:.5f} MVAr"
        max_mis = np.max(np.abs(v_or_me2 - vor_pp))
        assert np.max(
            error_q
        ) <= self.tol, f"\t Error: vor do not match, maximum absolute error is {max_mis:.5f} kV"
        max_mis = np.max(np.abs(a_or_me2 - aor_pp))
        assert np.max(
            error_q
        ) <= self.tol, f"\t Error: aor do not match, maximum absolute error is {max_mis:.5f} A"

        # "V - Check trafo proper conversion to r,x, b"
        from lightsim2grid_cpp import GridModel, PandaPowerConverter, SolverType
        from pandapower.build_branch import _calc_branch_values_from_trafo_df, get_trafo_values
        from pandapower.build_branch import _calc_nominal_ratio_from_dataframe, _calc_r_x_y_from_dataframe
        from pandapower.build_branch import _calc_tap_from_dataframe, BASE_KV, _calc_r_x_from_dataframe

        # my trafo parameters
        converter = PandaPowerConverter()
        converter.set_sn_mva(pp_net.sn_mva)
        converter.set_f_hz(pp_net.f_hz)
        tap_neutral = 1.0 * pp_net.trafo["tap_neutral"].values
        tap_neutral[~np.isfinite(tap_neutral)] = 0.
        if np.any(tap_neutral != 0.):
            raise RuntimeError(
                "lightsim converter supposes that tap_neutral is 0 for the transformers"
            )
        tap_step_pct = 1.0 * pp_net.trafo["tap_step_percent"].values
        tap_step_pct[~np.isfinite(tap_step_pct)] = 0.
        tap_pos = 1.0 * pp_net.trafo["tap_pos"].values
        tap_pos[~np.isfinite(tap_pos)] = 0.
        shift_ = 1.0 * pp_net.trafo["shift_degree"].values
        shift_[~np.isfinite(shift_)] = 0.
        is_tap_hv_side = pp_net.trafo["tap_side"].values == "hv"
        is_tap_hv_side[~np.isfinite(is_tap_hv_side)] = True
        if np.any(pp_net.trafo["tap_phase_shifter"].values):
            raise RuntimeError(
                "ideal phase shifter are not modeled. Please remove all trafo with "
                "pp_net.trafo[\"tap_phase_shifter\"] set to True.")
        tap_angles_ = 1.0 * pp_net.trafo["tap_step_degree"].values
        tap_angles_[~np.isfinite(tap_angles_)] = 0.
        tap_angles_ = np.deg2rad(tap_angles_)
        trafo_r, trafo_x, trafo_b = \
            converter.get_trafo_param(tap_step_pct,
                                      tap_pos,
                                      tap_angles_,  # in radian !
                                      is_tap_hv_side,
                                      pp_net.bus.loc[pp_net.trafo["hv_bus"]]["vn_kv"],
                                      pp_net.bus.loc[pp_net.trafo["lv_bus"]]["vn_kv"],
                                      pp_net.trafo["vk_percent"].values,
                                      pp_net.trafo["vkr_percent"].values,
                                      pp_net.trafo["sn_mva"].values,
                                      pp_net.trafo["pfe_kw"].values,
                                      pp_net.trafo["i0_percent"].values,
                                      )
        # pandapower trafo parameters
        ppc = copy.deepcopy(pp_net._ppc)
        bus_lookup = pp_net["_pd2ppc_lookups"]["bus"]
        trafo_df = pp_net["trafo"]
        lv_bus = get_trafo_values(trafo_df, "lv_bus")
        vn_lv = ppc["bus"][bus_lookup[lv_bus], BASE_KV]
        vn_trafo_hv, vn_trafo_lv, shift_pp = _calc_tap_from_dataframe(
            pp_net, trafo_df)
        ratio = _calc_nominal_ratio_from_dataframe(ppc, trafo_df, vn_trafo_hv,
                                                   vn_trafo_lv, bus_lookup)
        r_t, x_t, b_t = _calc_r_x_y_from_dataframe(pp_net, trafo_df,
                                                   vn_trafo_lv, vn_lv,
                                                   pp_net.sn_mva)

        # check where there are mismatch if any
        val_r_pp = r_t
        val_r_me = trafo_r
        all_equals_r = np.abs(val_r_pp - val_r_me) <= self.tol
        if not np.all(all_equals_r):
            test_ok = False
            print(
                f"\t Error: some trafo resistance are not equal, max error: {np.max(np.abs(val_r_pp - val_r_me)):.5f}"
            )

        val_x_pp = x_t
        val_x_me = trafo_x
        all_equals_x = np.abs(val_x_pp - val_x_me) <= self.tol
        assert np.all(all_equals_x), f"\t Error: some trafo x are not equal, max error: " \
                                     f"{np.max(np.abs(val_x_pp - val_x_me)):.5f}"

        val_ib_pp = np.imag(b_t)
        val_ib_me = np.imag(trafo_b)
        all_equals_imag_b = np.abs(val_ib_pp - val_ib_me) <= self.tol
        assert np.all(all_equals_imag_b), f"\t Error: some trafo (imag) b are not equal, max error: " \
                                          f"{np.max(np.abs(val_ib_pp - val_ib_me)):.5f}"

        val_reb_pp = np.real(b_t)
        val_reb_me = np.real(trafo_b)
        all_equals_real_b = np.abs(val_reb_pp - val_reb_me) <= self.tol
        assert np.all(all_equals_real_b), f"\t Error: some trafo (real) b are not equal, max error: " \
                                          f"{np.max(np.abs(val_reb_pp - val_reb_me)):.5f}"