diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 4ff7364a4d..f81f4d219c 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -48,10 +48,17 @@ 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_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_seg2.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 +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_seg2.py + femexamples/meshes/mesh_canticcx_seg3.py femexamples/meshes/mesh_canticcx_tetra10.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 @@ -287,10 +298,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 +364,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 +473,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_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_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 90% rename from src/Mod/Fem/femexamples/ccx_cantilever_hexa20faceload.py rename to src/Mod/Fem/femexamples/ccx_cantilever_ele_hexa20.py index 62f5252903..795d568959 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"], @@ -48,11 +48,12 @@ 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() See forum topic post: +hexa20 elements and face load ... """ @@ -68,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() 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/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/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/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/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 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 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/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): 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..f01efa3f4f 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,15 @@ 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( - '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 +111,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 +120,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 @@ -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) 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( 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): 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 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/PathScripts/PathAdaptive.py b/src/Mod/Path/PathScripts/PathAdaptive.py index 06cc36774f..f7b96cf96e 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) @@ -579,20 +580,30 @@ 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) + all_regions.append(shape) + elif sub.startswith("Edge"): + # 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: + for e in w.Edges: + edge_list.append([discretize(e)]) + # Apply regular Extensions op.exts = [] # pylint: disable=attribute-defined-outside-init for ext in extensions: @@ -605,10 +616,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 @@ -662,6 +675,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): @@ -703,6 +719,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) 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: 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: diff --git a/src/Mod/Path/PathTests/TestPathAdaptive.py b/src/Mod/Path/PathTests/TestPathAdaptive.py new file mode 100644 index 0000000000..8e053df53d --- /dev/null +++ b/src/Mod/Path/PathTests/TestPathAdaptive.py @@ -0,0 +1,459 @@ +# -*- coding: utf-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 * +# * 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. + ''' + + # 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 + 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") + + # 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): + '''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.''' + 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) + + +# 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; \ +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" diff --git a/src/Mod/Path/PathTests/test_adaptive.fcstd b/src/Mod/Path/PathTests/test_adaptive.fcstd new file mode 100644 index 0000000000..7af4b06f81 Binary files /dev/null and b/src/Mod/Path/PathTests/test_adaptive.fcstd differ diff --git a/src/Mod/Path/TestPathApp.py b/src/Mod/Path/TestPathApp.py index 0be621b040..961046d948 100644 --- a/src/Mod/Path/TestPathApp.py +++ b/src/Mod/Path/TestPathApp.py @@ -22,50 +22,51 @@ 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