diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt
index 8c5e0fba52..340e3ba855 100755
--- a/src/Mod/Fem/CMakeLists.txt
+++ b/src/Mod/Fem/CMakeLists.txt
@@ -563,6 +563,7 @@ SET(FemGuiObjects_SRCS
SET(FemGuiTaskPanels_SRCS
femtaskpanels/__init__.py
+ femtaskpanels/task_constraint_bodyheatsource.py
femtaskpanels/task_constraint_centrif.py
femtaskpanels/task_constraint_electrostaticpotential.py
femtaskpanels/task_constraint_flowvelocity.py
diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt
index 68678bd9ee..f208dfda0f 100755
--- a/src/Mod/Fem/Gui/CMakeLists.txt
+++ b/src/Mod/Fem/Gui/CMakeLists.txt
@@ -384,6 +384,7 @@ INSTALL(FILES ${FemGuiIcon_SVG} DESTINATION "${CMAKE_INSTALL_DATADIR}/Mod/Fem/Re
# Python modules ui files, they are copied as they are, thus the need not to be added to Fem.qrc
# see https://forum.freecadweb.org/viewtopic.php?f=10&t=25833
SET(FemGuiPythonUI_SRCS
+ Resources/ui/BodyHeatSource.ui
Resources/ui/ConstraintCentrif.ui
Resources/ui/ConstraintTie.ui
Resources/ui/ConstraintSectionPrint.ui
diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc
index 202cd4e0e2..247d75ab00 100755
--- a/src/Mod/Fem/Gui/Resources/Fem.qrc
+++ b/src/Mod/Fem/Gui/Resources/Fem.qrc
@@ -152,6 +152,7 @@
translations/Fem_zh-TW.qm
+ ui/BodyHeatSource.ui
ui/ConstraintCentrif.ui
ui/ConstraintSectionPrint.ui
ui/ConstraintTie.ui
diff --git a/src/Mod/Fem/Gui/Resources/ui/BodyHeatSource.ui b/src/Mod/Fem/Gui/Resources/ui/BodyHeatSource.ui
new file mode 100644
index 0000000000..76f049dffa
--- /dev/null
+++ b/src/Mod/Fem/Gui/Resources/ui/BodyHeatSource.ui
@@ -0,0 +1,79 @@
+
+
+ Form
+
+
+
+ 0
+ 0
+ 350
+ 40
+
+
+
+ Constraint Properties
+
+
+ -
+
+
+ Body heat in W/kg:
+
+
+
+ -
+
+
+ Qt::Horizontal
+
+
+
+ 130
+ 19
+
+
+
+
+ -
+
+
+ true
+
+
+
+ 100
+ 20
+
+
+
+ Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter
+
+
+ true
+
+
+ 0.000000000000000
+
+
+ 1000000000000000000000.000000000000000
+
+
+ 50.000000000000000
+
+
+ 0.000000000000000
+
+
+
+
+
+
+
+ Gui::QuantitySpinBox
+ QWidget
+
+
+
+
+
+
diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py
index 35f196e47f..466f7d3963 100644
--- a/src/Mod/Fem/femcommands/commands.py
+++ b/src/Mod/Fem/femcommands/commands.py
@@ -187,7 +187,7 @@ class _ConstraintBodyHeatSource(CommandManager):
"Creates a FEM constraint body heat source"
)
self.is_active = "with_analysis"
- self.do_activated = "add_obj_on_gui_noset_edit"
+ self.do_activated = "add_obj_on_gui_set_edit"
class _ConstraintCentrif(CommandManager):
diff --git a/src/Mod/Fem/femobjects/constraint_bodyheatsource.py b/src/Mod/Fem/femobjects/constraint_bodyheatsource.py
index f858aedb36..4ca679bd6a 100644
--- a/src/Mod/Fem/femobjects/constraint_bodyheatsource.py
+++ b/src/Mod/Fem/femobjects/constraint_bodyheatsource.py
@@ -40,8 +40,6 @@ class ConstraintBodyHeatSource(base_fempythonobject.BaseFemPythonObject):
def __init__(self, obj):
super(ConstraintBodyHeatSource, self).__init__(obj)
self.add_properties(obj)
- # the constraint does not take any references, thus hide this property
- obj.setEditorMode("References", 2)
def onDocumentRestored(self, obj):
self.add_properties(obj)
diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py
index 48555fe829..4f45dd862e 100644
--- a/src/Mod/Fem/femsolver/elmer/writer.py
+++ b/src/Mod/Fem/femsolver/elmer/writer.py
@@ -501,15 +501,31 @@ class Writer(object):
self._initial(name, "Temperature", temp)
self._handled(obj)
+ def _outputHeatBodyForce(self, obj, name):
+ heatSource = self._getFromUi(obj.HeatSource, "W/kg", "L^2*T^-3")
+ if heatSource == 0.0:
+ # a zero heat would break Elmer (division by zero)
+ raise WriteError("The body heat source must not be zero!")
+ self._bodyForce(name, "Heat Source", heatSource)
+
def _handleHeatBodyForces(self, bodies):
- obj = self._getSingleMember("Fem::ConstraintBodyHeatSource")
- if obj is not None:
- for name in bodies:
- heatSource = self._getFromUi(obj.HeatSource, "W/kg", "L^2*T^-3")
- # according Elmer forum W/kg is correct
- # http://www.elmerfem.org/forum/viewtopic.php?f=7&t=1765
- # 1 watt = kg * m2 / s3 ... W/kg = m2 / s3
- self._bodyForce(name, "Heat Source", heatSource)
+ bodyHeats = self._getMember("Fem::ConstraintBodyHeatSource")
+ for obj in bodyHeats:
+ if obj.References:
+ for name in obj.References[0][1]:
+ self._outputHeatBodyForce(obj, name)
+ self._handled(obj)
+ else:
+ # if there is only one body heat without a reference
+ # add it to all bodies
+ if len(bodyHeats) == 1:
+ for name in bodies:
+ self._outputHeatBodyForce(obj, name)
+ else:
+ raise WriteError(
+ "Several body heat constraints found without reference to a body.\n"
+ "Please set a body for each body heat constraint."
+ )
self._handled(obj)
def _handleHeatMaterial(self, bodies):
diff --git a/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py b/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py
new file mode 100644
index 0000000000..96b724d363
--- /dev/null
+++ b/src/Mod/Fem/femtaskpanels/task_constraint_bodyheatsource.py
@@ -0,0 +1,121 @@
+# ***************************************************************************
+# * Copyright (c) 2022 Uwe Stöhr *
+# * *
+# * This file is part of the FreeCAD CAx development system. *
+# * *
+# * This program is free software; you can redistribute it and/or modify *
+# * it under the terms of the GNU Lesser General Public License (LGPL) *
+# * as published by the Free Software Foundation; either version 2 of *
+# * the License, or (at your option) any later version. *
+# * for detail see the LICENCE text file. *
+# * *
+# * This program 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 Library General Public License for more details. *
+# * *
+# * You should have received a copy of the GNU Library General Public *
+# * License along with this program; if not, write to the Free Software *
+# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
+# * USA *
+# * *
+# ***************************************************************************
+
+__title__ = "FreeCAD FEM constraint body heat source task panel for the document object"
+__author__ = "Uwe Stöhr"
+__url__ = "https://www.freecadweb.org"
+
+## @package task_constraint_bodyheatsource
+# \ingroup FEM
+# \brief task panel for constraint bodyheatsource object
+
+import FreeCAD
+import FreeCADGui
+
+from femguiutils import selection_widgets
+
+from femtools import femutils
+from femtools import membertools
+
+
+class _TaskPanel(object):
+
+ def __init__(self, obj):
+ self._obj = obj
+
+ self._paramWidget = FreeCADGui.PySideUic.loadUi(
+ FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/BodyHeatSource.ui")
+ self._initParamWidget()
+
+ # geometry selection widget
+ # start with Solid in list!
+ self._selectionWidget = selection_widgets.GeometryElementsSelection(
+ obj.References,
+ ["Solid", "Face"],
+ True,
+ False
+ )
+
+ # form made from param and selection widget
+ self.form = [self._paramWidget, self._selectionWidget]
+
+ 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 = femutils.get_part_to_mesh(self._mesh)
+ 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._restoreVisibility()
+ FreeCADGui.ActiveDocument.resetEdit()
+ return True
+
+ def accept(self):
+ if self._obj.References != self._selectionWidget.references:
+ self._obj.References = self._selectionWidget.references
+ self._applyWidgetChanges()
+ self._obj.Document.recompute()
+ FreeCADGui.ActiveDocument.resetEdit()
+ self._restoreVisibility()
+ return True
+
+ def _restoreVisibility(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 _initParamWidget(self):
+ self._paramWidget.bodyheatQSB.setProperty(
+ 'value', self._obj.HeatSource)
+ self._paramWidget.bodyheatQSB.setProperty("unit", "W/kg")
+ FreeCADGui.ExpressionBinding(self._paramWidget.bodyheatQSB).bind(self._obj, "HeatSource")
+
+ def _applyWidgetChanges(self):
+ bodyheat = None
+ try:
+ bodyheat = self._paramWidget.bodyheatQSB.property('value').getValueAs("W/kg")
+ except ValueError:
+ FreeCAD.Console.PrintMessage(
+ "Wrong input. Not recognised input: '{}' "
+ "Body heat has not been set.\n"
+ .format(self._paramWidget.bodyheatQSB.text())
+ )
+ if bodyheat is not None:
+ self._obj.HeatSource = float(bodyheat)
diff --git a/src/Mod/Fem/femviewprovider/view_constraint_bodyheatsource.py b/src/Mod/Fem/femviewprovider/view_constraint_bodyheatsource.py
index ed58a56030..89083b35c8 100644
--- a/src/Mod/Fem/femviewprovider/view_constraint_bodyheatsource.py
+++ b/src/Mod/Fem/femviewprovider/view_constraint_bodyheatsource.py
@@ -30,10 +30,16 @@ __url__ = "https://www.freecadweb.org"
# \ingroup FEM
# \brief view provider for the constraint body heat source object
+from femtaskpanels import task_constraint_bodyheatsource
from . import view_base_femconstraint
class VPConstraintBodyHeatSource(view_base_femconstraint.VPBaseFemConstraint):
- def getIcon(self):
- return ":/icons/FEM_ConstraintBodyHeatSource.svg"
+ def setEdit(self, vobj, mode=0):
+ view_base_femconstraint.VPBaseFemConstraint.setEdit(
+ self,
+ vobj,
+ mode,
+ task_constraint_bodyheatsource._TaskPanel
+ )