FEM: material task panel, code formating, line length, prints

This commit is contained in:
Bernd Hahnebach
2019-04-23 09:13:08 +02:00
parent bec300e6b1
commit 9d3141ce31

View File

@@ -1,6 +1,6 @@
# ***************************************************************************
# * *
# * Copyright (c) 2013 Juergen Riegel <FreeCAD@juergen-riegel.net> *
# * Copyright (c) 2013 Juergen Riegel <FreeCAD@juergen-riegel.net> *
# * Copyright (c) 2016 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
@@ -77,10 +77,12 @@ class _ViewProviderFemMaterial:
FreeCADGui.Control.closeDialog()
return True
# overwrite the doubleClicked of material object python to make sure no other Material taskd (and thus no selection observer) is still active
# overwrite the doubleClicked of material object python to make sure no other Material taskd
# (and thus no selection observer) is still active
def doubleClicked(self, vobj):
guidoc = FreeCADGui.getDocument(vobj.Object.Document)
# check if another VP is in edit mode, https://forum.freecadweb.org/viewtopic.php?t=13077#p104702
# check if another VP is in edit mode
# https://forum.freecadweb.org/viewtopic.php?t=13077#p104702
if not guidoc.getInEdit():
guidoc.setEdit(vobj.Object.Name)
else:
@@ -110,27 +112,74 @@ class _TaskPanelFemMaterial:
# card_name is the file name of the mat_card
# card_path is the whole file path of the mat_card
# material_name is the value of the key name in FreeCAD material dictionary
# they might not match because of special letters in the material_name which are changed in the card_name to english standard characters
# they might not match because of special letters in the material_name
# which are changed in the card_name to english standard characters
self.has_transient_mat = False
# parameter widget
self.parameterWidget = FreeCADGui.PySideUic.loadUi(FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/Material.ui")
self.parameterWidget = FreeCADGui.PySideUic.loadUi(
FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/Material.ui"
)
# globals
QtCore.QObject.connect(self.parameterWidget.cb_materials, QtCore.SIGNAL("activated(int)"), self.choose_material)
QtCore.QObject.connect(self.parameterWidget.chbu_allow_edit, QtCore.SIGNAL("clicked()"), self.toggleInputFieldsReadOnly)
QtCore.QObject.connect(self.parameterWidget.pushButton_editMat, QtCore.SIGNAL("clicked()"), self.edit_material)
QtCore.QObject.connect(
self.parameterWidget.cb_materials,
QtCore.SIGNAL("activated(int)"),
self.choose_material
)
QtCore.QObject.connect(
self.parameterWidget.chbu_allow_edit,
QtCore.SIGNAL("clicked()"),
self.toggleInputFieldsReadOnly
)
QtCore.QObject.connect(
self.parameterWidget.pushButton_editMat,
QtCore.SIGNAL("clicked()"),
self.edit_material
)
# basic properties must be provided
QtCore.QObject.connect(self.parameterWidget.input_fd_density, QtCore.SIGNAL("editingFinished()"), self.density_changed)
QtCore.QObject.connect(
self.parameterWidget.input_fd_density,
QtCore.SIGNAL("editingFinished()"),
self.density_changed
)
# mechanical properties
QtCore.QObject.connect(self.parameterWidget.input_fd_young_modulus, QtCore.SIGNAL("editingFinished()"), self.ym_changed)
QtCore.QObject.connect(self.parameterWidget.spinBox_poisson_ratio, QtCore.SIGNAL("editingFinished()"), self.pr_changed)
QtCore.QObject.connect(
self.parameterWidget.input_fd_young_modulus,
QtCore.SIGNAL("editingFinished()"),
self.ym_changed
)
QtCore.QObject.connect(
self.parameterWidget.spinBox_poisson_ratio,
QtCore.SIGNAL("editingFinished()"),
self.pr_changed
)
# thermal properties
QtCore.QObject.connect(self.parameterWidget.input_fd_thermal_conductivity, QtCore.SIGNAL("editingFinished()"), self.tc_changed)
QtCore.QObject.connect(self.parameterWidget.input_fd_expansion_coefficient, QtCore.SIGNAL("editingFinished()"), self.tec_changed)
QtCore.QObject.connect(self.parameterWidget.input_fd_specific_heat, QtCore.SIGNAL("editingFinished()"), self.sh_changed)
QtCore.QObject.connect(
self.parameterWidget.input_fd_thermal_conductivity,
QtCore.SIGNAL("editingFinished()"),
self.tc_changed
)
QtCore.QObject.connect(
self.parameterWidget.input_fd_expansion_coefficient,
QtCore.SIGNAL("editingFinished()"),
self.tec_changed
)
QtCore.QObject.connect(
self.parameterWidget.input_fd_specific_heat,
QtCore.SIGNAL("editingFinished()"),
self.sh_changed
)
# fluidic properties, only volumetric thermal expansion coeff makes sense
QtCore.QObject.connect(self.parameterWidget.input_fd_kinematic_viscosity, QtCore.SIGNAL("editingFinished()"), self.kinematic_viscosity_changed)
QtCore.QObject.connect(self.parameterWidget.input_fd_vol_expansion_coefficient, QtCore.SIGNAL("editingFinished()"), self.vtec_changed)
QtCore.QObject.connect(
self.parameterWidget.input_fd_kinematic_viscosity,
QtCore.SIGNAL("editingFinished()"),
self.kinematic_viscosity_changed
)
QtCore.QObject.connect(
self.parameterWidget.input_fd_vol_expansion_coefficient,
QtCore.SIGNAL("editingFinished()"),
self.vtec_changed
)
# init all parameter input files with read only
self.parameterWidget.chbu_allow_edit.setCheckState(QtCore.Qt.CheckState.Unchecked)
@@ -156,22 +205,38 @@ class _TaskPanelFemMaterial:
if not self.card_path:
# we have not found our material in self.materials dict :-(
# we're going to add a user-defined temporary material: a document material
FreeCAD.Console.PrintMessage("Previously used material card cannot be found in material directories. Add document material.\n")
FreeCAD.Console.PrintMessage(
"Previously used material card cannot be found in material directories. "
"Add document material.\n"
)
self.card_path = '_document_material'
self.materials[self.card_path] = self.material
self.parameterWidget.cb_materials.addItem(QtGui.QIcon(":/icons/help-browser.svg"), self.card_path, self.card_path)
self.parameterWidget.cb_materials.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path,
self.card_path
)
index = self.parameterWidget.cb_materials.findData(self.card_path)
# print(index)
self.choose_material(index) # fill input fields and set the current material in the cb widget
# fill input fields and set the current material in the cb widget
self.choose_material(index)
else:
# we found our exact material in self.materials dict :-)
FreeCAD.Console.PrintMessage("Previously used material card was found in material directories. We will use this material.\n")
FreeCAD.Console.PrintMessage(
"Previously used material card was found in material directories. "
"We will use this material.\n"
)
index = self.parameterWidget.cb_materials.findData(self.card_path)
# print(index)
self.choose_material(index) # fill input fields and set the current material in the cb widget
# fill input fields and set the current material in the cb widget
self.choose_material(index)
# geometry selection widget
self.selectionWidget = FemSelectionWidgets.GeometryElementsSelection(obj.References, ['Solid', 'Face', 'Edge'], False) # start with Solid in list!
self.selectionWidget = FemSelectionWidgets.GeometryElementsSelection(
obj.References,
['Solid', 'Face', 'Edge'],
False
) # start with Solid in list!
# form made from param and selection widget
self.form = [self.parameterWidget, self.selectionWidget]
@@ -179,7 +244,7 @@ class _TaskPanelFemMaterial:
# check references, has to be after initialisation of selectionWidget
self.selectionWidget.has_equal_references_shape_types()
# leave task panel **********************************************
# leave task panel ***************************************************************************
def accept(self):
# print(self.material)
if self.selectionWidget.has_equal_references_shape_types():
@@ -200,7 +265,7 @@ class _TaskPanelFemMaterial:
FreeCADGui.Selection.removeObserver(self.selectionWidget.sel_server)
doc.resetEdit()
# choose material ***********************************************
# choose material ****************************************************************************
def get_material_card(self, material):
for a_mat in self.materials:
unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items())
@@ -212,7 +277,7 @@ class _TaskPanelFemMaterial:
def choose_material(self, index):
if index < 0:
return
self.card_path = self.parameterWidget.cb_materials.itemData(index) # returns the whole path !
self.card_path = self.parameterWidget.cb_materials.itemData(index) # returns whole path
# print('choose_material: ' + self.card_path)
self.material = self.materials[self.card_path]
self.check_material_keys()
@@ -237,19 +302,25 @@ class _TaskPanelFemMaterial:
def add_transient_material(self):
self.has_transient_mat = True
self.card_path = '_transient_material'
self.parameterWidget.cb_materials.addItem(QtGui.QIcon(":/icons/help-browser.svg"), self.card_path, self.card_path)
self.parameterWidget.cb_materials.addItem(
QtGui.QIcon(":/icons/help-browser.svg"),
self.card_path,
self.card_path
)
self.set_transient_material()
# how to edit a material ****************************************
# how to edit a material *********************************************************************
def edit_material(self):
# opens the material editor to choose a material or edit material params
# self.print_material_params()
import MaterialEditor
new_material_params = self.material.copy()
new_material_params = MaterialEditor.editMaterial(new_material_params)
# if the material editor was canceled a empty params dict will be returned, do not change the self.material
# if the material editor was canceled a empty params dict will be returned
# do not change the self.material
# self.print_material_params(new_material_params)
if new_material_params: # returns True if dict is not empty (do not use 'is True', this would return False for a non empty dict)
# check if dict is not empty (do not use 'is True'
if new_material_params:
self.material = new_material_params
self.check_material_keys()
self.set_mat_params_in_input_fields(self.material)
@@ -260,7 +331,8 @@ class _TaskPanelFemMaterial:
else:
FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n')
# self.print_material_params()
# material editor returns the mat_dict only not a card_path, if a standard FreeCAD mat_card was used
# material editor returns the mat_dict only not a card_path
# if a standard FreeCAD mat_card was used
def toggleInputFieldsReadOnly(self):
if self.parameterWidget.chbu_allow_edit.isChecked():
@@ -282,10 +354,11 @@ class _TaskPanelFemMaterial:
self.parameterWidget.input_fd_kinematic_viscosity.setReadOnly(True)
self.parameterWidget.input_fd_vol_expansion_coefficient.setReadOnly(True)
# material parameter input fields *******************************
# material parameter input fields ************************************************************
def print_material_params(self, material=None):
# in rare cases we gone pass a empty dict
# in such a case a empty dict should be printed and not self.material thus we check for None
# in such a case a empty dict should be printed and not self.material
# thus we check for None
if material is None:
material = self.material
if not material:
@@ -299,72 +372,131 @@ class _TaskPanelFemMaterial:
def check_material_keys(self):
# FreeCAD units definition is at file end of src/Base/Unit.cpp
if not self.material:
print('For some reason all material data is empty!')
FreeCAD.Console.PrintMessage('For some reason all material data is empty!\n')
self.material['Name'] = 'Empty'
if 'Density' in self.material:
if 'Density' not in str(Units.Unit(self.material['Density'])):
print('Density in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'Density in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['Density'] = '0 kg/m^3'
else:
print('Density not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'Density not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['Density'] = '0 kg/m^3'
if self.obj.Category == 'Solid':
# mechanical properties
if 'YoungsModulus' in self.material:
if 'Pressure' not in str(Units.Unit(self.material['YoungsModulus'])): # unit type of YoungsModulus is Pressure
print('YoungsModulus in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
# unit type of YoungsModulus is Pressure
if 'Pressure' not in str(Units.Unit(self.material['YoungsModulus'])):
FreeCAD.Console.PrintMessage(
'YoungsModulus in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['YoungsModulus'] = '0 MPa'
else:
print('YoungsModulus not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'YoungsModulus not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['YoungsModulus'] = '0 MPa'
if 'PoissonRatio' in self.material:
# PoissonRatio does not have a unit, but it is checked it there is no value at all
try:
float(self.material['PoissonRatio'])
except:
print('PoissonRatio has wrong or no data (reset the value): ' + self.material['PoissonRatio'])
FreeCAD.Console.PrintMessage(
'PoissonRatio has wrong or no data (reset the value): {}\n'
.format(self.material['PoissonRatio'])
)
self.material['PoissonRatio'] = '0'
else:
print('PoissonRatio not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'PoissonRatio not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['PoissonRatio'] = '0'
if self.obj.Category == 'Fluid':
# Fluidic properties
if 'KinematicViscosity' in self.material:
if 'KinematicViscosity' not in str(Units.Unit(self.material['KinematicViscosity'])):
print('KinematicViscosity in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
ki_vis = self.material['KinematicViscosity']
if 'KinematicViscosity' not in str(Units.Unit(ki_vis)):
FreeCAD.Console.PrintMessage(
'KinematicViscosity in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['KinematicViscosity'] = '0 m^2/s'
else:
print('KinematicViscosity not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'KinematicViscosity not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['KinematicViscosity'] = '0 m^2/s'
if 'VolumetricThermalExpansionCoefficient' in self.material:
# unit type of VolumetricThermalExpansionCoefficient is ThermalExpansionCoefficient
if 'VolumetricThermalExpansionCoefficient' not in str(Units.Unit(self.material['VolumetricThermalExpansionCoefficient'])):
print('VolumetricThermalExpansionCoefficient in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
# unit type VolumetricThermalExpansionCoefficient is ThermalExpansionCoefficient
vol_ther_ex_co = self.material['VolumetricThermalExpansionCoefficient']
if 'VolumetricThermalExpansionCoefficient' not in str(Units.Unit(vol_ther_ex_co)):
FreeCAD.Console.PrintMessage(
'VolumetricThermalExpansionCoefficient in material data '
'seems to have no unit or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
else:
print('VolumetricThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'VolumetricThermalExpansionCoefficient not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['VolumetricThermalExpansionCoefficient'] = '0 m/m/K'
# Thermal properties
if 'ThermalConductivity' in self.material:
if 'ThermalConductivity' not in str(Units.Unit(self.material['ThermalConductivity'])):
print('ThermalConductivity in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'ThermalConductivity in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['ThermalConductivity'] = '0 W/m/K'
else:
print('ThermalConductivity not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'ThermalConductivity not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['ThermalConductivity'] = '0 W/m/K'
if 'ThermalExpansionCoefficient' in self.material:
if 'ThermalExpansionCoefficient' not in str(Units.Unit(self.material['ThermalExpansionCoefficient'])):
print('ThermalExpansionCoefficient in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
the_ex_co = self.material['ThermalExpansionCoefficient']
if 'ThermalExpansionCoefficient' not in str(Units.Unit(the_ex_co)):
FreeCAD.Console.PrintMessage(
'ThermalExpansionCoefficient in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
else:
print('ThermalExpansionCoefficient not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'ThermalExpansionCoefficient not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['ThermalExpansionCoefficient'] = '0 um/m/K'
if 'SpecificHeat' in self.material:
if 'SpecificHeat' not in str(Units.Unit(self.material['SpecificHeat'])):
print('SpecificHeat in material data seems to have no unit or a wrong unit (reset the value): ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'SpecificHeat in material data seems to have no unit '
'or a wrong unit (reset the value): {}\n'
.format(self.material['Name'])
)
self.material['SpecificHeat'] = '0 J/kg/K'
else:
print('SpecificHeat not found in material data of: ' + self.material['Name'])
FreeCAD.Console.PrintMessage(
'SpecificHeat not found in material data of: {}\n'
.format(self.material['Name'])
)
self.material['SpecificHeat'] = '0 J/kg/K'
# mechanical input fields
@@ -394,7 +526,8 @@ class _TaskPanelFemMaterial:
# density has changed
material = self.material
value_in_kg_per_m3 = value * 1e9
material['Density'] = unicode(value_in_kg_per_m3) + " kg/m^3" # SvdW:Keep density in SI units for easier readability
# SvdW:Keep density in SI units for easier readability
material['Density'] = unicode(value_in_kg_per_m3) + " kg/m^3"
self.material = material
if self.has_transient_mat is False:
self.add_transient_material()
@@ -444,7 +577,9 @@ class _TaskPanelFemMaterial:
def tec_changed(self):
value = self.parameterWidget.input_fd_expansion_coefficient.property("rawValue")
old_tec = Units.Quantity(self.material['ThermalExpansionCoefficient']).getValueAs("um/m/K")
old_tec = Units.Quantity(
self.material['ThermalExpansionCoefficient']
).getValueAs("um/m/K")
variation = 0.001
if value:
if not (1 - variation < float(old_tec) / value < 1 + variation):
@@ -477,14 +612,16 @@ class _TaskPanelFemMaterial:
# fluidic input fields
def vtec_changed(self):
value = self.parameterWidget.input_fd_vol_expansion_coefficient.property("rawValue")
old_vtec = Units.Quantity(self.material['VolumetricThermalExpansionCoefficient']).getValueAs("m/m/K")
old_vtec = Units.Quantity(
self.material['VolumetricThermalExpansionCoefficient']
).getValueAs("m/m/K")
variation = 0.001
if value:
if not (1 - variation < float(old_vtec) / value < 1 + variation):
# VolumetricThermalExpansionCoefficient has changed
material = self.material
value_in_one_per_K = value
material['VolumetricThermalExpansionCoefficient'] = unicode(value_in_one_per_K) + " m/m/K"
value_in_one_per_K = unicode(value) + " m/m/K"
material['VolumetricThermalExpansionCoefficient'] = value_in_one_per_K
self.material = material
if self.has_transient_mat is False:
self.add_transient_material()
@@ -523,7 +660,8 @@ class _TaskPanelFemMaterial:
nu_with_new_unit = nu.getValueAs(nu_new_unit)
q = FreeCAD.Units.Quantity("{} {}".format(nu_with_new_unit, nu_new_unit))
self.parameterWidget.input_fd_kinematic_viscosity.setText(q.UserString)
# For isotropic materials the volumetric thermal expansion coefficient is three times the linear coefficient:
# For isotropic materials the volumetric thermal expansion coefficient
# is three times the linear coefficient:
if 'VolumetricThermalExpansionCoefficient' in matmap: # linear, only for solid
vtec_new_unit = "m/m/K"
vtec = FreeCAD.Units.Quantity(matmap['VolumetricThermalExpansionCoefficient'])
@@ -534,7 +672,9 @@ class _TaskPanelFemMaterial:
density_new_unit = "kg/m^3"
density = FreeCAD.Units.Quantity(matmap['Density'])
density_with_new_unit = density.getValueAs(density_new_unit)
# self.parameterWidget.input_fd_density.setText("{} {}".format(density_with_new_unit, density_new_unit))
# self.parameterWidget.input_fd_density.setText(
# "{} {}".format(density_with_new_unit, density_new_unit)
# )
q = FreeCAD.Units.Quantity("{} {}".format(density_with_new_unit, density_new_unit))
self.parameterWidget.input_fd_density.setText(q.UserString)
# thermal properties
@@ -557,7 +697,7 @@ class _TaskPanelFemMaterial:
q = FreeCAD.Units.Quantity("{} {}".format(sh_with_new_unit, sh_new_unit))
self.parameterWidget.input_fd_specific_heat.setText(q.UserString)
# material import and export ************************************
# material import and export *****************************************************************
def print_materialsdict(self):
print('\n\n')
for mat_card in self.materials:
@@ -569,7 +709,9 @@ class _TaskPanelFemMaterial:
self.pathList = []
self.parameterWidget.cb_materials.clear()
self.fem_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Resources")
self.fem_prefs = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Material/Resources"
)
if self.obj.Category == 'Fluid':
self.import_fluid_materials()
else: