from sympy import *
import numpy as np
from tabulate import tabulate
import pandas as pd
from scipy import signal
import matplotlib.pyplot as plt
import SymMNA
from IPython.display import display, Markdown, Math, Latex
init_printing()
28 Transient circuit
28.1 Introduction
The circuit above is a filter designed to explore transient analysis of a circuit using Python. The dependent source, V1, will be a time varying signal described below.
28.2 Circuit description
The circuit in Figure 28.1 is an elliptic low pass filter with a 1 Hz cut off and 3 dB of ripple in the pass band and 40 dB of attenuation in the stop band. Three dB of ripple in the pass band was designed in so that the transient response would have some ringing. The filter design tool linked here was used to design the filter.
28.3 Circuit analysis
The circuit analysis follows the steps listed below.
- Draw circuit in LTSpice, export netlist
- Generate network equations
- Symbolic solution
- AC sweep and plot the frequency response at the output
- Transient analysis
- Generate input signal for transient analysis
- Mostly following the procedure outlined here
- display the results
Transient analysis is somewhat more involved than the other types of circuit analysis, primarily because SymPy’s inverse Laplace transform is not very robust and can’t handle complicated expressions. The output equation needs to be simplified by writing some code to put the equation into forms that SymPy can deal with.
Load the following Python modules.
28.3.1 Load the netlist
The netlist generated by LTSpice is pasted into the cell below and some edits were made to remove the inductor series resistance and the independent source, V1, is set to a value of one.
= '''
net_list V1 1 0 1
R1 3 1 1
R2 2 0 1
L1 3 4 0.4925
L2 5 0 0.05081
C2 4 5 0.09876
L3 4 2 0.4925
'''
Generate the network equations.
= SymMNA.smna(net_list)
report, network_df, df2, A, X, Z
# Put matricies into SymPy
= Matrix(X)
X = Matrix(Z)
Z
= Eq(A*X,Z) NE_sym
Generate markdown text to display the network equations.
= ''
temp for i in range(len(X)):
+= '${:s}$<br>'.format(latex(Eq((A*X)[i:i+1][0],Z[i])))
temp
Markdown(temp)
\(I_{V1} + \frac{v_{1}}{R_{1}} - \frac{v_{3}}{R_{1}} = 0\)
\(- I_{L3} + \frac{v_{2}}{R_{2}} = 0\)
\(I_{L1} - \frac{v_{1}}{R_{1}} + \frac{v_{3}}{R_{1}} = 0\)
\(C_{2} s v_{4} - C_{2} s v_{5} - I_{L1} + I_{L3} = 0\)
\(- C_{2} s v_{4} + C_{2} s v_{5} + I_{L2} = 0\)
\(v_{1} = V_{1}\)
\(- I_{L1} L_{1} s + v_{3} - v_{4} = 0\)
\(- I_{L2} L_{2} s + v_{5} = 0\)
\(- I_{L3} L_{3} s - v_{2} + v_{4} = 0\)
As shown above MNA generated many equations and these would be difficult to solve by hand. The equations are displade in matrix notation below.
NE_sym
\(\displaystyle \left[\begin{matrix}I_{V1} + \frac{v_{1}}{R_{1}} - \frac{v_{3}}{R_{1}}\\- I_{L3} + \frac{v_{2}}{R_{2}}\\I_{L1} - \frac{v_{1}}{R_{1}} + \frac{v_{3}}{R_{1}}\\C_{2} s v_{4} - C_{2} s v_{5} - I_{L1} + I_{L3}\\- C_{2} s v_{4} + C_{2} s v_{5} + I_{L2}\\v_{1}\\- I_{L1} L_{1} s + v_{3} - v_{4}\\- I_{L2} L_{2} s + v_{5}\\- I_{L3} L_{3} s - v_{2} + v_{4}\end{matrix}\right] = \left[\begin{matrix}0\\0\\0\\0\\0\\V_{1}\\0\\0\\0\end{matrix}\right]\)
The sysmbols generated by the Python code are extraced by the SymPy function free_symbols and then declared as SymPy variables.
# turn the free symbols into SymPy variables
str(NE_sym.free_symbols).replace('{','').replace('}','')) var(
\(\displaystyle \left( I_{V1}, \ R_{2}, \ L_{2}, \ v_{1}, \ v_{4}, \ v_{3}, \ I_{L3}, \ L_{1}, \ V_{1}, \ s, \ L_{3}, \ I_{L2}, \ v_{2}, \ R_{1}, \ C_{2}, \ v_{5}, \ I_{L1}\right)\)
Built a dictionary of element values.
= SymMNA.get_part_values(network_df)
element_values element_values
\(\displaystyle \left\{ C_{2} : 0.09876, \ L_{1} : 0.4925, \ L_{2} : 0.05081, \ L_{3} : 0.4925, \ R_{1} : 1.0, \ R_{2} : 1.0, \ V_{1} : 1.0\right\}\)
28.4 Symbolic solution
Since the circuit is not too large, a symbolic solution can be easily obtained.
= solve(NE_sym,X) U_sym
Display the symbolic solution
= ''
temp for i in U_sym.keys():
+= '${:s} = {:s}$<br>'.format(latex(i),latex(U_sym[i]))
temp
Markdown(temp)
\(v_{1} = V_{1}\)
\(v_{2} = \frac{C_{2} L_{2} R_{2} V_{1} s^{2} + R_{2} V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(v_{3} = \frac{C_{2} L_{1} L_{2} V_{1} s^{3} + C_{2} L_{1} L_{3} V_{1} s^{3} + C_{2} L_{1} R_{2} V_{1} s^{2} + C_{2} L_{2} L_{3} V_{1} s^{3} + C_{2} L_{2} R_{2} V_{1} s^{2} + L_{1} V_{1} s + L_{3} V_{1} s + R_{2} V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(v_{4} = \frac{C_{2} L_{2} L_{3} V_{1} s^{3} + C_{2} L_{2} R_{2} V_{1} s^{2} + L_{3} V_{1} s + R_{2} V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(v_{5} = \frac{C_{2} L_{2} L_{3} V_{1} s^{3} + C_{2} L_{2} R_{2} V_{1} s^{2}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(I_{V1} = \frac{- C_{2} L_{2} V_{1} s^{2} - C_{2} L_{3} V_{1} s^{2} - C_{2} R_{2} V_{1} s - V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(I_{L1} = \frac{C_{2} L_{2} V_{1} s^{2} + C_{2} L_{3} V_{1} s^{2} + C_{2} R_{2} V_{1} s + V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(I_{L2} = \frac{C_{2} L_{3} V_{1} s^{2} + C_{2} R_{2} V_{1} s}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
\(I_{L3} = \frac{C_{2} L_{2} V_{1} s^{2} + V_{1}}{C_{2} L_{1} L_{2} s^{3} + C_{2} L_{1} L_{3} s^{3} + C_{2} L_{1} R_{2} s^{2} + C_{2} L_{2} L_{3} s^{3} + C_{2} L_{2} R_{1} s^{2} + C_{2} L_{2} R_{2} s^{2} + C_{2} L_{3} R_{1} s^{2} + C_{2} R_{1} R_{2} s + L_{1} s + L_{3} s + R_{1} + R_{2}}\)
28.4.1 AC Sweep
After substituting the numeric component values for the elements, a numerical solution for the note voltages can be obtained.
= NE_sym.subs(element_values)
NE NE
\(\displaystyle \left[\begin{matrix}I_{V1} + 1.0 v_{1} - 1.0 v_{3}\\- I_{L3} + 1.0 v_{2}\\I_{L1} - 1.0 v_{1} + 1.0 v_{3}\\- I_{L1} + I_{L3} + 0.09876 s v_{4} - 0.09876 s v_{5}\\I_{L2} - 0.09876 s v_{4} + 0.09876 s v_{5}\\v_{1}\\- 0.4925 I_{L1} s + v_{3} - v_{4}\\- 0.05081 I_{L2} s + v_{5}\\- 0.4925 I_{L3} s - v_{2} + v_{4}\end{matrix}\right] = \left[\begin{matrix}0\\0\\0\\0\\0\\1.0\\0\\0\\0\end{matrix}\right]\)
= solve(NE,X) U_ac
28.4.2 Plot the frequency response at node 2
= U_ac[v2]
H
= fraction(H) #returns numerator and denominator
num, denom
# convert symbolic to numpy polynomial
= np.array(Poly(num, s).all_coeffs(), dtype=float)
a = np.array(Poly(denom, s).all_coeffs(), dtype=float)
b = (a, b)
system
= np.logspace(-1, 1, 200, endpoint=False)*2*np.pi
x = signal.bode(system, w=x) # returns: rad/s, mag in dB, phase in deg
w, mag, phase
= plt.subplots()
fig, ax1 'magnitude, dB')
ax1.set_ylabel('frequency, Hz')
ax1.set_xlabel(
/(2*np.pi), mag,'-b') # Bode magnitude plot
plt.semilogx(w
='y')
ax1.tick_params(axis#ax1.set_ylim((-30,20))
plt.grid()
# instantiate a second y-axes that shares the same x-axis
= ax1.twinx()
ax2 = 'tab:blue'
color
/(2*np.pi), phase,':',color='tab:red') # Bode phase plot
plt.semilogx(w
'phase, deg',color=color)
ax2.set_ylabel(='y', labelcolor=color)
ax2.tick_params(axis#ax2.set_ylim((-5,25))
'Magnitude and phase response')
plt.title( plt.show()
28.4.3 Low pass filter impulse and step response
Use the SciPy functions impulse2 and step2 to plot the impulse and step response of the system.
The impulse and step response of the filter are plotted below. Any linear, time-invariant is completely characterized by its impulse response. The transfer function is the Laplace transform of the impulse response. The impulse response defines the response of a linear time-invariant system for all frequencies.
1,2,figsize=(15, 5))
plt.subplots(
# using subplot function and creating
# plot one
1, 2, 1)
plt.subplot(
# impulse response
= signal.impulse2(system,N=500)
t, y /1e-3, y)
plt.plot(t'Impulse response')
plt.title('volts')
plt.ylabel('time, msec')
plt.xlabel(
plt.grid()
# using subplot function and creating plot two
1, 2, 2)
plt.subplot(
= signal.step2(system,N=500)
t, y /1e-3, y)
plt.plot(t'Step response')
plt.title('volts')
plt.ylabel('time, msec')
plt.xlabel(
plt.grid()
# show plot
plt.show()
The results obtained from SciPy’s step2 function can be compared to the transient response results obtained below.
28.5 Transient Analysis
The input signal for the filter circuit is defined by using SymPy’s Heaveside function. The signal has a positive step at t=0, followed by a return to zero amplitude at t=5.
Declare SymPy symbols needed during the analysis.
= symbols('t',positive=True) # t > 0 t
= 1*Heaviside(t)*(1-Heaviside(t-5))
V1_t V1_t
\(\displaystyle 1 - \theta\left(t - 5\right)\)
Use the lambdify function to convert the input signal to a function for plotting.
= lambdify(t, V1_t) func_V1_t
The time domain description of the input signal is comvertered to the frequency domain with SymPy’s Laplace transform function.
= laplace_transform(V1_t, t, s, noconds=True)
V1_s V1_s
\(\displaystyle \frac{1}{s} - \frac{e^{- 5 s}}{s}\)
Put the component values into the network equations and set V1 equal to the Laplace of the input signal.
= V1_s
element_values[V1] = NE_sym.subs(element_values)
NE_trans NE_trans
\(\displaystyle \left[\begin{matrix}I_{V1} + 1.0 v_{1} - 1.0 v_{3}\\- I_{L3} + 1.0 v_{2}\\I_{L1} - 1.0 v_{1} + 1.0 v_{3}\\- I_{L1} + I_{L3} + 0.09876 s v_{4} - 0.09876 s v_{5}\\I_{L2} - 0.09876 s v_{4} + 0.09876 s v_{5}\\v_{1}\\- 0.4925 I_{L1} s + v_{3} - v_{4}\\- 0.05081 I_{L2} s + v_{5}\\- 0.4925 I_{L3} s - v_{2} + v_{4}\end{matrix}\right] = \left[\begin{matrix}0\\0\\0\\0\\0\\\frac{1}{s} - \frac{e^{- 5 s}}{s}\\0\\0\\0\end{matrix}\right]\)
Solve the newtork equations for the transient input and display the results.
= solve(NE_trans,X)
U_trans
= ''
temp for i in U_trans.keys():
+= '${:s} = {:s}$<br>'.format(latex(i),latex(U_trans[i]))
temp
Markdown(temp)
\(v_{1} = \frac{1}{s} - \frac{e^{- 5.0 s}}{s}\)
\(v_{2} = \frac{1254498900.0 s^{2} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{1254498900.0 s^{2}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{250000000000.0 e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{250000000000.0}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}}\)
\(v_{3} = \frac{7224395229.0 s^{3} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{7224395229.0 s^{3}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{13414323900.0 s^{2} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{13414323900.0 s^{2}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{246250000000.0 s e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{246250000000.0 s}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{250000000000.0 e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{250000000000.0}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}}\)
\(v_{4} = \frac{12544989.0 s^{2} e^{5.0 s}}{146688228.0 s^{3} e^{5.0 s} + 246900000.0 s^{2} e^{5.0 s} + 5000000000.0 s e^{5.0 s}} - \frac{12544989.0 s^{2}}{146688228.0 s^{3} e^{5.0 s} + 246900000.0 s^{2} e^{5.0 s} + 5000000000.0 s e^{5.0 s}} + \frac{2500000000.0 e^{5.0 s}}{146688228.0 s^{3} e^{5.0 s} + 246900000.0 s^{2} e^{5.0 s} + 5000000000.0 s e^{5.0 s}} - \frac{2500000000.0}{146688228.0 s^{3} e^{5.0 s} + 246900000.0 s^{2} e^{5.0 s} + 5000000000.0 s e^{5.0 s}}\)
\(v_{5} = \frac{12544989.0 s e^{5.0 s}}{146688228.0 s^{2} e^{5.0 s} + 246900000.0 s e^{5.0 s} + 5000000000.0 e^{5.0 s}} - \frac{12544989.0 s}{146688228.0 s^{2} e^{5.0 s} + 246900000.0 s e^{5.0 s} + 5000000000.0 e^{5.0 s}}\)
\(I_{V1} = - \frac{13414323900.0 s^{2} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{13414323900.0 s^{2}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{24690000000.0 s e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{24690000000.0 s}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{250000000000.0 e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{250000000000.0}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}}\)
\(I_{L1} = \frac{13414323900.0 s^{2} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{13414323900.0 s^{2}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{24690000000.0 s e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{24690000000.0 s}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{250000000000.0 e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{250000000000.0}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}}\)
\(I_{L2} = \frac{61725000.0 e^{5.0 s}}{36672057.0 s^{2} e^{5.0 s} + 61725000.0 s e^{5.0 s} + 1250000000.0 e^{5.0 s}} - \frac{61725000.0}{36672057.0 s^{2} e^{5.0 s} + 61725000.0 s e^{5.0 s} + 1250000000.0 e^{5.0 s}}\)
\(I_{L3} = \frac{1254498900.0 s^{2} e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{1254498900.0 s^{2}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} + \frac{250000000000.0 e^{5.0 s}}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}} - \frac{250000000000.0}{7224395229.0 s^{4} e^{5.0 s} + 26828647800.0 s^{3} e^{5.0 s} + 270940000000.0 s^{2} e^{5.0 s} + 500000000000.0 s e^{5.0 s}}\)
The equations for the solution are complex and long, but are easy to obtain and display.
The voltage on node 2 is the output of the filter. The expression is symplified with the chain of operators applied to the expression; nsimplify(), simplify(), expand() and together().
= U_trans[v2].nsimplify().simplify().expand().together()
H H
\(\displaystyle \frac{100 \cdot \left(12544989 s^{2} e^{5 s} - 12544989 s^{2} + 2500000000 e^{5 s} - 2500000000\right) e^{- 5 s}}{s \left(7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000\right)}\)
All the time dealy terms are in the numerator.
Extract the numerator and denominator and display.
= fraction(H)
n, d 'numerator', n, 'denominator', d) display(
'numerator'
\(\displaystyle 1254498900 s^{2} e^{5 s} - 1254498900 s^{2} + 250000000000 e^{5 s} - 250000000000\)
'denominator'
\(\displaystyle s \left(7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000\right) e^{5 s}\)
Each of the numerator terms can be put over the common denominator.
= [a / d for a in n.args]
terms display(terms)
\(\displaystyle \left[ - \frac{250000000000 e^{- 5 s}}{s \left(7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000\right)}, \ - \frac{1254498900 s e^{- 5 s}}{7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000}, \ \frac{250000000000}{s \left(7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000\right)}, \ \frac{1254498900 s}{7224395229 s^{3} + 26828647800 s^{2} + 270940000000 s + 500000000000}\right]\)
The following code processes each of the terms obtained above.
- The time delay operator \(e^{-ts}\) is removed from the xpression and the value of the time delay is saved in a list.
- use the SciPy residue function to get the partial-fraction expansion residues and poles
- build the partial expansion terms and find the inverse Laplace of each one and save
= []
time_delay = []
delay = []
N
for i in terms:
# look for and remove the time delay
if len(i.find(exp)) == 1:
= i.find(exp).pop()
delay list(delay.atoms())[0])
time_delay.append(= i/i.find(exp).pop()
ans else:
= i
ans 0)
time_delay.append(
# use the SciPy residue function to get the partial-fraction expansion residues and poles
= fraction(ans)
n, d = Poly(n, s).all_coeffs()
cn = Poly(d, s).all_coeffs()
cd = signal.residue(cn, cd, tol=0.001, rtype='avg')
r, p, k
# build a symbolic expression for each of the residues and find the inverse Laplace of each one and save
= 0
z for i in range(len(r)):
= (r[i]/(s-p[i])) #.nsimplify()
m += inverse_laplace_transform(m, s, t)
z
N.append(z)
The time delays associated with each term are:
time_delay
\(\displaystyle \left[ s, \ s, \ 0, \ 0\right]\)
The time domain version of each of the terms is displayed below.
N
\(\displaystyle \left[ 1.0 \left(\left(0.0868202525095611 - 0.00506716236561563 i\right) \sin{\left(5.77733847617481 t \right)} + \left(0.00506716236561563 + 0.0868202525095611 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 1.0 \left(\left(0.0868202525095611 + 0.00506716236561563 i\right) \sin{\left(5.77733847617481 t \right)} + \left(0.00506716236561563 - 0.0868202525095611 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} - 0.5 + 0.489865675268769 e^{- 2.03045685279188 t}, \ 1.0 \left(\left(-0.0139856047826648 + 0.00506716236561562 i\right) \sin{\left(5.77733847617481 t \right)} - \left(0.00506716236561562 + 0.0139856047826648 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 1.0 \left(- \left(0.0139856047826648 + 0.00506716236561562 i\right) \sin{\left(5.77733847617481 t \right)} + \left(-0.00506716236561562 + 0.0139856047826648 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 0.0101343247312312 e^{- 2.03045685279188 t}, \ 1.0 \left(\left(-0.0868202525095611 + 0.00506716236561563 i\right) \sin{\left(5.77733847617481 t \right)} - \left(0.00506716236561563 + 0.0868202525095611 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 1.0 \left(- \left(0.0868202525095611 + 0.00506716236561563 i\right) \sin{\left(5.77733847617481 t \right)} + \left(-0.00506716236561563 + 0.0868202525095611 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 0.5 - 0.489865675268769 e^{- 2.03045685279188 t}, \ 1.0 \left(\left(0.0139856047826648 - 0.00506716236561562 i\right) \sin{\left(5.77733847617481 t \right)} + \left(0.00506716236561562 + 0.0139856047826648 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} + 1.0 \left(\left(0.0139856047826648 + 0.00506716236561562 i\right) \sin{\left(5.77733847617481 t \right)} + \left(0.00506716236561562 - 0.0139856047826648 i\right) \cos{\left(5.77733847617481 t \right)}\right) e^{- 0.841580825422473 t} - 0.0101343247312312 e^{- 2.03045685279188 t}\right]\)
Each of these terms came be converted to a function using SymPy’s lambdify function.
= lambdify(t, N[0])
out0 = lambdify(t, N[1])
out1 = lambdify(t, N[2])
out2 = lambdify(t, N[3]) out3
Define the values for the x-axis of the plot and put each one into an array for plotting.
= np.linspace(0, 10, 2000, endpoint=True)
x
= out0(x)
out0a = out1(x)
out1a = out2(x)
out2a = out3(x) out3a
The arrays, out2a and out3a, do not have any delay so they can be summed and used to create the final array for plotting.
= out2a + out3a out
The arrays, out0a and out1a, have a delay associated with them, so and offset in the time is included by shifting right by the corrrect amount.
= 1000
offset = out[offset:] + (out0a[0:-offset] + out1a[0:-offset]) out[offset:]
Plot the final combined result.
'Filter output voltage vs time')
plt.title(
='v2(t)')
plt.plot(x, np.real(out),label='V1(t)')
plt.plot(x, np.real(func_V1_t(x)),label
'v(t), volts')
plt.ylabel('time, sec')
plt.xlabel(
plt.legend()
plt.grid() plt.show()
28.6 Summary
The inverse Laplace transform of complicated expressions requires that they be reduced to a set of simple terms by particial fraction expansion. I’ve not yet figured a way to easily code the delay terms, so these are handled manually by a offset shift in the finaly plot output.