From 6ba8b864d5cf43b30b37c18574514c638e011897 Mon Sep 17 00:00:00 2001 From: Yorik van Havre Date: Mon, 16 Nov 2015 16:11:32 -0200 Subject: [PATCH 1/8] Arch: Fixed flipped Space names --- src/Mod/Arch/ArchSectionPlane.py | 6 ++++-- src/Mod/Draft/Draft.py | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/Mod/Arch/ArchSectionPlane.py b/src/Mod/Arch/ArchSectionPlane.py index a423027f77..3e6ca0e509 100644 --- a/src/Mod/Arch/ArchSectionPlane.py +++ b/src/Mod/Arch/ArchSectionPlane.py @@ -324,9 +324,11 @@ class _ArchDrawingView: svg = svg.replace('SWPlaceholder', str(linewidth*st) + 'px') svg = svg.replace('DAPlaceholder', str(da)) if hasattr(self,"spaces"): - if round(self.direction.getAngle(FreeCAD.Vector(0,0,1)),Draft.precision()) in [0,round(math.pi,Draft.precision())]: + if self.spaces and round(self.direction.getAngle(FreeCAD.Vector(0,0,1)),Draft.precision()) in [0,round(math.pi,Draft.precision())]: + svg += '' for s in self.spaces: svg += Draft.getSVG(s,scale=obj.Scale,fontsize=obj.FontSize.Value,direction=self.direction) + svg += '' result = '' result += ' Date: Mon, 16 Nov 2015 18:07:14 +0000 Subject: [PATCH 2/8] FEM, Tests: Force unix line ends for comparing calculation stats Signed-off-by: Przemo Firszt --- src/Mod/Fem/TestFem.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index f53b3faff3..74488e43b8 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -134,15 +134,21 @@ class FemTest(unittest.TestCase): return result def compare_stats(self, fea, stat_file=None): + sf_content_normalised = [] if stat_file: sf = open(stat_file, 'r') sf_content = sf.readlines() sf.close() + # Force \n line ends + for line in sf_content: + if line.endswith("\r\n"): + line = line[:-2] + '\n' + sf_content_normalised.append(line) stat_types = ["U1", "U2", "U3", "Uabs", "Sabs"] stats = [] for s in stat_types: stats.append("{}: {}\n".format(s, fea.get_stats(s))) - if sf_content != stats: + if sf_content_normalised != stats: fcc_print("Expected stats from {}".format(stat_file)) fcc_print(sf_content) fcc_print("Stats read from {}.frd file".format(fea.base_name)) From 5b10de8d05578bc35a6dbfeb931b3e22de7ed5a7 Mon Sep 17 00:00:00 2001 From: fandaL Date: Sat, 31 Oct 2015 23:47:14 +0100 Subject: [PATCH 3/8] FEM: frd import mesh --- src/Mod/Fem/ccxFrdReader.py | 111 +++++++++++++++++++++++++++++++++--- 1 file changed, 103 insertions(+), 8 deletions(-) diff --git a/src/Mod/Fem/ccxFrdReader.py b/src/Mod/Fem/ccxFrdReader.py index 0fb0dbf17c..86e883b1de 100644 --- a/src/Mod/Fem/ccxFrdReader.py +++ b/src/Mod/Fem/ccxFrdReader.py @@ -38,7 +38,14 @@ if open.__module__ == '__builtin__': def readResult(frd_input): frd_file = pyopen(frd_input, "r") nodes = {} - elements = {} + elements_hexa8 = {} + elements_tetra4 = {} + elements_tetra10 = {} + elements_tria3 = {} + elements_tria6 = {} + elements_quad4 = {} + elements_quad8 = {} + elements_seg2 = {} results = [] mode_results = {} mode_disp = {} @@ -70,7 +77,25 @@ def readResult(frd_input): if elements_found and (line[1:3] == "-1"): elem = int(line[4:13]) elemType = int(line[14:18]) - #then the 10 id's for the Tet10 element + #then the 8 id's for the HEXA8 element + if elements_found and (line[1:3] == "-2") and elemType == 1: + node_id_5= int(line[3:13]) + node_id_6 = int(line[13:23]) + node_id_7 = int(line[23:33]) + node_id_8 = int(line[33:43]) + node_id_1 = int(line[43:53]) + node_id_2 = int(line[53:63]) + node_id_3 = int(line[63:73]) + node_id_4 = int(line[73:83]) + elements_hexa8[elem] = (node_id_1, node_id_2, node_id_3, node_id_4, node_id_5, node_id_6, node_id_7, node_id_8) + #then the 4 id's for the TETRA4 element + if elements_found and (line[1:3] == "-2") and elemType == 3: + node_id_2 = int(line[3:13]) + node_id_1 = int(line[13:23]) + node_id_3 = int(line[23:33]) + node_id_4 = int(line[33:43]) + elements_tetra4[elem] = (node_id_1, node_id_2, node_id_3, node_id_4) + #then the 10 id's for the TETRA10 element if elements_found and (line[1:3] == "-2") and elemType == 6: node_id_2 = int(line[3:13]) node_id_1 = int(line[13:23]) @@ -82,7 +107,46 @@ def readResult(frd_input): node_id_9 = int(line[73:83]) node_id_8 = int(line[83:93]) node_id_10 = int(line[93:103]) - elements[elem] = (node_id_1, node_id_2, node_id_3, node_id_4, node_id_5, node_id_6, node_id_7, node_id_8, node_id_9, node_id_10) + elements_tetra10[elem] = (node_id_1, node_id_2, node_id_3, node_id_4, node_id_5, node_id_6, node_id_7, node_id_8, node_id_9, node_id_10) + #then the 3 id's for the TRIA3 element + if elements_found and (line[1:3] == "-2") and elemType == 7: + node_id_1 = int(line[3:13]) + node_id_2 = int(line[13:23]) + node_id_3 = int(line[23:33]) + elements_tria3[elem] = (node_id_1, node_id_2, node_id_3) + #then the 6 id's for the TRIA6 element + if elements_found and (line[1:3] == "-2") and elemType == 8: + node_id_1 = int(line[3:13]) + node_id_2 = int(line[13:23]) + node_id_3 = int(line[23:33]) + node_id_4 = int(line[33:43]) + node_id_5 = int(line[43:53]) + node_id_6 = int(line[53:63]) + elements_tria6[elem] = (node_id_1, node_id_2, node_id_3, node_id_4, node_id_5, node_id_6) + #then the 4 id's for the QUAD4 element + if elements_found and (line[1:3] == "-2") and elemType == 9: + node_id_1 = int(line[3:13]) + node_id_2 = int(line[13:23]) + node_id_3 = int(line[23:33]) + node_id_4 = int(line[33:43]) + elements_quad4[elem] = (node_id_1, node_id_2, node_id_3, node_id_4) + #then the 8 id's for the QUAD8 element + if elements_found and (line[1:3] == "-2") and elemType == 10: + node_id_1 = int(line[3:13]) + node_id_2 = int(line[13:23]) + node_id_3 = int(line[23:33]) + node_id_4 = int(line[33:43]) + node_id_5 = int(line[43:53]) + node_id_6 = int(line[53:63]) + node_id_7 = int(line[63:73]) + node_id_8 = int(line[73:83]) + elements_quad8[elem] = (node_id_1, node_id_2, node_id_3, node_id_4, node_id_5, node_id_6, node_id_7, node_id_8) + #then the 2 id's for the SEG2 element + if elements_found and (line[1:3] == "-2") and elemType == 11: + node_id_1 = int(line[3:13]) + node_id_2 = int(line[13:23]) + elements_seg2[elem] = (node_id_1, node_id_2) + #Check if we found new eigenmode if line[5:10] == "PMODE": eigenmode = int(line[30:36]) @@ -129,7 +193,8 @@ def readResult(frd_input): elements_found = False frd_file.close() - return {'Nodes': nodes, 'Tet10Elem': elements, 'Results': results} + return {'Nodes': nodes, 'Hexa8Elem': elements_hexa8, 'Tetra4Elem': elements_tetra4, 'Tetra10Elem': elements_tetra10, 'Tria3Elem': elements_tria3, + 'Tria6Elem': elements_tria6, 'Quad4Elem': elements_quad4, 'Quad8Elem': elements_quad8, 'Seg2Elem': elements_seg2, 'Results': results} def calculate_von_mises(i): @@ -172,17 +237,47 @@ def importFrd(filename, Analysis=None): z_span = abs(p_z_max - p_z_min) span = max(x_span, y_span, z_span) - if ('Tet10Elem' in m) and ('Nodes' in m) and (not Analysis): + if (('Hexa8Elem' in m) or ('Tetra4Elem' in m) or ('Tetra10Elem' in m) or ('Tria3Elem' in m) or ('Tria6Elem' in m) or ('Quad4Elem' in m) or ('Quad8Elem' in m) or ('Seg2Elem' in m)) and ('Nodes' in m) and (not Analysis): mesh = Fem.FemMesh() nds = m['Nodes'] for i in nds: n = nds[i] mesh.addNode(n[0], n[1], n[2], i) - elms = m['Tet10Elem'] - for i in elms: - e = elms[i] + elms_hexa8 = m['Hexa8Elem'] + for i in elms_hexa8: + e = elms_hexa8[i] + mesh.addVolume([e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]], i) + elms_tetra4 = m['Tetra4Elem'] + for i in elms_tetra4: + e = elms_tetra4[i] + mesh.addVolume([e[0], e[1], e[2], e[3]], i) + elms_tetra10 = m['Tetra10Elem'] + for i in elms_tetra10: + e = elms_tetra10[i] mesh.addVolume([e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9]], i) + elms_tria3 = m['Tria3Elem'] + for i in elms_tria3: + e = elms_tria3[i] + mesh.addFace([e[0], e[1], e[2]], i) + elms_tria6 = m['Tria6Elem'] + for i in elms_tria6: + e = elms_tria6[i] + mesh.addFace([e[0], e[1], e[2], e[3], e[4], e[5]], i) + elms_quad4 = m['Quad4Elem'] + for i in elms_quad4: + e = elms_quad4[i] + mesh.addFace([e[0], e[1], e[2], e[3]], i) + elms_quad8 = m['Quad8Elem'] + for i in elms_quad8: + e = elms_quad8[i] + mesh.addFace([e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7]], i) + elms_seg2 = m['Seg2Elem'] + for i in elms_seg2: + e = elms_seg2[i] + mesh.addEdge(e[0], e[1]) + print ("imported mesh: %d nodes, %d HEXA8, %d TETRA4, %d TETRA10, %d TRIA3, %d TRIA6, %d QUAD4, %d QUAD8, %d SEG2" + %(len(nds), len(elms_hexa8), len(elms_tetra4), len(elms_tetra10), len(elms_tria3), len(elms_tria6), len(elms_quad4), len(elms_quad8), len(elms_seg2))) if len(nds) > 0: MeshObject = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', 'ResultMesh') MeshObject.FemMesh = mesh From 5df389f57a5026cd4fd709627229b5ce757cc753 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 15 Nov 2015 16:50:10 +0100 Subject: [PATCH 4/8] FEM: use proper command to create a Mechanical Anaylsis with all properties --- src/Mod/Fem/ccxFrdReader.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/ccxFrdReader.py b/src/Mod/Fem/ccxFrdReader.py index 86e883b1de..6aeb698f3f 100644 --- a/src/Mod/Fem/ccxFrdReader.py +++ b/src/Mod/Fem/ccxFrdReader.py @@ -220,7 +220,8 @@ def importFrd(filename, Analysis=None): import Fem if Analysis is None: AnalysisName = os.path.splitext(os.path.basename(filename))[0] - AnalysisObject = FreeCAD.ActiveDocument.addObject('Fem::FemAnalysis', 'Analysis') + import MechanicalAnalysis + AnalysisObject = MechanicalAnalysis.makeMechanicalAnalysis('Analysis') AnalysisObject.Label = AnalysisName else: AnalysisObject = Analysis From 90a9c387c4acbc1a7ac082929805d49be91a8371 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 15 Nov 2015 17:14:00 +0100 Subject: [PATCH 5/8] FEM: substitute some camel style variable names in frdReader --- src/Mod/Fem/ccxFrdReader.py | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/Mod/Fem/ccxFrdReader.py b/src/Mod/Fem/ccxFrdReader.py index 6aeb698f3f..a583115653 100644 --- a/src/Mod/Fem/ccxFrdReader.py +++ b/src/Mod/Fem/ccxFrdReader.py @@ -213,18 +213,18 @@ def calculate_von_mises(i): return vm_stress -def importFrd(filename, Analysis=None): +def importFrd(filename, analysis=None): m = readResult(filename) - MeshObject = None + mesh_object = None if(len(m['Nodes']) > 0): import Fem - if Analysis is None: - AnalysisName = os.path.splitext(os.path.basename(filename))[0] + if analysis is None: + analysis_name = os.path.splitext(os.path.basename(filename))[0] import MechanicalAnalysis - AnalysisObject = MechanicalAnalysis.makeMechanicalAnalysis('Analysis') - AnalysisObject.Label = AnalysisName + analysis_object = MechanicalAnalysis.makeMechanicalAnalysis('Analysis') + analysis_object.Label = analysis_name else: - AnalysisObject = Analysis + analysis_object = analysis # see if statement few lines later, if not analysis -> no FemMesh object is created ! if 'Nodes' in m: positions = [] @@ -238,7 +238,7 @@ def importFrd(filename, Analysis=None): z_span = abs(p_z_max - p_z_min) span = max(x_span, y_span, z_span) - if (('Hexa8Elem' in m) or ('Tetra4Elem' in m) or ('Tetra10Elem' in m) or ('Tria3Elem' in m) or ('Tria6Elem' in m) or ('Quad4Elem' in m) or ('Quad8Elem' in m) or ('Seg2Elem' in m)) and ('Nodes' in m) and (not Analysis): + if (not analysis) and ('Nodes' in m) and (('Hexa8Elem' in m) or ('Tetra4Elem' in m) or ('Tetra10Elem' in m) or ('Tria3Elem' in m) or ('Tria6Elem' in m) or ('Quad4Elem' in m) or ('Quad8Elem' in m) or ('Seg2Elem' in m)): mesh = Fem.FemMesh() nds = m['Nodes'] @@ -280,9 +280,9 @@ def importFrd(filename, Analysis=None): print ("imported mesh: %d nodes, %d HEXA8, %d TETRA4, %d TETRA10, %d TRIA3, %d TRIA6, %d QUAD4, %d QUAD8, %d SEG2" %(len(nds), len(elms_hexa8), len(elms_tetra4), len(elms_tetra10), len(elms_tria3), len(elms_tria6), len(elms_quad4), len(elms_quad8), len(elms_seg2))) if len(nds) > 0: - MeshObject = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', 'ResultMesh') - MeshObject.FemMesh = mesh - AnalysisObject.Member = AnalysisObject.Member + [MeshObject] + mesh_object = FreeCAD.ActiveDocument.addObject('Fem::FemMeshObject', 'ResultMesh') + mesh_object.FemMesh = mesh + analysis_object.Member = analysis_object.Member + [mesh_object] for result_set in m['Results']: eigenmode_number = result_set['number'] @@ -311,8 +311,8 @@ def importFrd(filename, Analysis=None): if len(disp) > 0: results.DisplacementVectors = map((lambda x: x * scale), disp.values()) results.NodeNumbers = disp.keys() - if(MeshObject): - results.Mesh = MeshObject + if(mesh_object): + results.Mesh = mesh_object stress = result_set['stress'] if len(stress) > 0: @@ -354,11 +354,11 @@ def importFrd(filename, Analysis=None): z_min, z_avg, z_max, a_min, a_avg, a_max, s_min, s_avg, s_max] - AnalysisObject.Member = AnalysisObject.Member + [results] + analysis_object.Member = analysis_object.Member + [results] if(FreeCAD.GuiUp): import FemGui - FemGui.setActiveAnalysis(AnalysisObject) + FemGui.setActiveAnalysis(analysis_object) def insert(filename, docname): From 63189bd85493a369d385a2d20a0a54a5dd20bf8a Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 16 Nov 2015 06:39:25 +0100 Subject: [PATCH 6/8] FEM: add some documentation to FemTools --- src/Mod/Fem/FemTools.py | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/Mod/Fem/FemTools.py b/src/Mod/Fem/FemTools.py index 59bb85b021..f029da64f6 100644 --- a/src/Mod/Fem/FemTools.py +++ b/src/Mod/Fem/FemTools.py @@ -152,6 +152,9 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): ## @var mesh # mesh of the analysis. Used to generate .inp file and to show results self.mesh = None + ## @var materials + # set of materials from the analysis. Updated with update_objects + # Induvidual materials are "App::MaterialObjectPython" type self.materials = [] ## @var fixed_constraints # set of fixed constraints from the analysis. Updated with update_objects @@ -165,7 +168,13 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): # set of pressure constraints from the analysis. Updated with update_objects # Individual constraints are "Fem::ConstraintPressure" type self.pressure_constraints = [] + ## @var beam_sections + # set of beam sections from the analyis. Updated with update_objects + # Individual beam sections are Proxy.Type "FemBeamSection" self.beam_sections = [] + ## @var shell_thicknesses + # set of shell thicknesses from the analyis. Updated with update_objects + # Individual shell thicknesses are Proxy.Type "FemShellThickness" self.shell_thicknesses = [] for m in self.analysis.Member: @@ -187,11 +196,11 @@ class FemTools(QtCore.QRunnable, QtCore.QObject): PressureObjectDict = {} PressureObjectDict['Object'] = m self.pressure_constraints.append(PressureObjectDict) - elif hasattr(m, "Proxy") and m.Proxy.Type == 'FemBeamSection': + elif hasattr(m, "Proxy") and m.Proxy.Type == "FemBeamSection": beam_section_dict = {} beam_section_dict['Object'] = m self.beam_sections.append(beam_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == 'FemShellThickness': + elif hasattr(m, "Proxy") and m.Proxy.Type == "FemShellThickness": shell_thickness_dict = {} shell_thickness_dict['Object'] = m self.shell_thicknesses.append(shell_thickness_dict) From 72a0060cfba8899ff6e6e8683da288e3e41ca248 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 16 Nov 2015 07:39:43 +0100 Subject: [PATCH 7/8] FEM: Mesh VP fix FreeCAD crash if not supported face is added to VP --- src/Mod/Fem/Gui/ViewProviderFemMesh.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp b/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp index bedb26aca9..9cc2dbaf96 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp @@ -779,9 +779,8 @@ void ViewProviderFEMMeshBuilder::createMesh(const App::Property* prop, case 6:// tria face with 6 nodes BndBox.Add(facesHelper[i++].set(6, aFace, aFace->GetID(), 0, aFace->GetNode(0), aFace->GetNode(1), aFace->GetNode(2), aFace->GetNode(3), aFace->GetNode(4), aFace->GetNode(5))); break; - - //unknown case - default: assert(0); + default://unknown face type + throw std::runtime_error("Node count not supported by ViewProviderFemMesh, [3|4|6] are allowed"); } } } From 2943188610c37f13b5afe140a8fc3ae5fe9c8167 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 16 Nov 2015 07:41:42 +0100 Subject: [PATCH 8/8] FEM: fix mixed line endings in VP FemMesh --- src/Mod/Fem/Gui/ViewProviderFemMesh.cpp | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp b/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp index 9cc2dbaf96..b1839ee074 100644 --- a/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp +++ b/src/Mod/Fem/Gui/ViewProviderFemMesh.cpp @@ -594,19 +594,19 @@ void ViewProviderFemMesh::setDisplacementByNodeIdHelper(const std::vectorpoint.getNum(); SbVec3f* verts = pcCoords->point.startEditing(); @@ -626,9 +626,9 @@ void ViewProviderFemMesh::applyDisplacementToNodes(double factor) verts[i].setValue(x,y,z); } pcCoords->point.finishEditing(); - - DisplacementFactor = factor; -} + + DisplacementFactor = factor; +} void ViewProviderFemMesh::setColorByElementId(const std::map &ElementColorMap) {