3.6 メッシュ作成方法(細分化指定有り)の変更(DEXCS化)2
前節までで、細分化用のオプションセットのないメッシュについてはDEXCS方式で作成できるようになった。メッシュ細分化コンテナにおいて将来的には、optimizeLayerオプションや、BoundaryLayerオプションなど追加したいが、それをやる前に、現行の細分化オプションセットだけを使って、DEXCS方式のメッシュ作成ができるようにしておきたい。本節ではその取り組みについて記すが、その際の前提というか、当面の目標について、現行のCfdOFの動作と対比して、どうしたいのかを具体的に掲げておく。
対象例題は、図14に示すように、前節で取り扱った例題に対して、regionという細分化指定領域を追加したモデルを使って実施する。
前節までの手順で作成したメッシュコンテナ(Fusion_Mesh)を選択すると、ツールバーのメッシュ細分化ツールボタンが有効になるので、これをクリックし、図15の手順にて、細分化パラメタを指定していくことになる。
問題は、ここで択するメニューにおいて、すべてのコンポーネントがリストアップされてしまう事と、設定が完了すると、設定したコンポーネントだけが表示状態で残り、他のコンポーネントがすべて非表示状態になってしまう点である(図16)。
したがって、当面の目標として、
- 細分化の対象オブジェクトリストとして、表示オブジェクトだけを対象にする
- 細分化設定をした後で、既存コンポーネントの表示状態を変更しない。
ようにしておいて、図17に示すように3種類の細分化設定を施したモデルに対して、DEXCS方式のメッシュ作成をする、すなわち前節での改変に加えて、細分化設定条件をこの細分化コンテナから取得して組み込むようにするものである。
なお、ここに述べた大きな問題以外にも、いくつか改善したい項目もあるが、当面の目標がクリアーできた時点で動作検証し、改めてリストアップする予定である。
また、メッシュ細分化ツールボタンを押した時に起動されるプログラムは、CfdMeshRefinement.py であり、この中で、細分化を指定する為のタスク画面は、
36: import _TaskPanelCfdRefinement
174: taskd = _TaskPanelCfdMeshRefinement._TaskPanelCfdMeshRefinement(self.Object)
として起動されるようになっている。この画面を今後変更していく事になるので、_TaskPanelCfdRefinement.pyをコピーして_dexcsTaskPanelCfdRefinement.py という名前に変更して、以下この内容を変更していく事にする。CfdMeshRefinement.py 本体は、以下変更するだけである。
36: import _dexcsTaskPanelCfdRefinement
174: taskd = _dexcsTaskPanelCfdMeshRefinement._TaskPanelCfdMeshRefinement(self.Object)
この _dexcsTaskPanelCfdRefinement.py の中で、CfdFaceSelectingWidget.py という細分化パーツを選択するツールを起動しており、この選択方法を変更していくので、これもコピーして、dexcsCfdFaceSelectingWidget.py という名前に変更し、この呼び出しに係る部分を、以下変更しておく。
33: import dexcsCfdFaceSelectWidget
51: self.faceSelector = dexcsCfdFaceSelectWidget.CfdFaceSelectWidget(self.form.referenceSelectWidget,
56: self.solidSelector = dexcsCfdFaceSelectWidget.CfdFaceSelectWidget(self.form.volReferenceSelectWidget,
先に掲げた問題
- 細分化の対象オブジェクトリストとして、表示オブジェクトだけを対象にする
- 細分化設定をした後で、既存コンポーネントの表示状態を変更しない。
については、この_dexcsTaskPanelCfdRefinement.pyの改変にて実現可能であった。つまり、前者の問題については、
108: for i in FreeCADGui.ActiveDocument.Document.Objects:
109: if "Shape" in i.PropertiesList:
110: # Do not restrict to solids
111: if not i.Name.startswith("CfdFluidBoundary"):
112: self.solidsNames.append(i.Name)
113: self.solidsLabels.append(i.Label)
となっていた部分を、以下に変更した。
108: for i in FreeCADGui.ActiveDocument.Document.Objects:
109: if i.ViewObject.Visibility:
111: if hasattr(i,"Proxy"):
112: pass
113: else:
114: self.solidsNames.append(i.Name)
115: self.solidsLabels.append(i.Label)
また、後者の表示状態が変更していたのは、
397: def closeFaceList(self):
398: self.form.stackedWidget.setCurrentIndex(0)
399: self.obj.ViewObject.show()
によるものであった為、399行目をコメントアウトすれば良かった。
以上で、外観上の問題はクリアーできたので、先に進むこととするが、前節において、DEXCSマクロ中の 2 つの関数( makeStlFile と makeMeshDict )を改変したが、これに加えて本節において追加したメッシュ細分化設定項目を反映できるようにしてやれば良さそうである。
(1) 領域細分化指定パーツを除外してSTLファイル作成
makeSrlFileに関しては、細分化領域指定に使用したパーツ(本例ではregion)を除外する必要がある。
そこで、dexcsCfdNeshTools.py の、def makeStlFile(…) において、STL作成対象とするパーツの選択を以下のように変更した。
outputStlFile = open(self.stlFileName, 'w')
# refinementRegion として指定(obj.Internal)されたパーツのLabelリストを作成
__region__=[]
doc = FreeCAD.activeDocument()
for obj in doc.Objects:
if obj.ViewObject.Visibility:
if hasattr(obj, "Proxy") and isinstance(obj.Proxy, _CfdMeshRefinement):
if obj.Internal :
for objList in(obj.LinkedObjects):
__region__.append(objList.Label)
for obj in doc.Objects:
if obj.ViewObject.Visibility:
__objs__=[]
try:
if obj.Shape:
# obj.Labelがregion指定パーツであるかどうか判定
checkRegion = False
for objRegion in __region__:
if obj.Label == objRegion :
print('pass ' + obj.Label)
checkRegion=True
# CfdSolver / Group Object / region指定Obj を除外
if obj.isDerivedFrom("Part::FeaturePython") or obj.isDerivedFrom("App::DocumentObjectGroupPython") or checkRegion:
pass
else:
print('append '+obj.Label)
__objs__.append(obj)
file=self.fileName+obj.Label+'.ast'
Mesh.export(__objs__,file)
importFile = open(file,'r')
temp = importFile.readlines()
for line in temp:
if 'endsolid' in line:
outputStlFile.write('endsolid ' + obj.Label + '\n')
elif 'solid' in line:
outputStlFile.write('solid ' + obj.Label + '\n')
else:
outputStlFile.write(line)
importFile.close
os.remove(file)
except AttributeError:
pass
outputStlFile.close
朱字部分で、regionの細分化指定対象パーツのリストを取得。青字部分で、対象パーツがこのリストに含まれるかどうか判別するものである。
なお、細分化指定用のパーツ(MeshRefinement…)のプロパティについては、CfdMeshRefinement.py 中、以下のように規定されているので、これを手懸りに設定値を取得できる。
def initProperties(self, obj):
# Common to all
addObjectProperty(obj, "RelativeLength", 0.75, "App::PropertyFloat", "",
"Set relative length of the elements for this region")
addObjectProperty(obj, 'LinkedObjects', [], "App::PropertyLinkList", "", "Linked objects")
addObjectProperty(obj, "References", [], "App::PropertyPythonObject", "",
"List of mesh refinement objects")
addObjectProperty(obj, "Internal", False, "App::PropertyBool", "",
"Whether the refinement region is a volume rather than surface")
#cfMesh:
addObjectProperty(obj, "RefinementThickness", "0 m", "App::PropertyLength", "cfMesh",
"Set refinement region thickness")
addObjectProperty(obj, "NumberLayers", 0, "App::PropertyInteger", "cfMesh",
"Set number of boundary layers")
addObjectProperty(obj, "ExpansionRatio", 1.2, "App::PropertyFloat", "cfMesh",
"Set expansion ratio within boundary layers")
addObjectProperty(obj, "FirstLayerHeight", "0 m", "App::PropertyLength", "cfMesh",
"Set the maximum first layer height")
# snappy:
addObjectProperty(obj, "RegionEdgeRefinement", 1, "App::PropertyFloat", "snappyHexMesh",
"Relative edge (feature) refinement")
(2) 領域細分化指定パラメタのmeshDictファイルへの反映
したがって、先に細分化指定したリージョンリスト(__region[]__)を取得したが、これに加えてそれぞれの細分化セルサイズ(RelativeLength)を取得して、以下のように細分化セルサイズリスト(__relativeLength__[])を作成することができる。
__region__=[]
__rerativeLength__[]
doc = FreeCAD.activeDocument()
for obj in doc.Objects:
if obj.ViewObject.Visibility:
if hasattr(obj, "Proxy") and isinstance(obj.Proxy, _CfdMeshRefinement):
if obj.Internal :
for objList in(obj.LinkedObjects):
__region__.append(objList.Label)
__relativeLength__.append(obj.RelativeLength)
オリジナルのDEXCSランチャーにおいて、細分化領域対象パーツを絞り込んでいた部分
while (self.viewControl.get_gridTableValue(iRow,0)):
for obj in self.doc.Objects:
if obj.Label == self.viewControl.get_gridTableValue(iRow,0):
iRow = iRow + 1
if self.viewControl.get_gridTableValue(iRow-1,1) == MainControl.REGION_STR:
を以下のように変更。
if __region__ :
regionNumber = 0
for objList in __region__ :
for obj in doc.Objects:
if obj.Label == objList :
そうすると、対象objの寸法を取得して、BounBox指定の部分は、ほとんどそのまま流用できることになる。ほとんどと記したのは、オリジナルのDEXCSランチャーにおいて、viewControl…としてマクロ画面から取得していたパラメタ部分はMeshRefinement…から取得した値に変更する必要があるという点である。具体的には、
strings7 = [
'\t' + str(self.viewControl.get_gridTableValue(iRow-1,0)) + '\n',
'\t{\n',
'\t\tadditionalRefinementLevels\t' + str(self.viewControl.get_gridTableValue(iRow-1,2)) + ';\n',
青字部分を、以下の赤字部分に変更した。
strings7 = [
'\t' + objList + '\n',
'\t{\n',
'\t\tadditionalRefinementLevels\t' + RefStr + ';\n',
ここに、RefStr(細分化レベル)は暫定的に、
RefStr = str(int( 1.0 / __relativeLength__[regionNumber])-1)
としておくが、この部分はRelativeLengthの指定方法を含めて、改変する予定である。
また、ここで、Box要素でないものを、Box要素相当のものとして設定しているのに対して、今後はBox要素のFreeCADパラメタを直接参照したり、円柱や球などプリミティブ要素を直接的に取り扱うこともできるようにしていく予定である。
(3) レイヤー指定パラメタのmeshDictファイルへの反映
細分化指定したリージョンリストを取得したのと同様に、レイヤー指定したパッチリスト(__patch__)とレイヤー数(__nLayer__)拡大比率(__expRatio__)レイヤー底層厚さ(__firstLayerHeight__)は、以下のようにして取得できる。
__patch__ = []
__nLayer__ = []
__expRatio__ = []
__firstLayerHeight__ = []
doc = FreeCAD.activeDocument()
for obj in doc.Objects:
if obj.ViewObject.Visibility:
if hasattr(obj, "Proxy") and isinstance(obj.Proxy, _CfdMeshRefinement):
if obj.NumberLayers > 1 :
for objList in(obj.LinkedObjects):
__patch__.append(objList.Label)
__nLayer__.append(obj.NumberLayers)
__expRatio__.append(obj.ExpansionRatio)
__firstLayerHeight__.append(obj.FirstLayerHeight)
レイヤー指定パッチの絞り込み部分
while (self.viewControl.get_gridTableValue(iRow,0)):
iRow = iRow + 1
if self.viewControl.get_gridTableValue(iRow-1,3) == 2:
を以下のように変更
if __patch__ :
patchNumber = 0
for objList in __patch__ :
for obj in doc.Objects:
if obj.Label == objList :
meshDictに書き込む部分は、以下の青字部分を、
strings3 = [
'\t\t' + str(self.viewControl.get_gridTableValue(iRow-1,0)) + '\n',
'\t\t{\n',
'\t\t\t// number of layers (optional)\n',
'\t\t\tnLayers ' + str(self.viewControl.get_gridTableValue(iRow-1,4)) + ';\n',
'\t\t\n',
'\t\t\t// thickness ratio (optional)\n',
'\t\t\tthicknessRatio ' + str(self.viewControl.get_gridTableValue(iRow-1,5)) + ';\n',
'\t\t\n',
'\t\t\t// max thickness of the first layer (optional)\n',
'\t\t\t// maxFirstLayerThickness ' + '0.5; // [m]\n',
以下、赤字に変更した。
strings3 = [
'\t\t' + objList + '\n',
'\t\t{\n',
'\t\t\t// number of layers (optional)\n',
'\t\t\tnLayers ' + str(__nLayer__[patchNumber]) + ';\n',
'\t\t\n',
'\t\t\t// thickness ratio (optional)\n',
'\t\t\tthicknessRatio ' + str(__expRatio__[patchNumber]) + ';\n',
'\t\t\n',
'\t\t\t// max thickness of the first layer (optional)\n',
'\t\t\tmaxFirstLayerThickness ' + str(__firstLayerHeight__[patchNumber]).replace('m','') + '; // [m]\n',
ここで、DEXCSオリジナルのマクロでは、最終行の maxFirstLayerThickness はコメントアウトして出力していたが、これにてパッチ毎の任意の指定が可能になった。
(4) パッチのセルサズ指定パラメタのmeshDictファイルへの反映
セルサイズ指定する部分もほとんど同じである。セルサイズを指定したパッチ名リスト(__patch__)と、相対サイズリスト(__relativeLength__)細分化厚さリスト(__refThickness__)を、以下取得。
__patch__ = []
__relativeLength__ = []
__refThickness__ = []
doc = FreeCAD.activeDocument()
for obj in doc.Objects:
if obj.ViewObject.Visibility:
if hasattr(obj, "Proxy") and isinstance(obj.Proxy, _CfdMeshRefinement):
if (not obj.Internal) and (obj.RelativeLength < 1) :
for objList in(obj.LinkedObjects):
__patch__.append(objList.Label)
__relativeLength__.append(obj.RelativeLength)
__refThickness__.append(obj.RefinementThickness)
セルサイズ指定パッチの絞り込み部分
while (self.viewControl.get_gridTableValue(iRow,0)):
iRow = iRow + 1
if (self.viewControl.get_gridTableValue(iRow-1,2) != Model.EMPTY_STR and
self.viewControl.get_gridTableValue(iRow-1,1) != MainControl.REGION_STR):
は、以下変更し、
if __patch__ :
patchNumber = 0
for objList in __patch__ :
for obj in doc.Objects:
if obj.Label == objList :
さらに、meshDictに書き込む部分は、以下のように暫定変更した。
RefStr = str(int( 1.0 / __relativeLength__[patchNumber])-1)
RefThickness = str(__refThickness__[patchNumber]).replace('m','')
RefThickness = str(float(RefThickness)/1000)
strings5 = [
'\t' + objList + '\n',
'\t{\n',
'\t\t// additional refinement levels\n',
'\t\t// to the maxCellSize\n',
'\t\t additionalRefinementLevels\t' + RefStr + ';\n',
'\t\n',
'\t\t// thickness of the refinement region;\n',
'\t\t// away from the patch;\n',
'\t\t refinementThickness\t' + RefThickness + ';\n',
'\t}\n'
]
patchNumber = patchNumber + 1
meshDict.writelines(strings5)
暫定変更というのは、DEXCSオリジナルでは細分化指定の方法を CellSize / RefLevel どちらでも出来るようにしてあったのが、現状のGUIでは設定できないので、RefLevelを使っているが、この値の指定方法もRelativeLengthの値から計算したものになっており、このあたりは今後見直していく予定であるので、暫定処置とした次第である。