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

Julia实现盒子内粒子碰撞模拟:update!与主模拟函数编写求助

Julia二维盒子粒子碰撞模拟实现

你已经完成了粒子结构体和两粒子碰撞的核心逻辑,以下是剩余函数的完整实现:
粒子碰撞示意图

前置参数定义

首先定义粒子半径作为全局常量,你也可以根据需求将其改为函数入参:

# 粒子半径,可根据实际需求调整
const PARTICLE_RADIUS = 0.02

update!函数实现

完全匹配你提出的逻辑要求:

function update!(particles, xlims, ylims, dt)
    num_p = length(particles)
    # 第一步:处理粒子间碰撞
    for i in 1:num_p
        p1 = particles[i]
        # 只遍历i之后的粒子,避免同一对粒子重复处理两次
        for j in i+1:num_p
            p2 = particles[j]
            # 计算两粒子间距
            dx = p1.pos[1] - p2.pos[1]
            dy = p1.pos[2] - p2.pos[2]
            dist = sqrt(dx^2 + dy^2)
            # 间距小于2倍半径判定为碰撞
            if dist < 2 * PARTICLE_RADIUS
                collision!(p1, p2)
                # 可选优化:避免粒子重叠卡住,碰撞后稍微分开两个粒子
                overlap = 2 * PARTICLE_RADIUS - dist
                push_vec = [dx, dy] ./ dist .* overlap / 2
                p1.pos .+= push_vec
                p2.pos .-= push_vec
            end
        end
        # 第二步:处理边界反弹
        # x方向边界
        if p1.pos[1] < xlims[1]
            p1.pos[1] = xlims[1]
            p1.vel[1] *= -1
        elseif p1.pos[1] > xlims[2]
            p1.pos[1] = xlims[2]
            p1.vel[1] *= -1
        end
        # y方向边界
        if p1.pos[2] < ylims[1]
            p1.pos[2] = ylims[1]
            p1.vel[2] *= -1
        elseif p1.pos[2] > ylims[2]
            p1.pos[2] = ylims[2]
            p1.vel[2] *= -1
        end
    end
    # 第三步:更新所有粒子位置
    for p in particles
        p.pos .+= p.vel .* dt
    end
    return nothing
end

实现说明:

  • 碰撞对遍历采用i<j的规则,避免同一对粒子被重复检测两次,减少一半计算量
  • 新增了重叠修正逻辑,避免两个粒子碰撞后重叠导致后续帧反复触发碰撞的bug
  • 边界反弹时同时修正粒子位置到边界上,避免粒子卡在边界外

particles_in_box!主模拟函数实现

function particles_in_box!(particles, xlims, ylims, T, dt=0.01)
    # 计算总模拟步数
    total_steps = round(Int, T / dt)
    # 逐时间步推进模拟
    for _ in 1:total_steps
        update!(particles, xlims, ylims, dt)
        # 可选:如果需要记录每帧粒子位置、绘制动画,可以在这里添加对应逻辑
    end
    return particles
end

可选初始化工具函数

如果你需要自动生成指定数量的初始粒子,可以用以下工具函数:

function init_particles(n::Int, xlims, ylims)
    particles = Particle[]
    for _ in 1:n
        # 初始位置在盒子范围内,避免生成时就越界
        pos = [
            rand()*(xlims[2] - xlims[1]) + xlims[1],
            rand()*(ylims[2] - ylims[1]) + ylims[1]
        ]
        # 初始速度范围设为[-1, 1],可按需调整
        vel = 2 .* rand(2) .- 1
        push!(particles, Particle(pos, vel))
    end
    return particles
end

使用示例

# 示例:模拟10个粒子在0~1的正方形盒子里运动10秒
xlims = (0.0, 1.0)
ylims = (0.0, 1.0)
particles = init_particles(10, xlims, ylims)
particles_in_box!(particles, xlims, ylims, 10.0, 0.01)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.12 10:42:01