こんにちは(@t_kun_kamakiri)
本記事ではSALOMEを用いたヘキサメッシュの手順について解説します。
本記事では、半導体のウェーハ洗浄工程で用いられる回転ディスク形状を対象に、オープンソースのプリ・ポストツールである SALOME を用いたヘキサメッシュ(六面体メッシュ)の作成手順を解説します。
半導体のウェーハ洗浄工程で用いられる回転ディスク形状をヘキサメッシュで作成する
曲面を含む回転体系モデルに対して、どのようにブロックを分割し、構造格子として整ったメッシュを構築するのかに焦点を当てます。
なお、本記事では OpenFOAMなどの解析ソフトでの設定や計算条件は適当であるため解の検証は十分に行っていないことをご了承ください。
- OpenFOAM v2412
- salome 9.15.0
計算の対象
半導体製造プロセスの中でも、半導体のウェーハ洗浄工程は、デバイス性能や製造歩留まりを左右する重要な工程のひとつです。特に、回転するディスク上にウェーハを載せ、液滴を滴下しながら遠心力によって不純物や微粒子を除去するスピン洗浄方式は、高精度な表面洗浄技術として広く用いられています。このような洗浄プロセスを数値的に理解・検討するためには、まず解析対象となる装置や流路形状に対して、適切なメッシュを作成することが不可欠です。

SALOMEのインストール
salomeのダウンロードはこちらから行います。
zipファイルでダウンロードして適当なフォルダで解凍すると使用することができます。
解凍が済んだらrun_salome.batをダブルクリックするとsalomeが起動します。

作成するモデル
今回はSALOMEを使ったヘキサメッシュなので以下のようなテストモデルを作成することとします。

なおフルモデルだと計算コストがかかるので1/4モデルにします。
また、底面は薄膜の再現性を気にするため64μmの厚みの中に8層くらいメッシュを入れるようにします。
SALOMEで形状作成
Shaperでスケッチを描いていきます。
まずはX-Z平面上にすべて四角形になるように線を描きます。

次にX-Y平面上にスケッチをします。
先ほど作成したスケッチより外側の円は大きめに作っておくと良いです。

作成したスケッチをもとにShellを作成します。

あとはShellを回転させたり、押し出したりしてソリッドにします。
以下のようにパーティションで区切るとソリッドに線が入ります。

線のグループ化
続いてメッシュの分割数をそろえるために線をグループ化していきます。


向かい合った線の分割数が同じでないとヘキサメッシュにできないので、重要な作業です。
メッシュ作成
Meshに移ってメッシュ作成を行います。
まずはデフォルトでヘキサメッシュを作成してみます。

メッシュを確認するとヘキサメッシュにできていることがわかります。

あとはSub-meshで各線の分割数を微調整していきます。
線上で分割幅を変える場合は、矢印の向きが逆だと始点と終点がおかしくなってしまうため、線上の矢印の向きに注意が必要です。
以下のように適宜修正します。

各線の分割数を微調整出来たら再度メッシュ作成します。
今回は以下のようにメッシュができました。

境界面に名前を付ける
OpenFOAMでは名前が付けられた面に境界条件を設定する必要があります。
Geometoryに戻って以下のように面に名前を付けていきます。

漏れなくすべての面に名前を付け終わったら、再度Meshに移ってメッシュに境界のgeometoryを割り当てます。

OpenFOAMの形式に変換
SALOMEで問題なくメッシュ作成と境界の設定が終わったらOpenFOAMの形式に変換します。
以下のようにunvファイルとして出力します。

出力したunvファイルをOpenFOAM形式に変換するにはダミーのケースファイルが必要です。適当なチュートリアルからコピーしてきます。
今回は気液混相流の計算を想定しているのでinterFoamからコピーしてきます。
|
1 2 |
cp -r /home/kamakiri/repo/openfoam/tutorials/multiphase/interFoam/RAS/damBreak/damBreak 004_run_salome cd 004_run_salome |
$FOAM_TUTORIALS = /home/kamakiri/repo/openfoam/tutorials
salomeで作成したunvファイルをケースファイルに保存します。
|
1 |
cp -r ../../../salome/20260104_thin_001/Mesh_1.unv . |
フォルダ構成としては以下のようになっています。

