[FEM] fix body heat source constraint

- as the name implies, it must be possible to set the heat to different bodies
- for this a selection dialog is necessary
- check that heat is not zero
This commit is contained in:
Uwe
2022-08-15 01:43:02 +02:00
parent 32d74bb0ca
commit d0ee6a46a0
9 changed files with 236 additions and 13 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -152,6 +152,7 @@
<file>translations/Fem_zh-TW.qm</file>
<!-- task panels -->
<file>ui/BodyHeatSource.ui</file>
<file>ui/ConstraintCentrif.ui</file>
<file>ui/ConstraintSectionPrint.ui</file>
<file>ui/ConstraintTie.ui</file>

View File

@@ -0,0 +1,79 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>Form</class>
<widget class="QWidget" name="Form">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>350</width>
<height>40</height>
</rect>
</property>
<property name="windowTitle">
<string>Constraint Properties</string>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="pressureLbl">
<property name="text">
<string>Body heat in W/kg:</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>130</width>
<height>19</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="Gui::QuantitySpinBox" name="bodyheatQSB">
<property name="enabled">
<bool>true</bool>
</property>
<property name="minimumSize">
<size>
<width>100</width>
<height>20</height>
</size>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
<property name="keyboardTracking">
<bool>true</bool>
</property>
<property name="minimum">
<double>0.000000000000000</double>
</property>
<property name="maximum">
<double>1000000000000000000000.000000000000000</double>
</property>
<property name="singleStep">
<double>50.000000000000000</double>
</property>
<property name="value">
<double>0.000000000000000</double>
</property>
</widget>
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>Gui::QuantitySpinBox</class>
<extends>QWidget</extends>
<header>Gui/QuantitySpinBox.h</header>
</customwidget>
</customwidgets>
<resources/>
<connections/>
</ui>

View File

@@ -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):

View File

@@ -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)

View File

@@ -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):

View File

@@ -0,0 +1,121 @@
# ***************************************************************************
# * Copyright (c) 2022 Uwe Stöhr <uwestoehr@lyx.org> *
# * *
# * 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)

View File

@@ -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
)