operation on Matrices with the elements in function form - python

I have a set of functions which are tended to be the elements of a matrix, and I have to do some + and * and / operation on them and also between each matrix element.
I am using Numpy, Sympy to do this and here is the code written on Python 2.7.
import numpy as np
import math
import cmath
import matplotlib.pyplot as pl
from cmath import*
from sympy import*
# delta, deltz and some other numbers are simple float number I changed varibles in for loop to the first value to test this section of my whole cod
f1 = Matrix([[1, 0],[ 0, 1]]) #an empty matrix from sympy
delta = 2.0*np.pi*1.6*((1.0/1530)-(1.0/(2.0*1550))) #this is a simple float number
deltz = (5*(10.0**6))/50
def apdFunc(x):
return np.exp(-2*np.log(2)*((x-(5/2))/5)**2)
def modFunc(x):
return (1+np.cos((2*np.pi/1)*x))
d1 = np.linspace(-20.0, 20.0, 5000)
apdFunc = apdFunc(d1)
modFunc = modFunc(d2)
Profile = modFunc*apdFunc
sig = (np.pi/1530)*fbgProfile + delta
kaa = (np.pi/1530)*fbgProfile
j = sqrt(-1)
gammab = np.sqrt(kaa**2.0-sig**2.0)
#Matrix elements definition
f11 = np.cosh(gammab*deltz)-1j*(sig/gammab)*np.sinh(gammab*deltz)
f22 = np.cosh(gammab*deltz)+1j*(sig/gammab)*np.sinh(gammab*deltz)
f12 = -1j*(kaa/gammab)*np.sinh(gammab*deltz)
f21 = 1j*(kaa/gammab)*np.sinh(gammab*deltz)
f1 = f1*Matrix([[f11, f12],[ f21, f22]])
PO=f1[0,0]
NO=f1[1,0]
REF=abs((NO/PO)**2)
pl.plot(d3,REF)
pl.show()
print f1[0,0]
print PO
print REF
The first problem is : gammab=np.sqrt(kaa**2.0-sig**2.0) that numpy can't accept complex number I mean negative value under sqrt and if I don't use Numpy I can't do Operation on them because kaa and sig are functions.
Second : I cant print the matrix elements (after reversing kaa**2.0-sig**2.0 and solving first problem), thus I can't plot the REF=abs((NO/PO)**2) and an error apears telling
AttributeError: 'ImmutableDenseNDimArray' object has no attribute 'as_coeff_Mul'
Any help appreciated and if you can introduce a reference to learn how to solve the problem.

Related

How to include known parameter that changes over time in solve_bvp

I am trying to use scipy's solve_bvp in python to solve differential equations that depend on a known parameter that changes over time. I have this parameter saved in a numpy array. However, when I try to use this array in the derivatives function, I get the following error ValueError: operands could not be broadcast together with shapes (10,) (11,).
Below is a simplified version of my code. I want the variable d2 to take certain values at different times according to an array, d2_set_values. The differential equations for some of the 12 variables then depend on d2. I hope it's clear from this code what I'm trying to achieve.
import numpy as np
from scipy.integrate import solve_bvp
t = np.linspace(0, 10, 11)
# Known parameter that changes over time
d2_set_values = np.zeros(t.size)
d2_set_values[:4] = 0.1
d2_set_values[4:8] = 0.2
d2_set_values[8:] = 0.1
# Initialise y vector
y = np.zeros((12, t.size))
# ODEs
def fun(x, y):
S1, I1, R1, S2, I2, R2, lamS1, lamI1, lamR1, lamS2, lamI2, lamR2 = y
d1 = 0.5*(I1 + 0.1*I2)*(lamS1 - lamI1)
d2 = d2_set_values
dS1dt = -0.5*S1*(1-d1)*(I1 + 0.1*I2)
dS2dt = -0.5*S2*(1-d2)*(I2 + 0.1*I1)
dI1dt = 0.5*S1*(1-d1)*(I1 + 0.1*I2) - 0.2*I1
dI2dt = 0.5*S2*(1-d2)*(I2 + 0.1*I1) - 0.2*I2
dR1dt = 0.2*I1
dR2dt = 0.2*I2
dlamS1dt = 0.5*(1-d1)*S1*lamS1
dlamS2dt = 0.5*(1-d2)*S2*lamS2
dlamI1dt = 0.5*(1-d1)*I1*lamI1
dlamI2dt = 0.5*(1-d2)*I2*lamI2
dlamR1dt = lamR1
dlamR2dt = lamR2
return np.vstack((dS1dt, dI1dt, dR1dt, dS2dt, dI2dt, dR2dt, dlamS1dt, dlamI1dt, dlamR1dt, dlamS2dt, dlamI2dt, dlamR2dt))
# Boundary conditions
def bc(ya, yb):
return np.array([ya[0]-0.99, ya[1]-0.01, ya[2]-0., ya[3]-1.0, ya[4]-0., ya[5]-0.,
yb[6]-0., yb[7]-1., yb[8]-0., yb[9]-0, yb[10]-0, yb[11]-0])
# Run the solver
sol = solve_bvp(fun, bc, t, y)
I have even tried reducing the size of d2_set_values by one, but that doesn't solve the issue.
Any help I can get would be much appreciated!

Why `numpy.fft.irfft` is so imprecise?

I understand that most FFT/IFFT routines have an error floor. I was expecting NumPy's FFT to have an error floor in the same orders as FFTW (say 1e-15), but the following experiment shows errors in the order of 1e-5.
Consider calculating the IDFT of a box. It is well-known that the result is the sinc-like Dirichlet kernel. But that is not what I get from numpy.fft.irfft. In fact even the first sample that should simply equal the width of the box divided by the number of FFT points is off by an amount around 4e-5 as the following example shows:
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import diric
N = 40960
K = 513
X = np.ones(K, dtype=np.complex)
x = np.fft.irfft(X, N)
print("x[0] = %g: expected %g - error = %g" % (x[0], (2*K+1)/N, x[0]-(2*K+1)/N))
# expected IDFT of a box is Dirichlet function (see
# https://en.wikipedia.org/wiki/Discrete_Fourier_transform#Some_discrete_Fourier_transform_pairs)
y = diric(2*np.pi*np.arange(N)/N, 2*K+1) * (2*K+1) / N
plt.figure()
plt.plot(x[:1024] - y[:1024])
plt.title('error')
plt.show(block=True)
It looks like the error is of sinusoidal form:
Has anybody experience same issue? Am I misunderstanding something about the NumPy's FFT pack or it is just not accurate?
Update
Here is the equivalent of part of the script in Octave:
N = 40960;
K = 513;
X = zeros(1, N);
X(1:K) = 1;
X(N-K:N) = 1;
x = ifft(X);
fprintf("x[0] = %g, expected = %g - error = %g\n", x(1), (2*K+1)/N, x(1)-(2*K+1)/N);
The error on x[0] is practically zero in Octave. (I did not check other samples because I am not aware of equivalent of diric function in Octave.)
Thanks to MarkDickinson, I realized that my math was wrong. The correct comparison would be carried out by:
import numpy as np
import matplotlib.pyplot as plt
from scipy.special import diric
N = 40960
K = 513
X = np.ones(K+1, dtype=np.complex)
x = np.fft.irfft(X, N)
print("x[0] = %g: expected %g - error = %g" % (x[0], (2*K+1)/N, x[0]-(2*K+1)/N))
# expected IDFT of a box is Dirichlet function (see
# https://en.wikipedia.org/wiki/Discrete_Fourier_transform#Some_discrete_Fourier_transform_pairs)
y = diric(2*np.pi*np.arange(N)/N, 2*K+1) * (2*K+1) / N
plt.figure()
plt.plot(x[:1024] - y[:1024])
plt.title('error')
plt.show(block=True)
that shows irfft is accurate. Here is the error plot:
Numpy is correct, my math was incorrect. I am sorry for posting this misleading question. I don't know what is the standard procedure in these cases. Should I delete my question or leave it here with this answer? I just don't want it to be undermining NumPy or challanging its accuracy (as this was clearly a false alarm).

Jacobi Method & Basic Matrix Math using NUMPY

I'm getting an import error for "norm". What am I not doing correct??
I'm open to constructive feedback on improving the code, however I have to keep the parameters as they are!
Thanks!!!
Code is below:
import numpy as np
from numpy import norm, inalg, array, zeros, diag, diagflat, dot, linalg
"""Test Case Data"""
A = np.matrix([[4,-1,-1],[-2,6,1],[-1,1,7]])
b = np.matrix([[3],[9],[-6]])
x = np.matrix([[0],[0],[0]])
"""Main Function"""
def jacobi(A, b, x, Tolerance, Iterations):
V = np.diag(A)
D = np.diag(V)
R = D-A
D_I = D.I
D = np.asmatrix(D)
Counter_1 = 1
tol_gauge = 100
while Counter_1 <= Iterations:
# I considered using the "dot" function in NUMPY but I was wary of mixed results
iterative_approach_form = D_I * ((R*x)+b)
tol_gauge = np.linalg.norm(iterative_approach_form-x)
x = iterative_approach_form
if initial_tol <= Tolerance:
return("The Solution x = {},y={}, z={} ".format(x[0], x[1], x[2]))
return("The Solution was found in %s interation(s)" %(Counter_1))
else:
pass
Counter_1 +=1
return("The Solution was not found in {} iteration(s)".format(Iterations))
You need to specify which numpy module you are importing from. The following works if you want to use a function only by its name:
from numpy import linalg
from numpy.linalg import norm
from numpy import zeros, array, diag, diagflat, dot
Looking at you code however, you don't need the second import line, because in the rest of the code the numpy functions are specified according to the accepted norm. For example, norm is already present in your code as np.linalg.norm.
There are three more issues with your code: 1) initial_tol is not assigned a value; 2) tol_gauge is assigned but not used in the code; 3) the last return statement is not indented properly (perhaps only here) and the same is very likely for the block in your while loop.

How do i cycle through an array and compare each element in that array to every element in another array?

I am very unfamiliar with python and have been tasked with doing some python coding. I need to compare every element in an array 't' to all elements in an array 'r'. My goal is to find if any elements (scalar) in the 't' array are isolated by a minimum of 200 units from ALL scalars in the 'r' array; that is, if they are separated by 200 units or more from all elements in the 'r' array I want to flag them as 'isolated'.
I imagine this is a fairly simple operation, I am just unfamiliar with the structure. Thank you in advance for taking the time to help me. Much appreciated!
If it is of any help, here is the code being used:
import numpy as np
import matplotlib.pyplot as plt
from scipy import integrate
from math import sqrt
from astropy import units as u
from astropy.coordinates import SkyCoord
omega_m = 0.3
omega_lam = 0.7
H0 = 70. # Hubble parameter at z=0, km/s/Mpc
c_kms = 299792.458 # speed of light, km/s
dH = c_kms / H0 # Hubble distance, Mpc
def inv_efunc(z):
""" Used to calculate the comoving distance to object at redshift
z. Eqn 14 from Hogg, astro-ph/9905116."""
return 1. / sqrt(omega_m * (1. + z)**3 + omega_lam)
# read in data from file
r = np.genfromtxt('coma_vicinity.dat', dtype=None, skip_header=0,
names='ra,dec,cz,r,g,z,rp',
usecols=(0, 1, 2, 3, 4, 5, 5))
# Calculate the comoving distance corresponding to each object's
redshift
dist = np.array([dH * integrate.quad(inv_efunc, 0, cz)[0] for cz in
r['cz']])
c1 = SkyCoord('12h59m48.7s','+27d58m05s',frame='icrs')
c2 = SkyCoord(r['ra']*u.deg,r['dec']*u.deg,frame='icrs')
sep = c1.separation(c2)
r['rp'] = sep.radian*dist
t = np.genfromtxt('UDGs.csv',dtype=None, skip_header=0,names='nm,ra,dec',usecols=(1,2,3))

odeint for an differential system

I have a problem with odeint. I have to solve an first order differential system and then a second order system but I am a little confused with the first order one. Can you explain what I have marked as wrong? Thank you :)
import scipy.integrate as integrate
import numpy as np
def fun(t,y):
ys = np.array([y[1], (1-y[0]**2)*y[1]-y[0]])
return(ys)
N = 3
x0 = np.array([2.00861986087484313650940188,0])
t0tf = [0, 17.0652165601579625588917206249]
T=([0 for i in range (N+1)])
T[0]= t0tf[0]
Pas = (t0tf[1]-t0tf[0])/N
for i in range (1,N+1):
T[i]= t0tf[0] + i*Pas
X = integrate.odeint(fun, x0,T,Dfun=None, col_deriv=0,full_output=True)
T = np.array(T)
T = T.reshape(N+1,1)
S = np.append(X,T,axis=1)
print(S)
The returned error is:
ys = np.array([y[1], (1-y[0]**2)*y[1]-y[0]])
TypeError: 'float' object is not subscriptable
You need to reverse the order of the arguments to your derivative function - it should be f(y, t), not f(t, y). This is the opposite order to that used by the scipy.integrate.ode class.
Also, the concatenation S = np.append(X,T,axis=1) will fail because X is a tuple containing your integrals and a dict. Use S = np.append(X[0],T,axis=1) instead.

Categories

Resources