如何处理相图中的不完整轨迹:补全或完全移除?
解决相图中不完整轨迹的问题
给定非线性系统
xdot = x + exp(-y) ydot = -y
原相图绘制代码
import numpy as np import matplotlib.pyplot as plt xvalues, yvalues = np.meshgrid(np.arange(-5, 5, 0.1), np.arange(-5, 5, 0.1)) xdot = xvalues - np.exp(-yvalues) ydot = - yvalues plt.streamplot(xvalues, yvalues, xdot, ydot, color='r', linewidth=0.5, density=1.2) plt.show()
问题描述
绘制出的相图中存在部分视觉效果不佳的不完整轨迹(类似示意中的蓝色轨迹),需要实现以下两种效果之一:
- (i) 移除这类不完整轨迹;
- (ii) 将其补全为类似黑色轨迹的完整形态。
解决方案
两种需求均可以实现,具体方案如下:
方案一:移除不完整轨迹
利用streamplot的minlength参数过滤短轨迹,设置合理阈值即可只保留完整流线:
import numpy as np import matplotlib.pyplot as plt xvalues, yvalues = np.meshgrid(np.arange(-5, 5, 0.1), np.arange(-5, 5, 0.1)) xdot = xvalues - np.exp(-yvalues) ydot = -yvalues # minlength设置为轨迹最小长度,可根据实际效果调整 plt.streamplot(xvalues, yvalues, xdot, ydot, color='r', linewidth=0.5, density=1.2, minlength=0.5) plt.show()
方案二:补全不完整轨迹
方法1:调整streamplot内置参数
通过修改积分方向和最大长度参数,延长短轨迹:
import numpy as np import matplotlib.pyplot as plt xvalues, yvalues = np.meshgrid(np.arange(-5, 5, 0.1), np.arange(-5, 5, 0.1)) xdot = xvalues - np.exp(-yvalues) ydot = -yvalues # maxlength控制单条流线最大长度,integration_direction设为双向积分 plt.streamplot(xvalues, yvalues, xdot, ydot, color='r', linewidth=0.5, density=1.2, maxlength=10, integration_direction='both') plt.show()
方法2:手动数值积分延拓
对于内置参数无法补全的轨迹,用scipy的数值积分工具单独计算并绘制延拓轨迹:
import numpy as np import matplotlib.pyplot as plt from scipy.integrate import solve_ivp # 定义系统微分方程 def system(t, z): x, y = z return [x - np.exp(-y), -y] # 生成网格数据 xvalues, yvalues = np.meshgrid(np.arange(-5, 5, 0.1), np.arange(-5, 5, 0.1)) xdot = xvalues - np.exp(-yvalues) ydot = -yvalues fig, ax = plt.subplots() # 绘制原流线并获取流线对象 sp = ax.streamplot(xvalues, yvalues, xdot, ydot, color='r', linewidth=0.5, density=1.2) # 过滤短轨迹并补全 min_length = 0.5 # 短轨迹长度阈值 for line in sp.lines.get_segments(): # 计算当前轨迹的长度 dx = line[1][0] - line[0][0] dy = line[1][1] - line[0][1] length = np.sqrt(dx**2 + dy**2) if length < min_length: # 获取轨迹的两个端点 start_point = line[0] end_point = line[1] # 向两个方向积分延拓 t_span = [0, 5] # 从起点向前积分 sol_forward = solve_ivp(system, t_span, start_point, t_eval=np.linspace(0, 5, 100)) # 从终点向后积分 sol_backward = solve_ivp(system, t_span, end_point, t_eval=np.linspace(0, 5, 100)) # 绘制延拓后的轨迹 ax.plot(sol_forward.y[0], sol_forward.y[1], color='r', linewidth=0.5) ax.plot(sol_backward.y[0], sol_backward.y[1], color='r', linewidth=0.5) # 移除原短轨迹 line.remove() plt.show()
可行性说明
- 移除不完整轨迹:完全可以实现,通过
minlength参数快速过滤即可,阈值可按需调整。 - 补全不完整轨迹:大部分情况可以实现,内置参数调整适合快速优化;手动积分延拓能处理更复杂的短轨迹,若轨迹终止是因为系统奇点(如导数无穷大),则无法完全补全,但能显著改善视觉效果。
内容的提问来源于stack exchange,提问作者user1393214
相关产品推荐
相关产品推荐

