Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CfdOF/CfdTools.py
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,10 @@ def getScalarTransportFunctionsGroup(analysis_object):
return getModelsOfType(analysis_object, 'CfdScalarTransportFunction')


def getMeanVelocityForceObject(analysis_object):
return getModelOfType(analysis_object, 'CfdMeanVelocityForce')


# Mesh
def getMeshRefinementObjs(mesh_obj):
return getModelsOfType(mesh_obj, 'CfdMeshRefinement')
Expand Down
4 changes: 4 additions & 0 deletions CfdOF/Solve/CfdCaseWriterFoam.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ def __init__(self, analysis_obj):
raise RuntimeError("No initial conditions object was found in analysis " + analysis_obj.Label)
self.reporting_functions = CfdTools.getReportingFunctionsGroup(analysis_obj)
self.scalar_transport_objs = CfdTools.getScalarTransportFunctionsGroup(analysis_obj)
self.mean_velocity_force_obj = CfdTools.getMeanVelocityForceObject(analysis_obj)
self.porous_zone_objs = CfdTools.getPorousZoneObjects(analysis_obj)
self.initialisation_zone_objs = CfdTools.getInitialisationZoneObjects(analysis_obj)
self.zone_objs = CfdTools.getZoneObjects(analysis_obj)
Expand Down Expand Up @@ -114,6 +115,9 @@ def writeCase(self):
'reportingFunctionsEnabled': False,
'scalarTransportFunctions': dict((st.Label, CfdTools.propsToDict(st)) for st in self.scalar_transport_objs),
'scalarTransportFunctionsEnabled': False,
'meanVelocityForce': CfdTools.propsToDict(self.mean_velocity_force_obj) if self.mean_velocity_force_obj else {},
'meanVelocityForceEnabled': self.mean_velocity_force_obj is not None,
'fvOptionsPresent': (self.mean_velocity_force_obj is not None),
'dynamicMesh': {},
'dynamicMeshEnabled': False,
'MovingMeshRegions': {},
Expand Down
180 changes: 180 additions & 0 deletions CfdOF/Solve/CfdMeanVelocityForce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# SPDX-FileNotice: Part of the CfdOF addon.

import os

import FreeCAD
import FreeCADGui
from pivy import coin

from CfdOF import CfdTools
from CfdOF.CfdTools import addObjectProperty

QT_TRANSLATE_NOOP = FreeCAD.Qt.QT_TRANSLATE_NOOP


def makeCfdMeanVelocityForce(name="MeanVelocityForce"):
obj = FreeCAD.ActiveDocument.addObject("Part::FeaturePython", name)
CfdMeanVelocityForce(obj)
if FreeCAD.GuiUp:
ViewProviderCfdMeanVelocityForce(obj.ViewObject)
return obj


class CommandCfdMeanVelocityForce:
def __init__(self):
pass

def GetResources(self):
icon_path = os.path.join(CfdTools.getModulePath(), "Gui", "Icons", "meanvelocityforce.svg")
return {
'Pixmap': icon_path,
'MenuText': QT_TRANSLATE_NOOP("CfdOF_MeanVelocityForce", "Mean velocity force"),
'ToolTip': QT_TRANSLATE_NOOP("CfdOF_MeanVelocityForce", "Create a mean velocity force fvOption"),
}

def IsActive(self):
return CfdTools.getActiveAnalysis() is not None

def Activated(self):
FreeCAD.ActiveDocument.openTransaction("Create MeanVelocityForce object")
FreeCADGui.doCommand("")
FreeCADGui.doCommand("from CfdOF.Solve import CfdMeanVelocityForce")
FreeCADGui.doCommand("from CfdOF import CfdTools")
FreeCADGui.doCommand(
"CfdTools.getActiveAnalysis().addObject(CfdMeanVelocityForce.makeCfdMeanVelocityForce())")
FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)


class CfdMeanVelocityForce:
def __init__(self, obj):
self.Object = obj
self.initProperties(obj)

