How do I use fsolve to find theta2? - python

I need to solve the attached equation for "theta2" given the attached values. There should be 56 results because there are 7 different insulation thicknesses(Linsluation/d2/hc), 4 different temperatures (theta1), and 2 e values (em, ec) which must be tested.
Given data:
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
[enter image description here](https://i.stack.imgur.com/MgBrp.png)
I tried:
import math
import sympy as sym
from sympy import symbols, Eq, solve
import scipy
from scipy.optimize import fsolve
from math import pi
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
def fun(e):
for i in range(len(Linsulation)):
for j in range(len(theta1)):
return (pi)*d2[i]*hc[i]*(theta2-theta3)+(pi)*d2[i]*e*sigma*(((theta2+460)**4)-((theta3+460)**4))-(2*(pi)*k*(theta1[j]-theta2))/ln(d2[i]/d1)
theta2 = fsolve(fun(em))
print(theta2)
I don't understand how fsolve should work in this context. What is the best way I can solve the equation for multiple values and when the variables cannot be separated?
Attempt 2:
import math
import sympy as sym
from sympy import symbols, Eq, solve
import scipy
from scipy.optimize import fsolve
from math import pi
k = .5
d1 = 20/12
Linsulation = [2/12,3/12,4/12,5/12,6/12,7/12,8/12]
em = .09
ec = .9
sigma = .171*10**(-8)
theta1 = [800, 900, 1000, 1100]
theta3 = 70
d2 = []
for i in range(len(Linsulation)):
di = (d1+(2*Linsulation[i]))
d2.append(di)
pi=math.pi
theta2 = sym.symbols("theta2")
hc=[]
for i in range(len(d2)):
hi = .270*((theta2-theta3)**(.25))*(d2[i]**(-.25))
hc.append(hi)
def fcn(theta2):
for i in range(len(Linsulation)):
for j in range(len(theta1)):
LHS = (pi)*d2[i]*hc[i]*(theta2-theta3)+(pi)*d2[i]*em*sigma*(((theta2+460)**4)-((theta3+460)**4))-(2*(pi)*k*(theta1[j]-theta2))/ln(d2[i]/d1)
return LHS
theta2_initial = 300 # Your inital guess
result = fsolve(fcn, [theta2_initial,])
Resulted in:
error: Result from function call is not a proper array of floats.

If you look at the documentation https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.fsolve.html you see that fsolve has two required arguments. The first is a callable, i.e. a function, or a function handle. The second is an initial "guess" for the variable you want to solve for.
So to use fsolve you would first define a function that will return 0 for the correct value of its input:
def fcn(theta2):
# rewrite your equation as LHS(theta2) = 0
LHS = # Some expression depending on theta2
return [LHS,] # fsolve requires input and output to be the same shape.
# Now call fsolve
theta2_initial = # Your inital guess
result = fsolve(fcn, [theta2_initial,]) # Note fsolve expects an array in general as it can solve multivariable equations.
See the documentation page for a complete example.

Related

Solving/graphing derivative equations

I am a student and am trying to figure out how to solve differential equations with python but I am very confused. I am also getting a syntax error on the fourth to last line, and I am not sure why. This model is supposed to show the progression of a virus.
import numpy as np
from scipy.integrate import odeint
import matplotlib.pyplot as plt
# function that returns dT/dt
# initial condition
T = 1
V = .001
I = 0
def model(t,T,I,V):
β = 10**-5
δ = 4
p = 2*(10**6)
c = 4
dTdt = -β*t*V
dIdt = (β*T*V) - (δ*I)
dVdt = (p*I) - (c* V)
return dTdt, dIdt,dVdt
# initial condition
T0 = 1
V0 = 10**-3
I0 = 0
# time points
t = np.linspace(0,25)
# solve
V = odeint(model,t,V0, args = (T0,I0)
# plot results
plt.plot(t,V)
plt.xlabel('time')
plt.ylabel('V(t)')
plt.show()
The state vector is one single argument in the ODE function. So you have to replace its first line with
def model(Y,t):
T,I,V = Y
and correct the integrator call to
Y = odeint(model,[T0,I0,V0],t)
T,I,V = Y.T

Trouble computing integral with scipy quad

I'm trying to compute the following definite integral:
Integral I want to compute:
where rho_ch is
and
a = 3.66 * 10^(-15) m (in meters)
b = 0.54 * 10^(-15) m
and rho_0 = 1.23 * 10^(-35) C/m^3.
When I compute it, I get something of the order of 10^(-61), but I believe it should be something closer to 1.
I take the upper limit of the integral to 10^(-10) because the integral should have converged by then. My guess is that the problem has do with overflow in the rho_ch function, although I tried a fix for that, but it didn't work.
Does anyone have any idea of what I'm doing wrong?
import numpy as np
from scipy.constants import *
from scipy import integrate
Z_t = 20
a = 1.07*40**(1/3)
b = 0.54
rho_0 = 0.077*e
X_0 = np.array([rho_0, a, b])*10**(-15)
E = 250*10**(6)*e
p_sq = (E/c)**2-(m_e*c)**2
beta_sq = 1-(1/(E/(m_e*c**2))**2)
theta = np.pi/6
def q(theta):
return 2*np.sqrt(p_sq*np.sin(theta/2)**2)
def F_quad(theta, X):
return 4*np.pi*hbar/(Z_t*e*q(theta))*integrate.quad(integrand2, 0, 10**(-10), args=(theta, X))[0]
integrand2 = lambda r, theta, X: r*X[0]/(1+np.exp((r-X[1])/X[2]))*np.sin(q(theta)*r/hbar) if (r-X[1])/X[2] <= 600 else 0

Error using scicpy.integrate.odeint and sympy symbols

I'm trying to solve the following system: d²i/dt² + R'(i)/L di/dt + 1/LC i(t) = 1/L dE/dt as a set of coupled first order differential equations:
di/dt = k
dk/dt = 1/L dE/dt - R'(i)/L k - 1/LC i(t)
Here is the code I'm using:
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
from scipy.integrate import odeint
#Define model: x = [i , k]
def RLC(x , t):
i = sp.Symbol('i')
t = sp.Symbol('t')
#Data:
E = sp.ln(t + 1)
dE_dt = E.diff(t)
R1 = 1000 #1 kOhm
R2 = 100 #100 Ohm
R = R1 * i + R2 * i**3
dR_di = R.diff(i)
i = x[0]
k = x[1]
L = 10e-3 #10 mHy
C = 1.56e-6 #1.56 uF
#Model
di_dt = k
dk_dt = 1/L * dE_dt - dR_di/L * k - 1/(L*C) * i
dx_dt = np.array([di_dt , dk_dt])
return dx_dt
#init cond:
x0 = np.array([0 , 0])
#time points:
time = np.linspace(0, 30, 1000)
#solve ODE:
x = odeint(RLC, x0, time)
i = x[: , 0]
However, I get the following error: TypeError: Cannot cast array data from dtype('O') to dtype('float64') according to the rule 'safe'
So, I don't know if sympy and odeint don't work well together. Or maybe is it a problem because I defined t as sp.Symbol?
When you differentiate a function, you get a function back. So you need to evaluate it at a point in order to get a number. To evaluate a sympy expression, you could use .subs() but I prefer .replace() which feels more powerful (at least for me).
You must try and make every single variable have its own name in order to avoid confusion. For example, you replace the float input t with a sympy Symbol from the very beginning, thus losing the value of t. The variables x and i are also repeated in the outer scope which is not good practice if they mean different things.
The following should avoid confusion and hopefully produce something that you were expecting:
import numpy as np
import sympy as sp
import matplotlib.pyplot as plt
from scipy.integrate import odeint
# Define model: x = [i , k]
def RLC(x, t):
# define constants first
i = x[0]
k = x[1]
L = 10e-3 # 10 mHy
C = 1.56e-6 # 1.56 uF
R1 = 1000 # 1 kOhm
R2 = 100 # 100 Ohm
# define symbols (used to find derivatives)
i_symbol = sp.Symbol('i')
t_symbol = sp.Symbol('t')
# Data (differentiate and evaluate)
E = sp.ln(t_symbol + 1)
dE_dt = E.diff(t_symbol).replace(t_symbol, t)
R = R1 * i_symbol + R2 * i_symbol ** 3
dR_di = R.diff(i_symbol).replace(i_symbol, i)
# nothing should contain symbols from here onwards
# variables can however contain sympy expressions
# Model (convert sympy expressions to floats)
di_dt = float(k)
dk_dt = float(1 / L * dE_dt - dR_di / L * k - 1 / (L * C) * i)
dx_dt = np.array([di_dt, dk_dt])
return dx_dt
# init cond:
x0 = np.array([0, 0])
# time points:
time = np.linspace(0, 30, 1000)
# solve ODE:
solution = odeint(RLC, x0, time)
result = solution[:, 0]
print(result)
Just something to note: the value i = x[0] seemed to sit very close to 0 throughout each iteration. This means dR_di stayed basically at 1000 the whole time. I'm not familiar with odeint or your specific ODE, but hopefully this phenomenon is expected and isn't a problem.

Solving an ODE with complex coefficients in python

I have a system of coupled ODEs with complex coefficients. I have figured out how to numerically solve a system with real values coefficients, for example,
u0' = u1
u1' = u0
To do this I use scipy.integrate.odeint class as follows,
def vectorfield(w,t):
u0,u1 = w
#create f = [x1',y1',...]
f = [u1, u0]
return f
wsol = odeint(vectorfield, w0, t)
where w0 is the initial value of w for example:
w0 = [1,1]
However now I need to solve a system with complex coefficients, say
u0' = i*u1
u1' = i*u0
However, when I tried using the same method as I did for the real valued coefficients, I don't get any complex numbers in the result, only real valued answers at each time step. How should I change the above code to account for complex coefficients?
Thanks in advance.
EDIT, here is my entire code for an example:
#coupled differential equations
from scipy.integrate import odeint
from scipy.integrate import ode
import numpy as np
import matplotlib.pyplot as plt
import math
from scipy import eye
# Setting initital conditions
u_initial = [1,1]
def vectorfield(w,t):
u0,u1 = w
#create f = [x1',y1',...]
f = [1j*u1*u1.conjugate()+u0,1j*u0*u0.conjugate()+u1]
return f
abserr = 1.0e-8
relerr = 1.0e-6
stoptime = 10
numpoints = 300
t = [stoptime * float(i) / (numpoints - 1) for i in range(numpoints)]
w0 = u_initial #set initial conditions
wsol = odeint(vectorfield, w0, t,
atol=abserr, rtol=relerr)

Finding the roots of an equation numerically returns the initial guess

I am trying to find the root of a cubic equation using fsolve. This is my code:
from scipy import *
from scipy.optimize import fsolve
import matplotlib.pyplot as plt
import numpy as np
#These are all parameters
g = 5.61
gamma = 6.45
kappa = 6.45
J = 6.45
rs = 10.0
m = 5.0*10**(-11)
wm = 2*3.14*23.4
r2 = np.linspace(0, 0.02, 1000)
deltaW = 0
A = 1j*g**2*(kappa + 1j*deltaW)*r2*r2/(m*wm**2)
B = J**2 + (1j*deltaW - gamma)*(1j*deltaW + kappa)
C = A + B
D = abs(C)*r2 - J*np.sqrt(2*kappa)*rs
def func(x):
D = abs(C)*r2 - J*np.sqrt(2*kappa)*rs
return D
x0 = fsolve(func, 0.0)
print x0
plt.plot(r2, D)
plt.show()
I can see from the plot that there is at least one r2 that makes D zero. However, the return value x0 I get from fsolve is always the guess value I set.
Can anyone tell me why this is happening and how to fix it?
You are passing to fsolve a function that isn't a function at all: it doesn't do anything with the inputs x. Yet, fsolve needs that, because it will test a series of values and each time check the return value from the function call with that test value. In your case, func(x) never changes, so fsolve stops with an error message of
The iteration is not making good progress, as measured by the improvement from the last ten iterations.
You could see that message if you would add full_output=True in the call to fsolve.
To solve it, define your function like this:
def func(x):
A = 1j*g**2*(kappa + 1j*deltaW)*x*x/(m*wm**2)
B = J**2 + (1j*deltaW - gamma)*(1j*deltaW + kappa)
C = A + B
D = abs(C)*x - J*np.sqrt(2*kappa)*rs
return D

Categories