Skip to content

Commit

Permalink
CFD: initial commit seperated from Fem workbench
Browse files Browse the repository at this point in the history
  • Loading branch information
qingfengxia committed Sep 29, 2016
0 parents commit c100a75
Show file tree
Hide file tree
Showing 41 changed files with 185,987 additions and 0 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
*.pyc
FoamCaseBuilder/*.pyc
FoamCaseBuilder/__pycache__
FoamCaseBuilder/PlyParse*

43 changes: 43 additions & 0 deletions CMakeLists.txt
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
)
33 changes: 33 additions & 0 deletions CfdAnalysis.py
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
147 changes: 147 additions & 0 deletions CfdCaseWriterFoam.py
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
}
114 changes: 114 additions & 0 deletions CfdExample.py
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()
Loading

0 comments on commit c100a75

Please sign in to comment.