用python / sympy解决RC电路

时间:2014-12-15 16:10:23

标签: python physics sympy

我独立完成了Mark Newman的“计算物理”一书,练习6.5具体(可以下载here)。问题是要解决由复指数源电压驱动的RC电路中的节点电压。

我想做的是将我的节点方程转换为 Av = B 的形式。这是我到目前为止所做的。

import numpy as np
import sympy

# Define constants
R1=R3=R5 = 1e3
R2=R4=R6 = 2e3
C1 = 1e-6
C2 = 0.5e-6
x_plus = 3
x_minus = 0
w = 1000

# Define relations
V_plus = sympy.symbols('V_plus')
t = sympy.symbols('t')

V_plus = x_plus*sympy.exp(1j*w*t)
V_minus = 0

V1,V2,V3 = sympy.symbols('V1 V2 V3')

V1_eqn = (V1-V_plus)/R1 + (V1-V2)/(1/(1j*w*C1)) + (V1-V_minus)/R4
V2_eqn = (V2-V_plus)/R2 + (V2-V1)/(1/(1j*w*C1)) + (V2-V_minus)/R5 + (V2-V3)/(1/(1j*w*C2))
V3_eqn = (V3-V_plus)/R3 + (V3-V2)/(1/(1j*w*C2)) + (V3-V_minus)/R6

# Prepare
V = [V1,V2,V3]
V_vec = np.matrix(V)

A = np.matrix([
    [V1_eqn.expand().coeff(x) for x in V],
    [V2_eqn.expand().coeff(x) for x in V],
    [V3_eqn.expand().coeff(x) for x in V]
    ])
print(A)

现在,我遇到的问题是提取三个方程的常数项,这样我就可以将它们加载到 B 中。除其他事项外,其中一个问题是“常数术语”实际上并不是恒定的。它是't'的复指数函数。由于笔和纸是一个相当简单的问题,我确切地知道常数术语的样子,所以我可以提取它。我的目标是以不需要知道答案的方式解决这个问题;)。

我考虑过的一种方法是采用每个等式并减去我已经放入 Av 的所有术语,但这似乎有点草率而且不是非常pythonic。有没有人知道一种更好的方法来提取技术上不恒定的常数项?感谢。

3 个答案:

答案 0 :(得分:1)

除了表示法中的一些快捷方式之外,减去您已经放入A的条款正是您应该而且必须这样做的。

这是一个稍短的版本:

import sympy

# Define constants
R1=R3=R5 = 1e3
R2=R4=R6 = 2e3
C1 = 1e-6
C2 = 0.5e-6
x_plus = 3
x_minus = 0
w = 1000

# Define relations
V_plus = sympy.symbols('V_plus')
t = sympy.symbols('t')

V_plus = x_plus*sympy.exp(1j*w*t)
V_minus = 0

V1,V2,V3 = sympy.symbols('V1 V2 V3')

# Using a matrix to collect all equations allows you to use a matrix-vector-product below
eqns = sympy.matrices.Matrix([
    (V1-V_plus)/R1 + (V1-V2)/(1/(1j*w*C1)) + (V1-V_minus)/R4,
    (V2-V_plus)/R2 + (V2-V1)/(1/(1j*w*C1)) + (V2-V_minus)/R5 + (V2-V3)/(1/(1j*w*C2)),
    (V3-V_plus)/R3 + (V3-V2)/(1/(1j*w*C2)) + (V3-V_minus)/R6
])

# Prepare
V = [V1,V2,V3]
V_vec = sympy.matrices.Matrix(V)

# The "or 0" does nothing if there are coefficients y in x, but if there aren't, it replaced
# the "None" with "0". This again is required for using A * V_vec below
A = sympy.matrices.Matrix([ [ x.expand().coeff(y) or 0 for y in V ] for x in eqns ])

print(A)

remainder = (eqns - A * V_vec)
remainder.simplify()
print remainder

答案 1 :(得分:1)

您可以直接使用sympy.solve解决此问题:

import sympy as sp

R1=R3=R5 = 1e3
R2=R4=R6 = 2e3
C1 = 1e-6
C2 = 0.5e-6
w = 1000
V0 = 5

t = sp.Symbol('t')
E = sp.exp(1j*w*t)

V1, V2, V3 = sp.symbols('V1 V2 V3')

V_plus = V0*E
V_minus = 0

V1_eqn = (V1-V_plus)/R1 + (V1-V2)/(1/(1j*w*C1)) + (V1-V_minus)/R4
V2_eqn = (V2-V_plus)/R2 + (V2-V1)/(1/(1j*w*C1)) + (V2-V_minus)/R5 + (V2-V3)/(1/(1j*w*C2))
V3_eqn = (V3-V_plus)/R3 + (V3-V2)/(1/(1j*w*C2)) + (V3-V_minus)/R6

print sp.solve([ sp.Eq(V1_eqn, 0), sp.Eq(V2_eqn, 0), sp.Eq(V3_eqn, 0)], [V1, V2, V3] )

答案 2 :(得分:0)

替换零是获得剩余常量的好方法。此外,jacobian方法更多的是数学和#34;用coeff方法做你正在做的事情的方式。

>>> eqs = sympy.Matrix((V1_eqn, V2_eqn, V3_eqn))
>>> eqs.jacobian(V)
Matrix([
[0.0015 + 0.001*I,          -0.001*I,                 0],
[        -0.001*I, 0.0015 + 0.0015*I,         -0.0005*I],
[               0,         -0.0005*I, 0.0015 + 0.0005*I]])