This commit is contained in:
wmayer 2015-10-10 09:49:05 +02:00
commit 9aa5f7b3a5
8 changed files with 154 additions and 186 deletions

3
.arcconfig Normal file
View File

@ -0,0 +1,3 @@
{
"phabricator.uri" : "http://pha.geofinder.eu/"
}

View File

@ -1,24 +1,24 @@
#***************************************************************************
#* *
#* Copyright (c) 2015 - 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) *
#* 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 *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 - 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) *
# * 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 *
# * *
# ***************************************************************************
import FreeCAD

View File

@ -46,13 +46,13 @@
<item>
<widget class="QGroupBox" name="groupBox_1">
<property name="title">
<string>Reference</string>
<string>References</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="l_label_text_1">
<property name="text">
<string>Leave reference blank </string>
<string>Leave references blank </string>
</property>
</widget>
</item>

View File

@ -1,24 +1,24 @@
#***************************************************************************
#* *
#* Copyright (c) 2015 - 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) *
#* 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 *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2015 - 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) *
# * 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 *
# * *
# ***************************************************************************
import FreeCAD

View File

@ -46,13 +46,13 @@
<item>
<widget class="QGroupBox" name="groupBox_1">
<property name="title">
<string>Reference</string>
<string>References</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2">
<item>
<widget class="QLabel" name="l_label_text_1">
<property name="text">
<string>Leave reference blank </string>
<string>Leave references blank </string>
</property>
</widget>
</item>

View File

@ -1,24 +1,24 @@
#***************************************************************************
#* *
#* Copyright (c) 2013 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
#* *
#* 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 *
#* *
#***************************************************************************
# ***************************************************************************
# * *
# * Copyright (c) 2013 - Juergen Riegel <FreeCAD@juergen-riegel.net> *
# * *
# * 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 *
# * *
# ***************************************************************************
import FreeCAD
@ -134,14 +134,14 @@ class _MechanicalMaterialTaskPanel:
QtCore.QObject.connect(self.form.input_fd_young_modulus, QtCore.SIGNAL("valueChanged(double)"), self.ym_changed)
QtCore.QObject.connect(self.form.spinBox_poisson_ratio, QtCore.SIGNAL("valueChanged(double)"), self.pr_changed)
QtCore.QObject.connect(self.form.input_fd_density, QtCore.SIGNAL("valueChanged(double)"), self.density_changed)
self.previous_material = self.obj.Material
self.material = self.obj.Material
self.import_materials()
previous_mat_path = self.get_material_path(self.previous_material)
previous_mat_path = self.get_material_path(self.material)
if not previous_mat_path:
print "Previously used material cannot be found in material directories. Using transient material."
material_name = self.get_material_name(self.previous_material)
material_name = self.get_material_name(self.material)
if material_name != 'None':
self.add_transient_material(self.previous_material)
self.add_transient_material(self.material)
index = self.form.cb_materials.findData(material_name)
else:
index = self.form.cb_materials.findText(material_name)
@ -151,11 +151,11 @@ class _MechanicalMaterialTaskPanel:
self.choose_material(index)
def accept(self):
self.obj.Material = self.material
FreeCADGui.ActiveDocument.resetEdit()
FreeCAD.ActiveDocument.recompute()
def reject(self):
self.obj.Material = self.previous_material
print "Reverting to material:"
FreeCADGui.ActiveDocument.resetEdit()
def goMatWeb(self):
@ -164,44 +164,44 @@ class _MechanicalMaterialTaskPanel:
def ym_changed(self, value):
import Units
old_ym = Units.Quantity(self.obj.Material['YoungsModulus'])
old_ym = Units.Quantity(self.material['YoungsModulus'])
if old_ym != value:
material = self.obj.Material
material = self.material
# FreeCAD uses kPa internall for Stress
material['YoungsModulus'] = unicode(value) + " kPa"
self.obj.Material = material
self.material = material
def density_changed(self, value):
import Units
old_density = Units.Quantity(self.obj.Material['Density'])
old_density = Units.Quantity(self.material['Density'])
if old_density != value:
material = self.obj.Material
material = self.material
material['Density'] = unicode(value) + " kg/mm^3"
self.obj.Material = material
self.material = material
def pr_changed(self, value):
import Units
old_pr = Units.Quantity(self.obj.Material['PoissonRatio'])
old_pr = Units.Quantity(self.material['PoissonRatio'])
if old_pr != value:
material = self.obj.Material
material = self.material
material['PoissonRatio'] = unicode(value)
self.obj.Material = material
self.material = material
def choose_material(self, index):
if index < 0:
return
mat_file_path = self.form.cb_materials.itemData(index)
self.obj.Material = self.materials[mat_file_path]
self.material = self.materials[mat_file_path]
self.form.cb_materials.setCurrentIndex(index)
self.set_mat_params_in_combo_box(self.obj.Material)
self.set_mat_params_in_combo_box(self.material)
gen_mat_desc = ""
if 'Description' in self.obj.Material:
gen_mat_desc = self.obj.Material['Description']
if 'Description' in self.material:
gen_mat_desc = self.material['Description']
self.form.l_mat_description.setText(gen_mat_desc)
def get_material_name(self, material):
if 'Name' in self.previous_material:
return self.previous_material['Name']
if 'Name' in self.material:
return self.material['Name']
else:
return 'None'

