Bi-directional converter

A single-phase bi-directional voltage source conveter is connected to an AC voltage source through an impedance $Z = R + j\,\omega\,L$ with $R=0.1\,\Omega$ and $L=10\,$mH. The output voltage of the converter $V_{BD}$ is a quasi-square wave with fundamental frequency $50\,$Hz. The DC source voltage is $400\,$V. If $\alpha = 30^{\circ}$ and $v_s(t) = 325\,\sin(100\,\pi\,t - 30^{\circ})\,$V, what is the RMS value of the fundamental component of the current through the AC source? Draw the fundamental and fifth harmonic phasor diagram showing the relationship between inverter voltage, grid voltage, and the voltage across the inductor. (Follow the convention that $\sin\,\omega\,t$ corresponds to the phasor $1\angle{0}$.)
In [1]:
from IPython.display import Image
Image(filename =r'VSC_bi_6_fig_1.png', width=700)
Out[1]:
No description has been provided for this image
In [2]:
# run this cell to view the circuit file.
%pycat VSC_bi_6_orig.in

We now replace the strings such as \$Vdc, \$L, with the values of our choice by running the python script given below. It takes an existing circuit file VSC_bi_6_orig.in and produces a new circuit file VSC_bi_6.in, after replacing \$Vdc, \$L, etc. with values of our choice.

In [3]:
import gseim_calc as calc
s_Vdc = '400'
s_R = '0.1'
s_L = '10e-3'
s_A_sin = '325'

s_f_hz = '50'
f_hz = float(s_f_hz)

alpha = 30.0
s_phi = ("%11.4E"%(-alpha)).strip()
T = 1/f_hz
d = 180.0 - 2.0*alpha
t0_1 = (alpha/360)*T
t0_2 = t0_1 + (d/360)*T

s_t0_1 = ("%11.4E"%(t0_1)).strip()
s_t0_2 = ("%11.4E"%(t0_2)).strip()

l = [
  ('$Vdc', s_Vdc),
  ('$R', s_R),
  ('$L', s_L),
  ('$phi', s_phi),
  ('$A_sin', s_A_sin),
  ('$f_hz', s_f_hz),
  ('$t0_1', s_t0_1),
  ('$t0_2', s_t0_2)
]
calc.replace_strings_1("VSC_bi_6_orig.in", "VSC_bi_6.in", l)
print('VSC_bi_6.in is ready for execution')
VSC_bi_6.in is ready for execution
Execute the following cell to run GSEIM on VSC_bi_6.in.
In [4]:
import os
import dos_unix
# uncomment for windows:
#dos_unix.d2u("VSC_bi_6.in")
os.system('run_gseim VSC_bi_6.in')
Circuit: filename = VSC_bi_6.in
main: i_solve = 0
main: calling solve_ssw
mat_ssw_1_ex: n_statevar: 1
Transient simulation starts...
i=0
i=1000
solve_ssw_ex: ssw_iter_newton=0, ssw_period_1_compute=4.0000e-02, rhs_ssw_norm=1.3785e+01
Transient simulation starts...
i=0
i=1000
solve_ssw_ex: ssw_iter_newton=1, ssw_period_1_compute=4.0000e-02, rhs_ssw_norm=1.2150e-12
solve_ssw_ex: calling solve_ssw_1_ex for one more trns step
Transient simulation starts...
i=0
i=1000
solve_ssw_ex over (after trns step for output)
solve_ssw_ex ends, slv.ssw_iter_newton=1
GSEIM: Program completed.
Out[4]:
0

The circuit file (VSC_bi_6.in) is created in the same directory as that used for launching Jupyter notebook. The last step (i.e., running GSEIM on VSC_bi_6.in) creates a data file called VSC_bi_6.datin the same directory. We can now use the python code below to compute/plot the various quantities of interest.

In [5]:
import numpy as np
import matplotlib.pyplot as plt 
import gseim_calc as calc
from setsize import set_size

slv = calc.slv("VSC_bi_6.in")

i_slv = 0
i_out = 0
filename = slv.l_filename_all[i_slv][i_out]
print('filename:', filename)
u = np.loadtxt(filename)
t = u[:, 0]

v_BD = slv.get_array_double(i_slv,i_out,"v_BD",u)
v_ac = slv.get_array_double(i_slv,i_out,"v_ac",u)
IL   = slv.get_array_double(i_slv,i_out,"IL",u)
g1   = slv.get_array_double(i_slv,i_out,"g1",u)
g2   = slv.get_array_double(i_slv,i_out,"g2",u)
g3   = slv.get_array_double(i_slv,i_out,"g3",u)
g4   = slv.get_array_double(i_slv,i_out,"g4",u)

