me2016 miniproject 2
This commit is contained in:
parent
07cbd62e63
commit
0bbc5521a1
203
ME_2016/mini_project_2/main.py
Normal file
203
ME_2016/mini_project_2/main.py
Normal file
@ -0,0 +1,203 @@
|
|||||||
|
import numpy as np
|
||||||
|
from scipy.optimize import fsolve
|
||||||
|
from scipy.integrate import quad
|
||||||
|
import matplotlib.pyplot as plt
|
||||||
|
|
||||||
|
# Persistent storage for fsolve initial conditions
|
||||||
|
nsolve_ics_storage = {'nsolve_ics': None}
|
||||||
|
|
||||||
|
# Helper functions for g1, g1timescos, and g1timessin
|
||||||
|
def g1(phi0, x, params):
|
||||||
|
"""
|
||||||
|
Purpose of the function:
|
||||||
|
Computes the transistor's nondimensionalized function `g1`, which represents
|
||||||
|
the piecewise relationship between input and output voltages.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
1. phi0 (float or array-like): Phase angle(s) at which the function is evaluated.
|
||||||
|
2. x (array-like): Fourier coefficients [U, G, H, X, Y].
|
||||||
|
3. params (dict): Dictionary containing nondimensional parameters:
|
||||||
|
- ep, gamma, u0.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
1. g1out (array-like): The value of the `g1` function at the input phase angles.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Implements piecewise behavior for the `g1` function based on the conditional
|
||||||
|
`ep * v1mu1 >= u0 - 1`.
|
||||||
|
- This is based on equations 28 and 34 in the referenced model.
|
||||||
|
"""
|
||||||
|
|
||||||
|
U, V, G, H, X, Y = x[0], 0, x[1], x[2], x[3], x[4]
|
||||||
|
ep = params['ep']
|
||||||
|
gamma = params['gamma']
|
||||||
|
u0 = params['u0']
|
||||||
|
|
||||||
|
# Equation 34
|
||||||
|
v1mu1 = (V - U) + (G - X) * np.cos(phi0) + (H - Y) * np.sin(phi0)
|
||||||
|
|
||||||
|
# Equation 28
|
||||||
|
cond = ep * v1mu1 >= u0 - 1
|
||||||
|
g1out = np.where(
|
||||||
|
cond,
|
||||||
|
gamma * v1mu1 * (2 * (1 - u0) + ep * v1mu1),
|
||||||
|
-gamma / ep * (1 - u0)**2
|
||||||
|
)
|
||||||
|
return g1out
|
||||||
|
|
||||||
|
def g1timescos(phi0, x, params):
|
||||||
|
"""Compute g1(phi0) * cos(phi0)."""
|
||||||
|
return g1(phi0, x, params) * np.cos(phi0)
|
||||||
|
|
||||||
|
def g1timessin(phi0, x, params):
|
||||||
|
"""Compute g1(phi0) * sin(phi0)."""
|
||||||
|
return g1(phi0, x, params) * np.sin(phi0)
|
||||||
|
|
||||||
|
# Harmonic balance system (hbsystem_case1)
|
||||||
|
def hbsystem_case1(x, params):
|
||||||
|
"""
|
||||||
|
Purpose of the function:
|
||||||
|
Computes the residuals for the harmonic balance system (Eq. 33a-f).
|
||||||
|
These residuals are minimized by `fsolve` to find the Fourier coefficients.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
1. x (array-like): A vector of Fourier coefficients [U, G, H, X, Y].
|
||||||
|
2. params (dict): Dictionary containing nondimensional parameters:
|
||||||
|
- mu, a1, a2, ep, gamma, a0 (current state), and u0 (steady-state solution).
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
1. F (array-like): A vector of residuals corresponding to equations 33a-f.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- The residuals involve integrals over `phi0` (0 to 2π), which are computed using
|
||||||
|
numerical quadrature (`quad`).
|
||||||
|
- The function incorporates `g1`, `g1timescos`, and `g1timessin`.
|
||||||
|
"""
|
||||||
|
mu = params['mu']
|
||||||
|
a1 = params['a1']
|
||||||
|
a2 = params['a2']
|
||||||
|
ep = params['ep']
|
||||||
|
gamma = params['gamma']
|
||||||
|
a0 = params['a0cur']
|
||||||
|
u0 = params['u0']
|
||||||
|
|
||||||
|
# Fourier coefficients
|
||||||
|
U, V, G, H, X, Y = x[0], 0, x[1], x[2], x[3], x[4]
|
||||||
|
|
||||||
|
# Equations 33a-f
|
||||||
|
F = np.zeros(5)
|
||||||
|
F[0] = -a2 * U + (1 / (2 * np.pi)) * quad(lambda phi: g1(phi, x, params), 0, 2 * np.pi)[0]
|
||||||
|
F[1] = H - Y + a1 * G
|
||||||
|
F[2] = -mu * H + (mu + 1) * Y + a2 * X - (1 / np.pi) * quad(lambda phi: g1timescos(phi, x, params), 0, 2 * np.pi)[0]
|
||||||
|
F[3] = -G + X + a1 * H + a0
|
||||||
|
F[4] = mu * G - (mu + 1) * X + a2 * Y - (1 / np.pi) * quad(lambda phi: g1timessin(phi, x, params), 0, 2 * np.pi)[0]
|
||||||
|
#print(f'F: {F}')
|
||||||
|
return F
|
||||||
|
|
||||||
|
# ODE function for A0
|
||||||
|
def odefun_A0(t, A0, params):
|
||||||
|
"""
|
||||||
|
Purpose of the function:
|
||||||
|
Defines the ordinary differential equation (ODE) for `A0` as part of the
|
||||||
|
larger Colpitts oscillator system. Computes the time derivative of `A0`.
|
||||||
|
|
||||||
|
Inputs:
|
||||||
|
1. t (float): Current time (unused in this specific ODE but required by solver).
|
||||||
|
2. A0 (float): Current value of `A0`.
|
||||||
|
3. params (dict): Dictionary containing nondimensional parameters:
|
||||||
|
- lambda, a0cur (current A0 state), and others used in `hbsystem_case1`.
|
||||||
|
|
||||||
|
Outputs:
|
||||||
|
1. dA0 (float): The time derivative of `A0`.
|
||||||
|
|
||||||
|
Notes:
|
||||||
|
- Uses `fsolve` to solve the harmonic balance equations (via `hbsystem_case1`).
|
||||||
|
- Returns `dA0` using the computed `H` value (harmonic balance coefficient).
|
||||||
|
"""
|
||||||
|
global nsolve_ics_storage
|
||||||
|
|
||||||
|
# Initialize fsolve initial conditions if not set
|
||||||
|
if nsolve_ics_storage['nsolve_ics'] is None:
|
||||||
|
nsolve_ics_storage['nsolve_ics'] = np.array([100, 100, 100, 100, 100])
|
||||||
|
|
||||||
|
# Update current A0 in parameters
|
||||||
|
params['a0cur'] = A0
|
||||||
|
lambda_ = params['lambda']
|
||||||
|
|
||||||
|
# Solve harmonic balance system
|
||||||
|
nsolve_ics = nsolve_ics_storage['nsolve_ics']
|
||||||
|
x = fsolve(lambda x: hbsystem_case1(x, params), nsolve_ics, xtol=1e-4)
|
||||||
|
|
||||||
|
# Update fsolve initial conditions for next iteration
|
||||||
|
nsolve_ics_storage['nsolve_ics'] = x
|
||||||
|
|
||||||
|
# Extract H from the solution
|
||||||
|
H = x[2]
|
||||||
|
|
||||||
|
# Compute dA0/d_eta_2
|
||||||
|
dA0 = (-1 / 2) * (lambda_ * A0 - H)
|
||||||
|
#print(f'dA0 {dA0}')
|
||||||
|
print(f't {t}')
|
||||||
|
return dA0
|
||||||
|
|
||||||
|
# Main function to solve the system and plot results
|
||||||
|
def main():
|
||||||
|
# Dimensional parameters
|
||||||
|
Cm = 2.201e-15
|
||||||
|
Cs = 1.62e-11
|
||||||
|
Cg = 2.32e-11
|
||||||
|
Lm = 4.496e-2
|
||||||
|
Rm = 5.62e1
|
||||||
|
Rs = 7.444e3
|
||||||
|
Rg = 5.168e4
|
||||||
|
Vth = -0.95
|
||||||
|
beta = 0.12
|
||||||
|
B = 0.8
|
||||||
|
|
||||||
|
# Compute nondimensional parameters
|
||||||
|
mu = Cg / Cs
|
||||||
|
a1 = np.sqrt(Lm * Cm) / (Cg * Rg)
|
||||||
|
a2 = np.sqrt(Lm * Cm) / (Cs * Rs)
|
||||||
|
ep = np.sqrt(Cm / Cg)
|
||||||
|
lmbda = Rm * Cg / np.sqrt(Lm * Cm)
|
||||||
|
gamma = beta * abs(Vth) * np.sqrt(Lm * Cm) / Cs
|
||||||
|
u0 = (1 + a2 / (2 * gamma)) - np.sqrt((1 + a2 / (2 * gamma))**2 - 1)
|
||||||
|
|
||||||
|
# Parameters
|
||||||
|
params = {
|
||||||
|
'mu': mu,
|
||||||
|
'a1': a1,
|
||||||
|
'a2': a2,
|
||||||
|
'ep': ep,
|
||||||
|
'lambda': lmbda,
|
||||||
|
'gamma': gamma,
|
||||||
|
'u0': u0,
|
||||||
|
'a0cur': 0,
|
||||||
|
'v0': 0,
|
||||||
|
}
|
||||||
|
|
||||||
|
# Initial conditions and time span
|
||||||
|
a0ic = 0
|
||||||
|
tspan = [0, 200]
|
||||||
|
|
||||||
|
# Solve the ODE
|
||||||
|
from scipy.integrate import solve_ivp
|
||||||
|
sol = solve_ivp(
|
||||||
|
fun=lambda t, A0: odefun_A0(t, A0, params),
|
||||||
|
t_span=tspan,
|
||||||
|
y0=[a0ic],
|
||||||
|
method='RK45',
|
||||||
|
max_step=1e-0
|
||||||
|
)
|
||||||
|
|
||||||
|
# Plot the results
|
||||||
|
plt.plot(sol.t / params['ep']**2, np.abs(sol.y[0]))
|
||||||
|
plt.xlabel('Scaled Time (t / ep^2)')
|
||||||
|
plt.ylabel('A0 (Amplitude)')
|
||||||
|
plt.title('Dynamics of A0 Over Time')
|
||||||
|
plt.grid()
|
||||||
|
plt.savefig('test.png')
|
||||||
|
|
||||||
|
# Run the main function
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Loading…
x
Reference in New Issue
Block a user