Reputation:
I'm trying to plot the harmonic potential U = 0.5 k(x-x_0)^2. as a function of distance and the angles. I'm taking the distance between the atoms and the angles between them from a .dat file, which I'll provide below, but I'm getting the strange plotting result. Am I missing something in the code??
Here is my code
import numpy as np
import matplotlib.pyplot as plt
#angles
a_i, a_j, a_k, theta_0, k_theta = np.loadtxt('angles.dat', unpack=True)
#bonds
b_i, b_j, r_0, k_b = np.loadtxt('bonds.dat',unpack=True)
def U_angles(theta, theta_0, k_theta):
U = 0.5*k_theta*(theta-theta_0)**2
return U
def U_bonds(r, r_0, k_b):
U = 0.5*k_b*(r-r_0)**2
return U
r = b_j - b_i
plt.plot(r, U_bonds(r, r_0, k_b))
plt.show()
Here are the data file, which I'm using Data files
Upvotes: 0
Views: 138
Reputation: 12410
Your array r
contains some values multiple times and is not sorted. Matplotlib plots the values as you provide them. You have to sort your array and find the corresponding U
values. Luckily, np.unique()
does all this for us - returns unique values, sorts them, and returns their indexes, if you ask nicely:
import numpy as np
import matplotlib.pyplot as plt
#angles
a_i, a_j, a_k, theta_0, k_theta = np.loadtxt('angles.dat', unpack=True)
#bonds
b_i, b_j, r_0, k_b = np.loadtxt('bonds.dat',unpack=True)
def U_angles(theta, theta_0, k_theta):
U = 0.5*k_theta*(theta-theta_0)**2
return U
def U_bonds(r, r_0, k_b):
U = 0.5*k_b*(r-r_0)**2
return U
r = b_j - b_i
Uplot = U_bonds(r, r_0, k_b)
#find unique, sorted r-values and retrieve their indexes
rplot, rind = np.unique(r, return_index=True)
plt.plot(rplot, Uplot[rind])
plt.show()
However, this is a patchwork solution. If U_bonds
were a function containing a complicated calculation, you would fare better to only calculate the U
-values for unique r
-values.
...
r = b_j - b_i
#find unique, sorted r-values and retrieve their indexes
_, rind = np.unique(r, return_index=True)
plt.plot(r[rind], U_bonds(r[rind], r_0[rind], k_b[rind]))
plt.show()
Upvotes: 1