You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

基于Pygame的库仑定律模拟故障:电荷受力行为异常排查

库仑定律模拟程序的物理异常修复方案

问题根源分析

  1. 同号电荷相互吸引:attraction函数中力的方向计算错误,库仑定律中同号电荷应相互排斥,但现有代码的力方向指向对方,导致吸引。
  2. 异号电荷同向运动:计算加速度时错误使用电荷量q代替质量m,违反牛顿第二定律F=ma,导致电子和质子的加速度方向异常,出现同步运动的情况。

修复步骤

1. 修正库仑力的方向

在attraction函数中添加负号,调整力的方向,确保同号电荷排斥、异号电荷吸引:

def attraction(self, other):
    other_x, other_y = other.x, other.y
    distance_x = other_x - self.x
    distance_y = other_y - self.y
    distance = math.sqrt(distance_x ** 2 + distance_y ** 2)

    # 添加负号修正力的方向
    force = -(1 / (4 * Pi * epsilon0)) * self.q * other.q / (distance ** 2)
    theta = math.atan2(distance_y, distance_x)
    force_x = math.cos(theta) * force
    force_y = math.sin(theta) * force
    return force_x, force_y

2. 引入质量属性并修正加速度计算

库仑力作用下的加速度需遵循F=ma,因此需要为电荷添加质量属性,并替换原有用q计算加速度的错误逻辑:

  • 添加质量常量:
# constants
Pi = np.pi
epsilon0 = 8.85e-12
q = 1.6e-19
m_proton = 1.67e-27  # 质子质量
m_electron = 9.11e-31  # 电子质量
  • 修改Charge类初始化方法,加入质量参数:
def __init__(self, x, y, radius, color, q, m):
    self.x = x
    self.y = y
    self.radius = radius
    self.color = color
    self.q = q
    self.m = m  # 新增质量属性

    self.x_vel = 0
    self.y_vel = 0
  • 修正update_position中的加速度计算:
def update_position(self, charges):
    total_fx = total_fy = 0
    for charge in charges:
        if self == charge:
            continue

        fx, fy = self.attraction(charge)
        total_fx += fx
        total_fy += fy

    # 用质量m代替电荷量q计算加速度
    self.x_vel += total_fx / self.m * self.TIMESTEP
    self.y_vel += total_fy / self.m * self.TIMESTEP

    self.x += self.x_vel * self.TIMESTEP
    self.y += self.y_vel * self.TIMESTEP

3. 调整时间步长与电荷创建逻辑

  • 调整TIMESTEP为适配物理量级的时间步长,避免运动异常:
class Charge:
    TIMESTEP = 1e-10
  • 修改电荷创建代码,传入对应质量:
# 初始电荷
proton = Charge(200, 200, 10, RED, q, m_proton)
electron = Charge(300, 200, 10, BLUE, -q, m_electron)

# 鼠标创建电荷
if event.button == 1:  # 左键创建质子
    charges.append(Charge(pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, RED, q, m_proton))
if event.button == 3:  # 右键创建电子
    charges.append(Charge(pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, BLUE, -q, m_electron))

完整修复后的代码

import pygame
import numpy as np
import math

pygame.init()

# window-settings
WIDTH, HEIGHT = 800, 800
WIN = pygame.display.set_mode((WIDTH, HEIGHT))
pygame.display.set_caption("Electric field simulation")

# constants
Pi = np.pi
epsilon0 = 8.85e-12
q = 1.6e-19
m_proton = 1.67e-27
m_electron = 9.11e-31

# colors
WHITE = (255,255,255)
BLACK = (0,0,0)
BLUE = (100, 149, 237)
RED = (188, 39, 50)

class Charge:
    TIMESTEP = 1e-10

    def __init__(self, x, y, radius, color, q, m):
        self.x = x
        self.y = y
        self.radius = radius
        self.color = color
        self.q = q
        self.m = m

        self.x_vel = 0
        self.y_vel = 0

    def draw(self, win):
        pygame.draw.circle(win, self.color, (self.x, self.y), self.radius)

    def attraction(self, other):
        other_x, other_y = other.x, other.y
        distance_x = other_x - self.x
        distance_y = other_y - self.y
        distance = math.sqrt(distance_x ** 2 + distance_y ** 2)

        force = -(1 / (4 * Pi * epsilon0)) * self.q * other.q / (distance ** 2)
        theta = math.atan2(distance_y, distance_x)
        force_x = math.cos(theta) * force
        force_y = math.sin(theta) * force
        return force_x, force_y

    def update_position(self, charges):
        total_fx = total_fy = 0
        for charge in charges:
            if self == charge:
                continue

            fx, fy = self.attraction(charge)
            total_fx += fx
            total_fy += fy

        self.x_vel += total_fx / self.m * self.TIMESTEP
        self.y_vel += total_fy / self.m * self.TIMESTEP

        self.x += self.x_vel * self.TIMESTEP
        self.y += self.y_vel * self.TIMESTEP


def main():
    run = True
    clock = pygame.time.Clock()

    proton = Charge(200, 200, 10, RED, q, m_proton)
    electron = Charge(300, 200, 10, BLUE, -q, m_electron)
    charges = [electron, proton]

    while run:
        clock.tick(60)
        WIN.fill(WHITE)

        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                run = False

            if event.type == pygame.MOUSEBUTTONDOWN:
                if event.button == 1:
                    charges.append(Charge(pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, RED, q, m_proton))
                if event.button == 3:
                    charges.append(Charge(pygame.mouse.get_pos()[0], pygame.mouse.get_pos()[1], 10, BLUE, -q, m_electron))

        for charge in charges:
            charge.update_position(charges)
            charge.draw(WIN)

        pygame.display.update()

    pygame.quit()


if __name__ == "__main__":
    main()

内容的提问来源于stack exchange,提问作者Mahlnycdir

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.24 22:09:21