From 66889de9fed32ec5bd263dc6af454c26c5095d0d Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sun, 11 Jul 2021 10:30:27 -0500 Subject: [PATCH 01/19] Path: Correct the processing of selected edges The recent Extensions upgrade for Adaptive disabled the processing of selected edges. This commit re-enables that capability. Issue raised in forum at, https://forum.freecadweb.org/viewtopic.php?f=15&t=60037 --- src/Mod/Path/PathScripts/PathAdaptive.py | 25 ++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathAdaptive.py b/src/Mod/Path/PathScripts/PathAdaptive.py index 06cc36774f..ee2ea7ecd0 100644 --- a/src/Mod/Path/PathScripts/PathAdaptive.py +++ b/src/Mod/Path/PathScripts/PathAdaptive.py @@ -579,16 +579,21 @@ def _get_working_edges(op, obj): # Get faces selected by user for base, subs in obj.Base: for sub in subs: - if sub not in avoidFeatures: - if obj.UseOutline: - face = base.Shape.getElement(sub) - # get outline with wire_A method used in PocketShape, but it does not play nicely later - # wire_A = TechDraw.findShapeOutline(face, 1, FreeCAD.Vector(0.0, 0.0, 1.0)) - wire_B = face.Wires[0] - shape = Part.Face(wire_B) - else: - shape = base.Shape.getElement(sub) - regions.append(shape) + if sub.startswith("Face"): + if sub not in avoidFeatures: + if obj.UseOutline: + face = base.Shape.getElement(sub) + # get outline with wire_A method used in PocketShape, but it does not play nicely later + # wire_A = TechDraw.findShapeOutline(face, 1, FreeCAD.Vector(0.0, 0.0, 1.0)) + wire_B = face.Wires[0] + shape = Part.Face(wire_B) + else: + shape = base.Shape.getElement(sub) + regions.append(shape) + elif sub.startswith("Edge"): + # Discretize selected edges directly + shape = base.Shape.getElement(sub) + edge_list.append([discretize(shape)]) # Efor # Return Extend Outline extension, OR regular edge extension From 7320b6d716b85474ce032877c502c7f6d73dcb92 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Wed, 14 Jul 2021 20:56:34 -0500 Subject: [PATCH 02/19] Path: Implement the Extensions feature with selected edges --- src/Mod/Path/PathScripts/PathAdaptive.py | 47 +++++++++++++++++------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathAdaptive.py b/src/Mod/Path/PathScripts/PathAdaptive.py index ee2ea7ecd0..6ece55493f 100644 --- a/src/Mod/Path/PathScripts/PathAdaptive.py +++ b/src/Mod/Path/PathScripts/PathAdaptive.py @@ -42,6 +42,7 @@ Part = LazyLoader('Part', globals(), 'Part') FeatureExtensions = LazyLoader('PathScripts.PathFeatureExtensions', globals(), 'PathScripts.PathFeatureExtensions') +DraftGeomUtils = LazyLoader('DraftGeomUtils', globals(), 'DraftGeomUtils') if FreeCAD.GuiUp: from pivy import coin @@ -559,16 +560,16 @@ def Execute(op, obj): def _get_working_edges(op, obj): - """_get_working_edges(op, obj)... + '''_get_working_edges(op, obj)... Compile all working edges from the Base Geometry selection (obj.Base) for the current operation. Additional modifications to selected region(face), such as extensions, should be placed within this function. - """ - regions = list() + ''' all_regions = list() edge_list = list() avoidFeatures = list() + rawEdges = list() # Get extensions and identify faces to avoid extensions = FeatureExtensions.getExtensions(obj) @@ -589,15 +590,25 @@ def _get_working_edges(op, obj): shape = Part.Face(wire_B) else: shape = base.Shape.getElement(sub) - regions.append(shape) + all_regions.append(shape) elif sub.startswith("Edge"): - # Discretize selected edges directly - shape = base.Shape.getElement(sub) - edge_list.append([discretize(shape)]) + # Save edges for later processing + rawEdges.append(base.Shape.getElement(sub)) # Efor - # Return Extend Outline extension, OR regular edge extension - all_regions = regions + # Process selected edges + if rawEdges: + edgeWires = DraftGeomUtils.findWires(rawEdges) + if edgeWires: + for w in edgeWires: + # Extrude closed wire, take cross-section (flatten), and add area to regions list with faces + if w.isClosed(): + extLen = w.BoundBox.ZLength + 10.0 + extrudeWire = w.extrude(FreeCAD.Vector(0.0, 0.0, extLen * 5.0)) + slices = extrudeWire.slice(FreeCAD.Vector(0.0, 0.0, 1.0), math.floor(w.BoundBox.ZMin + (extLen * 2.5))) + slices[0].translate(FreeCAD.Vector(0.0, 0.0, 0.0 - slices[0].BoundBox.ZMin)) + all_regions.append(Part.Face(slices[0])) # Add wire area to all regions for combination with extensions + # Apply regular Extensions op.exts = [] # pylint: disable=attribute-defined-outside-init for ext in extensions: @@ -610,10 +621,12 @@ def _get_working_edges(op, obj): # Second face-combining method attempted horizontal = PathGeom.combineHorizontalFaces(all_regions) - for f in horizontal: - for w in f.Wires: - for e in w.Edges: - edge_list.append([discretize(e)]) + if horizontal: + obj.removalshape = Part.makeCompound(horizontal) + for f in horizontal: + for w in f.Wires: + for e in w.Edges: + edge_list.append([discretize(e)]) return edge_list @@ -667,6 +680,9 @@ class PathAdaptive(PathOp.ObjectOp): obj.addProperty("App::PropertyBool", "UseOutline", "Adaptive", "Uses the outline of the base geometry.") + obj.addProperty("Part::PropertyPartShape", "removalshape", "Path", "") + obj.setEditorMode('removalshape', 2) # hide + FeatureExtensions.initialize_properties(obj) def opSetDefaultValues(self, obj, job): @@ -708,6 +724,11 @@ class PathAdaptive(PathOp.ObjectOp): "UseOutline", "Adaptive", "Uses the outline of the base geometry.") + + if not hasattr(obj, "removalshape"): + obj.addProperty("Part::PropertyPartShape", "removalshape", "Path", "") + obj.setEditorMode('removalshape', 2) # hide + FeatureExtensions.initialize_properties(obj) From 6108f9982e02a771237352d7aeb8b934aa02e1ec Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Thu, 22 Jul 2021 23:16:53 -0500 Subject: [PATCH 03/19] Path: Add some `Adaptive` unit tests Also includes alphabetical sort of affected lists in CMakeLists and TestPathApp files. Unit tests focus around feature selection capabilities. --- src/Mod/Path/CMakeLists.txt | 12 +- src/Mod/Path/PathTests/TestPathAdaptive.py | 544 +++++++++++++++++++++ src/Mod/Path/PathTests/test_adaptive.fcstd | Bin 0 -> 17180 bytes src/Mod/Path/TestPathApp.py | 79 +-- 4 files changed, 594 insertions(+), 41 deletions(-) create mode 100644 src/Mod/Path/PathTests/TestPathAdaptive.py create mode 100644 src/Mod/Path/PathTests/test_adaptive.fcstd diff --git a/src/Mod/Path/CMakeLists.txt b/src/Mod/Path/CMakeLists.txt index 6b78b5ea38..827727befe 100644 --- a/src/Mod/Path/CMakeLists.txt +++ b/src/Mod/Path/CMakeLists.txt @@ -194,7 +194,14 @@ SET(Tools_Shape_SRCS SET(PathTests_SRCS PathTests/__init__.py + PathTests/boxtest.fcstd PathTests/PathTestUtils.py + PathTests/test_adaptive.fcstd + PathTests/test_centroid_00.ngc + PathTests/test_geomop.fcstd + PathTests/test_holes00.fcstd + PathTests/test_linuxcnc_00.ngc + PathTests/TestPathAdaptive.py PathTests/TestPathCore.py PathTests/TestPathDeburr.py PathTests/TestPathDepthParams.py @@ -220,11 +227,6 @@ SET(PathTests_SRCS PathTests/Tools/Bit/test-path-tool-bit-bit-00.fctb PathTests/Tools/Library/test-path-tool-bit-library-00.fctl PathTests/Tools/Shape/test-path-tool-bit-shape-00.fcstd - PathTests/boxtest.fcstd - PathTests/test_centroid_00.ngc - PathTests/test_geomop.fcstd - PathTests/test_holes00.fcstd - PathTests/test_linuxcnc_00.ngc ) SET(PathImages_Ops diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py new file mode 100644 index 0000000000..56ccf52f88 --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -0,0 +1,544 @@ +# -*- coding: utf-8 -*- +# *************************************************************************** +# * Copyright (c) 2021 Russell Johnson (russ4262) * +# * * +# * 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 +import Part +import PathScripts.PathJob as PathJob +import PathScripts.PathAdaptive as PathAdaptive +import PathScripts.PathGeom as PathGeom +from PathTests.PathTestUtils import PathTestBase +if FreeCAD.GuiUp: + import PathScripts.PathAdaptiveGui as PathAdaptiveGui + import PathScripts.PathJobGui as PathJobGui + + +class TestPathAdaptive(PathTestBase): + '''Unit tests for the Adaptive operation.''' + + @classmethod + def setUpClass(cls): + '''setUpClass()... + This method is called upon instantiation of this test class. Add code and objects here + that are needed for the duration of the test() methods in this class. In other words, + set up the 'global' test environment here; use the `setUp()` method to set up a 'local' + test environment. + This method does not have access to the class `self` reference, but it + is able to call static methods within this same class. + ''' + + # Create a new document and create test geometry + # doc_title = "TestAdaptive" + # doc = FreeCAD.newDocument(doc_title) + # cls._createTestGeometry(doc) + + # Open existing document with test geometry + doc = FreeCAD.open(FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_adaptive.fcstd') + + # Create Job object, adding geometry objects from file opened above + job = PathJob.Create('Job', [doc.Fusion], None) + job.GeometryTolerance.Value = 0.001 + if FreeCAD.GuiUp: + job.ViewObject.Proxy = PathJobGui.ViewProvider(job.ViewObject) + + # Instantiate an Adaptive operation for quering available properties + prototype = PathAdaptive.Create("Adaptive") + prototype.Base = [(doc.Fusion, ["Face3"])] + prototype.Label = "Prototype" + _addViewProvider(prototype) + + doc.recompute() + + @classmethod + def tearDownClass(cls): + '''tearDownClass()... + This method is called prior to destruction of this test class. Add code and objects here + that cleanup the test environment after the test() methods in this class have been executed. + This method does not have access to the class `self` reference. This method + is able to call static methods within this same class. + ''' + # FreeCAD.Console.PrintMessage("TestPathAdaptive.tearDownClass()\n") + + # Do not close document unless unit tests are commandline only + if FreeCAD.GuiUp: + pass + else: + FreeCAD.closeDocument(FreeCAD.ActiveDocument.Name) + + @staticmethod + def _createTestGeometry(doc): + '''_createTestGeometry(doc)... + This contains the instructions to create test geometry for the unit tests in this class. + A simple example creation is provided. + ''' + + # Create a square donut + box0 = doc.addObject('Part::Box', 'Box0') # Box + box0.Length = 50.0 + box0.Width = 50.0 + box0.Height = 10.0 + box1 = doc.addObject('Part::Box', 'Box1') # Box001 + box1.Length = 10.0 # X + box1.Width = 10.0 # Y + box1.Height = 20.0 # Z + box1.Placement = FreeCAD.Placement(FreeCAD.Vector(10.0, 10.0, -5.0), FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0)) + cut0 = doc.addObject('Part::Cut', 'Cut0') + cut0.Base = box0 + cut0.Tool = box1 + doc.recompute() + + # Setup and tear down methods called before and after each unit test + def setUp(self): + '''setUp()... + This method is called prior to each `test()` method. Add code and objects here + that are needed for multiple `test()` methods. + ''' + self.doc = FreeCAD.ActiveDocument + self.con = FreeCAD.Console + + def tearDown(self): + '''tearDown()... + This method is called after each test() method. Add cleanup instructions here. + Such cleanup instructions will likely undo those in the setUp() method. + ''' + pass + + # Unit tests + def test00(self): + '''test00() Empty test: Verify default property values.''' + return + + def test01(self): + '''test01() Verify path generated on Face3.''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Face3"])] # (base, subs_list) + adaptive.Label = "test01+" + adaptive.Comment = "test01() Verify path generated on Face3." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + # moves = getGcodeMoves(adaptive.Path.Commands, includeRapids=False) + # operationMoves = "; ".join(moves) + # self.con.PrintMessage("test00_moves: " + operationMoves + "\n") + + # self.assertTrue(expected_moves_test01 == operationMoves, + # "expected_moves_test01: {}\noperationMoves: {}".format(expected_moves_test01, operationMoves)) + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + def test02(self): + '''test02() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) + adaptive.Label = "test02+" + adaptive.Comment = "test02() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + def test03(self): + '''test03() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different.''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Face3", "Face10"])] # (base, subs_list) + adaptive.Label = "test03+" + adaptive.Comment = "test03() Verify path generated on adjacent, combined Face3 and Face10. The Z heights are different." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = True + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + def test04(self): + '''test04() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19"])] # (base, subs_list) + adaptive.Label = "test04+" + adaptive.Comment = 'test04() Verify path generated non-closed edges with differing Z-heights that are closed with Z=1 projection: "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + def test05(self): + '''test05() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19"])] # (base, subs_list) + adaptive.Label = "test05+" + adaptive.Comment = 'test05() Verify path generated closed wire with differing Z-heights: "Edge13", "Edge7", "Edge9", "Edge2", "Edge8", "Edge15", "Edge30", "Edge31", "Edge29", "Edge19".' + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + def test06(self): + '''test06() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33"])] # (base, subs_list) + adaptive.Label = "test06+" + adaptive.Comment = 'test06() Verify path generated with outer and inner edge loops at same Z height: "Edge15", "Edge30", "Edge31", "Edge29", "Edge19", "Edge18", "Edge35", "Edge32", "Edge34", "Edge33".' + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + # Check command count + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + # Check if any paths originate inside inner hole of donut. They should not. + isInBox = False + edges = [self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"]] + square = Part.Wire(edges) + sqrBB = square.BoundBox + minPoint = FreeCAD.Vector(sqrBB.XMin, sqrBB.YMin, 0.0) + maxPoint = FreeCAD.Vector(sqrBB.XMax, sqrBB.YMax, 0.0) + for c in adaptive.Path.Commands: + if pathOriginatesInBox(c, minPoint, maxPoint): + isInBox = True + break + self.assertFalse(isInBox, "Paths originating within the inner hole.") + + def test07(self): + '''test07() Verify path generated on donut-shaped Face10.''' + + # Instantiate a Adaptive operation and set Base Geometry + adaptive = PathAdaptive.Create('Adaptive') + adaptive.Base = [(self.doc.Fusion, ["Face10"])] # (base, subs_list) + adaptive.Label = "test07+" + adaptive.Comment = "test07() Verify path generated on donut-shaped Face10." + + # Set additional operation properties + # setDepthsAndHeights(adaptive) + adaptive.FinishingProfile = False + adaptive.HelixAngle = 75.0 + adaptive.HelixDiameterLimit.Value = 1.0 + adaptive.LiftDistance.Value = 1.0 + adaptive.StepOver = 75 + adaptive.UseOutline = False + adaptive.setExpression('StepDown', None) + adaptive.StepDown.Value = 20.0 # Have to set expression to None before numerical value assignment + + _addViewProvider(adaptive) + self.doc.recompute() + + self.assertTrue(len(adaptive.Path.Commands) > 100, "Command count not greater than 100.") + + # Check if any paths originate inside inner hole of donut. They should not. + isInBox = False + edges = [self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"]] + square = Part.Wire(edges) + sqrBB = square.BoundBox + minPoint = FreeCAD.Vector(sqrBB.XMin, sqrBB.YMin, 0.0) + maxPoint = FreeCAD.Vector(sqrBB.XMax, sqrBB.YMax, 0.0) + for c in adaptive.Path.Commands: + if pathOriginatesInBox(c, minPoint, maxPoint): + isInBox = True + break + self.assertFalse(isInBox, "Paths originating within the inner hole.") + + # Set Adaptive op to only use the outline of the face. + adaptive.UseOutline = True + self.doc.recompute() + + # Check if any paths originate inside inner hole of donut. They should not. + isInBox = False + edges = [self.doc.Fusion.Shape.getElement(e) for e in ["Edge35", "Edge32", "Edge33", "Edge34"]] + square = Part.Wire(edges) + sqrBB = square.BoundBox + minPoint = FreeCAD.Vector(sqrBB.XMin, sqrBB.YMin, 0.0) + maxPoint = FreeCAD.Vector(sqrBB.XMax, sqrBB.YMax, 0.0) + for c in adaptive.Path.Commands: + if pathOriginatesInBox(c, minPoint, maxPoint): + isInBox = True + break + self.assertTrue(isInBox, "No paths originating within the inner hole.") +# Eclass + + +def setDepthsAndHeights(op, strDep=20.0, finDep=0.0): + '''setDepthsAndHeights(op, strDep=20.0, finDep=0.0)... Sets default depths and heights for `op` passed to it''' + + # Set start and final depth in order to eliminate effects of stock (and its default values) + op.setExpression('StartDepth', None) + op.StartDepth.Value = strDep + op.setExpression('FinalDepth', None) + op.FinalDepth.Value = finDep + + # Set step down so as to only produce one layer path + op.setExpression('StepDown', None) + op.StepDown.Value = 20.0 + + # Set Heights + # default values used + +def getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=True): + '''getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=True)... + Accepts command dict and returns point string coordinate. + ''' + gcode_list = list() + last = FreeCAD.Vector(0.0, 0.0, 0.0) + for c in cmdList: + p = c.Parameters + name = c.Name + if includeRapids and name in ["G0", "G00"]: + gcode = name + x = last.x + y = last.y + z = last.z + if p.get("X"): + x = round(p["X"], 2) + gcode += " X" + str(x) + if p.get("Y"): + y = round(p["Y"], 2) + gcode += " Y" + str(y) + if p.get("Z"): + z = round(p["Z"], 2) + gcode += " Z" + str(z) + last.x = x + last.y = y + last.z = z + gcode_list.append(gcode) + elif includeLines and name in ["G1", "G01"]: + gcode = name + x = last.x + y = last.y + z = last.z + if p.get("X"): + x = round(p["X"], 2) + gcode += " X" + str(x) + if p.get("Y"): + y = round(p["Y"], 2) + gcode += " Y" + str(y) + if p.get("Z"): + z = round(p["Z"], 2) + gcode += " Z" + str(z) + last.x = x + last.y = y + last.z = z + gcode_list.append(gcode) + elif includeArcs and name in ["G2", "G3", "G02", "G03"]: + gcode = name + x = last.x + y = last.y + z = last.z + i = 0.0 + j = 0.0 + k = 0.0 + if p.get("I"): + i = round(p["I"], 2) + gcode += " I" + str(i) + if p.get("J"): + j = round(p["J"], 2) + gcode += " J" + str(j) + if p.get("K"): + k = round(p["K"], 2) + gcode += " K" + str(k) + + if p.get("X"): + x = round(p["X"], 2) + gcode += " X" + str(x) + if p.get("Y"): + y = round(p["Y"], 2) + gcode += " Y" + str(y) + if p.get("Z"): + z = round(p["Z"], 2) + gcode += " Z" + str(z) + + gcode_list.append(gcode) + last.x = x + last.y = y + last.z = z + return gcode_list + + +def pathOriginatesInBox(cmd, minPoint, maxPoint): + p = cmd.Parameters + name = cmd.Name + if name in ["G0", "G00", "G1", "G01"]: + if p.get("X") and p.get("Y"): + x = p.get("X") + y = p.get("Y") + if x > minPoint.x and y > minPoint.y and x < maxPoint.x and y < maxPoint.y: + return True + return False + + + +def _addViewProvider(adaptiveOp): + if FreeCAD.GuiUp: + PathOpGui = PathAdaptiveGui.PathOpGui + cmdRes = PathAdaptiveGui.Command.res + adaptiveOp.ViewObject.Proxy = PathOpGui.ViewProvider(adaptiveOp.ViewObject, cmdRes) + + +# Expected moves for unit tests +expected_moves_test01 = "G1 X32.5 Y32.5 Z5.0; \ +G1 X17.5 Y32.5 Z5.0; \ +G1 X17.5 Y30.0 Z5.0; \ +G1 X32.5 Y30.0 Z5.0; \ +G1 X32.5 Y27.5 Z5.0; \ +G1 X17.5 Y27.5 Z5.0; \ +G1 X17.5 Y25.0 Z5.0; \ +G1 X32.5 Y25.0 Z5.0; \ +G1 X32.5 Y22.5 Z5.0; \ +G1 X17.5 Y22.5 Z5.0; \ +G1 X17.5 Y20.0 Z5.0; \ +G1 X32.5 Y20.0 Z5.0; \ +G1 X32.5 Y17.5 Z5.0; \ +G1 X17.5 Y17.5 Z5.0" + +expected_moves_test02 = "G1 X22.5 Y-17.5 Z15.0; \ +G1 X22.5 Y-22.5 Z15.0; \ +G1 X17.5 Y-22.5 Z15.0; \ +G1 X17.5 Y-17.5 Z15.0; \ +G1 X22.5 Y-17.5 Z15.0; \ +G1 X21.25 Y-18.75 Z15.0; \ +G1 X21.25 Y-21.25 Z15.0; \ +G1 X18.75 Y-21.25 Z15.0; \ +G1 X18.75 Y-18.75 Z15.0; \ +G1 X21.25 Y-18.75 Z15.0" + +expected_moves_test03 = "G1 X32.5 Y-22.5 Z5.0; \ +G1 X32.5 Y-22.76 Z5.0; \ +G3 I2.4 J-12.0 K0.0 X27.5 Y-25.01 Z5.0; \ +G1 X27.5 Y-25.0 Z5.0; \ +G1 X27.5 Y-22.5 Z5.0; \ +G1 X32.5 Y-22.5 Z5.0; \ +G1 X25.02 Y-27.5 Z5.0; \ +G3 I9.66 J-7.36 K0.0 X22.76 Y-32.5 Z5.0; \ +G1 X22.5 Y-32.5 Z5.0; \ +G1 X22.5 Y-27.5 Z5.0; \ +G1 X25.0 Y-27.5 Z5.0; \ +G1 X25.02 Y-27.5 Z5.0" + +expected_moves_test04 = "G1 X25.0 Y-15.0 Z15.0; \ +G1 X15.0 Y-15.0 Z15.0; \ +G1 X15.0 Y-25.0 Z15.0; \ +G1 X25.0 Y-25.0 Z15.0; \ +G1 X25.0 Y-22.5 Z15.0; \ +G1 X22.5 Y-22.5 Z15.0; \ +G1 X22.5 Y-17.5 Z15.0; \ +G1 X17.5 Y-17.5 Z15.0; \ +G1 X17.5 Y-22.5 Z15.0; \ +G1 X22.5 Y-22.5 Z15.0; \ +G1 X25.0 Y-22.5 Z15.0; \ +G1 X25.0 Y-15.0 Z15.0" + +expected_moves_test05 = "G1 X32.5 Y32.5 Z5.0; \ +G1 X32.5 Y17.5 Z5.0; \ +G1 X17.5 Y17.5 Z5.0; \ +G1 X17.5 Y32.5 Z5.0; \ +G1 X32.5 Y32.5 Z5.0; \ +G1 X30.0 Y30.0 Z5.0; \ +G1 X30.0 Y20.0 Z5.0; \ +G1 X20.0 Y20.0 Z5.0; \ +G1 X20.0 Y30.0 Z5.0; \ +G1 X30.0 Y30.0 Z5.0; \ +G1 X27.5 Y27.5 Z5.0; \ +G1 X27.5 Y22.5 Z5.0; \ +G1 X22.5 Y22.5 Z5.0; \ +G1 X22.5 Y27.5 Z5.0; \ +G1 X27.5 Y27.5 Z5.0; \ +G1 X26.25 Y26.25 Z5.0; \ +G1 X26.25 Y23.75 Z5.0; \ +G1 X23.75 Y23.75 Z5.0; \ +G1 X23.75 Y26.25 Z5.0; \ +G1 X26.25 Y26.25 Z5.0" \ No newline at end of file diff --git a/src/Mod/Path/PathTests/test_adaptive.fcstd b/src/Mod/Path/PathTests/test_adaptive.fcstd new file mode 100644 index 0000000000000000000000000000000000000000..7af4b06f81e90c822d2dbd8c98ae2ab5a296e7cf GIT binary patch literal 17180 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 literal 0 HcmV?d00001 diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 0be621b040..e436dbd86c 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -22,50 +22,57 @@ import TestApp -from PathTests.TestPathLog import TestPathLog -from PathTests.TestPathPreferences import TestPathPreferences -from PathTests.TestPathPropertyBag import TestPathPropertyBag -from PathTests.TestPathCore import TestPathCore -#from PathTests.TestPathPost import PathPostTestCases -from PathTests.TestPathGeom import TestPathGeom -from PathTests.TestPathOpTools import TestPathOpTools -from PathTests.TestPathUtil import TestPathUtil +# from PathTests.TestPathPost import PathPostTestCases +from PathTests.TestPathAdaptive import TestPathAdaptive +""" +from PathTests.TestPathCore import TestPathCore +from PathTests.TestPathDeburr import TestPathDeburr from PathTests.TestPathDepthParams import depthTestCases -from PathTests.TestPathDressupHoldingTags import TestHoldingTags from PathTests.TestPathDressupDogbone import TestDressupDogbone -from PathTests.TestPathStock import TestPathStock -from PathTests.TestPathTool import TestPathTool -from PathTests.TestPathToolBit import TestPathToolBit -from PathTests.TestPathTooltable import TestPathTooltable -from PathTests.TestPathToolController import TestPathToolController +from PathTests.TestPathDressupHoldingTags import TestHoldingTags +from PathTests.TestPathGeom import TestPathGeom +from PathTests.TestPathHelix import TestPathHelix +from PathTests.TestPathLog import TestPathLog +from PathTests.TestPathOpTools import TestPathOpTools +from PathTests.TestPathPreferences import TestPathPreferences +from PathTests.TestPathPropertyBag import TestPathPropertyBag from PathTests.TestPathSetupSheet import TestPathSetupSheet -from PathTests.TestPathDeburr import TestPathDeburr -from PathTests.TestPathHelix import TestPathHelix -from PathTests.TestPathVoronoi import TestPathVoronoi -from PathTests.TestPathThreadMilling import TestPathThreadMilling -from PathTests.TestPathVcarve import TestPathVcarve +from PathTests.TestPathStock import TestPathStock +from PathTests.TestPathThreadMilling import TestPathThreadMilling +from PathTests.TestPathTool import TestPathTool +from PathTests.TestPathToolBit import TestPathToolBit +from PathTests.TestPathToolController import TestPathToolController +from PathTests.TestPathTooltable import TestPathTooltable +from PathTests.TestPathUtil import TestPathUtil +from PathTests.TestPathVcarve import TestPathVcarve +from PathTests.TestPathVoronoi import TestPathVoronoi +""" # dummy usage to get flake8 and lgtm quiet -False if TestApp.__name__ else True -False if TestPathLog.__name__ else True -False if TestPathCore.__name__ else True -False if TestPathGeom.__name__ else True -False if TestPathOpTools.__name__ else True -False if TestPathUtil.__name__ else True +""" False if depthTestCases.__name__ else True -False if TestHoldingTags.__name__ else True +False if TestApp.__name__ else True False if TestDressupDogbone.__name__ else True -False if TestPathStock.__name__ else True -False if TestPathTool.__name__ else True -False if TestPathTooltable.__name__ else True -False if TestPathToolController.__name__ else True -False if TestPathSetupSheet.__name__ else True +False if TestHoldingTags.__name__ else True +""" +False if TestPathAdaptive.__name__ else True +""" +False if TestPathCore.__name__ else True False if TestPathDeburr.__name__ else True +False if TestPathGeom.__name__ else True False if TestPathHelix.__name__ else True +False if TestPathLog.__name__ else True +False if TestPathOpTools.__name__ else True False if TestPathPreferences.__name__ else True -False if TestPathToolBit.__name__ else True -False if TestPathVoronoi.__name__ else True -False if TestPathThreadMilling.__name__ else True -False if TestPathVcarve.__name__ else True False if TestPathPropertyBag.__name__ else True - +False if TestPathSetupSheet.__name__ else True +False if TestPathStock.__name__ else True +False if TestPathThreadMilling.__name__ else True +False if TestPathTool.__name__ else True +False if TestPathToolBit.__name__ else True +False if TestPathToolController.__name__ else True +False if TestPathTooltable.__name__ else True +False if TestPathUtil.__name__ else True +False if TestPathVcarve.__name__ else True +False if TestPathVoronoi.__name__ else True +""" From 33650efbe8e4c97086775fc7a83a4cf909ffb075 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 10:59:43 -0500 Subject: [PATCH 04/19] Path: Delete dead code and comments --- src/Mod/Path/PathTests/TestPathAdaptive.py | 85 ---------------------- 1 file changed, 85 deletions(-) diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py index 56ccf52f88..96185ec192 100644 --- a/src/Mod/Path/PathTests/TestPathAdaptive.py +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -46,10 +46,6 @@ class TestPathAdaptive(PathTestBase): ''' # Create a new document and create test geometry - # doc_title = "TestAdaptive" - # doc = FreeCAD.newDocument(doc_title) - # cls._createTestGeometry(doc) - # Open existing document with test geometry doc = FreeCAD.open(FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_adaptive.fcstd') @@ -83,28 +79,6 @@ class TestPathAdaptive(PathTestBase): else: FreeCAD.closeDocument(FreeCAD.ActiveDocument.Name) - @staticmethod - def _createTestGeometry(doc): - '''_createTestGeometry(doc)... - This contains the instructions to create test geometry for the unit tests in this class. - A simple example creation is provided. - ''' - - # Create a square donut - box0 = doc.addObject('Part::Box', 'Box0') # Box - box0.Length = 50.0 - box0.Width = 50.0 - box0.Height = 10.0 - box1 = doc.addObject('Part::Box', 'Box1') # Box001 - box1.Length = 10.0 # X - box1.Width = 10.0 # Y - box1.Height = 20.0 # Z - box1.Placement = FreeCAD.Placement(FreeCAD.Vector(10.0, 10.0, -5.0), FreeCAD.Rotation(FreeCAD.Vector(0,0,1), 0)) - cut0 = doc.addObject('Part::Cut', 'Cut0') - cut0.Base = box0 - cut0.Tool = box1 - doc.recompute() - # Setup and tear down methods called before and after each unit test def setUp(self): '''setUp()... @@ -461,7 +435,6 @@ def pathOriginatesInBox(cmd, minPoint, maxPoint): return False - def _addViewProvider(adaptiveOp): if FreeCAD.GuiUp: PathOpGui = PathAdaptiveGui.PathOpGui @@ -484,61 +457,3 @@ G1 X17.5 Y20.0 Z5.0; \ G1 X32.5 Y20.0 Z5.0; \ G1 X32.5 Y17.5 Z5.0; \ G1 X17.5 Y17.5 Z5.0" - -expected_moves_test02 = "G1 X22.5 Y-17.5 Z15.0; \ -G1 X22.5 Y-22.5 Z15.0; \ -G1 X17.5 Y-22.5 Z15.0; \ -G1 X17.5 Y-17.5 Z15.0; \ -G1 X22.5 Y-17.5 Z15.0; \ -G1 X21.25 Y-18.75 Z15.0; \ -G1 X21.25 Y-21.25 Z15.0; \ -G1 X18.75 Y-21.25 Z15.0; \ -G1 X18.75 Y-18.75 Z15.0; \ -G1 X21.25 Y-18.75 Z15.0" - -expected_moves_test03 = "G1 X32.5 Y-22.5 Z5.0; \ -G1 X32.5 Y-22.76 Z5.0; \ -G3 I2.4 J-12.0 K0.0 X27.5 Y-25.01 Z5.0; \ -G1 X27.5 Y-25.0 Z5.0; \ -G1 X27.5 Y-22.5 Z5.0; \ -G1 X32.5 Y-22.5 Z5.0; \ -G1 X25.02 Y-27.5 Z5.0; \ -G3 I9.66 J-7.36 K0.0 X22.76 Y-32.5 Z5.0; \ -G1 X22.5 Y-32.5 Z5.0; \ -G1 X22.5 Y-27.5 Z5.0; \ -G1 X25.0 Y-27.5 Z5.0; \ -G1 X25.02 Y-27.5 Z5.0" - -expected_moves_test04 = "G1 X25.0 Y-15.0 Z15.0; \ -G1 X15.0 Y-15.0 Z15.0; \ -G1 X15.0 Y-25.0 Z15.0; \ -G1 X25.0 Y-25.0 Z15.0; \ -G1 X25.0 Y-22.5 Z15.0; \ -G1 X22.5 Y-22.5 Z15.0; \ -G1 X22.5 Y-17.5 Z15.0; \ -G1 X17.5 Y-17.5 Z15.0; \ -G1 X17.5 Y-22.5 Z15.0; \ -G1 X22.5 Y-22.5 Z15.0; \ -G1 X25.0 Y-22.5 Z15.0; \ -G1 X25.0 Y-15.0 Z15.0" - -expected_moves_test05 = "G1 X32.5 Y32.5 Z5.0; \ -G1 X32.5 Y17.5 Z5.0; \ -G1 X17.5 Y17.5 Z5.0; \ -G1 X17.5 Y32.5 Z5.0; \ -G1 X32.5 Y32.5 Z5.0; \ -G1 X30.0 Y30.0 Z5.0; \ -G1 X30.0 Y20.0 Z5.0; \ -G1 X20.0 Y20.0 Z5.0; \ -G1 X20.0 Y30.0 Z5.0; \ -G1 X30.0 Y30.0 Z5.0; \ -G1 X27.5 Y27.5 Z5.0; \ -G1 X27.5 Y22.5 Z5.0; \ -G1 X22.5 Y22.5 Z5.0; \ -G1 X22.5 Y27.5 Z5.0; \ -G1 X27.5 Y27.5 Z5.0; \ -G1 X26.25 Y26.25 Z5.0; \ -G1 X26.25 Y23.75 Z5.0; \ -G1 X23.75 Y23.75 Z5.0; \ -G1 X23.75 Y26.25 Z5.0; \ -G1 X26.25 Y26.25 Z5.0" \ No newline at end of file From 6b822558e631e907b81850a47a8d4ef62d3bafab Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 11:00:17 -0500 Subject: [PATCH 05/19] Path: Improve comments and docStrings --- src/Mod/Path/PathTests/TestPathAdaptive.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py index 96185ec192..5c95b581f7 100644 --- a/src/Mod/Path/PathTests/TestPathAdaptive.py +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -2,6 +2,8 @@ # *************************************************************************** # * Copyright (c) 2021 Russell Johnson (russ4262) * # * * +# * 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 * @@ -45,8 +47,7 @@ class TestPathAdaptive(PathTestBase): is able to call static methods within this same class. ''' - # Create a new document and create test geometry - # Open existing document with test geometry + # Open existing FreeCAD document with test geometry doc = FreeCAD.open(FreeCAD.getHomePath() + 'Mod/Path/PathTests/test_adaptive.fcstd') # Create Job object, adding geometry objects from file opened above @@ -97,7 +98,7 @@ class TestPathAdaptive(PathTestBase): # Unit tests def test00(self): - '''test00() Empty test: Verify default property values.''' + '''test00() Empty test.''' return def test01(self): @@ -343,6 +344,7 @@ def setDepthsAndHeights(op, strDep=20.0, finDep=0.0): # Set Heights # default values used + def getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=True): '''getGcodeMoves(cmdList, includeRapids=True, includeLines=True, includeArcs=True)... Accepts command dict and returns point string coordinate. @@ -442,7 +444,8 @@ def _addViewProvider(adaptiveOp): adaptiveOp.ViewObject.Proxy = PathOpGui.ViewProvider(adaptiveOp.ViewObject, cmdRes) -# Expected moves for unit tests +# Example string literal of expected path moves from an operation +# Expected moves for unit test01 expected_moves_test01 = "G1 X32.5 Y32.5 Z5.0; \ G1 X17.5 Y32.5 Z5.0; \ G1 X17.5 Y30.0 Z5.0; \ From e6d6301769b2f1f2e7a74924340721647221d898 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 11:42:30 -0500 Subject: [PATCH 06/19] Path: Restore edge processing to Adaptive as in 0.19 release --- src/Mod/Path/PathScripts/PathAdaptive.py | 9 ++------- src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py | 2 +- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/Mod/Path/PathScripts/PathAdaptive.py b/src/Mod/Path/PathScripts/PathAdaptive.py index 6ece55493f..f7b96cf96e 100644 --- a/src/Mod/Path/PathScripts/PathAdaptive.py +++ b/src/Mod/Path/PathScripts/PathAdaptive.py @@ -601,13 +601,8 @@ def _get_working_edges(op, obj): edgeWires = DraftGeomUtils.findWires(rawEdges) if edgeWires: for w in edgeWires: - # Extrude closed wire, take cross-section (flatten), and add area to regions list with faces - if w.isClosed(): - extLen = w.BoundBox.ZLength + 10.0 - extrudeWire = w.extrude(FreeCAD.Vector(0.0, 0.0, extLen * 5.0)) - slices = extrudeWire.slice(FreeCAD.Vector(0.0, 0.0, 1.0), math.floor(w.BoundBox.ZMin + (extLen * 2.5))) - slices[0].translate(FreeCAD.Vector(0.0, 0.0, 0.0 - slices[0].BoundBox.ZMin)) - all_regions.append(Part.Face(slices[0])) # Add wire area to all regions for combination with extensions + for e in w.Edges: + edge_list.append([discretize(e)]) # Apply regular Extensions op.exts = [] # pylint: disable=attribute-defined-outside-init diff --git a/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py b/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py index 4f7da3c630..078c28ee63 100644 --- a/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py +++ b/src/Mod/Path/PathScripts/PathFeatureExtensionsGui.py @@ -440,7 +440,7 @@ class TaskPanelExtensionPage(PathOpGui.TaskPanelPage): baseItem.setData(base[0].Label, QtCore.Qt.EditRole) baseItem.setSelectable(False) for sub in sorted(base[1]): - if sub.startswith('Face') or True: + if sub.startswith('Face'): show = True baseItem.appendRow(self.createItemForBaseModel(base[0], sub, edges, extensions)) if show: From 161388b5229b85aca2b5bfc70c6a0d3aafec4156 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 16:37:03 -0500 Subject: [PATCH 07/19] Path: Fix multi-OS path issue. Not all operating systems use the same path scheme - the slash direction. The issue fixed with this commit exists in other parts of the Path workbench --- src/Mod/Path/PathScripts/PathJobDlg.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Mod/Path/PathScripts/PathJobDlg.py b/src/Mod/Path/PathScripts/PathJobDlg.py index c7e98edda5..047c92280c 100644 --- a/src/Mod/Path/PathScripts/PathJobDlg.py +++ b/src/Mod/Path/PathScripts/PathJobDlg.py @@ -213,7 +213,8 @@ class JobCreate: def setupTemplate(self): templateFiles = [] for path in PathPreferences.searchPaths(): - templateFiles.extend(self.templateFilesIn(path)) + cleanPaths = [f.replace("\\", "/") for f in self.templateFilesIn(path)] # Standardize slashes used accross os platforms + templateFiles.extend(cleanPaths) template = {} for tFile in templateFiles: From 23b4c1363bc8bc904b73f370a6ec420b6cf336d4 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 21:39:25 -0500 Subject: [PATCH 08/19] Path: Re-enable all disabled Path unit tests --- src/Mod/Path/TestPathApp.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index e436dbd86c..961046d948 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -24,7 +24,6 @@ import TestApp # from PathTests.TestPathPost import PathPostTestCases from PathTests.TestPathAdaptive import TestPathAdaptive -""" from PathTests.TestPathCore import TestPathCore from PathTests.TestPathDeburr import TestPathDeburr from PathTests.TestPathDepthParams import depthTestCases @@ -46,17 +45,13 @@ from PathTests.TestPathTooltable import TestPathTooltable from PathTests.TestPathUtil import TestPathUtil from PathTests.TestPathVcarve import TestPathVcarve from PathTests.TestPathVoronoi import TestPathVoronoi -""" # dummy usage to get flake8 and lgtm quiet -""" False if depthTestCases.__name__ else True False if TestApp.__name__ else True False if TestDressupDogbone.__name__ else True False if TestHoldingTags.__name__ else True -""" False if TestPathAdaptive.__name__ else True -""" False if TestPathCore.__name__ else True False if TestPathDeburr.__name__ else True False if TestPathGeom.__name__ else True @@ -75,4 +70,3 @@ False if TestPathTooltable.__name__ else True False if TestPathUtil.__name__ else True False if TestPathVcarve.__name__ else True False if TestPathVoronoi.__name__ else True -""" From 249b3f5133950d343a75c96fb66662cd561998b4 Mon Sep 17 00:00:00 2001 From: Russell Johnson <47639332+Russ4262@users.noreply.github.com> Date: Sat, 24 Jul 2021 21:59:05 -0500 Subject: [PATCH 09/19] Path: Close Adaptive geometry source file upon unit test completion --- src/Mod/Path/PathTests/TestPathAdaptive.py | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py index 5c95b581f7..8e053df53d 100644 --- a/src/Mod/Path/PathTests/TestPathAdaptive.py +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -74,11 +74,8 @@ class TestPathAdaptive(PathTestBase): ''' # FreeCAD.Console.PrintMessage("TestPathAdaptive.tearDownClass()\n") - # Do not close document unless unit tests are commandline only - if FreeCAD.GuiUp: - pass - else: - FreeCAD.closeDocument(FreeCAD.ActiveDocument.Name) + # Close geometry document without saving + FreeCAD.closeDocument(FreeCAD.ActiveDocument.Name) # Setup and tear down methods called before and after each unit test def setUp(self): From 0c00f5e85c47d918951a16c8cd8f78c3656abc8c Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Thu, 22 Jul 2021 23:44:16 +0200 Subject: [PATCH 10/19] FEM: solver tasks, use same result reading method name in all solver --- src/Mod/Fem/femsolver/calculix/tasks.py | 14 +++++++++++--- src/Mod/Fem/femsolver/z88/tasks.py | 5 +++-- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/Mod/Fem/femsolver/calculix/tasks.py b/src/Mod/Fem/femsolver/calculix/tasks.py index ea99c1a347..40050b7d47 100644 --- a/src/Mod/Fem/femsolver/calculix/tasks.py +++ b/src/Mod/Fem/femsolver/calculix/tasks.py @@ -106,7 +106,8 @@ class Solve(run.Solve): [binary, "-i", _inputFileName], cwd=self.directory, stdout=subprocess.PIPE, - stderr=subprocess.PIPE) + stderr=subprocess.PIPE + ) self.signalAbort.add(self._process.terminate) # output = self._observeSolver(self._process) self._process.communicate() @@ -127,16 +128,23 @@ class Results(run.Results): "User parameter:BaseApp/Preferences/Mod/Fem/General") if not prefs.GetBool("KeepResultsOnReRun", False): self.purge_results() - self.load_results_ccxfrd() - self.load_results_ccxdat() + self.load_results() def purge_results(self): + + # dat file will not be removed + # results from other solvers will be removed too + # the user should decide if purge should only delete the solver results or all results for m in membertools.get_member(self.analysis, "Fem::FemResultObject"): if m.Mesh and femutils.is_of_type(m.Mesh, "Fem::MeshResult"): self.analysis.Document.removeObject(m.Mesh.Name) self.analysis.Document.removeObject(m.Name) self.analysis.Document.recompute() + def load_results(self): + self.load_results_ccxfrd() + self.load_results_ccxdat() + def load_results_ccxfrd(self): frd_result_file = os.path.join( self.directory, _inputFileName + ".frd") diff --git a/src/Mod/Fem/femsolver/z88/tasks.py b/src/Mod/Fem/femsolver/z88/tasks.py index e931c4d5bc..dc6fe696f3 100644 --- a/src/Mod/Fem/femsolver/z88/tasks.py +++ b/src/Mod/Fem/femsolver/z88/tasks.py @@ -112,7 +112,7 @@ class Results(run.Results): "User parameter:BaseApp/Preferences/Mod/Fem/General") if not prefs.GetBool("KeepResultsOnReRun", False): self.purge_results() - self.load_results_z88o2() + self.load_results() def purge_results(self): for m in membertools.get_member(self.analysis, "Fem::FemResultObject"): @@ -121,7 +121,8 @@ class Results(run.Results): self.analysis.Document.removeObject(m.Name) self.analysis.Document.recompute() - def load_results_z88o2(self): + def load_results(self): + # displacements from z88o2 file disp_result_file = os.path.join( self.directory, "z88o2.txt") if os.path.isfile(disp_result_file): From c0c1979a0abc8da758308e8750abbd24b36f56ac Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 17:35:41 +0200 Subject: [PATCH 11/19] FEM: calculix writer, constraint force, code formating --- src/Mod/Fem/femsolver/calculix/write_constraint_force.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_force.py b/src/Mod/Fem/femsolver/calculix/write_constraint_force.py index 8e5306b844..27554855eb 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_force.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_force.py @@ -48,7 +48,7 @@ def write_meshdata_constraint(f, femobj, force_obj, ccxwriter): direction_vec = femobj["Object"].DirectionVector for ref_shape in femobj["NodeLoadTable"]: - f.write("** " + ref_shape[0] + "\n") + f.write("** {}\n".format(ref_shape[0])) for n in sorted(ref_shape[1]): node_load = ref_shape[1][n] if (direction_vec.x != 0.0): From f71dd0c689206499193253342b20823d8d6f321c Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 17:43:15 +0200 Subject: [PATCH 12/19] FEM: examples, code formating, use double quotes whenever it is possible --- ...material_multiple_bendingbeam_fiveboxes.py | 44 ++-- ...material_multiple_bendingbeam_fivefaces.py | 42 ++-- .../square_pipe_end_twisted_edgeforces.py | 2 +- .../square_pipe_end_twisted_nodeforces.py | 198 +++++++++--------- 4 files changed, 143 insertions(+), 143 deletions(-) diff --git a/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fiveboxes.py b/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fiveboxes.py index f474e11587..1a85f49fd4 100644 --- a/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fiveboxes.py +++ b/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fiveboxes.py @@ -72,33 +72,33 @@ def setup(doc=None, solvertype="ccxtools"): # geometric objects # name is important because the other method in this module use obj name - box_obj1 = doc.addObject('Part::Box', 'Box1') + box_obj1 = doc.addObject("Part::Box", "Box1") box_obj1.Height = 10 box_obj1.Width = 10 box_obj1.Length = 20 - box_obj2 = doc.addObject('Part::Box', 'Box2') + box_obj2 = doc.addObject("Part::Box", "Box2") box_obj2.Height = 10 box_obj2.Width = 10 box_obj2.Length = 20 box_obj2.Placement.Base = (20, 0, 0) - box_obj3 = doc.addObject('Part::Box', 'Box3') + box_obj3 = doc.addObject("Part::Box", "Box3") box_obj3.Height = 10 box_obj3.Width = 10 box_obj3.Length = 20 box_obj3.Placement.Base = (40, 0, 0) - box_obj4 = doc.addObject('Part::Box', 'Box4') + box_obj4 = doc.addObject("Part::Box", "Box4") box_obj4.Height = 10 box_obj4.Width = 10 box_obj4.Length = 20 box_obj4.Placement.Base = (60, 0, 0) - box_obj5 = doc.addObject('Part::Box', 'Box5') + box_obj5 = doc.addObject("Part::Box", "Box5") box_obj5.Height = 10 box_obj5.Width = 10 box_obj5.Length = 20 box_obj5.Placement.Base = (80, 0, 0) # make a CompSolid out of the boxes, to be able to remesh with GUI - j = BOPTools.SplitFeatures.makeBooleanFragments(name='BooleanFragments') + j = BOPTools.SplitFeatures.makeBooleanFragments(name="BooleanFragments") j.Objects = [box_obj1, box_obj2, box_obj3, box_obj4, box_obj5] j.Mode = "CompSolid" j.Proxy.execute(j) @@ -108,7 +108,7 @@ def setup(doc=None, solvertype="ccxtools"): for obj in j.ViewObject.Proxy.claimChildren(): obj.ViewObject.hide() - geom_obj = doc.addObject('Part::Feature', 'CompSolid') + geom_obj = doc.addObject("Part::Feature", "CompSolid") geom_obj.Shape = j.Shape.CompSolids[0] if FreeCAD.GuiUp: j.ViewObject.hide() @@ -142,33 +142,33 @@ def setup(doc=None, solvertype="ccxtools"): analysis.addObject(solver_obj) # material - material_obj1 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial1') + material_obj1 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial1") material_obj1.References = [(doc.Box3, "Solid1")] mat = material_obj1.Material - mat['Name'] = "Concrete-Generic" - mat['YoungsModulus'] = "32000 MPa" - mat['PoissonRatio'] = "0.17" - mat['Density'] = "0 kg/m^3" + mat["Name"] = "Concrete-Generic" + mat["YoungsModulus"] = "32000 MPa" + mat["PoissonRatio"] = "0.17" + mat["Density"] = "0 kg/m^3" material_obj1.Material = mat analysis.addObject(material_obj1) - material_obj2 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial2') + material_obj2 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial2") material_obj2.References = [(doc.Box2, "Solid1"), (doc.Box4, "Solid1")] mat = material_obj2.Material - mat['Name'] = "PLA" - mat['YoungsModulus'] = "3640 MPa" - mat['PoissonRatio'] = "0.36" - mat['Density'] = "0 kg/m^3" + mat["Name"] = "PLA" + mat["YoungsModulus"] = "3640 MPa" + mat["PoissonRatio"] = "0.36" + mat["Density"] = "0 kg/m^3" material_obj2.Material = mat analysis.addObject(material_obj2) - material_obj3 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial3') + material_obj3 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial3") material_obj3.References = [] mat = material_obj3.Material - mat['Name'] = "Steel-Generic" - mat['YoungsModulus'] = "200000 MPa" - mat['PoissonRatio'] = "0.30" - mat['Density'] = "7900 kg/m^3" + mat["Name"] = "Steel-Generic" + mat["YoungsModulus"] = "200000 MPa" + mat["PoissonRatio"] = "0.30" + mat["Density"] = "7900 kg/m^3" material_obj3.Material = mat analysis.addObject(material_obj3) diff --git a/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fivefaces.py b/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fivefaces.py index 73bda48513..3a2ee24267 100644 --- a/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fivefaces.py +++ b/src/Mod/Fem/femexamples/material_multiple_bendingbeam_fivefaces.py @@ -71,22 +71,22 @@ def setup(doc=None, solvertype="ccxtools"): # geometric objects # name is important because the other method in this module use obj name # parts - face_obj1 = doc.addObject('Part::Plane', 'Face1') + face_obj1 = doc.addObject("Part::Plane", "Face1") face_obj1.Width = 10 face_obj1.Length = 20 - face_obj2 = doc.addObject('Part::Plane', 'Face2') + face_obj2 = doc.addObject("Part::Plane", "Face2") face_obj2.Width = 10 face_obj2.Length = 20 face_obj2.Placement.Base = (20, 0, 0) - face_obj3 = doc.addObject('Part::Plane', 'Face3') + face_obj3 = doc.addObject("Part::Plane", "Face3") face_obj3.Width = 10 face_obj3.Length = 20 face_obj3.Placement.Base = (40, 0, 0) - face_obj4 = doc.addObject('Part::Plane', 'Face4') + face_obj4 = doc.addObject("Part::Plane", "Face4") face_obj4.Width = 10 face_obj4.Length = 20 face_obj4.Placement.Base = (60, 0, 0) - face_obj5 = doc.addObject('Part::Plane', 'Face5') + face_obj5 = doc.addObject("Part::Plane", "Face5") face_obj5.Width = 10 face_obj5.Length = 20 face_obj5.Placement.Base = (80, 0, 0) @@ -131,40 +131,40 @@ def setup(doc=None, solvertype="ccxtools"): analysis.addObject(solver_obj) # shell thickness - thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 10, 'ShellThickness') + thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 10, "ShellThickness") analysis.addObject(thickness_obj) # materials - material_obj1 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial1') + material_obj1 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial1") material_obj1.References = [(doc.Face3, "Face1")] mat = material_obj1.Material - mat['Name'] = "Concrete-Generic" - mat['YoungsModulus'] = "32000 MPa" - mat['PoissonRatio'] = "0.17" - mat['Density'] = "0 kg/m^3" + mat["Name"] = "Concrete-Generic" + mat["YoungsModulus"] = "32000 MPa" + mat["PoissonRatio"] = "0.17" + mat["Density"] = "0 kg/m^3" material_obj1.Material = mat analysis.addObject(material_obj1) - material_obj2 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial2') + material_obj2 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial2") material_obj2.References = [ (doc.Face2, "Face1"), (doc.Face4, "Face1") ] mat = material_obj2.Material - mat['Name'] = "PLA" - mat['YoungsModulus'] = "3640 MPa" - mat['PoissonRatio'] = "0.36" - mat['Density'] = "0 kg/m^3" + mat["Name"] = "PLA" + mat["YoungsModulus"] = "3640 MPa" + mat["PoissonRatio"] = "0.36" + mat["Density"] = "0 kg/m^3" material_obj2.Material = mat analysis.addObject(material_obj2) - material_obj3 = ObjectsFem.makeMaterialSolid(doc, 'FemMaterial3') + material_obj3 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial3") material_obj3.References = [] mat = material_obj3.Material - mat['Name'] = "Steel-Generic" - mat['YoungsModulus'] = "200000 MPa" - mat['PoissonRatio'] = "0.30" - mat['Density'] = "7900 kg/m^3" + mat["Name"] = "Steel-Generic" + mat["YoungsModulus"] = "200000 MPa" + mat["PoissonRatio"] = "0.30" + mat["Density"] = "7900 kg/m^3" material_obj3.Material = mat analysis.addObject(material_obj3) diff --git a/src/Mod/Fem/femexamples/square_pipe_end_twisted_edgeforces.py b/src/Mod/Fem/femexamples/square_pipe_end_twisted_edgeforces.py index 1fe781983a..ea5baa76e9 100644 --- a/src/Mod/Fem/femexamples/square_pipe_end_twisted_edgeforces.py +++ b/src/Mod/Fem/femexamples/square_pipe_end_twisted_edgeforces.py @@ -79,7 +79,7 @@ def setup(doc=None, solvertype="ccxtools"): l4 = Part.makeLine((-142.5, 142.5, 0), (-142.5, -142.5, 0)) wire = Part.Wire([l1, l2, l3, l4]) shape = wire.extrude(Vector(0, 0, 1000)) - geom_obj = doc.addObject('Part::Feature', 'SquareTube') + geom_obj = doc.addObject("Part::Feature", "SquareTube") geom_obj.Shape = shape doc.recompute() diff --git a/src/Mod/Fem/femexamples/square_pipe_end_twisted_nodeforces.py b/src/Mod/Fem/femexamples/square_pipe_end_twisted_nodeforces.py index c2b4310fd4..fc0d6fb079 100644 --- a/src/Mod/Fem/femexamples/square_pipe_end_twisted_nodeforces.py +++ b/src/Mod/Fem/femexamples/square_pipe_end_twisted_nodeforces.py @@ -79,7 +79,7 @@ def setup(doc=None, solvertype="ccxtools"): l4 = Part.makeLine((-142.5, 142.5, 0), (-142.5, -142.5, 0)) wire = Part.Wire([l1, l2, l3, l4]) shape = wire.extrude(Vector(0, 0, 1000)) - geom_obj = doc.addObject('Part::Feature', 'SquareTube') + geom_obj = doc.addObject("Part::Feature", "SquareTube") geom_obj.Shape = shape points_forces = [] @@ -182,9 +182,9 @@ def setup(doc=None, solvertype="ccxtools"): points_fixes.append(Part.Vertex(-71.25, 142.5, 1000.0)) points_fixes.append(Part.Vertex(-118.75, 142.5, 1000.0)) - geoforces_obj = doc.addObject('Part::Feature', 'Forces') + geoforces_obj = doc.addObject("Part::Feature", "Forces") geoforces_obj.Shape = Part.makeCompound(points_forces) - geofixes_obj = doc.addObject('Part::Feature', 'Fixes') + geofixes_obj = doc.addObject("Part::Feature", "Fixes") geofixes_obj.Shape = Part.makeCompound(points_fixes) doc.recompute() @@ -237,59 +237,59 @@ def setup(doc=None, solvertype="ccxtools"): # constraint fixed con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed") con_fixed.References = [ - (geofixes_obj, 'Vertex6'), - (geofixes_obj, 'Vertex15'), - (geofixes_obj, 'Vertex5'), - (geofixes_obj, 'Vertex29'), - (geofixes_obj, 'Vertex42'), - (geofixes_obj, 'Vertex30'), - (geofixes_obj, 'Vertex9'), - (geofixes_obj, 'Vertex31'), - (geofixes_obj, 'Vertex33'), - (geofixes_obj, 'Vertex32'), - (geofixes_obj, 'Vertex3'), - (geofixes_obj, 'Vertex34'), - (geofixes_obj, 'Vertex46'), - (geofixes_obj, 'Vertex1'), - (geofixes_obj, 'Vertex36'), - (geofixes_obj, 'Vertex11'), - (geofixes_obj, 'Vertex38'), - (geofixes_obj, 'Vertex12'), - (geofixes_obj, 'Vertex39'), - (geofixes_obj, 'Vertex13'), - (geofixes_obj, 'Vertex40'), - (geofixes_obj, 'Vertex16'), - (geofixes_obj, 'Vertex35'), - (geofixes_obj, 'Vertex14'), - (geofixes_obj, 'Vertex47'), - (geofixes_obj, 'Vertex20'), - (geofixes_obj, 'Vertex37'), - (geofixes_obj, 'Vertex18'), - (geofixes_obj, 'Vertex41'), - (geofixes_obj, 'Vertex17'), - (geofixes_obj, 'Vertex10'), - (geofixes_obj, 'Vertex26'), - (geofixes_obj, 'Vertex43'), - (geofixes_obj, 'Vertex21'), - (geofixes_obj, 'Vertex44'), - (geofixes_obj, 'Vertex19'), - (geofixes_obj, 'Vertex4'), - (geofixes_obj, 'Vertex28'), - (geofixes_obj, 'Vertex48'), - (geofixes_obj, 'Vertex22'), - (geofixes_obj, 'Vertex8'), - (geofixes_obj, 'Vertex23'), - (geofixes_obj, 'Vertex7'), - (geofixes_obj, 'Vertex24'), - (geofixes_obj, 'Vertex45'), - (geofixes_obj, 'Vertex27'), - (geofixes_obj, 'Vertex2'), - (geofixes_obj, 'Vertex25')] + (geofixes_obj, "Vertex6"), + (geofixes_obj, "Vertex15"), + (geofixes_obj, "Vertex5"), + (geofixes_obj, "Vertex29"), + (geofixes_obj, "Vertex42"), + (geofixes_obj, "Vertex30"), + (geofixes_obj, "Vertex9"), + (geofixes_obj, "Vertex31"), + (geofixes_obj, "Vertex33"), + (geofixes_obj, "Vertex32"), + (geofixes_obj, "Vertex3"), + (geofixes_obj, "Vertex34"), + (geofixes_obj, "Vertex46"), + (geofixes_obj, "Vertex1"), + (geofixes_obj, "Vertex36"), + (geofixes_obj, "Vertex11"), + (geofixes_obj, "Vertex38"), + (geofixes_obj, "Vertex12"), + (geofixes_obj, "Vertex39"), + (geofixes_obj, "Vertex13"), + (geofixes_obj, "Vertex40"), + (geofixes_obj, "Vertex16"), + (geofixes_obj, "Vertex35"), + (geofixes_obj, "Vertex14"), + (geofixes_obj, "Vertex47"), + (geofixes_obj, "Vertex20"), + (geofixes_obj, "Vertex37"), + (geofixes_obj, "Vertex18"), + (geofixes_obj, "Vertex41"), + (geofixes_obj, "Vertex17"), + (geofixes_obj, "Vertex10"), + (geofixes_obj, "Vertex26"), + (geofixes_obj, "Vertex43"), + (geofixes_obj, "Vertex21"), + (geofixes_obj, "Vertex44"), + (geofixes_obj, "Vertex19"), + (geofixes_obj, "Vertex4"), + (geofixes_obj, "Vertex28"), + (geofixes_obj, "Vertex48"), + (geofixes_obj, "Vertex22"), + (geofixes_obj, "Vertex8"), + (geofixes_obj, "Vertex23"), + (geofixes_obj, "Vertex7"), + (geofixes_obj, "Vertex24"), + (geofixes_obj, "Vertex45"), + (geofixes_obj, "Vertex27"), + (geofixes_obj, "Vertex2"), + (geofixes_obj, "Vertex25")] analysis.addObject(con_fixed) # con_force1 con_force1 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce1") - con_force1.References = [(geoforces_obj, 'Vertex1'), (geoforces_obj, 'Vertex14')] + con_force1.References = [(geoforces_obj, "Vertex1"), (geoforces_obj, "Vertex14")] con_force1.Force = 5555.56 con_force1.Direction = (geom_obj, ["Edge9"]) con_force1.Reversed = False @@ -297,7 +297,7 @@ def setup(doc=None, solvertype="ccxtools"): # con_force2 con_force2 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce2") - con_force2.References = [(geoforces_obj, 'Vertex2'), (geoforces_obj, 'Vertex8')] + con_force2.References = [(geoforces_obj, "Vertex2"), (geoforces_obj, "Vertex8")] con_force2.Force = 5555.56 con_force2.Direction = (geom_obj, ["Edge3"]) con_force2.Reversed = False @@ -306,11 +306,11 @@ def setup(doc=None, solvertype="ccxtools"): # con_force3 con_force3 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce3") con_force3.References = [ - (geoforces_obj, 'Vertex20'), - (geoforces_obj, 'Vertex21'), - (geoforces_obj, 'Vertex22'), - (geoforces_obj, 'Vertex23'), - (geoforces_obj, 'Vertex24'), ] + (geoforces_obj, "Vertex20"), + (geoforces_obj, "Vertex21"), + (geoforces_obj, "Vertex22"), + (geoforces_obj, "Vertex23"), + (geoforces_obj, "Vertex24"), ] con_force3.Force = 27777.78 con_force3.Direction = (geom_obj, ["Edge9"]) con_force3.Reversed = False @@ -319,11 +319,11 @@ def setup(doc=None, solvertype="ccxtools"): # con_force4 con_force4 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce4") con_force4.References = [ - (geoforces_obj, 'Vertex9'), - (geoforces_obj, 'Vertex10'), - (geoforces_obj, 'Vertex11'), - (geoforces_obj, 'Vertex12'), - (geoforces_obj, 'Vertex13'), ] + (geoforces_obj, "Vertex9"), + (geoforces_obj, "Vertex10"), + (geoforces_obj, "Vertex11"), + (geoforces_obj, "Vertex12"), + (geoforces_obj, "Vertex13"), ] con_force4.Force = 27777.78 con_force4.Direction = (geom_obj, ["Edge3"]) con_force4.Reversed = False @@ -332,12 +332,12 @@ def setup(doc=None, solvertype="ccxtools"): # con_force5 con_force5 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce5") con_force5.References = [ - (geoforces_obj, 'Vertex43'), - (geoforces_obj, 'Vertex44'), - (geoforces_obj, 'Vertex45'), - (geoforces_obj, 'Vertex46'), - (geoforces_obj, 'Vertex47'), - (geoforces_obj, 'Vertex48'), ] + (geoforces_obj, "Vertex43"), + (geoforces_obj, "Vertex44"), + (geoforces_obj, "Vertex45"), + (geoforces_obj, "Vertex46"), + (geoforces_obj, "Vertex47"), + (geoforces_obj, "Vertex48"), ] con_force5.Force = 66666.67 con_force5.Direction = (geom_obj, ["Edge9"]) con_force5.Reversed = False @@ -346,12 +346,12 @@ def setup(doc=None, solvertype="ccxtools"): # con_force6 con_force6 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce6") con_force6.References = [ - (geoforces_obj, 'Vertex31'), - (geoforces_obj, 'Vertex32'), - (geoforces_obj, 'Vertex33'), - (geoforces_obj, 'Vertex34'), - (geoforces_obj, 'Vertex35'), - (geoforces_obj, 'Vertex36'), ] + (geoforces_obj, "Vertex31"), + (geoforces_obj, "Vertex32"), + (geoforces_obj, "Vertex33"), + (geoforces_obj, "Vertex34"), + (geoforces_obj, "Vertex35"), + (geoforces_obj, "Vertex36"), ] con_force6.Force = 66666.67 con_force6.Direction = (geom_obj, ["Edge3"]) con_force6.Reversed = False @@ -359,7 +359,7 @@ def setup(doc=None, solvertype="ccxtools"): # con_force7 con_force7 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce7") - con_force7.References = [(geoforces_obj, 'Vertex1'), (geoforces_obj, 'Vertex2')] + con_force7.References = [(geoforces_obj, "Vertex1"), (geoforces_obj, "Vertex2")] con_force7.Force = 5555.56 con_force7.Direction = (geom_obj, ["Edge11"]) con_force7.Reversed = False @@ -367,7 +367,7 @@ def setup(doc=None, solvertype="ccxtools"): # con_force8 con_force8 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce8") - con_force8.References = [(geoforces_obj, 'Vertex8'), (geoforces_obj, 'Vertex14')] + con_force8.References = [(geoforces_obj, "Vertex8"), (geoforces_obj, "Vertex14")] con_force8.Force = 5555.56 con_force8.Direction = (geom_obj, ["Edge6"]) con_force8.Reversed = False @@ -376,11 +376,11 @@ def setup(doc=None, solvertype="ccxtools"): # con_force9 con_force9 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce9") con_force9.References = [ - (geoforces_obj, 'Vertex3'), - (geoforces_obj, 'Vertex4'), - (geoforces_obj, 'Vertex5'), - (geoforces_obj, 'Vertex6'), - (geoforces_obj, 'Vertex7'), ] + (geoforces_obj, "Vertex3"), + (geoforces_obj, "Vertex4"), + (geoforces_obj, "Vertex5"), + (geoforces_obj, "Vertex6"), + (geoforces_obj, "Vertex7"), ] con_force9.Force = 27777.78 con_force9.Direction = (geom_obj, ["Edge11"]) con_force9.Reversed = False @@ -389,11 +389,11 @@ def setup(doc=None, solvertype="ccxtools"): # con_force10 con_force10 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce10") con_force10.References = [ - (geoforces_obj, 'Vertex15'), - (geoforces_obj, 'Vertex16'), - (geoforces_obj, 'Vertex17'), - (geoforces_obj, 'Vertex18'), - (geoforces_obj, 'Vertex19'), ] + (geoforces_obj, "Vertex15"), + (geoforces_obj, "Vertex16"), + (geoforces_obj, "Vertex17"), + (geoforces_obj, "Vertex18"), + (geoforces_obj, "Vertex19"), ] con_force10.Force = 27777.78 con_force10.Direction = (geom_obj, ["Edge6"]) con_force10.Reversed = False @@ -402,12 +402,12 @@ def setup(doc=None, solvertype="ccxtools"): # con_force11 con_force11 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce11") con_force11.References = [ - (geoforces_obj, 'Vertex25'), - (geoforces_obj, 'Vertex26'), - (geoforces_obj, 'Vertex27'), - (geoforces_obj, 'Vertex28'), - (geoforces_obj, 'Vertex29'), - (geoforces_obj, 'Vertex30'), ] + (geoforces_obj, "Vertex25"), + (geoforces_obj, "Vertex26"), + (geoforces_obj, "Vertex27"), + (geoforces_obj, "Vertex28"), + (geoforces_obj, "Vertex29"), + (geoforces_obj, "Vertex30"), ] con_force11.Force = 66666.67 con_force11.Direction = (geom_obj, ["Edge11"]) con_force11.Reversed = False @@ -416,12 +416,12 @@ def setup(doc=None, solvertype="ccxtools"): # con_force12 con_force12 = ObjectsFem.makeConstraintForce(doc, name="ConstraintForce12") con_force12.References = [ - (geoforces_obj, 'Vertex37'), - (geoforces_obj, 'Vertex38'), - (geoforces_obj, 'Vertex39'), - (geoforces_obj, 'Vertex40'), - (geoforces_obj, 'Vertex41'), - (geoforces_obj, 'Vertex42'), ] + (geoforces_obj, "Vertex37"), + (geoforces_obj, "Vertex38"), + (geoforces_obj, "Vertex39"), + (geoforces_obj, "Vertex40"), + (geoforces_obj, "Vertex41"), + (geoforces_obj, "Vertex42"), ] con_force12.Force = 66666.67 con_force12.Direction = (geom_obj, ["Edge6"]) con_force12.Reversed = False From 616ee70e34560ad819b9e1e883409ec443c08207 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 17:42:32 +0200 Subject: [PATCH 13/19] FEM: examples and unit tests, some heavy file renaming --- src/Mod/Fem/CMakeLists.txt | 79 ++++++++++--------- ...r_base.py => ccx_cantilever_base_solid.py} | 2 +- ...ceload.py => ccx_cantilever_ele_hexa20.py} | 3 +- .../femexamples/ccx_cantilever_faceload.py | 6 +- .../femexamples/ccx_cantilever_nodeload.py | 4 +- .../ccx_cantilever_prescribeddisplacement.py | 4 +- .../Fem/femtest/app/test_solver_calculix.py | 10 +-- src/Mod/Fem/femtest/app/test_solver_z88.py | 8 +- ...xa20.inp => ccx_cantilever_ele_hexa20.inp} | 0 ...ceload.inp => ccx_cantilever_faceload.inp} | 0 ...deload.inp => ccx_cantilever_nodeload.inp} | 0 ...ccx_cantilever_prescribeddisplacement.inp} | 0 .../51.txt | 0 .../z88.dyn | 0 .../z88elp.txt | 0 .../z88i1.txt | 0 .../z88i2.txt | 0 .../z88i5.txt | 0 .../z88int.txt | 0 .../z88man.txt | 0 .../z88mat.txt | 0 .../51.txt | 0 .../z88.dyn | 0 .../z88elp.txt | 0 .../z88i1.txt | 0 .../z88i2.txt | 0 .../z88i5.txt | 0 .../z88int.txt | 0 .../z88man.txt | 0 .../z88mat.txt | 0 .../51.txt | 0 .../z88.dyn | 0 .../z88elp.txt | 0 .../z88i1.txt | 0 .../z88i2.txt | 0 .../z88i5.txt | 0 .../z88int.txt | 0 .../z88man.txt | 0 .../z88mat.txt | 0 39 files changed, 62 insertions(+), 54 deletions(-) rename src/Mod/Fem/femexamples/{ccx_cantilever_base.py => ccx_cantilever_base_solid.py} (98%) rename src/Mod/Fem/femexamples/{ccx_cantilever_hexa20faceload.py => ccx_cantilever_ele_hexa20.py} (97%) rename src/Mod/Fem/femtest/data/calculix/{ccxcantilever_hexa20.inp => ccx_cantilever_ele_hexa20.inp} (100%) rename src/Mod/Fem/femtest/data/calculix/{ccxcantilever_faceload.inp => ccx_cantilever_faceload.inp} (100%) rename src/Mod/Fem/femtest/data/calculix/{ccxcantilever_nodeload.inp => ccx_cantilever_nodeload.inp} (100%) rename src/Mod/Fem/femtest/data/calculix/{ccxcantilever_prescribeddisplacement.inp => ccx_cantilever_prescribeddisplacement.inp} (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_ele_hexa20}/51.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_ele_hexa20}/z88.dyn (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_ele_hexa20}/z88elp.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_ele_hexa20}/z88i1.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_ele_hexa20}/z88i2.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_ele_hexa20}/z88i5.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_ele_hexa20}/z88int.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_ele_hexa20}/z88man.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_ele_hexa20}/z88mat.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_faceload}/51.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_faceload}/z88.dyn (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_faceload}/z88elp.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_faceload}/z88i1.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_faceload}/z88i2.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_faceload}/z88i5.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_faceload}/z88int.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_hexa20 => ccx_cantilever_faceload}/z88man.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_faceload => ccx_cantilever_faceload}/z88mat.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/51.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88.dyn (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88elp.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88i1.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88i2.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88i5.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88int.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88man.txt (100%) rename src/Mod/Fem/femtest/data/z88/{ccxcantilever_nodeload => ccx_cantilever_nodeload}/z88mat.txt (100%) diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 4ff7364a4d..9bcaf04f8e 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -48,10 +48,15 @@ SET(FemExamples_SRCS femexamples/buckling_platebuckling.py femexamples/buckling_lateraltorsionalbuckling.py femexamples/ccx_buckling_flexuralbuckling.py - femexamples/ccx_cantilever_base.py + femexamples/ccx_cantilever_base_face.py + femexamples/ccx_cantilever_base_solid.py + femexamples/ccx_cantilever_ele_hexa20.py + femexamples/ccx_cantilever_ele_tetra4.py + femexamples/ccx_cantilever_ele_tria3.py + femexamples/ccx_cantilever_ele_tria6.py + femexamples/ccx_cantilever_ele_seg3.py femexamples/ccx_cantilever_faceload.py femexamples/ccx_cantilever_nodeload.py - femexamples/ccx_cantilever_hexa20faceload.py femexamples/ccx_cantilever_prescribeddisplacement.py femexamples/constraint_centrif.py femexamples/constraint_contact_shell_shell.py @@ -87,7 +92,9 @@ SET(FemExampleMeshes_SRCS femexamples/meshes/mesh_buckling_ibeam_tria6.py femexamples/meshes/mesh_buckling_plate_tria6.py femexamples/meshes/mesh_canticcx_hexa20.py + femexamples/meshes/mesh_canticcx_seg3.py femexamples/meshes/mesh_canticcx_tetra10.py + femexamples/meshes/mesh_canticcx_tria6.py femexamples/meshes/mesh_capacitance_two_balls_tetra10.py femexamples/meshes/mesh_constraint_centrif_tetra10.py femexamples/meshes/mesh_constraint_tie_tetra10.py @@ -287,10 +294,10 @@ SET(FemTestsCcx_SRCS femtest/data/calculix/box.FCStd femtest/data/calculix/ccx_buckling_flexuralbuckling.dat femtest/data/calculix/ccx_buckling_flexuralbuckling.inp - femtest/data/calculix/ccxcantilever_faceload.inp - femtest/data/calculix/ccxcantilever_hexa20.inp - femtest/data/calculix/ccxcantilever_nodeload.inp - femtest/data/calculix/ccxcantilever_prescribeddisplacement.inp + femtest/data/calculix/ccx_cantilever_faceload.inp + femtest/data/calculix/ccx_cantilever_ele_hexa20.inp + femtest/data/calculix/ccx_cantilever_nodeload.inp + femtest/data/calculix/ccx_cantilever_prescribeddisplacement.inp femtest/data/calculix/constraint_centrif.inp femtest/data/calculix/constraint_contact_shell_shell.FCStd femtest/data/calculix/constraint_contact_shell_shell.inp @@ -353,41 +360,41 @@ SET(FemTestsZ88Main_SRCS SET(FemTestsZ88Ccxcantifl_SRCS femtest/data/z88/__init__.py - femtest/data/z88/ccxcantilever_faceload/51.txt - femtest/data/z88/ccxcantilever_faceload/z88.dyn - femtest/data/z88/ccxcantilever_faceload/z88elp.txt - femtest/data/z88/ccxcantilever_faceload/z88i1.txt - femtest/data/z88/ccxcantilever_faceload/z88i2.txt - femtest/data/z88/ccxcantilever_faceload/z88i5.txt - femtest/data/z88/ccxcantilever_faceload/z88int.txt - femtest/data/z88/ccxcantilever_faceload/z88man.txt - femtest/data/z88/ccxcantilever_faceload/z88mat.txt + femtest/data/z88/ccx_cantilever_faceload/51.txt + femtest/data/z88/ccx_cantilever_faceload/z88.dyn + femtest/data/z88/ccx_cantilever_faceload/z88elp.txt + femtest/data/z88/ccx_cantilever_faceload/z88i1.txt + femtest/data/z88/ccx_cantilever_faceload/z88i2.txt + femtest/data/z88/ccx_cantilever_faceload/z88i5.txt + femtest/data/z88/ccx_cantilever_faceload/z88int.txt + femtest/data/z88/ccx_cantilever_faceload/z88man.txt + femtest/data/z88/ccx_cantilever_faceload/z88mat.txt ) SET(FemTestsZ88Ccxcantihex_SRCS femtest/data/z88/__init__.py - femtest/data/z88/ccxcantilever_hexa20/51.txt - femtest/data/z88/ccxcantilever_hexa20/z88.dyn - femtest/data/z88/ccxcantilever_hexa20/z88elp.txt - femtest/data/z88/ccxcantilever_hexa20/z88i1.txt - femtest/data/z88/ccxcantilever_hexa20/z88i2.txt - femtest/data/z88/ccxcantilever_hexa20/z88i5.txt - femtest/data/z88/ccxcantilever_hexa20/z88int.txt - femtest/data/z88/ccxcantilever_hexa20/z88man.txt - femtest/data/z88/ccxcantilever_hexa20/z88mat.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/51.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88.dyn + femtest/data/z88/ccx_cantilever_ele_hexa20/z88elp.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88i1.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88i2.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88i5.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88int.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88man.txt + femtest/data/z88/ccx_cantilever_ele_hexa20/z88mat.txt ) SET(FemTestsZ88Ccxcantinl_SRCS femtest/data/z88/__init__.py - femtest/data/z88/ccxcantilever_nodeload/51.txt - femtest/data/z88/ccxcantilever_nodeload/z88.dyn - femtest/data/z88/ccxcantilever_nodeload/z88elp.txt - femtest/data/z88/ccxcantilever_nodeload/z88i1.txt - femtest/data/z88/ccxcantilever_nodeload/z88i2.txt - femtest/data/z88/ccxcantilever_nodeload/z88i5.txt - femtest/data/z88/ccxcantilever_nodeload/z88int.txt - femtest/data/z88/ccxcantilever_nodeload/z88man.txt - femtest/data/z88/ccxcantilever_nodeload/z88mat.txt + femtest/data/z88/ccx_cantilever_nodeload/51.txt + femtest/data/z88/ccx_cantilever_nodeload/z88.dyn + femtest/data/z88/ccx_cantilever_nodeload/z88elp.txt + femtest/data/z88/ccx_cantilever_nodeload/z88i1.txt + femtest/data/z88/ccx_cantilever_nodeload/z88i2.txt + femtest/data/z88/ccx_cantilever_nodeload/z88i5.txt + femtest/data/z88/ccx_cantilever_nodeload/z88int.txt + femtest/data/z88/ccx_cantilever_nodeload/z88man.txt + femtest/data/z88/ccx_cantilever_nodeload/z88mat.txt ) SET(FemTools_SRCS @@ -462,9 +469,9 @@ INSTALL(FILES ${FemTestsElmer_SRCS} DESTINATION Mod/Fem/femtest/data/elmer) INSTALL(FILES ${FemTestsMesh_SRCS} DESTINATION Mod/Fem/femtest/data/mesh) INSTALL(FILES ${FemTestsOpen_SRCS} DESTINATION Mod/Fem/femtest/data/open) INSTALL(FILES ${FemTestsZ88Main_SRCS} DESTINATION Mod/Fem/femtest/data/z88) -INSTALL(FILES ${FemTestsZ88Ccxcantifl_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccxcantilever_faceload) -INSTALL(FILES ${FemTestsZ88Ccxcantihex_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccxcantilever_hexa20) -INSTALL(FILES ${FemTestsZ88Ccxcantinl_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccxcantilever_nodeload) +INSTALL(FILES ${FemTestsZ88Ccxcantifl_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccx_cantilever_faceload) +INSTALL(FILES ${FemTestsZ88Ccxcantihex_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20) +INSTALL(FILES ${FemTestsZ88Ccxcantinl_SRCS} DESTINATION Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload) INSTALL(FILES ${FemTools_SRCS} DESTINATION Mod/Fem/femtools) diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_base.py b/src/Mod/Fem/femexamples/ccx_cantilever_base_solid.py similarity index 98% rename from src/Mod/Fem/femexamples/ccx_cantilever_base.py rename to src/Mod/Fem/femexamples/ccx_cantilever_base_solid.py index c3d1d7da51..46e9327509 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_base.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_base_solid.py @@ -31,7 +31,7 @@ from .manager import get_meshname from .manager import init_doc -def setup_cantileverbase(doc=None, solvertype="ccxtools"): +def setup_cantilever_base_solid(doc=None, solvertype="ccxtools"): # init FreeCAD document if doc is None: diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_hexa20faceload.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py similarity index 97% rename from src/Mod/Fem/femexamples/ccx_cantilever_hexa20faceload.py rename to src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py index 62f5252903..0e7c6d9aeb 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_hexa20faceload.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py @@ -34,7 +34,7 @@ from .manager import init_doc def get_information(): return { - "name": "CCX cantilever hexa20 face load", + "name": "CCX cantilever hexa20 solid elements", "meshtype": "solid", "meshelement": "Hexa20", "constraints": ["fixed", "force"], @@ -53,6 +53,7 @@ setup() See forum topic post: +hexa20 elements and face load ... """ diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py b/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py index 249be5a176..fe0a444388 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_faceload.py @@ -25,7 +25,7 @@ import ObjectsFem from . import manager -from .ccx_cantilever_base import setup_cantileverbase +from .ccx_cantilever_base_solid import setup_cantilever_base_solid from .manager import init_doc @@ -65,8 +65,8 @@ def setup(doc=None, solvertype="ccxtools"): # just keep the following line and change text string in get_explanation method manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) - # setup CalculiX cantilever, apply 9 MN on surface of front end face - doc = setup_cantileverbase(doc, solvertype) + # setup CalculiX cantilever + doc = setup_cantilever_base_solid(doc, solvertype) analysis = doc.Analysis geom_obj = doc.Box diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_nodeload.py b/src/Mod/Fem/femexamples/ccx_cantilever_nodeload.py index b34367e3bb..e52ce68a53 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_nodeload.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_nodeload.py @@ -25,7 +25,7 @@ import ObjectsFem from . import manager -from .ccx_cantilever_base import setup_cantileverbase +from .ccx_cantilever_base_solid import setup_cantilever_base_solid from .manager import init_doc @@ -66,7 +66,7 @@ def setup(doc=None, solvertype="ccxtools"): manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) # setup CalculiX cantilever, apply 9 MN on the 4 nodes of the front end face - doc = setup_cantileverbase(doc, solvertype) + doc = setup_cantilever_base_solid(doc, solvertype) analysis = doc.Analysis geom_obj = doc.Box diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_prescribeddisplacement.py b/src/Mod/Fem/femexamples/ccx_cantilever_prescribeddisplacement.py index 6308d8fd9f..8b601737a5 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_prescribeddisplacement.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_prescribeddisplacement.py @@ -25,7 +25,7 @@ import ObjectsFem from . import manager -from .ccx_cantilever_base import setup_cantileverbase +from .ccx_cantilever_base_solid import setup_cantilever_base_solid from .manager import init_doc @@ -72,7 +72,7 @@ def setup(doc=None, solvertype="ccxtools"): # setup CalculiX cantilever # apply a prescribed displacement of 250 mm in -z on the front end face - doc = setup_cantileverbase(doc, solvertype) + doc = setup_cantilever_base_solid(doc, solvertype) analysis = doc.Analysis geom_obj = doc.Box diff --git a/src/Mod/Fem/femtest/app/test_solver_calculix.py b/src/Mod/Fem/femtest/app/test_solver_calculix.py index 6676343f54..42a2580431 100644 --- a/src/Mod/Fem/femtest/app/test_solver_calculix.py +++ b/src/Mod/Fem/femtest/app/test_solver_calculix.py @@ -104,7 +104,7 @@ class TestSolverCalculix(unittest.TestCase): self.input_file_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_faceload( + def test_ccx_cantilever_faceload( self ): from femexamples.ccx_cantilever_faceload import setup @@ -112,15 +112,15 @@ class TestSolverCalculix(unittest.TestCase): self.input_file_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_hexa20( + def test_ccx_cantilever_ele_hexa20( self ): - from femexamples.ccx_cantilever_hexa20faceload import setup + from femexamples.ccx_cantilever_ele_hexa20 import setup setup(self.document, "calculix") self.input_file_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_nodeload( + def test_ccx_cantilever_nodeload( self ): from femexamples.ccx_cantilever_nodeload import setup @@ -128,7 +128,7 @@ class TestSolverCalculix(unittest.TestCase): self.input_file_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_prescribeddisplacement( + def test_ccx_cantilever_prescribeddisplacement( self ): from femexamples.ccx_cantilever_prescribeddisplacement import setup diff --git a/src/Mod/Fem/femtest/app/test_solver_z88.py b/src/Mod/Fem/femtest/app/test_solver_z88.py index bcfd38f0fc..9b69c77216 100644 --- a/src/Mod/Fem/femtest/app/test_solver_z88.py +++ b/src/Mod/Fem/femtest/app/test_solver_z88.py @@ -76,7 +76,7 @@ class TestSolverZ88(unittest.TestCase): )) # ******************************************************************************************** - def test_ccxcantilever_faceload( + def test_ccx_cantilever_faceload( self ): from femexamples.ccx_cantilever_faceload import setup @@ -84,15 +84,15 @@ class TestSolverZ88(unittest.TestCase): self.inputfile_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_hexa20( + def test_ccx_cantilever_ele_hexa20( self ): - from femexamples.ccx_cantilever_hexa20faceload import setup + from femexamples.ccx_cantilever_ele_hexa20 import setup setup(self.document, "z88") self.inputfile_writing_test(get_namefromdef("test_")) # ******************************************************************************************** - def test_ccxcantilever_nodeload( + def test_ccx_cantilever_nodeload( self ): from femexamples.ccx_cantilever_nodeload import setup diff --git a/src/Mod/Fem/femtest/data/calculix/ccxcantilever_hexa20.inp b/src/Mod/Fem/femtest/data/calculix/ccx_cantilever_ele_hexa20.inp similarity index 100% rename from src/Mod/Fem/femtest/data/calculix/ccxcantilever_hexa20.inp rename to src/Mod/Fem/femtest/data/calculix/ccx_cantilever_ele_hexa20.inp diff --git a/src/Mod/Fem/femtest/data/calculix/ccxcantilever_faceload.inp b/src/Mod/Fem/femtest/data/calculix/ccx_cantilever_faceload.inp similarity index 100% rename from src/Mod/Fem/femtest/data/calculix/ccxcantilever_faceload.inp rename to src/Mod/Fem/femtest/data/calculix/ccx_cantilever_faceload.inp diff --git a/src/Mod/Fem/femtest/data/calculix/ccxcantilever_nodeload.inp b/src/Mod/Fem/femtest/data/calculix/ccx_cantilever_nodeload.inp similarity index 100% rename from src/Mod/Fem/femtest/data/calculix/ccxcantilever_nodeload.inp rename to src/Mod/Fem/femtest/data/calculix/ccx_cantilever_nodeload.inp diff --git a/src/Mod/Fem/femtest/data/calculix/ccxcantilever_prescribeddisplacement.inp b/src/Mod/Fem/femtest/data/calculix/ccx_cantilever_prescribeddisplacement.inp similarity index 100% rename from src/Mod/Fem/femtest/data/calculix/ccxcantilever_prescribeddisplacement.inp rename to src/Mod/Fem/femtest/data/calculix/ccx_cantilever_prescribeddisplacement.inp diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/51.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/51.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/51.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/51.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88.dyn b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88.dyn similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88.dyn rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88.dyn diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88elp.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88elp.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88elp.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88elp.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i1.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i1.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i1.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i1.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i2.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i2.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i2.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i2.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i5.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i5.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i5.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88i5.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88int.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88int.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88int.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88int.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88man.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88man.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88man.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88man.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88mat.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88mat.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88mat.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_ele_hexa20/z88mat.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/51.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/51.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/51.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/51.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88.dyn b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88.dyn similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88.dyn rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88.dyn diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88elp.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88elp.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88elp.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88elp.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i1.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i1.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i1.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i1.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i2.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i2.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88i2.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i2.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i5.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i5.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88i5.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88i5.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88int.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88int.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88int.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88int.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88man.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88man.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_hexa20/z88man.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88man.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88mat.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88mat.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_faceload/z88mat.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_faceload/z88mat.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/51.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/51.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/51.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/51.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88.dyn b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88.dyn similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88.dyn rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88.dyn diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88elp.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88elp.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88elp.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88elp.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i1.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i1.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i1.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i1.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i2.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i2.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i2.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i2.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i5.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i5.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88i5.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88i5.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88int.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88int.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88int.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88int.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88man.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88man.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88man.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88man.txt diff --git a/src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88mat.txt b/src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88mat.txt similarity index 100% rename from src/Mod/Fem/femtest/data/z88/ccxcantilever_nodeload/z88mat.txt rename to src/Mod/Fem/femtest/data/z88/ccx_cantilever_nodeload/z88mat.txt From 7e5a4263848a41283d30be56dbef69b1b90125c7 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 19:31:15 +0200 Subject: [PATCH 14/19] FEM: cmake, fix --- src/Mod/Fem/CMakeLists.txt | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 9bcaf04f8e..dc68564403 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -48,13 +48,13 @@ SET(FemExamples_SRCS femexamples/buckling_platebuckling.py femexamples/buckling_lateraltorsionalbuckling.py femexamples/ccx_buckling_flexuralbuckling.py - femexamples/ccx_cantilever_base_face.py + # femexamples/ccx_cantilever_base_face.py femexamples/ccx_cantilever_base_solid.py femexamples/ccx_cantilever_ele_hexa20.py - femexamples/ccx_cantilever_ele_tetra4.py - femexamples/ccx_cantilever_ele_tria3.py - femexamples/ccx_cantilever_ele_tria6.py - femexamples/ccx_cantilever_ele_seg3.py + # femexamples/ccx_cantilever_ele_tetra4.py + # femexamples/ccx_cantilever_ele_tria3.py + # femexamples/ccx_cantilever_ele_tria6.py + # femexamples/ccx_cantilever_ele_seg3.py femexamples/ccx_cantilever_faceload.py femexamples/ccx_cantilever_nodeload.py femexamples/ccx_cantilever_prescribeddisplacement.py @@ -92,9 +92,9 @@ SET(FemExampleMeshes_SRCS femexamples/meshes/mesh_buckling_ibeam_tria6.py femexamples/meshes/mesh_buckling_plate_tria6.py femexamples/meshes/mesh_canticcx_hexa20.py - femexamples/meshes/mesh_canticcx_seg3.py + # femexamples/meshes/mesh_canticcx_seg3.py femexamples/meshes/mesh_canticcx_tetra10.py - femexamples/meshes/mesh_canticcx_tria6.py + # femexamples/meshes/mesh_canticcx_tria6.py femexamples/meshes/mesh_capacitance_two_balls_tetra10.py femexamples/meshes/mesh_constraint_centrif_tetra10.py femexamples/meshes/mesh_constraint_tie_tetra10.py From c2d13b02eb8d6e56801fdf360bc59ad9d7b0526f Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 20:30:04 +0200 Subject: [PATCH 15/19] FEM: examples, ccx canti hexa20, fix comment --- src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py index 0e7c6d9aeb..8e1ff23c50 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py @@ -48,7 +48,7 @@ def get_explanation(header=""): return header + """ To run the example from Python console use: -from femexamples.ccx_cantilever_hexa20faceload import setup +from femexamples.ccx_cantilever_ele_hexa20 import setup setup() From a2413094f636e2ab2c227dbce7d92b86f0e92748 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 21:30:49 +0200 Subject: [PATCH 16/19] FEM: examples, canti hexa20, delete wrongly added exaplanation object --- src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py index 8e1ff23c50..795d568959 100644 --- a/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py @@ -69,10 +69,15 @@ def setup(doc=None, solvertype="ccxtools"): # just keep the following line and change text string in get_explanation method manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) - # setup cantilever faceload and exchange the mesh + # setup cantilever faceload doc = setup_with_faceload(doc, solvertype) femmesh_obj = doc.getObject(get_meshname()) + # delete explanation object wrongly added with setup faceload + if hasattr(doc, "Explanation_Report001"): + doc.removeObject("Explanation_Report001") + doc.recompute() + # load the hexa20 mesh from .meshes.mesh_canticcx_hexa20 import create_nodes, create_elements new_fem_mesh = Fem.FemMesh() From ad9a44e69085ab8357b299eacdb91391affffc68 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 25 Jul 2021 21:30:15 +0200 Subject: [PATCH 17/19] FEM: examples, ccx cantilever add face and edgemesh --- src/Mod/Fem/CMakeLists.txt | 18 +- .../femexamples/ccx_cantilever_base_edge.py | 138 ++ .../femexamples/ccx_cantilever_base_face.py | 121 ++ .../femexamples/ccx_cantilever_ele_seg2.py | 97 ++ .../femexamples/ccx_cantilever_ele_seg3.py | 71 + .../femexamples/ccx_cantilever_ele_tetra4.py | 83 + .../femexamples/ccx_cantilever_ele_tria3.py | 97 ++ .../femexamples/ccx_cantilever_ele_tria6.py | 70 + src/Mod/Fem/femexamples/examplesgui.py | 4 +- .../femexamples/meshes/mesh_canticcx_seg2.py | 117 ++ .../femexamples/meshes/mesh_canticcx_seg3.py | 24 + .../femexamples/meshes/mesh_canticcx_tria3.py | 1522 +++++++++++++++++ .../femexamples/meshes/mesh_canticcx_tria6.py | 255 +++ 13 files changed, 2609 insertions(+), 8 deletions(-) create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_base_edge.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_base_face.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_ele_seg2.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_ele_seg3.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_ele_tetra4.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_ele_tria3.py create mode 100644 src/Mod/Fem/femexamples/ccx_cantilever_ele_tria6.py create mode 100644 src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg2.py create mode 100644 src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg3.py create mode 100644 src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria3.py create mode 100644 src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria6.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index dc68564403..f81f4d219c 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -48,13 +48,15 @@ SET(FemExamples_SRCS femexamples/buckling_platebuckling.py femexamples/buckling_lateraltorsionalbuckling.py femexamples/ccx_buckling_flexuralbuckling.py - # femexamples/ccx_cantilever_base_face.py + femexamples/ccx_cantilever_base_edge.py + femexamples/ccx_cantilever_base_face.py femexamples/ccx_cantilever_base_solid.py femexamples/ccx_cantilever_ele_hexa20.py - # femexamples/ccx_cantilever_ele_tetra4.py - # femexamples/ccx_cantilever_ele_tria3.py - # femexamples/ccx_cantilever_ele_tria6.py - # femexamples/ccx_cantilever_ele_seg3.py + femexamples/ccx_cantilever_ele_tetra4.py + femexamples/ccx_cantilever_ele_tria3.py + femexamples/ccx_cantilever_ele_tria6.py + femexamples/ccx_cantilever_ele_seg2.py + femexamples/ccx_cantilever_ele_seg3.py femexamples/ccx_cantilever_faceload.py femexamples/ccx_cantilever_nodeload.py femexamples/ccx_cantilever_prescribeddisplacement.py @@ -92,9 +94,11 @@ SET(FemExampleMeshes_SRCS femexamples/meshes/mesh_buckling_ibeam_tria6.py femexamples/meshes/mesh_buckling_plate_tria6.py femexamples/meshes/mesh_canticcx_hexa20.py - # femexamples/meshes/mesh_canticcx_seg3.py + femexamples/meshes/mesh_canticcx_seg2.py + femexamples/meshes/mesh_canticcx_seg3.py femexamples/meshes/mesh_canticcx_tetra10.py - # femexamples/meshes/mesh_canticcx_tria6.py + femexamples/meshes/mesh_canticcx_tria3.py + femexamples/meshes/mesh_canticcx_tria6.py femexamples/meshes/mesh_capacitance_two_balls_tetra10.py femexamples/meshes/mesh_constraint_centrif_tetra10.py femexamples/meshes/mesh_constraint_tie_tetra10.py diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_base_edge.py b/src/Mod/Fem/femexamples/ccx_cantilever_base_edge.py new file mode 100644 index 0000000000..5fab3d337b --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_base_edge.py @@ -0,0 +1,138 @@ +# *************************************************************************** +# * Copyright (c) 2020 Bernd Hahnebach * +# * Copyright (c) 2020 Sudhanshu Dubey * +# * * +# * 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 * +# * * +# *************************************************************************** + +import FreeCAD + +import Fem +import ObjectsFem + +from .manager import get_meshname +from .manager import init_doc + + +def setup_cantilever_base_face(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # geometric objects + geom_obj = doc.addObject("Part::Plane", "CanileverPlate") + geom_obj.Width = 1000 + geom_obj.Length = 8000 + geom_obj.Placement = FreeCAD.Placement( + FreeCAD.Vector(0, 500, 0), + FreeCAD.Rotation(0, 0, 90), + FreeCAD.Vector(1, 0, 0), + ) + + doc.recompute() + + if FreeCAD.GuiUp: + geom_obj.ViewObject.Document.activeView().viewAxonometric() + geom_obj.ViewObject.Document.activeView().fitAll() + + # analysis + analysis = ObjectsFem.makeAnalysis(doc, "Analysis") + + # solver + if solvertype == "calculix": + solver_obj = ObjectsFem.makeSolverCalculix(doc, "SolverCalculiX") + elif solvertype == "ccxtools": + solver_obj = ObjectsFem.makeSolverCalculixCcxTools(doc, "CalculiXccxTools") + solver_obj.WorkingDir = u"" + else: + FreeCAD.Console.PrintWarning( + "Not known or not supported solver type: {}. " + "No solver object was created.\n".format(solvertype) + ) + if solvertype == "calculix" or solvertype == "ccxtools": + solver_obj.AnalysisType = "static" + solver_obj.GeometricalNonlinearity = "linear" + solver_obj.ThermoMechSteadyState = False + solver_obj.MatrixSolverType = "default" + solver_obj.IterationsControlParameterTimeUse = False + solver_obj.SplitInputWriter = False + analysis.addObject(solver_obj) + + # shell thickness + thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 1000, 'Thickness') + analysis.addObject(thickness_obj) + + # material + material_obj = ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial") + mat = material_obj.Material + mat["Name"] = "Calculix-Steel" + mat["YoungsModulus"] = "210000 MPa" + mat["PoissonRatio"] = "0.30" + material_obj.Material = mat + analysis.addObject(material_obj) + + # constraint fixed + con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed") + con_fixed.References = [(geom_obj, "Edge1")] + analysis.addObject(con_fixed) + + # constraint force + con_force = ObjectsFem.makeConstraintForce(doc, "ConstraintForce") + con_force.References = [(geom_obj, "Edge3")] + con_force.Force = 9000000.0 # 9'000'000 N = 9 MN + con_force.Direction = (geom_obj, ["Edge3"]) + con_force.Reversed = True + analysis.addObject(con_force) + + # mesh + from .meshes.mesh_canticcx_tria6 import create_nodes, create_elements + fem_mesh = Fem.FemMesh() + control = create_nodes(fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating nodes.\n") + control = create_elements(fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating elements.\n") + femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0] + femmesh_obj.FemMesh = fem_mesh + femmesh_obj.Part = geom_obj + femmesh_obj.SecondOrderLinear = False + femmesh_obj.ElementDimension = "2D" + femmesh_obj.CharacteristicLengthMax = "500.0 mm" + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg2.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg2.py new file mode 100644 index 0000000000..0a00f5568d --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg2.py @@ -0,0 +1,97 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +import FreeCAD + +import Fem + +from . import manager +from .ccx_cantilever_base_edge import setup_cantilever_base_edge +from .manager import get_meshname +from .manager import init_doc + + +def get_information(): + return { + "name": "CCX cantilever seg2 beam elements", + "meshtype": "edge", + "meshelement": "Seg2", + "constraints": ["fixed", "force"], + "solvers": ["calculix"], + "material": "solid", + "equation": "mechanical" + } + + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.ccx_cantilever_ele_seg2 import setup +setup() + + +See forum topic post (for seg3): +https://forum.freecadweb.org/viewtopic.php?f=18&t=16044 + +CalculiX cantilever modeled with seg2 beam elements + +""" + + +def setup(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # setup CalculiX cantilever + doc = setup_cantilever_base_edge(doc, solvertype) + femmesh_obj = doc.getObject(get_meshname()) + + # load the seg2 mesh + from .meshes.mesh_canticcx_seg2 import create_nodes, create_elements + new_fem_mesh = Fem.FemMesh() + control = create_nodes(new_fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating nodes.\n") + control = create_elements(new_fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating elements.\n") + + # overwrite mesh with the seg2 mesh + femmesh_obj.FemMesh = new_fem_mesh + + # set mesh obj parameter + femmesh_obj.SecondOrderLinear = False + femmesh_obj.ElementDimension = "1D" + femmesh_obj.ElementOrder = "1st" + femmesh_obj.CharacteristicLengthMax = "150.0 mm" + femmesh_obj.CharacteristicLengthMin = "150.0 mm" + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg3.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg3.py new file mode 100644 index 0000000000..ce075ecb15 --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_seg3.py @@ -0,0 +1,71 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +from . import manager +from .ccx_cantilever_base_edge import setup_cantilever_base_edge +from .manager import init_doc + + +def get_information(): + return { + "name": "CCX cantilever seg3 beam elements", + "meshtype": "edge", + "meshelement": "Seg3", + "constraints": ["fixed", "force"], + "solvers": ["calculix"], + "material": "solid", + "equation": "mechanical" + } + + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.ccx_cantilever_ele_seg3 import setup +setup() + + +See forum topic post: +https://forum.freecadweb.org/viewtopic.php?f=18&t=16044 + +CalculiX cantilever modeled with seg3 beam elements + +""" + + +def setup(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # setup CalculiX cantilever + doc = setup_cantilever_base_edge(doc, solvertype) + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_tetra4.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tetra4.py new file mode 100644 index 0000000000..19c4713535 --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tetra4.py @@ -0,0 +1,83 @@ +# *************************************************************************** +# * Copyright (c) 2019 Bernd Hahnebach * +# * Copyright (c) 2020 Sudhanshu Dubey * +# * * +# * 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 * +# * * +# *************************************************************************** + +import Fem + +from . import manager +from .ccx_cantilever_faceload import setup as setup_with_faceload +from .manager import get_meshname +from .manager import init_doc + + +def get_information(): + return { + "name": "CCX cantilever tetra4 solid elements", + "meshtype": "solid", + "meshelement": "Tetra4", + "constraints": ["fixed", "force"], + "solvers": ["calculix", "elmer", "z88"], + "material": "solid", + "equation": "mechanical" + } + + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.ccx_cantilever_ele_tetra4 import setup +setup() + + +Tetra4 elements. There are really a lot needed thus mesh is cleared. +Mesh before run the example. +... + +""" + + +def setup(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # setup cantilever faceload and exchange the mesh + doc = setup_with_faceload(doc, solvertype) + femmesh_obj = doc.getObject(get_meshname()) + + # clear mesh and set meshing parameter + femmesh_obj.FemMesh = Fem.FemMesh() + femmesh_obj.SecondOrderLinear = False + femmesh_obj.ElementDimension = "3D" + femmesh_obj.ElementOrder = "1st" + femmesh_obj.CharacteristicLengthMax = "150.0 mm" + femmesh_obj.CharacteristicLengthMin = "150.0 mm" + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria3.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria3.py new file mode 100644 index 0000000000..a3856fbf0e --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria3.py @@ -0,0 +1,97 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +import FreeCAD + +import Fem + +from . import manager +from .ccx_cantilever_base_face import setup_cantilever_base_face +from .manager import get_meshname +from .manager import init_doc + + +def get_information(): + return { + "name": "CCX cantilever tria3 face elements", + "meshtype": "face", + "meshelement": "Tria3", + "constraints": ["fixed", "force"], + "solvers": ["calculix"], + "material": "solid", + "equation": "mechanical" + } + + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.ccx_cantilever_ele_tria3 import setup +setup() + + +See forum topic post: + + +CalculiX cantilever modeled with tria3 face elements + +""" + + +def setup(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # setup CalculiX cantilever + doc = setup_cantilever_base_face(doc, solvertype) + femmesh_obj = doc.getObject(get_meshname()) + + # load the tria3 mesh + from .meshes.mesh_canticcx_tria3 import create_nodes, create_elements + new_fem_mesh = Fem.FemMesh() + control = create_nodes(new_fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating nodes.\n") + control = create_elements(new_fem_mesh) + if not control: + FreeCAD.Console.PrintError("Error on creating elements.\n") + + # overwrite mesh with the tria3 mesh + femmesh_obj.FemMesh = new_fem_mesh + + # set mesh obj parameter + femmesh_obj.SecondOrderLinear = False + femmesh_obj.ElementDimension = "2D" + femmesh_obj.ElementOrder = "1st" + femmesh_obj.CharacteristicLengthMax = "150.0 mm" + femmesh_obj.CharacteristicLengthMin = "150.0 mm" + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria6.py b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria6.py new file mode 100644 index 0000000000..b80a937ed3 --- /dev/null +++ b/src/Mod/Fem/femexamples/ccx_cantilever_ele_tria6.py @@ -0,0 +1,70 @@ +# *************************************************************************** +# * Copyright (c) 2021 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +from . import manager +from .ccx_cantilever_base_face import setup_cantilever_base_face +from .manager import init_doc + + +def get_information(): + return { + "name": "CCX cantilever tria6 face elements", + "meshtype": "face", + "meshelement": "Tria6", + "constraints": ["fixed", "force"], + "solvers": ["calculix"], + "material": "solid", + "equation": "mechanical" + } + + +def get_explanation(header=""): + return header + """ + +To run the example from Python console use: +from femexamples.ccx_cantilever_ele_tria6 import setup +setup() + + +See forum topic post: + +CalculiX cantilever modeled with face elements + +""" + + +def setup(doc=None, solvertype="ccxtools"): + + # init FreeCAD document + if doc is None: + doc = init_doc() + + # explanation object + # just keep the following line and change text string in get_explanation method + manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information()))) + + # setup CalculiX cantilever + doc = setup_cantilever_base_face(doc, solvertype) + + doc.recompute() + return doc diff --git a/src/Mod/Fem/femexamples/examplesgui.py b/src/Mod/Fem/femexamples/examplesgui.py index b36c6b294b..3e288ae87a 100644 --- a/src/Mod/Fem/femexamples/examplesgui.py +++ b/src/Mod/Fem/femexamples/examplesgui.py @@ -57,7 +57,9 @@ class FemExamples(QtGui.QWidget): "__init__.py", "__pycache__", "boxanalysis_base.py", - "ccx_cantilever_base.py", + "ccx_cantilever_base_edge.py", + "ccx_cantilever_base_face.py", + "ccx_cantilever_base_solid.py", "examplesgui.py", "manager.py", "meshes", diff --git a/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg2.py b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg2.py new file mode 100644 index 0000000000..8aed5793dc --- /dev/null +++ b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg2.py @@ -0,0 +1,117 @@ +def create_nodes(femmesh): + # nodes + femmesh.addNode(0.0, 500.0, 500.0, 1) + femmesh.addNode(8000.0, 500.0, 500.0, 2) + femmesh.addNode(148.14814814814792, 500.0, 500.0, 3) + femmesh.addNode(296.29629629629585, 500.0, 500.0, 4) + femmesh.addNode(444.4444444444438, 500.0, 500.0, 5) + femmesh.addNode(592.5925925925918, 500.0, 500.0, 6) + femmesh.addNode(740.7407407407396, 500.0, 500.0, 7) + femmesh.addNode(888.8888888888874, 500.0, 500.0, 8) + femmesh.addNode(1037.0370370370354, 500.0, 500.0, 9) + femmesh.addNode(1185.1851851851832, 500.0, 500.0, 10) + femmesh.addNode(1333.333333333331, 500.0, 500.0, 11) + femmesh.addNode(1481.4814814814792, 500.0, 500.0, 12) + femmesh.addNode(1629.6296296296275, 500.0, 500.0, 13) + femmesh.addNode(1777.7777777777753, 500.0, 500.0, 14) + femmesh.addNode(1925.9259259259236, 500.0, 500.0, 15) + femmesh.addNode(2074.0740740740716, 500.0, 500.0, 16) + femmesh.addNode(2222.22222222222, 500.0, 500.0, 17) + femmesh.addNode(2370.370370370368, 500.0, 500.0, 18) + femmesh.addNode(2518.5185185185155, 500.0, 500.0, 19) + femmesh.addNode(2666.666666666663, 500.0, 500.0, 20) + femmesh.addNode(2814.8148148148107, 500.0, 500.0, 21) + femmesh.addNode(2962.962962962958, 500.0, 500.0, 22) + femmesh.addNode(3111.1111111111054, 500.0, 500.0, 23) + femmesh.addNode(3259.259259259253, 500.0, 500.0, 24) + femmesh.addNode(3407.4074074074006, 500.0, 500.0, 25) + femmesh.addNode(3555.555555555548, 500.0, 500.0, 26) + femmesh.addNode(3703.7037037036957, 500.0, 500.0, 27) + femmesh.addNode(3851.851851851843, 500.0, 500.0, 28) + femmesh.addNode(3999.9999999999905, 500.0, 500.0, 29) + femmesh.addNode(4148.148148148138, 500.0, 500.0, 30) + femmesh.addNode(4296.296296296286, 500.0, 500.0, 31) + femmesh.addNode(4444.4444444444325, 500.0, 500.0, 32) + femmesh.addNode(4592.59259259258, 500.0, 500.0, 33) + femmesh.addNode(4740.740740740728, 500.0, 500.0, 34) + femmesh.addNode(4888.888888888877, 500.0, 500.0, 35) + femmesh.addNode(5037.037037037026, 500.0, 500.0, 36) + femmesh.addNode(5185.185185185173, 500.0, 500.0, 37) + femmesh.addNode(5333.333333333322, 500.0, 500.0, 38) + femmesh.addNode(5481.481481481471, 500.0, 500.0, 39) + femmesh.addNode(5629.6296296296205, 500.0, 500.0, 40) + femmesh.addNode(5777.777777777769, 500.0, 500.0, 41) + femmesh.addNode(5925.925925925918, 500.0, 500.0, 42) + femmesh.addNode(6074.074074074067, 500.0, 500.0, 43) + femmesh.addNode(6222.222222222214, 500.0, 500.0, 44) + femmesh.addNode(6370.370370370363, 500.0, 500.0, 45) + femmesh.addNode(6518.518518518513, 500.0, 500.0, 46) + femmesh.addNode(6666.6666666666615, 500.0, 500.0, 47) + femmesh.addNode(6814.81481481481, 500.0, 500.0, 48) + femmesh.addNode(6962.962962962959, 500.0, 500.0, 49) + femmesh.addNode(7111.111111111108, 500.0, 500.0, 50) + femmesh.addNode(7259.259259259256, 500.0, 500.0, 51) + femmesh.addNode(7407.407407407406, 500.0, 500.0, 52) + femmesh.addNode(7555.555555555554, 500.0, 500.0, 53) + femmesh.addNode(7703.703703703703, 500.0, 500.0, 54) + femmesh.addNode(7851.851851851851, 500.0, 500.0, 55) + return True + + +def create_elements(femmesh): + # elements + femmesh.addEdge([1, 3], 1) + femmesh.addEdge([3, 4], 2) + femmesh.addEdge([4, 5], 3) + femmesh.addEdge([5, 6], 4) + femmesh.addEdge([6, 7], 5) + femmesh.addEdge([7, 8], 6) + femmesh.addEdge([8, 9], 7) + femmesh.addEdge([9, 10], 8) + femmesh.addEdge([10, 11], 9) + femmesh.addEdge([11, 12], 10) + femmesh.addEdge([12, 13], 11) + femmesh.addEdge([13, 14], 12) + femmesh.addEdge([14, 15], 13) + femmesh.addEdge([15, 16], 14) + femmesh.addEdge([16, 17], 15) + femmesh.addEdge([17, 18], 16) + femmesh.addEdge([18, 19], 17) + femmesh.addEdge([19, 20], 18) + femmesh.addEdge([20, 21], 19) + femmesh.addEdge([21, 22], 20) + femmesh.addEdge([22, 23], 21) + femmesh.addEdge([23, 24], 22) + femmesh.addEdge([24, 25], 23) + femmesh.addEdge([25, 26], 24) + femmesh.addEdge([26, 27], 25) + femmesh.addEdge([27, 28], 26) + femmesh.addEdge([28, 29], 27) + femmesh.addEdge([29, 30], 28) + femmesh.addEdge([30, 31], 29) + femmesh.addEdge([31, 32], 30) + femmesh.addEdge([32, 33], 31) + femmesh.addEdge([33, 34], 32) + femmesh.addEdge([34, 35], 33) + femmesh.addEdge([35, 36], 34) + femmesh.addEdge([36, 37], 35) + femmesh.addEdge([37, 38], 36) + femmesh.addEdge([38, 39], 37) + femmesh.addEdge([39, 40], 38) + femmesh.addEdge([40, 41], 39) + femmesh.addEdge([41, 42], 40) + femmesh.addEdge([42, 43], 41) + femmesh.addEdge([43, 44], 42) + femmesh.addEdge([44, 45], 43) + femmesh.addEdge([45, 46], 44) + femmesh.addEdge([46, 47], 45) + femmesh.addEdge([47, 48], 46) + femmesh.addEdge([48, 49], 47) + femmesh.addEdge([49, 50], 48) + femmesh.addEdge([50, 51], 49) + femmesh.addEdge([51, 52], 50) + femmesh.addEdge([52, 53], 51) + femmesh.addEdge([53, 54], 52) + femmesh.addEdge([54, 55], 53) + femmesh.addEdge([55, 2], 54) + return True diff --git a/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg3.py b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg3.py new file mode 100644 index 0000000000..a16cd33eb7 --- /dev/null +++ b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_seg3.py @@ -0,0 +1,24 @@ +def create_nodes(femmesh): + # nodes + femmesh.addNode(0.0, 500.0, 500.0, 1) + femmesh.addNode(8000.0, 500.0, 500.0, 2) + femmesh.addNode(1600.0000000000023, 500.0, 500.0, 3) + femmesh.addNode(3200.000000000006, 500.0, 500.0, 4) + femmesh.addNode(4800.000000000003, 500.0, 500.0, 5) + femmesh.addNode(6399.999999999996, 500.0, 500.0, 6) + femmesh.addNode(800.0000000000011, 500.0, 500.0, 7) + femmesh.addNode(2400.000000000004, 500.0, 500.0, 8) + femmesh.addNode(4000.0000000000045, 500.0, 500.0, 9) + femmesh.addNode(5599.999999999999, 500.0, 500.0, 10) + femmesh.addNode(7199.999999999998, 500.0, 500.0, 11) + return True + + +def create_elements(femmesh): + # elements + femmesh.addEdge([1, 3, 7], 1) + femmesh.addEdge([3, 4, 8], 2) + femmesh.addEdge([4, 5, 9], 3) + femmesh.addEdge([5, 6, 10], 4) + femmesh.addEdge([6, 2, 11], 5) + return True diff --git a/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria3.py b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria3.py new file mode 100644 index 0000000000..d510eff161 --- /dev/null +++ b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria3.py @@ -0,0 +1,1522 @@ +def create_nodes(femmesh): + # nodes + femmesh.addNode(0.0, 500.0, 0.0, 1) + femmesh.addNode(0.0, 500.0000000000002, 1000.0, 2) + femmesh.addNode(8000.0, 500.0, 0.0, 3) + femmesh.addNode(8000.0, 500.0000000000002, 1000.0, 4) + femmesh.addNode(0.0, 500.00000000000006, 142.8571428571426, 5) + femmesh.addNode(0.0, 500.00000000000006, 285.7142857142854, 6) + femmesh.addNode(0.0, 500.0000000000001, 428.5714285714277, 7) + femmesh.addNode(0.0, 500.0000000000001, 571.4285714285699, 8) + femmesh.addNode(0.0, 500.00000000000017, 714.2857142857132, 9) + femmesh.addNode(0.0, 500.00000000000017, 857.1428571428565, 10) + femmesh.addNode(148.14814814814792, 500.0, 0.0, 11) + femmesh.addNode(296.29629629629585, 500.0, 0.0, 12) + femmesh.addNode(444.4444444444438, 500.0, 0.0, 13) + femmesh.addNode(592.5925925925918, 500.0, 0.0, 14) + femmesh.addNode(740.7407407407396, 500.0, 0.0, 15) + femmesh.addNode(888.8888888888874, 500.0, 0.0, 16) + femmesh.addNode(1037.0370370370354, 500.0, 0.0, 17) + femmesh.addNode(1185.1851851851832, 500.0, 0.0, 18) + femmesh.addNode(1333.333333333331, 500.0, 0.0, 19) + femmesh.addNode(1481.4814814814792, 500.0, 0.0, 20) + femmesh.addNode(1629.6296296296275, 500.0, 0.0, 21) + femmesh.addNode(1777.7777777777753, 500.0, 0.0, 22) + femmesh.addNode(1925.9259259259236, 500.0, 0.0, 23) + femmesh.addNode(2074.0740740740716, 500.0, 0.0, 24) + femmesh.addNode(2222.22222222222, 500.0, 0.0, 25) + femmesh.addNode(2370.370370370368, 500.0, 0.0, 26) + femmesh.addNode(2518.5185185185155, 500.0, 0.0, 27) + femmesh.addNode(2666.666666666663, 500.0, 0.0, 28) + femmesh.addNode(2814.8148148148107, 500.0, 0.0, 29) + femmesh.addNode(2962.962962962958, 500.0, 0.0, 30) + femmesh.addNode(3111.1111111111054, 500.0, 0.0, 31) + femmesh.addNode(3259.259259259253, 500.0, 0.0, 32) + femmesh.addNode(3407.4074074074006, 500.0, 0.0, 33) + femmesh.addNode(3555.555555555548, 500.0, 0.0, 34) + femmesh.addNode(3703.7037037036957, 500.0, 0.0, 35) + femmesh.addNode(3851.851851851843, 500.0, 0.0, 36) + femmesh.addNode(3999.9999999999905, 500.0, 0.0, 37) + femmesh.addNode(4148.148148148138, 500.0, 0.0, 38) + femmesh.addNode(4296.296296296286, 500.0, 0.0, 39) + femmesh.addNode(4444.4444444444325, 500.0, 0.0, 40) + femmesh.addNode(4592.59259259258, 500.0, 0.0, 41) + femmesh.addNode(4740.740740740728, 500.0, 0.0, 42) + femmesh.addNode(4888.888888888877, 500.0, 0.0, 43) + femmesh.addNode(5037.037037037026, 500.0, 0.0, 44) + femmesh.addNode(5185.185185185173, 500.0, 0.0, 45) + femmesh.addNode(5333.333333333322, 500.0, 0.0, 46) + femmesh.addNode(5481.481481481471, 500.0, 0.0, 47) + femmesh.addNode(5629.6296296296205, 500.0, 0.0, 48) + femmesh.addNode(5777.777777777769, 500.0, 0.0, 49) + femmesh.addNode(5925.925925925918, 500.0, 0.0, 50) + femmesh.addNode(6074.074074074067, 500.0, 0.0, 51) + femmesh.addNode(6222.222222222214, 500.0, 0.0, 52) + femmesh.addNode(6370.370370370363, 500.0, 0.0, 53) + femmesh.addNode(6518.518518518513, 500.0, 0.0, 54) + femmesh.addNode(6666.6666666666615, 500.0, 0.0, 55) + femmesh.addNode(6814.81481481481, 500.0, 0.0, 56) + femmesh.addNode(6962.962962962959, 500.0, 0.0, 57) + femmesh.addNode(7111.111111111108, 500.0, 0.0, 58) + femmesh.addNode(7259.259259259256, 500.0, 0.0, 59) + femmesh.addNode(7407.407407407406, 500.0, 0.0, 60) + femmesh.addNode(7555.555555555554, 500.0, 0.0, 61) + femmesh.addNode(7703.703703703703, 500.0, 0.0, 62) + femmesh.addNode(7851.851851851851, 500.0, 0.0, 63) + femmesh.addNode(8000.0, 500.00000000000006, 142.8571428571426, 64) + femmesh.addNode(8000.0, 500.00000000000006, 285.7142857142854, 65) + femmesh.addNode(8000.0, 500.0000000000001, 428.5714285714277, 66) + femmesh.addNode(8000.0, 500.0000000000001, 571.4285714285699, 67) + femmesh.addNode(8000.0, 500.00000000000017, 714.2857142857132, 68) + femmesh.addNode(8000.0, 500.00000000000017, 857.1428571428565, 69) + femmesh.addNode(148.14814814814792, 500.0000000000002, 1000.0, 70) + femmesh.addNode(296.29629629629585, 500.0000000000002, 1000.0, 71) + femmesh.addNode(444.4444444444438, 500.0000000000002, 1000.0, 72) + femmesh.addNode(592.5925925925918, 500.0000000000002, 1000.0, 73) + femmesh.addNode(740.7407407407396, 500.0000000000002, 1000.0, 74) + femmesh.addNode(888.8888888888874, 500.0000000000002, 1000.0, 75) + femmesh.addNode(1037.0370370370354, 500.0000000000002, 1000.0, 76) + femmesh.addNode(1185.1851851851832, 500.0000000000002, 1000.0, 77) + femmesh.addNode(1333.333333333331, 500.0000000000002, 1000.0, 78) + femmesh.addNode(1481.4814814814792, 500.0000000000002, 1000.0, 79) + femmesh.addNode(1629.6296296296275, 500.0000000000002, 1000.0, 80) + femmesh.addNode(1777.7777777777753, 500.0000000000002, 1000.0, 81) + femmesh.addNode(1925.9259259259236, 500.0000000000002, 1000.0, 82) + femmesh.addNode(2074.0740740740716, 500.0000000000002, 1000.0, 83) + femmesh.addNode(2222.22222222222, 500.0000000000002, 1000.0, 84) + femmesh.addNode(2370.370370370368, 500.0000000000002, 1000.0, 85) + femmesh.addNode(2518.5185185185155, 500.0000000000002, 1000.0, 86) + femmesh.addNode(2666.666666666663, 500.0000000000002, 1000.0, 87) + femmesh.addNode(2814.8148148148107, 500.0000000000002, 1000.0, 88) + femmesh.addNode(2962.962962962958, 500.0000000000002, 1000.0, 89) + femmesh.addNode(3111.1111111111054, 500.0000000000002, 1000.0, 90) + femmesh.addNode(3259.259259259253, 500.0000000000002, 1000.0, 91) + femmesh.addNode(3407.4074074074006, 500.0000000000002, 1000.0, 92) + femmesh.addNode(3555.555555555548, 500.0000000000002, 1000.0, 93) + femmesh.addNode(3703.7037037036957, 500.0000000000002, 1000.0, 94) + femmesh.addNode(3851.851851851843, 500.0000000000002, 1000.0, 95) + femmesh.addNode(3999.9999999999905, 500.0000000000002, 1000.0, 96) + femmesh.addNode(4148.148148148138, 500.0000000000002, 1000.0, 97) + femmesh.addNode(4296.296296296286, 500.0000000000002, 1000.0, 98) + femmesh.addNode(4444.4444444444325, 500.0000000000002, 1000.0, 99) + femmesh.addNode(4592.59259259258, 500.0000000000002, 1000.0, 100) + femmesh.addNode(4740.740740740728, 500.0000000000002, 1000.0, 101) + femmesh.addNode(4888.888888888877, 500.0000000000002, 1000.0, 102) + femmesh.addNode(5037.037037037026, 500.0000000000002, 1000.0, 103) + femmesh.addNode(5185.185185185173, 500.0000000000002, 1000.0, 104) + femmesh.addNode(5333.333333333322, 500.0000000000002, 1000.0, 105) + femmesh.addNode(5481.481481481471, 500.0000000000002, 1000.0, 106) + femmesh.addNode(5629.6296296296205, 500.0000000000002, 1000.0, 107) + femmesh.addNode(5777.777777777769, 500.0000000000002, 1000.0, 108) + femmesh.addNode(5925.925925925918, 500.0000000000002, 1000.0, 109) + femmesh.addNode(6074.074074074067, 500.0000000000002, 1000.0, 110) + femmesh.addNode(6222.222222222214, 500.0000000000002, 1000.0, 111) + femmesh.addNode(6370.370370370363, 500.0000000000002, 1000.0, 112) + femmesh.addNode(6518.518518518513, 500.0000000000002, 1000.0, 113) + femmesh.addNode(6666.6666666666615, 500.0000000000002, 1000.0, 114) + femmesh.addNode(6814.81481481481, 500.0000000000002, 1000.0, 115) + femmesh.addNode(6962.962962962959, 500.0000000000002, 1000.0, 116) + femmesh.addNode(7111.111111111108, 500.0000000000002, 1000.0, 117) + femmesh.addNode(7259.259259259256, 500.0000000000002, 1000.0, 118) + femmesh.addNode(7407.407407407406, 500.0000000000002, 1000.0, 119) + femmesh.addNode(7555.555555555554, 500.0000000000002, 1000.0, 120) + femmesh.addNode(7703.703703703703, 500.0000000000002, 1000.0, 121) + femmesh.addNode(7851.851851851851, 500.0000000000002, 1000.0, 122) + femmesh.addNode(7519.097353946394, 500.0000000000001, 486.44047362110416, 123) + femmesh.addNode(480.90264605360454, 500.0000000000001, 486.44047362110496, 124) + femmesh.addNode(4377.663810653201, 500.0000000000001, 495.2832031601589, 125) + femmesh.addNode(3044.3921495121385, 500.0000000000001, 495.227401818941, 126) + femmesh.addNode(3783.8823981965106, 500.0000000000001, 503.2059322265308, 127) + femmesh.addNode(2437.0893319693373, 500.0000000000001, 495.2274018189408, 128) + femmesh.addNode(1111.0223560497448, 500.0000000000001, 499.8767731965179, 129) + femmesh.addNode(1699.23614741982, 500.0000000000001, 495.8398288530509, 130) + femmesh.addNode(5117.058640509048, 500.0000000000001, 494.16303885375623, 131) + femmesh.addNode(6143.7385044327375, 500.0000000000001, 516.6482122194337, 132) + femmesh.addNode(6884.445927938705, 500.0000000000001, 499.2415848607458, 133) + femmesh.addNode(5647.817460317472, 500.0000000000001, 500.0, 134) + femmesh.addNode(2074.0740740740725, 500.0000000000001, 387.1742112482851, 135) + femmesh.addNode(4740.740740740732, 500.0000000000001, 387.1742112482876, 136) + femmesh.addNode(3407.4074074074015, 500.0000000000001, 387.1742112482837, 137) + femmesh.addNode(6529.516791736783, 500.0000000000001, 627.4332053037916, 138) + femmesh.addNode(804.4217687074812, 500.00000000000017, 659.996920578931, 139) + femmesh.addNode(7195.578231292519, 500.00000000000017, 659.996920578932, 140) + femmesh.addNode(4074.074074074067, 500.00000000000006, 332.3045267489734, 141) + femmesh.addNode(2740.740740740739, 500.00000000000017, 667.6954732510299, 142) + femmesh.addNode(1382.1376450640678, 500.00000000000006, 288.4521733196763, 143) + femmesh.addNode(2741.0040912230174, 500.00000000000006, 332.3822371418406, 144) + femmesh.addNode(4074.0740740740584, 500.00000000000017, 670.2611488393037, 145) + femmesh.addNode(1407.4074074074051, 500.00000000000017, 670.2611488393031, 146) + femmesh.addNode(826.7490268624668, 500.00000000000006, 328.5645802713502, 147) + femmesh.addNode(7177.028374478909, 500.00000000000006, 295.74079643706165, 148) + femmesh.addNode(5374.773883658418, 500.00000000000017, 676.6557030117461, 149) + femmesh.addNode(5391.526003346386, 500.00000000000006, 272.98622012319805, 150) + femmesh.addNode(3295.600900979507, 500.00000000000017, 684.4654431860611, 151) + femmesh.addNode(6406.71201209064, 500.00000000000006, 315.5345568139392, 152) + femmesh.addNode(2185.880580501969, 500.00000000000017, 684.4654431860607, 153) + femmesh.addNode(4628.934234312834, 500.00000000000017, 684.46544318606, 154) + femmesh.addNode(5898.609576424322, 500.00000000000017, 684.4424185223206, 155) + femmesh.addNode(5895.787242082226, 500.00000000000006, 295.8663221082943, 156) + femmesh.addNode(7726.775388768081, 500.00000000000017, 718.3978200389076, 157) + femmesh.addNode(7729.508951769956, 500.00000000000006, 265.880983919481, 158) + femmesh.addNode(273.2246112319166, 500.00000000000017, 718.3978200389083, 159) + femmesh.addNode(270.49104823003944, 500.00000000000006, 265.8809839194801, 160) + femmesh.addNode(3564.677059947713, 500.00000000000017, 741.9687593463968, 161) + femmesh.addNode(4894.335774469002, 500.00000000000017, 743.8671801070692, 162) + femmesh.addNode(1916.8044215337586, 500.00000000000017, 741.9687593463964, 163) + femmesh.addNode(6675.647623858817, 500.00000000000006, 257.9647404998144, 164) + femmesh.addNode(4528.500516254589, 500.00000000000006, 248.68408610023224, 165) + femmesh.addNode(2297.481388180274, 500.00000000000006, 256.41721287599285, 166) + femmesh.addNode(3184.0000933011984, 500.00000000000006, 256.4172128759929, 167) + femmesh.addNode(1863.453366261344, 500.00000000000006, 248.99208026467105, 168) + femmesh.addNode(3620.764124938444, 500.00000000000006, 249.5772677546173, 169) + femmesh.addNode(4980.683550415798, 500.00000000000006, 263.83563313455994, 170) + femmesh.addNode(6311.691982697567, 500.00000000000017, 752.5313754678206, 171) + femmesh.addNode(6758.461328193585, 500.00000000000017, 736.1643668654423, 172) + femmesh.addNode(579.1873060519074, 500.00000000000006, 230.99936263855923, 173) + femmesh.addNode(7420.812693948092, 500.00000000000006, 230.99936263855892, 174) + femmesh.addNode(4370.370370370361, 500.00000000000017, 755.486968449931, 175) + femmesh.addNode(2444.444444444443, 500.00000000000017, 755.4869684499315, 176) + femmesh.addNode(3037.0370370370333, 500.00000000000017, 755.486968449932, 177) + femmesh.addNode(1110.0887911816887, 500.00000000000006, 256.9177769898713, 178) + femmesh.addNode(6148.148148148161, 500.00000000000006, 244.5130315500682, 179) + femmesh.addNode(1128.20496412395, 500.00000000000017, 743.4579917656229, 180) + femmesh.addNode(7445.77750926458, 500.00000000000017, 767.6090351513436, 181) + femmesh.addNode(554.2224907354223, 500.00000000000017, 767.6090351513436, 182) + femmesh.addNode(1642.393190298241, 500.00000000000017, 771.655205235625, 183) + femmesh.addNode(3839.0882911832277, 500.00000000000017, 771.6552052356262, 184) + femmesh.addNode(6951.850743427138, 500.00000000000006, 250.73331227865367, 185) + femmesh.addNode(5620.1722163733475, 500.00000000000006, 235.6164310896373, 186) + femmesh.addNode(5620.548263058523, 500.00000000000017, 749.3388620996512, 187) + femmesh.addNode(5159.555818783418, 500.00000000000017, 758.7270417100899, 188) + femmesh.addNode(6994.49810921379, 500.00000000000017, 768.2631379536306, 189) + femmesh.addNode(211.2329077853915, 500.0000000000001, 499.9999999999989, 190) + femmesh.addNode(7788.767092214614, 500.0000000000001, 499.99999999999886, 191) + femmesh.addNode(4286.145296184866, 500.00000000000006, 217.50850016887512, 192) + femmesh.addNode(3861.9204537942705, 500.00000000000006, 217.00713354476628, 193) + femmesh.addNode(1609.3488440540948, 500.00000000000006, 226.89328602366547, 194) + femmesh.addNode(2528.12375168668, 500.00000000000006, 217.01207118565418, 195) + femmesh.addNode(2953.357729794794, 500.00000000000006, 217.0120711856532, 196) + femmesh.addNode(5190.802710097235, 500.00000000000006, 215.5276462080562, 197) + femmesh.addNode(6078.215097342937, 500.00000000000017, 792.0363019677964, 198) + femmesh.addNode(3583.8208358423444, 500.0000000000001, 478.23494961243927, 199) + femmesh.addNode(6684.0838928646845, 500.0000000000001, 492.00743630250474, 200) + femmesh.addNode(1906.691375941749, 500.0000000000001, 499.93979869666197, 201) + femmesh.addNode(4908.123285768417, 500.0000000000001, 499.9358754754902, 202) + femmesh.addNode(690.7517533456399, 500.0000000000001, 481.4907334328311, 203) + femmesh.addNode(7312.152665935738, 500.0000000000001, 474.7119145275551, 204) + femmesh.addNode(4819.364136862281, 500.00000000000006, 211.52595606001654, 205) + femmesh.addNode(3331.312837011274, 500.00000000000006, 210.99155859252647, 206) + femmesh.addNode(2150.2746332484003, 500.00000000000006, 210.46190281047143, 207) + femmesh.addNode(6570.679781658914, 500.00000000000017, 806.4128943758616, 208) + femmesh.addNode(3206.1827952923813, 500.0000000000001, 488.372495273334, 209) + femmesh.addNode(2275.2986861890936, 500.0000000000001, 488.37249527333245, 210) + femmesh.addNode(4539.505849926999, 500.0000000000001, 488.38179549686936, 211) + femmesh.addNode(6331.498674223819, 500.0000000000001, 510.44824502569446, 212) + femmesh.addNode(7085.945615969861, 500.0000000000001, 496.20921219531465, 213) + femmesh.addNode(914.0543840301425, 500.0000000000001, 496.20921219531584, 214) + femmesh.addNode(4179.7158900239065, 500.0000000000001, 497.3192810510361, 215) + femmesh.addNode(2634.8069329299083, 500.0000000000001, 495.2995176096491, 216) + femmesh.addNode(1518.6772271765653, 500.0000000000001, 500.43551675979285, 217) + femmesh.addNode(2845.7030843500197, 500.0000000000001, 495.7794310960958, 218) + femmesh.addNode(1298.9250894967872, 500.0000000000001, 500.6231840039535, 219) + femmesh.addNode(3953.5190378731395, 500.0000000000001, 508.9347634404576, 220) + femmesh.addNode(5838.996223242491, 500.0000000000001, 497.0598553389991, 221) + femmesh.addNode(5289.258388662224, 500.0000000000001, 518.0355527936534, 222) + femmesh.addNode(925.824759557911, 500.00000000000017, 810.3303624767582, 223) + femmesh.addNode(2587.2054817836924, 500.00000000000017, 813.1174093119453, 224) + femmesh.addNode(1279.1410894996675, 500.00000000000006, 190.67625699075495, 225) + femmesh.addNode(2868.1718643732233, 500.00000000000017, 792.3428470175296, 226) + femmesh.addNode(4231.074077426653, 500.00000000000017, 814.6492663298266, 227) + femmesh.addNode(1253.2563795569567, 500.00000000000017, 812.6444368824419, 228) + femmesh.addNode(971.4204314741182, 500.00000000000006, 186.68409635066166, 229) + femmesh.addNode(4763.0642506869945, 500.00000000000017, 811.918566634371, 230) + femmesh.addNode(2048.453955688606, 500.00000000000017, 807.7927457698634, 231) + femmesh.addNode(3433.027525792866, 500.00000000000017, 807.7927457698639, 232) + femmesh.addNode(6544.094702284656, 500.00000000000006, 192.19247743442926, 233) + femmesh.addNode(7259.309095210777, 500.00000000000017, 776.9781831816584, 234) + femmesh.addNode(717.8965209484061, 500.00000000000017, 803.5750168033601, 235) + femmesh.addNode(4524.024126217463, 500.00000000000017, 837.4173516252623, 236) + femmesh.addNode(3190.690792884138, 500.00000000000017, 837.4173516252647, 237) + femmesh.addNode(2290.7906885973407, 500.00000000000017, 837.4173516252655, 238) + femmesh.addNode(6301.801903995266, 500.00000000000006, 162.58264837474275, 239) + femmesh.addNode(5782.151001755968, 500.00000000000017, 822.6144529923005, 240) + femmesh.addNode(5777.242432958116, 500.00000000000006, 180.41307577128475, 241) + femmesh.addNode(6008.727830918599, 500.00000000000006, 156.43105879757186, 242) + femmesh.addNode(725.6160182470485, 500.00000000000006, 174.81677285424448, 243) + femmesh.addNode(7262.823446094069, 500.00000000000006, 192.4538441331061, 244) + femmesh.addNode(1494.7928306215902, 500.00000000000017, 827.7556137962181, 245) + femmesh.addNode(3986.688650859878, 500.00000000000017, 827.7556137962197, 246) + femmesh.addNode(7825.553130632656, 500.00000000000006, 162.94475519235124, 247) + femmesh.addNode(7826.130266239045, 500.00000000000017, 836.4834420448423, 248) + femmesh.addNode(174.44686936734647, 500.00000000000006, 162.94475519235232, 249) + femmesh.addNode(173.86973376095088, 500.00000000000017, 836.4834420448464, 250) + femmesh.addNode(5516.7524629964155, 500.0000000000001, 470.61996020787507, 251) + femmesh.addNode(4074.074074074062, 500.0, 121.85682748139425, 252) + femmesh.addNode(7086.699429390618, 500.00000000000006, 190.49758598986327, 253) + femmesh.addNode(428.44756058449417, 500.00000000000006, 183.5079071504006, 254) + femmesh.addNode(7571.5524394155, 500.00000000000006, 183.50790715040193, 255) + femmesh.addNode(2740.7407407407372, 500.0, 121.14512062141621, 256) + femmesh.addNode(5467.691311006454, 500.00000000000006, 187.51789055260895, 257) + femmesh.addNode(5467.400791725283, 500.00000000000017, 828.2803450779077, 258) + femmesh.addNode(4734.0515891099985, 500.0000000000001, 583.8482801067205, 259) + femmesh.addNode(2080.7632257048044, 500.0000000000001, 583.8482801067206, 260) + femmesh.addNode(3400.718255776669, 500.0000000000001, 583.8482801067222, 261) + femmesh.addNode(6511.829366887792, 500.0000000000001, 416.15171989328, 262) + femmesh.addNode(400.3512081049426, 500.00000000000017, 846.8008971381519, 263) + femmesh.addNode(7599.648791895056, 500.00000000000017, 846.8008971381512, 264) + femmesh.addNode(966.6320735277731, 500.00000000000017, 698.647975822787, 265) + femmesh.addNode(5297.676075082977, 500.00000000000017, 839.2396947387587, 266) + femmesh.addNode(2609.605679117323, 500.00000000000017, 653.4814963797409, 267) + femmesh.addNode(2884.656176355563, 500.0000000000001, 632.9897863356696, 268) + femmesh.addNode(1250.4934292500484, 500.00000000000006, 354.39301791483, 269) + femmesh.addNode(1457.704031244262, 500.00000000000006, 174.38597584487252, 270) + femmesh.addNode(4205.7663298043235, 500.00000000000017, 654.8844048420551, 271) + femmesh.addNode(1276.5985065799127, 500.00000000000017, 654.8512204592574, 272) + femmesh.addNode(3475.7957490559957, 500.00000000000006, 130.98143095516488, 273) + femmesh.addNode(2006.1825797348654, 500.00000000000006, 130.3681769602606, 274) + femmesh.addNode(4672.9052862415865, 500.00000000000006, 130.769626777317, 275) + femmesh.addNode(6449.497286440266, 500.00000000000017, 872.3962429173732, 276) + femmesh.addNode(956.5842338869468, 500.00000000000006, 344.12594769931235, 277) + femmesh.addNode(5741.105115276625, 500.0000000000001, 636.3630916365788, 278) + femmesh.addNode(5737.421169773017, 500.00000000000006, 356.0063687110833, 279) + femmesh.addNode(1788.1293897467203, 500.00000000000017, 835.2679450895512, 280) + femmesh.addNode(3693.352091734751, 500.00000000000017, 835.2679450895522, 281) + femmesh.addNode(6807.773849262738, 500.00000000000006, 176.45524487039563, 282) + femmesh.addNode(6257.079127394955, 500.00000000000006, 375.7316242978608, 283) + femmesh.addNode(3147.801784975059, 500.0000000000001, 623.8970090043587, 284) + femmesh.addNode(2333.6796965064173, 500.0000000000001, 623.8970090043587, 285) + femmesh.addNode(4481.064200456697, 500.0000000000001, 623.9553851735127, 286) + femmesh.addNode(142.48875513251812, 500.00000000000006, 365.5479406572575, 287) + femmesh.addNode(132.69644839780614, 500.0000000000001, 621.9515129513198, 288) + femmesh.addNode(7857.511244867481, 500.00000000000006, 365.54794065725815, 289) + femmesh.addNode(7867.303551602192, 500.0000000000001, 621.9515129513204, 290) + femmesh.addNode(6050.904786140333, 500.0000000000001, 631.104905099893, 291) + femmesh.addNode(5999.228508041354, 500.0000000000001, 426.6577526874719, 292) + femmesh.addNode(5530.871267588542, 500.0000000000001, 613.5892457981489, 293) + femmesh.addNode(5022.55147120029, 500.00000000000017, 823.4910615448234, 294) + femmesh.addNode(444.86810075408346, 500.00000000000006, 336.59582645899343, 295) + femmesh.addNode(7555.131899245911, 500.00000000000006, 336.5958264589947, 296) + femmesh.addNode(5208.421967836855, 500.00000000000006, 373.8619860209515, 297) + femmesh.addNode(7124.013307196437, 500.00000000000017, 843.4626017775935, 298) + femmesh.addNode(7643.596658117825, 500.0000000000001, 576.1777158335027, 299) + femmesh.addNode(356.40334188216684, 500.0000000000001, 576.1777158335007, 300) + femmesh.addNode(7325.398274566561, 500.0000000000001, 624.7219971245336, 301) + femmesh.addNode(669.4128790649441, 500.0000000000001, 630.9511423060778, 302) + femmesh.addNode(4271.4259430168, 500.00000000000006, 381.33147533687037, 303) + femmesh.addNode(1604.7592763501386, 500.00000000000006, 381.3314753368656, 304) + femmesh.addNode(3868.64401759244, 500.00000000000006, 373.32694976638714, 305) + femmesh.addNode(6876.174786203425, 500.00000000000017, 844.2790834980128, 306) + femmesh.addNode(3709.9466361009627, 500.00000000000017, 659.307020293735, 307) + femmesh.addNode(1771.7687116854875, 500.00000000000017, 658.2547198118081, 308) + femmesh.addNode(2939.648545872431, 500.00000000000006, 380.5429652593053, 309) + femmesh.addNode(2541.832935609046, 500.00000000000006, 380.54296525930584, 310) + femmesh.addNode(6823.303377023775, 500.00000000000006, 349.02942036926675, 311) + femmesh.addNode(5040.2820737786315, 500.00000000000017, 656.2028896227729, 312) + femmesh.addNode(5936.688923736598, 500.00000000000017, 836.7136430070282, 313) + femmesh.addNode(6904.785449318018, 500.00000000000017, 659.1042922054407, 314) + femmesh.addNode(5208.421967836853, 500.0000000000001, 618.4464215357175, 315) + femmesh.addNode(3737.5363252606157, 500.00000000000006, 162.8690753300165, 316) + femmesh.addNode(1716.2474173250976, 500.00000000000006, 141.97654503503156, 317) + femmesh.addNode(4410.701773864508, 500.00000000000006, 163.30513944907898, 318) + femmesh.addNode(2399.2631217871217, 500.00000000000006, 170.3044946230016, 319) + femmesh.addNode(3082.2183596943514, 500.00000000000006, 170.30449462300174, 320) + femmesh.addNode(5324.033304499792, 500.00000000000006, 155.91639291345302, 321) + femmesh.addNode(5090.478583640191, 500.00000000000006, 146.9524258936218, 322) + femmesh.addNode(3848.098725536811, 500.0000000000001, 629.682037888319, 323) + femmesh.addNode(1631.8998987462733, 500.0000000000001, 626.2985077811038, 324) + femmesh.addNode(6985.86484753412, 500.0000000000001, 404.1001082151455, 325) + femmesh.addNode(7057.844245270041, 500.0000000000001, 634.4823372198036, 326) + femmesh.addNode(3540.608606644148, 500.00000000000006, 373.333262023751, 327) + femmesh.addNode(1813.929384731171, 500.0000000000001, 405.88544152653253, 328) + femmesh.addNode(6663.278233719539, 500.0000000000001, 621.6844664136647, 329) + femmesh.addNode(4998.752613089293, 500.0000000000001, 410.0543301382136, 330) + femmesh.addNode(6170.265987554111, 500.00000000000017, 862.3354102331693, 331) + femmesh.addNode(592.765509644456, 500.0000000000001, 394.57261654323963, 332) + femmesh.addNode(7407.234490355553, 500.0000000000001, 394.57261654323133, 333) + femmesh.addNode(4938.544501943162, 500.0, 117.69598813414211, 334) + femmesh.addNode(2254.5731308291006, 500.00000000000006, 136.6309374675551, 335) + femmesh.addNode(3226.9083506523734, 500.00000000000006, 136.63093746755263, 336) + femmesh.addNode(6699.0175752735395, 500.00000000000017, 863.369062532444, 337) + femmesh.addNode(6265.667832999652, 500.0000000000001, 623.5424699259635, 338) + femmesh.addNode(6382.144573309605, 500.00000000000017, 642.585583774286, 339) + femmesh.addNode(3287.7079767721007, 500.00000000000006, 355.80370224167774, 340) + femmesh.addNode(3153.5224958938556, 500.00000000000006, 380.2202340827241, 341) + femmesh.addNode(4466.991157520215, 500.0000000000001, 399.26310595332023, 342) + femmesh.addNode(2347.823657294588, 500.0000000000001, 399.26310595331927, 343) + femmesh.addNode(4607.572883809357, 500.00000000000006, 377.71278105560907, 344) + femmesh.addNode(2198.5917276376504, 500.00000000000006, 355.99367369524987, 345) + femmesh.addNode(4862.285873490269, 500.00000000000006, 356.7457451179127, 346) + femmesh.addNode(3691.955202282983, 500.0000000000001, 403.198392847795, 347) + femmesh.addNode(1949.0013166444596, 500.00000000000006, 380.1484702474387, 348) + femmesh.addNode(7682.268866693696, 500.0000000000001, 421.77382341505654, 349) + femmesh.addNode(317.73113330630065, 500.0000000000001, 421.7738234150559, 350) + femmesh.addNode(3557.772894404354, 500.00000000000017, 861.8561150805002, 351) + femmesh.addNode(1923.7085870771184, 500.00000000000017, 861.8561150804992, 352) + femmesh.addNode(6668.583619555279, 500.00000000000006, 137.93605796145883, 353) + femmesh.addNode(422.89279148885663, 500.00000000000017, 705.2711873455931, 354) + femmesh.addNode(7577.107208511141, 500.00000000000017, 705.271187345593, 355) + femmesh.addNode(2734.926315100451, 500.00000000000017, 888.9545107305078, 356) + femmesh.addNode(5503.918843584262, 500.00000000000006, 330.71293303974284, 357) + femmesh.addNode(7474.552307081463, 500.00000000000017, 888.5084838362908, 358) + femmesh.addNode(525.4476929185394, 500.00000000000017, 888.5084838362966, 359) + femmesh.addNode(6035.493573501297, 500.00000000000006, 304.195501047588, 360) + femmesh.addNode(540.2212360002914, 500.0, 112.61725241699837, 361) + femmesh.addNode(7459.7787639997, 500.0, 112.61725241700351, 362) + femmesh.addNode(4354.442907841224, 500.00000000000017, 888.339347516092, 363) + femmesh.addNode(2460.7843765444773, 500.00000000000017, 888.0750968127634, 364) + femmesh.addNode(3017.589469779312, 500.00000000000017, 885.6019346348578, 365) + femmesh.addNode(1114.9050565484902, 500.0, 113.20294012239405, 366) + femmesh.addNode(1122.287309239265, 500.00000000000017, 887.9008082187651, 367) + femmesh.addNode(6150.994835871662, 500.0, 112.70534774447657, 368) + femmesh.addNode(6563.586741910367, 500.00000000000006, 315.8599768732983, 369) + femmesh.addNode(3452.475630799244, 500.00000000000017, 684.1400231267033, 370) + femmesh.addNode(2029.0058506822288, 500.00000000000017, 684.1400231267022, 371) + femmesh.addNode(4785.808964132577, 500.00000000000017, 684.1400231266972, 372) + femmesh.addNode(4882.9311878878625, 500.00000000000017, 867.5121506116186, 373) + femmesh.addNode(4199.619189652648, 500.0, 120.47005435871915, 374) + femmesh.addNode(3948.5289584954694, 500.0, 120.47005435871124, 375) + femmesh.addNode(2614.9050181912507, 500.0, 120.29130990045124, 376) + femmesh.addNode(2866.5764632902237, 500.0, 120.29130990044634, 377) + femmesh.addNode(7706.426190551767, 500.0, 122.79281432071397, 378) + femmesh.addNode(293.5738094482332, 500.0, 122.79281432071534, 379) + femmesh.addNode(5668.519908699008, 500.0, 108.78741739580167, 380) + femmesh.addNode(5672.2905340790885, 500.00000000000017, 895.9574866333423, 381) + femmesh.addNode(6780.5068908153335, 500.0000000000001, 577.6276790039055, 382) + femmesh.addNode(1717.8290726902774, 500.00000000000006, 316.8197761733028, 383) + femmesh.addNode(4650.466764911562, 500.00000000000017, 883.5856886038878, 384) + femmesh.addNode(2164.3480499032394, 500.00000000000017, 883.585688603893, 385) + femmesh.addNode(3317.133431578238, 500.00000000000017, 883.5856886038969, 386) + femmesh.addNode(6428.244542689359, 500.0, 116.41431139610256, 387) + femmesh.addNode(836.6508539248216, 500.00000000000017, 885.2356310303675, 388) + femmesh.addNode(1597.5206282730637, 500.00000000000017, 893.7491236895847, 389) + femmesh.addNode(3883.9608532084067, 500.00000000000017, 893.7491236895854, 390) + femmesh.addNode(6926.465161850476, 500.0, 123.82919649722665, 391) + femmesh.addNode(4378.563776959021, 500.00000000000006, 305.2556395901117, 392) + femmesh.addNode(712.2419870051812, 500.00000000000006, 319.66613304580596, 393) + femmesh.addNode(7302.225560220031, 500.00000000000006, 328.29619908333325, 394) + femmesh.addNode(3045.329464591457, 500.00000000000006, 305.28035820367467, 395) + femmesh.addNode(2436.1520168900133, 500.00000000000006, 305.28035820366966, 396) + femmesh.addNode(1106.1574778717522, 500.0000000000001, 386.00217950321803, 397) + femmesh.addNode(1117.9057422131627, 500.0000000000001, 622.1179377282334, 398) + femmesh.addNode(3756.164024773751, 500.00000000000006, 281.19576384871647, 399) + femmesh.addNode(5097.69967759807, 500.00000000000006, 317.3991767081932, 400) + femmesh.addNode(5131.145465942268, 500.00000000000017, 885.7289564223155, 401) + femmesh.addNode(6154.250245046664, 500.00000000000017, 697.1943164034237, 402) + femmesh.addNode(3452.15271525592, 500.00000000000006, 274.19460708300153, 403) + femmesh.addNode(1567.6178600338658, 500.0, 108.81013618086062, 404) + femmesh.addNode(7062.49730977581, 500.00000000000006, 300.40403707860503, 405) + femmesh.addNode(6482.64752026125, 500.00000000000017, 739.9989516416008, 406) + femmesh.addNode(4693.327611746292, 500.00000000000006, 269.39362060709345, 407) + femmesh.addNode(1517.1228178606711, 500.00000000000017, 694.5768231229472, 408) + femmesh.addNode(3963.798060037384, 500.00000000000017, 695.1954599819605, 409) + femmesh.addNode(1857.9174134050013, 500.0, 104.26736045199264, 410) + femmesh.addNode(3622.8247892206255, 500.0, 105.37270067698638, 411) + femmesh.addNode(4525.502882516417, 500.0, 105.30444335931585, 412) + femmesh.addNode(847.6263774639385, 500.0, 110.07064815120478, 413) + femmesh.addNode(282.87317584511385, 500.00000000000017, 877.7855258943977, 414) + femmesh.addNode(7717.126824154883, 500.00000000000017, 877.785525894397, 415) + femmesh.addNode(2027.0719864729972, 500.00000000000006, 267.3395309728046, 416) + femmesh.addNode(7015.779521089671, 500.00000000000017, 888.7214870040931, 417) + femmesh.addNode(5952.629790678609, 500.0000000000001, 557.1247698154624, 418) + femmesh.addNode(4107.6773567238815, 500.00000000000017, 890.2581681720553, 419) + femmesh.addNode(1377.8592606467264, 500.00000000000017, 890.0552715233002, 420) + femmesh.addNode(7473.748205742472, 500.0000000000001, 616.9720318049243, 421) + femmesh.addNode(521.9604750418066, 500.0000000000001, 617.1192217303526, 422) + femmesh.addNode(95.44983528072514, 500.0000000000001, 498.72443404169064, 423) + femmesh.addNode(7904.550164719275, 500.0000000000001, 498.72443404169076, 424) + femmesh.addNode(6121.062634589897, 500.00000000000006, 375.56212342765303, 425) + femmesh.addNode(4151.522367566544, 500.00000000000006, 258.53991424747824, 426) + femmesh.addNode(3994.466719790979, 500.00000000000006, 258.41764443089056, 427) + femmesh.addNode(4354.351085094542, 500.0000000000001, 619.199291231222, 428) + femmesh.addNode(2662.9456287413027, 500.00000000000006, 257.5976899925193, 429) + femmesh.addNode(2819.628071253836, 500.00000000000006, 258.82828067624115, 430) + femmesh.addNode(5418.224057723975, 500.0000000000001, 540.786888671358, 431) + femmesh.addNode(5883.187458672368, 500.0, 112.31868098172531, 432) + femmesh.addNode(3021.640795816791, 500.0000000000001, 618.6923063382654, 433) + femmesh.addNode(2459.840685664688, 500.0000000000001, 618.6923063382653, 434) + femmesh.addNode(5610.380855453107, 500.00000000000006, 379.88813316713396, 435) + femmesh.addNode(5262.288932839039, 500.00000000000017, 722.8898289041445, 436) + femmesh.addNode(7184.700911554622, 500.0, 93.46533188647751, 437) + femmesh.addNode(807.6882235109797, 500.0000000000001, 444.13714689257904, 438) + femmesh.addNode(7195.342883397356, 500.0000000000001, 541.568863515383, 439) + femmesh.addNode(1496.0779157026154, 500.00000000000006, 335.95862802786013, 440) + femmesh.addNode(5551.34599817357, 500.0, 92.16588192523949, 441) + femmesh.addNode(5551.3459981735605, 500.0000000000002, 907.8341180747605, 442) + femmesh.addNode(6304.809569856905, 500.0000000000002, 897.4526057236726, 443) + femmesh.addNode(829.631389505289, 500.00000000000017, 772.7215069246502, 444) + femmesh.addNode(4074.074074074068, 500.0000000000001, 556.2021550156052, 445) + femmesh.addNode(2740.7407407407377, 500.0000000000001, 553.6364794273326, 446) + femmesh.addNode(1407.4074074074056, 500.0000000000001, 556.2021550156056, 447) + femmesh.addNode(7752.921937697393, 500.0000000000001, 605.6891042725961, 448) + femmesh.addNode(247.07806230258075, 500.0000000000001, 605.689104272601, 449) + femmesh.addNode(2742.554426357161, 500.0000000000001, 441.557080091506, 450) + femmesh.addNode(1392.2864523495814, 500.0000000000001, 422.67744584028634, 451) + femmesh.addNode(4071.3488295859097, 500.0000000000001, 445.2310697794399, 452) + femmesh.addNode(965.6969126809465, 500.0000000000002, 912.0774375447143, 453) + femmesh.addNode(6034.870736487629, 500.00000000000017, 895.1962961523193, 454) + femmesh.addNode(4813.423945488539, 500.0, 88.0131384501446, 455) + femmesh.addNode(3336.804449325129, 500.0, 89.91235845460876, 456) + femmesh.addNode(2145.712718072921, 500.0, 88.10035749617299, 457) + femmesh.addNode(6588.322684837114, 500.0000000000002, 913.3310723189843, 458) + femmesh.addNode(5217.485699956585, 500.0, 106.99514838295694, 459) + femmesh.addNode(7126.248597636713, 500.00000000000017, 736.6366361423236, 460) + femmesh.addNode(7037.037037037038, 500.0, 82.53410217182414, 461) + femmesh.addNode(626.1800075871399, 500.00000000000017, 891.9385071582001, 462) + femmesh.addNode(7344.2083746165445, 500.00000000000017, 889.0402901816267, 463) + femmesh.addNode(103.79991695738111, 500.00000000000017, 743.8593806334494, 464) + femmesh.addNode(106.40465223691201, 500.00000000000006, 246.5811076582841, 465) + femmesh.addNode(7893.595347763094, 500.00000000000006, 246.5811076582797, 466) + femmesh.addNode(7896.200083042626, 500.00000000000017, 743.8593806334587, 467) + femmesh.addNode(635.6715787265157, 500.0, 103.68667758196041, 468) + femmesh.addNode(7346.378414415707, 500.0, 97.80962770945953, 469) + femmesh.addNode(5498.398551507691, 500.00000000000017, 716.9660389968634, 470) + femmesh.addNode(5855.635907299063, 500.0000000000002, 914.8320239998321, 471) + femmesh.addNode(3551.6012340221146, 500.0000000000001, 594.5031057095781, 472) + femmesh.addNode(1935.1372049729575, 500.0000000000001, 601.706161892535, 473) + femmesh.addNode(4882.6908046827475, 500.0000000000001, 597.4202283839372, 474) + femmesh.addNode(6657.508507648723, 500.0000000000001, 398.2113637306744, 475) + femmesh.addNode(6988.367503141852, 500.0000000000001, 547.5015401796788, 476) + femmesh.addNode(1017.6917785563771, 500.0000000000001, 452.53240748721714, 477) + femmesh.addNode(5387.738295780524, 500.0000000000002, 904.2804586849913, 478) + femmesh.addNode(2726.1438965832976, 500.00000000000017, 776.6288178802687, 479) + femmesh.addNode(5283.5868332074315, 500.00000000000006, 287.1772893263348, 480) + femmesh.addNode(1200.97279705511, 500.0000000000001, 544.4575711592724, 481) + femmesh.addNode(3667.8513153755084, 500.0000000000001, 531.9107568715456, 482) + femmesh.addNode(1815.1905074511733, 500.0000000000001, 537.2906229149341, 483) + femmesh.addNode(6772.260231715166, 500.0000000000001, 461.60647700262405, 484) + femmesh.addNode(4999.581659659807, 500.0000000000001, 536.8608981168566, 485) + femmesh.addNode(7203.6542408510595, 500.0000000000001, 428.72518955741486, 486) + femmesh.addNode(788.2251565826217, 500.0000000000001, 551.7972272592045, 487) + femmesh.addNode(3161.232159794134, 500.00000000000017, 728.6712438637365, 488) + femmesh.addNode(2320.2493216873436, 500.00000000000017, 728.6712438637376, 489) + femmesh.addNode(4494.552829225373, 500.00000000000017, 728.6816681796572, 490) + femmesh.addNode(6272.0158122104, 500.00000000000006, 271.2624406545201, 491) + femmesh.addNode(4089.959200653646, 500.00000000000017, 778.4323403800105, 492) + femmesh.addNode(1391.5222808278213, 500.00000000000017, 778.4323403800091, 493) + femmesh.addNode(2538.431512198923, 500.0000000000001, 533.976240706416, 494) + femmesh.addNode(2944.7369563953916, 500.0000000000001, 531.1174126267546, 495) + femmesh.addNode(7904.589064686527, 500.0000000000002, 906.4443132120504, 496) + femmesh.addNode(95.41093531346792, 500.0000000000002, 906.4443132120568, 497) + femmesh.addNode(90.50736318949515, 500.0, 102.1888063561127, 498) + femmesh.addNode(7909.492636810507, 500.0, 102.18880635611038, 499) + femmesh.addNode(5414.042014906579, 500.0, 82.1501785235767, 500) + femmesh.addNode(1699.2797972192734, 500.0000000000002, 906.521118082376, 501) + femmesh.addNode(3782.201684262197, 500.0000000000002, 906.5211180823751, 502) + femmesh.addNode(1363.769233361906, 500.0, 100.36463107278246, 503) + femmesh.addNode(2592.5925925925876, 500.0000000000002, 920.2962504519037, 504) + femmesh.addNode(2882.320457829789, 500.0000000000002, 915.3559704695299, 505) + femmesh.addNode(4276.278113146783, 500.0000000000001, 534.7238900714791, 506) + femmesh.addNode(5635.0855265602895, 500.0000000000001, 624.8227998835946, 507) + femmesh.addNode(1255.2667795857158, 500.0, 80.84876563718629, 508) + femmesh.addNode(2664.628802972087, 500.00000000000006, 381.4758980189642, 509) + femmesh.addNode(832.8749826325999, 500.00000000000006, 219.12744164786054, 510) + femmesh.addNode(4222.222222222219, 500.0000000000002, 920.9840993419909, 511) + femmesh.addNode(1259.2592592592569, 500.0000000000002, 920.9840993419933, 512) + femmesh.addNode(600.1101576452035, 500.0000000000001, 534.8185943508142, 513) + femmesh.addNode(7399.889842354805, 500.0000000000001, 534.8185943508029, 514) + femmesh.addNode(4149.617420853446, 500.00000000000006, 382.9452534327596, 515) + femmesh.addNode(3343.038093333996, 500.0000000000001, 473.37986692785205, 516) + femmesh.addNode(2202.813115409953, 500.0000000000001, 570.7926188996644, 517) + femmesh.addNode(4676.371426667326, 500.0000000000001, 473.3798669278519, 518) + femmesh.addNode(4611.985460094771, 500.0000000000001, 570.8061541782029, 519) + femmesh.addNode(2140.0547569001665, 500.0000000000001, 476.2901729998216, 520) + femmesh.addNode(3278.668366071523, 500.0000000000001, 570.7926188996656, 521) + femmesh.addNode(6458.982645116712, 500.0000000000001, 524.6420497886927, 522) + femmesh.addNode(6399.472142054875, 500.0000000000001, 426.87068612014446, 523) + femmesh.addNode(962.9629629629617, 500.0, 78.00542123291112, 524) + femmesh.addNode(2492.7052751552174, 500.0, 102.94009310276894, 525) + femmesh.addNode(2988.776206326256, 500.0, 102.94009310276799, 526) + femmesh.addNode(4316.723988778715, 500.0, 103.29546259094175, 527) + femmesh.addNode(3831.424930064103, 500.0, 103.19980639265381, 528) + femmesh.addNode(7218.944669475787, 500.0000000000002, 901.1460389204676, 529) + femmesh.addNode(3471.1990721711118, 500.0000000000001, 481.74561260477105, 530) + femmesh.addNode(2014.286992373035, 500.0000000000001, 488.18451586524384, 531) + femmesh.addNode(4804.089608860568, 500.0000000000001, 475.7595677289195, 532) + femmesh.addNode(6584.199906329039, 500.0000000000001, 513.355040238768, 533) + femmesh.addNode(2817.7076438112927, 500.00000000000006, 381.81799885299773, 534) + femmesh.addNode(6634.452749644213, 500.00000000000017, 735.5099606524759, 535) + femmesh.addNode(5998.042142164987, 500.00000000000017, 722.8587787582359, 536) + femmesh.addNode(3989.5798378280742, 500.0000000000001, 384.150166271885, 537) + femmesh.addNode(7102.959324254702, 500.0000000000001, 392.0640895099264, 538) + femmesh.addNode(1002.715395532759, 500.0000000000001, 561.2332349842806, 539) + femmesh.addNode(5373.098365336791, 500.0000000000001, 399.168690026159, 540) + femmesh.addNode(3466.0691755260673, 500.0000000000002, 912.945469964282, 541) + femmesh.addNode(2015.4123059554024, 500.0000000000002, 912.9454699642827, 542) + femmesh.addNode(1195.4851045136184, 500.0000000000001, 453.57002951351325, 543) + femmesh.addNode(1021.7292038259692, 500.00000000000017, 810.4829151657295, 544) + femmesh.addNode(895.2097556761555, 500.0000000000001, 593.5769141681038, 545) + femmesh.addNode(6576.897880224705, 500.0, 87.0855719830333, 546) + return True + + +def create_elements(femmesh): + # elements + femmesh.addFace([220, 445, 409], 123) + femmesh.addFace([408, 447, 217], 124) + femmesh.addFace([128, 285, 210], 125) + femmesh.addFace([211, 286, 125], 126) + femmesh.addFace([209, 284, 126], 127) + femmesh.addFace([132, 283, 212], 128) + femmesh.addFace([206, 340, 167], 129) + femmesh.addFace([166, 345, 207], 130) + femmesh.addFace([220, 409, 323], 131) + femmesh.addFace([324, 408, 217], 132) + femmesh.addFace([345, 416, 207], 133) + femmesh.addFace([135, 416, 345], 134) + femmesh.addFace([206, 403, 340], 135) + femmesh.addFace([155, 278, 221], 136) + femmesh.addFace([221, 278, 134], 137) + femmesh.addFace([134, 279, 221], 138) + femmesh.addFace([221, 279, 156], 139) + femmesh.addFace([340, 403, 137], 140) + femmesh.addFace([149, 315, 222], 141) + femmesh.addFace([240, 278, 155], 142) + femmesh.addFace([241, 279, 186], 143) + femmesh.addFace([156, 279, 241], 144) + femmesh.addFace([187, 278, 240], 145) + femmesh.addFace([182, 302, 235], 146) + femmesh.addFace([234, 301, 181], 147) + femmesh.addFace([235, 302, 139], 148) + femmesh.addFace([140, 301, 234], 149) + femmesh.addFace([170, 346, 205], 150) + femmesh.addFace([273, 456, 33], 151) + femmesh.addFace([42, 455, 275], 152) + femmesh.addFace([24, 457, 274], 153) + femmesh.addFace([276, 458, 113], 154) + femmesh.addFace([232, 386, 151], 155) + femmesh.addFace([153, 385, 231], 156) + femmesh.addFace([152, 387, 233], 157) + femmesh.addFace([230, 384, 154], 158) + femmesh.addFace([162, 312, 294], 159) + femmesh.addFace([294, 312, 188], 160) + femmesh.addFace([225, 270, 143], 161) + femmesh.addFace([222, 431, 149], 162) + femmesh.addFace([104, 266, 105], 163) + femmesh.addFace([346, 407, 205], 164) + femmesh.addFace([177, 365, 226], 165) + femmesh.addFace([224, 364, 176], 166) + femmesh.addFace([178, 366, 225], 167) + femmesh.addFace([156, 292, 221], 168) + femmesh.addFace([226, 268, 177], 169) + femmesh.addFace([142, 268, 226], 170) + femmesh.addFace([176, 267, 224], 171) + femmesh.addFace([143, 269, 225], 172) + femmesh.addFace([225, 269, 178], 173) + femmesh.addFace([151, 386, 237], 174) + femmesh.addFace([238, 385, 153], 175) + femmesh.addFace([239, 387, 152], 176) + femmesh.addFace([154, 384, 236], 177) + femmesh.addFace([291, 418, 132], 178) + femmesh.addFace([132, 418, 292], 179) + femmesh.addFace([103, 373, 294], 180) + femmesh.addFace([102, 373, 103], 181) + femmesh.addFace([217, 451, 440], 182) + femmesh.addFace([228, 367, 180], 183) + femmesh.addFace([175, 363, 227], 184) + femmesh.addFace([265, 444, 139], 185) + femmesh.addFace([230, 373, 101], 186) + femmesh.addFace([172, 314, 306], 187) + femmesh.addFace([306, 314, 189], 188) + femmesh.addFace([136, 407, 346], 189) + femmesh.addFace([104, 401, 266], 190) + femmesh.addFace([180, 272, 228], 191) + femmesh.addFace([227, 271, 175], 192) + femmesh.addFace([223, 444, 265], 193) + femmesh.addFace([254, 379, 13], 194) + femmesh.addFace([61, 378, 255], 195) + femmesh.addFace([280, 352, 81], 196) + femmesh.addFace([94, 351, 281], 197) + femmesh.addFace([282, 353, 56], 198) + femmesh.addFace([241, 432, 156], 199) + femmesh.addFace([289, 349, 158], 200) + femmesh.addFace([160, 350, 287], 201) + femmesh.addFace([229, 366, 178], 202) + femmesh.addFace([148, 253, 244], 203) + femmesh.addFace([178, 277, 229], 204) + femmesh.addFace([156, 432, 242], 205) + femmesh.addFace([191, 349, 289], 206) + femmesh.addFace([287, 350, 190], 207) + femmesh.addFace([185, 311, 282], 208) + femmesh.addFace([282, 311, 164], 209) + femmesh.addFace([131, 297, 222], 210) + femmesh.addFace([161, 307, 281], 211) + femmesh.addFace([183, 308, 280], 212) + femmesh.addFace([280, 308, 163], 213) + femmesh.addFace([281, 307, 184], 214) + femmesh.addFace([56, 353, 55], 215) + femmesh.addFace([81, 352, 82], 216) + femmesh.addFace([93, 351, 94], 217) + femmesh.addFace([217, 440, 304], 218) + femmesh.addFace([205, 334, 170], 219) + femmesh.addFace([167, 336, 206], 220) + femmesh.addFace([207, 335, 166], 221) + femmesh.addFace([34, 273, 33], 222) + femmesh.addFace([42, 275, 41], 223) + femmesh.addFace([24, 274, 23], 224) + femmesh.addFace([112, 276, 113], 225) + femmesh.addFace([53, 239, 52], 226) + femmesh.addFace([99, 236, 100], 227) + femmesh.addFace([90, 237, 91], 228) + femmesh.addFace([84, 238, 85], 229) + femmesh.addFace([210, 343, 128], 230) + femmesh.addFace([125, 342, 211], 231) + femmesh.addFace([126, 341, 209], 232) + femmesh.addFace([212, 338, 132], 233) + femmesh.addFace([11, 379, 249], 234) + femmesh.addFace([247, 378, 63], 235) + femmesh.addFace([217, 304, 130], 236) + femmesh.addFace([127, 305, 220], 237) + femmesh.addFace([158, 296, 255], 238) + femmesh.addFace([254, 295, 160], 239) + femmesh.addFace([62, 378, 61], 240) + femmesh.addFace([13, 379, 12], 241) + femmesh.addFace([206, 456, 273], 242) + femmesh.addFace([275, 455, 205], 243) + femmesh.addFace([274, 457, 207], 244) + femmesh.addFace([208, 458, 276], 245) + femmesh.addFace([234, 460, 140], 246) + femmesh.addFace([71, 263, 72], 247) + femmesh.addFace([120, 264, 121], 248) + femmesh.addFace([409, 445, 145], 249) + femmesh.addFace([146, 447, 408], 250) + femmesh.addFace([173, 295, 254], 251) + femmesh.addFace([255, 296, 174], 252) + femmesh.addFace([277, 438, 147], 253) + femmesh.addFace([214, 438, 277], 254) + femmesh.addFace([222, 315, 131], 255) + femmesh.addFace([258, 266, 149], 256) + femmesh.addFace([71, 414, 263], 257) + femmesh.addFace([264, 415, 121], 258) + femmesh.addFace([130, 324, 217], 259) + femmesh.addFace([220, 323, 127], 260) + femmesh.addFace([51, 242, 50], 261) + femmesh.addFace([132, 402, 291], 262) + femmesh.addFace([267, 479, 224], 263) + femmesh.addFace([221, 418, 155], 264) + femmesh.addFace([247, 466, 158], 265) + femmesh.addFace([157, 467, 248], 266) + femmesh.addFace([160, 465, 249], 267) + femmesh.addFace([250, 464, 159], 268) + femmesh.addFace([298, 460, 234], 269) + femmesh.addFace([338, 402, 132], 270) + femmesh.addFace([142, 479, 267], 271) + femmesh.addFace([290, 467, 157], 272) + femmesh.addFace([158, 466, 289], 273) + femmesh.addFace([287, 465, 160], 274) + femmesh.addFace([159, 464, 288], 275) + femmesh.addFace([12, 379, 11], 276) + femmesh.addFace([63, 378, 62], 277) + femmesh.addFace([303, 392, 125], 278) + femmesh.addFace([131, 400, 297], 279) + femmesh.addFace([128, 396, 310], 280) + femmesh.addFace([309, 395, 126], 281) + femmesh.addFace([150, 321, 257], 282) + femmesh.addFace([125, 392, 342], 283) + femmesh.addFace([343, 396, 128], 284) + femmesh.addFace([126, 395, 341], 285) + femmesh.addFace([127, 347, 305], 286) + femmesh.addFace([272, 493, 228], 287) + femmesh.addFace([227, 492, 271], 288) + femmesh.addFace([330, 400, 131], 289) + femmesh.addFace([138, 535, 406], 290) + femmesh.addFace([110, 454, 331], 291) + femmesh.addFace([274, 416, 168], 292) + femmesh.addFace([171, 406, 276], 293) + femmesh.addFace([275, 407, 165], 294) + femmesh.addFace([169, 403, 273], 295) + femmesh.addFace([146, 493, 272], 296) + femmesh.addFace([271, 492, 145], 297) + femmesh.addFace([101, 373, 102], 298) + femmesh.addFace([134, 293, 251], 299) + femmesh.addFace([110, 331, 111], 300) + femmesh.addFace([366, 508, 225], 301) + femmesh.addFace([239, 368, 52], 302) + femmesh.addFace([99, 363, 236], 303) + femmesh.addFace([90, 365, 237], 304) + femmesh.addFace([238, 364, 85], 305) + femmesh.addFace([347, 399, 305], 306) + femmesh.addFace([224, 504, 364], 307) + femmesh.addFace([365, 505, 226], 308) + femmesh.addFace([304, 383, 130], 309) + femmesh.addFace([267, 446, 142], 310) + femmesh.addFace([216, 446, 267], 311) + femmesh.addFace([268, 446, 218], 312) + femmesh.addFace([142, 446, 268], 313) + femmesh.addFace([168, 416, 348], 314) + femmesh.addFace([130, 383, 328], 315) + femmesh.addFace([393, 438, 203], 316) + femmesh.addFace([277, 510, 229], 317) + femmesh.addFace([300, 350, 124], 318) + femmesh.addFace([123, 349, 299], 319) + femmesh.addFace([339, 406, 171], 320) + femmesh.addFace([165, 407, 344], 321) + femmesh.addFace([145, 445, 271], 322) + femmesh.addFace([271, 445, 215], 323) + femmesh.addFace([272, 447, 146], 324) + femmesh.addFace([219, 447, 272], 325) + femmesh.addFace([147, 510, 277], 326) + femmesh.addFace([38, 252, 37], 327) + femmesh.addFace([327, 403, 169], 328) + femmesh.addFace([124, 350, 295], 329) + femmesh.addFace([296, 349, 123], 330) + femmesh.addFace([363, 511, 227], 331) + femmesh.addFace([228, 512, 367], 332) + femmesh.addFace([440, 451, 143], 333) + femmesh.addFace([245, 389, 79], 334) + femmesh.addFace([96, 390, 246], 335) + femmesh.addFace([115, 337, 306], 336) + femmesh.addFace([29, 256, 28], 337) + femmesh.addFace([139, 444, 235], 338) + femmesh.addFace([226, 479, 142], 339) + femmesh.addFace([45, 322, 44], 340) + femmesh.addFace([155, 313, 240], 341) + femmesh.addFace([139, 545, 265], 342) + femmesh.addFace([317, 404, 21], 343) + femmesh.addFace([122, 415, 248], 344) + femmesh.addFace([250, 414, 70], 345) + femmesh.addFace([185, 391, 253], 346) + femmesh.addFace([229, 524, 366], 347) + femmesh.addFace([269, 451, 219], 348) + femmesh.addFace([143, 451, 269], 349) + femmesh.addFace([162, 373, 230], 350) + femmesh.addFace([231, 371, 153], 351) + femmesh.addFace([154, 372, 230], 352) + femmesh.addFace([151, 370, 232], 353) + femmesh.addFace([233, 369, 152], 354) + femmesh.addFace([51, 368, 242], 355) + femmesh.addFace([319, 335, 26], 356) + femmesh.addFace([31, 336, 320], 357) + femmesh.addFace([233, 353, 164], 358) + femmesh.addFace([161, 351, 232], 359) + femmesh.addFace([231, 352, 163], 360) + femmesh.addFace([22, 317, 21], 361) + femmesh.addFace([179, 368, 239], 362) + femmesh.addFace([237, 365, 177], 363) + femmesh.addFace([176, 364, 238], 364) + femmesh.addFace([236, 363, 175], 365) + femmesh.addFace([45, 459, 322], 366) + femmesh.addFace([108, 381, 240], 367) + femmesh.addFace([241, 380, 49], 368) + femmesh.addFace([235, 462, 182], 369) + femmesh.addFace([181, 463, 234], 370) + femmesh.addFace([175, 490, 236], 371) + femmesh.addFace([177, 488, 237], 372) + femmesh.addFace([238, 489, 176], 373) + femmesh.addFace([239, 491, 179], 374) + femmesh.addFace([115, 306, 116], 375) + femmesh.addFace([101, 384, 230], 376) + femmesh.addFace([472, 482, 307], 377) + femmesh.addFace([308, 483, 473], 378) + femmesh.addFace([311, 484, 475], 379) + femmesh.addFace([474, 485, 312], 380) + femmesh.addFace([299, 421, 123], 381) + femmesh.addFace([124, 422, 300], 382) + femmesh.addFace([161, 472, 307], 383) + femmesh.addFace([308, 473, 163], 384) + femmesh.addFace([311, 475, 164], 385) + femmesh.addFace([162, 474, 312], 386) + femmesh.addFace([406, 535, 208], 387) + femmesh.addFace([257, 357, 150], 388) + femmesh.addFace([186, 357, 257], 389) + femmesh.addFace([173, 468, 243], 390) + femmesh.addFace([244, 469, 174], 391) + femmesh.addFace([391, 461, 253], 392) + femmesh.addFace([232, 370, 161], 393) + femmesh.addFace([163, 371, 231], 394) + femmesh.addFace([230, 372, 162], 395) + femmesh.addFace([164, 369, 233], 396) + femmesh.addFace([242, 368, 179], 397) + femmesh.addFace([159, 414, 250], 398) + femmesh.addFace([248, 415, 157], 399) + femmesh.addFace([480, 540, 297], 400) + femmesh.addFace([240, 471, 108], 401) + femmesh.addFace([266, 401, 188], 402) + femmesh.addFace([204, 486, 394], 403) + femmesh.addFace([355, 421, 299], 404) + femmesh.addFace([300, 422, 354], 405) + femmesh.addFace([149, 436, 315], 406) + femmesh.addFace([306, 417, 116], 407) + femmesh.addFace([95, 390, 96], 408) + femmesh.addFace([79, 389, 80], 409) + femmesh.addFace([329, 535, 138], 410) + femmesh.addFace([44, 334, 43], 411) + femmesh.addFace([114, 337, 115], 412) + femmesh.addFace([26, 335, 25], 413) + femmesh.addFace([32, 336, 31], 414) + femmesh.addFace([322, 334, 44], 415) + femmesh.addFace([255, 378, 158], 416) + femmesh.addFace([160, 379, 254], 417) + femmesh.addFace([158, 378, 247], 418) + femmesh.addFace([249, 379, 160], 419) + femmesh.addFace([204, 394, 333], 420) + femmesh.addFace([332, 393, 203], 421) + femmesh.addFace([235, 388, 74], 422) + femmesh.addFace([6, 287, 7], 423) + femmesh.addFace([68, 290, 67], 424) + femmesh.addFace([66, 289, 65], 425) + femmesh.addFace([8, 288, 9], 426) + femmesh.addFace([301, 439, 204], 427) + femmesh.addFace([140, 439, 301], 428) + femmesh.addFace([121, 415, 122], 429) + femmesh.addFace([70, 414, 71], 430) + femmesh.addFace([147, 438, 393], 431) + femmesh.addFace([74, 462, 235], 432) + femmesh.addFace([257, 441, 186], 433) + femmesh.addFace([187, 442, 258], 434) + femmesh.addFace([263, 414, 159], 435) + femmesh.addFace([157, 415, 264], 436) + femmesh.addFace([251, 435, 134], 437) + femmesh.addFace([180, 544, 265], 438) + femmesh.addFace([265, 544, 223], 439) + femmesh.addFace([179, 360, 242], 440) + femmesh.addFace([242, 360, 156], 441) + femmesh.addFace([150, 540, 480], 442) + femmesh.addFace([255, 362, 61], 443) + femmesh.addFace([13, 361, 254], 444) + femmesh.addFace([150, 480, 321], 445) + femmesh.addFace([159, 354, 263], 446) + femmesh.addFace([264, 355, 157], 447) + femmesh.addFace([309, 430, 196], 448) + femmesh.addFace([195, 429, 310], 449) + femmesh.addFace([248, 496, 122], 450) + femmesh.addFace([70, 497, 250], 451) + femmesh.addFace([249, 498, 11], 452) + femmesh.addFace([63, 499, 247], 453) + femmesh.addFace([280, 501, 183], 454) + femmesh.addFace([184, 502, 281], 455) + femmesh.addFace([263, 354, 182], 456) + femmesh.addFace([181, 355, 264], 457) + femmesh.addFace([303, 426, 192], 458) + femmesh.addFace([193, 427, 305], 459) + femmesh.addFace([153, 489, 238], 460) + femmesh.addFace([236, 490, 154], 461) + femmesh.addFace([237, 488, 151], 462) + femmesh.addFace([152, 491, 239], 463) + femmesh.addFace([49, 432, 241], 464) + femmesh.addFace([297, 540, 222], 465) + femmesh.addFace([56, 391, 282], 466) + femmesh.addFace([153, 371, 260], 467) + femmesh.addFace([259, 372, 154], 468) + femmesh.addFace([261, 370, 151], 469) + femmesh.addFace([152, 369, 262], 470) + femmesh.addFace([309, 534, 430], 471) + femmesh.addFace([429, 509, 310], 472) + femmesh.addFace([314, 326, 189], 473) + femmesh.addFace([194, 404, 317], 474) + femmesh.addFace([312, 315, 188], 475) + femmesh.addFace([131, 315, 312], 476) + femmesh.addFace([236, 384, 100], 477) + femmesh.addFace([84, 385, 238], 478) + femmesh.addFace([53, 387, 239], 479) + femmesh.addFace([237, 386, 91], 480) + femmesh.addFace([361, 468, 173], 481) + femmesh.addFace([174, 469, 362], 482) + femmesh.addFace([183, 501, 389], 483) + femmesh.addFace([390, 502, 184], 484) + femmesh.addFace([303, 515, 426], 485) + femmesh.addFace([186, 380, 241], 486) + femmesh.addFace([240, 381, 187], 487) + femmesh.addFace([427, 537, 305], 488) + femmesh.addFace([295, 332, 124], 489) + femmesh.addFace([173, 332, 295], 490) + femmesh.addFace([123, 333, 296], 491) + femmesh.addFace([296, 333, 174], 492) + femmesh.addFace([276, 443, 171], 493) + femmesh.addFace([211, 519, 286], 494) + femmesh.addFace([285, 517, 210], 495) + femmesh.addFace([209, 521, 284], 496) + femmesh.addFace([283, 523, 212], 497) + femmesh.addFace([273, 411, 169], 498) + femmesh.addFace([168, 410, 274], 499) + femmesh.addFace([165, 412, 275], 500) + femmesh.addFace([15, 413, 243], 501) + femmesh.addFace([270, 440, 143], 502) + femmesh.addFace([79, 420, 245], 503) + femmesh.addFace([246, 419, 96], 504) + femmesh.addFace([286, 519, 154], 505) + femmesh.addFace([153, 517, 285], 506) + femmesh.addFace([284, 521, 151], 507) + femmesh.addFace([152, 523, 283], 508) + femmesh.addFace([107, 381, 108], 509) + femmesh.addFace([49, 380, 48], 510) + femmesh.addFace([244, 394, 148], 511) + femmesh.addFace([243, 393, 173], 512) + femmesh.addFace([174, 394, 244], 513) + femmesh.addFace([308, 324, 130], 514) + femmesh.addFace([183, 324, 308], 515) + femmesh.addFace([127, 323, 307], 516) + femmesh.addFace([307, 323, 184], 517) + femmesh.addFace([151, 521, 261], 518) + femmesh.addFace([154, 519, 259], 519) + femmesh.addFace([260, 517, 153], 520) + femmesh.addFace([262, 523, 152], 521) + femmesh.addFace([242, 432, 50], 522) + femmesh.addFace([163, 352, 280], 523) + femmesh.addFace([281, 351, 161], 524) + femmesh.addFace([258, 470, 187], 525) + femmesh.addFace([311, 325, 133], 526) + femmesh.addFace([185, 325, 311], 527) + femmesh.addFace([306, 337, 172], 528) + femmesh.addFace([164, 353, 282], 529) + femmesh.addFace([318, 527, 40], 530) + femmesh.addFace([35, 528, 316], 531) + femmesh.addFace([254, 361, 173], 532) + femmesh.addFace([174, 362, 255], 533) + femmesh.addFace([183, 389, 245], 534) + femmesh.addFace([246, 390, 184], 535) + femmesh.addFace([26, 525, 319], 536) + femmesh.addFace([320, 526, 31], 537) + femmesh.addFace([40, 527, 39], 538) + femmesh.addFace([36, 528, 35], 539) + femmesh.addFace([245, 408, 183], 540) + femmesh.addFace([184, 409, 246], 541) + femmesh.addFace([243, 468, 15], 542) + femmesh.addFace([38, 374, 252], 543) + femmesh.addFace([252, 375, 37], 544) + femmesh.addFace([266, 436, 149], 545) + femmesh.addFace([27, 525, 26], 546) + femmesh.addFace([31, 526, 30], 547) + femmesh.addFace([294, 373, 162], 548) + femmesh.addFace([253, 437, 244], 549) + femmesh.addFace([120, 358, 264], 550) + femmesh.addFace([263, 359, 72], 551) + femmesh.addFace([256, 376, 28], 552) + femmesh.addFace([29, 377, 256], 553) + femmesh.addFace([213, 439, 326], 554) + femmesh.addFace([326, 439, 140], 555) + femmesh.addFace([253, 405, 185], 556) + femmesh.addFace([148, 405, 253], 557) + femmesh.addFace([331, 454, 198], 558) + femmesh.addFace([182, 462, 359], 559) + femmesh.addFace([358, 463, 181], 560) + femmesh.addFace([57, 391, 56], 561) + femmesh.addFace([168, 383, 317], 562) + femmesh.addFace([317, 383, 194], 563) + femmesh.addFace([5, 498, 465], 564) + femmesh.addFace([464, 497, 10], 565) + femmesh.addFace([466, 499, 64], 566) + femmesh.addFace([69, 496, 467], 567) + femmesh.addFace([198, 402, 331], 568) + femmesh.addFace([331, 402, 171], 569) + femmesh.addFace([381, 442, 187], 570) + femmesh.addFace([186, 441, 380], 571) + femmesh.addFace([149, 470, 258], 572) + femmesh.addFace([182, 359, 263], 573) + femmesh.addFace([264, 358, 181], 574) + femmesh.addFace([290, 424, 67], 575) + femmesh.addFace([8, 423, 288], 576) + femmesh.addFace([287, 423, 7], 577) + femmesh.addFace([66, 424, 289], 578) + femmesh.addFace([320, 336, 167], 579) + femmesh.addFace([166, 335, 319], 580) + femmesh.addFace([322, 400, 170], 581) + femmesh.addFace([197, 400, 322], 582) + femmesh.addFace([154, 490, 286], 583) + femmesh.addFace([285, 489, 153], 584) + femmesh.addFace([151, 488, 284], 585) + femmesh.addFace([283, 491, 152], 586) + femmesh.addFace([270, 503, 20], 587) + femmesh.addFace([265, 398, 180], 588) + femmesh.addFace([318, 392, 192], 589) + femmesh.addFace([165, 392, 318], 590) + femmesh.addFace([169, 411, 316], 591) + femmesh.addFace([318, 412, 165], 592) + femmesh.addFace([317, 410, 168], 593) + femmesh.addFace([167, 395, 320], 594) + femmesh.addFace([320, 395, 196], 595) + femmesh.addFace([319, 396, 166], 596) + femmesh.addFace([195, 396, 319], 597) + femmesh.addFace([194, 440, 270], 598) + femmesh.addFace([190, 423, 287], 599) + femmesh.addFace([288, 423, 190], 600) + femmesh.addFace([191, 424, 290], 601) + femmesh.addFace([289, 424, 191], 602) + femmesh.addFace([216, 494, 310], 603) + femmesh.addFace([310, 494, 128], 604) + femmesh.addFace([309, 495, 218], 605) + femmesh.addFace([126, 495, 309], 606) + femmesh.addFace([303, 506, 215], 607) + femmesh.addFace([125, 506, 303], 608) + femmesh.addFace([134, 507, 293], 609) + femmesh.addFace([269, 397, 178], 610) + femmesh.addFace([243, 510, 393], 611) + femmesh.addFace([189, 417, 306], 612) + femmesh.addFace([172, 382, 314], 613) + femmesh.addFace([190, 350, 300], 614) + femmesh.addFace([299, 349, 191], 615) + femmesh.addFace([171, 443, 331], 616) + femmesh.addFace([158, 349, 296], 617) + femmesh.addFace([295, 350, 160], 618) + femmesh.addFace([61, 362, 60], 619) + femmesh.addFace([14, 361, 13], 620) + femmesh.addFace([20, 404, 270], 621) + femmesh.addFace([193, 399, 316], 622) + femmesh.addFace([316, 399, 169], 623) + femmesh.addFace([393, 510, 147], 624) + femmesh.addFace([292, 425, 132], 625) + femmesh.addFace([294, 401, 103], 626) + femmesh.addFace([203, 487, 302], 627) + femmesh.addFace([302, 487, 139], 628) + femmesh.addFace([328, 348, 201], 629) + femmesh.addFace([327, 347, 199], 630) + femmesh.addFace([202, 346, 330], 631) + femmesh.addFace([357, 435, 251], 632) + femmesh.addFace([268, 433, 177], 633) + femmesh.addFace([176, 434, 267], 634) + femmesh.addFace([156, 360, 292], 635) + femmesh.addFace([267, 494, 216], 636) + femmesh.addFace([218, 495, 268], 637) + femmesh.addFace([225, 503, 270], 638) + femmesh.addFace([271, 428, 175], 639) + femmesh.addFace([155, 418, 291], 640) + femmesh.addFace([258, 478, 266], 641) + femmesh.addFace([266, 478, 105], 642) + femmesh.addFace([314, 476, 326], 643) + femmesh.addFace([300, 354, 159], 644) + femmesh.addFace([157, 355, 299], 645) + femmesh.addFace([180, 398, 272], 646) + femmesh.addFace([39, 374, 38], 647) + femmesh.addFace([37, 375, 36], 648) + femmesh.addFace([28, 376, 27], 649) + femmesh.addFace([30, 377, 29], 650) + femmesh.addFace([282, 391, 185], 651) + femmesh.addFace([272, 481, 219], 652) + femmesh.addFace([178, 397, 277], 653) + femmesh.addFace([283, 425, 179], 654) + femmesh.addFace([175, 428, 286], 655) + femmesh.addFace([250, 497, 464], 656) + femmesh.addFace([465, 498, 249], 657) + femmesh.addFace([247, 499, 466], 658) + femmesh.addFace([467, 496, 248], 659) + femmesh.addFace([177, 433, 284], 660) + femmesh.addFace([285, 434, 176], 661) + femmesh.addFace([270, 404, 194], 662) + femmesh.addFace([215, 506, 271], 663) + femmesh.addFace([117, 417, 298], 664) + femmesh.addFace([278, 507, 134], 665) + femmesh.addFace([219, 543, 269], 666) + femmesh.addFace([187, 507, 278], 667) + femmesh.addFace([273, 403, 206], 668) + femmesh.addFace([256, 430, 429], 669) + femmesh.addFace([429, 430, 144], 670) + femmesh.addFace([329, 382, 172], 671) + femmesh.addFace([288, 449, 159], 672) + femmesh.addFace([157, 448, 290], 673) + femmesh.addFace([279, 435, 186], 674) + femmesh.addFace([81, 501, 280], 675) + femmesh.addFace([281, 502, 94], 676) + femmesh.addFace([205, 407, 275], 677) + femmesh.addFace([276, 406, 208], 678) + femmesh.addFace([188, 436, 266], 679) + femmesh.addFace([277, 477, 214], 680) + femmesh.addFace([274, 410, 23], 681) + femmesh.addFace([34, 411, 273], 682) + femmesh.addFace([275, 412, 41], 683) + femmesh.addFace([207, 416, 274], 684) + femmesh.addFace([291, 536, 155], 685) + femmesh.addFace([179, 491, 283], 686) + femmesh.addFace([284, 488, 177], 687) + femmesh.addFace([176, 489, 285], 688) + femmesh.addFace([286, 490, 175], 689) + femmesh.addFace([426, 427, 252], 690) + femmesh.addFace([141, 427, 426], 691) + femmesh.addFace([59, 469, 437], 692) + femmesh.addFace([112, 443, 276], 693) + femmesh.addFace([106, 478, 442], 694) + femmesh.addFace([134, 435, 279], 695) + femmesh.addFace([170, 334, 322], 696) + femmesh.addFace([132, 425, 283], 697) + femmesh.addFace([5, 465, 6], 698) + femmesh.addFace([9, 464, 10], 699) + femmesh.addFace([65, 466, 64], 700) + femmesh.addFace([69, 467, 68], 701) + femmesh.addFace([286, 428, 125], 702) + femmesh.addFace([284, 433, 126], 703) + femmesh.addFace([128, 434, 285], 704) + femmesh.addFace([50, 432, 49], 705) + femmesh.addFace([46, 459, 45], 706) + femmesh.addFace([321, 459, 46], 707) + femmesh.addFace([100, 384, 101], 708) + femmesh.addFace([83, 385, 84], 709) + femmesh.addFace([91, 386, 92], 710) + femmesh.addFace([54, 387, 53], 711) + femmesh.addFace([293, 507, 187], 712) + femmesh.addFace([293, 470, 149], 713) + femmesh.addFace([322, 459, 197], 714) + femmesh.addFace([394, 486, 148], 715) + femmesh.addFace([292, 418, 221], 716) + femmesh.addFace([313, 454, 109], 717) + femmesh.addFace([289, 466, 65], 718) + femmesh.addFace([6, 465, 287], 719) + femmesh.addFace([288, 464, 9], 720) + femmesh.addFace([68, 467, 290], 721) + femmesh.addFace([155, 536, 313], 722) + femmesh.addFace([293, 431, 251], 723) + femmesh.addFace([149, 431, 293], 724) + femmesh.addFace([442, 478, 258], 725) + femmesh.addFace([437, 469, 244], 726) + femmesh.addFace([119, 358, 120], 727) + femmesh.addFace([72, 359, 73], 728) + femmesh.addFace([188, 401, 294], 729) + femmesh.addFace([103, 401, 104], 730) + femmesh.addFace([298, 529, 117], 731) + femmesh.addFace([20, 503, 19], 732) + femmesh.addFace([198, 536, 402], 733) + femmesh.addFace([402, 536, 291], 734) + femmesh.addFace([251, 540, 357], 735) + femmesh.addFace([357, 540, 150], 736) + femmesh.addFace([297, 400, 197], 737) + femmesh.addFace([314, 382, 133], 738) + femmesh.addFace([165, 344, 342], 739) + femmesh.addFace([340, 341, 167], 740) + femmesh.addFace([343, 345, 166], 741) + femmesh.addFace([210, 345, 343], 742) + femmesh.addFace([209, 341, 340], 743) + femmesh.addFace([342, 344, 211], 744) + femmesh.addFace([338, 339, 171], 745) + femmesh.addFace([212, 339, 338], 746) + femmesh.addFace([325, 476, 133], 747) + femmesh.addFace([213, 476, 325], 748) + femmesh.addFace([347, 482, 199], 749) + femmesh.addFace([87, 356, 88], 750) + femmesh.addFace([116, 417, 117], 751) + femmesh.addFace([305, 399, 193], 752) + femmesh.addFace([190, 449, 288], 753) + femmesh.addFace([290, 448, 191], 754) + femmesh.addFace([330, 346, 170], 755) + femmesh.addFace([168, 348, 328], 756) + femmesh.addFace([169, 347, 327], 757) + femmesh.addFace([192, 392, 303], 758) + femmesh.addFace([194, 383, 304], 759) + femmesh.addFace([16, 413, 15], 760) + femmesh.addFace([109, 454, 110], 761) + femmesh.addFace([133, 476, 314], 762) + femmesh.addFace([187, 470, 293], 763) + femmesh.addFace([182, 422, 302], 764) + femmesh.addFace([301, 421, 181], 765) + femmesh.addFace([96, 419, 97], 766) + femmesh.addFace([78, 420, 79], 767) + femmesh.addFace([298, 417, 189], 768) + femmesh.addFace([310, 396, 195], 769) + femmesh.addFace([196, 395, 309], 770) + femmesh.addFace([74, 388, 75], 771) + femmesh.addFace([98, 363, 99], 772) + femmesh.addFace([18, 366, 17], 773) + femmesh.addFace([76, 367, 77], 774) + femmesh.addFace([85, 364, 86], 775) + femmesh.addFace([52, 368, 51], 776) + femmesh.addFace([89, 365, 90], 777) + femmesh.addFace([189, 460, 298], 778) + femmesh.addFace([83, 542, 385], 779) + femmesh.addFace([386, 541, 92], 780) + femmesh.addFace([21, 404, 20], 781) + femmesh.addFace([234, 529, 298], 782) + femmesh.addFace([54, 546, 387], 783) + femmesh.addFace([197, 480, 297], 784) + femmesh.addFace([348, 531, 201], 785) + femmesh.addFace([202, 532, 346], 786) + femmesh.addFace([118, 463, 119], 787) + femmesh.addFace([73, 462, 74], 788) + femmesh.addFace([191, 448, 299], 789) + femmesh.addFace([300, 449, 190], 790) + femmesh.addFace([159, 449, 300], 791) + femmesh.addFace([299, 448, 157], 792) + femmesh.addFace([321, 480, 197], 793) + femmesh.addFace([328, 383, 168], 794) + femmesh.addFace([475, 533, 262], 795) + femmesh.addFace([259, 532, 474], 796) + femmesh.addFace([473, 531, 260], 797) + femmesh.addFace([261, 530, 472], 798) + femmesh.addFace([313, 536, 198], 799) + femmesh.addFace([117, 529, 118], 800) + femmesh.addFace([22, 410, 317], 801) + femmesh.addFace([316, 411, 35], 802) + femmesh.addFace([40, 412, 318], 803) + femmesh.addFace([170, 400, 330], 804) + femmesh.addFace([360, 425, 292], 805) + femmesh.addFace([118, 529, 463], 806) + femmesh.addFace([356, 504, 224], 807) + femmesh.addFace([87, 504, 356], 808) + femmesh.addFace([226, 505, 356], 809) + femmesh.addFace([356, 505, 88], 810) + femmesh.addFace([202, 485, 474], 811) + femmesh.addFace([475, 484, 200], 812) + femmesh.addFace([473, 483, 201], 813) + femmesh.addFace([199, 482, 472], 814) + femmesh.addFace([315, 436, 188], 815) + femmesh.addFace([122, 496, 4], 816) + femmesh.addFace([11, 498, 1], 817) + femmesh.addFace([2, 497, 70], 818) + femmesh.addFace([3, 499, 63], 819) + femmesh.addFace([137, 403, 327], 820) + femmesh.addFace([76, 453, 367], 821) + femmesh.addFace([409, 492, 246], 822) + femmesh.addFace([145, 492, 409], 823) + femmesh.addFace([408, 493, 146], 824) + femmesh.addFace([245, 493, 408], 825) + femmesh.addFace([200, 382, 329], 826) + femmesh.addFace([23, 410, 22], 827) + femmesh.addFace([35, 411, 34], 828) + femmesh.addFace([41, 412, 40], 829) + femmesh.addFace([204, 514, 301], 830) + femmesh.addFace([302, 513, 203], 831) + femmesh.addFace([304, 440, 194], 832) + femmesh.addFace([89, 505, 365], 833) + femmesh.addFace([364, 504, 86], 834) + femmesh.addFace([367, 512, 77], 835) + femmesh.addFace([98, 511, 363], 836) + femmesh.addFace([366, 524, 17], 837) + femmesh.addFace([18, 508, 366], 838) + femmesh.addFace([111, 443, 112], 839) + femmesh.addFace([4, 496, 69], 840) + femmesh.addFace([1, 498, 5], 841) + femmesh.addFace([10, 497, 2], 842) + femmesh.addFace([64, 499, 3], 843) + femmesh.addFace([183, 408, 324], 844) + femmesh.addFace([323, 409, 184], 845) + femmesh.addFace([39, 527, 374], 846) + femmesh.addFace([375, 528, 36], 847) + femmesh.addFace([109, 471, 313], 848) + femmesh.addFace([305, 537, 220], 849) + femmesh.addFace([200, 533, 475], 850) + femmesh.addFace([474, 532, 202], 851) + femmesh.addFace([201, 531, 473], 852) + femmesh.addFace([472, 530, 199], 853) + femmesh.addFace([215, 515, 303], 854) + femmesh.addFace([185, 405, 325], 855) + femmesh.addFace([173, 393, 332], 856) + femmesh.addFace([333, 394, 174], 857) + femmesh.addFace([385, 542, 231], 858) + femmesh.addFace([232, 541, 386], 859) + femmesh.addFace([218, 534, 309], 860) + femmesh.addFace([376, 525, 27], 861) + femmesh.addFace([30, 526, 377], 862) + femmesh.addFace([307, 482, 127], 863) + femmesh.addFace([130, 483, 308], 864) + femmesh.addFace([310, 509, 216], 865) + femmesh.addFace([198, 454, 313], 866) + femmesh.addFace([133, 484, 311], 867) + femmesh.addFace([105, 478, 106], 868) + femmesh.addFace([312, 485, 131], 869) + femmesh.addFace([387, 546, 233], 870) + femmesh.addFace([127, 482, 347], 871) + femmesh.addFace([313, 471, 240], 872) + femmesh.addFace([60, 469, 59], 873) + femmesh.addFace([15, 468, 14], 874) + femmesh.addFace([342, 392, 165], 875) + femmesh.addFace([341, 395, 167], 876) + femmesh.addFace([166, 396, 343], 877) + femmesh.addFace([192, 527, 318], 878) + femmesh.addFace([316, 528, 193], 879) + femmesh.addFace([7, 423, 8], 880) + femmesh.addFace([67, 424, 66], 881) + femmesh.addFace([196, 526, 320], 882) + femmesh.addFace([319, 525, 195], 883) + femmesh.addFace([333, 514, 204], 884) + femmesh.addFace([332, 513, 124], 885) + femmesh.addFace([203, 513, 332], 886) + femmesh.addFace([123, 514, 333], 887) + femmesh.addFace([437, 461, 58], 888) + femmesh.addFace([328, 483, 130], 889) + femmesh.addFace([201, 483, 328], 890) + femmesh.addFace([330, 485, 202], 891) + femmesh.addFace([131, 485, 330], 892) + femmesh.addFace([59, 437, 58], 893) + femmesh.addFace([253, 461, 437], 894) + femmesh.addFace([331, 443, 111], 895) + femmesh.addFace([169, 399, 347], 896) + femmesh.addFace([171, 402, 338], 897) + femmesh.addFace([106, 442, 107], 898) + femmesh.addFace([48, 441, 47], 899) + femmesh.addFace([181, 421, 355], 900) + femmesh.addFace([354, 422, 182], 901) + femmesh.addFace([179, 425, 360], 902) + femmesh.addFace([138, 406, 339], 903) + femmesh.addFace([344, 407, 136], 904) + femmesh.addFace([348, 416, 135], 905) + femmesh.addFace([453, 544, 367], 906) + femmesh.addFace([55, 546, 54], 907) + femmesh.addFace([92, 541, 93], 908) + femmesh.addFace([82, 542, 83], 909) + femmesh.addFace([326, 460, 189], 910) + femmesh.addFace([223, 453, 388], 911) + femmesh.addFace([388, 453, 75], 912) + femmesh.addFace([108, 471, 109], 913) + femmesh.addFace([94, 502, 95], 914) + femmesh.addFace([80, 501, 81], 915) + femmesh.addFace([340, 516, 209], 916) + femmesh.addFace([137, 516, 340], 917) + femmesh.addFace([136, 518, 344], 918) + femmesh.addFace([210, 520, 345], 919) + femmesh.addFace([344, 518, 211], 920) + femmesh.addFace([345, 520, 135], 921) + femmesh.addFace([212, 522, 339], 922) + femmesh.addFace([339, 522, 138], 923) + femmesh.addFace([186, 435, 357], 924) + femmesh.addFace([356, 479, 226], 925) + femmesh.addFace([75, 453, 76], 926) + femmesh.addFace([113, 458, 114], 927) + femmesh.addFace([33, 456, 32], 928) + femmesh.addFace([43, 455, 42], 929) + femmesh.addFace([25, 457, 24], 930) + femmesh.addFace([135, 531, 348], 931) + femmesh.addFace([346, 532, 136], 932) + femmesh.addFace([58, 461, 57], 933) + femmesh.addFace([197, 459, 321], 934) + femmesh.addFace([426, 515, 141], 935) + femmesh.addFace([327, 530, 137], 936) + femmesh.addFace([199, 530, 327], 937) + femmesh.addFace([138, 533, 329], 938) + femmesh.addFace([329, 533, 200], 939) + femmesh.addFace([337, 535, 172], 940) + femmesh.addFace([208, 535, 337], 941) + femmesh.addFace([369, 475, 262], 942) + femmesh.addFace([259, 474, 372], 943) + femmesh.addFace([371, 473, 260], 944) + femmesh.addFace([261, 472, 370], 945) + femmesh.addFace([47, 500, 46], 946) + femmesh.addFace([19, 508, 18], 947) + femmesh.addFace([86, 504, 87], 948) + femmesh.addFace([88, 505, 89], 949) + femmesh.addFace([97, 511, 98], 950) + femmesh.addFace([77, 512, 78], 951) + femmesh.addFace([144, 509, 429], 952) + femmesh.addFace([17, 524, 16], 953) + femmesh.addFace([46, 500, 321], 954) + femmesh.addFace([321, 500, 257], 955) + femmesh.addFace([375, 427, 193], 956) + femmesh.addFace([252, 427, 375], 957) + femmesh.addFace([192, 426, 374], 958) + femmesh.addFace([374, 426, 252], 959) + femmesh.addFace([325, 538, 213], 960) + femmesh.addFace([196, 430, 377], 961) + femmesh.addFace([377, 430, 256], 962) + femmesh.addFace([256, 429, 376], 963) + femmesh.addFace([376, 429, 195], 964) + femmesh.addFace([140, 460, 326], 965) + femmesh.addFace([463, 529, 234], 966) + femmesh.addFace([326, 476, 213], 967) + femmesh.addFace([257, 500, 441], 968) + femmesh.addFace([441, 500, 47], 969) + femmesh.addFace([114, 458, 337], 970) + femmesh.addFace([335, 457, 25], 971) + femmesh.addFace([207, 457, 335], 972) + femmesh.addFace([334, 455, 43], 973) + femmesh.addFace([336, 456, 206], 974) + femmesh.addFace([205, 455, 334], 975) + femmesh.addFace([32, 456, 336], 976) + femmesh.addFace([337, 458, 208], 977) + femmesh.addFace([431, 540, 251], 978) + femmesh.addFace([222, 540, 431], 979) + femmesh.addFace([141, 537, 427], 980) + femmesh.addFace([430, 534, 144], 981) + femmesh.addFace([93, 541, 351], 982) + femmesh.addFace([352, 542, 82], 983) + femmesh.addFace([265, 539, 398], 984) + femmesh.addFace([353, 546, 55], 985) + femmesh.addFace([269, 543, 397], 986) + femmesh.addFace([382, 484, 133], 987) + femmesh.addFace([172, 535, 329], 988) + femmesh.addFace([539, 545, 214], 989) + femmesh.addFace([214, 487, 438], 990) + femmesh.addFace([213, 486, 439], 991) + femmesh.addFace([413, 524, 229], 992) + femmesh.addFace([16, 524, 413], 993) + femmesh.addFace([107, 442, 381], 994) + femmesh.addFace([380, 441, 48], 995) + femmesh.addFace([200, 484, 382], 996) + femmesh.addFace([419, 511, 97], 997) + femmesh.addFace([227, 511, 419], 998) + femmesh.addFace([78, 512, 420], 999) + femmesh.addFace([420, 512, 228], 1000) + femmesh.addFace([193, 528, 375], 1001) + femmesh.addFace([374, 527, 192], 1002) + femmesh.addFace([213, 538, 486], 1003) + femmesh.addFace([377, 526, 196], 1004) + femmesh.addFace([195, 525, 376], 1005) + femmesh.addFace([224, 479, 356], 1006) + femmesh.addFace([214, 545, 487], 1007) + femmesh.addFace([265, 545, 539], 1008) + femmesh.addFace([351, 541, 232], 1009) + femmesh.addFace([231, 542, 352], 1010) + femmesh.addFace([119, 463, 358], 1011) + femmesh.addFace([359, 462, 73], 1012) + femmesh.addFace([233, 546, 353], 1013) + femmesh.addFace([235, 444, 388], 1014) + femmesh.addFace([388, 444, 223], 1015) + femmesh.addFace([14, 468, 361], 1016) + femmesh.addFace([362, 469, 60], 1017) + femmesh.addFace([389, 501, 80], 1018) + femmesh.addFace([95, 502, 390], 1019) + femmesh.addFace([57, 461, 391], 1020) + femmesh.addFace([398, 481, 272], 1021) + femmesh.addFace([129, 481, 398], 1022) + femmesh.addFace([370, 472, 161], 1023) + femmesh.addFace([163, 473, 371], 1024) + femmesh.addFace([164, 475, 369], 1025) + femmesh.addFace([372, 474, 162], 1026) + femmesh.addFace([129, 477, 397], 1027) + femmesh.addFace([397, 477, 277], 1028) + femmesh.addFace([398, 539, 129], 1029) + femmesh.addFace([397, 543, 129], 1030) + femmesh.addFace([367, 544, 180], 1031) + femmesh.addFace([405, 538, 325], 1032) + femmesh.addFace([413, 510, 243], 1033) + femmesh.addFace([262, 533, 522], 1034) + femmesh.addFace([260, 531, 520], 1035) + femmesh.addFace([137, 530, 516], 1036) + femmesh.addFace([522, 533, 138], 1037) + femmesh.addFace([516, 530, 261], 1038) + femmesh.addFace([520, 531, 135], 1039) + femmesh.addFace([518, 532, 259], 1040) + femmesh.addFace([136, 532, 518], 1041) + femmesh.addFace([301, 514, 421], 1042) + femmesh.addFace([422, 513, 302], 1043) + femmesh.addFace([420, 493, 245], 1044) + femmesh.addFace([228, 493, 420], 1045) + femmesh.addFace([419, 492, 227], 1046) + femmesh.addFace([246, 492, 419], 1047) + femmesh.addFace([447, 451, 217], 1048) + femmesh.addFace([216, 450, 446], 1049) + femmesh.addFace([445, 452, 215], 1050) + femmesh.addFace([229, 510, 413], 1051) + femmesh.addFace([271, 506, 428], 1052) + femmesh.addFace([148, 538, 405], 1053) + femmesh.addFace([124, 513, 422], 1054) + femmesh.addFace([421, 514, 123], 1055) + femmesh.addFace([268, 495, 433], 1056) + femmesh.addFace([433, 495, 126], 1057) + femmesh.addFace([128, 494, 434], 1058) + femmesh.addFace([434, 494, 267], 1059) + femmesh.addFace([428, 506, 125], 1060) + femmesh.addFace([477, 539, 214], 1061) + femmesh.addFace([446, 450, 218], 1062) + femmesh.addFace([220, 452, 445], 1063) + femmesh.addFace([219, 451, 447], 1064) + femmesh.addFace([439, 486, 204], 1065) + femmesh.addFace([438, 487, 203], 1066) + femmesh.addFace([216, 509, 450], 1067) + femmesh.addFace([481, 543, 219], 1068) + femmesh.addFace([452, 515, 215], 1069) + femmesh.addFace([450, 534, 218], 1070) + femmesh.addFace([220, 537, 452], 1071) + femmesh.addFace([223, 544, 453], 1072) + femmesh.addFace([450, 509, 144], 1073) + femmesh.addFace([486, 538, 148], 1074) + femmesh.addFace([141, 515, 452], 1075) + femmesh.addFace([503, 508, 19], 1076) + femmesh.addFace([522, 523, 262], 1077) + femmesh.addFace([212, 523, 522], 1078) + femmesh.addFace([261, 521, 516], 1079) + femmesh.addFace([260, 520, 517], 1080) + femmesh.addFace([516, 521, 209], 1081) + femmesh.addFace([518, 519, 211], 1082) + femmesh.addFace([517, 520, 210], 1083) + femmesh.addFace([259, 519, 518], 1084) + femmesh.addFace([225, 508, 503], 1085) + femmesh.addFace([144, 534, 450], 1086) + femmesh.addFace([487, 545, 139], 1087) + femmesh.addFace([452, 537, 141], 1088) + femmesh.addFace([129, 539, 477], 1089) + femmesh.addFace([129, 543, 481], 1090) + return True diff --git a/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria6.py b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria6.py new file mode 100644 index 0000000000..71d98d5237 --- /dev/null +++ b/src/Mod/Fem/femexamples/meshes/mesh_canticcx_tria6.py @@ -0,0 +1,255 @@ +def create_nodes(femmesh): + # nodes + femmesh.addNode(0.0, 500.0, 0.0, 1) + femmesh.addNode(0.0, 500.00000000000324, 1000.0, 2) + femmesh.addNode(8000.0, 500.0, 0.0, 3) + femmesh.addNode(8000.0, 500.00000000000324, 1000.0, 4) + femmesh.addNode(0.0, 500.0000000000001, 500.0, 5) + femmesh.addNode(0.0, 500.00000000000006, 250.0, 6) + femmesh.addNode(0.0, 500.00000000000017, 750.0, 7) + femmesh.addNode(500.0, 500.0, 0.0, 8) + femmesh.addNode(1000.0, 500.0, 0.0, 9) + femmesh.addNode(1500.0, 500.0, 0.0, 10) + femmesh.addNode(2000.0, 500.0, 0.0, 11) + femmesh.addNode(2500.0, 500.0, 0.0, 12) + femmesh.addNode(3000.0, 500.0, 0.0, 13) + femmesh.addNode(3500.0, 500.0, 0.0, 14) + femmesh.addNode(4000.0, 500.0, 0.0, 15) + femmesh.addNode(4500.0, 500.0, 0.0, 16) + femmesh.addNode(5000.0, 500.0, 0.0, 17) + femmesh.addNode(5500.0, 500.0, 0.0, 18) + femmesh.addNode(6000.0, 500.0, 0.0, 19) + femmesh.addNode(6500.0, 500.0, 0.0, 20) + femmesh.addNode(7000.0, 500.0, 0.0, 21) + femmesh.addNode(7500.0, 500.0, 0.0, 22) + femmesh.addNode(250.0, 500.0, 0.0, 23) + femmesh.addNode(750.0, 500.0, 0.0, 24) + femmesh.addNode(1250.0, 500.0, 0.0, 25) + femmesh.addNode(1750.0, 500.0, 0.0, 26) + femmesh.addNode(2250.0, 500.0, 0.0, 27) + femmesh.addNode(2750.0, 500.0, 0.0, 28) + femmesh.addNode(3250.0, 500.0, 0.0, 29) + femmesh.addNode(3750.0, 500.0, 0.0, 30) + femmesh.addNode(4250.0, 500.0, 0.0, 31) + femmesh.addNode(4750.0, 500.0, 0.0, 32) + femmesh.addNode(5250.0, 500.0, 0.0, 33) + femmesh.addNode(5750.0, 500.0, 0.0, 34) + femmesh.addNode(6250.0, 500.0, 0.0, 35) + femmesh.addNode(6750.0, 500.0, 0.0, 36) + femmesh.addNode(7250.0, 500.0, 0.0, 37) + femmesh.addNode(7750.0, 500.0, 0.0, 38) + femmesh.addNode(8000.0, 500.0000000000001, 500.0, 39) + femmesh.addNode(8000.0, 500.00000000000006, 250.0, 40) + femmesh.addNode(8000.0, 500.00000000000017, 750.0, 41) + femmesh.addNode(500.0, 500.0000000000002, 1000.0, 42) + femmesh.addNode(1000.0, 500.0000000000002, 1000.0, 43) + femmesh.addNode(1500.0, 500.0000000000002, 1000.0, 44) + femmesh.addNode(2000.0, 500.0000000000002, 1000.0, 45) + femmesh.addNode(2500.0, 500.0000000000002, 1000.0, 46) + femmesh.addNode(3000.0, 500.0000000000002, 1000.0, 47) + femmesh.addNode(3500.0, 500.0000000000002, 1000.0, 48) + femmesh.addNode(4000.0, 500.0000000000002, 1000.0, 49) + femmesh.addNode(4500.0, 500.0000000000002, 1000.0, 50) + femmesh.addNode(5000.0, 500.0000000000002, 1000.0, 51) + femmesh.addNode(5500.0, 500.0000000000002, 1000.0, 52) + femmesh.addNode(6000.0, 500.0000000000002, 1000.0, 53) + femmesh.addNode(6500.0, 500.0000000000002, 1000.0, 54) + femmesh.addNode(7000.0, 500.0000000000002, 1000.0, 55) + femmesh.addNode(7500.0, 500.0000000000002, 1000.0, 56) + femmesh.addNode(250.0, 500.0000000000002, 1000.0, 57) + femmesh.addNode(750.0, 500.0000000000002, 1000.0, 58) + femmesh.addNode(1250.0, 500.0000000000002, 1000.0, 59) + femmesh.addNode(1750.0, 500.0000000000002, 1000.0, 60) + femmesh.addNode(2250.0, 500.0000000000002, 1000.0, 61) + femmesh.addNode(2750.0, 500.0000000000002, 1000.0, 62) + femmesh.addNode(3250.0, 500.0000000000002, 1000.0, 63) + femmesh.addNode(3750.0, 500.0000000000002, 1000.0, 64) + femmesh.addNode(4250.0, 500.0000000000002, 1000.0, 65) + femmesh.addNode(4750.0, 500.0000000000002, 1000.0, 66) + femmesh.addNode(5250.0, 500.0000000000002, 1000.0, 67) + femmesh.addNode(5750.0, 500.0000000000002, 1000.0, 68) + femmesh.addNode(6250.0, 500.0000000000002, 1000.0, 69) + femmesh.addNode(6750.0, 500.0000000000002, 1000.0, 70) + femmesh.addNode(7250.0, 500.0000000000002, 1000.0, 71) + femmesh.addNode(7750.0, 500.0000000000002, 1000.0, 72) + femmesh.addNode(714.9234693877551, 500.0000000000001, 484.05612244897964, 73) + femmesh.addNode(1750.0, 500.0000000000001, 500.0, 74) + femmesh.addNode(2750.0, 500.0000000000001, 500.0, 75) + femmesh.addNode(3750.0, 500.0000000000001, 500.0, 76) + femmesh.addNode(4750.0, 500.0000000000001, 500.0, 77) + femmesh.addNode(5750.0, 500.0000000000001, 500.0, 78) + femmesh.addNode(6756.944444444443, 500.0000000000001, 489.5833333333333, 79) + femmesh.addNode(7301.463293650793, 500.0000000000001, 489.7073412698406, 80) + femmesh.addNode(1244.1539115646258, 500.0000000000001, 497.34268707482994, 81) + femmesh.addNode(2250.0, 500.0000000000001, 500.0, 82) + femmesh.addNode(3250.0, 500.0000000000001, 500.0, 83) + femmesh.addNode(4250.0, 500.0000000000001, 500.0, 84) + femmesh.addNode(5250.0, 500.0000000000001, 500.0, 85) + femmesh.addNode(6251.157407407407, 500.0000000000001, 498.2638888888889, 86) + femmesh.addNode(355.2776691684587, 500.0000000000001, 632.304566974645, 87) + femmesh.addNode(7660.398197179746, 500.00000000000017, 648.5965255878823, 88) + femmesh.addNode(7699.764777975907, 500.00000000000006, 310.456176890242, 89) + femmesh.addNode(314.0402277112428, 500.00000000000006, 323.27213788472494, 90) + femmesh.addNode(1122.0769557823128, 500.00000000000017, 748.6713435374149, 91) + femmesh.addNode(1372.0769557823128, 500.00000000000017, 748.6713435374149, 92) + femmesh.addNode(2125.0, 500.00000000000017, 750.0, 93) + femmesh.addNode(2375.0, 500.00000000000017, 750.0, 94) + femmesh.addNode(3125.0, 500.00000000000017, 750.0, 95) + femmesh.addNode(3375.0, 500.00000000000017, 750.0, 96) + femmesh.addNode(4125.0, 500.00000000000017, 750.0, 97) + femmesh.addNode(4375.0, 500.00000000000017, 750.0, 98) + femmesh.addNode(5125.0, 500.00000000000017, 750.0, 99) + femmesh.addNode(5375.0, 500.00000000000017, 750.0, 100) + femmesh.addNode(6125.5787037037035, 500.00000000000017, 749.1319444444445, 101) + femmesh.addNode(6375.5787037037035, 500.00000000000017, 749.1319444444445, 102) + femmesh.addNode(857.4617346938776, 500.00000000000017, 742.0280612244899, 103) + femmesh.addNode(979.5386904761904, 500.0000000000001, 490.6994047619048, 104) + femmesh.addNode(1497.0769557823128, 500.0000000000001, 498.67134353741494, 105) + femmesh.addNode(1625.0, 500.00000000000017, 750.0, 106) + femmesh.addNode(1875.0, 500.00000000000017, 750.0, 107) + femmesh.addNode(2000.0, 500.0000000000001, 500.0, 108) + femmesh.addNode(2500.0, 500.0000000000001, 500.0, 109) + femmesh.addNode(2625.0, 500.00000000000017, 750.0, 110) + femmesh.addNode(2875.0, 500.00000000000017, 750.0, 111) + femmesh.addNode(3000.0, 500.0000000000001, 500.0, 112) + femmesh.addNode(3500.0, 500.0000000000001, 500.0, 113) + femmesh.addNode(3625.0, 500.00000000000017, 750.0, 114) + femmesh.addNode(3875.0, 500.00000000000017, 750.0, 115) + femmesh.addNode(4000.0, 500.0000000000001, 500.0, 116) + femmesh.addNode(4500.0, 500.0000000000001, 500.0, 117) + femmesh.addNode(4625.0, 500.00000000000017, 750.0, 118) + femmesh.addNode(4875.0, 500.00000000000017, 750.0, 119) + femmesh.addNode(5000.0, 500.0000000000001, 500.0, 120) + femmesh.addNode(5500.0, 500.0000000000001, 500.0, 121) + femmesh.addNode(5625.0, 500.00000000000017, 750.0, 122) + femmesh.addNode(5875.0, 500.00000000000017, 750.0, 123) + femmesh.addNode(6000.5787037037035, 500.0000000000001, 499.13194444444446, 124) + femmesh.addNode(6504.050925925925, 500.0000000000001, 493.9236111111111, 125) + femmesh.addNode(6628.472222222222, 500.00000000000017, 744.7916666666666, 126) + femmesh.addNode(7150.731646825397, 500.00000000000006, 244.8536706349203, 127) + femmesh.addNode(7029.203869047618, 500.0000000000001, 489.64533730158695, 128) + femmesh.addNode(6878.472222222222, 500.00000000000006, 244.79166666666666, 129) + femmesh.addNode(6878.472222222222, 500.00000000000017, 744.7916666666666, 130) + femmesh.addNode(7150.731646825397, 500.00000000000017, 744.8536706349203, 131) + femmesh.addNode(7400.731646825397, 500.00000000000006, 244.8536706349203, 132) + femmesh.addNode(7400.731646825397, 500.00000000000017, 744.8536706349203, 133) + femmesh.addNode(857.4617346938776, 500.00000000000006, 242.02806122448982, 134) + femmesh.addNode(607.4617346938776, 500.00000000000006, 242.02806122448982, 135) + femmesh.addNode(1875.0, 500.00000000000006, 250.0, 136) + femmesh.addNode(1625.0, 500.00000000000006, 250.0, 137) + femmesh.addNode(2875.0, 500.00000000000006, 250.0, 138) + femmesh.addNode(2625.0, 500.00000000000006, 250.0, 139) + femmesh.addNode(3875.0, 500.00000000000006, 250.0, 140) + femmesh.addNode(3625.0, 500.00000000000006, 250.0, 141) + femmesh.addNode(4875.0, 500.00000000000006, 250.0, 142) + femmesh.addNode(4625.0, 500.00000000000006, 250.0, 143) + femmesh.addNode(5875.0, 500.00000000000006, 250.0, 144) + femmesh.addNode(5625.0, 500.00000000000006, 250.0, 145) + femmesh.addNode(6628.472222222222, 500.00000000000006, 244.79166666666666, 146) + femmesh.addNode(607.4617346938776, 500.00000000000017, 742.0280612244899, 147) + femmesh.addNode(1122.0769557823128, 500.00000000000006, 248.67134353741497, 148) + femmesh.addNode(1372.0769557823128, 500.00000000000006, 248.67134353741497, 149) + femmesh.addNode(2125.0, 500.00000000000006, 250.0, 150) + femmesh.addNode(2375.0, 500.00000000000006, 250.0, 151) + femmesh.addNode(3125.0, 500.00000000000006, 250.0, 152) + femmesh.addNode(3375.0, 500.00000000000006, 250.0, 153) + femmesh.addNode(4125.0, 500.00000000000006, 250.0, 154) + femmesh.addNode(4375.0, 500.00000000000006, 250.0, 155) + femmesh.addNode(5125.0, 500.00000000000006, 250.0, 156) + femmesh.addNode(5375.0, 500.00000000000006, 250.0, 157) + femmesh.addNode(6125.5787037037035, 500.00000000000006, 249.13194444444446, 158) + femmesh.addNode(6375.5787037037035, 500.00000000000006, 249.13194444444446, 159) + femmesh.addNode(514.4818485494989, 500.0000000000001, 403.66413016685226, 160) + femmesh.addNode(407.0201138556214, 500.00000000000006, 161.63606894236247, 161) + femmesh.addNode(177.63883458422936, 500.0000000000001, 566.1522834873225, 162) + femmesh.addNode(177.63883458422936, 500.00000000000017, 816.1522834873225, 163) + femmesh.addNode(427.63883458422936, 500.00000000000017, 816.1522834873225, 164) + femmesh.addNode(535.1005692781068, 500.0000000000001, 558.1803447118123, 165) + femmesh.addNode(7599.882388987953, 500.00000000000006, 155.228088445121, 166) + femmesh.addNode(7500.614035813351, 500.0000000000001, 400.08175908004125, 167) + femmesh.addNode(7830.199098589873, 500.00000000000017, 824.2982627939411, 168) + femmesh.addNode(7830.199098589873, 500.0000000000001, 574.2982627939411, 169) + femmesh.addNode(7580.199098589873, 500.00000000000017, 824.2982627939411, 170) + femmesh.addNode(7480.9307454152695, 500.0000000000001, 569.1519334288614, 171) + femmesh.addNode(334.65894843985075, 500.0000000000001, 477.788352429685, 172) + femmesh.addNode(7849.882388987953, 500.0000000000001, 405.228088445121, 173) + femmesh.addNode(7849.882388987953, 500.00000000000006, 155.228088445121, 174) + femmesh.addNode(157.0201138556214, 500.00000000000006, 161.63606894236247, 175) + femmesh.addNode(157.0201138556214, 500.0000000000001, 411.6360689423625, 176) + femmesh.addNode(7680.081487577827, 500.0000000000001, 479.52635123906214, 177) + return True + + +def create_elements(femmesh): + # elements + femmesh.addFace([43, 81, 44, 91, 92, 59], 37) + femmesh.addFace([45, 82, 46, 93, 94, 61], 38) + femmesh.addFace([47, 83, 48, 95, 96, 63], 39) + femmesh.addFace([49, 84, 50, 97, 98, 65], 40) + femmesh.addFace([51, 85, 52, 99, 100, 67], 41) + femmesh.addFace([53, 86, 54, 101, 102, 69], 42) + femmesh.addFace([43, 73, 81, 103, 104, 91], 43) + femmesh.addFace([44, 81, 74, 92, 105, 106], 44) + femmesh.addFace([45, 74, 82, 107, 108, 93], 45) + femmesh.addFace([46, 82, 75, 94, 109, 110], 46) + femmesh.addFace([47, 75, 83, 111, 112, 95], 47) + femmesh.addFace([48, 83, 76, 96, 113, 114], 48) + femmesh.addFace([49, 76, 84, 115, 116, 97], 49) + femmesh.addFace([50, 84, 77, 98, 117, 118], 50) + femmesh.addFace([51, 77, 85, 119, 120, 99], 51) + femmesh.addFace([52, 85, 78, 100, 121, 122], 52) + femmesh.addFace([53, 78, 86, 123, 124, 101], 53) + femmesh.addFace([54, 86, 79, 102, 125, 126], 54) + femmesh.addFace([21, 80, 79, 127, 128, 129], 55) + femmesh.addFace([55, 79, 80, 130, 128, 131], 56) + femmesh.addFace([21, 22, 80, 37, 132, 127], 57) + femmesh.addFace([55, 80, 56, 131, 133, 71], 58) + femmesh.addFace([8, 9, 73, 24, 134, 135], 59) + femmesh.addFace([10, 11, 74, 26, 136, 137], 60) + femmesh.addFace([12, 13, 75, 28, 138, 139], 61) + femmesh.addFace([14, 15, 76, 30, 140, 141], 62) + femmesh.addFace([16, 17, 77, 32, 142, 143], 63) + femmesh.addFace([18, 19, 78, 34, 144, 145], 64) + femmesh.addFace([20, 21, 79, 36, 129, 146], 65) + femmesh.addFace([42, 73, 43, 147, 103, 58], 66) + femmesh.addFace([44, 74, 45, 106, 107, 60], 67) + femmesh.addFace([46, 75, 47, 110, 111, 62], 68) + femmesh.addFace([48, 76, 49, 114, 115, 64], 69) + femmesh.addFace([50, 77, 51, 118, 119, 66], 70) + femmesh.addFace([52, 78, 53, 122, 123, 68], 71) + femmesh.addFace([54, 79, 55, 126, 130, 70], 72) + femmesh.addFace([9, 81, 73, 148, 104, 134], 73) + femmesh.addFace([10, 74, 81, 137, 105, 149], 74) + femmesh.addFace([11, 82, 74, 150, 108, 136], 75) + femmesh.addFace([12, 75, 82, 139, 109, 151], 76) + femmesh.addFace([13, 83, 75, 152, 112, 138], 77) + femmesh.addFace([14, 76, 83, 141, 113, 153], 78) + femmesh.addFace([15, 84, 76, 154, 116, 140], 79) + femmesh.addFace([16, 77, 84, 143, 117, 155], 80) + femmesh.addFace([17, 85, 77, 156, 120, 142], 81) + femmesh.addFace([18, 78, 85, 145, 121, 157], 82) + femmesh.addFace([19, 86, 78, 158, 124, 144], 83) + femmesh.addFace([20, 79, 86, 146, 125, 159], 84) + femmesh.addFace([9, 10, 81, 25, 149, 148], 85) + femmesh.addFace([11, 12, 82, 27, 151, 150], 86) + femmesh.addFace([13, 14, 83, 29, 153, 152], 87) + femmesh.addFace([15, 16, 84, 31, 155, 154], 88) + femmesh.addFace([17, 18, 85, 33, 157, 156], 89) + femmesh.addFace([19, 20, 86, 35, 159, 158], 90) + femmesh.addFace([8, 73, 90, 135, 160, 161], 91) + femmesh.addFace([2, 5, 87, 7, 162, 163], 92) + femmesh.addFace([2, 87, 42, 163, 164, 57], 93) + femmesh.addFace([42, 87, 73, 164, 165, 147], 94) + femmesh.addFace([22, 89, 80, 166, 167, 132], 95) + femmesh.addFace([4, 88, 39, 168, 169, 41], 96) + femmesh.addFace([4, 56, 88, 72, 170, 168], 97) + femmesh.addFace([56, 80, 88, 133, 171, 170], 98) + femmesh.addFace([73, 87, 90, 165, 172, 160], 99) + femmesh.addFace([3, 39, 89, 40, 173, 174], 100) + femmesh.addFace([3, 89, 22, 174, 166, 38], 101) + femmesh.addFace([1, 90, 5, 175, 176, 6], 102) + femmesh.addFace([1, 8, 90, 23, 161, 175], 103) + femmesh.addFace([80, 89, 88, 167, 177, 171], 104) + femmesh.addFace([5, 90, 87, 176, 172, 162], 105) + femmesh.addFace([39, 88, 89, 169, 177, 173], 106) + return True From 90b05cf954ffe086e21be10dc95e24f78a37e3cd Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 26 Jul 2021 11:37:51 +0200 Subject: [PATCH 18/19] FEM: solver frame work, code formating --- src/Mod/Fem/femsolver/run.py | 4 ++-- src/Mod/Fem/femsolver/settings.py | 16 ++++++++-------- src/Mod/Fem/femsolver/solver_taskpanel.py | 2 +- src/Mod/Fem/femsolver/writerbase.py | 2 +- 4 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index 00d0b9fc20..a4bbb357fc 100644 --- a/src/Mod/Fem/femsolver/run.py +++ b/src/Mod/Fem/femsolver/run.py @@ -95,8 +95,8 @@ def run_fem_solver(solver, working_dir=None): :note: There is some legacy code to execute the old Calculix solver - (pre-framework) which behaives differently because it doesn't use a - :class:`Machine`. + (pre-framework) which behaives differently because it does not + use a :class:`Machine`. """ if solver.Proxy.Type == "Fem::SolverCcxTools": diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index de7a24b783..a24ae15718 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -85,7 +85,7 @@ def get_binary(name): Return the specific path set by the user in FreeCADs settings/parameter system if set or the default binary name if no specific path is set. If no - path was found because the solver *name* isn't supported ``None`` is + path was found because the solver *name* is not supported ``None`` is returned. This method does not check whether the binary actually exists and is callable. @@ -93,12 +93,12 @@ def get_binary(name): """ if name in _SOLVER_PARAM: binary = _SOLVER_PARAM[name].get_binary() - FreeCAD.Console.PrintMessage('Solver binary path: {} \n'.format(binary)) + FreeCAD.Console.PrintMessage("Solver binary path: {} \n".format(binary)) return binary else: FreeCAD.Console.PrintError( - 'Settings solver name: {} not found in ' - 'solver settings modules _SOLVER_PARAM dirctionary.\n' + "Settings solver name: {} not found in " + "solver settings modules _SOLVER_PARAM dirctionary.\n" .format(name) ) return None @@ -108,8 +108,8 @@ def get_write_comments(name): """ Check whether "write_comments" is set for solver. Returns ``True`` if the "write_comments" setting/parameter is set for the - solver with the id *name*. Returns ``False`` otherwise. If the solver isn't - supported ``None`` is returned. + solver with the id *name*. Returns ``False`` otherwise. If the solver is + not supported ``None`` is returned. :param name: solver id as a ``str`` (see :mod:`femsolver.settings`) """ @@ -117,8 +117,8 @@ def get_write_comments(name): return _SOLVER_PARAM[name].get_write_comments() else: FreeCAD.Console.PrintError( - 'Settings solver name: {} not found in ' - 'solver settings modules _SOLVER_PARAM dirctionary.\n' + "Settings solver name: {} not found in " + "solver settings modules _SOLVER_PARAM dirctionary.\n" .format(name) ) return None diff --git a/src/Mod/Fem/femsolver/solver_taskpanel.py b/src/Mod/Fem/femsolver/solver_taskpanel.py index d4b400213d..84f60437b2 100644 --- a/src/Mod/Fem/femsolver/solver_taskpanel.py +++ b/src/Mod/Fem/femsolver/solver_taskpanel.py @@ -72,7 +72,7 @@ class ControlTaskPanel(QtCore.QObject): self.form.abortClicked.connect(self.abort) self.form.directoryChanged.connect(self.updateMachine) - # Seems that the task panel doesn't get destroyed. Disconnect + # Seems that the task panel does not get destroyed. Disconnect # as soon as the widget of the task panel gets destroyed. self.form.destroyed.connect(self._disconnectMachine) self.form.destroyed.connect(self._timer.stop) diff --git a/src/Mod/Fem/femsolver/writerbase.py b/src/Mod/Fem/femsolver/writerbase.py index 645456632b..b27dcfa021 100644 --- a/src/Mod/Fem/femsolver/writerbase.py +++ b/src/Mod/Fem/femsolver/writerbase.py @@ -56,7 +56,7 @@ class FemInputWriter(): self.document = self.analysis.Document # working dir self.dir_name = dir_name - # if dir_name was not given or if it exists but isn't empty: create a temporary dir + # if dir_name was not given or if it exists but is not empty: create a temporary dir # Purpose: makes sure the analysis can be run even on wired situation if not dir_name: FreeCAD.Console.PrintWarning( From bded5e146c131b4beeae5c6ab24589582170ce22 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Mon, 26 Jul 2021 11:40:58 +0200 Subject: [PATCH 19/19] FEM: solver frame work, improve binary handling --- src/Mod/Fem/femsolver/settings.py | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/src/Mod/Fem/femsolver/settings.py b/src/Mod/Fem/femsolver/settings.py index a24ae15718..f01efa3f4f 100644 --- a/src/Mod/Fem/femsolver/settings.py +++ b/src/Mod/Fem/femsolver/settings.py @@ -93,7 +93,10 @@ def get_binary(name): """ if name in _SOLVER_PARAM: binary = _SOLVER_PARAM[name].get_binary() - FreeCAD.Console.PrintMessage("Solver binary path: {} \n".format(binary)) + FreeCAD.Console.PrintMessage( + 'Solver binary path (returned from binary getter): {} \n' + .format(binary) + ) return binary else: FreeCAD.Console.PrintError( @@ -190,19 +193,31 @@ class _SolverDlg(object): def get_binary(self): # set the binary path to the FreeCAD defaults - # ATM pure unix shell commands without path names are used + # ATM pure unix shell commands without path names are used as standard + # TODO the binaries provieded with the FreeCAD distribution should be found + # without any additional user input + # see ccxttols, it works for Windows and Linux there binary = self.default - FreeCAD.Console.PrintLog("Solver binary path: {} \n".format(binary)) + FreeCAD.Console.PrintLog("Solver binary path default: {} \n".format(binary)) # check if use_default is set to True # if True the standard binary path will be overwritten with a user binary path if self.param_group.GetBool(self.use_default, True) is False: binary = self.param_group.GetString(self.custom_path) - FreeCAD.Console.PrintLog("Solver binary path: {} \n".format(binary)) + FreeCAD.Console.PrintLog("Solver binary path user setting: {} \n".format(binary)) # get the whole binary path name for the given command or binary path and return it + # None is returned if the binary has not been found + # The user does not know what exactly has going wrong. from distutils.spawn import find_executable as find_bin - return find_bin(binary) + the_found_binary = find_bin(binary) + if the_found_binary is None: + FreeCAD.Console.PrintError( + "The binary has not been found. Full binary search path: {}\n" + .format(binary) + ) + FreeCAD.Console.PrintLog("Solver binary found path: {}\n".format(the_found_binary)) + return the_found_binary def get_write_comments(self): return self.param_group.GetBool(self.WRITE_COMMENTS_PARAM, True)