def initProperties(self, obj):
obj.Proxy = self
self.Type = 'CfdMeanVelocityForce'

addObjectProperty(
obj,
"Direction",
FreeCAD.Vector(0, 0, 0),
"App::PropertyVector",
"Mean velocity force",
QT_TRANSLATE_NOOP("App::Property", "Direction vector for the mean velocity force"),
)
addObjectProperty(
obj,
"Ubar",
FreeCAD.Vector(0, 0, 0),
"App::PropertyVector",
"Mean velocity force",
QT_TRANSLATE_NOOP("App::Property", "Target mean velocity vector"),
)
addObjectProperty(
obj,
"Relaxation",
0.2,
"App::PropertyFloat",
"Mean velocity force",
QT_TRANSLATE_NOOP("App::Property", "Relaxation factor for mean velocity force"),
)

def onDocumentRestored(self, obj):
self.initProperties(obj)

def execute(self, obj):
pass

def __getstate__(self):
return None

def __setstate__(self, state):
return None

def dumps(self):
return None

def loads(self, state):
return None


class ViewProviderCfdMeanVelocityForce:
def __init__(self, vobj):
vobj.Proxy = self

def getIcon(self):
icon_path = os.path.join(CfdTools.getModulePath(), "Gui", "Icons", "meanvelocityforce.svg")
return icon_path

def attach(self, vobj):
self.ViewObject = vobj
self.Object = vobj.Object
self.standard = coin.SoGroup()
vobj.addDisplayMode(self.standard, "Standard")
return

def updateData(self, obj, prop):
analysis_obj = CfdTools.getParentAnalysisObject(obj)
if analysis_obj and not analysis_obj.Proxy.loading:
analysis_obj.NeedsCaseRewrite = True

def onChanged(self, vobj, prop):
return

def doubleClicked(self, vobj):
doc = FreeCADGui.getDocument(vobj.Object.Document)
if not doc.getInEdit():
doc.setEdit(vobj.Object.Name)
else:
FreeCAD.Console.PrintError('Task dialog already active\\n')
FreeCADGui.Control.showTaskView()
return True

def setEdit(self, vobj, mode):
analysis_object = CfdTools.getParentAnalysisObject(self.Object)
if analysis_object is None:
CfdTools.cfdErrorBox("Mean velocity force object must have a parent analysis object")
return False

from CfdOF.Solve import TaskPanelCfdMeanVelocityForce
import importlib
importlib.reload(TaskPanelCfdMeanVelocityForce)
taskd = TaskPanelCfdMeanVelocityForce.TaskPanelCfdMeanVelocityForce(self.Object)
taskd.obj = vobj.Object
FreeCADGui.Control.showDialog(taskd)
return True

def unsetEdit(self, vobj, mode):
FreeCADGui.Control.closeDialog()
return

def __getstate__(self):
return None

def __setstate__(self, state):
return None

def dumps(self):
return None

def loads(self, state):
return None


class _ViewProviderCfdMeanVelocityForce:
def attach(self, vobj):
new_proxy = ViewProviderCfdMeanVelocityForce(vobj)
new_proxy.attach(vobj)

def __getstate__(self):
return None

def __setstate__(self, state):
return None

def dumps(self):
return None

def loads(self, state):
return None
69 changes: 69 additions & 0 deletions CfdOF/Solve/TaskPanelCfdMeanVelocityForce.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
# SPDX-License-Identifier: LGPL-3.0-or-later
# SPDX-FileNotice: Part of the CfdOF addon.

import os

import FreeCAD
from FreeCAD import Units
from CfdOF import CfdTools
from CfdOF.CfdTools import setQuantity, getQuantity, storeIfChanged
if FreeCAD.GuiUp:
import FreeCADGui


class TaskPanelCfdMeanVelocityForce:
"""
Task panel for adding/editing mean velocity force fvOption objects
"""
def __init__(self, obj):
self.obj = obj

