The highlighted comment was edited in this revision. [diff]
I did a little research on combining cfMesh, Salome and OpenFoam to create completely free and Open-source parametric CFD simulation. So I want to share my experiences and maybe somebody can give me some advice to correct me or use part of what I did. I tried to create parametric Ahmed body simulations and I had some success, so I created a little tutorial. I will explain how to create parametric geometries with Salome and meshes with cfMesh. All files explained in these thread can be downloaded from tutorials page: Parametric Ahmed body.
To couple Salome and cfMesh with Foam use scripts page: Foam's little helpers
Salome geometry[edit]
First goal is to create completely automatic and parametric geometries. For that I used Salome and it's python scripting. For rest I used Bash scripting.
- Create working directory (eg. ahmed) and inside it create directory named FoamSetup. In that directory place all OpenFoam case needed files and directories ("0", "constant" and "system" directories; all files in them controlDict, fvSolution, meshDict, RASProperties, p, U, ...).
- Create python script template in Salome using GUI.
- Run Salome and create geometries you need for simulation. Key is to GET SURFACES. VOLUMES ARE NOT NEEDED BUT YOU CAN USE THEM.
- With volumes is easier to work with so use them to create flow domain
- DO NOT DELETE AND REDO PARTS OF GEOMETRIES because numbering of faces will be wrong when python script is runned over and over. You will get bad geometries after.
- Create groups of faces in a way you want to have patches in OpenFoam (Inlet, Outlet, ...).
- Dump study to create python script.
- Edit created python script
- Here is presented python script for creating Ahmed bodies with different slant angles. All edited parts (from originally dumped script) are commented:
### This file is generated automatically by SALOME v7.4.0 with dump python functionality import sys import salome salome.salome_init() theStudy = salome.myStudy import salome_notebook ### ### GEOM component ### import GEOM from salome.geom import geomBuilder # for solving math problems import math import SALOMEDS # library for checking and creating folders import os.path # library for getting script path import inspect # get python script location/path path = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe()))) geompy = geomBuilder.New(theStudy) O = geompy.MakeVertex(0, 0, 0) OX = geompy.MakeVectorDXDYDZ(1, 0, 0) OY = geompy.MakeVectorDXDYDZ(0, 1, 0) OZ = geompy.MakeVectorDXDYDZ(0, 0, 1) O_1 = geompy.MakeVertex(0, 0, 0) OX_1 = geompy.MakeVectorDXDYDZ(1, 0, 0) OY_1 = geompy.MakeVectorDXDYDZ(0, 1, 0) OZ_1 = geompy.MakeVectorDXDYDZ(0, 0, 1) Box_1 = geompy.MakeBoxDXDYDZ(9000, 4000, 2000) geompy.TranslateDXDYDZ(Box_1, -2000, -2000, 0) listSubShapeIDs = geompy.SubShapeAllIDs(Box_1, geompy.ShapeType["FACE"]) listSubShapeIDs = geompy.SubShapeAllIDs(Box_1, geompy.ShapeType["FACE"]) listSubShapeIDs = geompy.SubShapeAllIDs(Box_1, geompy.ShapeType["FACE"]) listSubShapeIDs = geompy.SubShapeAllIDs(Box_1, geompy.ShapeType["FACE"]) Inlet = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) geompy.UnionIDs(Inlet, [3]) Outlet = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) geompy.UnionIDs(Outlet, [13]) Bottom = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) geompy.UnionIDs(Bottom, [31]) Slip = geompy.CreateGroup(Box_1, geompy.ShapeType["FACE"]) geompy.UnionIDs(Slip, [23, 27, 33]) Box_2 = geompy.MakeBoxDXDYDZ(1044, 389, 288) geompy.TranslateDXDYDZ(Box_2, 0, -194.5, 50) Fillet_1 = geompy.MakeFillet(Box_2, 100, geompy.ShapeType["EDGE"], [5, 8, 10, 12]) # Instead of pure dimensions put variable that is going to be changed/parametrized. In this case it is "Slant_angle". # Dimensions needed for chamfer are 2 lengths or angle in radians and length. # Here I have angle and length and I replaced them with equations with one unknown – "Slant_angle". Chamfer_1 = geompy.MakeChamferEdgeAD(Fillet_1, math.cos(Slant_angle*(math.pi/180))*222, Slant_angle*(math.pi/180), 46, 54) # Get Id's of all faces that make ahmed body; in this case ahmed body is called "Chamfer_1" (Salomes automated naming could change faces numbers) Ids = geompy.SubShapeAllIDs(Chamfer_1,geompy.ShapeType["FACE"]) Ahmed = geompy.CreateGroup(Chamfer_1, geompy.ShapeType["FACE"]) # Create group Ahmed from collected faces above geompy.UnionIDs(Ahmed, Ids) geompy.addToStudy( O, 'O' ) geompy.addToStudy( OX, 'OX' ) geompy.addToStudy( OY, 'OY' ) geompy.addToStudy( OZ, 'OZ' ) geompy.addToStudy( O_1, 'O' ) geompy.addToStudy( OX_1, 'OX' ) geompy.addToStudy( OY_1, 'OY' ) geompy.addToStudy( OZ_1, 'OZ' ) geompy.addToStudy( Box_1, 'Box_1' ) geompy.addToStudyInFather( Box_1, Inlet, 'Inlet' ) geompy.addToStudyInFather( Box_1, Outlet, 'Outlet' ) geompy.addToStudyInFather( Box_1, Bottom, 'Bottom' ) geompy.addToStudyInFather( Box_1, Slip, 'Slip' ) geompy.addToStudy( Box_2, 'Box_2' ) geompy.addToStudy( Fillet_1, 'Fillet_1' ) geompy.addToStudy( Chamfer_1, 'Chamfer_1' ) geompy.addToStudyInFather( Chamfer_1, Ahmed, 'Ahmed' ) if salome.sg.hasDesktop(): salome.sg.updateObjBrowser(1) # Export the geometries as .stl files to folder defined in variable "path" at beginning geompy.Export(Ahmed, "%s/Ahmed.stl" % path, "STL_ASCII") geompy.Export(Bottom, "%s/Bottom.stl" % path, "STL_ASCII") geompy.Export(Inlet, "%s/Inlet.stl" % path, "STL_ASCII") geompy.Export(Outlet, "%s/Outlet.stl" % path, "STL_ASCII") geompy.Export(Slip, "%s/Slip.stl" % path, "STL_ASCII")