COMSOL Multiphysics のメッシュデータや解析データをテキストファイルに書き出したいと思ったことはありませんか? 他のソフトウェアプログラムに情報を渡すときや, スプレッドシートに書き出すときなど, 様々な場面で活用できます. また, 使用する他のツールのニーズに合わせて, データの書き出し形式をカスタマイズしたい場合も多いでしょう. アプリケーションビルダーを使えば, 簡単にカスタマイズできます. その方法を見ていきましょう!
ソフトウェアプラットフォーム間の連携
COMSOL Multiphysics モデルを作成し, ある系の熱解析を行っているとします. あなたは, 他の種類の解析を行っているチームメンバーと共同作業を行っています. 同僚たちはあなたほど幸運ではなく, COMSOL Multiphysics を使用できませんが, それでもあなたのモデリング結果にアクセスする必要があります. 幸いなことに, 解析データを特定のテキストファイル形式へ簡単に変換でき, 同僚が使用しているソフトウェアツールで読み取ることが可能です.

異なる要素タイプを持つシンプルな COMSOL Multiphysics 熱モデル.
さて, 上図に示すように, 四面体, ピラミッド型, 角柱型, 六面体 (ブリック型) など, あらゆる種類の要素を含むモデルの定常熱解析を実行すると仮定します. さらに, データを読み込むソフトウェアツールでは 線形離散化 が必須であると仮定します. つまり, 要素の角を定義する各ノード (頂点) の温度を書き出し, 要素内の温度場を計算するために温度の線形補間を使用する必要があるとします. したがって, すべての頂点の位置, 各頂点の温度データ, そしてどの頂点が各要素をどのように定義するかという記述を書き出す必要があります.
もちろん, この種の情報を記述する方法は様々です. このブログでは, シンプルなカンマ区切り形式を前提とします. その一般的なサンプルを以下に示します.
N, 1, 0.0, 0.0, 0.0 ... N, 1000, 10.0, 10.0, 10.0 D, 1, 332.0 ... D, 1000, 343.0 TET, 1, 2, 4, 6, 3 ... TET, 100, 42, 43, 41, 45 PYR, 101, 47, 48, 41, 40, 44 ... PRISM, 201, 66, 67, 65, 72, 74, 73 ... HEX, 301, 81, 82, 83, 84, 91, 92, 93, 94 ...
これらの各行の意味を見てみましょう. すべての行は, その行に含まれる情報の種類を示す文字列で始まり, 情報はカンマで区切られて様々な フィールド に分けられています. 最初の行には, 頂点 (ノード) の位置情報があります:
N, 1, 0.0, 0.0, 0.0
N 文字の後の最初のフィールドはノード番号 (任意) で, 2番目, 3番目, 4番目のフィールドはそのノードの x, y, z 座標です. つまり, 最初のノードはグローバル原点にあります. 上記のサンプルでは, 合計1000個のノードがあります.
次に, 各ノード位置における計算された温度データが別の行に書き込まれます:
D, 1, 332.0
ここで, D 文字の後の最初のフィールドは節点番号, 2番目のフィールドはその節点の位置における温度です.
残りの行は, 要素に関する情報と, それらが節点によってどのように定義されているかを示します. まずは最初の要素の定義を見てみましょう:
TET, 1, 2, 4, 6, 3
この行は四面体 (TET) 要素を定義しています. 最初のフィールドは要素番号で, 次の4つのフィールドは四面体を定義する節点を示します. ここでは, 節点2, 4, 6, 3が要素の節点1から4です. このような情報は 要素の接続性 とも呼ばれ, これを理解するために, 要素の図を見てみましょう.

四面体要素は4つの節点で定義されます.
この四面体要素の例では, 節点2, 4, 6が最初の3つの節点です. 右手の法則を用いてこれらの3つの節点を順番にたどっていくと, 4番目の節点 (節点番号3) の方向を指すベクトルが得られます. すべての3次元要素タイプにおける要素の順序を以下に示します.