以下のコマンドでOpenFOAMの形式に変換します。
|
1 |
ideasUnvToFoam Mesh_1.unv |
エラーがなければconstant/polyMeshフォルダが作成されOpenFOAMのメッシュ情報が作られています。
ParaViewで確認するために拡張子.foamの空ファイルを作成して読み込みます。

念のためモデルの大きさを確認しておきましょう。

salomeではmm単位のつもりで作成しましたが、実は数値しか意味がなく、OpenFOAMでの計算がm単位なので、半径150mのモデルになっていました。
以下のコマンドでスケールを1/1000倍にします。
|
1 |
transformPoints -scale '(0.001 0.001 0.001)' |
再度、モデルの大きさを確認します。

これでOKですね。
OpenFOAMの設定
ここからはOpenFOAM設定に移ります。
メッシュのタイプの変更
cyclic1とcyclic2は対称面なのでcyclicAMIに変更します。
また、bottomは底面を回転境界条件にするためwallにします。
constant/polyMesh/boundary
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
7 ( inlet { type patch; nFaces 1000; startFace 326670; } top { type patch; nFaces 3200; startFace 327670; } side { type patch; nFaces 920; startFace 330870; } inletWall { type patch; nFaces 600; startFace 331790; } cyclic1 { type cyclicAMI; inGroups 1(cyclicAMI); nFaces 3170; startFace 332390; transform rotational; neighbourPatch cyclic2; rotationAxis (0 0 1); rotationCentre (0 0 0); AMIMethod faceAreaWeightAMI; restartUncoveredSourceFace 1; } cyclic2 { type cyclicAMI; inGroups 1(cyclicAMI); nFaces 3170; startFace 335560; transform rotational; neighbourPatch cyclic1; rotationAxis (0 0 1); rotationCentre (0 0 0); AMIMethod faceAreaWeightAMI; restartUncoveredSourceFace 1; } bottom { type wall; nFaces 4200; startFace 338730; } ) |
乱流モデル
今回は乱流モデルは使用しませんのでlaminarにします。
constant/turbulenceProperties
|
1 2 3 4 5 6 7 8 9 10 11 12 |
simulationType laminar;//RAS; //density variable; RAS { RASModel kEpsilon; turbulence on; printCoeffs on; } |
物性値
物性は水と空気にしておきます。
constant/transportProperties
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
phases (water air); water { transportModel Newtonian; nu 1e-06; rho 1000; } air { transportModel Newtonian; nu 1.48e-05; rho 1; } sigma 0.07; |
境界条件
続いて境界条件の設定です。
底面を回転境界条件にします。
0/U
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
dimensions [0 1 -1 0 0 0 0]; internalField uniform (0.0 0.0 0.0); boundaryField { top { // type fixedValue; // value uniform (0 0 0); type pressureInletOutletVelocity; value uniform (0 0 0); // type noSlip; } bottom { type rotatingWallVelocity; origin (0 0 0); axis (0 0 1); omega 314.1592653589793;//[rad/s] } side { type pressureInletOutletVelocity; value uniform (0 0 0); // type noSlip; } inletWall { type fixedValue; value uniform (0 0 0); } inlet { type flowRateInletVelocity; volumetricFlowRate constant 0.0000016;//1e-05; //[m3/s] } "(cyclic1|cyclic2)" { type cyclicAMI; value $internalField; } } |
0/p_rgh
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
dimensions [1 -1 -2 0 0 0 0]; internalField uniform 101325; boundaryField { top { type totalPressure; p0 uniform 101325.0; value uniform 101325.0; /* type fixedFluxPressure; value uniform 101325; */ } bottom { type fixedFluxPressure; value uniform 101325; } side { type totalPressure; p0 uniform 101325.0; value uniform 101325.0; /* type fixedFluxPressure; value uniform 101325; */ } inletWall { type fixedFluxPressure; value uniform 101325; } inlet { type fixedFluxPressure; value uniform 101325; } "(cyclic1|cyclic2)" { type cyclicAMI; value $internalField; } } |
0/alpha.water
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
dimensions [0 0 0 0 0 0 0]; internalField uniform 0; boundaryField { top { /* type inletOutlet; inletValue uniform 1; value uniform 1; */ type inletOutlet; inletValue uniform 0; value uniform 0; } bottom { type zeroGradient; } side { type inletOutlet; inletValue uniform 0; value uniform 0; //type zeroGradient; } inletWall { type zeroGradient; } inlet { type fixedValue; value uniform 1; } "(cyclic1|cyclic2)" { type cyclicAMI; value $internalField; } } |
計算の制御
system/controlDict
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
application interFoam; startFrom latestTime;//startTime; startTime 0; stopAt endTime; endTime 1; deltaT 0.001; writeControl adjustable; writeInterval 0.05; purgeWrite 0; writeFormat ascii; writePrecision 6; writeCompression off; timeFormat general; timePrecision 6; runTimeModifiable yes; adjustTimeStep yes;//on;//off;//on; maxCo 10; maxAlphaCo 10; maxDeltaT 10; functions { continuityError1 { type continuityError; libs ( fieldFunctionObjects ); // Mandatory entries (unmodifiable)// Optional entries (runtime modifiable) phi phi; // Optional (inherited) entries writePrecision 8; writeToFile yes; useUserTime yes; region region0; enabled yes; log yes; timeStart 0; timeEnd 6000; executeControl timeStep; executeInterval 1; writeControl timeStep; writeInterval 50; } residuals { type solverInfo; libs ( "libutilityFunctionObjects.so" ); fields ( ".*" ); } fieldMinMax1 { type fieldMinMax; libs (fieldFunctionObjects ); // Mandatory entries (unmodifiable)// Mandatory entries (runtime modifiable) mode magnitude; fields ( U p ); // Optional entries (runtime modifiable) location yes; writePrecision 8; writeToFile yes; useUserTime yes; region region0; enabled yes; log yes; timeStart 0; timeEnd 8000; executeControl timeStep; executeInterval 1; writeControl timeStep; writeInterval 1; } } |
最大のクーラン数は発散しない程度に大きめにしておきます。
結果
結果は以下のようになりました。

こういうのを期待したのですが適当に設定したので解析条件の見直しが必要ですね。
ただひな形としては良しとしましょう。
まとめ
本記事では、SALOME を用いたヘキサメッシュ(六面体メッシュ)の作成手順について、半導体ウェーハ洗浄工程で用いられる回転ディスク形状を題材に解説しました。
特に、曲面を含む回転対称モデルに対して、いかにブロックを分割し、構造格子として破綻のないヘキサメッシュを構築するかに焦点を当てています。
SALOME はオープンソースでありながら、
- Shaper による柔軟な形状作成
- パーティションを用いたブロック分割
- エッジ分割数を揃えた構造格子生成
といった作業を GUI ベースで直感的に行える点が大きな強みです。
一方で、向かい合うエッジの分割数管理や、Sub-mesh 設定など、ヘキサメッシュ特有の注意点も多く、手順を理解していないと失敗しやすい部分でもあります。
また、本記事では SALOME で作成したメッシュを OpenFOAM(v2412)へ変換し、
- cyclicAMI を用いた回転対称境界
- rotatingWallVelocity による回転ディスクの再現
- interFoam を用いた気液二相流計算
まで一連の流れを示しました。
これにより、SALOME → OpenFOAM の実践的なワークフローを具体的にイメージできる構成になっています。
回転体系・薄膜・遠心力を伴う流れは、半導体洗浄プロセスに限らず、
ディスク流れ、スピンコーティング、回転容器内流動など、さまざまな工学分野で共通する重要テーマです。
その第一歩として、高品質なヘキサメッシュを安定して作成できることは、解析精度以前に不可欠なスキルと言えます。
SALOME を用いた構造格子生成に挑戦したい方、
blockMesh 以外の方法で 複雑形状 × ヘキサメッシュを扱いたい方にとって、
本記事が具体的な参考例になれば幸いです。



