Python 带电粒子在复合场中的动力学仿真

高中物理具有抽象性特点,由于高中生的抽象思维发展还未完全,在学习过程中难免存在一定的问题和困惑,若不能及时解决存在的这一矛盾,则对今后物理学习产生不利影响。

实践的认识的唯一来源。

但是,由于条件和技术限制,不可能每一个问题都通过做实验的方式解决。

那我们就可以结合发达的信息技术,通过软件模拟现实情况,暂时替代实验。

 

 

程序设计

运用Python编程并导入NumPy库

代码缩略图

完整代码 

import turtle as t    # 海龟画图库
import numpy as np
import time    # 时间库,用来放缩模拟速率

step_xy = 50    # 坐标单位长度(像素)
E0, Arg_E0, slot_E0 = 50, 0.5 * np.pi, 4    # 电场的场强,方向,所在象限
B0, Dir_B0, slot_B0 = 0.01, -1, 1    # 磁场的场强,方向,所在象限
x, y = 0, 100    # 质点初始坐标
loc1 = np.array([x, y])    # 初始的数组形式,方便调用numpy计算


class Environment:
    """
    画环境
    """

    def __init__(self):
        self.xlim = int(400)
        self.ylim = int(300)
        pass

    def draw_cs(self):
        """
        画坐标系
        :return: 无返回值
        """
        # 设置画笔
        t.speed(10)
        t.pensize(2)

        # 画x轴
        t.penup()
        t.goto(-self.xlim - 30, 0)  # 画出头
        t.pendown()
        t.goto(self.xlim, 0)

        # 画x轴的箭头
        t.penup()
        t.goto(self.xlim - 5, 5)
        t.pendown()
        t.goto(self.xlim, 0)
        t.goto(self.xlim - 5, -5)

        # 画x轴的点
        for i in range(-self.xlim, self.xlim, step_xy):
            # 画点
            t.penup()
            t.goto(i, 10)
            t.pendown()
            t.goto(i, 0)
            # 画字
            # t.penup()
            # if i == 0:  # 对0的处理
            #     t.goto(i - 10, - (step_xy - 50))
            #     t.write(i, align='center')
            # else:
            #     t.goto(i, -(step_xy - 25))
            #     t.write(i, align='center')
            # t.pendown()
        # 画x轴的X
        t.penup()
        t.goto(self.xlim * 0.96, -self.xlim * 0.1)  # x的相对位置
        t.pendown()
        t.write('x', font=("Arial", 16))

        # 画y轴
        t.penup()
        t.goto(0, -self.ylim - 30)
        t.pendown()
        t.goto(0, self.ylim)
        # 画y轴的箭头
        t.penup()
        t.goto(-5, self.ylim - 5)
        t.pendown()
        t.goto(0, self.ylim)
        t.goto(5, self.ylim - 5)

        # 画y轴的点
        for i in range(-self.ylim, self.ylim, step_xy):
            # 画点
            t.penup()
            t.goto(10, i)
            t.pendown()
            t.goto(0, i)
            # # 画字
            # t.penup()
            # if i == 0:  # 对0的处理
            #     pass
            # else:
            #     t.goto(- (step_xy - 25), i - 5)
            #     t.write(i, align='center')
            # t.pendown()
        # 画y轴的y
        t.penup()
        t.goto(-self.ylim * 0.1, self.ylim * 0.93)  # y的相对位置
        t.pendown()
        t.write('y', font=("Arial", 16))

        # 恢复初始位置
        t.penup()
        t.goto(0, 0)
        t.pendown()
        t.pensize(1)
        pass

    def electric_field(self, E, Arg_E, slot_E):
        """
        画电场
        :param E: 电场强度
        :param Arg_E: 电场方向向量辐角
        :param slot_E: 电场所在象限
        :return: 无返回值
        """
        t.speed(speed=None)
        t.delay(delay=None)
        t.tracer(n=10, delay=None)
        t.pensize(1)

        list_start = (0, 50, -50, -50, 50)
        x_start = list_start[slot_E]
        sign = (0, 1, 1, -1, -1)
        signy = sign[slot_E]

        if Arg_E == 0.5 * np.pi:  # 90d
            t.pendown()
            for i in range(x_start, x_start // abs(x_start) * self.xlim, x_start // abs(x_start) * step_xy):
                t.penup()
                t.goto(i, signy * self.ylim)
                t.pendown()
                t.goto(i, 0)
                # 画箭头
                t.penup()
                t.goto(i - 5, signy * self.ylim - 5)
                t.pendown()
                t.goto(i, signy * self.ylim)
                t.goto(i + 5, signy * self.ylim - 5)
                t.penup()

        elif Arg_E == np.pi:
            t.pendown()
            for i in range(x_start, x_start // abs(x_start) * self.ylim, x_start // abs(x_start) * step_xy):
                t.penup()
                t.goto(signy * self.xlim, i)
                t.pendown()
                t.goto(0, i)
                # 画箭头
                t.penup()
                t.goto(signy * self.xlim + 5, i + 5)
                t.pendown()
                t.goto(signy * self.xlim, i)
                t.goto(signy * self.xlim + 5, i - 5)
                t.penup()

        elif Arg_E == 1.5 * np.pi:
            t.pendown()
            for i in range(x_start, x_start // abs(x_start) * self.xlim, x_start // abs(x_start) * step_xy):
                t.penup()
                t.goto(i, signy * self.ylim)
                t.pendown()
                t.goto(i, 0)
                # 画箭头
                t.penup()
                t.goto(i + 5, signy * self.ylim + 5)
                t.pendown()
                t.goto(i, signy * self.ylim)
                t.goto(i - 5, signy * self.ylim + 5)
                t.penup()

        elif Arg_E == 0:
            t.pendown()
            for i in range(x_start, x_start // abs(x_start) * self.ylim, x_start // abs(x_start) * step_xy):
                t.penup()
                t.goto(signy * self.xlim, i)
                t.pendown()
                t.goto(0, i)
                # 画箭头
                t.penup()
                t.goto(signy * self.xlim - 5, i - 5)
                t.pendown()
                t.goto(signy * self.xlim, i)
                t.goto(signy * self.xlim - 5, i + 5)
                t.penup()

        else:  # y = tan a * (x - b)
            print('不支持方向')
            pass

        t.goto(x_start // abs(x_start) * self.xlim // 2, self.ylim * 1.1)  # y的相对位置
        t.pendown()
        t.write('E = ', font=("Arial", 16))
        t.penup()
        t.goto(x_start // abs(x_start) * self.xlim // 2 + 40, self.ylim * 1.1)
        t.write(str(E), font=("Arial", 16))
        t.goto(x_start // abs(x_start) * self.xlim // 2 + 80, self.ylim * 1.1)
        t.write('V/m', font=("Arial", 16))
        t.goto(0, 0)
        t.pendown()
        pass

    def magnetic_field(self, B, Dir_B, slot_B):
        """
        画磁场
        :param B: 磁感应强度
        :param Dir_B: 磁场方向,1为向外,-1为向内
        :param slot_B: 磁场所在象限
        :return: 无返回值
        """
        t.penup()

        x_start = [0, 0.5 * step_xy, -self.xlim + 0.5 * step_xy, -self.xlim + 0.5 * step_xy, 0.5 * step_xy]
        y_start = [0, 0.5 * step_xy, 0.5 * step_xy, -self.ylim + 0.5 * step_xy, -self.ylim + 0.5 * step_xy]
        startx = int(x_start[slot_B])
        starty = int(y_start[slot_B])

        # 画磁场
        if Dir_B == 1:
            for i in range(startx, startx + self.xlim, step_xy):
                for j in range(starty, starty + self.ylim, step_xy):
                    t.goto(i, j)
                    t.pensize(3)
                    t.pendown()
                    t.goto(i + 2, j)
                    t.penup()
                    pass
            t.goto(0, 0)
            pass

        elif Dir_B == -1:
            size = 3
            for i in range(startx, startx + self.xlim, step_xy):
                for j in range(starty, starty + self.ylim, step_xy):
                    t.goto(i, j)
                    t.pensize(size - 1)
                    t.penup()
                    t.goto(i + size, j + size)
                    t.pendown()
                    t.goto(i - size, j - size)
                    t.penup()
                    t.goto(i - size, j + size)
                    t.pendown()
                    t.goto(i + size, j - size)
                    t.penup()
            t.goto(0, 0)
            pass

        else:
            print('错误')
            pass

        # 画文字
        t.goto(startx // abs(startx) * self.xlim // 2, self.ylim * 1.1 - 20)
        t.write('B = ', font=("Arial", 16))
        t.penup()
        t.goto(startx // abs(startx) * self.xlim // 2 + 40, self.ylim * 1.1 - 20)
        t.write(str(B), font=("Arial", 16))
        t.goto(startx // abs(startx) * self.xlim // 2 + 80, self.ylim * 1.1 - 20)
        t.write('T', font=("Arial", 16))
        t.goto(0, 0)
        t.penup()
        pass

    @staticmethod
    def Judge(x, y):
        slot = None
        if y > 0:
            if x > 0:
                slot = 1
            elif x < 0:
                slot = 2
            else:
                pass
        elif y < 0:
            if x > 0:
                slot = 4
            elif x < 0:
                slot = 3
            else:
                pass
        else:
            pass
        # print(slot)
        return slot

    pass


class MassPoint:
    """
    质点
    """

    mass = 0.001  # 质量(kg)
    q = 0.2  # 电荷量(C)带正负

    v = 100  # m/s
    Angle_v = -0.3 * np.pi  # rad
    V = np.array([v * np.cos(Angle_v), v * np.sin(Angle_v)])  # 速度向量,大小(m/s)
    specific_charge = q / mass  # 比荷
    slot_now = Environment().Judge(x, y)
    pass


class Move:

    @staticmethod
    def ElectricFieldForce(slot):
        if slot == slot_E0:
            qE = MassPoint.q * E0
            F_electric = np.array([qE * np.cos(Arg_E0), qE * np.sin(Arg_E0)])

        else:
            F_electric = 0

        return F_electric
        pass

    @staticmethod
    def LorentzForce(v1, Angle_v, slot):
        if slot == slot_B0:
            Bqv = B0 * MassPoint.q * v1  # 标量
            F_lorentz = np.array([Bqv * np.cos(Angle_v - Dir_B0 * np.pi / 2),
                                  Bqv * np.sin(Angle_v - Dir_B0 * np.pi / 2)])

        else:
            F_lorentz = 0

        return F_lorentz

        pass

    @staticmethod
    def Gravity():
        g = 0  # 重力加速度(m/s)
        G = np.array([0, -MassPoint.mass * g])
        return G
        pass

    @staticmethod
    def Painter(T):
        X = np.array([0, 0])
        x1, y1 = x, y
        loc = np.array([x1, y1])
        slot = Environment.Judge(x1, y1)
        F = Move.LorentzForce(MassPoint.v, MassPoint.Angle_v, slot) + Move.ElectricFieldForce(slot) + Move.Gravity()
        a = F / MassPoint.mass
        V = MassPoint.V
        t.tracer(n=1, delay=None)
        t.goto(x1, y1)
        t.pendown()

        while True:
            slot = Environment.Judge(loc[0], loc[1])
            v = np.linalg.norm(V)
            print(v)

            if V[1] > 0:
                Angle_v = np.arccos(V[0] / v)
            elif V[1] < 0:
                Angle_v = -np.arccos(V[0] / v)
            else:
                if V[0] > 0:
                    Angle_v = 0
                elif V[0] < 0:
                    Angle_v = np.pi
                else:
                    Angle_v = None

            slot = Environment.Judge(loc[0], loc[1])
            F = Move.LorentzForce(v, Angle_v, slot) + Move.ElectricFieldForce(slot) + Move.Gravity()
            a = F / MassPoint.mass
            V = V + a * [T]
            X = X + V * [T]
            loc = loc + X

            t.goto(loc[0], loc[1])
            print(X)


if __name__ == '__main__':
    Environment().draw_cs()
    Environment().electric_field(E0, Arg_E0, slot_E0)
    Environment().magnetic_field(B0, Dir_B0, slot_B0)
    t.tracer(n=1, delay=None)
    t.penup()
    t.goto(x, y)
    Move().Painter(0.005)
    t.mainloop()

运行效果

 

 

 

问题和BUG 

轨迹总是左偏,电场线在部分象限画的有问题

  • 0
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
好的,我可以给您讲一下如何使用 Python 模拟带电粒子在电场中运动。 首先,您需要了解在电场中运动是由粒子所受到的电场力所决定的,而电场力的大小与粒子所处位置的电场强度有关。因此,我们需要知道粒子所处位置的电场强度。 接下来,我们可以使用 Python 的科学计算库 NumPy 来进行数值计算。我们可以将电场看作一个二维网格,每个网格点的值表示该点处的电场强度。我们可以使用 NumPy 的数组来表示这个二维网格。 然后,我们需要定义带电粒子的初始位置、速度和电荷量等参数。在模拟过程,我们可以使用欧拉法或者 RK4 等数值积分方法来计算粒子的位置和速度。 最后,我们可以将粒子的位置和电场强度等数据可视化,以便更好地观察粒子在电场中运动。 这是一个简单的带电粒子在电场中运动模拟的示例代码: ``` python import numpy as np import matplotlib.pyplot as plt # 定义电场强度网格 field = np.zeros((100, 100)) # 定义带电粒子参数 q = 1.6e-19 # 电荷量 m = 9.11e-31 # 质量 x0 = 50 # 初始位置 x 坐标 y0 = 50 # 初始位置 y 坐标 vx0 = 1e5 # 初始速度 x 分量 vy0 = 0 # 初始速度 y 分量 # 模拟过程 x = x0 y = y0 vx = vx0 vy = vy0 dt = 1e-9 # 时间步长 t = 0 trajectory = [] for i in range(10000): # 计算电场强度 Ex = field[int(x), int(y)] Ey = field[int(x), int(y)] # 计算电场力 Fx = q * Ex Fy = q * Ey # 计算加速度 ax = Fx / m ay = Fy / m # 计算速度 vx += ax * dt vy += ay * dt # 计算位置 x += vx * dt y += vy * dt # 记录轨迹 trajectory.append((x, y)) # 更新时间 t += dt # 可视化轨迹和电场 plt.imshow(field, cmap='gray') plt.plot([x for x, y in trajectory], [y for x, y in trajectory]) plt.show() ``` 需要注意的是,这只是一个简单的示例代码,实际应用需要根据具体情况进行调整和优化。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值