From ddfdce612ec632c98734806916ed7f889fb4ba03 Mon Sep 17 00:00:00 2001 From: Uwe Date: Mon, 6 Feb 2023 05:32:02 +0100 Subject: [PATCH] [FEM] Elmer: extent potential constraint - it is now possible to specify a an electric potential vector field --- .../Resources/ui/ElectrostaticPotential.ui | 580 +++++++++++++++++- .../constraint_electrostaticpotential.py | 117 +++- .../task_constraint_electrostaticpotential.py | 144 ++++- 3 files changed, 816 insertions(+), 25 deletions(-) diff --git a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui index a611733367..ca783344d6 100644 --- a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui +++ b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui @@ -6,15 +6,15 @@ 0 0 - 350 - 137 + 317 + 303 Constraint Properties - - + + @@ -48,7 +48,7 @@ - Electric potential in V + Electric potential true @@ -82,7 +82,441 @@ - + + + + To define a vector field + + + Vector Field + + + + + + + true + + + Imaginary part is only used for equations +with a harmonic/oscillating driving force + + + false + + + false + + + + + + true + + + Real + + + + + + + true + + + Imaginary + + + + + + + true + + + Scalar + + + + + + + false + + + + 100 + 20 + + + + Potential as specified above + + + true + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + + 100 + 20 + + + + Imaginary part of scalar potential + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + x + + + + + + + true + + + + 100 + 20 + + + + Real part of potential x-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + + 100 + 20 + + + + Imaginary part of potential x-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + y + + + + + + + true + + + + 100 + 20 + + + + Real part of potential y-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + + 100 + 20 + + + + Imaginary part of potential y-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + z + + + + + + + true + + + + 100 + 20 + + + + Real part of potential z-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + true + + + + 100 + 20 + + + + Imaginary part of potential z-component + + + true + + + V + + + -1000000000000000000000.000000000000000 + + + 1000000000000000000000.000000000000000 + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + unspecified + + + + + + + + + + Whether the constraint defines a constant potential @@ -92,7 +526,7 @@ - + true @@ -105,7 +539,7 @@ - + Whether the constraint is for the electric force @@ -115,7 +549,7 @@ - + @@ -211,5 +645,133 @@ + + potentialQSB + valueChanged(Base::Quantity) + realScalarQSB + setValue(Base::Quantity) + + + 126 + 19 + + + 103 + 98 + + + + + reZunspecBox + toggled(bool) + realZQSB + setDisabled(bool) + + + 179 + 178 + + + 103 + 176 + + + + + reYunspecBox + toggled(bool) + realYQSB + setDisabled(bool) + + + 179 + 148 + + + 103 + 150 + + + + + imXunspecBox + toggled(bool) + imagXQSB + setDisabled(bool) + + + 339 + 128 + + + 258 + 127 + + + + + reXunspecBox + toggled(bool) + realXQSB + setDisabled(bool) + + + 179 + 128 + + + 103 + 124 + + + + + imZunspecBox + toggled(bool) + imagZQSB + setDisabled(bool) + + + 339 + 178 + + + 258 + 179 + + + + + imYunspecBox + toggled(bool) + imagYQSB + setDisabled(bool) + + + 339 + 148 + + + 258 + 153 + + + + + imScalarunspecBox + toggled(bool) + imagScalarQSB + setDisabled(bool) + + + 339 + 98 + + + 258 + 101 + + + diff --git a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py index 33635621a7..806c2d6c16 100644 --- a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2017 Markus Hovorka * # * Copyright (c) 2020 Bernd Hahnebach * +# * Copyright (c) 2023 Uwe Stöhr * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -23,7 +24,7 @@ # *************************************************************************** __title__ = "FreeCAD FEM constraint electrostatic potential document object" -__author__ = "Markus Hovorka, Bernd Hahnebach" +__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr" __url__ = "https://www.freecadweb.org" ## @package constraint_electrostaticpotential @@ -56,6 +57,64 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject) # and the constraint holds usually Volts obj.Potential = "1 V" + if not hasattr(obj, "AV_re_1"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_re_1", + "Vector Potential", + "Real part of potential x-component" + ) + obj.AV_re_1 = "0 V" + if not hasattr(obj, "AV_re_2"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_re_2", + "Vector Potential", + "Real part of potential y-component" + ) + obj.AV_re_2 = "0 V" + if not hasattr(obj, "AV_re_3"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_re_3", + "Vector Potential", + "Real part of potential z-component" + ) + obj.AV_re_3 = "0 V" + if not hasattr(obj, "AV_im"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_im", + "Vector Potential", + "Imaginary part of scalar potential" + ) + obj.AV_im = "0 V" + if not hasattr(obj, "AV_im_1"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_im_1", + "Vector Potential", + "Imaginary part of potential x-component" + ) + obj.AV_im_1 = "0 V" + if not hasattr(obj, "AV_im_2"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_im_2", + "Vector Potential", + "Imaginary part of potential y-component" + ) + obj.AV_im_2 = "0 V" + if not hasattr(obj, "AV_im_3"): + obj.addProperty( + "App::PropertyElectricPotential", + "AV_im_3", + "Vector Potential", + "Imaginary part of potential z-component" + ) + obj.AV_im_3 = "0 V" + + # now the enable bools if not hasattr(obj, "PotentialEnabled"): obj.addProperty( "App::PropertyBool", @@ -64,6 +123,62 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject) "Potential Enabled" ) obj.PotentialEnabled = True + if not hasattr(obj, "AV_re_1_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_re_1_Disabled", + "Vector Potential", + "" + ) + obj.AV_re_1_Disabled = True + if not hasattr(obj, "AV_re_2_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_re_2_Disabled", + "Vector Potential", + "" + ) + obj.AV_re_2_Disabled = True + if not hasattr(obj, "AV_re_3_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_re_3_Disabled", + "Vector Potential", + "" + ) + obj.AV_re_3_Disabled = True + if not hasattr(obj, "AV_im_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_im_Disabled", + "Vector Potential", + "" + ) + obj.AV_im_Disabled = True + if not hasattr(obj, "AV_im_1_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_im_1_Disabled", + "Vector Potential", + "" + ) + obj.AV_im_1_Disabled = True + if not hasattr(obj, "AV_im_2_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_im_2_Disabled", + "Vector Potential", + "" + ) + obj.AV_im_2_Disabled = True + if not hasattr(obj, "AV_im_3_Disabled"): + obj.addProperty( + "App::PropertyBool", + "AV_im_3_Disabled", + "Vector Potential", + "" + ) + obj.AV_im_3_Disabled = True if not hasattr(obj, "PotentialConstant"): obj.addProperty( diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py index 27d13abc17..6418c6733b 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py @@ -1,6 +1,7 @@ # *************************************************************************** # * Copyright (c) 2017 Markus Hovorka * # * Copyright (c) 2020 Bernd Hahnebach * +# * Copyright (c) 2023 Uwe Stöhr * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -23,13 +24,15 @@ # *************************************************************************** __title__ = "FreeCAD FEM constraint electrostatic potential task panel for the document object" -__author__ = "Markus Hovorka, Bernd Hahnebach" +__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr" __url__ = "https://www.freecadweb.org" ## @package task_constraint_electrostaticpotential # \ingroup FEM # \brief task panel for constraint electrostatic potential object +from PySide import QtCore + import FreeCAD import FreeCADGui from femguiutils import selection_widgets @@ -69,6 +72,24 @@ class _TaskPanel(object): self._partVisible = None self._meshVisible = None + # start with vector inputs hidden if no vector is set + if self._obj.AV_re_1_Disabled and \ + self._obj.AV_re_2_Disabled and \ + self._obj.AV_re_3_Disabled and \ + self._obj.AV_im_Disabled and \ + self._obj.AV_im_1_Disabled and \ + self._obj.AV_im_2_Disabled and \ + self._obj.AV_im_3_Disabled: + self._vectorField_visibility(False) + QtCore.QObject.connect( + self._paramWidget.vectorFieldBox, + QtCore.SIGNAL("toggled(bool)"), + self._vectorField_visibility + ) + + def _vectorField_visibility(self, visible): + self._paramWidget.vectorFieldGB.setVisible(visible) + def open(self): if self._mesh is not None and self._part is not None: self._meshVisible = self._mesh.ViewObject.isVisible() @@ -108,6 +129,57 @@ class _TaskPanel(object): self._paramWidget.potentialQSB).bind(self._obj, "Potential") self._paramWidget.potentialBox.setChecked( not self._obj.PotentialEnabled) + + # the vector potentials + # realScalarQSB always the same value as potentialQSB + self._paramWidget.realScalarQSB.setProperty( + 'value', self._obj.Potential) + FreeCADGui.ExpressionBinding( + self._paramWidget.realScalarQSB).bind(self._obj, "Potential") + self._paramWidget.realXQSB.setProperty( + 'value', self._obj.AV_re_1) + FreeCADGui.ExpressionBinding( + self._paramWidget.realXQSB).bind(self._obj, "AV_re_1") + self._paramWidget.realYQSB.setProperty( + 'value', self._obj.AV_re_2) + FreeCADGui.ExpressionBinding( + self._paramWidget.realYQSB).bind(self._obj, "AV_re_2") + self._paramWidget.realZQSB.setProperty( + 'value', self._obj.AV_re_3) + FreeCADGui.ExpressionBinding( + self._paramWidget.realZQSB).bind(self._obj, "AV_re_3") + self._paramWidget.imagScalarQSB.setProperty( + 'value', self._obj.AV_im) + FreeCADGui.ExpressionBinding( + self._paramWidget.imagScalarQSB).bind(self._obj, "AV_im") + self._paramWidget.imagXQSB.setProperty( + 'value', self._obj.AV_im_1) + FreeCADGui.ExpressionBinding( + self._paramWidget.imagXQSB).bind(self._obj, "AV_im_1") + self._paramWidget.imagYQSB.setProperty( + 'value', self._obj.AV_im_2) + FreeCADGui.ExpressionBinding( + self._paramWidget.imagYQSB).bind(self._obj, "AV_im_2") + self._paramWidget.imagZQSB.setProperty( + 'value', self._obj.AV_im_3) + FreeCADGui.ExpressionBinding( + self._paramWidget.imagZQSB).bind(self._obj, "AV_im_3") + + self._paramWidget.reXunspecBox.setChecked( + self._obj.AV_re_1_Disabled) + self._paramWidget.reYunspecBox.setChecked( + self._obj.AV_re_2_Disabled) + self._paramWidget.reZunspecBox.setChecked( + self._obj.AV_re_3_Disabled) + self._paramWidget.imScalarunspecBox.setChecked( + self._obj.AV_im_Disabled) + self._paramWidget.imXunspecBox.setChecked( + self._obj.AV_im_1_Disabled) + self._paramWidget.imYunspecBox.setChecked( + self._obj.AV_im_2_Disabled) + self._paramWidget.imZunspecBox.setChecked( + self._obj.AV_im_3_Disabled) + self._paramWidget.potentialConstantBox.setChecked( self._obj.PotentialConstant) @@ -124,21 +196,63 @@ class _TaskPanel(object): self._paramWidget.capacitanceBody_spinBox.setEnabled( not self._paramWidget.capacitanceBodyBox.isChecked()) + def _applyPotentialChanges(self, enabledBox, potentialQSB): + enabled = enabledBox.isChecked() + potential = None + try: + potential = potentialQSB.property('value') + except ValueError: + FreeCAD.Console.PrintMessage( + "Wrong input. Not recognised input: '{}' " + "Potential has not been set.\n".format(potentialQSB.text()) + ) + potential = '0.0 mm^2*kg/(s^3*A)' + return enabled, potential + def _applyWidgetChanges(self): - self._obj.PotentialEnabled = \ - not self._paramWidget.potentialBox.isChecked() - if self._obj.PotentialEnabled: - potential = None - try: - potential = self._paramWidget.potentialQSB.property('value') - except ValueError: - FreeCAD.Console.PrintMessage( - "Wrong input. Not recognised input: '{}' " - "Potential has not been set.\n" - .format(self._paramWidget.potentialQSB.text()) - ) - if potential is not None: - self._obj.Potential = potential + # apply the voltages and their enabled state + self._obj.PotentialEnabled, self._obj.Potential = \ + self._applyPotentialChanges( + self._paramWidget.potentialBox, + self._paramWidget.potentialQSB + ) + self._obj.AV_re_1_Disabled, self._obj.AV_re_1 = \ + self._applyPotentialChanges( + self._paramWidget.reXunspecBox, + self._paramWidget.realXQSB + ) + self._obj.AV_re_2_Disabled, self._obj.AV_re_2 = \ + self._applyPotentialChanges( + self._paramWidget.reYunspecBox, + self._paramWidget.realYQSB + ) + self._obj.AV_re_3_Disabled, self._obj.AV_re_3 = \ + self._applyPotentialChanges( + self._paramWidget.reZunspecBox, + self._paramWidget.realZQSB + ) + self._obj.AV_im_Disabled, self._obj.AV_im = \ + self._applyPotentialChanges( + self._paramWidget.imScalarunspecBox, + self._paramWidget.imagScalarQSB + ) + self._obj.AV_im_1_Disabled, self._obj.AV_im_1 = \ + self._applyPotentialChanges( + self._paramWidget.imXunspecBox, + self._paramWidget.imagXQSB + ) + self._obj.AV_im_2_Disabled, self._obj.AV_im_2 = \ + self._applyPotentialChanges( + self._paramWidget.imYunspecBox, + self._paramWidget.imagYQSB + ) + self._obj.AV_im_3_Disabled, self._obj.AV_im_3 = \ + self._applyPotentialChanges( + self._paramWidget.imZunspecBox, + self._paramWidget.imagZQSB + ) + # because this is an enable the others are disabled, reverse + self._obj.PotentialEnabled = not self._obj.PotentialEnabled self._obj.PotentialConstant = self._paramWidget.potentialConstantBox.isChecked()