My while loop is not looping through the components in the array - python

I want the while loop at the end of my code to perform the calculation for each component of delta_omega, and print the result before moving on to the next number in the delta_omega array. When I run the code python outputs 'The rate of capture at a detuning of -5000000 is 3.0E+13' an infinite number of times before I manually stop it. I am unsure of why this is happening and how to fix it? I tried using break at the end of the loop, but this just performed the calculation once for the first component of the delta_omega array.
import numpy as np
from scipy.integrate import odeint
#import matplotlib.pyplot as plt
# Constants
m_Rb = 1.443*10**-25 #mass of rubidium 87
k_b = 1.38*10**-23
h = 6.63*10**-34
hbar = 1.05*10**-34
L = 38.116*10**6 #natural linewidth
epsilon_0 = 8.85418782*10**-12 #permittivity of free space
# Changable paramaters
lmbda = 780*10**-9 #wavelength of laser light
k = (2*np.pi)/lmbda #wavevector of laser light
B = 5*10**-4 #magnetic field strength
# D2 effective magetic moment
gj_gnd = 1 + (0.5*(0.5+1) + 0.5*(0.5+1) - 0*(0+1))/(2*0.5*(0.5+1))
mj_gnd = 0.5
gj_ex = 1 + (1.5*(1.5+1) + 0.5*(0.5+1) - 1*(1+1))/(2*1.5*(1.5+1))
mj_ex = 1.5
Bohr = 9.274*10**-24 #Bohr magneton value
mu_eff = Bohr*(gj_ex*mj_ex - gj_gnd*mj_gnd)
# -------- Before slower --------
T = 700 #temperature of oven
vp = ((2*k_b*T)/m_Rb)**0.5 #mean velocity of particles coming out of the oven
x_os = 0.1
a = (hbar*L*k)/(2*m_Rb) #max decelleration of atoms
vf_oven = (vp**2 + (2*a*x_os))**0.5
t_b = (2*x_os)/(vp + vf_oven) #time taken from oven to start of slower
# -------- During slower --------
length_slow = 0.5
vz_max = (vf_oven**2 + 2*a*length_slow)**0.5
Z = 0.7
#Z = np.linspace(0, length_slow, 100)
P = 10**(4.312-(4040/T)) #vapour pressure for liquid phase (use 4.857 for solid phase)
A = 5*10**-4 #area of the oven aperture
n = P/(k_b*T) #atomic number density
I = 1*10**5 #intensity
n0 = 1 #refraction constant for medium
E_0 = ((2*I)/(3*10**8*n0*epsilon_0))**0.5
Rabi = (E_0*3.5844*10**-29)/hbar
II_sat = (2*Rabi**2)/L**2
delta_omega = np.array([-5*10**6, -10*10**6, -30*10**6]) #range of frequencies
i = 0
while i<len(delta_omega):
B_p = (h/mu_eff) * (delta_omega[i] + (1/lmbda)*(vf_oven**2 - (2*a*length_slow))**0.5)
B_n = (h/mu_eff) * (delta_omega[i] - (1/lmbda)*(vf_oven**2 - (2*a*length_slow))**0.5)
delta_n = delta_omega[i] + (k*vf_oven) - (mu_eff*B_n)/hbar
delta_p = delta_omega[i] - (k*vf_oven) + (mu_eff*B_p)/hbar
F = (hbar*k*L)/2 * ((II_sat/(1+II_sat+(2*delta_n/L)**2))
- (II_sat/(1+II_sat+(2*delta_p/L)**2)))
accn = abs(F/m_Rb)
vf_slower = (vf_oven**2 - (2*accn*length_slow))**0.5
t_d = 1/accn * (vf_oven - vf_slower) #time taken during slower
# -------- After slower --------
da = 0.1 #distance from end of slower to the middle of the MOT
vf_MOT = (vf_slower**2 - (2*accn*da))**0.5
t_a = da/vf_MOT #time taken after slower
r0 = 0.01 #MOT capture radius
vr_max = r0/(t_b+t_d+t_a)
# -------- Flux of atoms captured --------
f_oven = ((n*A)/4) * (2/(np.pi)**0.5) * ((2*k_b*T)/m_Rb)**0.5
f = f_oven * (1 - np.exp(-vr_max**2/vp**2))*(1 - np.exp(-vz_max**2/vp**2))
print('The rate of capture at a detuning of', delta_omega[i], 'is', format(f, '.1E'))

It seems you forgot to increment i within the loop...

Related

