diff --git a/src/App/Application.cpp b/src/App/Application.cpp index 1120475074..6ab625095d 100644 --- a/src/App/Application.cpp +++ b/src/App/Application.cpp @@ -2061,6 +2061,7 @@ void Application::initTypes() App::PropertyElectricalInductance ::init(); App::PropertyElectricalResistance ::init(); App::PropertyElectricCharge ::init(); + App::PropertySurfaceChargeDensity ::init(); App::PropertyElectricCurrent ::init(); App::PropertyElectricPotential ::init(); App::PropertyElectromagneticPotential ::init(); diff --git a/src/App/PropertyUnits.cpp b/src/App/PropertyUnits.cpp index b18ea6b65f..b4ed219cd9 100644 --- a/src/App/PropertyUnits.cpp +++ b/src/App/PropertyUnits.cpp @@ -392,6 +392,17 @@ PropertyElectricCharge::PropertyElectricCharge() setUnit(Base::Unit::ElectricCharge); } +//************************************************************************** +// PropertySurfaceChargeDensity +//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + +TYPESYSTEM_SOURCE(App::PropertySurfaceChargeDensity, App::PropertyQuantity) + +PropertySurfaceChargeDensity::PropertySurfaceChargeDensity() +{ + setUnit(Base::Unit::SurfaceChargeDensity); +} + //************************************************************************** // PropertyElectricCurrent //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/src/App/PropertyUnits.h b/src/App/PropertyUnits.h index 8a19ead0ce..e81a8fd9c3 100644 --- a/src/App/PropertyUnits.h +++ b/src/App/PropertyUnits.h @@ -361,6 +361,19 @@ public: ~PropertyElectricCharge() override = default; }; +/** SurfaceChargeDensity property + * This is a property for representing surface charge density. It is basically a float + * property. On the Gui it has a quantity like C/m^2. + */ +class AppExport PropertySurfaceChargeDensity: public PropertyQuantity +{ + TYPESYSTEM_HEADER_WITH_OVERRIDE(); + +public: + PropertySurfaceChargeDensity(); + ~PropertySurfaceChargeDensity() override = default; +}; + /** ElectricCurrent property * This is a property for representing electric currents. It is basically a * float property. On the Gui it has a quantity like A. diff --git a/src/Base/Unit.cpp b/src/Base/Unit.cpp index a3c2a12c87..6aaa117af1 100644 --- a/src/Base/Unit.cpp +++ b/src/Base/Unit.cpp @@ -587,7 +587,7 @@ std::string Unit::getString() const std::string Unit::getTypeString() const { - static std::array, 55> unitSpecs {{ + static std::array, 56> unitSpecs {{ { Unit::Acceleration, "Acceleration" }, { Unit::AmountOfSubstance, "AmountOfSubstance" }, { Unit::Angle, "Angle" }, @@ -603,6 +603,7 @@ std::string Unit::getTypeString() const { Unit::ElectricalInductance, "ElectricalInductance" }, { Unit::ElectricalResistance, "ElectricalResistance" }, { Unit::ElectricCharge, "ElectricCharge" }, + { Unit::SurfaceChargeDensity, "SurfaceChargeDensity" }, { Unit::ElectricCurrent, "ElectricCurrent" }, { Unit::ElectricPotential, "ElectricPotential" }, { Unit::ElectromagneticPotential, "ElectromagneticPotential" }, @@ -681,6 +682,7 @@ const Unit Unit::ElectricalConductivity (-3, -1, 3, 2); const Unit Unit::ElectricalInductance (2, 1, -2, -2); const Unit Unit::ElectricalResistance (2, 1, -3, -2); const Unit Unit::ElectricCharge (0, 0, 1, 1); +const Unit Unit::SurfaceChargeDensity (-2, 0, 1, 1); const Unit Unit::ElectricPotential (2, 1, -3, -1); const Unit Unit::ElectromagneticPotential (1, 1, -2, -1); const Unit Unit::Force (1, 1, -2); diff --git a/src/Base/Unit.h b/src/Base/Unit.h index 670cf67526..b47d5c26ae 100644 --- a/src/Base/Unit.h +++ b/src/Base/Unit.h @@ -110,6 +110,7 @@ public: static const Unit ElectricCurrent; static const Unit ElectricPotential; static const Unit ElectricCharge; + static const Unit SurfaceChargeDensity; static const Unit MagneticFieldStrength; static const Unit MagneticFlux; static const Unit MagneticFluxDensity; diff --git a/src/Base/UnitsSchemaInternal.cpp b/src/Base/UnitsSchemaInternal.cpp index 63e543d205..1d67455bab 100644 --- a/src/Base/UnitsSchemaInternal.cpp +++ b/src/Base/UnitsSchemaInternal.cpp @@ -364,6 +364,10 @@ UnitsSchemaInternal::schemaTranslate(const Quantity& quant, double& factor, std: unitString = "C"; factor = 1.0; } + else if (unit == Unit::SurfaceChargeDensity) { + unitString = "C/m^2"; + factor = 1e-6; + } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { unitString = "A/m^2"; diff --git a/src/Base/UnitsSchemaMKS.cpp b/src/Base/UnitsSchemaMKS.cpp index 98ef0545eb..241e3eba9b 100644 --- a/src/Base/UnitsSchemaMKS.cpp +++ b/src/Base/UnitsSchemaMKS.cpp @@ -312,6 +312,10 @@ UnitsSchemaMKS::schemaTranslate(const Quantity& quant, double& factor, std::stri unitString = "C"; factor = 1.0; } + else if (unit == Unit::SurfaceChargeDensity) { + unitString = "C/m^2"; + factor = 1e-6; + } else if (unit == Unit::CurrentDensity) { if (UnitValue <= 1e3) { unitString = "A/m^2"; diff --git a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui index 0e0338008c..3956a7e83d 100644 --- a/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui +++ b/src/Mod/Fem/Gui/Resources/ui/ElectrostaticPotential.ui @@ -6,519 +6,427 @@ 0 0 - 317 - 303 + 357 + 593 Analysis feature properties - + - - - - - Potential: - - - - - - - Qt::Horizontal - - - - 20 - 20 - - - - - - - - false - - - - 100 - 20 - - - - Electric potential - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - true - - - - - - - - - To define a vector field - - - Vector Field - - - true + + + + + + + + Boundary Condition: + + + + + + + - - - - true - - - Imaginary part is only used for equations -with a harmonic/oscillating driving force + + + + Dirichlet 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 -Note: has no effect if a solid was selected - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - - - - - - - - true - - - - 100 - 20 - - - - Imaginary part of potential x-component -Note: has no effect if a solid was selected - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - - - + + + + + + + Potential: + + + + + + + false + + + Electric potential + + + true + + + V + + + 1.000000000000000 + + + 1.000000000000000 + + + + - - - true + + + To define scalar potential and magnetic vector potential - y + Electromagnetic Potential - - - - - + true - - - 100 - 20 - - - - Real part of potential y-component -Note: has no effect if a solid was selected - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - - - - - - - - true - - - - 100 - 20 - - - - Imaginary part of potential y-component -Note: has no effect if a solid was selected - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - - - + + + + true + + Imaginary part is only used for equations +with a harmonic/oscillating driving force + + + false + + + + + + true + + + Real + + + + + + + true + + + Imaginary + + + + + + + true + + + Scalar + + + + + + + + + + + + + + true + + + Real part of scalar potential + + + true + + + V + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + Imaginary part of scalar potential + + + true + + + V + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + x + + + + + + + + + + + + + + true + + + Real part of vector potential x-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + Imaginary part of vector potential x-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + y + + + + + + + + + + + + + + true + + + Real part of vector potential y-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + Imaginary part of vector potential y-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + z + + + + + + + + + + + + + + true + + + Real part of vector potential z-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + true + + + Imaginary part of vector potential z-component +Note: has no effect if a solid was selected + + + true + + + Wb/m + + + 1.000000000000000 + + + 1.000000000000000 + + + + + + + + + + + + true + + + Whether the boundary condition defines a farfield potential + + + Electric Infinity + + + + + + + Whether the boundary condition defines a constant potential + + + Potential Constant + + + + + + + + + + + + Neumann + + + + - z + Surface Charge Density: - - - - true - - - - 100 - 20 - - + + - Real part of potential z-component -Note: has no effect if a solid was selected - - - true + Surface charge density - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - - - - - - - - true - - - - 100 - 20 - - - - Imaginary part of potential z-component -Note: has no effect if a solid was selected - - - true - - - V - - - -1000000000000000000000.000000000000000 - - - 1000000000000000000000.000000000000000 - - - 1.000000000000000 - - - 1.000000000000000 - - - - - - - unspecified - - - + C/m^2 @@ -526,91 +434,40 @@ Note: has no effect if a solid was selected - - - Whether the boundary condition defines a constant potential - - - Potential Constant + + + Capacitance + + + + + Capacitance Body: + + + Enabled by 'Calculate Capacity Matrix' in Electrostatic equation + + + + + + + Counter of the body (or face) with a capacitance + + + false + + + 1 + + + 1 + + + + - - - - true - - - Whether the boundary condition defines a farfield potential - - - Farfield / Electric infinity - - - - - - - Whether the boundary condition is for the electric force - - - Calculate Electric Force - - - - - - - - - Capacity Body: - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - unspecified - - - true - - - - - - - - 55 - 16777215 - - - - Counter of the body (or face) with a capacitance - - - 1 - - - 1 - - - - - @@ -619,168 +476,11 @@ Note: has no effect if a solid was selected QWidget
Gui/QuantitySpinBox.h
+ + Gui::IntSpinBox + QWidget +
Gui/SpinBox.h
+
- - - capacitanceBodyBox - toggled(bool) - capacitanceBody_spinBox - setDisabled(bool) - - - 262 - 116 - - - 323 - 116 - - - - - potentialBox - toggled(bool) - potentialQSB - setDisabled(bool) - - - 301 - 19 - - - 206 - 19 - - - - - 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/femexamples/equation_magnetodynamics_elmer.py b/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py index fa56c42130..bd5778f875 100644 --- a/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py +++ b/src/Mod/Fem/femexamples/equation_magnetodynamics_elmer.py @@ -164,30 +164,28 @@ def setup(doc=None, solvertype="elmer"): (BooleanFragments, "Face6"), ] AxialField.PotentialEnabled = False - AxialField.AV_im_1_Disabled = False - AxialField.AV_im_2_Disabled = False - AxialField.AV_re_1_Disabled = False - AxialField.AV_re_2_Disabled = False + AxialField.EnableAV_1 = True + AxialField.EnableAV_2 = True analysis.addObject(AxialField) # voltage on one end Voltage = ObjectsFem.makeConstraintElectrostaticPotential(doc, "Voltage") Voltage.References = [(BooleanFragments, "Face3")] - Voltage.Potential = "10.000 mV" - Voltage.AV_im_1_Disabled = False - Voltage.AV_im_2_Disabled = False - Voltage.AV_re_1_Disabled = False - Voltage.AV_re_2_Disabled = False + Voltage.AV_re = "10.000 mV" + Voltage.AV_im = "0 V" + Voltage.EnableAV = True + Voltage.EnableAV_1 = True + Voltage.EnableAV_2 = True analysis.addObject(Voltage) # ground on other end Ground = ObjectsFem.makeConstraintElectrostaticPotential(doc, "Ground") Ground.References = [(BooleanFragments, "Face2")] - Ground.Potential = "0 V" - Ground.AV_im_1_Disabled = False - Ground.AV_im_2_Disabled = False - Ground.AV_re_1_Disabled = False - Ground.AV_re_2_Disabled = False + Ground.AV_re = "0 V" + Ground.AV_im = "0 V" + Ground.EnableAV = True + Ground.EnableAV_1 = True + Ground.EnableAV_2 = True analysis.addObject(Ground) # magnetization diff --git a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py index e3e9554531..50ac56a951 100644 --- a/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femobjects/constraint_electrostaticpotential.py @@ -2,6 +2,7 @@ # * Copyright (c) 2017 Markus Hovorka * # * Copyright (c) 2020 Bernd Hahnebach * # * Copyright (c) 2023 Uwe Stöhr * +# * Copyright (c) 2024 Mario Passaglia * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -24,15 +25,19 @@ # *************************************************************************** __title__ = "FreeCAD FEM constraint electrostatic potential document object" -__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr" +__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr, Mario Passaglia" __url__ = "https://www.freecad.org" ## @package constraint_electrostaticpotential # \ingroup FEM # \brief constraint electrostatic potential object +from FreeCAD import Base + from . import base_fempythonobject +_PropHelper = base_fempythonobject._PropHelper + class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject): @@ -40,158 +45,257 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject) def __init__(self, obj): super().__init__(obj) - self.add_properties(obj) + + for prop in self._get_properties(): + prop.add_to_object(obj) + + def _get_properties(self): + prop = [] + + prop.append( + _PropHelper( + type="App::PropertyElectricPotential", + name="Potential", + group="Parameter", + doc="Electric Potential", + value="1 V", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="PotentialEnabled", + group="Parameter", + doc="Enable electric potential", + value=True, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectricPotential", + name="AV_re", + group="Electromagnetic Potential", + doc="Real part of scalar potential", + value="0 V", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectricPotential", + name="AV_im", + group="Electromagnetic Potential", + doc="Imaginary part of scalar potential", + value="0 V", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_re_1", + group="Electromagnetic Potential", + doc="Real part of vector potential x-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_re_2", + group="Electromagnetic Potential", + doc="Real part of vector potential y-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_re_3", + group="Electromagnetic Potential", + doc="Real part of vector potential z-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_im_1", + group="Electromagnetic Potential", + doc="Imaginary part of vector potential x-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_im_2", + group="Electromagnetic Potential", + doc="Imaginary part of vector potential y-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectromagneticPotential", + name="AV_im_3", + group="Electromagnetic Potential", + doc="Imaginary part of vector potential z-component", + value="0 Wb/m", + ) + ) + prop.append( + _PropHelper( + type="App::PropertySurfaceChargeDensity", + name="SurfaceChargeDensity", + group="Parameter", + doc="Free surface charge density", + value="0 C/m^2", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="BoundaryCondition", + group="Parameter", + doc="Set boundary condition type", + value=["Dirichlet", "Neumann"], + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="EnableAV", + group="Electromagnetic Potential", + doc="Enable scalar potential boundary condition", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="EnableAV_1", + group="Electromagnetic Potential", + doc="Enable vector potential x-component boundary condition", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="EnableAV_2", + group="Electromagnetic Potential", + doc="Enable vector potential y-component boundary condition", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="EnableAV_3", + group="Electromagnetic Potential", + doc="Enable vector potential z-component boundary condition", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="PotentialConstant", + group="Parameter", + doc="", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="ElectricInfinity", + group="Parameter", + doc="Electric Infinity", + value=False, + ) + ) + + prop.append( + _PropHelper( + type="App::PropertyBool", + name="ElectricForcecalculation", + group="Parameter", + doc="Electric force calculation", + value=False, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyInteger", + name="CapacitanceBody", + group="Parameter", + doc="Capacitance body", + value=0, + ) + ) + prop.append( + _PropHelper( + type="App::PropertyBool", + name="CapacitanceBodyEnabled", + group="Parameter", + doc="Capacitance body enabled", + value=False, + ) + ) + + return prop def onDocumentRestored(self, obj): - self.add_properties(obj) + # update old project with new properties + for prop in self._get_properties(): + try: + obj.getPropertyByName(prop.name) + except Base.PropertyError: + prop.add_to_object(obj) - def add_properties(self, obj): - if not hasattr(obj, "Potential"): - obj.addProperty( - "App::PropertyElectricPotential", "Potential", "Parameter", "Electric Potential" - ) - obj.setPropertyStatus("Potential", "LockDynamic") - # setting 1 V assures that the unit does not switch to mV - # and the constraint holds usually Volts - obj.Potential = "1 V" + # convert old potential float to Volt + if prop.name == "Potential": + prop.handle_change_type( + obj, + old_type="App::PropertyFloat", + convert_old_value=lambda x: "{} V".format(1e6 * x), + ) + # fix unit for magnetic vector potential properties + if prop.name in ("AV_re_1", "AV_re_2", "AV_re_3", "AV_im_1", "AV_im_2", "AV_im_3"): + prop.handle_change_type( + obj, + old_type="App::PropertyElectricPotential", + convert_old_value=lambda x: "{} Wb/m".format(x.getValueAs("V").Value), + ) - if not hasattr(obj, "AV_re_1"): - obj.addProperty( - "App::PropertyElectricPotential", - "AV_re_1", - "Vector Potential", - "Real part of potential x-component", - ) - obj.setPropertyStatus("AV_re_1", "LockDynamic") - 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.setPropertyStatus("AV_re_2", "LockDynamic") - 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.setPropertyStatus("AV_re_3", "LockDynamic") - 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.setPropertyStatus("AV_im", "LockDynamic") - 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.setPropertyStatus("AV_im_1", "LockDynamic") - 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.setPropertyStatus("AV_im_2", "LockDynamic") - 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.setPropertyStatus("AV_im_3", "LockDynamic") - obj.AV_im_3 = "0 V" + # enable electromagnetic properties from old properties + try: + obj.EnableAV_1 = not obj.getPropertyByName( + "AV_re_1_Disabled" + ) or not obj.getPropertyByName("AV_im_1_Disabled") + obj.EnableAV_2 = not obj.getPropertyByName( + "AV_re_2_Disabled" + ) or not obj.getPropertyByName("AV_im_2_Disabled") + obj.EnableAV_3 = not obj.getPropertyByName( + "AV_re_3_Disabled" + ) or not obj.getPropertyByName("AV_im_3_Disabled") + obj.EnableAV = not obj.getPropertyByName("AV_im_Disabled") - # now the enable bools - if not hasattr(obj, "PotentialEnabled"): - obj.addProperty( - "App::PropertyBool", "PotentialEnabled", "Parameter", "Potential Enabled" - ) - obj.setPropertyStatus("PotentialEnabled", "LockDynamic") - obj.PotentialEnabled = True - if not hasattr(obj, "AV_re_1_Disabled"): - obj.addProperty("App::PropertyBool", "AV_re_1_Disabled", "Vector Potential", "") - obj.setPropertyStatus("AV_re_1_Disabled", "LockDynamic") - 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.setPropertyStatus("AV_re_2_Disabled", "LockDynamic") - 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.setPropertyStatus("AV_re_3_Disabled", "LockDynamic") - obj.AV_re_3_Disabled = True - if not hasattr(obj, "AV_im_Disabled"): - obj.addProperty("App::PropertyBool", "AV_im_Disabled", "Vector Potential", "") - obj.setPropertyStatus("AV_im_Disabled", "LockDynamic") - obj.AV_im_Disabled = True - if not hasattr(obj, "AV_im_1_Disabled"): - obj.addProperty("App::PropertyBool", "AV_im_1_Disabled", "Vector Potential", "") - obj.setPropertyStatus("AV_im_1_Disabled", "LockDynamic") - 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.setPropertyStatus("AV_im_2_Disabled", "LockDynamic") - 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.setPropertyStatus("AV_im_3_Disabled", "LockDynamic") - obj.AV_im_3_Disabled = True + # remove old properties + obj.setPropertyStatus("AV_re_1_Disabled", "-LockDynamic") + obj.removeProperty("AV_re_1_Disabled") + obj.setPropertyStatus("AV_re_2_Disabled", "-LockDynamic") + obj.removeProperty("AV_re_2_Disabled") + obj.setPropertyStatus("AV_re_3_Disabled", "-LockDynamic") + obj.removeProperty("AV_re_3_Disabled") + obj.setPropertyStatus("AV_im_1_Disabled", "-LockDynamic") + obj.removeProperty("AV_im_1_Disabled") + obj.setPropertyStatus("AV_im_2_Disabled", "-LockDynamic") + obj.removeProperty("AV_im_2_Disabled") + obj.setPropertyStatus("AV_im_3_Disabled", "-LockDynamic") + obj.removeProperty("AV_im_3_Disabled") + obj.setPropertyStatus("AV_im_Disabled", "-LockDynamic") + obj.removeProperty("AV_im_Disabled") - if not hasattr(obj, "PotentialConstant"): - obj.addProperty( - "App::PropertyBool", "PotentialConstant", "Parameter", "Potential Constant" - ) - obj.setPropertyStatus("PotentialConstant", "LockDynamic") - obj.PotentialConstant = False - - if not hasattr(obj, "ElectricInfinity"): - obj.addProperty( - "App::PropertyBool", "ElectricInfinity", "Parameter", "Electric Infinity" - ) - obj.setPropertyStatus("ElectricInfinity", "LockDynamic") - obj.ElectricInfinity = False - - if not hasattr(obj, "ElectricForcecalculation"): - obj.addProperty( - "App::PropertyBool", - "ElectricForcecalculation", - "Parameter", - "Electric Force Calculation", - ) - obj.setPropertyStatus("ElectricForcecalculation", "LockDynamic") - obj.ElectricForcecalculation = False - - if not hasattr(obj, "CapacitanceBody"): - obj.addProperty( - "App::PropertyInteger", "CapacitanceBody", "Parameter", "Capacitance Body" - ) - obj.setPropertyStatus("CapacitanceBody", "LockDynamic") - obj.CapacitanceBody = 0 - - if not hasattr(obj, "CapacitanceBodyEnabled"): - obj.addProperty( - "App::PropertyBool", - "CapacitanceBodyEnabled", - "Parameter", - "Capacitance Body Enabled", - ) - obj.setPropertyStatus("CapacitanceBodyEnabled", "LockDynamic") - obj.CapacitanceBodyEnabled = False + except Base.PropertyError: + pass diff --git a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py index 5014df97ff..6ffba76461 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py @@ -125,22 +125,17 @@ class ESwriter: # output the FreeCAD label as comment if obj.Label: self.write.boundary(name, "! FreeCAD Name", obj.Label) - if obj.PotentialEnabled: - if hasattr(obj, "Potential"): - # Potential was once a float and scaled not fitting SI units - if isinstance(obj.Potential, float): - savePotential = obj.Potential - obj.removeProperty("Potential") - obj.addProperty( - "App::PropertyElectricPotential", - "Potential", - "Parameter", - "Electric Potential", - ) - # scale to match SI units - obj.Potential = savePotential * 1e6 - potential = float(obj.Potential.getValueAs("V")) - self.write.boundary(name, "Potential", potential) + if obj.BoundaryCondition == "Dirichlet": + if obj.PotentialEnabled: + self.write.boundary( + name, "Potential", obj.Potential.getValueAs("V").Value + ) + elif obj.BoundaryCondition == "Neumann": + self.write.boundary( + name, + "Surface Charge Density", + obj.SurfaceChargeDensity.getValueAs("C/m^2").Value, + ) if obj.PotentialConstant: self.write.boundary(name, "Potential Constant", True) if obj.ElectricInfinity: @@ -148,8 +143,7 @@ class ESwriter: if obj.ElectricForcecalculation: self.write.boundary(name, "Calculate Electric Force", True) if obj.CapacitanceBodyEnabled: - if hasattr(obj, "CapacitanceBody"): - self.write.boundary(name, "Capacitance Body", obj.CapacitanceBody) + self.write.boundary(name, "Capacitance Body", obj.CapacitanceBody) self.write.handled(obj) diff --git a/src/Mod/Fem/femsolver/elmer/equations/magnetodynamic_writer.py b/src/Mod/Fem/femsolver/elmer/equations/magnetodynamic_writer.py index c67ddf22ba..d0a7e759fc 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/magnetodynamic_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/magnetodynamic_writer.py @@ -31,6 +31,7 @@ __url__ = "https://www.freecad.org" from FreeCAD import Console from FreeCAD import Units +from femtools import femutils from .. import sifio from .. import writer as general_writer @@ -207,16 +208,13 @@ class MgDynwriter: magnetization = float(obj.Magnetization_im_3.getValueAs("A/m")) self.write.bodyForce(name, "Magnetization Im 3", magnetization) - if hasattr(obj, "PotentialEnabled"): - # check for PotentialEnabled not Potential since PotentialEnabled was - # added later and only with this the imaginary property is available + if femutils.is_derived_from(obj, "Fem::ConstraintElectrostaticPotential"): if obj.PotentialEnabled: # output only if potential is enabled and needed potential = float(obj.Potential.getValueAs("V")) self.write.bodyForce(name, "Electric Potential", round(potential, 6)) - # imaginary is only needed for harmonic equation - if equation.IsHarmonic: - if not obj.AV_im_Disabled: + # imaginary is only needed for harmonic equation + if equation.IsHarmonic: potential = float(obj.AV_im.getValueAs("V")) self.write.bodyForce(name, "Electric Potential Im", round(potential, 6)) @@ -289,47 +287,39 @@ class MgDynwriter: currentDensity = float(obj.CurrentDensity_im_1.getValueAs("A/m^2")) self.write.boundary(name, "Current Density Im 1", round(currentDensity, 6)) - if hasattr(obj, "PotentialEnabled"): - # check for PotentialEnabled not Potential since PotentialEnabled was - # added later and only with this the vectorial properties are available - if obj.PotentialEnabled: - potential = float(obj.Potential.getValueAs("V")) + if femutils.is_derived_from(obj, "Fem::ConstraintElectrostaticPotential"): + if obj.EnableAV: + potential = obj.AV_re.getValueAs("V").Value if equation.IsHarmonic: self.write.boundary(name, "AV re", round(potential, 6)) + potential = obj.AV_im.getValueAs("V").Value + self.write.boundary(name, "AV im", round(potential, 6)) else: self.write.boundary(name, "AV", round(potential, 6)) - if not obj.AV_re_1_Disabled: - potential = float(obj.AV_re_1.getValueAs("V")) + if obj.EnableAV_1: + potential = obj.AV_re_1.getValueAs("Wb/m").Value if equation.IsHarmonic: self.write.boundary(name, "AV re {e} 1", round(potential, 6)) + potential = obj.AV_im_1.getValueAs("Wb/m").Value + self.write.boundary(name, "AV im {e} 1", round(potential, 6)) else: self.write.boundary(name, "AV {e} 1", round(potential, 6)) - if not obj.AV_re_2_Disabled: - potential = float(obj.AV_re_2.getValueAs("V")) + if obj.EnableAV_2: + potential = obj.AV_re_2.getValueAs("Wb/m").Value if equation.IsHarmonic: self.write.boundary(name, "AV re {e} 2", round(potential, 6)) + potential = obj.AV_im_2.getValueAs("Wb/m").Value + self.write.boundary(name, "AV im {e} 2", round(potential, 6)) else: self.write.boundary(name, "AV {e} 2", round(potential, 6)) - if not obj.AV_re_3_Disabled: - potential = float(obj.AV_re_3.getValueAs("V")) + if obj.EnableAV_3: + potential = obj.AV_re_3.getValueAs("Wb/m").Value if equation.IsHarmonic: self.write.boundary(name, "AV re {e} 3", round(potential, 6)) + potential = obj.AV_im_3.getValueAs("Wb/m").Value + self.write.boundary(name, "AV im {e} 3", round(potential, 6)) else: self.write.boundary(name, "AV {e} 3", round(potential, 6)) - # imaginaries are only needed for harmonic equation - if equation.IsHarmonic: - if not obj.AV_im_Disabled: - potential = float(obj.AV_im.getValueAs("V")) - self.write.boundary(name, "AV im", round(potential, 6)) - if not obj.AV_im_1_Disabled: - potential = float(obj.AV_im_1.getValueAs("V")) - self.write.boundary(name, "AV im {e} 1", round(potential, 6)) - if not obj.AV_im_2_Disabled: - potential = float(obj.AV_im_2.getValueAs("V")) - self.write.boundary(name, "AV im {e} 2", round(potential, 6)) - if not obj.AV_im_3_Disabled: - potential = float(obj.AV_im_3.getValueAs("V")) - self.write.boundary(name, "AV im {e} 3", round(potential, 6)) def handleMagnetodynamicBndConditions(self, equation): # the current density can either be a body force or a boundary constraint diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py index da268a8b3b..3d1826e126 100644 --- a/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electrostaticpotential.py @@ -2,6 +2,7 @@ # * Copyright (c) 2017 Markus Hovorka * # * Copyright (c) 2020 Bernd Hahnebach * # * Copyright (c) 2023 Uwe Stöhr * +# * Copyright (c) 2024 Mario Passaglia * # * * # * This file is part of the FreeCAD CAx development system. * # * * @@ -24,7 +25,7 @@ # *************************************************************************** __title__ = "FreeCAD FEM constraint electrostatic potential task panel for the document object" -__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr" +__author__ = "Markus Hovorka, Bernd Hahnebach, Uwe Stöhr, André Kapelrud, Mario Passaglia" __url__ = "https://www.freecad.org" ## @package task_constraint_electrostaticpotential @@ -46,10 +47,9 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): def __init__(self, obj): super().__init__(obj) - self._paramWidget = FreeCADGui.PySideUic.loadUi( + self.parameter_widget = FreeCADGui.PySideUic.loadUi( FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElectrostaticPotential.ui" ) - self._initParamWidget() # geometry selection widget # start with Solid in list! @@ -58,7 +58,7 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): ) # form made from param and selection widget - self.form = [self._paramWidget, self._selectionWidget] + self.form = [self.parameter_widget, self._selectionWidget] analysis = obj.getParentGroup() self._mesh = None @@ -70,26 +70,113 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): 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) - self._paramWidget.vectorFieldBox.setChecked(False) QtCore.QObject.connect( - self._paramWidget.vectorFieldBox, + self.parameter_widget.ckb_electromagnetic, QtCore.SIGNAL("toggled(bool)"), - self._vectorField_visibility, + self.electromagnetic_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.cb_boundary_condition, + QtCore.SIGNAL("currentIndexChanged(int)"), + self.boundary_condition_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_potential, + QtCore.SIGNAL("toggled(bool)"), + self.potential_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_potential, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.potential_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_av, + QtCore.SIGNAL("toggled(bool)"), + self.av_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_re, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_re_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_av_1, + QtCore.SIGNAL("toggled(bool)"), + self.av_1_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_re_1, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_re_1_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_av_2, + QtCore.SIGNAL("toggled(bool)"), + self.av_2_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_re_2, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_re_2_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_av_3, + QtCore.SIGNAL("toggled(bool)"), + self.av_3_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_re_3, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_re_3_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_im, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_im_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_im_1, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_im_1_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_im_2, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_im_2_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_av_im_3, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.av_im_3_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_capacitance_body, + QtCore.SIGNAL("toggled(bool)"), + self.capacitance_body_enabled_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.spb_capacitance_body, + QtCore.SIGNAL("valueChanged(int)"), + self.capacitance_body_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_potential_constant, + QtCore.SIGNAL("toggled(bool)"), + self.potential_constant_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.ckb_electric_infinity, + QtCore.SIGNAL("toggled(bool)"), + self.electric_infinity_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_surface_charge_density, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.surface_charge_density_changed, ) - def _vectorField_visibility(self, visible): - self._paramWidget.vectorFieldGB.setVisible(visible) + self.init_parameter_widget() def open(self): if self._mesh is not None and self._part is not None: @@ -106,7 +193,7 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): def accept(self): if self.obj.References != self._selectionWidget.references: self.obj.References = self._selectionWidget.references - self._applyWidgetChanges() + self._set_params() self._selectionWidget.finish_selection() self._restoreVisibility() return super().accept() @@ -122,100 +209,202 @@ class _TaskPanel(base_femtaskpanel._BaseTaskPanel): else: self._part.ViewObject.hide() - def _initParamWidget(self): - self._paramWidget.potentialQSB.setProperty("value", self.obj.Potential) - FreeCADGui.ExpressionBinding(self._paramWidget.potentialQSB).bind(self.obj, "Potential") - self._paramWidget.potentialBox.setChecked(not self.obj.PotentialEnabled) + def _get_params(self): + self.potential = self.obj.Potential + self.potential_enabled = 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.av_re = self.obj.AV_re + self.av_re_1 = self.obj.AV_re_1 + self.av_re_2 = self.obj.AV_re_2 + self.av_re_3 = self.obj.AV_re_3 + self.av_im = self.obj.AV_im + self.av_im_1 = self.obj.AV_im_1 + self.av_im_2 = self.obj.AV_im_2 + self.av_im_3 = 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.av_enabled = self.obj.EnableAV + self.av_1_enabled = self.obj.EnableAV_1 + self.av_2_enabled = self.obj.EnableAV_2 + self.av_3_enabled = self.obj.EnableAV_3 - self._paramWidget.potentialConstantBox.setChecked(self.obj.PotentialConstant) + self.boundary_condition = self.obj.BoundaryCondition + self.potential_constant = self.obj.PotentialConstant + self.electric_infinity = self.obj.ElectricInfinity + self.capacitance_body_enabled = self.obj.CapacitanceBodyEnabled + self.capacitance_body = self.obj.CapacitanceBody + self.surface_charge_density = self.obj.SurfaceChargeDensity - self._paramWidget.electricInfinityBox.setChecked(self.obj.ElectricInfinity) + def _set_params(self): + self.obj.Potential = self.potential + self.obj.PotentialEnabled = self.potential_enabled - self._paramWidget.electricForcecalculationBox.setChecked(self.obj.ElectricForcecalculation) + self.obj.AV_re = self.av_re + self.obj.AV_re_1 = self.av_re_1 + self.obj.AV_re_2 = self.av_re_2 + self.obj.AV_re_3 = self.av_re_3 + self.obj.AV_im = self.av_im + self.obj.AV_im_1 = self.av_im_1 + self.obj.AV_im_2 = self.av_im_2 + self.obj.AV_im_3 = self.av_im_3 - self._paramWidget.capacitanceBodyBox.setChecked(not self.obj.CapacitanceBodyEnabled) - self._paramWidget.capacitanceBody_spinBox.setValue(self.obj.CapacitanceBody) - self._paramWidget.capacitanceBody_spinBox.setEnabled( - not self._paramWidget.capacitanceBodyBox.isChecked() + self.obj.EnableAV = self.av_enabled + self.obj.EnableAV_1 = self.av_1_enabled + self.obj.EnableAV_2 = self.av_2_enabled + self.obj.EnableAV_3 = self.av_3_enabled + + self.obj.BoundaryCondition = self.boundary_condition + self.obj.PotentialConstant = self.potential_constant + self.obj.ElectricInfinity = self.electric_infinity + self.obj.CapacitanceBodyEnabled = self.capacitance_body_enabled + self.obj.CapacitanceBody = self.capacitance_body + + self.obj.SurfaceChargeDensity = self.surface_charge_density + + def init_parameter_widget(self): + self._get_params() + + self.parameter_widget.qsb_potential.setProperty("value", self.potential) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_potential).bind( + self.obj, "Potential" + ) + self.parameter_widget.ckb_potential.setChecked(self.potential_enabled) + + # scalar potential + self.parameter_widget.qsb_av_re.setProperty("value", self.av_re) + self.parameter_widget.qsb_av_re.setEnabled(self.av_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_re).bind(self.obj, "AV_re") + self.parameter_widget.qsb_av_im.setProperty("value", self.av_im) + self.parameter_widget.qsb_av_im.setEnabled(self.av_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_im).bind(self.obj, "AV_im") + + # vector potential + self.parameter_widget.qsb_av_re_1.setProperty("value", self.av_re_1) + self.parameter_widget.qsb_av_re_1.setEnabled(self.av_1_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_re_1).bind(self.obj, "AV_re_1") + self.parameter_widget.qsb_av_re_2.setProperty("value", self.av_re_2) + self.parameter_widget.qsb_av_re_2.setEnabled(self.av_2_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_re_2).bind(self.obj, "AV_re_2") + self.parameter_widget.qsb_av_re_3.setProperty("value", self.av_re_3) + self.parameter_widget.qsb_av_re_3.setEnabled(self.av_3_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_re_3).bind(self.obj, "AV_re_3") + + self.parameter_widget.qsb_av_im_1.setProperty("value", self.av_im_1) + self.parameter_widget.qsb_av_im_1.setEnabled(self.av_1_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_im_1).bind(self.obj, "AV_im_1") + self.parameter_widget.qsb_av_im_2.setProperty("value", self.av_im_2) + self.parameter_widget.qsb_av_im_2.setEnabled(self.av_2_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_im_2).bind(self.obj, "AV_im_2") + self.parameter_widget.qsb_av_im_3.setProperty("value", self.av_im_3) + self.parameter_widget.qsb_av_im_3.setEnabled(self.av_3_enabled) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_av_im_3).bind(self.obj, "AV_im_3") + + self.parameter_widget.ckb_av.setChecked(self.av_enabled) + self.parameter_widget.ckb_av_1.setChecked(self.av_1_enabled) + self.parameter_widget.ckb_av_2.setChecked(self.av_2_enabled) + self.parameter_widget.ckb_av_3.setChecked(self.av_3_enabled) + + self.parameter_widget.ckb_potential_constant.setChecked(self.potential_constant) + + self.parameter_widget.ckb_electric_infinity.setChecked(self.electric_infinity) + + self.parameter_widget.ckb_capacitance_body.setChecked(self.capacitance_body_enabled) + self.parameter_widget.spb_capacitance_body.setProperty("value", self.capacitance_body) + FreeCADGui.ExpressionBinding(self.parameter_widget.spb_capacitance_body).bind( + self.obj, "CapacitanceBody" ) - 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 + self.parameter_widget.qsb_surface_charge_density.setProperty( + "value", self.surface_charge_density + ) + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_surface_charge_density).bind( + self.obj, "SurfaceChargeDensity" + ) - def _applyWidgetChanges(self): - # 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.bc_enum = self.obj.getEnumerationsOfProperty("BoundaryCondition") + index = self.bc_enum.index(self.boundary_condition) + self.parameter_widget.cb_boundary_condition.addItems(self.bc_enum) + self.parameter_widget.cb_boundary_condition.setCurrentIndex(index) - self.obj.PotentialConstant = self._paramWidget.potentialConstantBox.isChecked() + # start with electromagnetic inputs hidden if no field is set + if not (self.av_enabled or self.av_1_enabled or self.av_2_enabled or self.av_3_enabled): + self.parameter_widget.ckb_electromagnetic.setChecked(False) - self.obj.ElectricInfinity = self._paramWidget.electricInfinityBox.isChecked() + def potential_changed(self, value): + self.potential = value - calc_is_checked = self._paramWidget.electricForcecalculationBox.isChecked() - self.obj.ElectricForcecalculation = calc_is_checked # two lines because max line length + def potential_enabled_changed(self, value): + self.potential_enabled = value + self.parameter_widget.qsb_potential.setEnabled(value) - self.obj.CapacitanceBodyEnabled = not self._paramWidget.capacitanceBodyBox.isChecked() - if self.obj.CapacitanceBodyEnabled: - self._paramWidget.capacitanceBody_spinBox.setEnabled(True) - self.obj.CapacitanceBody = self._paramWidget.capacitanceBody_spinBox.value() + def electromagnetic_enabled_changed(self, value): + self.parameter_widget.gb_electromagnetic.setVisible(value) + + def av_enabled_changed(self, value): + self.av_enabled = value + self.parameter_widget.qsb_av_re.setEnabled(value) + self.parameter_widget.qsb_av_im.setEnabled(value) + + def av_1_enabled_changed(self, value): + self.av_1_enabled = value + self.parameter_widget.qsb_av_re_1.setEnabled(value) + self.parameter_widget.qsb_av_im_1.setEnabled(value) + + def av_2_enabled_changed(self, value): + self.av_2_enabled = value + self.parameter_widget.qsb_av_re_2.setEnabled(value) + self.parameter_widget.qsb_av_im_2.setEnabled(value) + + def av_3_enabled_changed(self, value): + self.av_3_enabled = value + self.parameter_widget.qsb_av_re_3.setEnabled(value) + self.parameter_widget.qsb_av_im_3.setEnabled(value) + + def av_re_changed(self, value): + self.av_re = value + + def av_re_1_changed(self, value): + self.av_re_1 = value + + def av_re_2_changed(self, value): + self.av_re_2 = value + + def av_re_3_changed(self, value): + self.av_re_3 = value + + def av_im_changed(self, value): + self.av_im = value + + def av_im_1_changed(self, value): + self.av_im_1 = value + + def av_im_2_changed(self, value): + self.av_im_2 = value + + def av_im_3_changed(self, value): + self.av_im_3 = value + + def potential_constant_changed(self, value): + self.potential_constant = value + + def electric_infinity_changed(self, value): + self.electric_infinity = value + + def capacitance_body_enabled_changed(self, value): + self.capacitance_body_enabled = value + self.parameter_widget.spb_capacitance_body.setEnabled(value) + + def capacitance_body_changed(self, value): + self.capacitance_body = value + self.parameter_widget.spb_capacitance_body.setValue(value) + + def surface_charge_density_changed(self, value): + self.surface_charge_density = value + + def boundary_condition_changed(self, index): + self.boundary_condition = self.bc_enum[index] + if self.boundary_condition == "Dirichlet": + self.parameter_widget.gb_neumann.setEnabled(False) + self.parameter_widget.gb_dirichlet.setEnabled(True) + elif self.boundary_condition == "Neumann": + self.parameter_widget.gb_neumann.setEnabled(True) + self.parameter_widget.gb_dirichlet.setEnabled(False)