I am trying to numerically solve the following ODE
with boundary conditions
y(x=0)=0;y(x=20)=1
Where f(x) is the solution of another ODE that I already solved numerically. I am trying to solve my ODE with https://docs.scipy.org/doc/scipy-0.18.1/reference/generated/scipy.integrate.solve_bvp.html, but the problem that I have is that f(x) is written as a list for
coordinates x = np.arange(0,20.01,0.05)
and I do not know how to insert the list in scipy.integrate.solve_bvp to obtain the solution of ODE.
Thanks in advance
The best way is to solve the coupled system, that is to integrate the DE for f at the same time as the current DE. If this is a variant of your previous problem on math.SE then this coupled approach is unavoidable.
As for the literal solution, use interpolation
def f(x): return numpy.interp(x, x_samples, f_samples)
and then call this function in the ODE function
def y_ODE(x,y): return [y[1], -0.5*f(x)*y[1]]
Related
I have an assignment where I need to make a single defined function that runs newtons method and then be able plug in other defined functions to it and it will solve them all. I wrote one that works for equations that have 1 variable, and I only need to solve for one variable from the system but I don't know how to do that in code without solving for all four of them.
the function I wrote to run newtons method is this:
def fnewton(function, dx, x, n):
#defined the functions that need to be evaluated so that this code can be applied to any function I call
def f(x):
f=eval(function)
return f
#eval is used to evaluate whatever I put in the function place when I recall fnewton
#this won't work without eval to run the functions
def df(x):
df=eval(dx)
return df
for intercept in range(1,n):
i= x-(f(x)/df(x))
x= i
#this is literally just newtons method
#to find an intercept you can literally input intercept in a for loop and it'll do it for you
#I just found this out
#putting n in the range makes it count iterations
print ('root is at')
print (x)
print ('after this many iterations:')
print (n)
my current system of equations function looks like this:
def c(x):
T=x[0]
y=x[1]
nl=x[2]
nv=x[3]
RLN=.63*Antoine(An,Bn,Cn,T)-y*760
RLH=(1-.63)*Antoine(Ah,Bh,Ch,T)-(1-y)*760
N=.63*nl+y*nv-50
H=(1-.63)*nl+(1-y)*nv-50
return[RLN,RLH,N,H]
To use my function to solve this I've entered multiple variations of:
fnewton("c(x)","dcdx(x)", (2,2,2,2), 10)
Do I need to change the system of equations into 1 equation somehow or something I don't know how to manipulate my code to make this work and also work for equations with only 1 variable.
To perform Newton's method in multiple dimensions, you must replace the simple derivative by a Jacobian matrix, that is, a matrix that has the derivatives of all components of your multidimensional function with respect to all given variables. This is decribed here: https://en.wikipedia.org/wiki/Newton%27s_method#Systems_of_equations,
(or, perhaps more helpful, here: https://web.mit.edu/18.06/www/Spring17/Multidimensional-Newton.pdf in Sec. 1.4)
Instead of f(x)/f'(x), you need to work with the inverse of the Jacobian matrix times the vector function f. So the formula is actually quite similar!
I was working on some linear equation problems regarding spline function, which already exists in our beautiful Python library, but the thing is that my professor requested me to find out the every coefficients of spline function so that I can fully understand its mathematical structure.
As a result, I came out with some simultaneous linear equations - the number of equations depend on the user input.
So I allocated my variables dynamically so that if the user declares he/she will utilize 3 points, it prints out 3 equations, and if declare 4 points, prints out 4 equations, and so on.
and now I have to solve these equations without even knowing how many equations there will be.
I searched some methods for solving linear equations using solve of Sympy, but none of them were showing me how to call these equations dynamically, depending on the user input.
All articles were saying like, oh it's easy, you can write as:
solve((eq1, eq2), dict=True)
but mine will be like :
solve((eq1, eq2, eq3, eq4, eq5, eq6, ... )
and the variables will be also like (a_0, a_1, a_2, a_3, ...)
I was trying to use 'eq{}'.format(i) to call all the 'eq{}'s I made, but systematically failed for the reason I don't know.
How can I call all the equations and variables I made in 'solve' method dynamically?
I'm a newbie to Python, please help me......
If there are not symbolic variables other than the ones for which you want to solve, then my favorite way of getting the symbols is:
def neq(n):
return list or tuple containing the n equations
from sympy import Tuple, solve
eqs = Tuple(*neq(n))
syms = eqs.free_symbols
sol = solve(eqs, syms)
You will get back a single dictionary (or a list of dictionaries) with the mapping for the symbol: solution.
I want to solve a second order differential equation with variable coefficients by using something like odeint. The problem with this one is that it doesn't work if the initial conditions are complex (which is the case now).
Do you know a way to solve the aforementioned equation with something similar to odeint?
odeint does not accept complex variables. You could use: the newer solver, solve_ivp; the older ode class with the "zvode" integrator; or odeintw, a wrapper of odeint that I wrote that handles complex-valued and matrix-valued differential equations.
You could always work with the real components (odeint convention)
def odesys(u,t):
z = u[0]+1j*u[1]
dz = u[2]+1j*u[3]
d2z = f(t,z,dz)
return [ dz.real, dz.imag, d2z.real, d2z.imag ]
where f stands for the explicit form of the second order ODE.
If I remember correctly, one of the methods ("vzode"?) that you can use in scipy.integrate.ode works directly with complex state variables.
Here's what I wrote: it's a classical exercise on interpolation, which I already finished and sent. I was wondering if there was another (longer) way...
q is a list of floats (the points of interpolation)
i is the index of the Lagrange polynomial
x is the point where is evaluated:
def l(q,i,x):
poly=1.0
for j,p in enumerate(q):
if j==i:
continue
poly *=(x-p)/(q[i]-p)
return poly
Then there is the function on which I'm working:
def Lambda(q,x):
value=0.0
for j in range(0,len(q)):
value+=abs(l(q,j,x))
return value
Now I can use some routines of python to find it's maxium value in the interval [0,1] and I did.
In python there is a polynomial module, with which I can easily re-define l:
import numpy.polynomial.polynomial as P
def l_poly(q,i):
poly = []
for j,p in enumerate(q):
if j==i:
continue
poly.append(p/(q[i]-p))
return P.polyfromroots(poly)
I'd like to do the same with Lambda so that I can find its maximum using the built in function of the derivative (find its zeros and so on and so forth). The problem is that it is a sum of abs(polynomials). Is there a way to do this? Or to mix the polynomial derivative and the derivative of abs(...)?
NumPy does not support arbitrary symbolic expression. It works only with polynomials, representing a polynomial as an array of coefficients. The absolute value of a polynomial is not a polynomial, so it is not a concept that NumPy has. It's a symbolic expression that can be handled by symbolic manipulation libraries like SymPy.
using the built in function of the derivative (find its zeros and so on and so forth).
There are several problems with this:
As said before, the polyder method of NumPy does not apply to this situation, since abs(polynomial) is not a polynomial.
The derivative of absolute function is undefined at 0.
The minimum or maximum of an expression involving absolute values may be attained where the derivative does not exist, so even if you could find the derivative, and somehow find its roots, you still would not solve the problem.
Looking for zeros of derivative is not a good way to minimize or maximize a function, outside of calculus exercises. Libraries like scipy.optimize implement many efficient numerical methods for this kind of problems.
I'm using fsolve in order to solve a non linear equation. My problem is that, depending on the starting point the solutions change and I am not sure that the ones that I found are the most reasonable.
This is the code
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import fsolve, brentq,newton
A = np.arange(0.05,0.95,0.01)
PHI = np.deg2rad(np.arange(0,90,1))
def f(b):
return np.angle((1+3*a**4-3*a**2)+(a**4-a**6)*(np.exp(2j*b)+2*np.exp(-1j*b))+(a**2-2*a**4+a**6)*(np.exp(-2j*b)+2*np.exp(1j*b)))-Phi
B = np.zeros((len(A),len(PHI)))
for i in range(len(A)):
for j in range(len(PHI)):
a = A[i]
Phi = PHI[j]
b = fsolve(f, 1)
B[i,j]= b
I fixed x0 = 1 because it seems to give the more reasonable values. But sometimes, I think the method doesn't converge and the resulting values are too big.
What can I do to find the best solution?
Many thanks!
The eternal issue with turning non-linear solvers loose is having a really good understanding of your function, your initial guess, the solver itself, and the problem you are trying to address.
I note that there are many (a,Phi) combinations where your function does not have real roots. You should do some math, directed by the actual problem you are trying to solve, and determine where the function should have roots. Not knowing the actual problem, I can't do that for you.
Also, as noted on a (since deleted) answer, this is cyclical on b, so using a bounded solver (such as scipy.optimize.minimize using method='L-BFGS-B' might help to keep things under control. Note that to find roots with a minimizer you use the square of your function. If the found minimum is not close to zero (for you to define based on the problem), the real minima might be a complex conjugate pair.
Good luck.