Performing a cumulative sum with the loop variable itself

I want to get my code to loop so that every time it performs the calculation, it adds basically does a cumulative sum for my variable delta_omega. i.e. for every calculation, it takes the previous values in the delta_omega array, adds them together and uses that value to perform the calculation again and so on. I'm really not sure how to go about this as I want to plot these results too.
import numpy as np
import matplotlib.pyplot as plt
delta_omega = np.linspace(-900*10**6, -100*10**6, m) #Hz - range of frequencies
i = 0
while i<len(delta_omega):
delta = delta_omega[i] - (k*v_cap) + (mu_eff*B)/hbar
p_ee = (s0*L/2) / (1 + s0 + (2*delta/L)**2) #population of the excited state
R = L * p_ee # scattering rate
F = hbar*k*(R) #scattering force on atoms
a = F/m_Rb #acceleration assumed constant
vf_slower = (v_cap**2 - (2*a*z0))**0.5 #velocity at the end of the slower
t_d = 1/a * (v_cap - vf_slower) #time taken during slower
# -------- After slower --------
da = 0.1 #(m) distance from end of slower to the middle of the MOT
vf_MOT = (vf_slower**2 - (2*a*da))**0.5 #(m/s) - velocity of the particles at MOT center
t_a = da/vf_MOT #(s) time taken after slower
r0 = 0.01 #MOT capture radius
vr_max = r0/(t_b+t_d+t_a) #maximum transveral velocity
vz_max = (v_cap**2 + 2*a_max*z0)**0.5 #m/s - maximum axial velocity
# -------- Flux of atoms captured --------
P = 10**(4.312-(4040/T)) #vapour pressure for liquid phase (use 4.857 for solid phase)
A = 5*10**-4 #area of the oven aperture
n = P/(k_b*T) #atomic number density
f_oven = ((n*A)/4) * (2/(np.pi)**0.5) * ((2*k_b*T)/m_Rb)**0.5
f = f_oven * (1 - np.exp(-vr_max**2/vp**2))*(1 - np.exp(-vz_max**2/vp**2))
i+=1
plt.plot(delta_omega, f)
A simple cumulative sum would be defining the variable outside the loop and adding to it
i = 0
x = 0
while i < 10:
x = x + 5 #do your work on the cumulative value here
i += 1
print("cumulative sum: {}".format(x))
so define a variable that will contain the cumulative sum, and every loop, add to it

Python 1D PDE Using the Implicit Method

How would I code the equation and the initial and boundary conditions of the problem below? I did them by hand but I'm unsure of how to code them. I also attached the code I have so far. I know what I coded below is incorrect, but it is somewhat similar.
enter image description here
enter image description here
import numpy as np
import matplotlib.pyplot as plt
# Constants
r1 = 0.06 # Inner radius (m)
r2 = 0.15 # Outer radius (m)
r = r2-r1
a1 = 45.4*10**-6 # Inner thermal diffusivity (m^2/s)
a2 = 101.2*10**-6 # Outer thermal diffusivity (m^2/s)
a = (a1+a2)/2
T1 = 303 # Inner uniform temperature (K), where t = 0 s
T2 = 393 # Outer uniform temperature (K), where t = 0 s
tt = 200 # Total time (s)
dr = 0.001 # (m)
dt = 0.05 # (s)
tol = 0.1 # Absolute tolerance (K)
lam = a*dt/dr/dr # Parameter for convergence rate
print('lambda = % f ' %(lam));
nt = int(tt/dt)+1 # Number of time segments
nr = int(r/dr)+1
rr = np.linspace(0,r,num=nr,endpoint=True)
nn = nr-1 # One fixed boundary
# Create tridiagonal matrix
Ea = np.ones(nn)
Eb = np.ones(nn-1)
# Implicit euler
IE = np.diagflat(-lam*Eb,k=-1) \
+ np.diagflat((1+2*lam)*Ea,k=0) \
+ np.diagflat(-lam*Eb,k=1);
IE[-1,-2] = -2*lam;
# Vector of constants via BCs
ie = np.zeros(nn);
ie[0] = -lam*T1;
# Space and time matrix for T
M = T1*np.ones(nn); # Initial condition
# Implicit
MM_ie = np.zeros((nn,nt))
MM_ie[:,0] = M
# Solve inverse mats here
IE_inv = np.linalg.inv(IE)
for i in range(0,nt-1):
MM_ie[:,i+1] = np.matmul(IE_inv,MM_ie[:,i]-ie);
wa = T1*np.ones((1,nt));
MM_ie = np.concatenate((wa,MM_ie))
def show_plot(time) :
tind = int(time/dt)
print("time index: %d" % tind)
print(MM_ie.shape)
fig = plt.figure()
ax = plt.axes(xlim=(0, r), ylim=(0, 2*T1))
ax.plot(rr, MM_ie[:,tind], lw=2)
time_template = 'time = %4.2f s'
time_text = ax.text(0.75, 0.90,time_template % time,transform=ax.transAxes)
plt.xlabel('Radius (m)')
plt.ylabel('Temperature, K')
plt.title('Temperature Profile')
plt.show()
show_plot(1)
show_plot(10)
show_plot(30)
show_plot(70)
show_plot(200)

FTCS Solution of the Wave Equation - Issues with Vpython

I am attempting to make an animation of the motion of the piano string
using the facilities provided by the vpython package. There are
various ways you could do this, but my goal is to do this with using
the curve object within the vpython package. Below is my code for
solution of the initial problem of solving the complete sets of
simultaneous 1st-order equation. Thanks in advance, I am really
uncertain as to where to start with the vpython animation.
# Key Module and Function Import(s):
import numpy as np
import math as m
import pylab as py
import matplotlib
from time import time
import scipy
# Variable(s) and Constant(s):
L = 1.0 # Length on string in m
C = 1.0 # velocity of the hammer strike in ms^-1
d = 0.1 # Hammer distance from 0 to point of impact with string
N = 100 # Number of divisions in grid
sigma = 0.3 # sigma value in meters
a = L/N # Grid spacing
v = 100.0 # Initial velocity of wave on the string
h = 1e-6 # Time-step
epsilon = h/1000
# Computation(s):
def initialpsi(x):
return (C*x*(L-x)/(L**2))*m.exp((-(x-d)**2)/(2*sigma**2)) # Definition of the function
phibeg = 0.0 # Beginning - fixed point
phimiddle = 0.0 # Initial x
phiend = 0.0 # End fixed point
psibeg = 0.0 # Initial v at beg
psiend = 0.0 # Initial v at end
t2 = 2e-3 # string at 2ms
t50 = 50e-3 # string at 50ms
t100 = 100e-3 # string at 100ms
tend = t100 + epsilon
# Creation of empty array(s)
phi = np.empty(N+1,float)
phi[0] = phibeg
phi[N] = phiend
phi[1:N] = phimiddle
phip = np.empty(N+1,float)
phip[0] = phibeg
phip[N] = phiend
psi = np.empty(N+1,float)
psi[0] = psibeg
psi[N] = psiend
for i in range(1,N):
psi[i] = initialpsi(i*a)
psip = np.empty(N+1,float)
psip[0] = psibeg
psip[N] = psiend
# Main loop
t = 0.0
D = h*v**2 / (a*a)
timestart = time()
while t<tend:
# Calculation the new values of T
for i in range(1,N):
phip[i] = phi[i] + h*psi[i]
psip[i] = psi[i] + D*(phi[i+1]+phi[i-1]-2*phi[i])
phip[1:N] = phi[1:N] + h*psi[1:N]
psip[1:N] = psi[1:N] + D*(phi[0:N-1] + phi[2:N+1] -2*phi[1:N])
phi= np.copy(phip)
psi= np.copy(psip)
#phi,phip = phip,phi
#psi,psip = psip,psi
t += h
# Plot creation in step(s)
if abs(t-t2)<epsilon:
t2array = np.copy(phi)
py.plot(phi, label = "2 ms")
if abs(t-t50)<epsilon:
t50array = np.copy(phi)
py.plot(phi, label = "50 ms")
if abs(t-t100)<epsilon:
t100array = np.copy(phi)
py.plot(phi, label = "100 ms")
See the curve documentation at
https://www.glowscript.org/docs/VPythonDocs/curve.html
Use the "modify" method to change the individual points along the curve object, inside a loop that contains a rate statement:
https://www.glowscript.org/docs/VPythonDocs/rate.html

Floating RMS in Python

I'm trying to implement a floating window RMS in python. I'm simulating an incoming stream of measurement data by simpling iterating over time and calculating the sine wave. Since it's a perfect sine wave, its easy to compare the results using math. I also added a numpy calculation to confirm my arrays are populated correctly.
However my floating RMS is not returning the right values, unrelated to my sample size.
Code:
import matplotlib.pyplot as plot
import numpy as np
import math
if __name__ == '__main__':
# sine generation
time_array = []
value_array = []
start = 0
end = 6*math.pi
steps = 100000
amplitude = 10
#rms calc
acc_load_current = 0
sample_size = 1000
for time in np.linspace(0, end, steps):
time_array.append(time)
actual_value = amplitude * math.sin(time)
value_array.append(actual_value)
# rms calc
acc_load_current -= (acc_load_current/sample_size)
# square here
sq_value = actual_value * actual_value
acc_load_current += sq_value
# mean and then root here
floating_rms = np.sqrt(acc_load_current/sample_size)
fixed_rms = np.sqrt(np.mean(np.array(value_array)**2))
math_rms = 1/math.sqrt(2) * amplitude
print(floating_rms)
print(fixed_rms)
print(math_rms)
plot.plot(time_array, value_array)
plot.show()
Result:
2.492669969708522
7.071032456438027
7.071067811865475
I solved the issue by usin a recursive average with zero crossing detection:
import matplotlib.pyplot as plot
import numpy as np
import math
def getAvg(prev_avg, x, n):
return (prev_avg * n + x) / (n+1)
if __name__ == '__main__':
# sine generation
time_array = []
value_array = []
used_value_array = []
start = 0
end = 6*math.pi + 0.5
steps = 10000
amplitude = 325
#rms calc
rms_stream = 0
stream_counter = 0
#zero crossing
in_crossing = 0
crossing_counter = 0
crossing_limits = [-5,5]
left_crossing = 0
for time in np.linspace(0, end, steps):
time_array.append(time)
actual_value = amplitude * math.sin(time) + 4 * np.random.rand()
value_array.append(actual_value)
# detect zero crossing, by checking the first time we reach the limits
# and then not counting until we left it again
is_crossing = crossing_limits[0] < actual_value < crossing_limits[1]
# when we are at amp/2 we can be sure the noise is not causing zero crossing
left_crossing = abs(actual_value) > amplitude/2
if is_crossing and not in_crossing:
in_crossing = 1
crossing_counter += 1
elif not is_crossing and in_crossing and left_crossing:
in_crossing = 0
# rms calc
# square here
if 2 <= crossing_counter <= 3:
sq_value = actual_value * actual_value
rms_stream = getAvg(rms_stream, sq_value, stream_counter)
stream_counter += 1
# debugging by recording the used values
used_value_array.append(actual_value)
else:
used_value_array.append(0)
# mean and then root here
stream_rms_sqrt = np.sqrt(rms_stream)
fixed_rms_sqrt = np.sqrt(np.mean(np.array(value_array)**2))
math_rms_sqrt = 1/math.sqrt(2) * amplitude
print(stream_rms_sqrt)
print(fixed_rms_sqrt)
print(math_rms_sqrt)
plot.plot(time_array, value_array, time_array, used_value_array)
plot.show()

Matrix vs scalar expression mismatch when using NumPy

