-
Notifications
You must be signed in to change notification settings - Fork 41
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
CFD: initial commit seperated from Fem workbench
- Loading branch information
0 parents
commit c100a75
Showing
41 changed files
with
185,987 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
*.pyc | ||
FoamCaseBuilder/*.pyc | ||
FoamCaseBuilder/__pycache__ | ||
FoamCaseBuilder/PlyParse* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,43 @@ | ||
|
||
fc_copy_to_mod_path("Cfd" | ||
|
||
) | ||
|
||
INSTALL( | ||
FILES | ||
# changes on the file list here needs to be made in App/CMakeLists.txt as well | ||
Init.py | ||
InitGui.py | ||
# OpenFOAM solver related | ||
CfdAnalysis.py | ||
CfdSolver.py | ||
CfdSolverFoam.py | ||
CfdTools.py | ||
CfdCaseWriterFoam.py | ||
CfdRunnableFoam.py | ||
CfdResult.py | ||
|
||
TaskPanelCfdSolverControl.ui | ||
_TaskPanelCfdSolverControl.py | ||
_ViewProviderCfdSolverFoam.py | ||
TaskPanelCfdResult.ui | ||
_TaskPanelCfdResult.py | ||
_ViewProviderCfdResult.py | ||
|
||
_CommandCfdAnalysis.py | ||
_CommandCfdSolverFoam.py | ||
_CommandCfdSolverControl.py | ||
_CommandCfdResult.py | ||
|
||
FoamCaseBuilder/BasicBuilder.py | ||
FoamCaseBuilder/__init__.py | ||
FoamCaseBuilder/utility.py | ||
FoamCaseBuilder/ThermalBuilder.py | ||
FoamCaseBuilder/FoamTemplateString.py | ||
FoamCaseBuilder/TestBuilder.py | ||
FoamCaseBuilder/Readme.md | ||
FoamCaseBuilder/Roadmap.md | ||
|
||
DESTINATION | ||
Mod/Cfd | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
# *************************************************************************** | ||
# * * | ||
# * Copyright (c) 2013-2015 - Juergen Riegel <FreeCAD@juergen-riegel.net> * | ||
# * * | ||
# * This program is free software; you can redistribute it and/or modify * | ||
# * it under the terms of the GNU Lesser General Public License (LGPL) * | ||
# * as published by the Free Software Foundation; either version 2 of * | ||
# * the License, or (at your option) any later version. * | ||
# * for detail see the LICENCE text file. * | ||
# * * | ||
# * This program is distributed in the hope that it will be useful, * | ||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
# * GNU Library General Public License for more details. * | ||
# * * | ||
# * You should have received a copy of the GNU Library General Public * | ||
# * License along with this program; if not, write to the Free Software * | ||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | ||
# * USA * | ||
# * * | ||
# *************************************************************************** | ||
|
||
import FreeCAD | ||
|
||
__title__ = "CFD Analysis creation" | ||
__author__ = "Qingfeng Xia" | ||
__url__ = "http://www.freecadweb.org" | ||
|
||
|
||
def makeCfdAnalysis(name): | ||
'''makeCfdAnalysis(name): makes a Cfd Analysis object based on Fem::FemAnalysisPython''' | ||
obj = FreeCAD.ActiveDocument.addObject("Fem::FemAnalysisPython", name) | ||
return obj |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
# *************************************************************************** | ||
# * * | ||
# * Copyright (c) 2015 - Qingfeng Xia <qingfeng.xia eng ox ac uk> * * | ||
# * * | ||
# * This program is free software; you can redistribute it and/or modify * | ||
# * it under the terms of the GNU Lesser General Public License (LGPL) * | ||
# * as published by the Free Software Foundation; either version 2 of * | ||
# * the License, or (at your option) any later version. * | ||
# * for detail see the LICENCE text file. * | ||
# * * | ||
# * This program is distributed in the hope that it will be useful, * | ||
# * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
# * GNU Library General Public License for more details. * | ||
# * * | ||
# * You should have received a copy of the GNU Library General Public * | ||
# * License along with this program; if not, write to the Free Software * | ||
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | ||
# * USA * | ||
# * * | ||
# *************************************************************************** | ||
|
||
""" | ||
After playback macro, Mesh object need to build up in taskpanel | ||
2D meshing is hard to converted to OpenFOAM, but possible to export UNV mesh | ||
""" | ||
|
||
__title__ = "FoamCaseWriter" | ||
__author__ = "Qingfeng Xia" | ||
__url__ = "http://www.freecadweb.org" | ||
|
||
import os | ||
import os.path | ||
|
||
import FreeCAD | ||
|
||
import CfdTools | ||
import FoamCaseBuilder as fcb # independent module, not depending on FreeCAD | ||
|
||
|
||
## write CFD analysis setup into OpenFOAM case | ||
# write_case() is the only public API | ||
class CfdCaseWriterFoam: | ||
def __init__(self, analysis_obj): | ||
""" analysis_obj should contains all the information needed, | ||
boundaryConditionList is a list of all boundary Conditions objects(FemConstraint) | ||
""" | ||
self.analysis_obj = analysis_obj | ||
self.solver_obj = CfdTools.getSolver(analysis_obj) | ||
self.mesh_obj = CfdTools.getMesh(analysis_obj) | ||
self.material_obj = CfdTools.getMaterial(analysis_obj) | ||
self.bc_group = CfdTools.getConstraintGroup(analysis_obj) | ||
self.mesh_generated = False | ||
|
||
self.case_folder = self.solver_obj.WorkingDir + os.path.sep + self.solver_obj.InputCaseName | ||
self.mesh_file_name = self.case_folder + os.path.sep + self.solver_obj.InputCaseName + u".unv" | ||
if self.solver_obj.HeatTransfering: | ||
self.builder = fcb.BasicBuilder(self.case_folder, CfdTools.getSolverSettings(self.solver_obj)) | ||
else: | ||
self.builder = fcb.BasicBuilder(self.case_folder, CfdTools.getSolverSettings(self.solver_obj)) | ||
self.builder.createCase() | ||
|
||
def write_case(self, updating=False): | ||
""" Write_case() will collect case setings, and finally build a runnable case | ||
""" | ||
FreeCAD.Console.PrintMessage("Start to write case to folder {}\n".format(self.solver_obj.WorkingDir)) | ||
self.write_mesh() | ||
|
||
self.write_material() | ||
self.write_boundary_condition() | ||
self.builder.turbulenceProperties = {"name": self.solver_obj.TurbulenceModel} | ||
|
||
self.write_solver_control() | ||
self.write_time_control() | ||
|
||
self.builder.check() | ||
self.builder.build() | ||
FreeCAD.Console.PrintMessage("{} Sucessfully write {} case to folder \n".format( | ||
self.solver_obj.SolverName, self.solver_obj.WorkingDir)) | ||
return True | ||
|
||
def write_mesh(self): | ||
""" This is FreeCAD specific code, convert from UNV to OpenFoam | ||
""" | ||
caseFolder = self.solver_obj.WorkingDir + os.path.sep + self.solver_obj.InputCaseName | ||
unvMeshFile = caseFolder + os.path.sep + self.solver_obj.InputCaseName + u".unv" | ||
|
||
self.mesh_generated = CfdTools.write_unv_mesh(self.mesh_obj, self.bc_group, unvMeshFile) | ||
|
||
# FreecAD (internal standard length) mm; while in CFD, it is metre, so mesh needs scaling | ||
# mesh generated from FreeCAD nees to be scaled by 0.001 | ||
# `transformPoints -scale "(1e-3 1e-3 1e-3)"` | ||
scale = 0.001 | ||
self.builder.setupMesh(unvMeshFile, scale) | ||
#FreeCAD.Console.PrintMessage('mesh file {} converted and scaled with ratio {}\n'.format(unvMeshFile, scale)) | ||
|
||
def write_material(self, material=None): | ||
""" Air, Water, CustomedFluid, first step, default to Water, but here increase viscosity for quick convergence | ||
""" | ||
self.builder.fluidProperties = {'name': 'oneLiquid', 'kinematicViscosity': 1e-3} | ||
#self.builder.fluidProperties = self.material_obj.FluidicProperties | ||
|
||
def write_boundary_condition(self): | ||
""" Switch case to deal diff fluid boundary condition, thermal and turbulent is not yet fully tested | ||
""" | ||
#caseFolder = self.solver_obj.WorkingDir + os.path.sep + self.solver_obj.InputCaseName | ||
bc_settings = [] | ||
for bc in self.bc_group: | ||
#FreeCAD.Console.PrintMessage("write boundary condition: {}\n".format(bc.Label)) | ||
assert bc.isDerivedFrom("Fem::ConstraintFluidBoundary") | ||
bc_dict = {'name': bc.Label, "type": bc.BoundaryType, "subtype": bc.Subtype, "value": bc.BoundaryValue} | ||
if bc_dict['type'] == 'inlet' and bc_dict['subtype'] == 'uniformVelocity': | ||
bc_dict['value'] = [abs(v) * bc_dict['value'] for v in tuple(bc.DirectionVector)] | ||
# fixme: App::PropertyVector should be normalized to unit length | ||
if self.solver_obj.HeatTransfering: | ||
bc_dict['thermalSettings'] = {"subtype": bc.ThermalBoundaryType, | ||
"temperature": bc.TemperatureValue, | ||
"heatFlux": bc.HeatFluxValue, | ||
"HTC": bc.HTCoeffValue} | ||
bc_dict['turbulenceSettings'] = {'name': self.solver_obj.TurbulenceModel} | ||
# ["Intensity&DissipationRate","Intensity&LengthScale","Intensity&ViscosityRatio", "Intensity&HydraulicDiameter"] | ||
if self.solver_obj.TurbulenceModel not in set(["laminar", "invisid", "DNS"]): | ||
bc_dict['turbulenceSettings'] = {"name": self.solver_obj.TurbulenceModel, | ||
"specification": bc.TurbulenceSpecification, | ||
"intensityValue": bc.TurbulentIntensityValue, | ||
"lengthValue": bc.TurbulentLengthValue | ||
} | ||
|
||
bc_settings.append(bc_dict) | ||
self.builder.internalFields = {'p': 0.0, 'U': (0, 0, 0.001)} # must set a nonzero for velocity field | ||
self.builder.boundaryConditions = bc_settings | ||
|
||
def write_solver_control(self): | ||
""" relaxRatio, fvOptions, pressure reference value, residual contnrol | ||
""" | ||
self.builder.setupSolverControl() | ||
# set relaxationFactors like 0.1 for the coarse 3D mesh, this is a temperoary solution | ||
|
||
def write_time_control(self): | ||
""" controlDict for time information | ||
""" | ||
if self.solver_obj.Transient: | ||
self.builder.transientSettings = {"startTime": self.solver_obj.StartTime, | ||
"endTime": self.solver_obj.EndTime, | ||
"timeStep": self.solver_obj.TimeStep, | ||
"writeInterval": self.solver_obj.WriteInterval | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,114 @@ | ||
#*************************************************************************** | ||
#* * | ||
#* Copyright (c) 2015 - Qingfeng Xia @iesensor.com * | ||
#* * | ||
#* This program is free software; you can redistribute it and/or modify * | ||
#* it under the terms of the GNU Lesser General Public License (LGPL) * | ||
#* as published by the Free Software Foundation; either version 2 of * | ||
#* the License, or (at your option) any later version. * | ||
#* for detail see the LICENCE text file. * | ||
#* * | ||
#* This program is distributed in the hope that it will be useful, * | ||
#* but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
#* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * | ||
#* GNU Library General Public License for more details. * | ||
#* * | ||
#* You should have received a copy of the GNU Library General Public * | ||
#* License along with this program; if not, write to the Free Software * | ||
#* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * | ||
#* USA * | ||
#* * | ||
#*************************************************************************** | ||
|
||
App.newDocument("Unnamed") | ||
App.setActiveDocument("Unnamed") | ||
App.ActiveDocument=App.getDocument("Unnamed") | ||
Gui.ActiveDocument=Gui.getDocument("Unnamed") | ||
# | ||
Gui.activateWorkbench("PartWorkbench") | ||
App.ActiveDocument.addObject("Part::Cylinder","Cylinder") | ||
App.ActiveDocument.ActiveObject.Label = "Cylinder" | ||
App.ActiveDocument.getObject("Cylinder").Radius = '5 mm' | ||
App.ActiveDocument.getObject("Cylinder").Height = '20 mm' | ||
App.ActiveDocument.recompute() | ||
Gui.SendMsgToActiveView("ViewFit") | ||
Gui.activateWorkbench("FemWorkbench") | ||
# | ||
mesh_obj = App.activeDocument().addObject('Fem::FemMeshShapeNetgenObject', 'Cylinder_Mesh') | ||
App.activeDocument().ActiveObject.Shape = App.activeDocument().Cylinder | ||
Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name) | ||
Gui.activeDocument().resetEdit() | ||
# | ||
import FemGui | ||
import CaeAnalysis | ||
analysis_obj = CaeAnalysis._CreateCaeAnalysis('OpenFOAM', 'OpenFOAMAnalysis') | ||
analysis_obj.Member = analysis_obj.Member + [mesh_obj] | ||
Gui.getDocument("Unnamed").getObject("Cylinder_Mesh").Visibility=False | ||
Gui.getDocument("Unnamed").getObject("Cylinder").Visibility=True | ||
#copy and paste the code above, nesh must be generated in TaskPanel | ||
# uncheck the "second order" checkbox to gen mesh, also use the very fine mesh | ||
################################################# | ||
import FemMaterial | ||
FemMaterial.makeFemMaterial('Fluid') | ||
App.activeDocument().OpenFOAMAnalysis.Member = App.activeDocument().OpenFOAMAnalysis.Member + [App.ActiveDocument.ActiveObject] | ||
Gui.activeDocument().setEdit(App.ActiveDocument.ActiveObject.Name) | ||
############################################### | ||
Gui.getDocument("Unnamed").getObject("Cylinder").Visibility=True | ||
Gui.getDocument("Unnamed").getObject("OpenFOAM").WorkingDir = "/tmp/" | ||
# | ||
App.activeDocument().addObject("Fem::FluidBoundary","FluidBoundary") | ||
App.activeDocument().OpenFOAMAnalysis.Member = App.activeDocument().OpenFOAMAnalysis.Member + [App.activeDocument().FluidBoundary] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().setEdit('FluidBoundary') | ||
App.ActiveDocument.FluidBoundary.BoundaryType = 'outlet' | ||
App.ActiveDocument.FluidBoundary.Subtype = 'totalPressure' | ||
App.ActiveDocument.FluidBoundary.BoundaryValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary.Direction = None | ||
App.ActiveDocument.FluidBoundary.ThermalBoundaryType = 'zeroGradient' | ||
App.ActiveDocument.FluidBoundary.TemperatureValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary.HeatFluxValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary.HTCoeffValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary.References = [(App.ActiveDocument.Cylinder,"Face2")] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().resetEdit() | ||
# | ||
App.activeDocument().addObject("Fem::FluidBoundary","FluidBoundary001") | ||
App.activeDocument().OpenFOAMAnalysis.Member = App.activeDocument().OpenFOAMAnalysis.Member + [App.activeDocument().FluidBoundary001] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().setEdit('FluidBoundary001') | ||
App.ActiveDocument.FluidBoundary001.BoundaryType = 'inlet' | ||
App.ActiveDocument.FluidBoundary001.Subtype = 'uniformVelocity' | ||
App.ActiveDocument.FluidBoundary001.BoundaryValue = 1.000000 | ||
App.ActiveDocument.FluidBoundary001.Direction = None | ||
App.ActiveDocument.FluidBoundary001.ThermalBoundaryType = 'zeroGradient' | ||
App.ActiveDocument.FluidBoundary001.TemperatureValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary001.HeatFluxValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary001.HTCoeffValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary001.References = [(App.ActiveDocument.Cylinder,"Face3")] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().resetEdit() | ||
# | ||
App.activeDocument().addObject("Fem::FluidBoundary","FluidBoundary002") | ||
App.activeDocument().OpenFOAMAnalysis.Member = App.activeDocument().OpenFOAMAnalysis.Member + [App.activeDocument().FluidBoundary002] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().setEdit('FluidBoundary002') | ||
App.ActiveDocument.FluidBoundary002.BoundaryType = 'wall' | ||
App.ActiveDocument.FluidBoundary002.Subtype = 'fixed' | ||
App.ActiveDocument.FluidBoundary002.BoundaryValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary002.Direction = None | ||
App.ActiveDocument.FluidBoundary002.ThermalBoundaryType = 'zeroGradient' | ||
App.ActiveDocument.FluidBoundary002.TemperatureValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary002.HeatFluxValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary002.HTCoeffValue = 0.000000 | ||
App.ActiveDocument.FluidBoundary002.References = [(App.ActiveDocument.Cylinder,"Face1")] | ||
App.ActiveDocument.recompute() | ||
Gui.activeDocument().resetEdit() | ||
# | ||
############################################################ | ||
# | ||
# must generate mesh in GUI dialog, or the mesh_obj is empty without cells | ||
# CFD mesh must NOT second-order, or optimized, so untick those checkboxes in GUI | ||
# | ||
import FoamCaseWriter | ||
writer = FoamCaseWriter.FoamCaseWriter(App.activeDocument().OpenFOAMAnalysis) | ||
writer.write_case() |
Oops, something went wrong.