我尝试模拟以下简单的 RC 电路,使用有限元方法来验证我对稍微改变的传输线问题的解决方案。
虽然与问题没有直接关系,但
R(i)
、R(0i)
或C(i)
不一定彼此相等。
在模拟开始时,底部导轨中的所有节点都具有相同的电势。同样,顶部导轨中的所有节点在开始时具有相同的电势。
我可以使用 PySpice 在循环中生成此电路,即
for i in range(1, number_of_branches - 1):
circuit.R('R'+str(i), 'n'+str(i), 'n'+str(i+1), 1000@u_Ω)
for i in range(1, number_of_branches - 1):
circuit.R('R_'+str(i), 'n_'+str(i), 'n_'+str(i+1), 1000@u_Ω)
for i in range(1, number_of_branches-1):
circuit.C('C'+str(i), 'n'+str(i), 'n_'+str(i), 100@u_μF)
但是,我无法在循环中生成初始条件。如果我单独输入所有节点,即
simulator.initial_condition(n1=ic,n2=ic,n3=ic,n4=ic,n_2=0,n_3=0,n_4=0)
模拟结果给了我我想要的。但这对于大量分支来说是不可能的。主要问题是
n1, n2, n_1, n_2...
是只能由电路方法识别的变量。这些节点是使用创建电路元件时传递的字符串名称创建的(如果它们尚不存在)。我深入研究了代码。我尝试检查由 circuit
方法创建的所有对象,以获取可用于传递初始条件的节点列表,但这似乎超出了我的 Python 技能。
如何在循环中提供初始条件?这也可以通过传递字典来实现。我有下面的最小工作示例。
import PySpice.Logging.Logging as Logging
logger = Logging.setup_logging()
import matplotlib.pyplot as plt
from PySpice.Probe.Plot import plot
from PySpice.Spice.Netlist import Circuit
from PySpice.Unit import *
circuit = Circuit('Test')
steptime=.1@u_us
finaltime = 1000@u_ms
number_of_branches = 6
ic=100@u_mV
for i in range(1, number_of_branches - 1):
circuit.R('R'+str(i), 'n'+str(i), 'n'+str(i+1), 1000@u_Ω)
for i in range(1, number_of_branches - 1):
circuit.R('R_'+str(i), 'n_'+str(i), 'n_'+str(i+1), 1000@u_Ω)
for i in range(1, number_of_branches-1):
circuit.C('C'+str(i), 'n'+str(i), 'n_'+str(i), 100@u_μF)
circuit.C('C'+str(number_of_branches-1), 'n'+str(number_of_branches-1), circuit.gnd, 100@u_μF)
ra = circuit.R('Ra', 'n1', 'n_1', 10@u_Ω)
simulator = circuit.simulator(temperature=25, nominal_temperature=25)
simulator.initial_condition(n1=ic,n2=ic,n3=ic,n4=ic,n_2=0,n_3=0,n_4=0)
analysis = simulator.transient(step_time=steptime, end_time=finaltime)
figure = plt.subplots(figsize=(11, 6))
axe = plt.subplot(111)
plot(analysis['n3']-analysis['n_3'], axis=axe)
plt.show()
作为临时解决方案,我决定使用开关。
我使用开关将上轨中的所有节点连接到保持在
ncc
的 Vcc
节点,将下轨中的所有节点连接到保持在 ndd
节点的 Vdd
节点。开关最初是闭合的,这迫使所有节点处于所需的值。它们会在某个时间打开,我假设模拟开始了。
在代码方面,我删除了以下行。
simulator.initial_condition(n1=ic,n2=ic,n3=ic,n4=ic,n_2=0,n_3=0,n_4=0)
并添加以下功能。
def switch_generator(circuit, number_of_branches, switchingtime):
circuit.PulseVoltageSource('SV', 'SVN', circuit.gnd,initial_value=1, pulsed_value=-1,
pulse_width=finaltime, period=finaltime, delay_time=switchingtime)
circuit.R('SR1', 'SVN', circuit.gnd, 1@u_kΩ)
circuit.V('Vcc', 'ncc', circuit.gnd, 100@u_mV)
circuit.V('Vdd', 'ndd', circuit.gnd, 0@u_mV)
for i in range(1, number_of_branches - 1):
circuit.VoltageControlledSwitch('S'+str(i), 'n'+str(i), 'ncc','SVN', circuit.gnd, model='switch')
for i in range(2, number_of_branches - 1):
circuit.VoltageControlledSwitch('S_'+str(i), 'n_'+str(i), 'ndd','SVN', circuit.gnd, model='switch')
return circuit
我正在寻找的值在两次模拟之间几乎相同。差异在于小数点后第 7 位有效数字。
这种方法会带来一些相关的计算负担。切换过程似乎会带来一次性的额外负担,但对于长时间的模拟来说,这种负担会逐渐消失。
如果我的格式不正确,我深表歉意,这是我对 SO 帖子的第一个回答。 以下是我相信您正在寻找的内容:
kwargDict = {}
for n in netlist.node_names:
kwargDict[n] = IC
simulator.initial_conditions(**kwargDict)
Pyspice 的源代码显示它将接受任何带有节点的字符串名称和值的 kwarg 字典,因此您可以随意修改 kwargDict,但是您想更改初始条件。完成后,将其与双星号 (**) 一起传递给 Simulator.initial_conditions 来代替 arg 列表。所以从你的例子来看: (n1=ic,n2=ic,n3=ic,n4=ic,n_2=0,n_3=0,n_4=0) 变为:
{'n1':ic,'n2':ic,'n3':ic,'n4':ic,'n_2':0,'n_3':0,'n_4':0},带有字符串名称的字典作为键,IC 值作为值
希望这有帮助!