# since we have stored two cycles, we need to divide the last time point
# by 2 to get the period:

T = t[-1]/2

fig, ax = plt.subplots(3, sharex=False)
plt.subplots_adjust(wspace=0, hspace=0.0)

set_size(6.5, 7, ax[0])

for i in range(3):
    ax[i].set_xlim(left=0.0, right=2.0*T*1e3)
    ax[i].grid(color='#CCCCCC', linestyle='solid', linewidth=0.5)

ax[0].set_ylabel(r'$g_x$'   , fontsize=12)
ax[1].set_ylabel(r'$v_{BD}$', fontsize=12)
ax[2].set_ylabel(r'$i_L$'   , fontsize=12)

ax[0].tick_params(labelbottom=False)
ax[1].tick_params(labelbottom=False)

color1 = "tomato"
color2 = "dodgerblue"
color3 = "olive"
color4 = "blue"
color5 = "crimson"
color6 = "green"

ax[0].plot(t*1e3, (g1      ), color=color1, linewidth=1.0, label="$g_1$")
ax[0].plot(t*1e3, (g2 - 1.5), color=color2, linewidth=1.0, label="$g_2$")
ax[0].plot(t*1e3, (g3 - 3.0), color=color3, linewidth=1.0, label="$g_3$")
ax[0].plot(t*1e3, (g4 - 4.5), color=color4, linewidth=1.0, label="$g_4$")

ax[0].tick_params(left = False)
ax[0].set_yticks([])

ax[1].plot(t*1e3, v_BD, color=color5, linewidth=1.0, label="$v_{BD}$")
ax[1].plot(t*1e3, v_ac, color=color3, linewidth=1.0, label="$v_{ac}$")
ax[2].plot(t*1e3, IL  , color=color6, linewidth=1.0, label="$i_L$")

ax[2].set_xlabel('time (msec)', fontsize=12)

for k in range(2):
    ax[k].legend(loc = 'lower right',frameon = True, fontsize = 10, title = None,
      markerfirst = True, markerscale = 1.0, labelspacing = 0.5, columnspacing = 2.0,
      prop = {'size' : 12})

#plt.tight_layout()
plt.show()
filename: VSC_bi_6.dat
No description has been provided for this image
In [6]:
import numpy as np
import matplotlib.pyplot as plt
import gseim_calc as calc
from setsize import set_size

slv = calc.slv("VSC_bi_6.in")

i_slv = 0
i_out = 0
filename = slv.l_filename_all[i_slv][i_out]
print('filename:', filename)
u = np.loadtxt(filename)
t = u[:, 0]

v_BD = slv.get_array_double(i_slv,i_out,"v_BD",u)
IL   = slv.get_array_double(i_slv,i_out,"IL",u)

T = t[-1]/2

t_start = 0.0
t_end = T

n_fourier = 20
coeff_IL, thd_IL = calc.fourier_coeff_1C(t, IL, 
    t_start, t_end, 1.0e-4*T, n_fourier)
print("IL fundamental: RMS value: ", "%11.4E"%(coeff_IL[1]/np.sqrt(2.0)))

coeff_v_BD, thd_v_BD = calc.fourier_coeff_1C(t, v_BD,
    t_start, t_end, 1.0e-4*T, n_fourier)

x_IL   = np.linspace(0, n_fourier, n_fourier+1)
x_v_BD = np.linspace(0, n_fourier, n_fourier+1)

y_IL   = np.array(coeff_IL)
y_v_BD = np.array(coeff_v_BD)

fig, ax = plt.subplots(2, sharex=False)

bars1 = ax[0].bar(x_IL  , y_IL  , width=0.3, color='red' , label="$i_L$")
bars2 = ax[1].bar(x_v_BD, y_v_BD, width=0.3, color='blue', label="$V_{BD}$")

ax[0].set_ylabel('$i_L$'   , fontsize=11)
ax[1].set_ylabel('$v_{BD}$', fontsize=11)

for k in range(2):
    ax[k].set_xlabel('N', fontsize=11)
    ax[k].set_xlim(left=0, right=n_fourier)
    ax[k].xaxis.set_ticks(np.arange(0, n_fourier, 2))
    ax[k].legend(loc = 'upper right',frameon = True, fontsize = 10, title = None,
      markerfirst = True, markerscale = 1.0, labelspacing = 0.5, columnspacing = 2.0,
      prop = {'size' : 12},)

