SymPy 中的维度分析

Dimensional analysis in SymPy

我正在尝试使用 SymPy 来完成以下任务:

  1. 简化一些物理量和物理常数的代数方程。
  2. 执行量纲分析以确保我的方程式正确
  3. 通过代入物理量的值来计算方程。

我的Minimal, Reproducible Example for this problem is below, where I want to find the amount of mass equivalent to a given energy using mass-energy equivalence。 (我 运行 在 Jupyter 中这样做,因为它可以使方程式看起来不错。)

盯着E=m*c**2我想解决m:

from sympy import *
E, m, c = symbols('E m c') # symbols, for energy, mass, and speed of light
eq_E = Eq(E, m*c**2) # define equation for E in terms of m and c
eq_m = Eq(m,solve(eq_E,m)[0]) # solve equation for m
display(eq_m)

m = \frac{E}{c^2}

太棒了!现在是执行维度分析的时候了。我将以焦耳为单位定义我的能量 E,我不需要定义 c 的单位,因为它是一个物理常数,而且我使用 SI 单位(这似乎是默认单位)对于 SymPy)。 我想知道 1 焦耳的能量有多少质量,我想知道这个质量的单位。 我将使用 Quantity() 定义我的变量,然后设置再次将它们放在方程式中,以便 SymPy 可以解决它:

from sympy.physics.units import Quantity, energy, joule, speed_of_light
from sympy import Eq, solve
m = Quantity('m')                    # Define unknown mass 'm' as a quantity
E = Quantity('E')                    # Define known energy 'E' as a quantity
E.set_dimension(energy)              # E is a quantity of energy
E.set_scale_factor(1.0*joule, 'SI')  # set energy to 1.0 Joules
eq_E = Eq(E,m*speed_of_light**2)     # define E = mc^2
eq_m = Eq(m,solve(eq_E,m)[0])        # Solve E = mc^2 for m
display(eq_m)

Quantity(m,m)=\frac{Quantity(E,E)}{Quantity(speed_{oflight},c)^2}

长得不好看,但是表达的很到位。现在我想看看 m 的值是多少,以及 m 有什么单位。首先,我将 m 的解决方案保存在 m_solve:

m_solve = solve(eq_E,m)[0]
display(m_solve)

\frac{Quantity(E,E)}{Quantity(speed_{oflight},c)^2}

现在,我可以看看 m_solve 有哪些单位吗?

print(m_solve.dimension)

AttributeError: 'Mul' object has no attribute 'dimension'

m_solve的值呢?

print(m_solve.scale_factor)

AttributeError: 'Mul' object has no attribute 'scale_factor'

什么是Mul?我如何获得 Quantity?更一般地说,SymPy 中是否有一个很好的工作流程来处理符号方程并沿途检查单位,然后最终评估这些方程?如果不是 SymPy,是否有好的替代品? (我尝试了一些替代方案,最有希望的 pint,但它似乎缺乏符号支持。)

我制作了一个名为 SymDim 的 python 包(Symbolic Dim综合分析)使用 SymPy 和 astropy.units.

执行此操作

使用

安装 SymDim(它还将安装 SymPy、Astropy 和 num2tex)
pip install SymDim

下面的例子可以在Jupyter notebook中运行 第一个用例:我知道光速但我还不知道我需要多少能量,只想看看 m 的单位是什么:

E = S('E', u.J) # energy in Joules ('J')
c = S('c', u.m/u.s, 3.0e8) # speed of light: 3.0e8 m/s
m = S('m') # I don't know the units yet!
E.equals(m*c**2)
m = E.solve_for(m)[0]  # solve returns a list of possible solutions
display(m)

m是公斤!现在我想看看有多少质量相当于 9000 焦耳的能量:

E = S('E', u.J, 9000) # energy
m = S('m') # I don't know the units or the value
E.equals(m*c**2)
m = E.solve_for(m)[0]
display(m)

这就是我想要的!您还可以做一些疯狂的事情,例如:

x = S('x', u.m, 5.0)
L = S('L', u.m, 3.0)
Zw = S('Z_w')
T0 = S('T_0', u.K, 300.0)
T0.equals(Zw**(x/L-S(1)/S(2))) # enclose '1' and '2' in Sympint so python doesn't evaluate them 1/2 as 0.5
display(T0)
# now solve for Zw, whatever that is
Zw = T0.solve_for(Zw)[0]
display(Zw) # good to know that Zw has units of Kelvin^(6/7)!

免责声明:

  1. 有些部分很笨拙
  2. 有时您不能重用一个变量,而是需要重新定义它,一旦它执行了它的 equals() 方法。
  3. 我还需要更新 GitHub 上的文档。

请在 https://github.com/AndrewChap/symdim

提交 bugs/requests