I want to plot a graph in python by substituting piecewise function.
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
#set up constants
d0=0.2
d1=0.2
L0=0.2
L=5
delta1=0.02
Dp=1
def fun(x):
out = np.zeros_like(x)
out[(x >= 0) & (x <= d1)] = d0
mask = (x >= d1) & (x <= d1 + L0)
out[mask] = d0-0.5*delta1*(1+np.cos(2*np.pi/L0)*(x[mask]-d1-0.5*L0))
out[(x >= d1 + L0) & (x <= L)] = L0
return out
# Define 100 points between 0 to 5 evenly spaced
y = np.linspace(0, 5, 100) # Change
g = Dp*(y*y-(fun(y))**2) # Change
plt.plot(y, g) # Change
plt.show() # Change
dear fun(y)is not a function of y its a function of x. i am attaching the sample graph
Related
I'm trying to graph this function. x domain is (1,3) a_1 domain is (0,1) and b domain is (0,0.8)
function
My code is this so far:
import numpy as np
def t2(x,a,b):
if (x <= 1.5 - (a/2)).any():
imagent2=0
elif np.logical_and((1.5) - (a/2) < x, x <=(1.5) + (a/2)).all():
imagent2=(x-(1.5)+(a/2))/a
elif np.logical_and((1.5)+(a/2) < x ,x <= (2.6)-(b/2)).all():
imagent2=1
elif np.logical_and((2.6)-(b/2) < x, x <= 2.6+(b/2)).all():
imagent2=((2.6)+(b/2)-x)/b
elif (((2.6)+(b/2)) < x).any():
imagent2=0
return imagent2
n=5
q = np.linspace(1.01, 2.99,n)
w = np.linspace(0.01,0.99,n)
e = np.linspace(0.01,0.79,n)
X, A, B= np.meshgrid(q, w, e, indexing='ij')
assert np.all(X[:,0,0] == q)
assert np.all(A[0,:,0] == w)
assert np.all(B[0,0,:] == e)
print(t2(X,A,B))
I put the .all() and .any() cause i was getting errors without them. I will like to have an array with the values of the function on the specific domain. With that i would graph using f(x) as z, x as x, a as y and b should be represented as a colour. Don't really know how to do that last part also.
In the end i did something like this. Not quite what i wanted but i guess is enough.
from mpl_toolkits.mplot3d import axes3d
import matplotlib.pyplot as plt
from matplotlib import cm
import numpy as np
def t2(x,a,b):
return np.piecewise(x, [np.logical_and(x>1,x<=1.5-(a/2)),np.logical_and((1.5)-(a/2)<x,x<=(1.5)+(a/2)),np.logical_and((1.5)+(a/2)<x,x<=(2.6)-(b/2)),np.logical_and((2.6)-(b/2)<x,x<=2.6+(b/2)),np.logical_and(x<3,((2.6)+(b/2))<x)], [lambda x: 0, lambda x: (x-(1.5)+(a/2))/a,lambda x: 1, lambda x: ((2.6)+(b/2)-x)/b, lambda x: 0])
n=100
x = np.linspace(1.01, 2.99,n)
y = np.linspace(0.01,0.99,n)
X,Y = np.meshgrid(x,y)
b_vals = [ 0.01,0.4, 0.79 ]
num_subplots = len(b_vals)
fig = plt.figure(figsize=(10, 4))
for i,b in enumerate(b_vals):
ax = fig.add_subplot(1 , num_subplots , i+1, projection='3d')
ax.plot_surface(X, Y, np.vectorize(t2)(X,Y,b), cmap=cm.gnuplot)
ax.set_title('b = %.2f'%b, fontsize=10)
plt.xlabel("x")
plt.ylabel("a")
ax.set_zlabel('T1(x,a,a_2)')
fig.savefig('contours.png', facecolor='grey', edgecolor='none')
I just have place holders for the initial conditions. But it seems the u function is the main issue. In removing it and replacing it as a constant I get a float int error. I feel like I'm almost there and am just making a small mistake.
enter image description here
code:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('text', usetex = True)
mpl.rc('font', family = 'serif', size=16)
from scipy.integrate import solve_ivp
%matplotlib inline
def EulerSys(F, y0, ti, tf, h):
t = np.arange(ti, tf+h, h)
n = len(t)
neq = len(y0)
x = np.zeros((neq, n))
x[:,0] = y0
for i in range(t.size - 1):
# [new value] = [old value] + [slope x step size]
x[:,i+1] = x[:,i] + h*F( t[i], x[:,i] )
return x
m1=55
m2=400
m3=100
k1=230000
k2=30000
k3=50000
k4=0
b2=1500
b3=4000
b4=700
L0=5
v=15
A=0.03
h = .05
ti =0
tf =3.2
t = np.arange(ti, tf+h, h)
# the initial conditions:
x0 = np.array([ 2.0, 0.0 , 1, 1,1,1])
n = len(t)
neq = len(x0)
# initialize the vector to store the solutions:
# the rows are the solutions, the columns are the time instances:
x = np.zeros((neq, n))
# store the initial conditions:
x[:,0] = x0
print(x)
def myFun(t,x):
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))
n = len(x)
dx = np.zeros((n))
dx[0] = x[1]
dx[1] = (-(b2 + b4)*x[1]+b2*x[3]+b4*x[5]-[k1+k2+k4]*x[0]+k2*x[2]+k4*x[4]+k1*u)/m1
dx[2] = x[3]
dx[3] = (b2*x[1]-(b2+b3)*x[3]+b3*x[5]+k2*x[0]-(k2+k3)*x[2]+k3*x[4])/m2
dx[4] = x[5]
dx[5] = (b4*x[1]+b3*x[3]-(b3+b4)*x[5]+k4*x[0]+k3*x[2]-(k3+k4)*x(4))/m3
return dx
xsol= EulerSys(myFun, x0, ti, tf, h)
you are simply missing one bracket at the end.
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))
should be:
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))) # one more bracket
here is the test code that is stripped from the original question:
import numpy as np
# define variables needed
A = 1
v = 1
L0 = 1
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0))))
print(u(1))
the result (with test numbers) is this:
2.536543312392503e-06
I have a 1D piecewise shape which looks like a rectangular with smooth edges (quarter circles):
import numpy as np
import matplotlib.pyplot as plt
def piecewise(x, r, d, h):
if -d/2 <= x <= - d/2 + r or d/2- r <= x <= d/2:
return np.sqrt(r**2-(x-np.sign(x)*d/2+np.sign(x)*r)**2)+r+(h-2*r)
elif -d/2 - r <= x <= -d/2 or d/2 <= x <= d/2 + r:
return -np.sqrt(r**2-(x- np.sign(x)*d/2-np.sign(x)*r)**2)+r
elif - d / 2 + r < x < d / 2 - r:
return 2*r+(h-2*r)
return 0.0
vpiecewise = np.vectorize(piecewise)
x = np.linspace(-20, 20, 10000)
z = vpiecewise(x, 4, 20, 10)
plt.plot(x, z, '-')
plt.show()
I would like to rotate it around Y-axis which is its centre to get a cyllinder with smoothed out edges. Is there a way to do it in Python?
I am trying to plot the error of this algorithm against h and I have run into a problem, for this error calculation, it cant use the first value, as it divides 0/0. How do I go about ignoring the first value where x =0? I basically need to start the summation on i=2 on line 46 (the absolute error one). Any help is much appreciated
import numpy
import matplotlib.pyplot as pyplot
from scipy.optimize import fsolve
from matplotlib import rcParams
rcParams['font.family'] = 'serif'
rcParams['font.size'] = 16
rcParams['figure.figsize'] = (12,6)
printing = False
def rk3(A, bvector, y0, interval, N):
h = (interval[1] - interval[0]) / N
x = numpy.linspace(interval[0], interval[1], N+1)
y = numpy.zeros((len(y0), N+1))
y[:, 0] = y0
b = bvector
for i in range(N):
y_1 = y[:, i] + h *(numpy.dot(A, y[:, i]) + b(x[i]))
y_2= (3/4)*y[:, i] + 0.25*y_1+0.25* h* (numpy.dot(A,y_1)+b(x[i]+h))
y[:, i+1] = (1/3)*y[:, i] + (2/3)*y_2 + (2/3)*h*(numpy.dot(A,y_2)+b(x[i]+h))
return x, y
def exact( interval, N):
w = numpy.linspace(interval[0], interval[1], N+1)
z = numpy.array([numpy.exp(-1000*w),(1000/999)*(numpy.exp(-w)-numpy.exp(-1000*w))])
return w, z
A=numpy.array([[-1000,0],[1000,-1]])
def bvector(x):
return numpy.zeros(2)
y0=numpy.array([1,0])
interval=numpy.array([0,0.1])
N=numpy.arange(40,401,40)
h=numpy.zeros(len(N))
abs_err = numpy.zeros(len(N))
for i in range(len(N)):
interval=numpy.array([0,0.1])
h[i]=(interval[1] - interval[0]) / N[i]
x, y = rk3(A, bvector, y0, interval, N[i])
w,z=exact(interval,N[i])
abs_err[i] = h[i]*numpy.sum(numpy.abs((y[1,:]-z[1,:])/z[1,:]))
p = numpy.polyfit(numpy.log(h), numpy.log(abs_err),1)
fig = pyplot.figure(figsize = (12, 8), dpi = 50)
pyplot.loglog(h, abs_err, 'kx')
pyplot.loglog(h, numpy.exp(p[1]) * h**(p[0]), 'b-')
pyplot.xlabel('$h$', size = 16)
pyplot.ylabel('$|$Error$|$', size = 16)
pyplot.show()
Simply add an if for the value which is zero. so for example if the dividing variable is x.
if x>0:
#code here for the calculation
The above code will use all positive non-zero value. to only skip zero use this
if x!=0:
You can also us the three arguments of a for loop:
for a in range(start_value, end_value, increment):
so this means
for a in range(2,10,2):
print a
will give you the below result
2
4
6
8
My goal is to make a density heat map plot of sphere in 2D. The plotting code below the line works when I use rectangular domains. However, I am trying to use the code for a circular domain. The radius of sphere is 1. The code I have so far is:
from pylab import *
import numpy as np
from matplotlib.colors import LightSource
from numpy.polynomial.legendre import leggauss, legval
xi = 0.0
xf = 1.0
numx = 500
yi = 0.0
yf = 1.0
numy = 500
def f(x):
if 0 <= x <= 1:
return 100
if -1 <= x <= 0:
return 0
deg = 1000
xx, w = leggauss(deg)
L = np.polynomial.legendre.legval(xx, np.identity(deg))
integral = (L * (f(x) * w)[None,:]).sum(axis = 1)
c = (np.arange(1, 500) + 0.5) * integral[1:500]
def r(x, y):
return np.sqrt(x ** 2 + y ** 2)
theta = np.arctan2(y, x)
x, y = np.linspace(0, 1, 500000)
def T(x, y):
return (sum(r(x, y) ** l * c[:,None] *
np.polynomial.legendre.legval(xx, identity(deg)) for l in range(1, 500)))
T(x, y) should equal the sum of c the coefficients times the radius as a function of x and y to the l power times the legendre polynomial where the argument is of the legendre polynomial is cos(theta).
In python: integrating a piecewise function, I learned how to use the Legendre polynomials in a summation but that method is slightly different, and for the plotting, I need a function T(x, y).
This is the plotting code.
densityinterpolation = 'bilinear'
densitycolormap = cm.jet
densityshadedflag = False
densitybarflag = True
gridflag = True
plotfilename = 'laplacesphere.eps'
x = arange(xi, xf, (xf - xi) / (numx - 1))
y = arange(yi, yf, (yf - yi) / (numy - 1))
X, Y = meshgrid(x, y)
z = T(X, Y)
if densityshadedflag:
ls = LightSource(azdeg = 120, altdeg = 65)
rgb = ls.shade(z, densitycolormap)
im = imshow(rgb, extent = [xi, xf, yi, yf], cmap = densitycolormap)
else:
im = imshow(z, extent = [xi, xf, yi, yf], cmap = densitycolormap)
im.set_interpolation(densityinterpolation)
if densitybarflag:
colorbar(im)
grid(gridflag)
show()
I made the plot in Mathematica for reference of what my end goal is
If you set the values outside of the disk domain (or whichever domain you want) to float('nan'), those points will be ignored when plotting (leaving them in white color).