plt.tight_layout()
plt.show()
filename: VSC_bi_6.dat
IL fundamental: RMS value:   5.0899E+01
No description has been provided for this image
In [7]:
import numpy as np
import gseim_calc as calc
import os
import dos_unix
import cmath
import matplotlib.pyplot as plt 
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)
from setsize import set_size

slv = calc.slv("VSC_bi_6.in")

i_slv = 0
i_out = 0
filename = slv.l_filename_all[i_slv][i_out]
print('filename:', filename)
u = np.loadtxt(filename)
t = u[:, 0]
t0 = t[0]
t = t - t0

v_ac = slv.get_array_double(i_slv,i_out,"v_ac",u)
v_BD = slv.get_array_double(i_slv,i_out,"v_BD",u)
v_BC = slv.get_array_double(i_slv,i_out,"v_BC",u)

T = t[-1]/2

coeff_v_ac, thd_v_ac, coeff_a_v_ac, coeff_b_v_ac = calc.fourier_coeff_2A(t, v_ac, 0.0, T, 1.0e-8*T, 1)
coeff_v_BD, thd_v_BD, coeff_a_v_BD, coeff_b_v_BD = calc.fourier_coeff_2A(t, v_BD, 0.0, T, 1.0e-8*T, 1)
coeff_v_BC, thd_v_BC, coeff_a_v_BC, coeff_b_v_BC = calc.fourier_coeff_2A(t, v_BC, 0.0, T, 1.0e-8*T, 1)

k_fourier = 1

A_v_ac, theta_rad_v_ac, theta_deg_v_ac = calc.get_mag_angle_1(k_fourier, coeff_a_v_ac, coeff_b_v_ac)
A_v_BD, theta_rad_v_BD, theta_deg_v_BD = calc.get_mag_angle_1(k_fourier, coeff_a_v_BD, coeff_b_v_BD)
A_v_BC, theta_rad_v_BC, theta_deg_v_BC = calc.get_mag_angle_1(k_fourier, coeff_a_v_BC, coeff_b_v_BC)

z_v_ac = cmath.rect(A_v_ac, (theta_rad_v_ac + np.pi/2))
z_v_BD = cmath.rect(A_v_BD, (theta_rad_v_BD + np.pi/2))
z_v_BC = cmath.rect(A_v_BC, (theta_rad_v_BC + np.pi/2))

print('phasors in polar form:')

s_format = "%7.2f"

calc.print_complex_polar('v_ac', z_v_ac, s_format)
calc.print_complex_polar('v_BD', z_v_BD, s_format)
calc.print_complex_polar('v_BC', z_v_BC, s_format)

l_colors = ["blue", "red", "green", "grey", "dodgerblue", "tomato"]

l1 = []
l1_labels = []

color_v_ac = calc.phasor_append_1a(l1, l1_labels, z_v_ac, "$V_{ac}$", l_colors)
color_v_BD = calc.phasor_append_1a(l1, l1_labels, z_v_BD, "$V_{BD}$", l_colors)
color_v_BC = calc.phasor_append_1a(l1, l1_labels, z_v_BC, "$V_{BC}$", l_colors)

theta_deg = 20.0
length_arrow = calc.phasor_3(l1, 0.02)
l1_arrow = calc.phasor_2(l1, theta_deg, length_arrow, 0.2)

l2 = []
l2_colors = []

calc.phasor_append_2(l2, l2_colors, z_v_BC, (z_v_BC + z_v_ac), color_v_ac)

l2_arrow = calc.phasor_2(l2, theta_deg, length_arrow, 0.2)

fig, ax = plt.subplots()
ax.set_aspect('equal', adjustable='box')
ax.grid()

for i, l_dummy in enumerate(l1_arrow):
    for k, t in enumerate(l_dummy):
        if (k == 0): 
            ax.plot(t[0],t[1], color=l_colors[i], label=l1_labels[i])
        else:
            ax.plot(t[0],t[1], color=l_colors[i])

for i, l_dummy in enumerate(l2_arrow):
    for k, t in enumerate(l_dummy):
        ax.plot(t[0],t[1], color=l2_colors[i], linestyle='--', dashes=(4, 2))

calc.revise_axis_limits_1(ax, 3.0)
ax.legend(loc='center left', fontsize=11, bbox_to_anchor=(1.05, 0.5))

