From b10c02407f299b8488101d86b86873cbafd62ba7 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 27 Mar 2025 10:18:16 -0300 Subject: [PATCH] Fem: Add electric charge density object --- src/Mod/Fem/CMakeLists.txt | 3 + src/Mod/Fem/Gui/CMakeLists.txt | 2 + src/Mod/Fem/Gui/Command.cpp | 19 + src/Mod/Fem/Gui/Resources/Fem.qrc | 2 + .../FEM_ConstraintElectricChargeDensity.svg | 430 ++++++++++++++++++ .../ConstraintElectricChargeDensity.iv | 74 +++ .../Gui/Resources/ui/ElectricChargeDensity.ui | 187 ++++++++ src/Mod/Fem/Gui/Workbench.cpp | 3 +- src/Mod/Fem/ObjectsFem.py | 14 + src/Mod/Fem/femcommands/commands.py | 17 + .../constraint_electricchargedensity.py | 87 ++++ .../elmer/equations/electrostatic_writer.py | 61 ++- src/Mod/Fem/femsolver/elmer/writer.py | 1 + .../task_constraint_electricchargedensity.py | 171 +++++++ .../view_constraint_electricchargedensity.py | 51 +++ 15 files changed, 1119 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg create mode 100644 src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv create mode 100644 src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui create mode 100644 src/Mod/Fem/femobjects/constraint_electricchargedensity.py create mode 100644 src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py create mode 100644 src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 44aff6f11c..aabc377464 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -180,6 +180,7 @@ SET(FemObjects_SRCS femobjects/constraint_bodyheatsource.py femobjects/constraint_centrif.py femobjects/constraint_currentdensity.py + femobjects/constraint_electricchargedensity.py femobjects/constraint_electrostaticpotential.py femobjects/constraint_flowvelocity.py femobjects/constraint_initialflowvelocity.py @@ -582,6 +583,7 @@ SET(FemGuiTaskPanels_SRCS femtaskpanels/task_constraint_bodyheatsource.py femtaskpanels/task_constraint_centrif.py femtaskpanels/task_constraint_currentdensity.py + femtaskpanels/task_constraint_electricchargedensity.py femtaskpanels/task_constraint_electrostaticpotential.py femtaskpanels/task_constraint_flowvelocity.py femtaskpanels/task_constraint_initialflowvelocity.py @@ -627,6 +629,7 @@ SET(FemGuiViewProvider_SRCS femviewprovider/view_constraint_bodyheatsource.py femviewprovider/view_constraint_centrif.py femviewprovider/view_constraint_currentdensity.py + femviewprovider/view_constraint_electricchargedensity.py femviewprovider/view_constraint_electrostaticpotential.py femviewprovider/view_constraint_flowvelocity.py femviewprovider/view_constraint_initialflowvelocity.py diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index 6fb0572ecd..cbe6e488db 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -369,6 +369,7 @@ SET(FemGuiIcon_SVG SET(FemGuiSymbol_IV Resources/symbols/ConstraintContact.iv Resources/symbols/ConstraintDisplacement.iv + Resources/symbols/ConstraintElectricChargeDensity.iv Resources/symbols/ConstraintElectrostaticPotential.iv Resources/symbols/ConstraintCurrentDensity.iv Resources/symbols/ConstraintFixed.iv @@ -405,6 +406,7 @@ SET(FemGuiPythonUI_SRCS Resources/ui/ConstraintSectionPrint.ui Resources/ui/CurrentDensity.ui Resources/ui/DlgSettingsNetgen.ui + Resources/ui/ElectricChargeDensity.ui Resources/ui/ElectrostaticPotential.ui Resources/ui/ElementFluid1D.ui Resources/ui/ElementGeometry1D.ui diff --git a/src/Mod/Fem/Gui/Command.cpp b/src/Mod/Fem/Gui/Command.cpp index e71185cacd..20c52dbcbf 100644 --- a/src/Mod/Fem/Gui/Command.cpp +++ b/src/Mod/Fem/Gui/Command.cpp @@ -1416,6 +1416,9 @@ void CmdFemCompEmConstraints::activated(int iMsg) else if (iMsg == 2) { rcCmdMgr.runCommandByName("FEM_ConstraintMagnetization"); } + else if (iMsg == 3) { + rcCmdMgr.runCommandByName("FEM_ConstraintElectricChargeDensity"); + } else { return; } @@ -1441,6 +1444,8 @@ Gui::Action* CmdFemCompEmConstraints::createAction() cmd1->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintCurrentDensity")); QAction* cmd2 = pcAction->addAction(QString()); cmd2->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintMagnetization")); + QAction* cmd3 = pcAction->addAction(QString()); + cmd3->setIcon(Gui::BitmapFactory().iconFromTheme("FEM_ConstraintElectricChargeDensity")); _pcAction = pcAction; languageChange(); @@ -1502,6 +1507,20 @@ void CmdFemCompEmConstraints::languageChange() cmd2->setStatusTip(QApplication::translate("FEM_ConstraintMagnetization", ConstraintMagnetization->getStatusTip())); } + + Gui::Command* ConstraintElectricChargeDensity = + rcCmdMgr.getCommandByName("FEM_ConstraintElectricChargeDensity"); + if (ConstraintElectricChargeDensity) { + QAction* cmd3 = a[3]; + cmd3->setText(QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getMenuText())); + cmd3->setToolTip( + QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getToolTipText())); + cmd3->setStatusTip( + QApplication::translate("FEM_ConstraintElectricChargeDensity", + ConstraintElectricChargeDensity->getStatusTip())); + } } bool CmdFemCompEmConstraints::isActive() diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index dd132e54fc..4033dfc273 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -15,6 +15,7 @@ icons/FEM_ConstraintContact.svg icons/FEM_ConstraintCurrentDensity.svg icons/FEM_ConstraintDisplacement.svg + icons/FEM_ConstraintElectricChargeDensity.svg icons/FEM_ConstraintElectrostaticPotential.svg icons/FEM_ConstraintFixed.svg icons/FEM_ConstraintFlowVelocity.svg @@ -127,6 +128,7 @@ ui/ConstraintTie.ui ui/CurrentDensity.ui ui/DlgSettingsNetgen.ui + ui/ElectricChargeDensity.ui ui/ElectrostaticPotential.ui ui/ElementFluid1D.ui ui/ElementGeometry1D.ui diff --git a/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg new file mode 100644 index 0000000000..4e8402350a --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/FEM_ConstraintElectricChargeDensity.svg @@ -0,0 +1,430 @@ + + + + FEM_ConstraintElectrostaticPotential + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + FEM_ConstraintElectrostaticPotential + + + [bitacovir] + + + PartDesign_MoveTip + 12-02-2021 + https://www.freecad.org/wiki/index.php?title=Artwork + + + FreeCAD + + + + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv b/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv new file mode 100644 index 0000000000..1689168a72 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/symbols/ConstraintElectricChargeDensity.iv @@ -0,0 +1,74 @@ +#Inventor V2.1 ascii + +# SPDX-License-Identifier: LGPL-2.1-or-later + +#/*************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# ************************************************************************** + + +Separator { + + Separator { + + Translation { + translation 0 0.5 0 + + } + Sphere { + radius 0.5 + + } + Translation { + translation 0 2.0 0 + + } + BaseColor { + rgb 0.17 0.46 1.0 + + } + Sphere { + radius 0.5 + + } + Translation { + translation 0 -1.375 0 + + } + BaseColor { + rgb 1 1 1 + + } + Cylinder { + radius 0.1 + height 0.75 + + } + Translation { + translation 0 .625 0 + + } + Cone { + bottomRadius 0.25 + height 0.5 + + } + } +} diff --git a/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui b/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui new file mode 100644 index 0000000000..77def88519 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/ui/ElectricChargeDensity.ui @@ -0,0 +1,187 @@ + + + Form + + + + 0 + 0 + 350 + 40 + + + + Analysis feature properties + + + + + + + + + + + Mode: + + + + + + + + + + + + + 0 + 0 + + + + 0 + + + + + + + Free surface charge density + + + + + Density: + + + + + + + true + + + C/mm^2 + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + 1 + + + + + + + Free volume charge density + + + + + Density: + + + + + + + true + + + C/mm^3 + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + 2 + + + + + + + Free total charge + + + + + Total Charge: + + + + + + + true + + + C + + + Qt::AlignLeft|Qt::AlignTrailing|Qt::AlignVCenter + + + true + + + 1.000000000000000 + + + 0.000000000000000 + + + + + + + + + + + + + + + + + Gui::QuantitySpinBox + QWidget +
Gui/QuantitySpinBox.h
+
+
+ + +
diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 345632754e..7740d29c19 100644 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -246,7 +246,8 @@ Gui::MenuItem* Workbench::setupMenuBar() const elec->setCommand("&Electromagnetic boundary conditions"); *elec << "FEM_ConstraintElectrostaticPotential" << "FEM_ConstraintCurrentDensity" - << "FEM_ConstraintMagnetization"; + << "FEM_ConstraintMagnetization" + << "FEM_ConstraintElectricChargeDensity"; Gui::MenuItem* fluid = new Gui::MenuItem; fluid->setCommand("&Fluid boundary conditions"); diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index b8893e5d20..17a8b436f9 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -132,6 +132,20 @@ def makeConstraintDisplacement(doc, name="ConstraintDisplacement"): return obj +def makeConstraintElectricChargeDensity(doc, name="ElectricChargeDensity"): + """makeConstraintElectricChargeDensity(document, [name]): + makes a Fem ElectricChargeDensity object""" + obj = doc.addObject("Fem::ConstraintPython", name) + from femobjects import constraint_electricchargedensity + + constraint_electricchargedensity.ConstraintElectricChargeDensity(obj) + if FreeCAD.GuiUp: + from femviewprovider import view_constraint_electricchargedensity + + view_constraint_electricchargedensity.VPConstraintElectricChargeDensity(obj.ViewObject) + return obj + + def makeConstraintElectrostaticPotential(doc, name="ConstraintElectrostaticPotential"): """makeConstraintElectrostaticPotential(document, [name]): makes a Fem ElectrostaticPotential object""" diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 69bed9352f..89dad73b83 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -221,6 +221,22 @@ class _ConstraintCurrentDensity(CommandManager): self.do_activated = "add_obj_on_gui_set_edit" +class _ConstraintElectricChargeDensity(CommandManager): + "The FEM_ConstraintElectricChargeDensity command definition" + + def __init__(self): + super().__init__() + self.pixmap = "FEM_ConstraintElectricChargeDensity" + self.menutext = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectricChargeDensity", "Electric charge density" + ) + self.tooltip = Qt.QT_TRANSLATE_NOOP( + "FEM_ConstraintElectricChargeDensity", "Creates a electric charge density" + ) + self.is_active = "with_analysis" + self.do_activated = "add_obj_on_gui_set_edit" + + class _ConstraintElectrostaticPotential(CommandManager): "The FEM_ConstraintElectrostaticPotential command definition" @@ -1171,6 +1187,7 @@ FreeCADGui.addCommand("FEM_ConstantVacuumPermittivity", _ConstantVacuumPermittiv FreeCADGui.addCommand("FEM_ConstraintBodyHeatSource", _ConstraintBodyHeatSource()) FreeCADGui.addCommand("FEM_ConstraintCentrif", _ConstraintCentrif()) FreeCADGui.addCommand("FEM_ConstraintCurrentDensity", _ConstraintCurrentDensity()) +FreeCADGui.addCommand("FEM_ConstraintElectricChargeDensity", _ConstraintElectricChargeDensity()) FreeCADGui.addCommand("FEM_ConstraintElectrostaticPotential", _ConstraintElectrostaticPotential()) FreeCADGui.addCommand("FEM_ConstraintFlowVelocity", _ConstraintFlowVelocity()) FreeCADGui.addCommand("FEM_ConstraintInitialFlowVelocity", _ConstraintInitialFlowVelocity()) diff --git a/src/Mod/Fem/femobjects/constraint_electricchargedensity.py b/src/Mod/Fem/femobjects/constraint_electricchargedensity.py new file mode 100644 index 0000000000..fb2b9a6b16 --- /dev/null +++ b/src/Mod/Fem/femobjects/constraint_electricchargedensity.py @@ -0,0 +1,87 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge density document object" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package constraint_electricchargedensity +# \ingroup FEM +# \brief constraint electric charge density object + +from . import base_fempythonobject + +_PropHelper = base_fempythonobject._PropHelper + + +class ConstraintElectricChargeDensity(base_fempythonobject.BaseFemPythonObject): + + Type = "Fem::ConstraintElectricChargeDensity" + + def __init__(self, obj): + super().__init__(obj) + + for prop in self._get_properties(): + prop.add_to_object(obj) + + def _get_properties(self): + prop = [] + + prop.append( + _PropHelper( + type="App::PropertyVolumeChargeDensity", + name="SourceChargeDensity", + group="Electric Charge Density", + doc="Free electric charge per unit volume at the sources", + value="0 C/mm^3", + ) + ) + prop.append( + _PropHelper( + type="App::PropertySurfaceChargeDensity", + name="InterfaceChargeDensity", + group="Electric Charge Density", + doc="Free electric charge per unit surface at the boundaries", + value="0 C/mm^2", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyElectricCharge", + name="TotalCharge", + group="Electric Charge Density", + doc="Total free electric charge", + value="0 C", + ) + ) + prop.append( + _PropHelper( + type="App::PropertyEnumeration", + name="Mode", + group="Electric Charge Density", + doc="Switch quantity input mode", + value=["Interface", "Source", "Total Interface", "Total Source"], + ) + ) + + return prop diff --git a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py index 6ffba76461..bc49f4ee05 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py +++ b/src/Mod/Fem/femsolver/elmer/equations/electrostatic_writer.py @@ -30,6 +30,8 @@ __url__ = "https://www.freecad.org" ## \addtogroup FEM # @{ +from FreeCAD import Units + from .. import sifio @@ -133,8 +135,8 @@ class ESwriter: elif obj.BoundaryCondition == "Neumann": self.write.boundary( name, - "Surface Charge Density", - obj.SurfaceChargeDensity.getValueAs("C/m^2").Value, + "Electric Flux", + obj.ElectricFluxDensity.getValueAs("C/m^2").Value, ) if obj.PotentialConstant: self.write.boundary(name, "Potential Constant", True) @@ -146,5 +148,60 @@ class ESwriter: self.write.boundary(name, "Capacitance Body", obj.CapacitanceBody) self.write.handled(obj) + for obj in self.write.getMember("Fem::ConstraintElectricChargeDensity"): + if obj.Mode not in ["Interface", "Total Interface"]: + continue + + size = 0 + items = [] + for feat, sub_elem in obj.References: + for name in sub_elem: + sub = feat.getSubObject(name) + if sub.ShapeType == "Face": + size += sub.Area + items.append(name) + elif sub.ShapeType == "Edge": + size += sub.Length + items.append(name) + + if items: + if obj.Mode == "Interface": + density = obj.InterfaceChargeDensity.getValueAs("C/m^2").Value + elif obj.Mode == "Total Interface": + area = Units.Quantity(f"{size} mm^2") + density = (obj.TotalCharge / area).getValueAs("C/m^2").Value + for name in items: + self.write.boundary(name, "! FreeCAD Name", obj.Label) + self.write.boundary(name, "Surface Charge Density", round(density, 6)) + self.write.handled(obj) + + def handleElectrostaticBodyForces(self): + for obj in self.write.getMember("Fem::ConstraintElectricChargeDensity"): + if obj.Mode not in ["Source", "Total Source"]: + continue + + size = 0 + items = [] + for feat, sub_elem in obj.References: + for name in sub_elem: + sub = feat.getSubObject(name) + if sub.ShapeType == "Solid": + size += sub.Volume + items.append(name) + elif sub.ShapeType == "Face": + size += sub.Area + items.append(name) + + if items: + if obj.Mode == "Source": + density = obj.SourceChargeDensity.getValueAs("C/m^3").Value + elif obj.Mode == "Total Source": + vol = Units.Quantity(f"{size} mm^3") + density = (obj.TotalCharge / vol).getValueAs("C/m^3").Value + for name in items: + self.write.bodyForce(name, "! FreeCAD Name", obj.Label) + self.write.bodyForce(name, "Charge Density", round(density, 6)) + self.write.handled(obj) + ## @} diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index 834d87bcc1..b55833c754 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -471,6 +471,7 @@ class Writer: if activeIn: ESW.handleElectrostaticConstants() ESW.handleElectrostaticBndConditions() + ESW.handleElectrostaticBodyForces() ESW.handleElectrostaticMaterial(activeIn) # ------------------------------------------------------------------------------------------- diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py b/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py new file mode 100644 index 0000000000..1d082454ae --- /dev/null +++ b/src/Mod/Fem/femtaskpanels/task_constraint_electricchargedensity.py @@ -0,0 +1,171 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge density task panel" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package task_constraint_electricchargedensity +# \ingroup FEM +# \brief task panel for constraint electric charge density object + +from PySide import QtCore + +import FreeCAD +import FreeCADGui + +from femguiutils import selection_widgets + +from femtools import membertools +from . import base_femtaskpanel + + +class _TaskPanel(base_femtaskpanel._BaseTaskPanel): + + def __init__(self, obj): + super().__init__(obj) + + self.parameter_widget = FreeCADGui.PySideUic.loadUi( + FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/ElectricChargeDensity.ui" + ) + + self.init_parameter_widget() + + QtCore.QObject.connect( + self.parameter_widget.qsb_source_charge_density, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.source_charge_density_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_interface_charge_density, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.interface_charge_density_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.qsb_total_charge, + QtCore.SIGNAL("valueChanged(Base::Quantity)"), + self.total_charge_changed, + ) + QtCore.QObject.connect( + self.parameter_widget.cb_mode, + QtCore.SIGNAL("currentIndexChanged(int)"), + self.mode_changed, + ) + + # geometry selection widget + # start with Solid in list! + self.selection_widget = selection_widgets.GeometryElementsSelection( + obj.References, ["Solid", "Face", "Edge"], False, False + ) + + # form made from param and selection widget + self.form = [self.parameter_widget, self.selection_widget] + + analysis = obj.getParentGroup() + self._mesh = None + self._part = None + if analysis is not None: + self._mesh = membertools.get_single_member(analysis, "Fem::FemMeshObject") + if self._mesh is not None: + self._part = self._mesh.Shape + self._partVisible = None + self._meshVisible = None + + def open(self): + if self._mesh is not None and self._part is not None: + self._meshVisible = self._mesh.ViewObject.isVisible() + self._partVisible = self._part.ViewObject.isVisible() + self._mesh.ViewObject.hide() + self._part.ViewObject.show() + + def reject(self): + self.restore_visibility() + self.selection_widget.finish_selection() + return super().reject() + + def accept(self): + self.obj.References = self.selection_widget.references + self.obj.SourceChargeDensity = self.source_charge_density + self.obj.InterfaceChargeDensity = self.interface_charge_density + self.obj.TotalCharge = self.total_charge + self.obj.Mode = self.mode + + self.selection_widget.finish_selection() + self.restore_visibility() + return super().accept() + + def restore_visibility(self): + if self._mesh is not None and self._part is not None: + if self._meshVisible: + self._mesh.ViewObject.show() + else: + self._mesh.ViewObject.hide() + if self._partVisible: + self._part.ViewObject.show() + else: + self._part.ViewObject.hide() + + def init_parameter_widget(self): + self.source_charge_density = self.obj.SourceChargeDensity + self.interface_charge_density = self.obj.InterfaceChargeDensity + self.total_charge = self.obj.TotalCharge + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_source_charge_density).bind( + self.obj, "SourceChargeDensity" + ) + self.parameter_widget.qsb_source_charge_density.setProperty( + "value", self.source_charge_density + ) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_interface_charge_density).bind( + self.obj, "InterfaceChargeDensity" + ) + self.parameter_widget.qsb_interface_charge_density.setProperty( + "value", self.interface_charge_density + ) + + FreeCADGui.ExpressionBinding(self.parameter_widget.qsb_total_charge).bind( + self.obj, "TotalCharge" + ) + self.parameter_widget.qsb_total_charge.setProperty("value", self.total_charge) + + self.mode = self.obj.Mode + self.mode_enum = self.obj.getEnumerationsOfProperty("Mode") + self.parameter_widget.cb_mode.addItems(self.mode_enum) + index = self.mode_enum.index(self.mode) + self.parameter_widget.cb_mode.setCurrentIndex(index) + self.mode_changed(index) + + def source_charge_density_changed(self, base_quantity_value): + self.source_charge_density = base_quantity_value + + def interface_charge_density_changed(self, base_quantity_value): + self.interface_charge_density = base_quantity_value + + def total_charge_changed(self, base_quantity_value): + self.total_charge = base_quantity_value + + def mode_changed(self, index): + self.mode = self.mode_enum[index] + if self.mode in ["Total Interface", "Total Source"]: + index = 2 + self.parameter_widget.sw_mode.setCurrentIndex(index) diff --git a/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py b/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py new file mode 100644 index 0000000000..59517f2c4e --- /dev/null +++ b/src/Mod/Fem/femviewprovider/view_constraint_electricchargedensity.py @@ -0,0 +1,51 @@ +# SPDX-License-Identifier: LGPL-2.1-or-later + +# *************************************************************************** +# * Copyright (c) 2025 Mario Passaglia * +# * * +# * This file is part of FreeCAD. * +# * * +# * FreeCAD is free software: you can redistribute it and/or modify it * +# * under the terms of the GNU Lesser General Public License as * +# * published by the Free Software Foundation, either version 2.1 of the * +# * License, or (at your option) any later version. * +# * * +# * FreeCAD is distributed in the hope that it will be useful, but * +# * WITHOUT ANY WARRANTY; without even the implied warranty of * +# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * +# * Lesser General Public License for more details. * +# * * +# * You should have received a copy of the GNU Lesser General Public * +# * License along with FreeCAD. If not, see * +# * . * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM constraint electric charge view provider" +__author__ = "Mario Passaglia" +__url__ = "https://www.freecad.org" + +## @package view_constraint_electricchargedensity +# \ingroup FEM +# \brief view provider for the constraint electric charge density object + +from femtaskpanels import task_constraint_electricchargedensity +from . import view_base_femconstraint + + +class VPConstraintElectricChargeDensity(view_base_femconstraint.VPBaseFemConstraint): + + def __init__(self, vobj): + super().__init__(vobj) + mat = vobj.ShapeAppearance[0] + mat.DiffuseColor = (1.0, 0.0, 0.2, 0.0) + vobj.ShapeAppearance = mat + + def setEdit(self, vobj, mode=0): + return view_base_femconstraint.VPBaseFemConstraint.setEdit( + self, vobj, mode, task_constraint_electricchargedensity._TaskPanel + ) + + def attach(self, vobj): + super().attach(vobj) + vobj.loadSymbol(self.resource_symbol_dir + "ConstraintElectricChargeDensity.iv")