我正在尝试使用 Matplotlib 的 quiver 函数绘制引力矢量场,我有一个函数可以计算由任意数量的质量引起的引力场,但是在绘制它时,我在质量位置周围得到了奇怪的结果。出于矢量绘图的目的,该函数返回 x 和 y 方向上的场分量、它们的 x 和 y 坐标以及 2D 场数组,这对于绘图不是必需的,但对于稍后与此无关的其他代码来说是必需的。 x 和 y 分量是列表,其中每个索引的 4 个列表中的每个值对应于相同的元素,因此在所有 4 个列表中的索引 0 处,我们可以获得字段的 x 和 y 分量及其位置。|| |当前代码如下:
当以颜色编码形式表示场的强度时,该函数起作用,但是当使用 quiver 函数绘制它时,我获得了您在图像中看到的内容。除了质量本身附近出现有趣的矢量之外,该场是正确的。我不认为这是除以零的错误,因为我在计算时忽略了这些错误。
import matplotlib.pyplot as plt
import numpy as np
import math
G = 6.674 * 10**(-11)
#Function to calculate gravitational field at each point on the screen caused by all other masses whose mass and positions are defined in lists along with the size of the screen and the components of the field
def gravfield(mass, x, y, screen_width, screen_height, give_components = False):
#Define screen position points
x_screen = list(range(screen_width))
y_screen = list(range(screen_height))
#Define empty array containing all field magnitudes at each pixel position of the screen along with empty field component lists and positions
field = np.zeros((screen_width, screen_height))
field_x = []
field_y = []
field_x_position = []
field_y_position = []
#Calculate the gravitational field from each mass by the vector method
for i in range(len(x_screen)):
for n in range(len(y_screen)):
#Define empty variable which will end up being the value of the field at a specific position after all mass contributions have been added
x_field = 0
y_field = 0
for j in range(len(mass)):
#Calculate position vector from the mass causing the field to the point affected
x_distance = x[j] - x_screen[i]
y_distance = y[j] - y_screen[n]
distance = np.sqrt((x_distance**2) + (y_distance**2))
if not math.isclose(distance, 0):
#Calculate the unit vector of the shortest path between the mass and point
x_unit_vector = x_distance / distance
y_unit_vector = y_distance / distance
#Calculate magnitude of the field
magnitude = (G * mass[j] * 1) / (distance ** 2)
#Calculate the component of the field in each direction and add them to the variable which contains the resultant field value at that position
x_field = (magnitude * x_unit_vector) + x_field
y_field = (magnitude * y_unit_vector) + y_field
else:
pass
#Add the resultant field component value and its position to the defined lists and calculate its magnitude which is assigned to an array where each position corresponds to a pixel on the screen
#Only fill the field component lists if specified
if give_components == True:
gx = x_field
gy = y_field
field_x.append(gx)
field_y.append(gy)
g = np.sqrt((gx**2) + (gy**2))
field[n, i] = g
field_x_position.append(i)
field_y_position.append(n)
else:
gx = x_field
gy = y_field
g = np.sqrt((gx**2) + (gy**2))
field[n, i] = g
#Return the specified elements
if give_components == True:
return field, field_x, field_y, field_x_position, field_y_position
else:
return field
mass = [400000000000000000000000, 800000000000000000000000]
x_cord = [10, 15]
y_cord = [10, 15]
screen_width = 20
screen_height = 20
give_components = True
field, field_x, field_y, field_x_position, field_y_position = gravfield(mass, x_cord, y_cord, screen_width, screen_height, give_components)
fig, ax = plt.subplots()
# Plot the vectors using quiver
ax.quiver(field_x_position, field_y_position, field_x, field_y)
# Set the x and y axis limits
ax.set_xlim([min(field_x_position), max(field_x_position)])
ax.set_ylim([min(field_y_position), max(field_y_position)])
# Show the plot
plt.show()
This function works when representing the intensity of the field in a color-coded form, but when plotting it with the quiver function I obtain what you can see in the image. The field is correct apart from near the mass itself where interesting vectors arise. I do not think it is a divide by zero error since those I just ignore when calculating.
代码的问题在于,你将整个屏幕宽度上的场分量附加到列表中,然后在循环的每次迭代中,你再次对整个屏幕高度执行此操作。这会导致你的向量位置不正确,从而导致绘图出现问题。
你需要做的是将
field_x
、
field_y
、
field_x_position
和
field_y_position
列表的追加缩进到循环的内层,这样每次计算出一个新的场分量时,你都会将其附加到列表中,以及其相应的
x
和
y
位置。
以下是更正后的代码:
import matplotlib.pyplot as plt
import numpy as np
import math
G = 6.674 * 10**(-11)
#Function to calculate gravitational field at each point on the screen caused by all other masses whose mass and positions are defined in lists along with the size of the screen and the components of the field
def gravfield(mass, x, y, screen_width, screen_height, give_components = False):
#Define screen position points
x_screen = list(range(screen_width))
y_screen = list(range(screen_height))
#Define empty array containing all field magnitudes at each pixel position of the screen along with empty field component lists and positions
field = np.zeros((screen_width, screen_height))
field_x = []
field_y = []
field_x_position = []
field_y_position = []
#Calculate the gravitational field from each mass by the vector method
for i in range(len(x_screen)):
for n in range(len(y_screen)):
#Define empty variable which will end up being the value of the field at a specific position after all mass contributions have been added
x_field = 0
y_field = 0
for j in range(len(mass)):
#Calculate position vector from the mass causing the field to the point affected
x_distance = x[j] - x_screen[i]
y_distance = y[j] - y_screen[n]
distance = np.sqrt((x_distance**2) + (y_distance**2))
if not math.isclose(distance, 0):
#Calculate the unit vector of the shortest path between the mass and point
x_unit_vector = x_distance / distance
y_unit_vector = y_distance / distance
#Calculate magnitude of the field
magnitude = (G * mass[j] * 1) / (distance ** 2)
#Calculate the component of the field in each direction and add them to the variable which contains the resultant field value at that position
x_field = (magnitude * x_unit_vector) + x_field
y_field = (magnitude * y_unit_vector) + y_field
else:
pass
# Add the resultant field component value and its position to the defined lists
if give_components == True:
gx = x_field
gy = y_field
field_x.append(gx)
field_y.append(gy)
g = np.sqrt((gx**2) + (gy**2))
field[n, i] = g
field_x_position.append(i)
field_y_position.append(n)
else:
gx = x_field
gy = y_field
g = np.sqrt((gx**2) + (gy**2))
field[n, i] = g
#Return the specified elements
if give_components == True:
return field, field_x, field_y, field_x_position, field_y_position
else:
return field
mass = [400000000000000000000000, 800000000000000000000000]
x_cord = [10, 15]
y_cord = [10, 15]
screen_width = 20
screen_height = 20
give_components = True
field, field_x, field_y, field_x_position, field_y_position = gravfield(mass, x_cord, y_cord, screen_width, screen_height, give_components)
fig, ax = plt.subplots()
# Plot the vectors using quiver
ax.quiver(field_x_position, field_y_position, field_x, field_y)
# Set the x and y axis limits
ax.set_xlim([min(field_x_position), max(field_x_position)])
ax.set_ylim([min(field_y_position), max(field_y_position)])
# Show the plot
plt.show()
通过这个更改,你的向量场现在应该可以正确绘制了。
标签:python,matplotlib,vector,gravity From: 76650005