4つの異なる 3D 要素タイプの要素番号規則.
テキストファイルに書き込む必要があるデータ形式がわかったので, アプリケーションビルダーを使用してこれをどのように実行するかを見てみましょう.
アプリケーションビルダーを使用したデータの書き出し
先ほど示したように, 定常温度解析が既に計算されている既存の 3D モデルからアプリ開発を始めます. アプリを開発するには, アプリケーションビルダーに切り替え, グラフィカルユーザーインターフェースを定義し, アプリの背後にあるデータ処理コードを記述します. インターフェースは非常にシンプルで, メソッド を呼び出す ボタン と, 情報を表示する メッセージログ のみで構成されています. アプリは1つのことだけを実行します: ユーザーがボタンをクリックすると, 上記のデータ形式がテキストファイルに書き込まれ, 書き込まれた内容の概要がメッセージログに表示されます.

このアプリには, メソッド (2) を呼び出すボタン (1) があります. メソッド (2) は, メッシュと解のデータをファイルに書き込み, 統計情報をメッセージログ (3) に書き込みます.
このメソッドにはすべてのデータ処理コードが含まれており, 以下に行番号と赤字の文字列を付けて示します.
1 StringBuffer FileB = new StringBuffer(); 2 double[][] d_Vtx = model.mesh("mesh1").getVertex(); 3 String[][] s_Vtx = toString(d_Vtx); 4 for (int m = 0; m < s_Vtx[0].length; m++) { 5 FileB.append("N, "+(m+1)+", "+s_Vtx[0][m]+", "+s_Vtx[1][m]+", "+s_Vtx[2][m]+"\n"); 6 } 7 model.result().numerical().create("interp", "Interp").setInterpolationCoordinates(d_Vtx); 8 model.result().numerical("interp").set("expr", "T"); 9 double[][][] AllData = model.result().numerical("interp").getData(); 10 model.result().numerical().remove("interp"); 11 for (int m = 0; m < AllData[0][0].length; m++) { 12 FileB.append("D, "+(m+1)+", "+AllData[0][0][m]+"\n"); 13 } 14 int[][] Ei; 15 int numTets = model.mesh("mesh1").getNumElem("tet"); 16 if (numTets > 0) { 17 Ei = model.mesh("mesh1").getElem("tet"); 18 for (int m = 0; m < numTets; m++) { 19 FileB.append("TET, "+(m+1)+", "+(Ei[0][m]+1)+", "+(Ei[1][m]+1)+", "+(Ei[2][m]+1)+", "+(Ei[3][m]+1)+"\n"); 20 } 21 } 22 int numPyrs = model.mesh("mesh1").getNumElem("pyr"); 23 if (numPyrs > 0) { 24 Ei = model.mesh("mesh1").getElem("pyr"); 25 for (int m = 0; m < numPyrs; m++) { 26 FileB.append("PYR, "+(m+1+numTets)+", "+(Ei[0][m]+1)+", "+(Ei[1][m]+1)+", "+(Ei[2][m]+1)+", "+(Ei[3][m]+1)+", "+(Ei[4][m]+1)+"\n"); 27 } 28 } 29 int numPrisms = model.mesh("mesh1").getNumElem("prism"); 30 if (numPrisms > 0) { 31 Ei = model.mesh("mesh1").getElem("prism"); 32 for (int m = 0; m < numPrisms; m++) { 32 FileB.append("PRISM, "+(m+1+numTets+numPyrs)+", "+(Ei[0][m]+1)+", "+(Ei[1][m]+1)+", "+(Ei[2][m]+1)+", "+(Ei[3][m]+1)+", "+(Ei[4][m]+1)+", "+(Ei[5][m]+1)+"\n"); 34 } 35 } 36 int numHexes = model.mesh("mesh1").getNumElem("hex"); 37 if (numHexes > 0) { 38 Ei = model.mesh("mesh1").getElem("hex"); 39 for (int m = 0; m < numHexes; m++) { 40 FileB.append("HEX, "+(m+1+numTets+numPyrs+numPrisms)+", "+(Ei[0][m]+1)+", "+(Ei[1][m]+1)+", "+(Ei[2][m]+1)+", "+(Ei[3][m]+1)+", "+(Ei[4][m]+1)+", "+(Ei[5][m]+1)+", "+(Ei[6][m]+1)+", "+(Ei[7][m]+1)+"\n"); 41 } 42 } 43 writeFile("user:///output.txt", FileB.toString()); 44 message("Data written to file output.txt in the user directory."); 45 message(s_Vtx[0].length+" Nodes\n"+numTets+" Tetrahedral Elements\n"+numPyrs+" Pyramid Elements\n"+numPrisms+" Prismatic Elements\n"+numHexes+" Hexahedral Elements\n");
このメソッドを1行ずつ見ていきましょう.
- ファイルに書き込むデータを格納する文字列バッファを作成します.
- モデルからすべてのメッシュ頂点の位置を抽出し, そのデータを2次元の double 配列に格納します.
- メッシュ位置の数値データはテキストファイルに書き込まれるため, 文字列データに変換します.
- すべてのノード位置を反復処理する for ループを開始します.
- 各ノードの行を文字列バッファに追加し, ノードのインデックスと xyz 位置を指定します.
- ノードの for ループを閉じます.
- 以前に抽出したノードポイントの位置にあるデータを抽出するための補間機能を設定します.
- これらのノードポイントで評価する式を設定します. この場合, 変数 “T” は温度を抽出することを意味します.
- 補間機能を使用して, すべての温度データを抽出します. これは3次元の double 配列に格納されます.
- 不要になった補間機能を削除します.
- 抽出したすべてのデータに対して for ループを設定します. 抽出するフィールドは1つだけ (温度) で, モデルには解セットが1つしか存在しないと想定しているため, 配列の最後の次元のインデックスを指定するだけで済みます.
- 節点番号とその節点における温度の値を含むデータ行を文字列バッファに追加します.
- すべての出力データに対する for ループを閉じます.
- 要素インデックスデータを格納する空の2次元配列を初期化します.
- モデルから四面体要素の数を抽出します.
- 書き出す四面体要素があるかどうかを確認します.
- モデルから四面体要素の接続データを抽出します.
- すべての四面体要素に対して for ループを設定します.
- 各四面体要素ごとに, 要素番号と節点番号を含む行を文字列バッファに追加します.
- すべての四面体要素に対するループを閉じます.
- 四面体要素があるかどうかを確認する if 文を閉じます.
22行目から42行目は, 他の要素タイプについて15行目から21行目の機能を単純に繰り返します. 要素番号は, 以前のすべての要素番号に基づいて増分されることに注意してください. また, このメソッド全体を通して, すべての節点のインデックスが 1 ずつ増加します. これは, COMSOL Multiphysics が内部的にすべてのインデックスを 0 から開始しますが, 目的の出力形式では, すべての節点と要素のインデックスを 1 から開始するためです. 文字列バッファ全体が文字列に変換され, 43行目でファイルに書き込まれます. 44行目と45行目では, いくつかの情報がメッセージログに出力されます.
書き出されるファイルは output.txt という名前で, ユーザーディレクトリに保存されます. ディスク上のディレクトリの場所は, ソフトウェアの環境設定で指定できます. ファイルメニュー > 環境設定 > ファイル > アプリケーションファイル を選択すると, 以下のスクリーンショットのようにディレクトリを変更できます. 必要に応じてディレクトリを変更できます.

