invalid value encountered in power - python

Python 3. Following code says:
25: RuntimeWarning: invalid value encountered in power
L[i] = (((volume*(10**6))*4*(F**2))/(C*pi))**(1/3) #ft
The error is encountered at L[1,22] to L[1,30] and L[2,15] to L[2,30]
Is it part of the loop? I can copy and paste volume=22 and F=5 and it comes up with the number just fine.
lo = 0.06521 # lbm/ft^3
volume = np.arange(0,31) # M ft^3
lift = volume*10**6*lo # lbm
lift = lift/2000 # ton
C = 0.6 # Cylindrical Coefficient
pi = np.pi
L = np.zeros((3,len(volume)))
for F in range(4,7):
i = F - 4
L[i] = (((volume*(10**6))*4*(F**2))/(C*pi))**(1/3) #ft

You have a scalar overflow problem. Specifying volume as int64 solves the problem.
volume = np.arange(31, dtype=np.int64)

If I rewrite the problem like this:
L = np.zeros((3,len(volume)))
for F in range(4,7):
i = F - 4
D = (((volume*(10**6))*4*(F**2))/(C*pi))
L[i] = D ** (1 / 3)
I can see that at F = 5, I get negative values for some parts of D.
These numbers cube rooted become complex, raising the error.

Related

Using Taylor expansion to calculate pi with an user set precision value

The input is the precision to which pi is calculated and I need to output the value of calculated pi and the number of terms to reach that value.
This is the code that I have made and it is supposed to print out (3.33968, 5). Could someone check where I have went wrong?
t_precisionstr = input("Precision Value for Taylor: ")
t_precision = float(t_precisionstr)
t_list = []
def taylor(t_precision):
t_number1 = 0
t_number2 = 1
t_final = 0
while t_final <= abs(m.pi - t_precision):
t_number1 = t_number1 + 1
t_answer = t_number2 + ((-1)**t_number1 / (2*t_number1+1))
print(t_answer)
t_number = t_number1 + t_number2
t_number2 = 0
t_list.append(t_answer)
t_final = 4 * (sum(t_list))
return(t_final,t_number+1)
print(taylor(t_precision))
I think the first issue is that your code is difficult to read and therefore difficult to debug. It's always better to use meaningful variable names and to try to minimize declaration of unnecessary ones.
Here is a working implementation of your problem as stated by the title, e.g. calculating pi up to a given precision:
# Pi/4 = 1 - 1/3 + 1/5 - 1/7 + ...
import numpy as np
def taylor(precision):
t_pi, factor, error, order = 0, 0, np.pi, 0
while (error >= precision):
t_pi += 4 * (-1)**factor / (2*factor + 1)
error = abs(np.pi - t_pi)
order += 1
factor += 1
return t_pi, order
taylor(0.2)
>>> (3.3396825396825403, 5)
And this is the corrected version of your code:
def taylor(t_precision):
t_list = []
t_number = 0
t_final = 0
while t_precision <= abs(np.pi - t_final):
t_answer = (-1)**t_number / (2*t_number+1)
print(t_answer)
t_list.append(t_answer)
t_final = 4 * (sum(t_list))
t_number = t_number + 1
return (t_final,t_number)
t_precision = 0.2
taylor(t_precision)
>>> (3.3396825396825403, 5)
The errors were:
The condition of the while loop. You are checking the your final approximation against the difference between the actual value of pi and the desired precision. e.g. if you approximation is 2.6 and the precision 0.1 then the condition is already true, while the error is bigger than the precision required
The return statement is wrongly indented, so the loop exits at the first execution no matter what.

Solving multivariate equation for a subset of variables

I am using sympy to solve some equations and I am running into a problem. I have this issue with many equations but I will illustrate with an example. I have an equation with multiple variables and I want to solve this equation in terms of all variables but one is excluded. For instance the equation 0 = 2^n*(2-a) - b + 1. Here there are three variables a, b and n. I want to get the values for a and b not in terms of n so the a and b may not contain n.
2^n*(2-a) - b + 1 = 0
# Since we don't want to solve in terms of n we know that (2 - a)
# has to be zero and -b + 1 has to be zero.
2 - a = 0
a = 2
-b + 1 = 0
b = 1
I want sympy to do this. Maybe I'm just not looking at the right documentation but I have found no way to do this. When I use solve and instruct it to solve for symbols a and b sympy returns to me a single solution where a is defined in terms of n and b. I assume this means I am free to choose b and n, However I don't want to fix n to a specific value I want n to still be a variable.
Code:
import sympy
n = sympy.var("n", integer = True)
a = sympy.var("a")
b = sympy.var("b")
f = 2**n*(2-a) - b + 1
solutions = sympy.solve(f, [a,b], dict = True)
# this will return: "[{a: 2**(-n)*(2**(n + 1) - b + 1)}]".
# A single solution where b and n are free variables.
# However this means I have to choose an n I don't want
# to that I want it to hold for any n.
I really hope someone can help me. I have been searching google for hours now...
Ok, here's what I came up with. This seems to solve the type of equations you're looking for. I've provided some tests as well. Of course, this code is rough and can be easily caused to fail, so i'd take it more as a starting point than a complete solution
import sympy
n = sympy.Symbol('n')
a = sympy.Symbol('a')
b = sympy.Symbol('b')
c = sympy.Symbol('c')
d = sympy.Symbol('d')
e = sympy.Symbol('e')
f = sympy.sympify(2**n*(2-a) - b + 1)
g = sympy.sympify(2**n*(2-a) -2**(n-1)*(c+5) - b + 1)
h = sympy.sympify(2**n*(2-a) -2**(n-1)*(e-1) +(c-3)*9**n - b + 1)
i = sympy.sympify(2**n*(2-a) -2**(n-1)*(e+4) +(c-3)*9**n - b + 1 + (d+2)*9**(n+2))
def rewrite(expr):
if expr.is_Add:
return sympy.Add(*[rewrite(f) for f in expr.args])
if expr.is_Mul:
return sympy.Mul(*[rewrite(f) for f in expr.args])
if expr.is_Pow:
if expr.args[0].is_Number:
if expr.args[1].is_Symbol:
return expr
elif expr.args[1].is_Add:
base = expr.args[0]
power = sympy.solve(expr.args[1])
sym = expr.args[1].free_symbols.pop()
return sympy.Mul(sympy.Pow(base,-power[0]), sympy.Pow(base,sym))
else:
return expr
else:
return expr
else:
return expr
def my_solve(expr):
if not expr.is_Add:
return None
consts_list = []
equations_list = []
for arg in expr.args:
if not sympy.Symbol('n') in arg.free_symbols:
consts_list.append(arg)
elif arg.is_Mul:
coeff_list = []
for nested_arg in arg.args:
if not sympy.Symbol('n') in nested_arg.free_symbols:
coeff_list.append(nested_arg)
equations_list.append(sympy.Mul(*coeff_list))
equations_list.append(sympy.Add(*consts_list))
results = {}
for eq in equations_list:
var_name = eq.free_symbols.pop()
val = sympy.solve(eq)[0]
results[var_name] = val
return results
print(my_solve(rewrite(f)))
print(my_solve(rewrite(g)))
print(my_solve(rewrite(h)))
print(my_solve(rewrite(i)))

using jacobi method to solve laplace equation PYTHON

I am fairly new to python and am trying to recreate the electric potential in a metal box using the laplace equation and the jacobi method. I have written a code that seems to work initially, however I am getting the error: IndexError: index 8 is out of bounds for axis 0 with size 7 and can not figure out why. any help would be awesome!
from visual import*
from visual.graph import*
import numpy as np
lenx = leny = 7
delta = 2
vtop = [-1,-.67,-.33,.00,.33,.67,1]
vbottom = [-1,-.67,-.33,.00,.33,.67,1]
vleft = -1
vright = 1
vguess= 0
x,y = np.meshgrid(np.arange(0,lenx), np.arange(0,leny))
v = np.empty((lenx,leny))
v.fill(vguess)
v[(leny-1):,:] = vtop
v [:1,:] = vbottom
v[:,(lenx-1):] = vright
v[:,:1] = vleft
maxit = 500
for iteration in range (0,maxit):
for i in range(1,lenx):
for j in range(1,leny-1):
v[i,j] = .25*(v[i+i][j] + v[i-1][j] + v[i][j+1] + v[i][j-1])
print v
Just from a quick glance at your code it seems as though the indexing error is happening at this part and can be changed accordingly:
# you had v[i+i][j] instead if v[i+1][j]
v[i,j] = .25*(v[i+1][j] + v[i-1][j] + v[i][j+1] + v[i][j-1])
You simply added and extra i to your indexing which would have definitely been out of range

Translating a function integrating another function from BASIC into Python

The book Calculus and Pizza by Clifford Pickover has a few code examples here and there, all written in some dialect of BASIC.
I wrote a Python version of the code example covering integration. His BASIC example goes like:
10 REM Integration
20 DEF FNY(X) = X*X*X
30 A = 0
40 B = 1
50 N = 10
55 R = 0
60 H = (B-A)/N
70 FOR X = A TO B - H/2 STEP H
80 R = R + FNY(X)
90 NEXT X
100 R = R * H
110 PRINT *INTEGRATION ESTIMATE*: R
I changed a few things here and there, allowing the user to specify the interval over which to take the integral, specify the function to be integrated as a lambda, and so forth. I knew right off the bat that the for loop wouldn't work as I have written it below. I'm just wondering if there's some direct or idiomatic translation of the BASIC for to a Python for.
def simpleintegration():
f = eval(input("specify the function as a lambda\n:%"))
a = int(input("take the integral from x = a = ...\n:%"))
b = int(input("to x = b = ...\n:%"))
n = 10
r = 0
h = (b-a)/n
for x in range(a,b-h/2,h):
r = r + f(x)
r = r * h
print(r)
Your translation isn't far off. The only difference between the for loop in other languages and Python's "loop-over-a-range" pattern is that the "stop" value is usually inclusive in other languages, but is exclusive in Python.
Thus, in most other languages, a loop including a and b looks like
for i = a to b step c
' Do stuff
next i
In Python, it would be
for i in range(a, b + 1, c):
# Do stuff
The formula is computing the Riemann sums using the values at the left end of the subdivision intervals. Thus the last used value for X should be B-H.
Due to floating point errors, stepping from A by H can give a last value that is off by some small amount, thus B-H is not a good bound (in the BASIC code) and B-H/2 is used to stop before X reaches B.
The Python code should work in the presented form for the same reasons, since the bound B-H/2 is unreachable, thus the range should stop with B-H or a value close by.
Using a slight modification you can actually compute the trapezoidal approximation, where you initialize with R=f(A)/2, step X from A+H to including B-H adding f(X) to R and then finish by adding f(B)/2 (which could already be done in the initialization). As before, the approximation of the integral is then R*H.
You can do as below, just changing iteration of 'i' in for loop.
def simpleintegration():
f = eval(input("specify the function as a lambda\n:%"))
a = int(input("take the integral from x = a = ...\n:%"))
b = int(input("to x = b = ...\n:%"))
n = 10
r = 0
h = (b-a)/n
for x = a to b-h/2 step h:
r = r + f(x)
r = r * h
print(r)

f seems to be always positive in the MATLAB code, but in my Python code, f also gets negative values

How to convert the following MATLAB code to Python? Here is my solution, but it doesn't quite produce the same results. For example, f seems to be always positive in the MATLAB code, but in my Python code, f also gets negative values.
Any ideas how to fix the program?
Mostly, I am concerned about these:
MATLAB:
for k = 1 : nx
j = k+2;
Python:
for k in range(1,nx+1):
j = k+2
MATLAB:
[V,D] = eig(A, B);
DD = diag(D);
keep_idxs = find( ~isinf(DD) );
D = diag( DD(keep_idxs) );
V = V(:, keep_idxs);
[lambda, idx] = min(diag(D));
f = V(:,idx);
Python:
w,vr = scipy.linalg.decomp.eig(A,B)
w = w.real
vr = vr.real
w = w[2:-1-2]
lambda_ = w.min()
idx = w.argmin()
f = vr[:,idx]
MATLAB:
f = f(3:end-2);
[nf, nf_idx] = max(abs(f)); % L_infty norm
n2 = f(nf_idx); % normalize sign away, too
f = f ./ n2;
Python:
f = f[2:-1-1]
nf = max(np.absolute(f))
nf_idx = np.absolute(f).argmax()
nf_idx = np.ma.argmax(f)
n2 = f[nf_idx]
f = f/n2
MATLAB:
xx = -kappa:h:kappa;
Python:
xx = np.arange(-kappa, kappa+h, h)
Are those equivalent with each other? If they are, then why don't they produce exact the same results?
I don't know about matlab, but for python the code
for k in range(1,nx+1):
j = k+2
is the same as
j = nx+2
This isn't your main problem, but it's worrying.

Categories