From 06061e37dc2b1e42f168457b99744f8fb1453ecc Mon Sep 17 00:00:00 2001 From: Uwe Date: Sat, 18 Mar 2023 05:36:36 +0100 Subject: [PATCH] [FEM] rewrite velocity constraint - complete revision of the constraint. This is a breaking change, meaning existing constraints won't work. This is possible because since 2 days ago the whole flow equation did not work at all. Also the existing constraint implementation if buggy and cannot be used to do the Elmer tutorial. Also, the constraint is only used by Elmer and only be the flow equation. Since nobody complained about the obvious wrong results, we can assume the flow equation was not yet in practical usage (and for FC 0.20 we known that it does not work at all, first with FC 0.20.1). It is necessary since it must be possible to either input a velocity or an equation. With an equation, a velocity profile can be specified. - update the flow examples accordingly: -- simplify them since an initial and and output velocity is not necessary to specify -- use a formula as input velocity for the non-turbulent example --- src/Mod/Fem/Gui/Resources/ui/FlowVelocity.ui | 280 +++++++++--------- .../Fem/femexamples/equation_flow_elmer_2D.py | 48 +-- .../equation_flow_turbulent_elmer_2D.py | 48 +-- .../Fem/femobjects/constraint_flowvelocity.py | 54 +++- .../femsolver/elmer/equations/flow_writer.py | 21 +- .../task_constraint_flowvelocity.py | 190 ++++++++++-- 6 files changed, 391 insertions(+), 250 deletions(-) diff --git a/src/Mod/Fem/Gui/Resources/ui/FlowVelocity.ui b/src/Mod/Fem/Gui/Resources/ui/FlowVelocity.ui index 3793c63e4f..088c802cc8 100644 --- a/src/Mod/Fem/Gui/Resources/ui/FlowVelocity.ui +++ b/src/Mod/Fem/Gui/Resources/ui/FlowVelocity.ui @@ -6,78 +6,27 @@ 0 0 - 400 - 300 + 300 + 197 Constraint Properties - - - - - Velocity x: - - - - - - - Velocity y: - - - - - - - Velocity z: - - - - - - - + + + + + false - - 1.000000000000000 - - - m/s - - - - - - unspecified - - - true + formula - - - - - - - - false - - - 1.000000000000000 - - - m/s - - - - + unspecified @@ -87,24 +36,52 @@ - - - - - - - - false - - - 1.000000000000000 - - - m/s + + + + Velocity x: - + + + + false + + + + + + + false + + + + + + + + + + + + + + false + + + formula + + + + + + + Velocity y: + + + + unspecified @@ -114,12 +91,77 @@ + + + + false + + + + + + + false + + + + + + - + + + + + + unspecified + + + true + + + + + + + false + + + formula + + + + + + + Velocity z: + + + + + + + false + + + + + + + false + + + + + + + + + - normal to boundary + Normal to boundary @@ -127,9 +169,9 @@ - Gui::InputField - QLineEdit -
Gui/InputField.h
+ Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
@@ -137,96 +179,48 @@ velocityXBox toggled(bool) - velocityXTxt - setEnabled(bool) - - - 230 - 44 - - - 230 - 18 - - - - - velocityXBox - toggled(bool) - velocityXTxt + formulaXCB setDisabled(bool) - 230 - 44 + 351 + 19 - 230 - 18 + 351 + 45 velocityYBox toggled(bool) - velocityYTxt - setEnabled(bool) - - - 347 - 53 - - - 184 - 53 - - - - - velocityYBox - toggled(bool) - velocityYTxt + formulaYCB setDisabled(bool) - 347 - 53 + 351 + 73 - 184 - 53 + 351 + 99 velocityZBox toggled(bool) - velocityZTxt - setEnabled(bool) - - - 347 - 87 - - - 184 - 87 - - - - - velocityZBox - toggled(bool) - velocityZTxt + formulaZCB setDisabled(bool) - 347 - 87 + 351 + 127 - 184 - 87 + 351 + 153 diff --git a/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py b/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py index 32d09e317d..60e71d5cb1 100644 --- a/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py +++ b/src/Mod/Fem/femexamples/equation_flow_elmer_2D.py @@ -71,19 +71,19 @@ def setup(doc=None, solvertype="elmer"): # geometric objects # the wire defining the pipe volume in 2D - p1 = Vector(400, 0, -50.000) - p2 = Vector(400, 0, -150.000) - p3 = Vector(1200, 0, -150.000) - p4 = Vector(1200, 0, 50.000) - p5 = Vector(0, 0, 50.000) - p6 = Vector(0, 0, -50.000) + p1 = Vector(400, -50.000, 0) + p2 = Vector(400, -150.000, 0) + p3 = Vector(1200, -150.000, 0) + p4 = Vector(1200, 50.000, 0) + p5 = Vector(0, 50.000, 0) + p6 = Vector(0, -50.000, 0) wire = Draft.make_wire([p1, p2, p3, p4, p5, p6], closed=True) wire.Label = "Wire" # the circle defining the heating rod pCirc = Vector(160, 0, 0) axisCirc = Vector(1, 0, 0) - placementCircle = Placement(pCirc, Rotation(axisCirc, 90)) + placementCircle = Placement(pCirc, Rotation(axisCirc, 0)) circle = Draft.make_circle(10, placement=placementCircle) circle.Label = "HeatingRod" circle.ViewObject.Visibility = False @@ -107,7 +107,6 @@ def setup(doc=None, solvertype="elmer"): doc.recompute() if FreeCAD.GuiUp: BooleanFragments.ViewObject.Transparency = 50 - BooleanFragments.ViewObject.Document.activeView().viewFront() BooleanFragments.ViewObject.Document.activeView().fitAll() # analysis @@ -119,6 +118,7 @@ def setup(doc=None, solvertype="elmer"): # solver if solvertype == "elmer": solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer") + solver_obj.CoordinateSystem = "Cartesian 2D" equation_flow = ObjectsFem.makeEquationFlow(doc, solver_obj) equation_heat = ObjectsFem.makeEquationHeat(doc, solver_obj) else: @@ -133,6 +133,7 @@ def setup(doc=None, solvertype="elmer"): equation_flow.IdrsParameter = 3 equation_flow.LinearIterativeMethod = "Idrs" equation_flow.LinearPreconditioning = "ILU1" + equation_flow.Variable = "Flow Solution[Velocity:2 Pressure:1]" equation_heat.Convection = "Computed" equation_heat.IdrsParameter = 3 equation_heat.LinearIterativeMethod = "Idrs" @@ -179,20 +180,11 @@ def setup(doc=None, solvertype="elmer"): FlowVelocity_Inlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Inlet") FlowVelocity_Inlet.References = [(BooleanFragments, "Edge5")] FlowVelocity_Inlet.NormalDirection = Vector(-1, 0, 0) - FlowVelocity_Inlet.VelocityX = 0.020 - FlowVelocity_Inlet.VelocityXEnabled = True - FlowVelocity_Inlet.VelocityYEnabled = True - FlowVelocity_Inlet.VelocityZEnabled = True + FlowVelocity_Inlet.VelocityXFormula = "Variable Coordinate 2; Real MATC \"-0.01*(tx-1)*(2-tx)\"" + FlowVelocity_Inlet.VelocityXUnspecified = False + FlowVelocity_Inlet.VelocityXHasFormula = True analysis.addObject(FlowVelocity_Inlet) - # constraint outlet velocity - FlowVelocity_Outlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Outlet") - FlowVelocity_Outlet.References = [(BooleanFragments, "Edge6")] - FlowVelocity_Outlet.NormalDirection = Vector(1, 0, 0) - FlowVelocity_Outlet.VelocityYEnabled = True - FlowVelocity_Outlet.VelocityZEnabled = True - analysis.addObject(FlowVelocity_Outlet) - # constraint wall velocity FlowVelocity_Wall = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Wall") FlowVelocity_Wall.References = [ @@ -200,21 +192,11 @@ def setup(doc=None, solvertype="elmer"): (BooleanFragments, "Edge3"), (BooleanFragments, "Edge4"), (BooleanFragments, "Edge7")] - FlowVelocity_Wall.NormalDirection = Vector(0, 0, -1) - FlowVelocity_Wall.VelocityXEnabled = True - FlowVelocity_Wall.VelocityYEnabled = True - FlowVelocity_Wall.VelocityZEnabled = True + FlowVelocity_Wall.NormalDirection = Vector(0, -1, 0) + FlowVelocity_Wall.VelocityXUnspecified = False + FlowVelocity_Wall.VelocityYUnspecified = False analysis.addObject(FlowVelocity_Wall) - # constraint initial velocity - FlowVelocity_Initial = ObjectsFem.makeConstraintInitialFlowVelocity(doc, "FlowVelocity_Initial") - FlowVelocity_Initial.References = [(BooleanFragments, "Face2")] - FlowVelocity_Initial.NormalDirection = Vector(0, -1, 0) - FlowVelocity_Initial.VelocityXEnabled = True - FlowVelocity_Initial.VelocityYEnabled = True - FlowVelocity_Initial.VelocityZEnabled = True - analysis.addObject(FlowVelocity_Initial) - # constraint initial temperature Temperature_Initial = ObjectsFem.makeConstraintInitialTemperature(doc, "Temperature_Initial") Temperature_Initial.initialTemperature = 300.0 diff --git a/src/Mod/Fem/femexamples/equation_flow_turbulent_elmer_2D.py b/src/Mod/Fem/femexamples/equation_flow_turbulent_elmer_2D.py index e21510bc75..3e8e2c631c 100644 --- a/src/Mod/Fem/femexamples/equation_flow_turbulent_elmer_2D.py +++ b/src/Mod/Fem/femexamples/equation_flow_turbulent_elmer_2D.py @@ -71,19 +71,19 @@ def setup(doc=None, solvertype="elmer"): # geometric objects # the wire defining the pipe volume in 2D - p1 = Vector(400, 0, -50.000) - p2 = Vector(400, 0, -150.000) - p3 = Vector(1200, 0, -150.000) - p4 = Vector(1200, 0, 50.000) - p5 = Vector(0, 0, 50.000) - p6 = Vector(0, 0, -50.000) + p1 = Vector(400, -50.000, 0) + p2 = Vector(400, -150.000, 0) + p3 = Vector(1200, -150.000, 0) + p4 = Vector(1200, 50.000, 0) + p5 = Vector(0, 50.000, 0) + p6 = Vector(0, -50.000, 0) wire = Draft.make_wire([p1, p2, p3, p4, p5, p6], closed=True) wire.Label = "Wire" # the circle defining the heating rod pCirc = Vector(160, 0, 0) axisCirc = Vector(1, 0, 0) - placementCircle = Placement(pCirc, Rotation(axisCirc, 90)) + placementCircle = Placement(pCirc, Rotation(axisCirc, 0)) circle = Draft.make_circle(10, placement=placementCircle) circle.Label = "HeatingRod" circle.ViewObject.Visibility = False @@ -107,7 +107,6 @@ def setup(doc=None, solvertype="elmer"): doc.recompute() if FreeCAD.GuiUp: BooleanFragments.ViewObject.Transparency = 50 - BooleanFragments.ViewObject.Document.activeView().viewFront() BooleanFragments.ViewObject.Document.activeView().fitAll() # analysis @@ -119,6 +118,7 @@ def setup(doc=None, solvertype="elmer"): # solver if solvertype == "elmer": solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer") + solver_obj.CoordinateSystem = "Cartesian 2D" equation_flow = ObjectsFem.makeEquationFlow(doc, solver_obj) equation_heat = ObjectsFem.makeEquationHeat(doc, solver_obj) else: @@ -131,7 +131,6 @@ def setup(doc=None, solvertype="elmer"): # solver settings equation_flow.IdrsParameter = 3 - equation_flow.LinearIterations = 250 equation_flow.LinearIterativeMethod = "Idrs" equation_flow.LinearPreconditioning = "ILU1" equation_flow.setExpression("LinearTolerance", "1e-6") @@ -139,9 +138,9 @@ def setup(doc=None, solvertype="elmer"): equation_flow.NonlinearNewtonAfterIterations = 30 equation_flow.setExpression("NonlinearTolerance", "1e-4") equation_flow.RelaxationFactor = 0.1 + equation_flow.Variable = "Flow Solution[Velocity:2 Pressure:1]" equation_heat.Convection = "Computed" equation_heat.IdrsParameter = 3 - equation_heat.LinearIterations = 250 equation_heat.LinearIterativeMethod = "Idrs" equation_heat.LinearPreconditioning = "ILU1" equation_heat.setExpression("LinearTolerance", "1e-6") @@ -187,20 +186,11 @@ def setup(doc=None, solvertype="elmer"): FlowVelocity_Inlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Inlet") FlowVelocity_Inlet.References = [(BooleanFragments, "Edge5")] FlowVelocity_Inlet.NormalDirection = Vector(-1, 0, 0) - FlowVelocity_Inlet.VelocityX = 0.020 - FlowVelocity_Inlet.VelocityXEnabled = True - FlowVelocity_Inlet.VelocityYEnabled = True - FlowVelocity_Inlet.VelocityZEnabled = True + FlowVelocity_Inlet.VelocityX = "20.0 mm/s" + FlowVelocity_Inlet.VelocityXUnspecified = False + FlowVelocity_Inlet.VelocityYUnspecified = False analysis.addObject(FlowVelocity_Inlet) - # constraint outlet velocity - FlowVelocity_Outlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Outlet") - FlowVelocity_Outlet.References = [(BooleanFragments, "Edge6")] - FlowVelocity_Outlet.NormalDirection = Vector(1, 0, 0) - FlowVelocity_Outlet.VelocityYEnabled = True - FlowVelocity_Outlet.VelocityZEnabled = True - analysis.addObject(FlowVelocity_Outlet) - # constraint wall velocity FlowVelocity_Wall = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Wall") FlowVelocity_Wall.References = [ @@ -209,20 +199,10 @@ def setup(doc=None, solvertype="elmer"): (BooleanFragments, "Edge4"), (BooleanFragments, "Edge7")] FlowVelocity_Wall.NormalDirection = Vector(0, 0, -1) - FlowVelocity_Wall.VelocityXEnabled = True - FlowVelocity_Wall.VelocityYEnabled = True - FlowVelocity_Wall.VelocityZEnabled = True + FlowVelocity_Wall.VelocityXUnspecified = False + FlowVelocity_Wall.VelocityYUnspecified = False analysis.addObject(FlowVelocity_Wall) - # constraint initial velocity - FlowVelocity_Initial = ObjectsFem.makeConstraintInitialFlowVelocity(doc, "FlowVelocity_Initial") - FlowVelocity_Initial.References = [(BooleanFragments, "Face2")] - FlowVelocity_Initial.NormalDirection = Vector(0, -1, 0) - FlowVelocity_Initial.VelocityXEnabled = True - FlowVelocity_Initial.VelocityYEnabled = True - FlowVelocity_Initial.VelocityZEnabled = True - analysis.addObject(FlowVelocity_Initial) - # constraint initial temperature Temperature_Initial = ObjectsFem.makeConstraintInitialTemperature(doc, "Temperature_Initial") Temperature_Initial.initialTemperature = 300.0 diff --git a/src/Mod/Fem/femobjects/constraint_flowvelocity.py b/src/Mod/Fem/femobjects/constraint_flowvelocity.py index 5625439fa7..8243c3a622 100644 --- a/src/Mod/Fem/femobjects/constraint_flowvelocity.py +++ b/src/Mod/Fem/femobjects/constraint_flowvelocity.py @@ -40,41 +40,83 @@ class ConstraintFlowVelocity(base_fempythonobject.BaseFemPythonObject): def __init__(self, obj): super(ConstraintFlowVelocity, self).__init__(obj) obj.addProperty( - "App::PropertyFloat", + "App::PropertyVelocity", "VelocityX", "Parameter", "Velocity in x-direction" ) + obj.addProperty( + "App::PropertyString", + "VelocityXFormula", + "Parameter", + "Velocity formula in x-direction" + ) obj.addProperty( "App::PropertyBool", - "VelocityXEnabled", + "VelocityXUnspecified", "Parameter", "Use velocity in x-direction" ) + obj.VelocityXUnspecified = True obj.addProperty( - "App::PropertyFloat", + "App::PropertyBool", + "VelocityXHasFormula", + "Parameter", + "Use formula for velocity in x-direction" + ) + + obj.addProperty( + "App::PropertyVelocity", "VelocityY", "Parameter", "Velocity in y-direction" ) + obj.addProperty( + "App::PropertyString", + "VelocityYFormula", + "Parameter", + "Velocity formula in y-direction" + ) obj.addProperty( "App::PropertyBool", - "VelocityYEnabled", + "VelocityYUnspecified", "Parameter", "Use velocity in y-direction" ) + obj.VelocityYUnspecified = True obj.addProperty( - "App::PropertyFloat", + "App::PropertyBool", + "VelocityYHasFormula", + "Parameter", + "Use formula for velocity in y-direction" + ) + + obj.addProperty( + "App::PropertyVelocity", "VelocityZ", "Parameter", "Velocity in z-direction" ) + obj.addProperty( + "App::PropertyString", + "VelocityZFormula", + "Parameter", + "Velocity formula in z-direction" + ) obj.addProperty( "App::PropertyBool", - "VelocityZEnabled", + "VelocityZUnspecified", "Parameter", "Use velocity in z-direction" ) + obj.VelocityZUnspecified = True + obj.addProperty( + "App::PropertyBool", + "VelocityZHasFormula", + "Parameter", + "Use formula for velocity in z-direction" + ) + obj.addProperty( "App::PropertyBool", "NormalToBoundary", diff --git a/src/Mod/Fem/femsolver/elmer/equations/flow_writer.py b/src/Mod/Fem/femsolver/elmer/equations/flow_writer.py index 796d8adcd6..68dd68333c 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/flow_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/flow_writer.py @@ -227,14 +227,23 @@ class Flowwriter: for obj in self.write.getMember("Fem::ConstraintFlowVelocity"): if obj.References: for name in obj.References[0][1]: - if obj.VelocityXEnabled: - velocity = self.write.getFromUi(obj.VelocityX, "m/s", "L/T") + if not obj.VelocityXUnspecified: + if not obj.VelocityXHasFormula: + velocity = float(obj.VelocityX.getValueAs("m/s")) + else: + velocity = obj.VelocityXFormula self.write.boundary(name, "Velocity 1", velocity) - if obj.VelocityYEnabled: - velocity = self.write.getFromUi(obj.VelocityY, "m/s", "L/T") + if not obj.VelocityYUnspecified: + if not obj.VelocityYHasFormula: + velocity = float(obj.VelocityY.getValueAs("m/s")) + else: + velocity = obj.VelocityYFormula self.write.boundary(name, "Velocity 2", velocity) - if obj.VelocityZEnabled: - velocity = self.write.getFromUi(obj.VelocityZ, "m/s", "L/T") + if not obj.VelocityZUnspecified: + if not obj.VelocityZHasFormula: + velocity = float(obj.VelocityZ.getValueAs("m/s")) + else: + velocity = obj.VelocityZFormula self.write.boundary(name, "Velocity 3", velocity) if obj.NormalToBoundary: self.write.boundary(name, "Normal-Tangential Velocity", True) diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py b/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py index 7e98729b47..41f2d8d072 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_flowvelocity.py @@ -29,9 +29,10 @@ __url__ = "https://www.freecadweb.org" # \ingroup FEM # \brief task panel for constraint flow velocity object +from PySide import QtCore + import FreeCAD import FreeCADGui -from FreeCAD import Units from femguiutils import selection_widgets from femtools import femutils @@ -46,8 +47,7 @@ class _TaskPanel(object): self._paramWidget = FreeCADGui.PySideUic.loadUi( FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/FlowVelocity.ui" ) - self._initParamWidget() - + # geometry selection widget # start with Solid in list! self._selectionWidget = selection_widgets.GeometryElementsSelection( @@ -70,6 +70,96 @@ class _TaskPanel(object): self._partVisible = None self._meshVisible = None + # connect unspecified option + QtCore.QObject.connect( + self._paramWidget.velocityXBox, + QtCore.SIGNAL("toggled(bool)"), + self._velocityXEnable + ) + QtCore.QObject.connect( + self._paramWidget.velocityYBox, + QtCore.SIGNAL("toggled(bool)"), + self._velocityYEnable + ) + QtCore.QObject.connect( + self._paramWidget.velocityZBox, + QtCore.SIGNAL("toggled(bool)"), + self._velocityZEnable + ) + + # connect formula option + QtCore.QObject.connect( + self._paramWidget.formulaXCB, + QtCore.SIGNAL("toggled(bool)"), + self._formulaXEnable + ) + QtCore.QObject.connect( + self._paramWidget.formulaYCB, + QtCore.SIGNAL("toggled(bool)"), + self._formulaYEnable + ) + QtCore.QObject.connect( + self._paramWidget.formulaZCB, + QtCore.SIGNAL("toggled(bool)"), + self._formulaZEnable + ) + + self._initParamWidget() + + def _velocityXEnable(self, toggled): + if toggled: + self._paramWidget.formulaX.setDisabled(toggled) + self._paramWidget.velocityX.setDisabled(toggled) + else: + if self._paramWidget.formulaXCB.isChecked(): + self._paramWidget.formulaX.setDisabled(toggled) + else: + self._paramWidget.velocityX.setDisabled(toggled) + + def _velocityYEnable(self, toggled): + if toggled: + self._paramWidget.formulaY.setDisabled(toggled) + self._paramWidget.velocityY.setDisabled(toggled) + else: + if self._paramWidget.formulaYCB.isChecked(): + self._paramWidget.formulaY.setDisabled(toggled) + else: + self._paramWidget.velocityY.setDisabled(toggled) + + def _velocityZEnable(self, toggled): + if toggled: + self._paramWidget.formulaZ.setDisabled(toggled) + self._paramWidget.velocityZ.setDisabled(toggled) + else: + if self._paramWidget.formulaZCB.isChecked(): + self._paramWidget.formulaZ.setDisabled(toggled) + else: + self._paramWidget.velocityZ.setDisabled(toggled) + + def _formulaXEnable(self, toggled): + FreeCAD.Console.PrintMessage("_formulaXEnable\n") + if self._paramWidget.velocityXBox.isChecked(): + FreeCAD.Console.PrintMessage("velocityXBox isChecked\n") + return + else: + FreeCAD.Console.PrintMessage("velocityXBox not checked\n") + self._paramWidget.formulaX.setEnabled(toggled) + self._paramWidget.velocityX.setDisabled(toggled) + + def _formulaYEnable(self, toggled): + if self._paramWidget.velocityYBox.isChecked(): + return + else: + self._paramWidget.formulaY.setEnabled(toggled) + self._paramWidget.velocityY.setDisabled(toggled) + + def _formulaZEnable(self, toggled): + if self._paramWidget.velocitZXBox.isChecked(): + return + else: + self._paramWidget.formulaZ.setEnabled(toggled) + self._paramWidget.velocityZ.setDisabled(toggled) + def open(self): if self._mesh is not None and self._part is not None: self._meshVisible = self._mesh.ViewObject.isVisible() @@ -104,36 +194,80 @@ class _TaskPanel(object): def _initParamWidget(self): unit = "m/s" - self._paramWidget.velocityXTxt.setText( - str(self._obj.VelocityX) + unit) - self._paramWidget.velocityYTxt.setText( - str(self._obj.VelocityY) + unit) - self._paramWidget.velocityZTxt.setText( - str(self._obj.VelocityZ) + unit) + self._paramWidget.velocityX.setProperty('unit', unit) + self._paramWidget.velocityY.setProperty('unit', unit) + self._paramWidget.velocityZ.setProperty('unit', unit) + + self._paramWidget.velocityX.setProperty( + 'value', self._obj.VelocityX) + FreeCADGui.ExpressionBinding( + self._paramWidget.velocityX).bind(self._obj, "VelocityX") self._paramWidget.velocityXBox.setChecked( - not self._obj.VelocityXEnabled) + self._obj.VelocityXUnspecified) + self._paramWidget.formulaX.setText(self._obj.VelocityXFormula) + self._paramWidget.formulaXCB.setChecked( + self._obj.VelocityXHasFormula) + + self._paramWidget.velocityY.setProperty( + 'value', self._obj.VelocityY) + FreeCADGui.ExpressionBinding( + self._paramWidget.velocityY).bind(self._obj, "VelocityY") self._paramWidget.velocityYBox.setChecked( - not self._obj.VelocityYEnabled) + self._obj.VelocityYUnspecified) + self._paramWidget.formulaY.setText(self._obj.VelocityYFormula) + self._paramWidget.formulaYCB.setChecked( + self._obj.VelocityYHasFormula) + + self._paramWidget.velocityZ.setProperty( + 'value', self._obj.VelocityZ) + FreeCADGui.ExpressionBinding( + self._paramWidget.velocityZ).bind(self._obj, "VelocityZ") self._paramWidget.velocityZBox.setChecked( - not self._obj.VelocityZEnabled) + self._obj.VelocityZUnspecified) + self._paramWidget.formulaZ.setText(self._obj.VelocityZFormula) + self._paramWidget.formulaZCB.setChecked( + self._obj.VelocityZHasFormula) + self._paramWidget.normalBox.setChecked( self._obj.NormalToBoundary) + def _applyVelocityChanges(self, enabledBox, velocityQSB): + enabled = enabledBox.isChecked() + velocity = None + try: + velocity = velocityQSB.property('value') + except ValueError: + FreeCAD.Console.PrintMessage( + "Wrong input. Not recognised input: '{}' " + "Velocity has not been set.\n".format(velocityQSB.text()) + ) + velocity = '0.0 m/s' + return enabled, velocity + def _applyWidgetChanges(self): - unit = "m/s" - self._obj.VelocityXEnabled = \ - not self._paramWidget.velocityXBox.isChecked() - if self._obj.VelocityXEnabled: - quantity = Units.Quantity(self._paramWidget.velocityXTxt.text()) - self._obj.VelocityX = quantity.getValueAs(unit).Value - self._obj.VelocityYEnabled = \ - not self._paramWidget.velocityYBox.isChecked() - if self._obj.VelocityYEnabled: - quantity = Units.Quantity(self._paramWidget.velocityYTxt.text()) - self._obj.VelocityY = quantity.getValueAs(unit).Value - self._obj.VelocityZEnabled = \ - not self._paramWidget.velocityZBox.isChecked() - if self._obj.VelocityZEnabled: - quantity = Units.Quantity(self._paramWidget.velocityZTxt.text()) - self._obj.VelocityZ = quantity.getValueAs(unit).Value + # apply the velocities and their enabled state + self._obj.VelocityXUnspecified, self._obj.VelocityX = \ + self._applyVelocityChanges( + self._paramWidget.velocityXBox, + self._paramWidget.velocityX + ) + self._obj.VelocityXHasFormula = self._paramWidget.formulaXCB.isChecked() + self._obj.VelocityXFormula = self._paramWidget.formulaX.text() + + self._obj.VelocityYUnspecified, self._obj.VelocityY = \ + self._applyVelocityChanges( + self._paramWidget.velocityYBox, + self._paramWidget.velocityY + ) + self._obj.VelocityYHasFormula = self._paramWidget.formulaYCB.isChecked() + self._obj.VelocityYFormula = self._paramWidget.formulaY.text() + + self._obj.VelocityZUnspecified, self._obj.VelocityZ = \ + self._applyVelocityChanges( + self._paramWidget.velocityZBox, + self._paramWidget.velocityZ + ) + self._obj.VelocityZHasFormula = self._paramWidget.formulaZCB.isChecked() + self._obj.VelocityZFormula = self._paramWidget.formulaZ.text() + self._obj.NormalToBoundary = self._paramWidget.normalBox.isChecked()