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
相关产品推荐
相关产品推荐

