技術的な議論
ドキュメンテーションのこのセクションはユーザがJoSIMの内部動作についてより良く理解できるよう作られています。
既に述べられているように、このセクションは全体の概観を見た後、各ブロックの詳細を書いていきます。
回路の入力ファイル
JoSIMの入力ファイルは 文法ガイドに規定されている文法に沿っていることが必要です。この入力ファイルはさらに、シミュレーションエンジンにこのファイルは何をするファイルなのかを教えるためのトランジェント解析に書かれているコマンドが必要です。
入力ファイルは特別な拡張子が必要というわけではないですが、回路シミュレーションにおける標準に合わせる意味で.cir
拡張子を推奨しています。
さらに、josim-cliを実行している場合JoSIMでは-i
オプションをつけることで標準入力から入力させることができます。このコマンドではJoSIMにコマンドラインから、.end
制御文字列を受け取るまで一行一行入力を読み取る指示を出しています。他のプログラムの出力からjosim-cliにパイプするような使い方が理想的なケースです。
CLIオプション
josim-cliを使っているとき、JoSIMは入力のパースに進んでいく前にユーザからのコマンドラインオプションが何かないかチェックして処理する必要があります。
CLIのオプションオブジェクトが処理されたコマンドラインオプションから作られ、入力データとともに入力パーサに送られます。
利用可能なコマンドラインオプションは-h
を使うことで表示することが出来ます。どのコマンドがどのような動作をするかをここに記述していきます。
-h
を実行すると次のように出力されます:
Analysis (-a):
このコマンドはJoSIMでどの解析タイプを使用するか指定します。0
で電圧解析または1
で位相解析になります。バージョン2.5以降は位相モードがデフォルトのモードになっています。この方法の違いについては modified nodal analysis のセクションで議論されています。
Help (-h):
上記のヘルプメニューを表示しすぐにプログラムを終了します。このコマンドが他のコマンドと合わせて送られてた場合、このコマンドが優先します。
Input (-i):
先に述べた通り、JoSIMは一行一行コマンドラインインターフェース(標準入力)からの入力を受け付けることが出来ます。このコマンドは追加の入力ファイルの指定などに関わらず、.endコマンドが読み込まれたときまたはEOF(プラットフォーム固有)文字が読み込まれたとき終了します。
Minimal (-m):
JoSIMが進捗バーなどの不必要な出力をコマンドラインインターフェースに表示するのを防ぐために使います。詳細出力はミュートされません。
Output (-o):
結果が保存されるときの出力ファイルのファイル名と(拡張子によって)ファイルタイプを指定します。デフォルトでは、-o
が指定されファイル名が入力されなかった場合、output.csv
が出力されます。利用可能なファイルフォーマットは出力結果のセクションで詳細に議論されています。
Parallel (-p):
バージョン2.5からは今のところJoSIMで並列実行される部分はありません。このオプションが有効化されるとCMakeのスイッチでJoSIMが--DUSING_OPENMP=1
でコンパイルされているかどうかをチェックします。このオプションは将来的に非常に大規模な回路を実装する時のために用意されています。現在のところ、このオプションは何もしておらずパフォーマンスに害を与えることもありません。
Verbose (-V):
シミュレータによるログ出力レベルを設定できます。レベル1
ではシミュレーションされている回路の統計情報だけを表示します。レベル2
ではレベル1の全てと、回路中で評価された.param
記述部分全てを表示します。レベル3ではレベル2とシミュレーションされているメインの回路を全て展開して表示します。この出力は-m
によってミュートされません。
Version (-v):
josim-cliのバージョン情報の出力だけを行い終了します。どのコマンドでもデフォルトでこの文字列は出力されますが、このコマンドはバージョン情報だけを表示します。
Solver (-x):
このオプションでLUソルバと切り替えることが出来ます。デフォルトはKLUソルバです。1
を設定することでSuperLUを有効化出来ます。
入力のパース
上述の2つのうちいずれかの方法で受け取った入力データは次のステップによりパースされます:
入力の読み込み
入力データの各行は曖昧さ回避のため大文字に変換されます。これは非常に重要なことで、JoSIM is CaSe InSeNsItIvE、つまり文法上の識別子は大文字小文字が違っても全て同じものとして見なされます。各行はさらに空白によってトークン化されるため、JoSIMではスペースによる曖昧さや入力データの位置情報を排除することが出来ています。
もし行が空白または(アスタリスク)または#
(ハッシュ)の文字から始まっている場合、その行は無視され処理されません。+
(プラス)文字から始まる行は内部的に既に処理された行として扱われます。JoSIM内では、ある行における処理済みのトークンは、前の行の処理済みのトークンの最後に付け加えられることになります。
さらに、このセクションでは色々な種類の.include
記述について取り扱います。このコントロール文字列によって現在処理されているデータの中に直ちに他のファイルを含めることが出来ます。これは極めて便利で、いくつものサブサーキットが複数のファイルにわたって使用されていて(セルライブラリなど)ある場所に保存されているような時に、簡単に必要なところで各ファイルをインクルードすることが出来ます。ファイルを一元化することでサブサーキットが散在してしまう状態を減らせます。文法ガイドのincludeセクションも見てみてください。
入力のパース
前のプロセスで処理されたトークンのリストはコントロール文字列、パラメータ、サブサーキット、メイン回路に分類されさらに処理されます。
リストにある各要素の最初のトークンを見ていくことで実行されていきます。もしこれが.subckt
または.ends
であれば、信号はそれぞれサブサーキットの始まりもしくは終わりであることを表しています。これらのリストの間にある行はサブサーキットオブジェクトに追加されます。トークンが.param
トークンであった場合パラメータのリストに追加され、行が.model
から始まる場合はモデルのリストに追加されます。さらに、もしトークンが.
(ピリオド)から始まっており上のどちらでもないなら通常のコントロール文字列であり、コントロールのリストに追加されます。最後に、上のどれでもない場合メイン回路のオブジェクトとして追加されます。
各部分に関してのこれ以上の情報は文法ガイドセクションで見ることが出来ます。
パラメータ
分類されたパラメータはパースされていないパラメータがなくなるまで再帰的にパースされます。もし網羅的にパースされてもパラメータが残っている場合、定義されていないパラメータに関するエラーが投げられます。
正常な文法のパラメータはカスタム実装のダイクストラの操車場アルゴリズム1に渡されます。このアルゴリズムは処理された値を返し、関連する変数に結びつけます。パラメータはサブサーキットに固有のものであるため、パラメータはパースされているときどのサブサーキットに属しているかチェックされています。もしどこにも属していない場合グローバルパラメータとなります。これによって同じ変数名を保持していたとしてもサブサーキットは固有のパラメータの値を持つことが出来るようになります。
モデル
各モデルに対して処理が行われ文法がチェックされます。もしどのモデルも正しい文法に従っていなかった場合、JoSIMはエラーにより停止します。現在ではジョセフソン接合モデルのみがサポートされています。これについては文法ガイドのJosephson Junctionの部分で取り扱っています。
サブサーキットの展開
このセクションではサブサーキットは1段より深くならないことの確認だけを行います。つまり、ネストしたサブサーキットは1段だけになるところまで平坦化する必要があるということです。そのためには、リストの要素がX
(サブサーキットの識別子)から始まるサブサーキットがあるかどうかを再帰的にチェックします。ネストを最も深いレベルまで辿り、逆に展開していくことでネストされていないサブサーキットのリストが得られます。
展開の処理はサブサーキットの名前としてデバイスのラベル(X
から始まるトークン)を受け取ることで行われます。
その時これは、|
(パイプ)の後に名前を続けることで、ノード同様識別・展開されたサブサーキットの全てのラベルに追加されます。このプロセス中に、I/O(入出力)ノードはそれぞれが属している回路に識別・置換されていきます。
各レベルごとに親サブサーキットの名前は現在のサブサーキット名に追加されていきます。 メイン回路の展開セクションに例とともに詳細が示されています。
メイン回路の展開
各回路にはメイン回路が必要です。メイン回路はサブサーキットではないネットリストで、何らかの形での入出力を含んでいます。前のセクションの方法で平坦化されたサブサーキットは全て、デバイスのラベルとノードの名前にサブサーキット名を追加するという、前のセクションで用いたのと同じ方法を用いてメイン回路に追加されます。
このプロセスがどういう意味なのか説明するため簡単な例を示します。まずコンパクトなネットリストを示します。 注:これは完全に説明のためのものであり回路の動作を示すものではありません。
# Subcircuit
.subckt RLC IN OUT
R01 IN 1 2
L01 1 2 2pH
C01 2 OUT 2uF
.ends
# Nested subcircuit
.subckt RRLCLC IN OUT
R01 IN 1 2
X01 1 2 RLC
L01 2 3 2pH
C01 3 OUT 2uF
.ends
# Main design
V01 1 0 DC 5V
X02 1 2 RRLCLC
R01 2 0 2
.tran 0.25p 500p
この非常に単純な回路では、メイン回路で使われているサブサーキットの中にネストされた他のサブサーキットがあることを示しています。展開された回路はこのようになります:
V01 1 0 DC 5V
R01|X02 1 1|X02 2
R01|X01|X02 1|X02 1|X01|X02 2
L01|X01|X02 1|X01|X02 2|X01|X02 2PH
C01|X01|X02 2|X01|X02 2|X02 2UF
L01|X02 2|X02 3|X02 2PH
C01|X02 3|X02 2 2UF
R01 2 0 2
.TRAN 0.25P 500P
奇妙でやや複雑に感じるかもしれませんが、これにより大きなメイン回路の中で各ノードの名前とラベルを一意にすることが出来ます。これにより回路の深いところでネストしたデバイスの結果の保存がさらに簡単になります。文法ガイドの出力のセクションで結果の保存に関するさらなる情報が述べられています。
シミュレーションの種類
最後に、ネットリストを動かすためにはシミュレーションコマンドが必要です。JoSIMは現在トランジェントシミュレーションしかサポートしていません。このため正しい文法の内容に続いて、.tran
コマンドが存在する必要があります。文法に関してのさらなる情報に関しては、トランジェント解析 を見てください。
ノイズの導入
バージョン2.5より、JoSIMは抵抗(発熱素子)と並列になっている電流源より回路に熱雑音を加えられるようになりました。パース中にコントロールのリストの中に.temp
コントロール文字列が見つかった場合この機能が起動します。展開された全体のメイン回路がスキャンされ、次の式2を用いて全ての抵抗に対して並列に電流源が追加されます:
この式では、T
は.temp
コントロールから指定できるケルビン単位での温度であり、R
は抵抗で\(k_{B}\) はボルツマン定数です。この式はノイズ源に対してノイズのスペクトル振幅を与えます。さらなる情報についてはノイズに、そして文法に関しては文法ガイドに書かれています。
コマンドはサブサーキットに含めることは出来ないことに注意が必要です。警告が発生し、コマンドは無視されます。
行列の作成
行列を作成するプロセスは以下の概要の図に示されたステップを辿ります。
素子の作成
展開されたメイン回路の各行に対し、最初の文字によって素子のタイプを繰り返し識別していきます。各素子の持つnode number、ラベル、値、non-zerosなどのような関係する情報からオブジェクトが作られます。
以下に最初の一文字を下にして利用可能になる素子のリストを示します。下のリストにない文字から始まる行はエラーを起こしプログラムは終了します。
Character | Component |
---|---|
B | Junction (at present only Josephson) |
C | Capacitor |
E | Voltage Controlled Voltage Source (VCVS) |
F | Current Controlled Current Source (CCCS) |
G | Voltage Controlled Current Source (VCCS) |
H | Current Controlled Voltage Source (CCVS) |
I | Current Source |
K | Mutual Inductance |
L | Inductor |
P | Phase Source |
R | Resistor |
T | Transmission Line |
V | Voltage Source |
各素子についての文法は文法ガイドのセクションの各該当箇所に書かれています。
行列は modified nodal analysisを用いてセットアップされます。
Modified nodal analysis
回路中の電圧または電流について解くための一次方程式を用意する方法はいくつもあります。よく知られている方法の一つは回路のネットリスト中で定義された各ノードに対して式を作成する節点解析法を用いる方法です。この方法は元々のBerkeley SPICE3 が出来たことを基礎とする方法です。一方、この方法ではただ全てのノードの電圧を計算しているだけなのでインダクタやJJのような電圧依存素子を取り扱うのが難しくなります。
この欠点より、ノード電圧に加えブランチ電流を計算できるようにした、先の発展形のとしてのmodified nodal analysis (MNA)が作られました。したがってインダクタや超伝導のジョセフソン接合を大規模に使用するため我々はJoSIM中で一次方程式の集合を作ってMNA法を使用しています。
MNA法の便利な特徴は全ての素子をスタンプと呼ばれる部分行列によって表せることです。全てのスタンプの総和はAとなり、一次方程式を解くためにはxとb行列も必要です。スタンプについては今後のサブセクションで議論されます。
後体微分法
トランジェント解析では多くの素子は時間依存性\((\frac{d}{dt})\)の電圧か電流の値を持っています。こういった微分は簡単には解くことが出来ず、前のステップの値が与えられている、あるタイミングでの値を近似するためには特別なテクニックが必要になります。そのための一つの方法が後体微分法(BDF)5です。これは線形多段法であり、回路解析のアプリケーションとしては、BDF2法(二次)が最も安定であると考えられています。
この方法は以下のように表されます:
ここで\(h\)は時間微分、より正確にはシミュレーションのタイムステップです。この方法では\(n-1\)と\(n-2\)によって示される、2つ前までのタイムステップを知っている必要があります。この方法を使うと全素子に対して余計な計算が必要に見えますが、実際は微分が必要な素子を簡単化しています。
キャパシタを使って例を示します。
上記のキャパシタには、通る電流を決めるための一般式があります:
この式は時間依存であることに注意すると、BDF2法を適用する必要があります:
ここで\(V\)は素子での電圧の差であり\(V_{1} - V_{2}\)であることに注意します。ここでさらに現在のタイムステップを左辺(LHS)に置き、既知の値を右辺(RHS)に置くため式を展開します:
行列の形では次のように書けます:
上の行列はキャパシタ\(C_{1}\)を記述するものとして見なすことができる一般的なスタンプとなっています。
Modified nodal phase analysis
バージョン2.0で初めて導入され、電圧ではなくノード位相を計算するシミュレーションを行うことができます。この新しい解析法は modified nodal phase analysis (MNPA)と呼ばれ、以下で見られるように電圧-位相6関係を利用しています。
JoSIMの中での全ての素子にこの関係が適用されていればMNPAスタンプを得ることができ、phaseを直ちに解くことが出来るようになります。前のセクションでは例としてキャパシタの式を示しています。
これは以下のように素子のスタンプとしてまとめることができます:
この展開式が示す通り、キャパシタは現在のステップを計算するために4つ前までのタイムステップを必要とします。
電圧解析が可能なデザインに対しネットリストに対する変更の必要なしに位相解析が出来るようJoSIMは変化してきました。電圧は単純に位相の時間微分によって見積もられるため、電圧はユーザが必要とすればポスト処理として計算可能です。
CLIオプションセクションで述べられているように、バージョン2.5よりシミュレーションのデフォルトモードはphaseになっています。
全てのMNPAスタンプは 素子のスタンプセクションに入っています。
相互インダクタンス
相互インダクタンスが回路に含まれている場合このセクションが動作します。前のセクションで相互インダクタンスが見つかったとき、単純に後処理のためのリストに追加されます。これによって相互インダクタンスが適用される前に全てのインダクタをオブジェクトとして作成することが出来ます。
同時にカップリングされているインダクタが存在するかという正常性チェックをすることも出来るようになります。
CSRの作成
ゼロの概念というものは不思議なもので、人間にとっては何もないことであるのに機械にとっては他の全ての数値と同じであり同じだけのメモリを消費します。もちろんゼロを保持することでメモリも計算も無駄遣いはしたくないので、圧縮行格納方式(CSR)7として知られる異なる行列表現を用います。
このデータは非ゼロ (nnz)、列インデックス(ci)、行ポインタ(rp)という3つのベクトルから成ります。 非ゼロベクトルは各素子のnon-zero要素だけを保持します。列インデックスベクトルは各非ゼロが見つかったインデックスを保持します。行ポインタは各行がゼロから始まる後に非ゼロがいくつあるかを保持しています。これにより行列が疎行列であったとしてもシミュレーションエンジンは素早く非ゼロがどこにあるかを判断することができます。
例として次の5x5行列を使います:
この行列をシステムメモリに格納しようとすると数値25個分がかかります。CSR形式に変換すると次の3ベクトルとなります:
このデータ構造では数値20個分しか使用していません。これは以前の25に比べてそこまで大きく減っていないように見えますが、非常に大きな回路では非常に顕著にスケールします。
行列の作成パート中では、既に作られているオブジェクトによって各素子がnnz, ci, rpベクトルを成します。このパート中では回路全体のCSRを作るために全てのベクトルが集められます。
関連するトレースを見つける
前で全ての行列を保持するのではなくCSRによってメモリを節約していたように、シミュレーションのステップ中計算された全ての素子の値を持っておかないということもまた有益であることがあります。これを避けるためには、シミュレーションが始まる前に固有のトレース(計算済みの値への参照)を特定します。
これは出力文(.print
,.plot
または.save
)のコントロールのリストと、どの素子またはノードがそれぞれ何を参照しているかを組み合わせることで実現できます。関連するノードと電流ブランチのインデックスはシミュレーション中で使用するためここでリストに保持されます。
シミュレーション
全ての素子オブジェクトと行列を表現するCSRを用意すると、要求されたシミュレーションを行えるようになります。シミュレーションの概要を下に示します。
シミュレーションオブジェクトを作る
JoSIMは疎行列ソルバのライブラリであるSuiteSparse8を使用しておりそのうちのKLUソルバが実装されています。KLU固有のオブジェクトはCSRベクトルを用いて作る必要があります。このパートでは関連するデータを用いてオブジェクトを作成・初期化します。
シミュレーションを始める
トランジェントシミュレーションは時間領域シミュレーションと同義であるので、合計のシミュレーション時間をステップサイズで割ったステップ回数で時間シミュレーションは離散化する必要があります。
b行列を作る
各素子の式のRHSから得られた値を用いてb行列はつくられます。全ての素子にわたってイテレーションが行われ、シミュレーションが終わるまでにRHSの値は行列の正しい場所に挿入されます。
Ax=bを解く
Aとbがともに知られているとき、KLUは現在のステップに対し(未知の)xを解きます。
結果を保存する
x中の結果はイテレーションされ、前で求められた関連トレースデータだけが保持されます。
現在JoSIMの伝送線路の実装は規格化された遅延についてだけであり、伝送線路に接続されているノードや電流などは常に保持されていなければなりません。
一度完了したあとは、シミュレーションが終わるまで次のタイムステップの処理が繰り返されます。
出力結果
時間情報のついたシミュレーションの結果は各列の意味を記述したラベルとともに、二次元のデータセットの形に整形されます。
JoSIMは3つの出力形式をサポートしています。それぞれはCLIオプションで指定されたファイルの拡張子によって決定されます。形式はカンマ区切りファイル(CSV)、スペース区切りファイル(DAT)、生のSPICE出力の3つです。
CSV (.csv)
整形された結果は一番上の行のラベルとともに、各行のデータが時間から始まるようなファイルとして格納されます。このファイルの全ての素子はカンマ区切りになっています。これは人間の観点からだけでなく、グラフプロットのための様々なライブラリにとっても非常に読みやすく解釈しやすい形式です。これは出力が要求されていてもファイル名が指定されていないときのデフォルトの形式でもあります。この場合output.csvという名前のファイルに保存されます。
DAT (.dat)
CSVファイルに非常に似ていますがカンマではなく、空白が使われています。これはJSIMのような昔のシミュレータで出力として使われていた古典的なフォーマットです。
RAW形式(拡張子なし)
拡張子が指定されていない場合生のSPICEファイルが作られます。これはリストの中に変数を指定し、タイムステップとその時の変数のデータを後に続けるという非常に具体的な形式のファイルです。この形式は様々なSPICE出力のプロットツールが読むことが出来ます。
プロットのインターフェース
前のバージョンのJoSIMではFLTKとMatplotlibという2つのプロットウインドウが存在しました。しかし、このインターフェースは最終的にはメンテナンス性やクロスプラットフォームの互換性の問題から破棄されました。ユーザは各自が一番いいと思うプロットシステムを使って頂くことになりました。
以下に全ての結果が.csvとなっているファイルをプロットする簡単なPython 3スクリプトを示します。これは非常にシンプルなので必要に応じて修正してください。このスクリプトはPython 3のNumpyとMatplotlibパッケージのインストールを必要とします。オプションとして、Qt5プロットのバックエンドとして使用した場合の行をコメントにしてあります。PyQt5パッケージがインストールされている場合有効化できます。
よりエレガントな方法で結果を可視化するPlotlyや PandasというスクリプトはGitHubリポジトリのscriptsフォルダに用意されており、より多くの設定をユーザが調整できるようになっています。
#!/usr/bin/env python
import math
# import matplotlib
# matplotlib.use('Qt5Agg')
import matplotlib.pyplot as pl
from matplotlib import gridspec
import numpy as np
import csv
import sys
time = []
data = []
labels = set()
with open(sys.argv[1], 'r') as csvFile:
reader = csv.DictReader(csvFile)
labels = reader.fieldnames
data.append([])
for row in reader:
time.append(float(row[labels[0]]))
for var in range(1,len(labels)):
data.append([])
data[var].append(float(row[labels[var]]))
csvFile.close()
N = len(labels) - 1
cols = int(math.ceil(N / 4))
rows = int(math.ceil(N / cols))
gs = gridspec.GridSpec(rows, cols)
fig = pl.figure()
for var in range(1,len(labels)):
ax = fig.add_subplot(gs[var - 1])
ax.plot(time, data[var])
ax.set_xlabel(labels[0])
ax.set_ylabel(labels[var])
fig.set_tight_layout(True)
fig.show()
input()
-
E. W. Dijkstra, "Algol 60 translation : An Algol 60 translator for the x1 and Making a translator for Algol 60" in MR35, Mathematisch Centrum, Amsterdam, 1961 ↩
-
J. Satchell, "Limitations on HTS single flux quantum logic," in IEEE Transactions on Applied Superconductivity, vol. 9, no. 2, pp. 3841-3844, June 1999, doi: 10.1109/77.783865 ↩
-
L. Nagel, "Spice: A computer program to simulate computer circuits" in University of California, Berkeley UCB/ERL Memo M520, pp. 201-204, 1995 ↩
-
C. Ho, A. Ruehli, & P. Brennan, "The modified nodal approach to network analysis" in IEEE Transactions on circuits and systems, vol. 22, no. 6, pp. 506-509, 1975 ↩
-
C. F. Curtiss, & J. O. Hirschfelder, "Integration of stiff equations" in Proceedings of the National Academy of Sciences, vol. 38, no. 3, pp. 235-243, 1952 ↩
-
T. P. Orlando & K. A. Delin, "Foundations of Applied Superconductivity", Addison-Wesley Reading, MA vol. 8, 1991 ↩
-
A. Bulu, J. T. Fineman, M. Frigo, J. R. Gilbert and C. E. Leiserson, "Parallel sparse matrix-vector and matrix-transpose-vector multiplication using compressed sparse blocks" in Proceedings of the twenty-first annual symposium on Parallelism in algorithms and architectures, pp. 233-244, 2009 ↩
-
T. A. Davis, "Direct methods for sparse linear systems", SIAM, Philadelphia, 2006 ↩