plt.xlabel('Re (V)', fontsize=11)
plt.ylabel('Im (V)', fontsize=11)
plt.show()
filename: VSC_bi_6.dat
phasors in polar form:
v_ac: magnitude:  325.00, angle:  -30.00 deg
v_BD: magnitude:  441.05, angle:    0.00 deg
v_BC: magnitude:  227.76, angle:   45.52 deg
No description has been provided for this image
In [8]:
import numpy as np
import gseim_calc as calc
import os
import dos_unix
import cmath
import matplotlib.pyplot as plt 
from matplotlib.ticker import (MultipleLocator, AutoMinorLocator)
from setsize import set_size

slv = calc.slv("VSC_bi_6.in")

i_slv = 0
i_out = 0
filename = slv.l_filename_all[i_slv][i_out]
print('filename:', filename)
u = np.loadtxt(filename)
t = u[:, 0]
t0 = t[0]
t = t - t0

v_ac = slv.get_array_double(i_slv,i_out,"v_ac",u)
v_BD = slv.get_array_double(i_slv,i_out,"v_BD",u)
v_BC = slv.get_array_double(i_slv,i_out,"v_BC",u)

T = t[-1]/2

coeff_v_ac, thd_v_ac, coeff_a_v_ac, coeff_b_v_ac = calc.fourier_coeff_2A(t, v_ac, 0.0, T, 1.0e-8*T, 5)
coeff_v_BD, thd_v_BD, coeff_a_v_BD, coeff_b_v_BD = calc.fourier_coeff_2A(t, v_BD, 0.0, T, 1.0e-8*T, 5)
coeff_v_BC, thd_v_BC, coeff_a_v_BC, coeff_b_v_BC = calc.fourier_coeff_2A(t, v_BC, 0.0, T, 1.0e-8*T, 5)

k_fourier = 5

A_v_ac, theta_rad_v_ac, theta_deg_v_ac = calc.get_mag_angle_1(k_fourier, coeff_a_v_ac, coeff_b_v_ac)
A_v_BD, theta_rad_v_BD, theta_deg_v_BD = calc.get_mag_angle_1(k_fourier, coeff_a_v_BD, coeff_b_v_BD)
A_v_BC, theta_rad_v_BC, theta_deg_v_BC = calc.get_mag_angle_1(k_fourier, coeff_a_v_BC, coeff_b_v_BC)

z_v_ac = cmath.rect(A_v_ac, (theta_rad_v_ac + np.pi/2))
z_v_BD = cmath.rect(A_v_BD, (theta_rad_v_BD + np.pi/2))
z_v_BC = cmath.rect(A_v_BC, (theta_rad_v_BC + np.pi/2))

print('phasors in polar form:')

s_format = "%7.2f"

calc.print_complex_polar('v_ac', z_v_ac, s_format)
calc.print_complex_polar('v_BD', z_v_BD, s_format)
calc.print_complex_polar('v_BC', z_v_BC, s_format)

l_colors = ["blue", "red", "green", "grey", "dodgerblue", "tomato"]

l1 = []
l1_labels = []

color_v_ac = calc.phasor_append_1a(l1, l1_labels,   z_v_ac,  "$V_{ac}$",  l_colors)
color_v_BD = calc.phasor_append_1a(l1, l1_labels,   z_v_BD,  "$V_{BD}$",  l_colors)
color_v_BC = calc.phasor_append_1a(l1, l1_labels, (-z_v_BC), "$-V_{BC}$", l_colors)

theta_deg = 20.0
length_arrow = calc.phasor_3(l1, 0.02)
l1_arrow = calc.phasor_2(l1, theta_deg, length_arrow, 0.2)

fig, ax = plt.subplots()
ax.set_aspect('equal', adjustable='box')
ax.grid()

for i, l_dummy in enumerate(l1_arrow):
    for k, t in enumerate(l_dummy):
        if (k == 0): 
            ax.plot(t[0],t[1], color=l_colors[i], label=l1_labels[i])
        else:
            ax.plot(t[0],t[1], color=l_colors[i])

calc.revise_axis_limits_1(ax, 3.0)
ax.legend(loc='center left', fontsize=11, bbox_to_anchor=(1.05, 0.5))

plt.xlabel('Re (V)', fontsize=11)
plt.ylabel('Im (V)', fontsize=11)
plt.show()
filename: VSC_bi_6.dat
phasors in polar form:
v_ac: magnitude:    0.00, angle:   40.97 deg
v_BD: magnitude:   88.18, angle:  180.00 deg
v_BC: magnitude:   88.19, angle:  180.00 deg
No description has been provided for this image

This notebook was contributed by Prof. Nakul Narayanan K, Govt. Engineering College, Thrissur. He may be contacted at nakul@gectcr.ac.in.

In [ ]: