Color Mesh Incompatible Dimensions - python

Error Message
File "/Applications/Spyder.app/Contents/Resources/lib/python3.9/matplotlib/axes/_axes.py", line 5575, in _pcolorargs
raise TypeError('Dimensions of C %s are incompatible with'
TypeError: Dimensions of C (101, 101) are incompatible with X (101) and/or Y (101); see help(pcolormesh)
Problem
https://www.chegg.com/homework-help/questions-and-answers/problem-1-compute-steady-state-concentration-umol-um3-distribution-channel-shown-figure--p-q96105354
Code
# Import the required modules
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits import mplot3d
# Constants
D = 0.5 # (μm^2)/s
k = 0.1 # 1/s
Lx = 30 # μm
Ly = 10 # μm
Ca = 40 # Initial concentration (μmol/μm^3)
Cb = 100 # Final concentration (μmol/μm^3)
Cguess = 70 # Guess concentration (μmol/μm^3)
# Iteration parameters
maxit = 2000
tol = 0.0001 # Relative tolerance
merr = 1e5
lam = 1.4 # Parameter for convergence rate
# Setup grid
npts = 100
dx = Lx/npts;
xx = np.linspace(0,Lx,num=npts+1,endpoint=True);
nx = npts+1;
dy = Ly/npts;
yy = np.linspace(0,Ly,num=npts+1,endpoint=True);
ny = npts+1;
# Step 1 - Initial Guesses
M = np.ones((ny,nx)); # set matrix size
M = Cguess*M; # initial guess for Ca in all nodes
# Step 2 - Apply Boundary Conditions
M[0,:] = Ca
M[:,0] = Cb
# Step 3 and 4 - Apply LDE, walking over nodes
cc = 0 # Counter
a = 1+k*dx*dx/(4*D)
while merr>tol:
Mold = np.copy(M) # Save current values to old
M[-1,-1] = (2*M[-2,-1]+2*M[-1,-2])/(4*a)
for j in range(1,ny-1):
for i in range(1,nx-1):
M[j,i] = (M[j,i-1]+M[j,i+1]+M[j-1,i]+M[j+1,i])/(4*a);
for j in range(1,ny-1):
M[j,-1] = (2*M[j,-2]+M[j-1,-1]+M[j+1,-1])/(4*a);
for i in range(1,nx-1):
M[-1,i] = (M[-1,i-1]+M[-1,i+1]+2*M[-2,i])/(4*a);
for i in range(1,68):
M[0,i] = (M[0,i-1]+M[0,i+1]+2*M[1,i])/(4*a);
M = lam*M+(1-lam)*Mold # Adjust for convergence rate
cc = cc+1
ea = np.abs((M-Mold)/M)
merr = np.max(ea)
if cc>maxit: break
avg = np.mean(M[:,0])
# Plot 2D
X,Y = np.meshgrid(xx,yy)
ax = plt.axes(projection="3d")
ax.plot_surface(X,Y,M,edgecolor="none")
ax.view_init(elev=40,azim=-35)
plt.show()
# Plot color mesh
p = plt.pcolormesh(xx, yy, M, cmap="RdBu", shading="flat", vmin=0, vmax=100)
ct = plt.contour(X, Y, M, cmap="gray", levels=10, vmin=0, vmax=100)
c = plt.colorbar(p)
plt.xlabel("Lx (μm)")
plt.ylabel("Ly (μm)")
c.set_label("Concentration (μmol/μm3)")
plt.show()
# Print Results
print("Converged in %d iterations" % cc)
print("Max error is %f" % merr)
print("Mean concentration along central axis = %f μmol/μm^3" % avg)

Related

2-D laplace heat equation with periodic boundary conditions

desired output**I'm trying to implement periodic condition for horizontal direction, I discretized laplace equation bottom temperature is high, at the top temperature is zero and also left and right side **
import numpy as np
import matplotlib.pyplot as plt
# Set maximum iteration
maxIter = 500
lenX = lenY = 20 #we set it rectangular
delta = 1
# Boundary condition
Ttop = 0
Tbottom = 9.75
Tright = 0
Tleft = 0
# Initial guess of interior grid
Tguess = (Ttop + Tbottom)/2
colorinterpolation = 50
colourMap = plt.cm.jet #you can try: colourMap = plt.cm.coolwarm
X, Y = np.meshgrid(np.arange(0, lenX), np.arange(0, lenY))#,indexing='ij')
T = np.empty((lenX, lenY))+ np.random.random((lenX,lenY))
T.fill(Tguess)
T[(lenY-1):, :] = Ttop
T[:1, :] = Tbottom
T[:, (lenX-1):] = Tright
T[:, :1] = Tleft
for iteration in range(0, maxIter):
for i in range(1, lenX-1, delta):
for j in range(1, lenY-1, delta):
T[i, j] = 0.125 * (T[i+1][j] + T[i-1][j] + T[i][j+1] + T[i][j-1] - 4*T[i,j]) + T[i,j]
plt.contourf(X, Y, T, colorinterpolation, cmap=colourMap)
plt.colorbar()
plt.show()
I'm getting this

Random coordinates generator

I want to generate random coordinates for spheres in a box geometry. I'm using while loop and i have 2 condition. First one is the distance of coordinates. General distance formula was used so that the coordinates do not overlap. Second one is the porosity. When porosity is less than 0.45 generating should stop. My code is working correctly but when i reduce porosity condition less than 0.80 the algorithm stucks. It cannot reach that porosity even after hours. How can I improve it to generate coordinates faster? Any suggestions are appreciated.
#dist = math.sqrt(((x2-x1)**2) + ((y2-y1)**2) + ((z2-z1)**2))
import math
import random
import numpy as np
import matplotlib.pyplot as plt
A = 0.04 # x border.
B = 0.04 # y border.
C = 0.125 # z border.
V_total = A*B*C # volume
r = 0.006 # min distance of spheres.
radius = 0.003 # radius of spheres.
wall_distance = 0.003
Porosity = 1.0
coordinates = np.array([])
while Porosity >= 0.90:
# coordinates
x = random.uniform(wall_distance, A-wall_distance)
y = random.uniform(wall_distance, B-wall_distance)
z = random.uniform(wall_distance, C-wall_distance)
coord1 = (x,y,z)
if coordinates.shape[0] == 0: # add first one without condition
coordinates = np.array([coord1])
else:
coordinates = np.vstack((coordinates, coord1))
# seperate x,y,z and convert list for control
d_x = coordinates[:,0]
x = d_x.tolist()
d_y = coordinates[:,1]
y = d_y.tolist()
d_z = coordinates[:,2]
z = d_z.tolist()
for j in range(len(y)):
for k in range(j+1, len(z)):
dist = math.sqrt(((x[j]-x[k])**2) + ((y[j]-y[k])**2) + ((z[j]-z[k])**2))
if dist <= r:
coordinates = coordinates[:-1, :] # if distance is less than r, remove last coordinate
# check porosity
V_spheres = (4/3) * (np.pi) * (radius**3) * len(coordinates)
V_void = V_total - V_spheres
Porosity = V_void / V_total
print("Porosity: {}".format(Porosity))
print("Number of spheres: {}".format(len(coordinates)))
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlim([0, A])
ax.set_ylim([0, B])
ax.set_zlim([0, C])
ax.set_title('Coordinates for spheres')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
p = ax.scatter(coordinates[:,0], coordinates[:,1], coordinates[:,2])
fig.colorbar(p)
plt.show()
There are a number of things you can do to improve your performance here. See my modified code below, with explanations
import math
import random
import numpy as np
import matplotlib.pyplot as plt
A = 0.04 # x border.
B = 0.04 # y border.
C = 0.125 # z border.
V_total = A*B*C # volume
r = 0.006 # min distance of spheres.
radius = 0.003 # radius of spheres.
wall_distance = 0.003
Porosity = 1.0
coordinates = np.empty((0,3)) # initialize array with correct shape
while Porosity >= 0.70:
# coordinates
x = random.uniform(wall_distance, A-wall_distance)
y = random.uniform(wall_distance, B-wall_distance)
z = random.uniform(wall_distance, C-wall_distance)
is_invalid = (True in [
math.sqrt(((x - coordinates[i_coor,0])**2) +
((y - coordinates[i_coor,1])**2) +
((z - coordinates[i_coor,2])**2)) <= r
for i_coor in range(coordinates.shape[0]) ])
if not is_invalid:
coordinates = np.append(coordinates,[[x,y,z]], axis = 0)
else:
continue
V_spheres = (4/3) * (np.pi) * (radius**3) * len(coordinates)
V_void = V_total - V_spheres
Porosity = V_void / V_total
print(f"placed coord {len(coordinates)}, por = {Porosity}")
print("Porosity: {}".format(Porosity))
print("Number of spheres: {}".format(len(coordinates)))
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.set_xlim([0, A])
ax.set_ylim([0, B])
ax.set_zlim([0, C])
ax.set_title('Coordinates for spheres')
ax.set_xlabel('X')
ax.set_ylabel('Y')
ax.set_zlabel('Z')
p = ax.scatter(coordinates[:,0], coordinates[:,1], coordinates[:,2])
np.savetxt('out.csv', coordinates)
fig.colorbar(p)
plt.show()
the main thing I changed is this double for loop
for j in range(len(y)):
for k in range(j+1, len(z)):
dist = math.sqrt(((x[j]-x[k])**2) + ((y[j]-y[k])**2) + ((z[j]-z[k])**2))
This was checking every pair of points for overlap EACH TIME YOU ADD A SINGLE POINT. That took unnecessarily long. By only checking if the new point intersects with the old points, you reduce your runtime from O(n^3) to O(n^2). I was able to pretty quickly run this with 0.5 perosity.

Plot the graphs for 2D square lattice for nearest and next nearest neighbours

I am trying to plot the graphs for 2D square lattice for nearest and next nearest neighbours but the plots that I am getting out of it are incorrect.
An N × N matrix is used to represent a 2-D square lattice; every entry of the matrix represents a lattice site and has entry ±1, representing the spin of the particle at that site. A random matrix is initially used so that the initial configuration of spins is randomised.
import numpy as np
from numpy.random import rand
import matplotlib.pyplot as plt
N=15 # size of the lattice, N x N
init_random = np.random.random((N,N))
lattice_n = np.zeros((N, N))
lattice_n[init_random>=0.75] = 1
lattice_n[init_random<0.75] = -1
init_random = np.random.random((N,N))
lattice_p = np.zeros((N, N))
lattice_p[init_random>=0.25] = 1
lattice_p[init_random<0.25] = -1
This is the metropolis algorithm.
A lattice site is selected at random and ∆E is calculated. If ∆E ≤ 0, the change is favourable and the spin is flipped. If ∆E > 0 then the spin is flipped only if exp (−∆E/kBT) > x where x is a random number on the interval [0, 1] (i.e. the particle has enough energy to flip its spin).
This process is repeated for every site in the lattice, selecting the sites at random.
def mcmove(config, beta):
#Monte Carlo move using Metropolis algorithm
for i in range(N):
for j in range(N):
a = np.random.randint(0, N)
b = np.random.randint(0, N)
s = config[a, b] #calling any element of the configuration matrix randomly
nb = config[(a+1)%N,b] + config[a,(b+1)%N] + config[(a-1)%N,b] + config[a,(b-1)%N]
sb = config[(a+2)%N,b] + config[a,(b+2)%N] + config[(a-2)%N,b] + config[a,(b-2)%N]
delta_e = 2*12*s*nb + 2*6*s*sb
if delta_e < 0:
s *= -1
elif rand() < np.exp(-delta_e*beta):
s *= -1
config[a, b] = s
return config
def calcEnergy(config):
#Energy of a given configuration
energy = 0
for i in range(len(config)):
for j in range(len(config)):
S = config[i,j]
nb = config[(i+1)%N, j] + config[i,(j+1)%N] + config[(i-1)%N, j] + config[i,(j-1)%N]
sb = config[(i+2)%N, j] + config[i,(j+2)%N] + config[(i-2)%N, j] + config[i,(j-2)%N]
energy += -nb*S -sb*S
return energy/4
def calcMag(config):
#Magnetization of a given configuration
mag = np.sum(config)
return mag
temp_points = 40 # number of temperature points
eqSteps = 300 # number of MC sweeps for equilibration
mcSteps = 300 # number of MC sweeps for calculation
T = np.linspace(1.53, 3.28, temp_points);
E,M,C,X = np.zeros(temp_points), np.zeros(temp_points), np.zeros(temp_points), np.zeros(temp_points)
n1, n2 = 1.0/(mcSteps*N*N), 1.0/(mcSteps*mcSteps*N*N)
for tp in range(temp_points):
E1 = M1 = E2 = M2 = 0
config = lattice_p
iT=1.0/T[tp]; iT2=iT*iT;
for i in range(eqSteps): # equilibrate
mcmove(config, iT) # Monte Carlo moves
for i in range(mcSteps):
mcmove(config, iT) #returns the new configuration after monte carlo move
Ene = calcEnergy(config) # calculate the energy
Mag = calcMag(config) # calculate the magnetisation
E1 = E1 + Ene
M1 = M1 + Mag
M2 = M2 + Mag*Mag
E2 = E2 + Ene*Ene
E[tp] = n1*E1
M[tp] = n1*M1
C[tp] = (n1*E2 - n2*E1*E1)*iT2
X[tp] = (n1*M2 - n2*M1*M1)*iT
f = plt.figure(figsize=(18, 10)); # plot the calculated values
sp = f.add_subplot(2, 2, 1 );
plt.scatter(T, E, s=50, marker='o', color='IndianRed')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Energy ", fontsize=20); plt.axis('tight');
sp = f.add_subplot(2, 2, 2 );
plt.scatter(T, abs(M), s=50, marker='o', color='RoyalBlue')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Magnetization ", fontsize=20); plt.axis('tight');
sp = f.add_subplot(2, 2, 3 );
plt.scatter(T, C, s=50, marker='o', color='IndianRed')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Specific Heat ", fontsize=20); plt.axis('tight');
sp = f.add_subplot(2, 2, 4 );
plt.scatter(T, X, s=50, marker='o', color='RoyalBlue')
plt.xlabel("Temperature (T)", fontsize=20);
plt.ylabel("Susceptibility", fontsize=20); plt.axis('tight');
plt.show()

Barabasi-Albert model, wrong degree exponent

I'm trying to generate a scale-free network using the Barabasi-Albert model. The model predicts a degree distribution that follows p(k) ~ k^-3 but mine shows k^-2.
The algorithm was taken from Barabasi's book at this URL: http://barabasi.com/networksciencebook,
here is the relevant paragraph:
Barabasi's algorithm
Here is my code, could someone please help me figure out what is wrong?
import numpy as np
import matplotlib.pyplot as plt
from collections import Counter
plt.rcParams["figure.figsize"] = (15,6)
#initialize values
N = 10000
k = 2
m = int(k / 2)
#initialize matrices
adjacency = np.zeros((N,N))
degrees = np.zeros(N)
#add links
for i in range(N):
degrees[i] = m
for c in range(m):
# choose a node with probability proportional to it's degree
j = np.random.choice(N, p = degrees / (2 * m * i + m + c))
degrees[j] += 1
adjacency[i][j] += 1
adjacency[j][i] += 1
def get_binned_data(labels, values, num):
min_label, max_label = min(labels), max(labels)
base = (max_label / min_label) ** (1 / num)
bins = [base**i for i in range(int(np.log(max_label) / np.log(base)) + 1)]
binned_values, binned_labels = [], []
counter = 0
for b in bins:
bin_size = 0
bin_sum = 0
while counter < len(labels) and labels[counter] <= b:
bin_size += values[counter]
bin_sum += values[counter] * labels[counter]
counter += 1
if(bin_size):
binned_values.append(bin_size)
binned_labels.append(bin_sum / bin_size)
return binned_labels, binned_values
labels, values = zip(*sorted(Counter(degrees).items(), key = lambda pair:
pair[0]))
binned_labels, binned_values = get_binned_data(labels, values, 15)
fig, (ax1, ax2) = plt.subplots(ncols = 2, nrows = 1)
fig.suptitle('Barabasi-Albert Model',fontsize = 25)
ax1.loglog(binned_labels, binned_values, basex = 10, basey = 10, linestyle =
'None', marker = 'o', color = 'red')
ax1.set(xlabel = 'degree', ylabel = '# of nodes')
ax1.set_title('log-log scale (log-binned)',{'fontsize':'15'})
ax2.plot(labels, values, 'ro')
ax2.set(xlabel = 'degree', ylabel = '# of nodes')
ax2.set_title('linear scale',{'fontsize':'15'})
plt.show()
Your code does not run (probabilities in np.random.choice do not sum to 1). Why not p = degrees/np.sum(degrees)?
According to Wikipedia, you need to start with some already connected nodes, whereas you start from nothing. Also, you should probably put degrees[i] = m after the inner loop to avoid forming links from node i to itself.
This might help, but it's not clear to me how you generate your degree plot, so I can't verify it.

Python: IIR Filter response

This is related to this post but is a question in its own right:
Sampling at 40MHz, I have created a narrow pass band IIR filter which has a center frequency of 1MHz and a BW of 20kHz. This gives the following coefficients -
Fc = 1e6 /40e6 # Fcenter as a fraction of Fsample
BW = 20e3/40e6 # BW as a fraction of Fsample
a0 = 0.00140
a2 = 0.00018
b1 = 1.97241
b2 = -0.9970
Applying the signal appears to work as indicated below - My question is:
How may I plot the magnitude and phase response in python?
[As per my previous post this is intentionally idiomatic]
import numpy as np
import matplotlib.pyplot as plt
# create an array of 1024 points sampled at 40MHz
# [each sample is 25ns apart and the key signal is 1MHz]
Fs = 40e6
T = 1/Fs
t = np.arange(0,(1024*T),T)
f = 1e6
Omega = 2*np.pi*f
x = np.sin(Omega*t) * (t**3) * np.exp(-t/2e-6)
x /= max(x)
y = [0]*len(x)
# create a narrow passband IIR filter with fcentre=1MHz
# and BW=0.0005
Fc = 1e6
Ft = Fc/Fs
BW = 0.0005
R = 1 - (3*BW)
K = (1 - 2*R*np.cos(2*np.pi*Ft) + (R*R)) / (2 - 2*np.cos(2*np.pi*Ft))
# coefficients
a0 = 1 - K
a1 = 2*(K-R)*np.cos(2*np.pi*Ft)
a2 = (R*R) - K
b1 = 2*R*np.cos(2*np.pi*Ft)
b2 = -(R*R)
for n in range(2, len(x)):
y[n] = a0*x[n] + a1*x[n-1] + a2*x[n-2] + b1*y[n-1] + b2*y[n-2]
y /= max(y)
plt.subplot(211)
plt.plot( x,'r-', linewidth=2)
plt.xlabel( 'sample length' )
plt.ylabel( 'ip value' )
plt.grid()
plt.subplot(212)
plt.plot( y,'k-', linewidth=2)
plt.xlabel( 'sample length' )
plt.ylabel( 'op value' )
plt.grid()
plt.show()
Maybe the scipy.signal.freqz function can help you here?
http://docs.scipy.org/doc/scipy-0.13.0/reference/generated/scipy.signal.freqz.html

Categories