OpenFOAMのpolyMesh周りの仕様
雑にデータとコード見てわかったことを書いておく。正確性は保証しない。
用語説明
Cell
Control Volumeのこと.Faceから構成されるがメッシュファイル自体ではIDとしてのみ扱われる.
Face
面(Surface)のこと.Pointから構成され,その情報は constant/polyMesh/faces に出力される.
Point
点のこと.座標の情報を持ち, constant/polyMesh/points に出力される.
neighbourとowner
あるFaceを持つCellのこと.境界以外のFaceは必ず2つのCellの構成要素となるため,CellのIDの小さい方をowner cell, 大きい方をneighbour cellと呼称している(neighbourはイギリス英語).境界のFaceはowner cellのみを持つと扱われている.各faceのowner cellのリストは constant/polyMesh/owner に,neighbour cellのリストは constant/polyMesh/neighbour に出力される.別々に出力する仕様上,FaceはまずinternalなFaceがIDの若い方を埋めていき,境界のFaceは後ろに固まっている.
OpenFOAMのデータ型とその表現
基本的なデータ型によってシリアライズ方式が決まっているため,これらを参考にして実装する必要がある.
Label
0以上の整数を表すデータ型.主にCellやFace, PointのIDとして利用する.binaryでの表現はメッシュファイルのheaderの FoamFile.arch の記述によるが,大半の場合Little Endianの32bitの符号なし整数である.
Scalar
実数を表すデータ型.主にスカラーの物理量を表すのに利用する.binaryでの表現はメッシュファイルのheaderの FoamFile.arch の記述によるが,大半の場合Little Endianの64bitの倍精度浮動小数点型である.
Vector
ベクトルを表すデータ型.主に座標や物理量を表すのに利用する.内部的には Scalar の固定長の配列として扱われるが,二次元の場合と三次元の場合で当然違うで注意.
ascii
() で囲い,delimiterとしてspaceを利用する.
code:vector
(4 10 1.234e-5)
binary
delimiterは用いず,そのまま続けてシリアライズする.ベクトルの各要素の表現は Scalar と同じである.
List<T>
任意長の配列を表すデータ型.IDの列の labelList や 物理量の列の scalarField などとして利用する.
ascii
先頭に要素数,続けて () で囲んだデータの列をspaceあるいは改行をdelimiterとして記述する.
複数のspaceや改行も合法な可能性もあるが,未検証(そのようなメッシュファイルが出力されたことがないため)
code:listt_ascii
// labelListの例
4(1 2 3 4)
// delimiterとして改行を用いても良い
4
(
1
2
3
4
)
// 空の場合
0()
binary
asciiと同様で, () の中身のみbyte列になる.
code: listt_binary
// labelListの例
4(^@^@^@^@^D^@^@^@^H^@^@^@^L^@^@^@^P^@^@^@)
// 先頭の要素数と(の間は改行しても良い
4
(^@^@^@^@^D^@^@^@^H^@^@^@^L^@^@^@^P^@^@^@)
Field<T>
任意長の配列を表すデータ型.Dictionary内に現れる事が多い.出力にデータ型の情報も含んでいる.OpenFOAMの内部のField classに相当し,Listとの違いは算術演算が定義されているか否かである.
ほとんどListと一緒だが,先頭に List<T> というデータ型の情報が付与される.
code: fieldt
// ascii
List<Label> 4
(
1
2
3
4
);
// binary
List<Label> 4 (^@^@^@^@^D^@^@^@^H^@^@^@^L^@^@^@^P^@^@^@);
scalarField
List<Scalar> のこと.pointwiseなのか,facewiseなのか,cellwiseなのかで名称が変わる.
scalarField: pointwiseなScalarの列.要素数はPointの数と一致する
surfaceScalarField: facewiseなScalarの列. 要素数はFaceの数と一致する
volScalarField: cellwiseなScalarの列.要素数はCellの数と一致する
vectorField
List<Vector> のこと.pointwiseなのか,facewiseなのか,cellwiseなのかで名称が変わる.
vectorField: pointwiseなScalarの列.要素数はPointの数と一致する
surfaceVectorField: facewiseなScalarの列. 要素数はFaceの数と一致する
volVectorField: cellwiseなScalarの列.要素数はCellの数と一致する
Dictionary
いわゆる辞書型.フィールド名と値からなる.各fieldは ; で終わる必要がある.
code:dictionary
subDict
{
filedname1 value;
subDict2
{
fieldname2 value2;
}
}
上記の例で, subDict , subDict2 も任意の文字列が利用できる.例えば,メッシュファイルのheaderの FoamFile は以下のようなDictionaryである.
code: foamFile
FoamFile
{
version 2.0;
format ascii;
arch "LSB;label=32;scalar=64";
class faceList;
location "constant/polyMesh";
object faces;
}
自由度が高いため,パースは困難かもしれない.
regIOobject
OpenFOAMの内部表現をそのまま出力する際のデータ型.内部表現そのままなので仕様という仕様はなさそうである. cellZones や faceZones の出力がこれである.
メッシュファイルの構成
基本的にOpenFOAMのメッシュ関連の基礎的なデータは constant/polyMesh ディレクトリ以下に配置されている.一般的に以下のようなファイルが配置されている.
code:bash
├── boundary
├── cellZones
├── faceZones
├── faces
├── neighbour
├── owner
├── pointZones
└── points
メッシュファイル全般
コメント
メッシュファイルでは C++と同様に, /* ... */ による複数行のコメントや // のpinlineコメントが利用できる.OpenFOAMの体外の出力にはこれらによるOpenFOAM versionの記述などが存在する.
ファイル構成
メッシュファイルは Header部とBody部からなる.Body部はデータのasciiあるいはbinaryの表現がそのまま出力されている.Header部は FoamFile から始まるDictionaryでフォーマットの情報などが記載されている.以下はその例である.
code: foamFile
FoamFile
{
version 2.0;
format ascii;
arch "LSB;label=32;scalar=64";
class faceList;
location "constant/polyMesh";
object faces;
}
version: フォーマットのversion
format: このファイルの出力形式.ascii or binaryである.
arch: 主に機種依存のデータ表現に関する情報.上記の例では label 型が32bit, scalar 型64bitであることを示している.
class: body部のデータの型を表す.OpenFOAM内のC++のclassと対応する.
location: 出力ファイルが配置されているディレクトリの場所.OpenFOAMファイルのベースディレクトリからの相対パスで表す.
object: 出力データの名前.ファイル名と一致する.
その他にも, note や meta などのsub dictionaryがフィールドに含まれることがある.
boundary
メッシュの境界条件について記載されている.binary出力でも変わらずasciiで出力される.
データ型(class)は polyBoundaryMesh でその実態はDictionaryのListである.
詳細について後日記述.フォーマットは以下の通りである.
code: boundary
n // 境界条件の数
(
<boundary-name> // 境界の名前
{
type <boundary-type>; // 境界条件の種類.OpenFOAMの仕様に準拠
nFaces m; // この境界条件が適用されるfaceの数
startFace l; // この境界条件が適用されるfaceのIDの先頭.ここからl+m-1まで適用される
}
...
)
以下は具体例.
code: boundary_example
4
(
inlet
{
type patch;
nFaces 280;
startFace 36612;
}
outlet
{
type patch;
nFaces 280;
startFace 36892;
}
ground
{
type wall;
inGroups 1(wall);
nFaces 1288;
startFace 37172;
}
frontAndBack
{
type symmetry;
inGroups 1(symmetry);
nFaces 2208;
startFace 38460;
}
)
typeのpatchやwall, symmetryはOpenFOAMの境界条件の種類である.
cellZones
Cellの集合にラベルをつけたものについて記載されている.データ型(class)は regIOobject でその実態はDictionaryのListである.フォーマットは以下のようになっている.
code:cellZones
n // cellZoneの数
( <CellZoneの名前>
{
type cellZone; // cellZoneであることを宣言
cellLabels <Field型の値>; // cellZoneを構成するCellのIDのリスト(Field型)
}
...
)
cellLabelsの値が Field<Label> 型で有ることに注意.
code:cellLabels_example
1
(inletChannel
{
type cellZone;
cellLabels List<label>
5
(
0
1
2
3
4
);
}
)
binaryの場合,cellLabelsの値が Field<Label> のbinary表現になるなるだけである.
code: cellLabels_example_binary
1
(inletChannel
{
type cellZone;
cellLabels List<label>
5
(^@^@^@^@^A^@^@^@^B^@^@^@^C^@^@^@^D);
}
)
faceZones
Faceの集合にラベルをつけたものについて記載されている.データ型(class)は regIOobject でその実態はDictionaryのListである.フォーマットに関してはcellZonesと同様で, type が faceZone に, cellLabels が faceLabels になるだけである.
code:faceZones
1
(inletChannel
{
type faceZone;
faceLabels List<label>
5
(
0
1
2
3
4
);
}
)
pointZones
Pointの集合にラベルをつけたものについて記載されている.データ型(class)は regIOobject でその実態はDictionaryのListである.
フォーマットに関してはcellZonesと同様で, type が pointZone に, cellLabels がpointLabels になるだけである.
code:pointZones
1
(inletChannel
{
type pointZone;
pointLabels List<label>
5
(
0
1
2
3
4
);
}
)
faces
faceを構成する点の情報について記載されている.
asciiの場合
データ型(class)は faceList であり,その実態は List<List<Label>> である.
code:faces_ascii
8
(
4(8 13 30 25)
4(24 25 30 29)
4(7 24 29 12)
4(12 29 30 13)
4(7 8 25 24)
4(9 14 31 26)
4(25 26 31 30)
4(13 30 31 14)
)
binaryの場合
データ型(class)は faceCompactList であり,その実態はindexの列である List<Label> とPointのIDの列である List<Label> をそのまま出力したのもである.Listの中身がbinaryになっている.
binary部分をasciiにした場合以下のような構成になっている
code:faces_binary
8
(
4 8 12 16 20 24 28 32
)
32
(
8 13 30 25 24 25 30 29 7 24 29 12 12 29 30 13 7 8 25 24 9 14 31 26 25 26 31 30 13 30 31 14
)
最初のList(上の例で8要素のもの)は次のList(上の例で32要素のもの)の最後の位置を示している.
この場合下記のようにsplitして List<Label> を List<List<Label>> へとデシリアライズする.
code:deserialise
(
8 13 30 25 | 24 25 30 29 | 7 24 29 12 | 12 29 30 13 | 7 8 25 24 | 9 14 31 26 25 26 31 30 13 30 31 14
) | | | | |
4 8 12 16 20 ...
owner
各faceのower cellのIDが記載されている.データ型(class)は labelList (List<Label> )である.
code:owner
6
(
0
0
0
0
0
1
)
neighbour
各Faceのneighbour cellのIDが記載されている.データ型(class)は labelList (List<Label> )である.仕様上境界のfaceはneighbour cellを持たないため,neighbourの要素数はownerの要素数以下である.
code:neihbour
4
(
1
4
65
75
)
points
各Pointの座標が記載されている.データ型(class)は vectorField (List<Vector>) である.
code:points
8
(
(220 170 0)
(230 170 0)
(240 170 0)
(250 170 0)
(260 170 0)
(270 170 0)
(280 170 0)
(290 170 0)
)