Whilst running a simulation of a discrete-time system, I'm having trouble getting the equivalent scalar expressions of the original matrix equation to generate identical output (I need to convert all matrix expressions to scalars in order to implement the code in my embedded C project).
Please run the function with the following input parameters.
torque_sim_ctest(0.006,0,0.01,12)
Click the hyperlinks to see screen-shots of the expected output computed using the matrix expression (correct) vs. the output using the (supposedly) equivalent scalar expressions (incorrect).
Below is the code, which should give the correct output by default. To test the scalar computations, please comment line # 98 (qo_next = np.dot(Ado,qo) + np.dot(Bo,np.vstack([hallf, v[:,k]]))), and uncomment 100 through 102, run the script, and then call the function with the same parameters as shown above.
Lines to uncomment in tandem with the qo_next = ... matrix expression highlighted above:
# qo_next[0] = Ado[0,0]*qo[0] + Ado[0,1]*qo[1] + Ado[0,2]*qo[2] + Bo[0,0]*hallf
# qo_next[1] = Ado[1,0]*qo[0] + Ado[1,1]*qo[1] + Ado[1,2]*qo[2] + Bo[1,0]*hallf + Bo[1,1]*v[:,k]
# qo_next[2] = Ado[2,0]*qo[0] + Ado[2,1]*qo[1] + Ado[2,2]*qo[2] + Bo[2,0]*hallf
I would really appreciate it if someone could point out the bug in the scalar version of the code and help me fix this (numerical?) issue. Thank you!
import numpy as np
import scipy.signal as sig
import matplotlib.pyplot as plt
def torque_sim_ctest(K,Kp,Kd,tau_ampl):
# Example parameter values: torque_sim_ctest(0.006,0,0.01,12)
# -----------------------------------------------------------------------------
# Motor & System Parameters in continuous time:
bm, Jm, K_e, K_t = 1.5e-6, 3.507e-6, 12.5e-3, 12.5e-3
R, L = 0.476, 0.334e-3
gr, Jl, bl = 16.348, 10, 20
Jeq, beq = Jl + Jm*gr**2, bl + bm*gr**2
A = np.array([ [ 0, 1 ],
[ 0, -beq/Jeq ] ])
Ac = np.array( [[ 0, 1, 0 ],
[ 0, 0, 1 ],
[ 0, 0, 0 ]])
B = np.array([ [ 0, 0 ],
[ gr/Jeq, gr**2*K_t/(Jeq*R) ]])
Bc = np.array([ 0, 1, 0 ]).reshape(3,1)
C = np.array([ 1, 0 ])
Co = np.array([ 1, 0, 0 ]).reshape(1,3)
# -----------------------------------------------------------------------------
# Controller update interval Tc and simulation time step Td
Tc = 0.01
Td = 0.1*Tc
# Now discretise the continuous-time system model
Ad, Bd, Cd, Dd, dt = sig.cont2discrete((A,B,C,0),Td,method='bilinear')
# Output smoothing: filter parameters
f_ord = 2
num, den = sig.cheby1(f_ord,5,2*np.pi*10,'low',analog=True)
Af, Bf, Cf, Df = sig.tf2ss(num,den)
Afd, Bfd, Cfd, Dfd, dt = sig.cont2discrete((Af,Bf,Cf,Df),Tc,
method='bilinear')
# -----------------------------------------------------------------------------
# Observer Parameters
eps = 0.01
alph = Tc/eps
a1, a2, a3 = 3, 3, 1
Ho = np.array([a1, a2, a3]).reshape(3,1)
Ao = Ac - np.dot(Ho,Co)
D = np.diag([1, eps, eps**2])
Do = np.zeros([3,1])
Ado, Bdo, Cdo, Ddo, dt = sig.cont2discrete((Ao,Ho,np.linalg.inv(D),Do),
alph,method='bilinear')
Bo = np.hstack([Bdo.reshape(3,1), Bc.reshape(3,1)])
# -----------------------------------------------------------------------------
# Total simulation steps
n = 5001
# Define initial conditions prior to running simulation
x, q = np.zeros([2,n]), np.zeros([2,1])
q_next = np.zeros([2,1])
y, v = 0, np.zeros([1,n])
tau_ext = np.zeros([1,n])
hallc = 0
qf, qf_next, hallf = np.zeros([f_ord,1]), np.zeros([f_ord,1]), 0
qo, qo_next, xhat = np.zeros([3,1]), np.zeros([3,1]), np.zeros([3,1])
# The for loop below simulates the closed-loop system in discrete time steps Td
print('Simulation running; please wait ...')
for k in range(n-1):
# External torque input with peaks at 0.5 s and 1.6 s
tau_ext[:,k] = tau_ampl*(0.5*np.exp(-10*(k*Td-0.5)**2) \
+ np.exp(-5*(k*Td-1.6)**2))
# y is the output angle in SI units (radians)
y = gr*np.dot(C,x[:,k])
# Conversion of rotor angle to ideal hall-count
hallc = int(150/np.pi*y+0.5*np.sign(y))
# Now apply a smoothing filter
# qf_next = Afd # qf + Bfd # np.matrix([hallc[:,k]/gr])
# hallf = Cf # (qf + qf_next)
qf_next[0] = 0.661939208333454*qf[0] - 19.836230603818*qf[1] + 0.00830969604166727*hallc/gr
qf_next[1] = 0.00830969604166727*qf[0] + 0.90081884698091*qf[1] + 4.15484802083364e-5*hallc/gr
# Filtered hall-count
hallf = 1342.37547903*(qf[1] + qf_next[1])
# -----------------------------------------------------------------------------
# State Observer & Control Law
# Update the controller states only every Tc = 10*Td time step
if np.mod(k,int(Tc/Td+0.5)) == 0:
qo_next = np.dot(Ado,qo) + np.dot(Bo,np.vstack([hallf, v[:,k]]))
# qo_next[0] = Ado[0,0]*qo[0] + Ado[0,1]*qo[1] + Ado[0,2]*qo[2] + Bo[0,0]*hallf
# qo_next[1] = Ado[1,0]*qo[0] + Ado[1,1]*qo[1] + Ado[1,2]*qo[2] + Bo[1,0]*hallf + Bo[1,1]*v[:,k]
# qo_next[2] = Ado[2,0]*qo[0] + Ado[2,1]*qo[1] + Ado[2,2]*qo[2] + Bo[2,0]*hallf
# qo_next[0] = 1.40740740740741*hallf - 0.407407407407407*qo[0] + 0.296296296296296*qo[1] + 0.148148148148148*qo[2]
# qo_next[1] = 1.03703703703704*hallf - 1.03703703703704*qo[0] + 0.481481481481481*qo[1] + 0.740740740740741*qo[2] + v[:,k]
# qo_next[2] = 0.296296296296296*hallf - 0.296296296296296*qo[0] - 0.148148148148148*qo[1] + 0.925925925925926*qo[2]
xhat[0] = 0.703703703703704*hallf + 0.296296296296296*qo[0] + 0.148148148148148*qo[1] + 0.0740740740740741*qo[2]
xhat[1] = 51.8518518518519*hallf - 51.8518518518518*qo[0] + 74.0740740740741*qo[1] + 37.037037037037*qo[2]
xhat[2] = 1481.48148148148*hallf - 1481.48148148148*qo[0] - 740.740740740741*qo[1] + 9629.62962962963*qo[2]
# xhat = Cdo # qo + Ddo # np.matrix(hallf)
# Update the control voltage v[:,k]
v[:,k] = K*xhat[2] + Kp*hallf + Kd*xhat[1]
if v[:,k] < 0:
v[:,k] = 0
elif v[:,k] >= 12:
v[:,k] = 12
else:
# Wait and hold; don't update in this cycle
qo_next = qo
v[:,k] = v[:,k-1]
# -----------------------------------------------------------------------------
# Now calculate the system dynamics in discrete time steps Td
q_next = np.dot(Ad,q) + np.dot(Bd,np.vstack([tau_ext[:,k], v[:,k]]))
x[:,k+1:k+2] = q + q_next
q = q_next
qf[0] = qf_next[0]
qf[1] = qf_next[1]
qo[0] = qo_next[0]
qo[1] = qo_next[1]
qo[2] = qo_next[2]
# ** End For Loop **
# Plot the simulation output
# NOTE: System velocity signal is x[1,:], and position is y = x[0,:]
print('Done.')
tau_spr = gr*K_t/R*v[0,0:n-1]
tau_net = tau_spr + tau_ext[0,0:n-1]
t = np.linspace(0.0,(n-1)*Td,num=n-1)
fig1, ax1 = plt.subplots(2,2)
ax1[0,0].plot(t,tau_ext[0,0:n-1],'r--',t,tau_spr,'b-')
ax1[0,0].set_xlabel('Time (s)')
ax1[0,0].set_ylabel('Torque (N m)')
ax1[0,0].set_title('Torque Comparison')
ax1[0,1].plot(t,tau_ext[0,0:n-1]/tau_net,'r--',t,tau_spr/tau_net,'b-')
ax1[0,1].set_xlabel('Time (s)')
ax1[0,1].set_ylabel('Torque (Normalised)')
ax1[0,1].set_title('Torque Comparison')
ax1[1,0].step(t,v[0,0:n-1],'g-')
ax1[1,0].set_xlabel('Time (s)')
ax1[1,0].set_ylabel('Drive Voltage (V)')
ax1[1,0].set_title('Motor Voltage')
ax1[1,1].step(t,30/np.pi*x[1,0:n-1],'m-')
ax1[1,1].set_xlabel('Time (s)')
ax1[1,1].set_ylabel('Motor Speed (rpm)')
ax1[1,1].set_title('Motor Speed vs Time')
Phew, I may have finally got to the bottom of my issue, even though I don't fully understand the nature of the problem with array vs. scalar assignments.
When I use the vector computation: qo_next = np.dot(Ado,qo) + np.dot(Bo,np.vstack([hallf, v[:,k]])), then my implementation of the Zero-Order-Hold further down: qo_next = qo appears to work as one would expect.
When I convert the first assignment to a set of scalar expressions, however, it appears I must also do an element-by-element assignment to implement the Z.O.H., i.e.:
qo_next[0] = qo[0]
qo_next[1] = qo[1]
qo_next[2] = qo[2]
When I do that, the scalar conversion magically works and generates output equivalent to the vector version.
That was a real head-scratcher -- perhaps someone can explain to me how assignment works in Python so I can make sense of this. Thank you for reading.

Categories