ui_path = os.path.join(CfdTools.getModulePath(), 'Gui', "TaskPanelCfdMeanVelocityForce.ui")
self.form = FreeCADGui.PySideUic.loadUi(ui_path)

self.load()

def load(self):
setQuantity(self.form.inputDirectionX, self.obj.Direction.x)
setQuantity(self.form.inputDirectionY, self.obj.Direction.y)
setQuantity(self.form.inputDirectionZ, self.obj.Direction.z)

setQuantity(self.form.inputUbarX, "{} mm/s".format(float(self.obj.Ubar.x) * 1000.0))
setQuantity(self.form.inputUbarY, "{} mm/s".format(float(self.obj.Ubar.y) * 1000.0))
setQuantity(self.form.inputUbarZ, "{} mm/s".format(float(self.obj.Ubar.z) * 1000.0))

setQuantity(self.form.inputRelaxation, self.obj.Relaxation)

def _toMS(self, widget, field_name):
try:
return Units.Quantity(getQuantity(widget)).getValueAs('m/s')
except Exception:
raise ValueError("{} must be a valid velocity".format(field_name))

def accept(self):
try:
direction = FreeCAD.Vector(
self.form.inputDirectionX.property("quantity").Value,
self.form.inputDirectionY.property("quantity").Value,
self.form.inputDirectionZ.property("quantity").Value)
ubar = FreeCAD.Vector(
self._toMS(self.form.inputUbarX, 'Ubar X'),
self._toMS(self.form.inputUbarY, 'Ubar Y'),
self._toMS(self.form.inputUbarZ, 'Ubar Z'))
relaxation = self.form.inputRelaxation.property("quantity").Value
except ValueError as err:
CfdTools.cfdErrorBox(str(err))
return

doc = FreeCADGui.getDocument(self.obj.Document)
doc.resetEdit()

storeIfChanged(self.obj, 'Direction', direction)
storeIfChanged(self.obj, 'Ubar', ubar)
storeIfChanged(self.obj, 'Relaxation', relaxation)

FreeCADGui.doCommand("FreeCAD.ActiveDocument.recompute()")

def reject(self):
doc = FreeCADGui.getDocument(self.obj.Document)
doc.resetEdit()
21 changes: 21 additions & 0 deletions Data/Templates/case/system/fvOptions
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
%{%(fvOptionsPresent%)
%:True
%[_header%]
FoamFile
{
Expand Down Expand Up @@ -54,4 +56,23 @@ FoamFile

#includeIfPresent "fvOptionsScalarTransport"

%{%(meanVelocityForceEnabled%)
%:True
momentumSource
{
type meanVelocityForce;
selectionMode all;
active yes;
meanVelocityForceCoeffs
{
selectionMode all;
fields (U);
direction (%(meanVelocityForce/Direction%));
Ubar (%(meanVelocityForce/Ubar%));
relaxation %(meanVelocityForce/Relaxation%);
}
}

%}
//************************************************************************ //
%}
56 changes: 56 additions & 0 deletions Data/TestFiles/cases/PeriodicBoundaryAndMeanVelocityForce/case/0/U
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*--------------------------------*- C++ -*----------------------------------*\
| |
| Generated by the CfdOF workbench for FreeCAD |
| https://github.com/jaheyns/CfdOF |
| |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class volVectorField;
object U;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

dimensions [0 1 -1 0 0 0 0];

internalField uniform (0.005 0.0 0.0);

boundaryField
{

constraint
{
type symmetry;
value $internalField;
}

constraint001_master
{
type cyclicAMI;
}

constraint001_slave
{
type cyclicAMI;
}



wall
{
// movingWallVelocity reduces to fixedValue if the mesh is not moving
type movingWallVelocity;
value uniform (0 0 0);
}

defaultFaces
{
type slip;
value $internalField;
}

}

// ************************************************************************* //
Loading