出力ファイルの場所は, ソフトウェアの環境設定で指定できます.
これで手順は完了です. 以下のスクリーンショットでは, アプリケーションの動作を確認できます.

アプリケーションは, ファイルに書き込まれた内容を報告します.
アプリケーションビルダーを使用したデータエクスポートに関するまとめ
COMSOL Multiphysics の定常熱シミュレーションからメッシュと結果を書き出す, 非常にシンプルなアプリの作成方法を説明しました. アプリからデータをコピーして, テキストファイルまたはスプレッドシートに貼り付けるだけです. もちろん, このアプリには, 以下のような, より高度な機能を組み込むことができます:
- 異なる荷重ケースや, 過渡シミュレーションからの異なる時間を表す可能性のある複数のデータセットを書き出す.
- データを固定形式のファイル形式にフォーマットする.
- 高次要素タイプと補間スキームを書き出す.
- ベクトルデータ, つまり要素間で不連続なデータを書き出す.
もちろん, ここでこれらすべてのケースについて説明するわけではありませんが, 独自のカスタマイズアプリにこのような変更を加えることにご興味がある場合は, 以下のリソースをご覧ください:
- Introduction to Application Builder をダウンロードする
- アプリケーションビルダーおよび COMSOL Server™ の基本 を学習するためのビデオを見る
- シミュレーションアプリが様々なアプリケーションでどのように使用されているか については, ブログをご覧ください
特定の種類のアプリの構築方法について詳しく知りたい場合や, モデリングに関するその他のご質問がある場合は, お問い合わせ ください.

コメント (0)