#はじめに
こんにちは。アナログ回路シミュレーションソフトであるLTSpiceをJupyter Notebook上から回して、
結果を取得する方法を紹介します。
LTSpiceには、コマンドラインによるバッチ処理モードが用意されており、
そちらを使ってネットリストの生成とシミュレーションの実行を行います。
#なぜやろうと思ったか
機械学習でアナログ回路設計を行うことを試みるために、自動シミュレーションを行う必要があったため。
こちらの記事で紹介しています。 → https://qiita.com/dl10yr/items/fe100b3aeb18045d3ff5
#動作環境
OS: Ubuntu 18.04.2 LTS
ubuntuでLTSpiceを動かすためにwineを使っています。
Jupyter Notebook: 5.7.8
Python: 3.7.3
#シミュレーションを回す
基本的にはこれです。
シミュレーションを行うネットリストのあるフォルダまで移動して、これで実行できます。
$ wine /hogehoge/LTSpice/XVIIx64.exe -b XXX.net
/hogehoge/LTSpice/XVIIx64.exe: XVIIx64.exeのあるLTSpiceのフォルダ
-b: バッチモードでのシミュレーションを行うことを指定するオプション
XXX.net: シミュレーションを行いたいネットリスト
#結果の取得
結果の取得は、自分が使っているものは2パターンあります。
###.logファイルから取得
大体のものはこっちです。.logファイルをテキスト処理して欲しい数字を抽出します。
上手くテキスト処理するのが難しいですね。。。
import codecs
with codecs.open(file + ".log", "r", "Shift-JIS", "ignore") as file:
s = file.read()
そして、重要なポイントは、codecsモジュールを使用することです。
"ignore"を指定することでエラーを無視して力技で読んでくれます。
###.rawファイルから取得
.rawファイルに結果が記載されるシミュレーションがあります。
これはltspiceモジュールを利用して読み込みます。
pythonにはLTSpiceのデータを読み込むモジュールがあるんです!
import ltspice
l = ltspice.Ltspice(file + ".raw")
l.parse()
r0_sim = l.getData("output_impedance_at_V(output)")[0]
#Jupyter Notebookにおける具体的な実装例
具体例を上げて紹介します。
今回は上で紹介した記事で行ったオペアンプ回路のCMRRの解析と出力抵抗の解析部分について紹介します。
シミュレーションの実行し、結果を返却する関数の実装例です。
コードはGithubに上げたここのJupyter Notebookのコードから抜粋しています。
コードが汚く不必要な記述もあるかもしれません。。。
Jupyter Notebook上からコマンドを実行するので、subprocessモジュールを利用しています。
###CMRR
こっちは.logファイルから結果の取得をしています。
import ltspice
import os
import subprocess
import shutil
import codecs
import re
def analysis_CMRR(self): ##CMRR
try:
os.mkdir(self.wk_dir + "/CMRR")
shutil.copy(self.wk_dir + "/tsmc018.lib", self.wk_dir + "/CMRR/tsmc018.lib")
except:
pass
os.chdir(self.wk_dir + "/CMRR")
file = self.wk_dir + "/CMRR/test-OpAmp-CMRR"
shutil.copyfile(self.wk_dir + "/test-OpAmp-CMRR.net", file + ".net")
output = subprocess.run(["wine", "/hogehoge/LTSpice/XVIIx64.exe", "-b","test-OpAmp-CMRR.net"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
with codecs.open(file + ".log", "r", "Shift-JIS", "ignore") as file:
s = file.read()
lines = s.split("\n")
for line in lines:
if "cmrr:" in line:
cmrr = line
words = re.split('[|(|)|,|]| |\r',cmrr)
words = [x for x in words if x]
for word in words:
if "dB" in word:
CMRR_value = float(word.strip("dB"))
os.chdir(self.wk_dir)
return CMRR_value
###出力抵抗
こっちは.rawファイルからの結果取得をしています。
import ltspice
import os
import subprocess
import shutil
import codecs
import re
def analysis_Out_R(self):
##出力抵抗
try:
os.mkdir(self.wk_dir + "/Out_R")
shutil.copy(self.wk_dir + "/tsmc018.lib", self.wk_dir + "/Out_R/tsmc018.lib")
except:
pass
os.chdir(self.wk_dir + "/Out_R")
file = self.wk_dir + "/Out_R/test-OpAmp-Out_R"
shutil.copyfile(self.wk_dir + "/test-OpAmp-Out_R.net", file + ".net")
tf_con = ".tf V(OUTPUT) VIN"
with open(file + ".net", "r") as f:
s = f.read()
line = s.split("\n")
line.insert(-3, tf_con)
wr_s = "\n".join(line)
with open(file + ".net", "w") as f:
f.write(wr_s)
output = subprocess.run(["wine", "/hogehoge/LTSpice/XVIIx64.exe", "-b","test-OpAmp-Out_R.net"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
l = ltspice.Ltspice(file + ".raw")
l.parse()
r0_sim = l.getData("output_impedance_at_V(output)")[0]
os.chdir(self.wk_dir)
return r0_sim
#ネットリストを生成する
余談になりますが、バッチモードでは、回路図ファイル(asc)からネットリストを生成することもできます。
$ wine /hogehoge/LTSpice/XVIIx64.exe -netlist test-OpAmp-CMRR.asc