蒙特卡洛粒子扩散模拟中指定区域粒子数随时间统计的技术求助
解决粒子扩散Monte Carlo模拟的时间点粒子数统计问题
首先咱们先拆解核心问题:你的每个粒子的position_tracker只记录位置发生变化的时刻,但模拟总共有10次移动(对应10个时间点),所以得先把每个粒子在所有10个时间点的位置补全,才能准确统计每个时间点的区域内粒子数。
先说说你现有代码的问题
- 循环变量冲突:外层和内层循环都用了
x,直接导致循环逻辑混乱,内层应该换用time_step这类独立变量; - 循环范围错误:
range(99)只遍历了0-98号粒子,漏掉了第99个;range(9)只到第8个时间点,漏掉了第9个时间步; - 未处理短tracker的情况:比如粒子1的tracker只有3个元素,后面7个时间点的位置完全没被处理;
- 变量未初始化:
y没有初始值就直接自增,会触发未定义错误。
解决方案分步走
我们需要先给每个粒子补全10个时间点的位置,再逐时间点统计区域内的粒子数:
步骤1:补全所有粒子的时间点位置
对于每个粒子:
- 如果它的
position_tracker长度是L,前L个时间点直接用tracker里的坐标; - 从第
L个时间点到第9个时间点,全部沿用tracker的最后一个坐标(因为粒子没移动,位置保持不变)。
步骤2:逐时间点统计区域内粒子数
对每个时间点(0到9),遍历所有粒子,判断该时间点的位置是否在gr.tspace中,累加计数。
步骤3:绘制粒子数随时间变化的曲线
完整代码示例
import numpy as np import matplotlib.pyplot as plt # 假设gr已定义,包含list_of_atoms和tspace # 步骤1:补全每个粒子的10个时间点位置 total_time_steps = 10 all_positions = [] for atom in gr.list_of_atoms: tracker = atom.position_tracker # 处理tracker长度不足或超过10的情况 if len(tracker) >= total_time_steps: full_pos = tracker[:total_time_steps] else: last_pos = tracker[-1] num_missing = total_time_steps - len(tracker) full_pos = tracker + [last_pos] * num_missing all_positions.append(full_pos) # 步骤2:统计每个时间点的区域内粒子数 count_per_time = np.zeros(total_time_steps) for time_step in range(total_time_steps): current_count = 0 for pos_list in all_positions: if pos_list[time_step] in gr.tspace: current_count += 1 count_per_time[time_step] = current_count # 步骤3:绘制变化曲线 plt.figure(figsize=(8, 5)) plt.plot(range(total_time_steps), count_per_time, marker='o', linestyle='-', color='navy') plt.xlabel('时间步') plt.ylabel('区域内粒子数') plt.title('粒子数随时间变化趋势') plt.grid(True, alpha=0.3) plt.show()
代码细节说明
- 补全位置时兼容了tracker长度超过10的情况(虽然你的模拟是10次移动,大概率不会出现,但做了鲁棒性处理);
- 统计逻辑清晰易懂,如果粒子数量极大(比如上万级),可以改用numpy向量化操作进一步提速;
- 绘图部分用matplotlib生成了带标记点的曲线,方便直观观察粒子数的变化趋势。
针对你尝试的lngth列表的优化
你之前尝试记录每个tracker的长度,其实可以用它简化补全逻辑,比如:
lngth = [len(atom.position_tracker) for atom in gr.list_of_atoms]
后续补全时直接用这个列表判断每个粒子需要补多少个位置,和上面的代码逻辑一致,只是写法更简洁。
内容的提问来源于stack exchange,提问作者Tom
相关产品推荐
相关产品推荐

