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

如何使用Sympy绘制带单位的3D函数?

问题描述

尝试使用Sympy创建带单位的3D绘图,无论将单位嵌入函数本身,还是添加到绘图轴变量(如(a, 2.*meter/second^2., 0.*meter/second^2.))中,都会出现错误,错误类型为TypeError: Cannot convert the expression to float或TypeError: cannot determine the truth value of Relational。查阅Sympy文档后未找到相关实现方法,询问是否有既定方案。

用户提供的测试代码:

import matplotlib.pyplot as plt
from sympy.physics.units.systems.si import SI
from sympy.physics.units import second, newton, meter, kilogram
from sympy import init_printing
from sympy import *
from IPython.display import display
from sympy.plotting import plot3d

F, m, a = symbols('F_ m_ a_')

def F(a,m):
    return a*(meter/second**2.)*m*kilogram

plot3d(F(a,m), (a, 2.,0.), (m, 0.,1.), zlabel=S('F_'))
解决方案

Sympy的plot3d工具本身不支持直接处理带单位的表达式,因为绘图过程需要将符号表达式转换为数值,而单位符号会干扰这一转换流程。以下是两种可行的实现方式:

方式一:分离数值与单位,手动标注轴单位

先定义纯数值的物理关系函数,避免单位符号进入绘图计算,完成绘图后再为坐标轴添加单位标注:

from sympy import symbols, plot3d, S
from sympy.physics.units import meter, kilogram, newton, second

# 定义无单位的符号变量
a, m = symbols('a_ m_')

# 纯数值函数(对应F=ma的物理关系)
def F(a, m):
    return a * m

# 绘制3D图,轴范围使用纯数值,手动添加单位标注
p = plot3d(F(a, m), 
           (a, 0., 2.), 
           (m, 0., 1.), 
           xlabel=S('a_ (m/s²)'), 
           ylabel=S('m_ (kg)'), 
           zlabel=S('F_ (N)'),
           show=False)
p.show()

这种方式既保证绘图功能正常运行,又能清晰展示各物理量的单位,是最简便的解决方案。

方式二:保留单位计算,转换数值后用Matplotlib绘图

如果需要在计算过程中保留单位,可以先将带单位的表达式转换为纯数值,再使用Matplotlib直接绘制3D图形(Sympy的plot3d对带单位的数值转换支持有限):

import numpy as np
import matplotlib.pyplot as plt
from sympy import symbols
from sympy.physics.units import meter, kilogram, second, newton, convert_to

a, m = symbols('a_ m_')

# 带单位的物理函数
def F_with_units(a_val, m_val):
    return a_val*(meter/second**2) * m_val*kilogram

# 将带单位的结果转换为牛顿并提取数值
F_numeric = lambda a_num, m_num: convert_to(F_with_units(a_num, m_num), newton).evalf()

# 生成网格数据
a_vals = np.linspace(0, 2, 100)
m_vals = np.linspace(0, 1, 100)
A, M = np.meshgrid(a_vals, m_vals)

# 向量化函数以处理数组
Z = np.vectorize(F_numeric)(A, M)

# 使用Matplotlib绘制3D曲面图
fig = plt.figure()
ax = fig.add_subplot(projection='3d')
ax.plot_surface(A, M, Z)

# 添加轴标签与单位
ax.set_xlabel('a (m/s²)')
ax.set_ylabel('m (kg)')
ax.set_zlabel('F (N)')

plt.show()

这种方式保留了单位计算的严谨性,同时借助Matplotlib的灵活性完成绘图,适合需要严格单位校验的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 17:56:16