View File

@ -28,6 +28,7 @@ import Fem
import FemTools
import FreeCAD
import MechanicalAnalysis
import MechanicalMaterial
import csv
import tempfile
import unittest
@ -89,7 +90,7 @@ class FemTest(unittest.TestCase):
self.active_doc.recompute()
def create_new_material(self):
self.new_material_object = self.active_doc.addObject("App::MaterialObjectPython", 'MechanicalMaterial')
self.new_material_object = MechanicalMaterial.makeMechanicalMaterial('MechanicalMaterial')
mat = self.new_material_object.Material
mat['Name'] = "Steel"
mat['YoungsModulus'] = "200000 MPa"

View File

@ -203,7 +203,7 @@ class inp_writer:
elsetdef = 'ELSET=' + ccx_elset['ccx_elset_name'] + ', '
material = 'MATERIAL=' + ccx_elset['ccx_mat_name']
setion_def = '*BEAM SECTION, ' + elsetdef + material + ', SECTION=RECT\n'
setion_geo = str(beamsec_obj.Hight.getValueAs('mm')) + ', ' + str(beamsec_obj.Width.getValueAs('mm')) + '\n'
setion_geo = str(beamsec_obj.Height.getValueAs('mm')) + ', ' + str(beamsec_obj.Width.getValueAs('mm')) + '\n'
f.write(setion_def)
f.write(setion_geo)
elif 'shellthickness_obj'in ccx_elset: # shell mesh
@ -511,7 +511,7 @@ class inp_writer:
def get_ccx_elsets_single_mat_multiple_beam(self):
mat_obj = self.material_objects[0]['Object']
self.get_beamsection_element_sets()
self.get_femelement_sets(self.beamsection_objects)
for beamsec_data in self.beamsection_objects:
beamsec_obj = beamsec_data['Object']
ccx_elset = {}
@ -524,7 +524,7 @@ class inp_writer:
def get_ccx_elsets_single_mat_multiple_shell(self):
mat_obj = self.material_objects[0]['Object']
self.get_shellthickness_element_sets()
self.get_femelement_sets(self.shellthickness_objects)
for shellth_data in self.shellthickness_objects:
shellth_obj = shellth_data['Object']
ccx_elset = {}
@ -537,7 +537,7 @@ class inp_writer:
def get_ccx_elsets_multiple_mat_single_beam(self):
beamsec_obj = self.beamsection_objects[0]['Object']
self.get_material_element_sets()
self.get_femelement_sets(self.material_objects)
for mat_data in self.material_objects:
mat_obj = mat_data['Object']
ccx_elset = {}
@ -550,7 +550,7 @@ class inp_writer:
def get_ccx_elsets_multiple_mat_single_shell(self):
shellth_obj = self.shellthickness_objects[0]['Object']
self.get_material_element_sets()
self.get_femelement_sets(self.material_objects)
for mat_data in self.material_objects:
mat_obj = mat_data['Object']
ccx_elset = {}
@ -562,7 +562,7 @@ class inp_writer:
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_solid(self):
self.get_material_element_sets()
self.get_femelement_sets(self.material_objects)
for mat_data in self.material_objects:
mat_obj = mat_data['Object']
ccx_elset = {}
@ -573,8 +573,8 @@ class inp_writer:
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_multiple_beam(self):
self.get_beamsection_element_sets()
self.get_material_element_sets()
self.get_femelement_sets(self.beamsection_objects)
self.get_femelement_sets(self.material_objects)
for beamsec_data in self.beamsection_objects:
beamsec_obj = beamsec_data['Object']
for mat_data in self.material_objects:
@ -592,8 +592,8 @@ class inp_writer:
self.ccx_elsets.append(ccx_elset)
def get_ccx_elsets_multiple_mat_multiple_shell(self):
self.get_shellthickness_element_sets()
self.get_material_element_sets()
self.get_femelement_sets(self.shellthickness_objects)
self.get_femelement_sets(self.material_objects)
for shellth_data in self.shellthickness_objects:
shellth_obj = shellth_data['Object']
for mat_data in self.material_objects:
@ -610,102 +610,55 @@ class inp_writer:
ccx_elset['ccx_mat_name'] = mat_obj.Material['Name'][:80]
self.ccx_elsets.append(ccx_elset)
def get_material_element_sets(self):
# get femelements for reference shapes of each material_obj
FreeCAD.Console.PrintError('Multiple materials defined, this could result in a broken CalculiX input file!\n')
# TODO get the elset nodeids and write them to mat_data['FEMElements']
# if not hasattr(self, 'fem_element_table'):
# self.fem_element_table = getFemElementTable(self.mesh_object.FemMesh)
for mat_data_i, mat_data in enumerate(self.material_objects):
mat_data['ShortName'] = 'Mat' + str(mat_data_i) # unique short ccx_identifier
# mat_obj = mat_data['Object']
mat_data['FEMElements'] = self.ccx_eall
def get_beamsection_element_sets(self):
# get femelements for reference shapes of each beamsec_obj
def get_femelement_sets(self, fem_objects):
# get femelements for reference shapes of each obj.References
if not hasattr(self, 'fem_element_table'):
self.fem_element_table = getFemElementTable(self.mesh_object.FemMesh)
count_femelements_beamsection = 0
referenced_femelements_beamsection = []
has_remaining_femelements_beamsection = None
for beamsec_data_i, beamsec_data in enumerate(self.beamsection_objects):
beamsec_data['ShortName'] = 'Beam' + str(beamsec_data_i) # unique short ccx_identifier
beamsec_obj = beamsec_data['Object']
if beamsec_obj.References:
count_femelements = 0
referenced_femelements = []
has_remaining_femelements = None
for fem_object_i, fem_object in enumerate(fem_objects):
obj = fem_object['Object']
fem_object['ShortName'] = get_ccx_elset_short_name(obj, fem_object_i) # unique short ccx_identifier
if obj.References:
ref_shape_femelements = []
for ref in beamsec_obj.References:
nodeids = []
elemids = []
for ref in obj.References:
femnodes = []
femelements = []
r = ref[0].Shape.getElement(ref[1])
print(' ReferenceShape : ', r.ShapeType, ', ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1])
if r.ShapeType == 'Edge':
# print(' BeamSectionReferenceEdge : ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1])
nodeids = self.mesh_object.FemMesh.getNodesByEdge(r)
elemids = getFemElementsByNodes(self.fem_element_table, nodeids)
femnodes = self.mesh_object.FemMesh.getNodesByEdge(r)
elif r.ShapeType == 'Face':
femnodes = self.mesh_object.FemMesh.getNodesByFace(r)
elif r.ShapeType == 'Solid':
# femnodes = self.mesh_object.FemMesh.getNodesBySolid(r) --> TODO
FreeCAD.Console.PrintError('Solid Reference Shapes, CalculiX input file may be broken!\n')
fem_object['FEMElements'] = self.ccx_eall
return
else:
print(' No Edge, but BeamSection needs Edges as reference shapes!')
ref_shape_femelements += elemids
referenced_femelements_beamsection += elemids
count_femelements_beamsection += len(elemids)
beamsec_data['FEMElements'] = ref_shape_femelements
print(' No Edge, Face or Solid as reference shapes!')
femelements = getFemElementsByNodes(self.fem_element_table, femnodes)
ref_shape_femelements += femelements
referenced_femelements += femelements
count_femelements += len(femelements)
fem_object['FEMElements'] = ref_shape_femelements
else:
has_remaining_femelements_beamsection = beamsec_obj.Name
# get remaining femelements for the beamsection objects
if has_remaining_femelements_beamsection:
remaining_femelements_beamsection = []
has_remaining_femelements = obj.Name
# get remaining femelements for the fem_objects
if has_remaining_femelements:
remaining_femelements = []
for elemid in self.fem_element_table:
if elemid not in referenced_femelements_beamsection:
remaining_femelements_beamsection.append(elemid)
count_femelements_beamsection += len(remaining_femelements_beamsection)
for beamsec_data in self.beamsection_objects:
beamsec_obj = beamsec_data['Object']
if beamsec_obj.Name == has_remaining_femelements_beamsection:
beamsec_data['FEMElements'] = sorted(remaining_femelements_beamsection)
if elemid not in referenced_femelements:
remaining_femelements.append(elemid)
count_femelements += len(remaining_femelements)
for fem_object in fem_objects:
obj = fem_object['Object']
if obj.Name == has_remaining_femelements:
fem_object['FEMElements'] = sorted(remaining_femelements)
# check if all worked out well
if not femelements_count_ok(self.fem_element_table, count_femelements_beamsection):
FreeCAD.Console.PrintError('Error in BeamSection -- > femelements_count_ok failed!\n')
def get_shellthickness_element_sets(self):
# get femelements for reference shapes of each shellth_obj
if not hasattr(self, 'fem_element_table'):
self.fem_element_table = getFemElementTable(self.mesh_object.FemMesh)
count_femelements_shellthickness = 0
referenced_femelements_shellthickness = []
has_remaining_femelements_shellthickness = None
for shellth_data_i, shellth_data in enumerate(self.shellthickness_objects):
shellth_data['ShortName'] = 'Shell' + str(shellth_data_i) # unique short ccx_identifier
shellth_obj = shellth_data['Object']
if shellth_obj.References:
ref_shape_femelements = []
for ref in shellth_obj.References:
nodeids = []
elemids = []
r = ref[0].Shape.getElement(ref[1])
if r.ShapeType == 'Face':
# print(' ShellThicknessReferenceFace : ', ref[0].Name, ', ', ref[0].Label, ' --> ', ref[1])
nodeids = self.mesh_object.FemMesh.getNodesByFace(r)
elemids = getFemElementsByNodes(self.fem_element_table, nodeids)
else:
print(' No Face, but ShellThickness needs Faces as reference shapes!')
ref_shape_femelements += elemids
referenced_femelements_shellthickness += elemids
count_femelements_shellthickness += len(elemids)
shellth_data['FEMElements'] = ref_shape_femelements
else:
has_remaining_femelements_shellthickness = shellth_obj.Name
# get remaining femelements for the shellthickness objects
if has_remaining_femelements_shellthickness:
remaining_femelements_shellthickness = []
for elemid in self.fem_element_table:
if elemid not in referenced_femelements_shellthickness:
remaining_femelements_shellthickness.append(elemid)
count_femelements_shellthickness += len(remaining_femelements_shellthickness)
for shellth_data in self.shellthickness_objects:
shellth_obj = shellth_data['Object']
if shellth_obj.Name == has_remaining_femelements_shellthickness:
shellth_data['FEMElements'] = sorted(remaining_femelements_shellthickness)
# check if all worked out well
if not femelements_count_ok(self.fem_element_table, count_femelements_shellthickness):
FreeCAD.Console.PrintError('Error in ShellThickness -- > femelements_count_ok failed!\n')
if not femelements_count_ok(self.fem_element_table, count_femelements):
FreeCAD.Console.PrintError('Error in get_femelement_sets -- > femelements_count_ok failed!\n')
# Helpers
@ -812,3 +765,14 @@ def get_ccx_elset_solid_name(mat_name, solid_name=None, mat_short_name=None):
return mat_short_name + solid_name
else:
return mat_name + solid_name
def get_ccx_elset_short_name(obj, i):
if hasattr(obj, "Proxy") and obj.Proxy.Type == 'MechanicalMaterial':
return 'Mat' + str(i)
elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemBeamSection':
return 'Beam' + str(i)
elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemShellThickness':
return 'Shell' + str(i)
else:
print 'Error: ', obj.Name, ' --> ', obj.Proxy.Type