From 58b41b95509eeda8ddce6cb7c6a0da3a6e25d9ce 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 a423027f7..3e6ca0e50 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 f53b3faff..74488e43b 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 36ffb450f1e8d1dd44764f4515840b8ea664cd41 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 0fb0dbf17..86e883b1d 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 d14e79eafa5f2509921e7f93420362d8f9ed0316 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 86e883b1d..6aeb698f3 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 01d3b3ecad0f8a2f6207a9c45ac1b990835637c6 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 6aeb698f3..a58311565 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 eec2b566293fc2be855a98bc0ae6bf7aadcb8c46 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 59bb85b02..f029da64f 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 49b002beaf9fc1c168bc5bac58260c3a393683fe 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 bedb26aca..9cc2dbaf9 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 d37ac54c8e3c920789b684d95fa6d76b1c356204 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 9cc2dbaf9..b1839ee07 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) {