Python Matplotlib Quiver绘制向量场

vtwuwzda  于 2023-08-06  发布在  Python
关注(0)|答案(1)|浏览(103)

我试图用Matplotlib的箭袋函数绘制一个引力向量场,我有一个函数可以计算由任何数量的质量引起的引力场,但当绘制它时,我得到了质量位置周围的奇怪结果。为了矢量绘图,该函数返回x和y方向上的场分量、它们的x和y坐标以及2D场阵列,该2D场阵列对于绘图不是必需的,但是对于稍后与此无关的其他代码是必需的。x和y分量是列表,其中每个索引的4个列表中的每个值对应于相同的元素,因此在所有4个列表中的索引0处,我们可以获得字段的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 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()

字符串
这个函数在以颜色编码的形式表示场的强度时有效,但是当用 Flutter 函数绘制它时,我得到了你在图像中看到的。除了在质量本身附近出现有趣的矢量外,场是正确的。我不认为这是一个除以零的错误,因为那些我只是忽略计算时。


的数据

kt06eoxx

kt06eoxx1#

我相信你的解决方案是正确的,但是当使用默认参数(即angles="uv"而不是angles="xy")或不使用ax.set_aspect(1)(相当于:ax.set_aspect("equal")),则向量可能看起来是错误的。在进行其中一项更改后,结果看起来很好,如下所示。我还对你的代码做了一些其他编辑以简化事情(注意:不需要执行if value == True,因为您可以执行if value)。

import matplotlib.pyplot as plt
import numpy as np
import math

plt.close("all")

G = 6.674e-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
                    y_field += magnitude*y_unit_vector
                
            # 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
            field[n, i] = np.sqrt((x_field**2) + (y_field**2))
    
            # Only fill the field component lists if specified 
            if give_components:
                field_x_position.append(i)
                field_y_position.append(n)
                field_x.append(x_field)
                field_y.append(y_field)

    # Return the specified elements        
    if give_components:
        return field, field_x, field_y, field_x_position, field_y_position
    return field

mass = [4000]
x_cord = [10]
y_cord = [10]
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)

field_x = np.array(field_x)
field_y = np.array(field_y)

fig, ax = plt.subplots()

# Plot the vectors using quiver
ax.quiver(field_x_position, field_y_position, field_x, field_y)
ax.set_aspect(1)

# 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
fig.show()

字符串


的数据

相关问题