my task is to integrate the following equation for 1d Fresnel diffraction, in red in:
The point is that you are fourier transforming the aperture to a pattern on the screen, but for now just focussing on integrating the horizontal strip in 1d (ignoring the height for now). yprime is thus ignored. You also have fixed z and k, and j is an imaginary number. I have written the following code for it:
import math
import numpy as np
import cmath
k=5
z=5
x=0
j=cmath.sqrt(-1)
func=math.exp((j*k/2*z)(x-xp)*(x-xp))
def X(xp1,xp2,function,N):
h=(xp2-xp1)/N
y=0.0
xp=xp1
for x in np.arange(1, N/2 +1): #summing odd order y terms
y+=4*f(xp)
xp+=2*h
xp=xp1+2*h
for x in np.arange(0, N/2): #summing even order y terms
y+=2*f(x)
xp+=2*h
integral= (h/3)*(y+f(xp1)+f(xp2))
return integral
print(simpson(0,5,func,10))
however, it is saying that xp is not defined. but I clearly have defined xp in the function.
Does anyone have an idea what could be wrong?
Thanks
EDIT: here is a neater version of my code. But it's still asking me to define xp..
import math
import cmath
lamda=0.2
k=(2*math.pi)/lamda
z=0.1
def expfunc(x, xp):
func = math.exp(((1j)*k/2*z)(x-(xp))*(x-(xp)))
return(func)
def X(xp1,xp2,x,f,N):
h=(xp2-xp1)/N
y=0.0
xp=xp1
for i in np.arange(1, N/2 +1): #summing odd order y terms
y+=4*f(xp)
xp+=2*h
xp=xp1+2*h
for i in np.arange(0, N/2): #summing even order y terms
y+=2*f(xp)
xp+=2*h
integral= (h/3)*(y+f(xp1)+f(xp2))
return integral
print(X(0,1,x,expfunc,10))
You try to use the variable xp before you have defined it.
import math
import numpy as np
import cmath
k=5
z=5
x=0
j=cmath.sqrt(-1)
func=math.exp((j*k/2*z)(x-xp)*(x-xp)) #xp is not defined yet
You gave initial values for everything else except xp.
when you define func as you did
func=math.exp((j*k/2*z)(x-xp)*(x-xp))
you define a single value called func. What you probably want is something like that:
func = lambda x,xp : math.exp((j*k/2*z)(x-xp)*(x-xp))
and then change call of func to
y+=4*f(x, xp)
and
y+=2*f(x, xp)
I believe the issue is y+=4*f(xp) inside the first for loop of the function X.
At the very end you have print(X(0,1,x,expfunc,10)) where expfunc is acting as f in the bit of code y+=4*f(xp). The function expfunc takes two arguments, one of them defined as xp. Although the variable you pass in f is defined with the name xp, the function only sees that you have passed in the first argument x and not the argument xp.
Further, I do not see the variable x in print(X(0,1,x,expfunc,10)) defined anywhere.
Also, the second snipit of code is much different than the first. If the same questions apply then you should remove the first snipit altogether and/or rephrase your questions because from what I see in the second chuck the error you claim to be getting should not be raised.
Related
I have two equalities and an inequality relationship between them. I would like to simplify those to a single inequality (I do not need to solve the unknowns). Here is my code:
from sympy.abc import x,y
from sympy import reduce_inequalities
eq1 = np.multiply(array_1[0], (1-delta))+delta*Q[0]*[x,y]
eq2 = np.multiply(array_1[1], (1-delta)) + delta*Q[1]*[x,y]
print(reduce_inequalities(eq1, eq2))
array_1 is a 1x4 array I defined previously, and I only need one element (I choose the elements by slicing the array). Q is a 4x2 array I defined previously. The unknowns are x and y. The output I get is True.
Is there any way to simplify this with sympy or any other python library in such a way I could use the simplified version later on?
Edit: I forgot to mention delta is also defined previously.
I am attempting to create a loop that will evaluate a function at discrete values. Normally this will be okay, however, this is proving to be difficult as my function is conditional (it has an adittional piecewise function which is dependent on the main variable.) This is an attempt I made below;
import math
import numpy as np
for i in np.arange(4000,8000,1000):
def f(λ,a,u,o1,o2):
o = o1 if (λ <= u) else o2
return a*math.exp((λ-u)^2/(-2*o^2))
print(f(i,1.056,5998,379,310))
I expected the code to evaluate the function at i=4000, then i=5000 etc. The output I recieve is as follows;
TypeError: ufunc 'bitwise_xor' not supported for the input types, and the inputs could not be safely coerced to any supported types according to the casting rule ''safe''
I can't seem to find any specific examples for implementing a conditional function like this. Another attempt was made without a loop but I ran into value errors where I believe I was evaluating arrays as if they were one variable.
I wish to integrate and plot sums of the function later. Will I run into any issues with an approach involving a loop?
Python uses ** for exponentiation. ^ is bitwise xor.
Assuming your function is correct apart from the power operator **, a possible implementation with numpy would look like this
# import math # does not work well with numpy
import numpy as np
def f(l,a,u,o1,o2): # change 'λ' to 'l' (it's easier to type)
o = np.where(l <= u, o1, o2) # vectorize piecewise definition
return a*np.exp((l-u)**2/(-2*o**2)) # change '^' to '**' operator, use np.exp
x = np.arange(4000,8000,1000) # define value range
print(f(x,1.056,5998,379,310)) # call your function one time with entire range
Output
[9.74560013e-07 3.29586202e-02 1.05597802e+00 5.68878883e-03]
To reuse your function you can change it into a parameterized version
import numpy as np
def f(a,u,o1,o2):
return lambda x: a*np.exp((x-u)**2/(-2*np.where(x <= u, o1, o2)**2))
x = np.arange(4000,8000,1000)
f_p = f(1.056,5998,379,310) # parameterize your function
print(f_p(x)) # call the parameterized function with your value range
Output
[9.74560013e-07 3.29586202e-02 1.05597802e+00 5.68878883e-03]
import math
import numpy as np
def f(λ,a,u,o1,o2):
o = o1 if (λ <= u) else o2
return a*math.exp((λ-u)^2/(-2*o^2))
for i in np.arange(4000,8000,1000):
print(f(i,1.056,5998,379,310))
Try this code. This will work
I am very new to programming, and had to use sympy for a school project.
I think I get that using nonlinsolve to return an angle gives an ImageSet with the angle + 2n*pi. However I want it to return only the value of the angle (in the interval [0,pi/2]), and as one value and not an interval.
from sympy import nonlinsolve, symbols,cos
x=symbols('x')
print(nonlinsolve([cos(x)-1],[x]).args[0][0])
I want the result to be 0 and not 2*n*pi.
Clarification : I know that the result is correct, but I only want one value, that I can use algebraically, and I don't know how Sympy works (how to manipulate ImageSets)
So I might be wrong because i dont use sympy, but the solution that solvers return seems to be corect to me.
ImageSet(Lambda(_n, 2*_n*pi), Integers)
From what I understand solver returned lambda function. Cosinus is a cyclic function which means it reapeats it's value every 2PI. So the solver says first solution (_n = 0) is 0, second (_n = 1) is 2pi and so on.
look at the function plot and it will hopefully make sense:
Wolfram Alpha - (cos(x) - 1)
EDIT: I think you need to use intersect method of imageset like this( note that intersect returns all the intersections, here i selected just the first one):
from sympy import nonlinsolve, symbols,cos, Interval
import math
x = symbols('x')
f = nonlinsolve([cos(x)-1], [x]).args[0][0]
sol = f.intersect(Interval(0, math.pi/2)).args[0]
print(sol)
I need to write a function that can write and solve the inverse of tan for values that I input as two arrays. Sometimes the array on the denominator contains zero so always a division by zero occurs. I don't know how to get rid of the error and make the answer return pi/2 instead.
def deviation(x):
if capture(x)==True:
for i in range(len(yvf)):
theta=sp.arctan(xvf/yvf) #xvf and yvf are two arrays
First of all: write xvf[i] and yvf[i] to access the single elements of the arrays one after the other.
Secondly discern if yvf[i] equals zero or not:
if yvf[i] == 0:
theta = math.pi/2.0
else:
theta = sp.arctan(xvf[i]/yvf[i])
If you import numpy, I suggest using arctan2 instead of arctan (see this doc). This function manages zero values in the 2nd argument.
If not, you can solve this problem with atan2 function of math library and zip built-in function :
import math
xvf = [0.,2.,2.]
yvf = [20.,0.,2.]
def arctan(xvf,yvf):
return [math.atan2(x,y) for x,y in zip(xvf,yvf)]
print arctan(xvf,yvf)
Using Sympy, I would like to define a function of one variable where the variable is the upper limit of some integral.
I tried the following, which works
import sympy as sp
def g(a,x):
y = sp.Symbol('y')
expr = sp.Integral( f(y,p), [y,a,x] )
return expr.doit()
However, I ask myself if this is gonna be efficient when evaluated on many points. I have been reading about lambdify and would like to use it for this case, but am not sure how.
I am actually not sure if lambdify is the right way to go. In alternative, one could think of computing the indefinite integral once, and then only apply the limits to evaluate the definite integral.
Let me show an example. I have a function of one variable with some parameters, say a polynomial in y
def f(y, p):
c0,c1,c2=p
return c0+c1*y+c2*y**2
I want to define another function by integrating this polynomial, where the function is going to depend on the upper limit of the integration (Latex because I don't have enough reputation...),
g_{a,p}(x) = \int_{a}^{x} f(y,p)dy
So, in this simple case, g(x) would be polynomial or order 3 which needs to be evaluated between a and x. Once I have g(x), I want to evaluate it on "many" points, so my question is if I can do this efficiently.
I made a naive implementation of the solution and one using sympy.lambdify. Only timed it once, so not the most accurate results. However, using sympy.lambdify seems 100x faster.
Naive implementation
import sympy as sp
import numpy as np
import time
def f(y, p):
c0,c1,c2,c3,c4,c5 = p
return c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + c5*x**5
def g(a,x):
y = sp.Symbol('y')
expr = sp.Integral( f(y,p), [y,a,x] )
return expr.doit()
start = time.clock()
l = []
for x in np.arange(a,b,0.001):
l.append(g(a,x))
end = time.clock()
print end-start
Improved implementation
import sympy as sp
import numpy as np
import time
def f(y, p):
c0,c1,c2,c3,c4,c5 = p
return c0 + c1*x + c2*x**2 + c3*x**3 + c4*x**4 + c5*x**5
x=sp.Symbol('x')
itgx = sp.Integral( f(y,p), [y,a, x] )
start = time.clock()
g = sp.lambdify(x, itgx.doit(), "numpy")
l = g(np.arange(a,b,0.001))
end = time.clock()
print end-start
On my architecture (i7-3770 #3.40GHz, Ubuntu 14.04),
the naive implementation times 12.086627s while the lambdify implementation times 0.054799s, that looks like a significant speed up. Sympy manual also suggests to use lambdify when possible
So my question, which maybe is not clear enough, is:
Is there a better way of doing this kind of computation? If so, please let me know
Of course the lambdified version is faster. Not only is it vectorizing the result over a numpy array rather than using a Python for loop, you're also being very inefficient in the other version by recomputing the integral each time.
I don't see an actual question here. Your lambdified version looks correct. I don't see any issues with it.