From ed006b82c34be50f77550bf6d3cc4a6eb9281d07 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:03 +0200 Subject: [PATCH 01/13] FEM: reinforced material, add object, including all FEM object unit tests --- src/Mod/Fem/CMakeLists.txt | 2 + src/Mod/Fem/ObjectsFem.py | 15 ++++ .../_ViewProviderFemMaterialReinforced.py | 89 +++++++++++++++++++ .../Fem/femobjects/_FemMaterialReinforced.py | 59 ++++++++++++ src/Mod/Fem/femtest/testobject.py | 34 ++++++- 5 files changed, 196 insertions(+), 3 deletions(-) create mode 100644 src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py create mode 100644 src/Mod/Fem/femobjects/_FemMaterialReinforced.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 88460c7304..38aab6b7c5 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -206,6 +206,7 @@ SET(FemObjectsScripts_SRCS femobjects/_FemElementGeometry2D.py femobjects/_FemElementRotation1D.py femobjects/_FemMaterial.py + femobjects/_FemMaterialReinforced.py femobjects/_FemMaterialMechanicalNonlinear.py femobjects/_FemMeshBoundaryLayer.py femobjects/_FemMeshGmsh.py @@ -286,6 +287,7 @@ SET(FemGuiScripts_SRCS femguiobjects/_ViewProviderFemElementGeometry2D.py femguiobjects/_ViewProviderFemElementRotation1D.py femguiobjects/_ViewProviderFemMaterial.py + femguiobjects/_ViewProviderFemMaterialReinforced.py femguiobjects/_ViewProviderFemMaterialMechanicalNonlinear.py femguiobjects/_ViewProviderFemMeshBoundaryLayer.py femguiobjects/_ViewProviderFemMeshGmsh.py diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index a49fcabeaf..6ba8a97ea5 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -372,6 +372,21 @@ def makeMaterialMechanicalNonlinear( return obj +def makeMaterialReinforced( + doc, + name="MaterialReinforced" +): + '''makeMaterialReinforced(document, [matrix_material], [reinforcement_material], [name]): + creates a reinforced material object''' + obj = doc.addObject("App::MaterialObjectPython", name) + from femobjects import _FemMaterialReinforced + _FemMaterialReinforced._FemMaterialReinforced(obj) + if FreeCAD.GuiUp: + from femguiobjects import _ViewProviderFemMaterialReinforced + _ViewProviderFemMaterialReinforced._ViewProviderFemMaterialReinforced(obj.ViewObject) + return obj + + def makeMaterialSolid( doc, name="MechanicalSolidMaterial" diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py new file mode 100644 index 0000000000..39556b3b8b --- /dev/null +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py @@ -0,0 +1,89 @@ +# *************************************************************************** +# * Copyright (c) 2019 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM material reinforced ViewProvider for the document object" +__author__ = "Bernd Hahnebach" +__url__ = "http://www.freecadweb.org" + +## @package ViewProviderFemMaterialReinforced +# \ingroup FEM +# \brief FreeCAD FEM _ViewProviderFemMaterialReinforced + +import FreeCAD +import FreeCADGui +import FemGui # needed to display the icons in TreeView +False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui' + + +class _ViewProviderFemMaterialReinforced: + "A View Provider for the FemMaterialReinfocement object" + def __init__(self, vobj): + vobj.Proxy = self + + def getIcon(self): + return ":/icons/fem-constraint-selfweight.svg" # TODO: create one + + def attach(self, vobj): + from pivy import coin + self.ViewObject = vobj + self.Object = vobj.Object + self.standard = coin.SoGroup() + vobj.addDisplayMode(self.standard, "Default") + + def getDisplayModes(self, obj): + return ["Default"] + + def updateData(self, obj, prop): + return + + def onChanged(self, vobj, prop): + return + + def setEdit(self, vobj, mode=0): + # avoid edit mode by return False + # https://forum.freecadweb.org/viewtopic.php?t=12139&start=10#p161062 + return False + + def unsetEdit(self, vobj, mode=0): + FreeCADGui.Control.closeDialog() + return True + + def doubleClicked(self, vobj): + guidoc = FreeCADGui.getDocument(vobj.Object.Document) + # check if another VP is in edit mode + # https://forum.freecadweb.org/viewtopic.php?t=13077#p104702 + if not guidoc.getInEdit(): + guidoc.setEdit(vobj.Object.Name) + else: + from PySide.QtGui import QMessageBox + message = ( + 'Active Task Dialog found! ' + 'Please close this one before opening a new one!' + ) + QMessageBox.critical(None, "Error in tree view", message) + FreeCAD.Console.PrintError(message + '\n') + return True + + def __getstate__(self): + return None + + def __setstate__(self, state): + return None diff --git a/src/Mod/Fem/femobjects/_FemMaterialReinforced.py b/src/Mod/Fem/femobjects/_FemMaterialReinforced.py new file mode 100644 index 0000000000..d8b970e0db --- /dev/null +++ b/src/Mod/Fem/femobjects/_FemMaterialReinforced.py @@ -0,0 +1,59 @@ +# *************************************************************************** +# * * +# * Copyright (c) 2019 Bernd Hahnebach * +# * * +# * 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 * +# * * +# *************************************************************************** + +__title__ = "FreeCAD FEM reinforced material" +__author__ = "Bernd Hahnebach" +__url__ = "http://www.freecadweb.org" + +## @package FemMaterialReinforced +# \ingroup FEM +# \brief FreeCAD FEM _FemMaterialReinforced + + +class _FemMaterialReinforced: + "The FemMaterialReinforced object" + def __init__(self, obj): + obj.addProperty( + "App::PropertyLinkSubList", + "References", + "Material", + "List of material shapes" + ) + obj.addProperty( + "App::PropertyMap", + "Reinforcement", + "Composites", + "Reinforcement material properties" + ) + obj.addProperty( + "App::PropertyEnumeration", + "Category", + "Material", + "Matrix material properties" + ) + obj.Category = ['Solid'] + obj.Category = 'Solid' + obj.Proxy = self + self.Type = "Fem::MaterialReinforced" + + def execute(self, obj): + return diff --git a/src/Mod/Fem/femtest/testobject.py b/src/Mod/Fem/femtest/testobject.py index a56b076a07..4adb6e968b 100644 --- a/src/Mod/Fem/femtest/testobject.py +++ b/src/Mod/Fem/femtest/testobject.py @@ -82,6 +82,7 @@ class TestObjectCreate(unittest.TestCase): analysis.addObject(ObjectsFem.makeMaterialFluid(doc)) mat = analysis.addObject(ObjectsFem.makeMaterialSolid(doc))[0] analysis.addObject(ObjectsFem.makeMaterialMechanicalNonlinear(doc, mat)) + analysis.addObject(ObjectsFem.makeMaterialReinforced(doc)) msh = analysis.addObject(ObjectsFem.makeMeshGmsh(doc))[0] analysis.addObject(ObjectsFem.makeMeshBoundaryLayer(doc, msh)) @@ -266,6 +267,10 @@ class TestObjectType(unittest.TestCase): 'Fem::MaterialMechanicalNonlinear', type_of_obj(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid)) ) + self.assertEqual( + 'Fem::MaterialReinforced', + type_of_obj(ObjectsFem.makeMaterialReinforced(doc)) + ) mesh = ObjectsFem.makeMeshGmsh(doc) self.assertEqual( 'Fem::FemMeshGmsh', @@ -330,7 +335,7 @@ class TestObjectType(unittest.TestCase): 'Fem::FemEquationElmerHeat', type_of_obj(ObjectsFem.makeEquationHeat(doc, solverelmer)) ) - # is = 43 (just copy in empty file to test) + # is = 44 tests (just copy in empty file to test) # TODO: vtk post objs # TODO: use different type for fluid and solid material @@ -450,6 +455,10 @@ class TestObjectType(unittest.TestCase): ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid), 'Fem::MaterialMechanicalNonlinear' )) + self.assertTrue(is_of_type( + ObjectsFem.makeMaterialReinforced(doc), + 'Fem::MaterialReinforced' + )) mesh = ObjectsFem.makeMeshGmsh(doc) self.assertTrue(is_of_type( mesh, @@ -516,7 +525,7 @@ class TestObjectType(unittest.TestCase): ObjectsFem.makeEquationHeat(doc, solverelmer), 'Fem::FemEquationElmerHeat' )) - # is = 43 (just copy in empty file to test) + # is = 44 tests (just copy in empty file to test) # ******************************************************************************************** def test_femobjects_derivedfromfem( @@ -899,6 +908,20 @@ class TestObjectType(unittest.TestCase): 'Fem::MaterialMechanicalNonlinear' )) + # MaterialReinforced + self.assertTrue(is_derived_from( + ObjectsFem.makeMaterialReinforced(doc), + 'App::DocumentObject' + )) + self.assertTrue(is_derived_from( + ObjectsFem.makeMaterialReinforced(doc), + 'App::MaterialObjectPython' + )) + self.assertTrue(is_derived_from( + ObjectsFem.makeMaterialReinforced(doc), + 'Fem::MaterialReinforced' + )) + # FemMeshGmsh self.assertTrue(is_derived_from( mesh, 'App::DocumentObject' @@ -1270,6 +1293,11 @@ class TestObjectType(unittest.TestCase): materialsolid ).isDerivedFrom('Fem::FeaturePython') ) + self.assertTrue( + ObjectsFem.makeMaterialReinforced( + doc + ).isDerivedFrom('App::MaterialObjectPython') + ) mesh = ObjectsFem.makeMeshGmsh(doc) self.assertTrue( mesh.isDerivedFrom('Fem::FemMeshObjectPython') @@ -1356,7 +1384,7 @@ class TestObjectType(unittest.TestCase): solverelmer ).isDerivedFrom('App::FeaturePython') ) - # is = 43 (just copy in empty file to test) + # is = 44 tests (just copy in empty file to test) # ******************************************************************************************** def tearDown( From 5e201aef97aa8696332f593bd61b195a66df0c60 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:05 +0200 Subject: [PATCH 02/13] FEM: reinforced material, add icon (thanks to bitacovir) --- src/Mod/Fem/Gui/Resources/Fem.qrc | 1 + .../icons/fem-material-reinforced.svg | 686 ++++++++++++++++++ .../_ViewProviderFemMaterialReinforced.py | 2 +- 3 files changed, 688 insertions(+), 1 deletion(-) create mode 100644 src/Mod/Fem/Gui/Resources/icons/fem-material-reinforced.svg diff --git a/src/Mod/Fem/Gui/Resources/Fem.qrc b/src/Mod/Fem/Gui/Resources/Fem.qrc index 04cbc0624d..f0b001711b 100755 --- a/src/Mod/Fem/Gui/Resources/Fem.qrc +++ b/src/Mod/Fem/Gui/Resources/Fem.qrc @@ -52,6 +52,7 @@ icons/fem-material.svg icons/fem-material-fluid.svg icons/fem-material-nonlinear.svg + icons/fem-material-reinforced.svg icons/fem-post-data-pipline.svg icons/fem-post-filter-clip-region.svg icons/fem-post-filter-clip-scalar.svg diff --git a/src/Mod/Fem/Gui/Resources/icons/fem-material-reinforced.svg b/src/Mod/Fem/Gui/Resources/icons/fem-material-reinforced.svg new file mode 100644 index 0000000000..cfcc4d6667 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/icons/fem-material-reinforced.svg @@ -0,0 +1,686 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + [Przemo Firszt] + + + fem-material + 2015-07-28 + http://www.freecadweb.org/wiki/index.php?title=Artwork + + + FreeCAD + + + FreeCAD/src/Mod/ + + + FreeCAD LGPL2+ + + + https://www.gnu.org/copyleft/lesser.html + + + [agryson] Alexander Gryson + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py index 39556b3b8b..0a5c89f602 100644 --- a/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py @@ -39,7 +39,7 @@ class _ViewProviderFemMaterialReinforced: vobj.Proxy = self def getIcon(self): - return ":/icons/fem-constraint-selfweight.svg" # TODO: create one + return ":/icons/fem-material-reinforced.svg" def attach(self, vobj): from pivy import coin From ba08d3d54f636e35b96e746464a7717a20666f4d Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:05 +0200 Subject: [PATCH 03/13] FEM: reinforced material, add a GUI command --- src/Mod/Fem/Gui/Workbench.cpp | 2 ++ src/Mod/Fem/femcommands/commands.py | 35 +++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+) diff --git a/src/Mod/Fem/Gui/Workbench.cpp b/src/Mod/Fem/Gui/Workbench.cpp index 84646e8c71..10598fbf14 100755 --- a/src/Mod/Fem/Gui/Workbench.cpp +++ b/src/Mod/Fem/Gui/Workbench.cpp @@ -87,6 +87,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const << "FEM_MaterialSolid" << "FEM_MaterialFluid" << "FEM_MaterialMechanicalNonlinear" + << "FEM_MaterialReinforced" << "FEM_MaterialEditor" << "Separator" << "FEM_ElementGeometry1D" @@ -190,6 +191,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const *material << "FEM_MaterialSolid" << "FEM_MaterialFluid" << "FEM_MaterialMechanicalNonlinear" + << "FEM_MaterialReinforced" << "FEM_MaterialEditor"; Gui::MenuItem* elec = new Gui::MenuItem; diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index 4a08def59f..e14f1d0146 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -665,6 +665,37 @@ class _CommandFemMaterialMechanicalNonlinear(CommandManager): FreeCAD.ActiveDocument.recompute() +class _CommandFemMaterialReinforced(CommandManager): + "The FEM_MaterialReinforced command definition" + def __init__(self): + super(_CommandFemMaterialReinforced, self).__init__() + self.resources = { + 'Pixmap': 'fem-material-reinforced', + 'MenuText': QtCore.QT_TRANSLATE_NOOP( + "FEM_MaterialReinforced", + "Reinforced material (concrete)" + ), + 'Accel': "M, M", + 'ToolTip': QtCore.QT_TRANSLATE_NOOP( + "FEM_MaterialReinforced", + "Creates a material for reinforced matrix material such as concrete" + ) + } + self.is_active = 'with_analysis' + + def Activated(self): + FreeCAD.ActiveDocument.openTransaction("Create Reinforced Material") + FreeCADGui.addModule("ObjectsFem") + FreeCADGui.doCommand( + "FemGui.getActiveAnalysis().addObject(ObjectsFem." + "makeMaterialReinforced(FreeCAD.ActiveDocument, 'ReinforcedMaterial'))" + ) + FreeCADGui.doCommand( + "FreeCADGui.ActiveDocument.setEdit(FreeCAD.ActiveDocument.ActiveObject.Name)" + ) + FreeCAD.ActiveDocument.recompute() + + class _CommandFemMaterialSolid(CommandManager): "The FEM_MaterialSolid command definition" def __init__(self): @@ -1296,6 +1327,10 @@ FreeCADGui.addCommand( 'FEM_MaterialMechanicalNonlinear', _CommandFemMaterialMechanicalNonlinear() ) +FreeCADGui.addCommand( + 'FEM_MaterialReinforced', + _CommandFemMaterialReinforced() +) FreeCADGui.addCommand( 'FEM_MaterialSolid', _CommandFemMaterialSolid() From cf5eb3c5edf97d662f42c6b9117b88582575d7b5 Mon Sep 17 00:00:00 2001 From: HarryvL Date: Sun, 16 Jun 2019 18:26:09 +0200 Subject: [PATCH 04/13] FEM: result properties, add new lists to hold concrete results --- src/Mod/Fem/App/FemVTKTools.cpp | 7 +++ .../_ViewProviderFemResultMechanical.py | 25 +++++++++- .../Fem/femobjects/_FemResultMechanical.py | 50 +++++++++++++++++++ 3 files changed, 81 insertions(+), 1 deletion(-) diff --git a/src/Mod/Fem/App/FemVTKTools.cpp b/src/Mod/Fem/App/FemVTKTools.cpp index 250454bf1e..432bc37cbf 100644 --- a/src/Mod/Fem/App/FemVTKTools.cpp +++ b/src/Mod/Fem/App/FemVTKTools.cpp @@ -660,6 +660,9 @@ std::map _getFreeCADMechResultVectorProperties() { // App::PropertyVectorList will be a list of vectors in vtk std::map resFCVecProp; resFCVecProp["DisplacementVectors"] = "Displacement"; + resFCVecProp["PS1Vector"] = "PS1Vector"; + resFCVecProp["PS2Vector"] = "PS2Vector"; + resFCVecProp["PS3Vector"] = "PS3Vector"; return resFCVecProp; } @@ -691,6 +694,10 @@ std::map _getFreeCADMechResultScalarProperties() { resFCScalProp["PrincipalMin"] = "Minor Principal Stress"; // can be plotted in Paraview as THE MINOR PRINCIPAL STRESS MAGNITUDE resFCScalProp["StressValues"] = "von Mises Stress"; resFCScalProp["Temperature"] = "Temperature"; + resFCScalProp["MohrCoulomb"] = "MohrCoulomb"; + resFCScalProp["ReinforcementRatio_x"] = "ReinforcementRatio_x"; + resFCScalProp["ReinforcementRatio_y"] = "ReinforcementRatio_y"; + resFCScalProp["ReinforcementRatio_z"] = "ReinforcementRatio_z"; resFCScalProp["UserDefined"] = "UserDefinedMyName"; // this is empty or am I wrong ?! resFCScalProp["MassFlowRate"] = "Mass Flow Rate"; diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemResultMechanical.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemResultMechanical.py index 1d4f823d92..f108e29dc8 100644 --- a/src/Mod/Fem/femguiobjects/_ViewProviderFemResultMechanical.py +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemResultMechanical.py @@ -467,6 +467,28 @@ class _TaskPanelFemResultShow: exy = np.array(self.result_obj.NodeStrainXY) exz = np.array(self.result_obj.NodeStrainXZ) eyz = np.array(self.result_obj.NodeStrainYZ) + + # Display of Reinforcement Ratios and Mohr Coulomb Criterion + rx = np.array(self.result_obj.ReinforcementRatio_x) + ry = np.array(self.result_obj.ReinforcementRatio_y) + rz = np.array(self.result_obj.ReinforcementRatio_z) + mc = np.array(self.result_obj.MohrCoulomb) + + ps1vector = np.array(self.result_obj.PS1Vector) + s1x = np.array(ps1vector[:, 0]) + s1y = np.array(ps1vector[:, 1]) + s1z = np.array(ps1vector[:, 2]) + + ps2vector = np.array(self.result_obj.PS2Vector) + s2x = np.array(ps2vector[:, 0]) + s2y = np.array(ps2vector[:, 1]) + s2z = np.array(ps2vector[:, 2]) + + ps3vector = np.array(self.result_obj.PS1Vector) + s3x = np.array(ps3vector[:, 0]) + s3y = np.array(ps3vector[:, 1]) + s3z = np.array(ps3vector[:, 2]) + userdefined_eq = self.form.user_def_eq.toPlainText() # Get equation to be used UserDefinedFormula = eval(userdefined_eq).tolist() self.result_obj.UserDefined = UserDefinedFormula @@ -486,7 +508,8 @@ class _TaskPanelFemResultShow: del x, y, z, T, Von, Peeq, P1, P2, P3 del sxx, syy, szz, sxy, sxz, syz del exx, eyy, ezz, exy, exz, eyz - del MF, NP + del MF, NP, rx, ry, rz, mc + del s1x, s1y, s1z, s2x, s2y, s2z, s3x, s3y, s3z def select_displacement_type(self, disp_type): QApplication.setOverrideCursor(Qt.WaitCursor) diff --git a/src/Mod/Fem/femobjects/_FemResultMechanical.py b/src/Mod/Fem/femobjects/_FemResultMechanical.py index 721678122f..81da7d554b 100644 --- a/src/Mod/Fem/femobjects/_FemResultMechanical.py +++ b/src/Mod/Fem/femobjects/_FemResultMechanical.py @@ -80,6 +80,56 @@ class _FemResultMechanical(): "List of equivalent plastic strain values", True ) + obj.addProperty( + "App::PropertyFloatList", + "MohrCoulomb", + "NodeData", + "List of Mohr Coulomb stress values", + True + ) + obj.addProperty( + "App::PropertyFloatList", + "ReinforcementRatio_x", + "NodeData", + "Reinforcement ratio x-direction", + True + ) + obj.addProperty( + "App::PropertyFloatList", + "ReinforcementRatio_y", + "NodeData", + "Reinforcement ratio y-direction", + True + ) + obj.addProperty( + "App::PropertyFloatList", + "ReinforcementRatio_z", + "NodeData", + "Reinforcement ratio z-direction", + True + ) + obj.addProperty( + "App::PropertyVectorList", + "PS1Vector", + "NodeData", + "List of 1st Principal Stress Vectors", + True + ) + obj.addProperty( + "App::PropertyVectorList", + "PS2Vector", + "NodeData", + "List of 2nd Principal Stress Vectors", + True + ) + obj.addProperty( + "App::PropertyVectorList", + "PS3Vector", + "NodeData", + "List of 3rd Principal Stress Vectors", + True + ) + # readonly in propertyEditor of comboView obj.addProperty( "App::PropertyFloatList", From fc1c954c951556881a829f88099615634467c51d Mon Sep 17 00:00:00 2001 From: HarryvL Date: Sun, 16 Jun 2019 18:26:11 +0200 Subject: [PATCH 05/13] FEM: vtk tool, change the results exported to vtk --- src/Mod/Fem/App/FemVTKTools.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/src/Mod/Fem/App/FemVTKTools.cpp b/src/Mod/Fem/App/FemVTKTools.cpp index 432bc37cbf..a0b4fd04c4 100644 --- a/src/Mod/Fem/App/FemVTKTools.cpp +++ b/src/Mod/Fem/App/FemVTKTools.cpp @@ -660,9 +660,10 @@ std::map _getFreeCADMechResultVectorProperties() { // App::PropertyVectorList will be a list of vectors in vtk std::map resFCVecProp; resFCVecProp["DisplacementVectors"] = "Displacement"; - resFCVecProp["PS1Vector"] = "PS1Vector"; - resFCVecProp["PS2Vector"] = "PS2Vector"; - resFCVecProp["PS3Vector"] = "PS3Vector"; + // https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=70#p296317 + resFCVecProp["PS1Vector"] = "Major Principal Stress"; + resFCVecProp["PS2Vector"] = "Intermediate Principal Stress"; + resFCVecProp["PS3Vector"] = "Minor Principal Stress"; return resFCVecProp; } @@ -689,9 +690,10 @@ std::map _getFreeCADMechResultScalarProperties() { resFCScalProp["NodeStrainXZ"] = "Strain xz component"; resFCScalProp["NodeStrainYZ"] = "Strain yz component"; resFCScalProp["Peeq"] = "Equivalent Plastic Strain"; - resFCScalProp["PrincipalMax"] = "Major Principal Stress"; // can be plotted in Paraview as THE MAJOR PRINCIPAL STRESS MAGNITUDE - resFCScalProp["PrincipalMed"] = "Intermediate Principal Stress"; // can be plotted in Paraview as THE INTERMEDIATE PRINCIPAL STRESS MAGNITUDE - resFCScalProp["PrincipalMin"] = "Minor Principal Stress"; // can be plotted in Paraview as THE MINOR PRINCIPAL STRESS MAGNITUDE + // https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=70#p296317 + // resFCScalProp["PrincipalMax"] = "Major Principal Stress"; // can be plotted in Paraview as THE MAJOR PRINCIPAL STRESS MAGNITUDE + // resFCScalProp["PrincipalMed"] = "Intermediate Principal Stress"; // can be plotted in Paraview as THE INTERMEDIATE PRINCIPAL STRESS MAGNITUDE + // resFCScalProp["PrincipalMin"] = "Minor Principal Stress"; // can be plotted in Paraview as THE MINOR PRINCIPAL STRESS MAGNITUDE resFCScalProp["StressValues"] = "von Mises Stress"; resFCScalProp["Temperature"] = "Temperature"; resFCScalProp["MohrCoulomb"] = "MohrCoulomb"; From d3007258e7651b4f36d2a8c5ba6b952ddfaf8b6e Mon Sep 17 00:00:00 2001 From: HarryvL Date: Sun, 16 Jun 2019 18:26:13 +0200 Subject: [PATCH 06/13] FEM: concrete results, new methods for calculating results for concrete materials --- src/Mod/Fem/TestFem.py | 8 +- src/Mod/Fem/femresult/resulttools.py | 221 ++++++++++++++++++++++++++- src/Mod/Fem/femtest/testresult.py | 23 ++- 3 files changed, 246 insertions(+), 6 deletions(-) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index 03fa8380db..4a127c4f79 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -126,7 +126,8 @@ gf() ./bin/FreeCADCmd --run-test "femtest.testobject.TestObjectType.test_femobjects_derivedfromstd" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_read_frd_massflow_networkpressure" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_von_mises" -./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal" +./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_std" +./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_reinforced" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_disp_abs" ./bin/FreeCADCmd --run-test "femtest.testsolverframework.TestSolverFrameWork.test_solver_framework" @@ -214,7 +215,10 @@ import unittest unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_von_mises")) import unittest -unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal")) +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_std")) + +import unittest +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_reinforced")) import unittest unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_disp_abs")) diff --git a/src/Mod/Fem/femresult/resulttools.py b/src/Mod/Fem/femresult/resulttools.py index 10343b9064..f81ff0a628 100644 --- a/src/Mod/Fem/femresult/resulttools.py +++ b/src/Mod/Fem/femresult/resulttools.py @@ -324,7 +324,7 @@ def add_principal_stress(res_obj): res_obj.NodeStressYZ ) for Sxx, Syy, Szz, Sxy, Sxz, Syz in iterator: - prin1, prin2, prin3, shear = calculate_principal_stress((Sxx, Syy, Szz, Sxy, Sxz, Syz)) + prin1, prin2, prin3, shear = calculate_principal_stress_std((Sxx, Syy, Szz, Sxy, Sxz, Syz)) prinstress1.append(prin1) prinstress2.append(prin2) prinstress3.append(prin3) @@ -373,7 +373,7 @@ def calculate_von_mises(stress_tensor): return np.sqrt(1.5 * np.linalg.norm(normal - pressure)**2 + 3.0 * np.linalg.norm(shear)**2) -def calculate_principal_stress(stress_tensor): +def calculate_principal_stress_std(stress_tensor): s11 = stress_tensor[0] # Sxx s22 = stress_tensor[1] # Syy s33 = stress_tensor[2] # Szz @@ -399,6 +399,223 @@ def calculate_principal_stress(stress_tensor): # https://forum.freecadweb.org/viewtopic.php?f=22&t=33911&start=10#p284229 +def calculate_principal_stress_reinforced(stress_tensor): + # + # HarryvL - calculate principal stress vectors and values + # - for total stresses use stress_tensor[0], stress_tensor[1], stress_tensor[2] + # on the diagonal of the stress tensor + # + # difference to the original method: + # https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=90#p296539 + # + + s11 = stress_tensor[0] # Sxx + s22 = stress_tensor[1] # Syy + s33 = stress_tensor[2] # Szz + s12 = stress_tensor[3] # Sxy + s31 = stress_tensor[4] # Sxz + s23 = stress_tensor[5] # Syz + sigma = np.array([ + [s11, s12, s31], + [s12, s22, s23], + [s31, s23, s33] + ]) # https://forum.freecadweb.org/viewtopic.php?f=18&t=24637&start=10#p240408 + + eigenvalues, eigenvectors = np.linalg.eig(sigma) + + # + # HarryvL: suppress complex eigenvalue and vectors that may occur for + # near-zero (numerical noise) stress fields + # + + eigenvalues = eigenvalues.real + eigenvectors = eigenvectors.real + + eigenvectors[:, 0] = eigenvalues[0] * eigenvectors[:, 0] + eigenvectors[:, 1] = eigenvalues[1] * eigenvectors[:, 1] + eigenvectors[:, 2] = eigenvalues[2] * eigenvectors[:, 2] + + idx = eigenvalues.argsort()[::-1] + eigenvalues = eigenvalues[idx] + eigenvectors = eigenvectors[:, idx] + + maxshear = (eigenvalues[0] - eigenvalues[2]) / 2.0 + + return (eigenvalues[0], eigenvalues[1], eigenvalues[2], maxshear, + tuple([tuple(row) for row in eigenvectors.T])) + + +def calculate_rho(stress_tensor, fy): + + # + # HarryvL - Calculation of Reinforcement Ratios and + # Concrete Stresses according to http://heronjournal.nl/53-4/3.pdf + # - See post: + # https://forum.freecadweb.org/viewtopic.php?f=18&t=28821 + # fy: factored yield strength of reinforcement bars + # + + rmin = 1.0e9 + eqmin = 14 + + sxx = stress_tensor[0] + syy = stress_tensor[1] + szz = stress_tensor[2] + sxy = stress_tensor[3] + syz = stress_tensor[5] + sxz = stress_tensor[4] + + rhox = np.zeros(15) + rhoy = np.zeros(15) + rhoz = np.zeros(15) + + # i1=sxx+syy+szz NOT USED + # i2=sxx*syy+syy*szz+szz*sxx-sxy**2-sxz**2-syz**2 NOT USED + i3 = (sxx * syy * szz + 2 * sxy * sxz * syz - sxx * syz**2 + - syy * sxz**2 - szz * sxy**2) + + # Solution (5) + d = (sxx * syy - sxy**2) + if d != 0.: + rhoz[0] = i3 / d / fy + + # Solution (6) + d = (sxx * szz - sxz**2) + if d != 0.: + rhoy[1] = i3 / d / fy + + # Solution (7) + d = (syy * szz - syz**2) + if d != 0.: + rhox[2] = i3 / d / fy + + # Solution (9) + if sxx != 0.: + fc = sxz * sxy / sxx - syz + fxy = sxy**2 / sxx + fxz = sxz**2 / sxx + + # Solution (9+) + rhoy[3] = syy - fxy + fc + rhoy[3] /= fy + rhoz[3] = szz - fxz + fc + rhoz[3] /= fy + + # Solution (9-) + rhoy[4] = syy - fxy - fc + rhoy[4] /= fy + rhoz[4] = szz - fxz - fc + rhoz[4] /= fy + + # Solution (10) + if syy != 0.: + fc = syz * sxy / syy - sxz + fxy = sxy**2 / syy + fyz = syz**2 / syy + + # Solution (10+) + rhox[5] = sxx - fxy + fc + rhox[5] /= fy + rhoz[5] = szz - fyz + fc + rhoz[5] /= fy + + # Solution (10-)vm + rhox[6] = sxx - fxy - fc + + rhox[6] /= fy + rhoz[6] = szz - fyz - fc + rhoz[6] /= fy + + # Solution (11) + if szz != 0.: + fc = sxz * syz / szz - sxy + fxz = sxz**2 / szz + fyz = syz**2 / szz + + # Solution (11+) + rhox[7] = sxx - fxz + fc + rhox[7] /= fy + rhoy[7] = syy - fyz + fc + rhoy[7] /= fy + + # Solution (11-) + rhox[8] = sxx - fxz - fc + rhox[8] /= fy + rhoy[8] = syy - fyz - fc + rhoy[8] /= fy + + # Solution (13) + rhox[9] = (sxx + sxy + sxz) / fy + rhoy[9] = (syy + sxy + syz) / fy + rhoz[9] = (szz + sxz + syz) / fy + + # Solution (14) + rhox[10] = (sxx + sxy - sxz) / fy + rhoy[10] = (syy + sxy - syz) / fy + rhoz[10] = (szz - sxz - syz) / fy + + # Solution (15) + rhox[11] = (sxx - sxy - sxz) / fy + rhoy[11] = (syy - sxy + syz) / fy + rhoz[11] = (szz - sxz + syz) / fy + + # Solution (16) + rhox[12] = (sxx - sxy + sxz) / fy + rhoy[12] = (syy - sxy - syz) / fy + rhoz[12] = (szz + sxz - syz) / fy + + # Solution (17) + if syz != 0.: + rhox[13] = (sxx - sxy * sxz / syz) / fy + if sxz != 0.: + rhoy[13] = (syy - sxy * syz / sxz) / fy + if sxy != 0.: + rhoz[13] = (szz - sxz * syz / sxy) / fy + + for ir in range(0, rhox.size): + + if rhox[ir] >= -1.e-10 and rhoy[ir] >= -1.e-10 and rhoz[ir] > -1.e-10: + + # Concrete Stresses + scxx = sxx - rhox[ir] * fy + scyy = syy - rhoy[ir] * fy + sczz = szz - rhoz[ir] * fy + ic1 = (scxx + scyy + sczz) + ic2 = (scxx * scyy + scyy * sczz + sczz * scxx - sxy**2 + - sxz**2 - syz**2) + ic3 = (scxx * scyy * sczz + 2 * sxy * sxz * syz - scxx * syz**2 + - scyy * sxz**2 - sczz * sxy**2) + + if ic1 <= 1.e-6 and ic2 >= -1.e-6 and ic3 <= 1.0e-6: + + rsum = rhox[ir] + rhoy[ir] + rhoz[ir] + + if rsum < rmin and rsum > 0.: + rmin = rsum + eqmin = ir + + return rhox[eqmin], rhoy[eqmin], rhoz[eqmin] + + +def calculate_mohr_coulomb(prin1, prin3, phi, fck): + # + # HarryvL - Calculation of Mohr Coulomb yield criterion to judge + # concrete curshing and shear failure + # phi: angle of internal friction + # fck: factored compressive strength of the matrix material (usually concrete) + # + + coh = fck * (1 - np.sin(phi)) / 2 / np.cos(phi) + + mc_stress = ((prin1 - prin3) + (prin1 + prin3) * np.sin(phi) + - 2. * coh * np.cos(phi)) + + if mc_stress < 0.: + mc_stress = 0. + + return mc_stress + + def calculate_disp_abs(displacements): # see https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=100#p296657 return [np.linalg.norm(nd) for nd in displacements] diff --git a/src/Mod/Fem/femtest/testresult.py b/src/Mod/Fem/femtest/testresult.py index 2d75557422..ba3fa8bc63 100644 --- a/src/Mod/Fem/femtest/testresult.py +++ b/src/Mod/Fem/femtest/testresult.py @@ -313,11 +313,11 @@ class TestResult(unittest.TestCase): ) # ******************************************************************************************** - def test_stress_principal( + def test_stress_principal_std( self ): expected_principal = (-178.0076, -194.0749, -468.9075, 145.4499) - from femresult.resulttools import calculate_principal_stress as pr + from femresult.resulttools import calculate_principal_stress_std as pr prin = pr(self.get_stress_values()) rounded_prin = ( round(prin[0], 4), @@ -332,6 +332,25 @@ class TestResult(unittest.TestCase): "Calculated principal stresses are not the expected values." ) + # ******************************************************************************************** + def test_stress_principal_reinforced( + self + ): + expected_principal = (-178.0076, -194.0749, -468.9075, 145.4499) + from femresult.resulttools import calculate_principal_stress_reinforced as prrc + prin = prrc(self.get_stress_values()) + rounded_prin = ( + round(prin[0], 4), + round(prin[1], 4), + round(prin[2], 4), + round(prin[3], 4)) + # fcc_print(rounded_prin) + self.assertEqual( + rounded_prin, + expected_principal, + "Calculated principal reinforced stresses are not the expected values." + ) + # ******************************************************************************************** def test_disp_abs( self From 30ec7477d1c5c3e2a24c8639e0dc92954c809da8 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:15 +0200 Subject: [PATCH 07/13] FEM: concrete results, use the new concrete result reading methods on result reading --- src/Mod/Fem/feminout/importCcxFrdResults.py | 16 +- src/Mod/Fem/femresult/resulttools.py | 161 +++++++++++++++++++- src/Mod/Fem/femsolver/calculix/tasks.py | 7 +- src/Mod/Fem/femtools/ccxtools.py | 5 +- 4 files changed, 184 insertions(+), 5 deletions(-) diff --git a/src/Mod/Fem/feminout/importCcxFrdResults.py b/src/Mod/Fem/feminout/importCcxFrdResults.py index f9253a62f7..23280ddbc3 100644 --- a/src/Mod/Fem/feminout/importCcxFrdResults.py +++ b/src/Mod/Fem/feminout/importCcxFrdResults.py @@ -120,19 +120,31 @@ def importFrd( analysis_object.addObject(res_obj) # complementary result object calculations import femresult.resulttools as restools + import femtools.femutils as femutils if not res_obj.MassFlowRate: # only compact result if not Flow 1D results # compact result object, workaround for bug 2873 # https://www.freecadweb.org/tracker/view.php?id=2873 res_obj = restools.compact_result(res_obj) + # fill DisplacementLengths res_obj = restools.add_disp_apps(res_obj) # fill StressValues res_obj = restools.add_von_mises(res_obj) - # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear - res_obj = restools.add_principal_stress(res_obj) + if res_obj.getParentGroup(): + has_reinforced_mat = False + for obj in res_obj.getParentGroup().Group: + if obj.isDerivedFrom('App::MaterialObjectPython') \ + and femutils.is_of_type(obj, 'Fem::MaterialReinforced'): + has_reinforced_mat = True + restools.add_principal_stress_reinforced(res_obj) + break + if has_reinforced_mat is False: + # fill PrincipalMax, PrincipalMed, PrincipalMin, MaxShear + res_obj = restools.add_principal_stress_std(res_obj) # fill Stats res_obj = restools.fill_femresult_stats(res_obj) + else: error_message = ( "We have nodes but no results in frd file, " diff --git a/src/Mod/Fem/femresult/resulttools.py b/src/Mod/Fem/femresult/resulttools.py index f81ff0a628..22eeceba19 100644 --- a/src/Mod/Fem/femresult/resulttools.py +++ b/src/Mod/Fem/femresult/resulttools.py @@ -310,7 +310,7 @@ def add_von_mises(res_obj): return res_obj -def add_principal_stress(res_obj): +def add_principal_stress_std(res_obj): prinstress1 = [] prinstress2 = [] prinstress3 = [] @@ -337,6 +337,165 @@ def add_principal_stress(res_obj): return res_obj +def get_concrete_nodes(res_obj): + + # + # HarryvL: determine concrete / non-concrete nodes + # + + from femmesh.meshtools import get_femnodes_by_refshape + femmesh = res_obj.Mesh.FemMesh + nsr = femmesh.NodeCount # nsr number of stress results + + # ic[iic]: + # ic = flag for material type; iic = node number + # ic = 0: NOT ASSIGNED + # ic = 1: ReinforcedMaterial + # ic = 2: NOT ReinforcedMaterial + ic = np.zeros(nsr) + + for obj in res_obj.getParentGroup().Group: + if obj.isDerivedFrom('App::MaterialObjectPython') \ + and femutils.is_of_type(obj, 'Fem::MaterialReinforced'): + print("ReinforcedMaterial") + if obj.References == []: + for iic in range(nsr): + if ic[iic] == 0: + ic[iic] = 1 + else: + for ref in obj.References: + concrete_nodes = get_femnodes_by_refshape(femmesh, ref) + for cn in concrete_nodes: + ic[cn - 1] = 1 + elif obj.isDerivedFrom('App::MaterialObjectPython') \ + and femutils.is_of_type(obj, 'Fem::Material'): + print("NOT ReinforcedMaterial") + if obj.References == []: + for iic in range(nsr): + if ic[iic] == 0: + ic[iic] = 2 + else: + for ref in obj.References: + non_concrete_nodes = get_femnodes_by_refshape(femmesh, ref) + for ncn in non_concrete_nodes: + ic[ncn - 1] = 2 + return ic + + +def add_principal_stress_reinforced(res_obj): + + # + # HarryvL: determine concrete / non-concrete nodes + # + ic = get_concrete_nodes(res_obj) + + # + # calculate principal and max Shear and fill them in res_obj + # + prinstress1 = [] + prinstress2 = [] + prinstress3 = [] + shearstress = [] + ps1v = [] + ps2v = [] + ps3v = [] + # + # HarryvL: additional arrays to hold reinforcement ratios + # and mohr coulomb stress + # + rhx = [] + rhy = [] + rhz = [] + moc = [] + + # material parameter + for obj in res_obj.getParentGroup().Group: + if femutils.is_of_type(obj, 'Fem::MaterialReinforced'): + matrix_af = float( + FreeCAD.Units.Quantity(obj.Material['AngleOfFriction']).getValueAs('rad') + ) + matrix_cs = float( + FreeCAD.Units.Quantity(obj.Material['CompressiveStrength']).getValueAs('MPa') + ) + reinforce_yield = float( + FreeCAD.Units.Quantity(obj.Reinforcement['YieldStrength']).getValueAs('MPa') + ) + # print(matrix_af) + # print(matrix_cs) + # print(reinforce_yield) + + iterator = zip( + res_obj.NodeStressXX, + res_obj.NodeStressYY, + res_obj.NodeStressZZ, + res_obj.NodeStressXY, + res_obj.NodeStressXZ, + res_obj.NodeStressYZ + ) + for isv, stress_tensor in enumerate(iterator): + + rhox = 0. + rhoy = 0. + rhoz = 0. + mc = 0. + + if ic[isv] == 1: + # + # HarryvL: for concrete scxx etc. are affected by + # reinforcement (see calculate_rho(stress_tensor)). for all other + # materials scxx etc. are the original stresses + # + rhox, rhoy, rhoz = calculate_rho( + stress_tensor, + reinforce_yield + ) + + prin1, prin2, prin3, shear, psv = calculate_principal_stress_reinforced( + stress_tensor + ) + + prinstress1.append(prin1) + prinstress2.append(prin2) + prinstress3.append(prin3) + shearstress.append(shear) + ps1v.append(psv[0]) + ps2v.append(psv[1]) + ps3v.append(psv[2]) + + # + # reinforcement ratios and mohr coulomb criterion + # + rhx.append(rhox) + rhy.append(rhoy) + rhz.append(rhoz) + if ic[isv] == 1: + mc = calculate_mohr_coulomb(prin1, prin3, matrix_af, matrix_cs) + moc.append(mc) + + res_obj.PrincipalMax = prinstress1 + res_obj.PrincipalMed = prinstress2 + res_obj.PrincipalMin = prinstress3 + res_obj.MaxShear = shearstress + # + # HarryvL: additional concrete and principal stress plot + # results for use in _ViewProviderFemResultMechanical + # + res_obj.ReinforcementRatio_x = rhx + res_obj.ReinforcementRatio_y = rhy + res_obj.ReinforcementRatio_z = rhz + res_obj.MohrCoulomb = moc + + res_obj.PS1Vector = ps1v + res_obj.PS2Vector = ps2v + res_obj.PS3Vector = ps3v + + FreeCAD.Console.PrintMessage( + 'Added principal stress and max shear values as well as' + 'reinforcment rations, Mohr Coloumb values.\n' + ) + return res_obj + + def compact_result(res_obj): ''' compacts result.Mesh and appropriate result.NodeNumbers diff --git a/src/Mod/Fem/femsolver/calculix/tasks.py b/src/Mod/Fem/femsolver/calculix/tasks.py index 8dbd07c246..d51c26d961 100644 --- a/src/Mod/Fem/femsolver/calculix/tasks.py +++ b/src/Mod/Fem/femsolver/calculix/tasks.py @@ -184,9 +184,14 @@ class _Container(object): # get member # materials - self.materials_linear = self.get_several_member( + std_mats = self.get_several_member( 'Fem::Material' ) + rei_mats = self.get_several_member( + 'Fem::MaterialReinforced' + ) + self.materials_linear = std_mats + rei_mats + self.materials_nonlinear = self.get_several_member( 'Fem::MaterialMechanicalNonlinear' ) diff --git a/src/Mod/Fem/femtools/ccxtools.py b/src/Mod/Fem/femtools/ccxtools.py index 5f26c6d440..52b21ae78b 100644 --- a/src/Mod/Fem/femtools/ccxtools.py +++ b/src/Mod/Fem/femtools/ccxtools.py @@ -223,7 +223,10 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): ## @var materials_linear # list of linear materials from the analysis. Updated with update_objects - self.materials_linear = self._get_several_member('Fem::Material') + self.materials_linear = ( + self._get_several_member('Fem::Material') + + self._get_several_member('Fem::MaterialReinforced') + ) ## @var materials_nonlinear # list of nonlinear materials from the analysis. Updated with update_objects self.materials_nonlinear = self._get_several_member('Fem::MaterialMechanicalNonlinear') From 7cd6ea884b6fdf2abfa7acee0e44e55f719fdd7c Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:17 +0200 Subject: [PATCH 08/13] FEM: add reinforced concrete 2D wall example --- src/Mod/Fem/CMakeLists.txt | 2 + src/Mod/Fem/femexamples/manager.py | 17 + .../meshes/mesh_rc_wall_2d_tria6.py | 1343 +++++++++++++++++ src/Mod/Fem/femexamples/rc_wall_2d.py | 165 ++ 4 files changed, 1527 insertions(+) create mode 100644 src/Mod/Fem/femexamples/meshes/mesh_rc_wall_2d_tria6.py create mode 100644 src/Mod/Fem/femexamples/rc_wall_2d.py diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 38aab6b7c5..4507fb1ce4 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -36,11 +36,13 @@ SET(FemExamples_SRCS femexamples/__init__.py femexamples/ccx_cantilever_std.py femexamples/manager.py + femexamples/rc_wall_2d.py ) SET(FemExampleMeshes_SRCS femexamples/meshes/__init__.py femexamples/meshes/mesh_canticcx_tetra10.py + femexamples/meshes/mesh_rc_wall_2d_tria6.py ) SET(FemInOut_SRCS diff --git a/src/Mod/Fem/femexamples/manager.py b/src/Mod/Fem/femexamples/manager.py index 0d9eecf32b..3d54e1a8d6 100644 --- a/src/Mod/Fem/femexamples/manager.py +++ b/src/Mod/Fem/femexamples/manager.py @@ -75,6 +75,7 @@ def run_all(): run_ccx_cantileverfaceload() run_ccx_cantilevernodeload() run_ccx_cantileverprescribeddisplacement() + run_rcwall2d() def run_ccx_cantileverfaceload(solver=None, base_name=None): @@ -119,6 +120,20 @@ def run_ccx_cantileverprescribeddisplacement(solver=None, base_name=None): return doc +def run_rcwall2d(solver=None, base_name=None): + + from femexamples.rc_wall_2d import setup_rcwall2d as setup + doc = setup() + + if base_name is None: + base_name = 'RC_FIB_Wall_2D' + if solver is not None: + base_name += ('_' + solver) + run_analysis(doc, base_name) + + return doc + + ''' from femexamples.manager import * @@ -132,4 +147,6 @@ doc = run_ccx_cantilevernodeload('calculix') doc = run_ccx_cantilevernodeload('ccxtools') doc = run_ccx_cantilevernodeload('z88') +doc = run_rcwall2d() + ''' diff --git a/src/Mod/Fem/femexamples/meshes/mesh_rc_wall_2d_tria6.py b/src/Mod/Fem/femexamples/meshes/mesh_rc_wall_2d_tria6.py new file mode 100644 index 0000000000..c257afb5eb --- /dev/null +++ b/src/Mod/Fem/femexamples/meshes/mesh_rc_wall_2d_tria6.py @@ -0,0 +1,1343 @@ +def create_nodes(femmesh): + # nodes + femmesh.addNode(0.0, 0.0, 0.0, 1) + femmesh.addNode(0.0, 2000.0, 0.0, 2) + femmesh.addNode(500.0, 0.0, 0.0, 3) + femmesh.addNode(4000.0, 2000.0, 0.0, 4) + femmesh.addNode(3500.0, 0.0, 0.0, 5) + femmesh.addNode(4000.0, 0.0, 0.0, 6) + femmesh.addNode(0.0, -2000.0, 0.0, 7) + femmesh.addNode(500.0, -2000.0, 0.0, 8) + femmesh.addNode(3500.0, -2000.0, 0.0, 9) + femmesh.addNode(4000.0, -2000.0, 0.0, 10) + femmesh.addNode(0.0, 250.0, 0.0, 11) + femmesh.addNode(0.0, 500.0, 0.0, 12) + femmesh.addNode(0.0, 750.0, 0.0, 13) + femmesh.addNode(0.0, 1000.0, 0.0, 14) + femmesh.addNode(0.0, 1250.0, 0.0, 15) + femmesh.addNode(0.0, 1500.0, 0.0, 16) + femmesh.addNode(0.0, 1750.0, 0.0, 17) + femmesh.addNode(0.0, 125.0, 0.0, 18) + femmesh.addNode(0.0, 375.0, 0.0, 19) + femmesh.addNode(0.0, 625.0, 0.0, 20) + femmesh.addNode(0.0, 875.0, 0.0, 21) + femmesh.addNode(0.0, 1125.0, 0.0, 22) + femmesh.addNode(0.0, 1375.0, 0.0, 23) + femmesh.addNode(0.0, 1625.0, 0.0, 24) + femmesh.addNode(0.0, 1875.0, 0.0, 25) + femmesh.addNode(250.0, 0.0, 0.0, 26) + femmesh.addNode(125.0, 0.0, 0.0, 27) + femmesh.addNode(375.0, 0.0, 0.0, 28) + femmesh.addNode(250.0, 2000.0, 0.0, 29) + femmesh.addNode(500.0, 2000.0, 0.0, 30) + femmesh.addNode(750.0, 2000.0, 0.0, 31) + femmesh.addNode(1000.0, 2000.0, 0.0, 32) + femmesh.addNode(1250.0, 2000.0, 0.0, 33) + femmesh.addNode(1500.0, 2000.0, 0.0, 34) + femmesh.addNode(1750.0, 2000.0, 0.0, 35) + femmesh.addNode(2000.0, 2000.0, 0.0, 36) + femmesh.addNode(2250.0, 2000.0, 0.0, 37) + femmesh.addNode(2500.0, 2000.0, 0.0, 38) + femmesh.addNode(2750.0, 2000.0, 0.0, 39) + femmesh.addNode(3000.0, 2000.0, 0.0, 40) + femmesh.addNode(3250.0, 2000.0, 0.0, 41) + femmesh.addNode(3500.0, 2000.0, 0.0, 42) + femmesh.addNode(3750.0, 2000.0, 0.0, 43) + femmesh.addNode(125.0, 2000.0, 0.0, 44) + femmesh.addNode(375.0, 2000.0, 0.0, 45) + femmesh.addNode(625.0, 2000.0, 0.0, 46) + femmesh.addNode(875.0, 2000.0, 0.0, 47) + femmesh.addNode(1125.0, 2000.0, 0.0, 48) + femmesh.addNode(1375.0, 2000.0, 0.0, 49) + femmesh.addNode(1625.0, 2000.0, 0.0, 50) + femmesh.addNode(1875.0, 2000.0, 0.0, 51) + femmesh.addNode(2125.0, 2000.0, 0.0, 52) + femmesh.addNode(2375.0, 2000.0, 0.0, 53) + femmesh.addNode(2625.0, 2000.0, 0.0, 54) + femmesh.addNode(2875.0, 2000.0, 0.0, 55) + femmesh.addNode(3125.0, 2000.0, 0.0, 56) + femmesh.addNode(3375.0, 2000.0, 0.0, 57) + femmesh.addNode(3625.0, 2000.0, 0.0, 58) + femmesh.addNode(3875.0, 2000.0, 0.0, 59) + femmesh.addNode(750.0, 0.0, 0.0, 60) + femmesh.addNode(1000.0, 0.0, 0.0, 61) + femmesh.addNode(1250.0, 0.0, 0.0, 62) + femmesh.addNode(1500.0, 0.0, 0.0, 63) + femmesh.addNode(1750.0, 0.0, 0.0, 64) + femmesh.addNode(2000.0, 0.0, 0.0, 65) + femmesh.addNode(2250.0, 0.0, 0.0, 66) + femmesh.addNode(2500.0, 0.0, 0.0, 67) + femmesh.addNode(2750.0, 0.0, 0.0, 68) + femmesh.addNode(3000.0, 0.0, 0.0, 69) + femmesh.addNode(3250.0, 0.0, 0.0, 70) + femmesh.addNode(625.0, 0.0, 0.0, 71) + femmesh.addNode(875.0, 0.0, 0.0, 72) + femmesh.addNode(1125.0, 0.0, 0.0, 73) + femmesh.addNode(1375.0, 0.0, 0.0, 74) + femmesh.addNode(1625.0, 0.0, 0.0, 75) + femmesh.addNode(1875.0, 0.0, 0.0, 76) + femmesh.addNode(2125.0, 0.0, 0.0, 77) + femmesh.addNode(2375.0, 0.0, 0.0, 78) + femmesh.addNode(2625.0, 0.0, 0.0, 79) + femmesh.addNode(2875.0, 0.0, 0.0, 80) + femmesh.addNode(3125.0, 0.0, 0.0, 81) + femmesh.addNode(3375.0, 0.0, 0.0, 82) + femmesh.addNode(4000.0, 250.0, 0.0, 83) + femmesh.addNode(4000.0, 500.0, 0.0, 84) + femmesh.addNode(4000.0, 750.0, 0.0, 85) + femmesh.addNode(4000.0, 1000.0, 0.0, 86) + femmesh.addNode(4000.0, 1250.0, 0.0, 87) + femmesh.addNode(4000.0, 1500.0, 0.0, 88) + femmesh.addNode(4000.0, 1750.0, 0.0, 89) + femmesh.addNode(4000.0, 125.0, 0.0, 90) + femmesh.addNode(4000.0, 375.0, 0.0, 91) + femmesh.addNode(4000.0, 625.0, 0.0, 92) + femmesh.addNode(4000.0, 875.0, 0.0, 93) + femmesh.addNode(4000.0, 1125.0, 0.0, 94) + femmesh.addNode(4000.0, 1375.0, 0.0, 95) + femmesh.addNode(4000.0, 1625.0, 0.0, 96) + femmesh.addNode(4000.0, 1875.0, 0.0, 97) + femmesh.addNode(3750.0, 0.0, 0.0, 98) + femmesh.addNode(3625.0, 0.0, 0.0, 99) + femmesh.addNode(3875.0, 0.0, 0.0, 100) + femmesh.addNode(0.0, -1750.0, 0.0, 101) + femmesh.addNode(0.0, -1500.0, 0.0, 102) + femmesh.addNode(0.0, -1250.0, 0.0, 103) + femmesh.addNode(0.0, -1000.0, 0.0, 104) + femmesh.addNode(0.0, -750.0, 0.0, 105) + femmesh.addNode(0.0, -500.0, 0.0, 106) + femmesh.addNode(0.0, -250.0, 0.0, 107) + femmesh.addNode(0.0, -1875.0, 0.0, 108) + femmesh.addNode(0.0, -1625.0, 0.0, 109) + femmesh.addNode(0.0, -1375.0, 0.0, 110) + femmesh.addNode(0.0, -1125.0, 0.0, 111) + femmesh.addNode(0.0, -875.0, 0.0, 112) + femmesh.addNode(0.0, -625.0, 0.0, 113) + femmesh.addNode(0.0, -375.0, 0.0, 114) + femmesh.addNode(0.0, -125.0, 0.0, 115) + femmesh.addNode(250.0, -2000.0, 0.0, 116) + femmesh.addNode(125.0, -2000.0, 0.0, 117) + femmesh.addNode(375.0, -2000.0, 0.0, 118) + femmesh.addNode(500.0, -1750.0, 0.0, 119) + femmesh.addNode(500.0, -1500.0, 0.0, 120) + femmesh.addNode(500.0, -1250.0, 0.0, 121) + femmesh.addNode(500.0, -1000.0, 0.0, 122) + femmesh.addNode(500.0, -750.0, 0.0, 123) + femmesh.addNode(500.0, -500.0, 0.0, 124) + femmesh.addNode(500.0, -250.0, 0.0, 125) + femmesh.addNode(500.0, -1875.0, 0.0, 126) + femmesh.addNode(500.0, -1625.0, 0.0, 127) + femmesh.addNode(500.0, -1375.0, 0.0, 128) + femmesh.addNode(500.0, -1125.0, 0.0, 129) + femmesh.addNode(500.0, -875.0, 0.0, 130) + femmesh.addNode(500.0, -625.0, 0.0, 131) + femmesh.addNode(500.0, -375.0, 0.0, 132) + femmesh.addNode(500.0, -125.0, 0.0, 133) + femmesh.addNode(3500.0, -1750.0, 0.0, 134) + femmesh.addNode(3500.0, -1500.0, 0.0, 135) + femmesh.addNode(3500.0, -1250.0, 0.0, 136) + femmesh.addNode(3500.0, -1000.0, 0.0, 137) + femmesh.addNode(3500.0, -750.0, 0.0, 138) + femmesh.addNode(3500.0, -500.0, 0.0, 139) + femmesh.addNode(3500.0, -250.0, 0.0, 140) + femmesh.addNode(3500.0, -1875.0, 0.0, 141) + femmesh.addNode(3500.0, -1625.0, 0.0, 142) + femmesh.addNode(3500.0, -1375.0, 0.0, 143) + femmesh.addNode(3500.0, -1125.0, 0.0, 144) + femmesh.addNode(3500.0, -875.0, 0.0, 145) + femmesh.addNode(3500.0, -625.0, 0.0, 146) + femmesh.addNode(3500.0, -375.0, 0.0, 147) + femmesh.addNode(3500.0, -125.0, 0.0, 148) + femmesh.addNode(3750.0, -2000.0, 0.0, 149) + femmesh.addNode(3625.0, -2000.0, 0.0, 150) + femmesh.addNode(3875.0, -2000.0, 0.0, 151) + femmesh.addNode(4000.0, -1750.0, 0.0, 152) + femmesh.addNode(4000.0, -1500.0, 0.0, 153) + femmesh.addNode(4000.0, -1250.0, 0.0, 154) + femmesh.addNode(4000.0, -1000.0, 0.0, 155) + femmesh.addNode(4000.0, -750.0, 0.0, 156) + femmesh.addNode(4000.0, -500.0, 0.0, 157) + femmesh.addNode(4000.0, -250.0, 0.0, 158) + femmesh.addNode(4000.0, -1875.0, 0.0, 159) + femmesh.addNode(4000.0, -1625.0, 0.0, 160) + femmesh.addNode(4000.0, -1375.0, 0.0, 161) + femmesh.addNode(4000.0, -1125.0, 0.0, 162) + femmesh.addNode(4000.0, -875.0, 0.0, 163) + femmesh.addNode(4000.0, -625.0, 0.0, 164) + femmesh.addNode(4000.0, -375.0, 0.0, 165) + femmesh.addNode(4000.0, -125.0, 0.0, 166) + femmesh.addNode(1151.2155027143724, 991.1595002148733, 0.0, 167) + femmesh.addNode(2345.552182966278, 992.5521461426597, 0.0, 168) + femmesh.addNode(3153.541159295079, 1199.5398685297591, 0.0, 169) + femmesh.addNode(1750.0, 695.3125, 0.0, 170) + femmesh.addNode(1681.25, 1347.65625, 0.0, 171) + femmesh.addNode(2881.435948455562, 621.2099677847261, 0.0, 172) + femmesh.addNode(606.0449604906953, 635.4082348210767, 0.0, 173) + femmesh.addNode(657.2976568366603, 1353.3222602999324, 0.0, 174) + femmesh.addNode(3445.1692479821986, 652.3366992631719, 0.0, 175) + femmesh.addNode(2674.4322928661404, 1434.2147374924186, 0.0, 176) + femmesh.addNode(2185.539194525211, 1473.115044788804, 0.0, 177) + femmesh.addNode(1273.2425124792012, 510.71781405990015, 0.0, 178) + femmesh.addNode(2215.6598753905773, 520.7910541541594, 0.0, 179) + femmesh.addNode(1115.670904262049, 1485.8186742572047, 0.0, 180) + femmesh.addNode(3519.3278588807784, 1519.3278588807786, 0.0, 181) + femmesh.addNode(388.34501905880387, 1026.9203157654522, 0.0, 182) + femmesh.addNode(3614.4372160624785, 1020.2250489643089, 0.0, 183) + femmesh.addNode(3105.4482841646395, 1593.0462413828066, 0.0, 184) + femmesh.addNode(2818.493830446949, 990.0975624837915, 0.0, 185) + femmesh.addNode(1959.2775916812711, 1064.8265300145413, 0.0, 186) + femmesh.addNode(1546.3069778764673, 1011.232872978363, 0.0, 187) + femmesh.addNode(2591.0841961277283, 363.09805979524884, 0.0, 188) + femmesh.addNode(900.8498339227292, 372.74375656728824, 0.0, 189) + femmesh.addNode(3159.4114197567123, 364.99779587913827, 0.0, 190) + femmesh.addNode(390.87897826169245, 345.62828737063484, 0.0, 191) + femmesh.addNode(413.062332090631, 1650.5023139707077, 0.0, 192) + femmesh.addNode(1599.1990546119257, 331.5972138397307, 0.0, 193) + femmesh.addNode(1495.152113940753, 1619.2944541079414, 0.0, 194) + femmesh.addNode(1863.5454857801321, 1658.2389001513154, 0.0, 195) + femmesh.addNode(778.2580283531327, 931.2966961410348, 0.0, 196) + femmesh.addNode(3674.5511265257346, 338.9844927685506, 0.0, 197) + femmesh.addNode(3172.7789481491654, 832.1374169291745, 0.0, 198) + femmesh.addNode(784.7082624860842, 1653.7264044731728, 0.0, 199) + femmesh.addNode(2554.739497815064, 712.365487790745, 0.0, 200) + femmesh.addNode(1943.1567961046958, 330.9370445232647, 0.0, 201) + femmesh.addNode(981.3704439777061, 695.0014769598008, 0.0, 202) + femmesh.addNode(2453.2517051286445, 1672.8747213645538, 0.0, 203) + femmesh.addNode(907.6249789310948, 1264.8279056360939, 0.0, 204) + femmesh.addNode(1342.8357754800325, 1305.982903143703, 0.0, 205) + femmesh.addNode(301.68045436748366, 1278.0614848964112, 0.0, 206) + femmesh.addNode(321.4019295935336, 712.8743177284927, 0.0, 207) + femmesh.addNode(2426.6601885758864, 1313.9261459477857, 0.0, 208) + femmesh.addNode(2867.9421371538983, 263.92048664402716, 0.0, 209) + femmesh.addNode(2046.149001386518, 725.1823701492324, 0.0, 210) + femmesh.addNode(2854.1111443273658, 1741.083702840498, 0.0, 211) + femmesh.addNode(3695.4452236106526, 1279.177794976091, 0.0, 212) + femmesh.addNode(3685.7292713722686, 751.032843822758, 0.0, 213) + femmesh.addNode(624.8652096522102, 258.70949318509355, 0.0, 214) + femmesh.addNode(1466.6263015417012, 719.2247946131447, 0.0, 215) + femmesh.addNode(3719.1293832862143, 1719.129383286214, 0.0, 216) + femmesh.addNode(2945.872854070339, 1363.49471903432, 0.0, 217) + femmesh.addNode(3344.6356052877895, 1737.2354549848008, 0.0, 218) + femmesh.addNode(1942.1605314429821, 1315.7220947444227, 0.0, 219) + femmesh.addNode(2093.97656761822, 1743.5731735527538, 0.0, 220) + femmesh.addNode(2337.404696236552, 259.86552863747835, 0.0, 221) + femmesh.addNode(1136.4178616265353, 256.9280165667089, 0.0, 222) + femmesh.addNode(3436.9983781650485, 1261.4961473823978, 0.0, 223) + femmesh.addNode(3406.2893160086924, 251.07304786541548, 0.0, 224) + femmesh.addNode(2215.636485028124, 1177.419912858442, 0.0, 225) + femmesh.addNode(1126.6678439977832, 1759.6448940404007, 0.0, 226) + femmesh.addNode(2335.9075546219287, 765.8443516431239, 0.0, 227) + femmesh.addNode(623.3677071526471, 1794.4665663127212, 0.0, 228) + femmesh.addNode(1183.6674808624416, 743.4840698227251, 0.0, 229) + femmesh.addNode(676.4452885380255, 1103.2769600640684, 0.0, 230) + femmesh.addNode(1747.334612316145, 938.7081036305343, 0.0, 231) + femmesh.addNode(1403.1870558121493, 254.37888532175242, 0.0, 232) + femmesh.addNode(3314.847513203245, 987.8243030056708, 0.0, 233) + femmesh.addNode(1640.5623138995034, 1785.4652572759182, 0.0, 234) + femmesh.addNode(2694.302594697601, 1191.5326623293304, 0.0, 235) + femmesh.addNode(3249.075663998931, 1405.1235272166903, 0.0, 236) + femmesh.addNode(3194.7171333591295, 605.4257226147388, 0.0, 237) + femmesh.addNode(3787.3499723629325, 540.6602594003787, 0.0, 238) + femmesh.addNode(185.04426967129564, 1086.6700079903421, 0.0, 239) + femmesh.addNode(3046.934155784866, 1000.6169552050135, 0.0, 240) + femmesh.addNode(1969.4468096267958, 523.2169628726109, 0.0, 241) + femmesh.addNode(2129.5909553861516, 192.09252274746703, 0.0, 242) + femmesh.addNode(1136.6994499219468, 1211.2946783273387, 0.0, 243) + femmesh.addNode(2597.352264247392, 1808.9701221137507, 0.0, 244) + femmesh.addNode(3819.1744978371717, 1088.9949533284503, 0.0, 245) + femmesh.addNode(2584.2256241005716, 935.7579854262561, 0.0, 246) + femmesh.addNode(3125.0, 1815.2509614904245, 0.0, 247) + femmesh.addNode(3777.6248611905694, 1504.537741959381, 0.0, 248) + femmesh.addNode(588.8115450690148, 859.6463157782961, 0.0, 249) + femmesh.addNode(2143.2683627665697, 936.9869149561475, 0.0, 250) + femmesh.addNode(2754.7204686764762, 780.5893488071242, 0.0, 251) + femmesh.addNode(178.93890438705535, 903.482590983227, 0.0, 252) + femmesh.addNode(1747.982107629327, 1148.2128944222316, 0.0, 253) + femmesh.addNode(1666.5850159712468, 1563.4019198648652, 0.0, 254) + femmesh.addNode(851.0519754307722, 1495.0619168135465, 0.0, 255) + femmesh.addNode(3481.0728671542547, 837.1465204467868, 0.0, 256) + femmesh.addNode(2443.601401640797, 530.7979808791658, 0.0, 257) + femmesh.addNode(205.94642509722854, 499.4693567890037, 0.0, 258) + femmesh.addNode(206.07459453719548, 1499.857298977669, 0.0, 259) + femmesh.addNode(834.6180802078031, 567.491198370818, 0.0, 260) + femmesh.addNode(1766.7929131536002, 212.0366200123763, 0.0, 261) + femmesh.addNode(1372.868119293763, 1786.5908878427776, 0.0, 262) + femmesh.addNode(217.93466600459956, 214.41626585864105, 0.0, 263) + femmesh.addNode(211.16821383061668, 1789.0339304012352, 0.0, 264) + femmesh.addNode(1346.4369194052335, 1104.0442859810998, 0.0, 265) + femmesh.addNode(2625.0, 168.47319683138994, 0.0, 266) + femmesh.addNode(875.0000000000001, 168.27854442880616, 0.0, 267) + femmesh.addNode(3124.9999999999995, 166.32624951132104, 0.0, 268) + femmesh.addNode(2725.0455335697234, 531.4266954931735, 0.0, 269) + femmesh.addNode(1522.1536134860664, 504.98683031131714, 0.0, 270) + femmesh.addNode(3802.9015660741943, 197.09843392580635, 0.0, 271) + femmesh.addNode(1505.6503066232626, 1428.2716333977896, 0.0, 272) + femmesh.addNode(1051.6943688460692, 524.3943887245401, 0.0, 273) + femmesh.addNode(3359.4878194613807, 477.16337384383746, 0.0, 274) + femmesh.addNode(1528.4103478357204, 1224.233473320531, 0.0, 275) + femmesh.addNode(3535.438527288789, 1801.7330078935504, 0.0, 276) + femmesh.addNode(434.67162780804375, 542.3401347012916, 0.0, 277) + femmesh.addNode(451.9072533191967, 1434.6301952460099, 0.0, 278) + femmesh.addNode(2981.795085118534, 448.0055367511777, 0.0, 279) + femmesh.addNode(2978.1800808120247, 805.0128289707615, 0.0, 280) + femmesh.addNode(935.1388659912074, 1056.3754597693553, 0.0, 281) + femmesh.addNode(1754.4192556759315, 451.41573980441683, 0.0, 282) + femmesh.addNode(2361.398753416636, 1810.7310101916673, 0.0, 283) + femmesh.addNode(2422.5421676233855, 1516.583426074803, 0.0, 284) + femmesh.addNode(880.47047742822, 1807.7722912938007, 0.0, 285) + femmesh.addNode(630.2325312193318, 1563.618276186015, 0.0, 286) + femmesh.addNode(444.11067943331193, 184.20265254642115, 0.0, 287) + femmesh.addNode(399.0489951122346, 1843.0986785146765, 0.0, 288) + femmesh.addNode(1326.4741772662737, 1564.2672411316362, 0.0, 289) + femmesh.addNode(1873.5987279934327, 1848.0564063658549, 0.0, 290) + femmesh.addNode(2857.8120840696374, 1538.7765004950957, 0.0, 291) + femmesh.addNode(3615.420858496385, 153.92013164518346, 0.0, 292) + femmesh.addNode(1986.4322329809784, 1519.8742672628473, 0.0, 293) + femmesh.addNode(795.7903110696158, 761.2330506728068, 0.0, 294) + femmesh.addNode(3827.887082573013, 916.2471888959267, 0.0, 295) + femmesh.addNode(2931.8289188589665, 1149.0563535164429, 0.0, 296) + femmesh.addNode(3857.0724217345637, 373.58588179238143, 0.0, 297) + femmesh.addNode(1603.8358047155352, 159.6025438347719, 0.0, 298) + femmesh.addNode(2632.697761232849, 1624.134712542077, 0.0, 299) + femmesh.addNode(981.8039384323351, 874.5293213047062, 0.0, 300) + femmesh.addNode(680.2099424162964, 475.33856352911357, 0.0, 301) + femmesh.addNode(3559.7627922855345, 501.8751194940187, 0.0, 302) + femmesh.addNode(974.4233579675891, 1639.6167774462617, 0.0, 303) + femmesh.addNode(495.13513442403405, 1239.242243254375, 0.0, 304) + femmesh.addNode(1377.2739687571882, 899.7018057699061, 0.0, 305) + femmesh.addNode(3867.2823458215535, 1867.2823458215535, 0.0, 306) + femmesh.addNode(3343.8770189511474, 1557.6498333315424, 0.0, 307) + femmesh.addNode(1824.8290135155744, 1476.484523517676, 0.0, 308) + femmesh.addNode(1577.5083720983002, 852.8360153983897, 0.0, 309) + femmesh.addNode(1914.9321930628041, 875.9179316201704, 0.0, 310) + femmesh.addNode(2284.573533854269, 1640.5742507791397, 0.0, 311) + femmesh.addNode(2119.0518265489545, 365.3806225869961, 0.0, 312) + femmesh.addNode(2453.275415073692, 1122.2377705408946, 0.0, 313) + femmesh.addNode(3322.401080864958, 774.4507864829744, 0.0, 314) + femmesh.addNode(666.8714726873429, 1228.2996101820004, 0.0, 315) + femmesh.addNode(792.0351337345601, 1184.052432850081, 0.0, 316) + femmesh.addNode(782.4613178838775, 1309.0750829680132, 0.0, 317) + femmesh.addNode(108.96733300229978, 232.20813292932053, 0.0, 318) + femmesh.addNode(211.94054555091407, 356.9428113238224, 0.0, 319) + femmesh.addNode(102.97321254861427, 374.7346783945019, 0.0, 320) + femmesh.addNode(208.62140418390607, 1644.4456146894522, 0.0, 321) + femmesh.addNode(105.58410691530834, 1769.5169652006175, 0.0, 322) + femmesh.addNode(103.03729726859774, 1624.9286494888345, 0.0, 323) + femmesh.addNode(1854.974854629148, 271.4868322678205, 0.0, 324) + femmesh.addNode(1883.3964565768001, 106.01831000618814, 0.0, 325) + femmesh.addNode(1971.578398052348, 165.46852226163236, 0.0, 326) + femmesh.addNode(2802.055572163683, 1870.541851420249, 0.0, 327) + femmesh.addNode(2927.055572163683, 1870.541851420249, 0.0, 328) + femmesh.addNode(2684.367443781871, 1312.8736999108746, 0.0, 329) + femmesh.addNode(2820.08772438397, 1277.5136906818252, 0.0, 330) + femmesh.addNode(2810.15257346824, 1398.8547282633695, 0.0, 331) + femmesh.addNode(3888.8124305952847, 1377.2688709796905, 0.0, 332) + femmesh.addNode(3736.535042400611, 1391.8577684677362, 0.0, 333) + femmesh.addNode(3847.7226118053263, 1264.5888974880454, 0.0, 334) + femmesh.addNode(3086.4486070855774, 705.2192757927501, 0.0, 335) + femmesh.addNode(2929.8080146337934, 713.1113983777439, 0.0, 336) + femmesh.addNode(3038.0765409073456, 613.3178451997325, 0.0, 337) + femmesh.addNode(2989.555572163683, 1778.1673321654612, 0.0, 338) + femmesh.addNode(3062.5, 1907.6254807452124, 0.0, 339) + femmesh.addNode(2924.8686111362163, 355.96301169760244, 0.0, 340) + femmesh.addNode(2853.420309344129, 489.7161161221756, 0.0, 341) + femmesh.addNode(2796.493835361811, 397.67359106860033, 0.0, 342) + femmesh.addNode(2813.0657567782837, 1170.2945079228866, 0.0, 343) + femmesh.addNode(2938.850886464653, 1256.2755362753815, 0.0, 344) + femmesh.addNode(102.97321254861427, 499.7346783945019, 0.0, 345) + femmesh.addNode(103.03729726859774, 1499.9286494888345, 0.0, 346) + femmesh.addNode(2658.064864848726, 447.26237764421114, 0.0, 347) + femmesh.addNode(2729.5131666408133, 313.509273219638, 0.0, 348) + femmesh.addNode(529.768418730127, 400.5248139431926, 0.0, 349) + femmesh.addNode(412.7753030348681, 443.9842110359632, 0.0, 350) + femmesh.addNode(507.8720939569513, 302.1688902778642, 0.0, 351) + femmesh.addNode(652.5375760342533, 367.0240283571036, 0.0, 352) + femmesh.addNode(557.44078511217, 508.8393491152026, 0.0, 353) + femmesh.addNode(3888.8124305952847, 1502.2688709796905, 0.0, 354) + femmesh.addNode(2064.7954776930756, 96.04626137373351, 0.0, 355) + femmesh.addNode(2036.3738757454237, 261.51478363536586, 0.0, 356) + femmesh.addNode(983.3614398464106, 1490.4402955353758, 0.0, 357) + femmesh.addNode(879.3384771809335, 1379.9449112248203, 0.0, 358) + femmesh.addNode(1011.6479415965719, 1375.3232899466493, 0.0, 359) + femmesh.addNode(102.97321254861427, 624.7346783945019, 0.0, 360) + femmesh.addNode(263.67417734538105, 606.1718372587482, 0.0, 361) + femmesh.addNode(160.7009647967668, 731.4371588642464, 0.0, 362) + femmesh.addNode(253.87752445233957, 1388.95939193704, 0.0, 363) + femmesh.addNode(103.03729726859774, 1374.9286494888345, 0.0, 364) + femmesh.addNode(150.84022718374183, 1264.0307424482057, 0.0, 365) + femmesh.addNode(2569.482560957818, 824.0617366085005, 0.0, 366) + femmesh.addNode(2460.0665893612504, 850.8011685346901, 0.0, 367) + femmesh.addNode(2445.323526218496, 739.1049197169344, 0.0, 368) + femmesh.addNode(2464.888903533425, 964.155065784458, 0.0, 369) + femmesh.addNode(2340.7298687941034, 879.1982488928918, 0.0, 370) + femmesh.addNode(3748.377122238392, 1611.8335626227977, 0.0, 371) + femmesh.addNode(3888.8124305952847, 1627.2688709796905, 0.0, 372) + femmesh.addNode(3859.564691643107, 1734.564691643107, 0.0, 373) + femmesh.addNode(2200.5878397766674, 1325.2674788236232, 0.0, 374) + femmesh.addNode(2321.1483368020054, 1245.673029403114, 0.0, 375) + femmesh.addNode(2306.0996915505484, 1393.5205953682948, 0.0, 376) + femmesh.addNode(1436.4340596468815, 1893.2954439213888, 0.0, 377) + femmesh.addNode(1506.7152165966331, 1786.028072559348, 0.0, 378) + femmesh.addNode(1570.2811569497517, 1892.7326286379591, 0.0, 379) + femmesh.addNode(2933.971068576949, 131.96024332201358, 0.0, 380) + femmesh.addNode(2808.971068576949, 131.96024332201358, 0.0, 381) + femmesh.addNode(2931.6155167870484, 534.6077522679519, 0.0, 382) + femmesh.addNode(3088.256109238832, 526.7156296829583, 0.0, 383) + femmesh.addNode(2548.487230244763, 1475.3990817836107, 0.0, 384) + femmesh.addNode(2424.601178099636, 1415.2547860112943, 0.0, 385) + femmesh.addNode(2550.5462407210134, 1374.0704417201023, 0.0, 386) + femmesh.addNode(1226.5710106320284, 1661.9560675860184, 0.0, 387) + femmesh.addNode(1349.6711482800183, 1675.429064487207, 0.0, 388) + femmesh.addNode(1249.767981645773, 1773.1178909415892, 0.0, 389) + femmesh.addNode(1022.1622144265208, 1238.0612919817163, 0.0, 390) + femmesh.addNode(1126.185177091998, 1348.5566762922717, 0.0, 391) + femmesh.addNode(805.7920772646164, 1079.8262099167118, 0.0, 392) + femmesh.addNode(921.3819224611511, 1160.6016827027247, 0.0, 393) + femmesh.addNode(1239.7676127009895, 1258.6387907355208, 0.0, 394) + femmesh.addNode(1229.2533398710407, 1395.9007887004539, 0.0, 395) + femmesh.addNode(597.428252779855, 747.5272752996864, 0.0, 396) + femmesh.addNode(455.1067373312742, 786.2603167533944, 0.0, 397) + femmesh.addNode(463.72344504211446, 674.1412762747847, 0.0, 398) + femmesh.addNode(488.57828206390934, 943.2833157718742, 0.0, 399) + femmesh.addNode(354.8734743261688, 869.8973167469724, 0.0, 400) + femmesh.addNode(687.432604826105, 129.35474659254677, 0.0, 401) + femmesh.addNode(562.432604826105, 129.35474659254677, 0.0, 402) + femmesh.addNode(1334.6549763731532, 1435.1250721376696, 0.0, 403) + femmesh.addNode(1221.0725407641612, 1525.0429576944205, 0.0, 404) + femmesh.addNode(1494.389957513884, 612.1058124622309, 0.0, 405) + femmesh.addNode(1636.076806743033, 600.1496651556586, 0.0, 406) + femmesh.addNode(1608.3131507708506, 707.2686473065723, 0.0, 407) + femmesh.addNode(754.1748161337163, 1424.1920885567395, 0.0, 408) + femmesh.addNode(1462.6703346491079, 379.6828578165348, 0.0, 409) + femmesh.addNode(1397.698062982634, 507.8523221856086, 0.0, 410) + femmesh.addNode(1338.2147841456754, 382.5483496908263, 0.0, 411) + femmesh.addNode(378.03677870078866, 627.6072262148921, 0.0, 412) + femmesh.addNode(520.3582941493695, 588.8741847611841, 0.0, 413) + femmesh.addNode(1269.8024587193422, 255.65345094423066, 0.0, 414) + femmesh.addNode(1204.8301870528683, 383.8229153133045, 0.0, 415) + femmesh.addNode(3736.5396218676005, 645.8465516115683, 0.0, 416) + femmesh.addNode(3893.674986181466, 645.3301297001893, 0.0, 417) + femmesh.addNode(3842.8646356861345, 750.516421911379, 0.0, 418) + femmesh.addNode(1638.286434580999, 478.201285057867, 0.0, 419) + femmesh.addNode(1752.2096278379659, 573.3641199022084, 0.0, 420) + femmesh.addNode(3115.2241420823198, 1704.1486014366155, 0.0, 421) + femmesh.addNode(2979.7797142460026, 1667.0649721116524, 0.0, 422) + femmesh.addNode(2653.565027049495, 1529.174725017248, 0.0, 423) + femmesh.addNode(2527.6199644281173, 1570.35906930844, 0.0, 424) + femmesh.addNode(2007.797905506657, 624.1996665109216, 0.0, 425) + femmesh.addNode(2092.5533425086865, 522.0040085133851, 0.0, 426) + femmesh.addNode(2130.9044383885475, 622.9867121516959, 0.0, 427) + femmesh.addNode(1434.010116617258, 1702.9426709753595, 0.0, 428) + femmesh.addNode(1567.8572139201283, 1702.3798556919298, 0.0, 429) + femmesh.addNode(1005.7089308132677, 212.6032804977575, 0.0, 430) + femmesh.addNode(937.5, 84.13927221440308, 0.0, 431) + femmesh.addNode(1068.2089308132677, 128.46400828335445, 0.0, 432) + femmesh.addNode(1121.169374129916, 1622.7317841488027, 0.0, 433) + femmesh.addNode(3297.3178026438945, 1868.6177274924003, 0.0, 434) + femmesh.addNode(3422.3178026438945, 1868.6177274924003, 0.0, 435) + femmesh.addNode(2562.5, 84.23659841569497, 0.0, 436) + femmesh.addNode(2481.202348118276, 214.16936273443415, 0.0, 437) + femmesh.addNode(2418.702348118276, 129.93276431873917, 0.0, 438) + femmesh.addNode(283.64196172292964, 965.2014533743396, 0.0, 439) + femmesh.addNode(250.17041699029448, 808.1784543558599, 0.0, 440) + femmesh.addNode(3566.221800887851, 1270.3369711792443, 0.0, 441) + femmesh.addNode(3525.7177971137635, 1140.8605981733533, 0.0, 442) + femmesh.addNode(3654.9412198365653, 1149.7014219702, 0.0, 443) + femmesh.addNode(3478.1631185229135, 1390.4120031315883, 0.0, 444) + femmesh.addNode(3607.3865412457153, 1399.2528269284348, 0.0, 445) + femmesh.addNode(92.52213483564782, 1168.335003995171, 0.0, 446) + femmesh.addNode(243.36236201938965, 1182.3657464433768, 0.0, 447) + femmesh.addNode(1193.2089308132677, 128.46400828335445, 0.0, 448) + femmesh.addNode(2293.702348118276, 129.93276431873917, 0.0, 449) + femmesh.addNode(2078.898508235553, 1246.5710038014324, 0.0, 450) + femmesh.addNode(2063.8498629840965, 1394.4185697666135, 0.0, 451) + femmesh.addNode(2430.6993767083177, 1905.3655050958337, 0.0, 452) + femmesh.addNode(2479.375508832014, 1809.850566152709, 0.0, 453) + femmesh.addNode(2548.6761321236963, 1904.4850610568753, 0.0, 454) + femmesh.addNode(3617.1569594056346, 420.42980613128464, 0.0, 455) + femmesh.addNode(3483.0260541471134, 376.47408367971707, 0.0, 456) + femmesh.addNode(3540.4202212672135, 295.028770316983, 0.0, 457) + femmesh.addNode(3459.6253058734574, 489.5192466689281, 0.0, 458) + femmesh.addNode(3382.8885677350363, 364.11821085462645, 0.0, 459) + femmesh.addNode(2803.2407410126425, 576.3183316389498, 0.0, 460) + femmesh.addNode(2407.32522927264, 1741.8028657781106, 0.0, 461) + femmesh.addNode(2525.3019846880184, 1740.9224217391522, 0.0, 462) + femmesh.addNode(1117.6809248542554, 633.9392292736327, 0.0, 463) + femmesh.addNode(1162.4684406626352, 517.5561013922202, 0.0, 464) + femmesh.addNode(1228.4549966708214, 627.1009419413126, 0.0, 465) + femmesh.addNode(3075.479514480595, 818.575122949968, 0.0, 466) + femmesh.addNode(3183.7480407541475, 718.7815697719566, 0.0, 467) + femmesh.addNode(3100.2376575399726, 1100.0784118673864, 0.0, 468) + femmesh.addNode(3180.8908344940555, 994.2206291053421, 0.0, 469) + femmesh.addNode(3234.194336249162, 1093.6820857677149, 0.0, 470) + femmesh.addNode(3109.8565519670155, 916.377186067094, 0.0, 471) + femmesh.addNode(3243.8132306762054, 909.9808599674227, 0.0, 472) + femmesh.addNode(89.46945219352767, 826.7412954916135, 0.0, 473) + femmesh.addNode(286.6946443650497, 1056.795161877897, 0.0, 474) + femmesh.addNode(345.0127367131438, 1152.4909003309317, 0.0, 475) + femmesh.addNode(2275.7837150062533, 643.3177028986416, 0.0, 476) + femmesh.addNode(2191.0282780042235, 745.5133608961781, 0.0, 477) + femmesh.addNode(441.740076741419, 1133.0812795099137, 0.0, 478) + femmesh.addNode(398.40779439575886, 1258.651864075393, 0.0, 479) + femmesh.addNode(751.9190922904336, 1801.119428803261, 0.0, 480) + femmesh.addNode(815.23523871411, 1903.8861456469003, 0.0, 481) + femmesh.addNode(686.6838535763236, 1897.2332831563606, 0.0, 482) + femmesh.addNode(1758.3964565768001, 106.01831000618814, 0.0, 483) + femmesh.addNode(1016.5324064118877, 609.6979328421705, 0.0, 484) + femmesh.addNode(1082.5189624200739, 719.242773391263, 0.0, 485) + femmesh.addNode(2304.040681074298, 1494.8492354318034, 0.0, 486) + femmesh.addNode(3453.144658004346, 125.53652393270774, 0.0, 487) + femmesh.addNode(3328.144658004346, 125.53652393270774, 0.0, 488) + femmesh.addNode(3201.308411647005, 1302.3316978732246, 0.0, 489) + femmesh.addNode(3097.474259034635, 1384.3091231255053, 0.0, 490) + femmesh.addNode(3049.707006682709, 1281.5172937820396, 0.0, 491) + femmesh.addNode(3177.2619740817854, 1499.0848842997484, 0.0, 492) + femmesh.addNode(3025.660569117489, 1478.2704802085632, 0.0, 493) + femmesh.addNode(856.6984471721701, 993.836077955195, 0.0, 494) + femmesh.addNode(727.351658445579, 1017.2868281025516, 0.0, 495) + femmesh.addNode(3265.6446580043457, 208.69964868836826, 0.0, 496) + femmesh.addNode(3187.5, 83.16312475566052, 0.0, 497) + femmesh.addNode(534.487944542761, 221.45607286575733, 0.0, 498) + femmesh.addNode(472.05533971665596, 92.10132627321057, 0.0, 499) + femmesh.addNode(2746.471068576949, 216.19684173770855, 0.0, 500) + femmesh.addNode(2687.5, 84.23659841569497, 0.0, 501) + femmesh.addNode(3893.674986181466, 520.3301297001893, 0.0, 502) + femmesh.addNode(2608.042098063864, 265.7856283133194, 0.0, 503) + femmesh.addNode(3062.5, 83.16312475566052, 0.0, 504) + femmesh.addNode(2996.4710685769487, 215.12336807767412, 0.0, 505) + femmesh.addNode(3142.205709878356, 265.66202269522967, 0.0, 506) + femmesh.addNode(3013.6767784553053, 314.4591412615827, 0.0, 507) + femmesh.addNode(887.9249169613647, 270.5111504980472, 0.0, 508) + femmesh.addNode(1018.6338477746323, 314.83588656699857, 0.0, 509) + femmesh.addNode(3384.2017614398546, 1462.2256930487345, 0.0, 510) + femmesh.addNode(3343.0370210819897, 1333.3098372995441, 0.0, 511) + femmesh.addNode(2560.481391636744, 1252.729404138558, 0.0, 512) + femmesh.addNode(3431.602438915963, 1538.4888461061605, 0.0, 513) + femmesh.addNode(3296.476341475039, 1481.3866802741163, 0.0, 514) + femmesh.addNode(2464.24444618214, 311.4817942163636, 0.0, 515) + femmesh.addNode(2087.4570383546975, 1121.1232214364918, 0.0, 516) + femmesh.addNode(1950.7190615621266, 1190.2743123794821, 0.0, 517) + femmesh.addNode(2399.413799019985, 1057.394958341777, 0.0, 518) + femmesh.addNode(2334.4559500509076, 1149.8288416996684, 0.0, 519) + femmesh.addNode(2280.594333997201, 1084.986029500551, 0.0, 520) + femmesh.addNode(1325.1468912020714, 731.3544322179349, 0.0, 521) + femmesh.addNode(1369.9344070104512, 614.9713043365224, 0.0, 522) + femmesh.addNode(561.6838535763236, 1897.2332831563606, 0.0, 523) + femmesh.addNode(3756.8081769726405, 833.6400163593423, 0.0, 524) + femmesh.addNode(3721.1621493177454, 968.2361189301178, 0.0, 525) + femmesh.addNode(3650.0832437173735, 885.6289463935334, 0.0, 526) + femmesh.addNode(2439.967801824789, 1218.08195824434, 0.0, 527) + femmesh.addNode(3070.6032524376233, 406.501666315158, 0.0, 528) + femmesh.addNode(3440.037066288289, 1769.4842314391756, 0.0, 529) + femmesh.addNode(3517.7192636443942, 1900.866503946775, 0.0, 530) + femmesh.addNode(2046.98828380911, 1871.786586776377, 0.0, 531) + femmesh.addNode(2171.98828380911, 1871.786586776377, 0.0, 532) + femmesh.addNode(312.1152729606238, 1719.7681221859716, 0.0, 533) + femmesh.addNode(309.56846331391324, 1575.1798064741884, 0.0, 534) + femmesh.addNode(304.406822133146, 280.0222766146379, 0.0, 535) + femmesh.addNode(298.4127016794605, 422.5488220798193, 0.0, 536) + femmesh.addNode(3375.9229456841467, 1124.6602251940344, 0.0, 537) + femmesh.addNode(3464.6423646328617, 1004.0246759849899, 0.0, 538) + femmesh.addNode(3295.269768730064, 1230.5180079560785, 0.0, 539) + femmesh.addNode(1747.658359972736, 1043.4604990263829, 0.0, 540) + femmesh.addNode(1647.144542752897, 1079.7228837002972, 0.0, 541) + femmesh.addNode(1646.820795096306, 974.9704883044487, 0.0, 542) + femmesh.addNode(832.589369957152, 1730.7493478834867, 0.0, 543) + femmesh.addNode(704.0379848193656, 1724.096485392947, 0.0, 544) + femmesh.addNode(3642.7192636443942, 1900.866503946775, 0.0, 545) + femmesh.addNode(3627.2839552875016, 1760.4311955898822, 0.0, 546) + femmesh.addNode(3734.564691643107, 1859.564691643107, 0.0, 547) + femmesh.addNode(3757.309860723912, 1184.0863741522708, 0.0, 548) + femmesh.addNode(3909.587248918586, 1169.4974766642251, 0.0, 549) + femmesh.addNode(1045.047131114819, 1562.7177258517331, 0.0, 550) + femmesh.addNode(912.7376666991806, 1567.3393471299041, 0.0, 551) + femmesh.addNode(632.6284168035202, 981.4616379211823, 0.0, 552) + femmesh.addNode(532.3951537984146, 1065.0986379147603, 0.0, 553) + femmesh.addNode(683.5347867110737, 895.4715059596654, 0.0, 554) + femmesh.addNode(2517.3427988842627, 446.94802033720737, 0.0, 555) + femmesh.addNode(2390.5030489386745, 395.33175475832206, 0.0, 556) + femmesh.addNode(2329.630638515687, 525.7945175166626, 0.0, 557) + femmesh.addNode(2276.5322858135646, 390.32829139581884, 0.0, 558) + femmesh.addNode(1638.1962277325238, 1186.2231838713813, 0.0, 559) + femmesh.addNode(1537.3586628560938, 1117.7331731494469, 0.0, 560) + femmesh.addNode(1859.7234048133978, 609.2647314363055, 0.0, 561) + femmesh.addNode(1898.0745006932589, 710.2474350746162, 0.0, 562) + femmesh.addNode(3648.4763600356737, 1511.9328004200797, 0.0, 563) + femmesh.addNode(1326.5935279060745, 127.18944266087621, 0.0, 564) + femmesh.addNode(3282.8503678827024, 308.03542187227686, 0.0, 565) + femmesh.addNode(1980.540597224661, 800.5501508847015, 0.0, 566) + femmesh.addNode(1832.466096531402, 785.6152158100851, 0.0, 567) + femmesh.addNode(3502.4660201338666, 577.1059093785952, 0.0, 568) + femmesh.addNode(3622.7460318289013, 626.4539816583883, 0.0, 569) + femmesh.addNode(3565.4492596772334, 701.6847715429649, 0.0, 570) + femmesh.addNode(3527.3831930847837, 1660.5304333871645, 0.0, 571) + femmesh.addNode(3619.2286210834964, 1619.2286210834964, 0.0, 572) + femmesh.addNode(1560.676334048996, 418.29202207552396, 0.0, 573) + femmesh.addNode(1501.1930552120375, 292.9880495807416, 0.0, 574) + femmesh.addNode(749.9326048261051, 213.49401880694984, 0.0, 575) + femmesh.addNode(762.8575217874698, 315.7266248761909, 0.0, 576) + femmesh.addNode(812.5, 84.13927221440308, 0.0, 577) + femmesh.addNode(3431.981732084284, 1628.2816569327897, 0.0, 578) + femmesh.addNode(2044.249318087875, 444.2987927298035, 0.0, 579) + femmesh.addNode(2167.355850969766, 443.08583837057773, 0.0, 580) + femmesh.addNode(2673.6761321236963, 1904.4850610568753, 0.0, 581) + femmesh.addNode(2725.731704287379, 1775.0269124771244, 0.0, 582) + femmesh.addNode(108.96733300229978, 107.20813292932053, 0.0, 583) + femmesh.addNode(233.96733300229977, 107.20813292932053, 0.0, 584) + femmesh.addNode(105.58410691530834, 1894.5169652006175, 0.0, 585) + femmesh.addNode(230.58410691530833, 1894.5169652006175, 0.0, 586) + femmesh.addNode(2855.9616141985016, 1639.9301016677969, 0.0, 587) + femmesh.addNode(2981.6301841171385, 1565.9113709389512, 0.0, 588) + femmesh.addNode(521.6474316549813, 1607.0602950783614, 0.0, 589) + femmesh.addNode(626.8001191859894, 1679.042421249368, 0.0, 590) + femmesh.addNode(518.215019621639, 1722.4844401417145, 0.0, 591) + femmesh.addNode(1063.3339219988916, 1879.8224470202003, 0.0, 592) + femmesh.addNode(1188.3339219988916, 1879.8224470202003, 0.0, 593) + femmesh.addNode(1848.7880258903137, 391.1763921638408, 0.0, 594) + femmesh.addNode(1760.606084414766, 331.72617990839655, 0.0, 595) + femmesh.addNode(3547.755041608367, 928.6857847055478, 0.0, 596) + femmesh.addNode(3583.401069263262, 794.0896821347724, 0.0, 597) + femmesh.addNode(3463.1210575682267, 744.7416098549793, 0.0, 598) + femmesh.addNode(3716.8058569498253, 1054.6100011463795, 0.0, 599) + femmesh.addNode(417.49482884750216, 264.915469958528, 0.0, 600) + femmesh.addNode(1410.8131456035135, 1591.7808476197888, 0.0, 601) + femmesh.addNode(2639.264109399086, 1063.6453238777933, 0.0, 602) + femmesh.addNode(2701.35972727376, 962.9277739550239, 0.0, 603) + femmesh.addNode(2756.398212572275, 1090.815112406561, 0.0, 604) + femmesh.addNode(1924.9888593805554, 1589.0565837070812, 0.0, 605) + femmesh.addNode(2040.2044002995992, 1631.7237204078006, 0.0, 606) + femmesh.addNode(1978.761026699176, 1700.9060368520345, 0.0, 607) + femmesh.addNode(541.0698922692643, 1499.1242357160124, 0.0, 608) + femmesh.addNode(432.48479270491384, 1542.5662546083588, 0.0, 609) + femmesh.addNode(347.05533971665596, 92.10132627321057, 0.0, 610) + femmesh.addNode(331.02267271895573, 199.30945920253112, 0.0, 611) + femmesh.addNode(1451.5935279060745, 127.18944266087621, 0.0, 612) + femmesh.addNode(1663.7541860491501, 774.0742576991948, 0.0, 613) + femmesh.addNode(1522.0673368200007, 786.0304050057672, 0.0, 614) + femmesh.addNode(790.5298881695128, 424.04116004820094, 0.0, 615) + femmesh.addNode(2085.9857137530944, 1496.4946560258256, 0.0, 616) + femmesh.addNode(2139.7578810717155, 1608.344109170779, 0.0, 617) + femmesh.addNode(3913.9435412865064, 833.1235944479633, 0.0, 618) + femmesh.addNode(1695.2811569497517, 1892.7326286379591, 0.0, 619) + femmesh.addNode(2898.3369556294865, 897.5551957272764, 0.0, 620) + femmesh.addNode(3012.5571182984454, 902.8148920878875, 0.0, 621) + femmesh.addNode(2932.713993115907, 995.3572588444025, 0.0, 622) + femmesh.addNode(1983.7876478058265, 1795.8147899593043, 0.0, 623) + femmesh.addNode(1868.5721068867824, 1753.1476532585853, 0.0, 624) + femmesh.addNode(3823.530790205092, 1002.6210711121885, 0.0, 625) + femmesh.addNode(2542.9747331807466, 1648.5047169533154, 0.0, 626) + femmesh.addNode(2437.896936376015, 1594.7290737196784, 0.0, 627) + femmesh.addNode(1936.7993639967162, 1924.0282031829274, 0.0, 628) + femmesh.addNode(3042.685039077023, 1174.298111023101, 0.0, 629) + femmesh.addNode(2573.789004885646, 1156.8852164351124, 0.0, 630) + femmesh.addNode(2518.7505195871317, 1028.9978779835753, 0.0, 631) + femmesh.addNode(1845.0713195361545, 1231.9674945833272, 0.0, 632) + femmesh.addNode(1853.629849655299, 1106.5197122183863, 0.0, 633) + femmesh.addNode(1714.6160538146635, 1247.9345722111157, 0.0, 634) + femmesh.addNode(1811.705265721491, 1331.6891723722115, 0.0, 635) + femmesh.addNode(1094.0561152363023, 390.6612026456245, 0.0, 636) + femmesh.addNode(976.2721013843992, 448.56907264591416, 0.0, 637) + femmesh.addNode(92.52213483564782, 1043.335003995171, 0.0, 638) + femmesh.addNode(3933.6411729107767, 1808.6411729107767, 0.0, 639) + femmesh.addNode(3793.2058645538837, 1793.2058645538837, 0.0, 640) + femmesh.addNode(3808.6411729107767, 1933.6411729107767, 0.0, 641) + femmesh.addNode(2866.4502747442502, 792.8010888889428, 0.0, 642) + femmesh.addNode(2786.6071495617125, 885.3434556454579, 0.0, 643) + femmesh.addNode(3901.450783037097, 98.54921696290317, 0.0, 644) + femmesh.addNode(3776.450783037097, 98.54921696290317, 0.0, 645) + femmesh.addNode(3901.450783037097, 223.5492169629032, 0.0, 646) + femmesh.addNode(3187.5, 1907.6254807452124, 0.0, 647) + femmesh.addNode(3234.8178026438945, 1776.2432082376126, 0.0, 648) + femmesh.addNode(3225.0419447262148, 1665.1408481838037, 0.0, 649) + femmesh.addNode(2179.4524238973468, 1057.2034139072948, 0.0, 650) + femmesh.addNode(2244.410272866424, 964.7695305494036, 0.0, 651) + femmesh.addNode(1676.8091551439286, 391.50647682207375, 0.0, 652) + femmesh.addNode(1682.995983882763, 271.8169169260535, 0.0, 653) + femmesh.addNode(3909.587248918586, 1044.4974766642251, 0.0, 654) + femmesh.addNode(181.9915870291755, 995.0762994867846, 0.0, 655) + femmesh.addNode(3344.2563121194685, 1647.4426441581716, 0.0, 656) + femmesh.addNode(2233.4978258113515, 225.9790256924727, 0.0, 657) + femmesh.addNode(2189.7954776930756, 96.04626137373351, 0.0, 658) + femmesh.addNode(2901.8424690699885, 1451.1356097647079, 0.0, 659) + femmesh.addNode(2051.2729772239204, 1000.9067224853444, 0.0, 660) + femmesh.addNode(2389.7544781313627, 648.3211662611449, 0.0, 661) + femmesh.addNode(2499.1704497279306, 621.5817343349554, 0.0, 662) + femmesh.addNode(3177.064276557921, 485.2117592469385, 0.0, 663) + femmesh.addNode(940.23523871411, 1903.8861456469003, 0.0, 664) + femmesh.addNode(1003.5691607130016, 1783.7085926671007, 0.0, 665) + femmesh.addNode(3224.6626515578937, 1575.3480373571745, 0.0, 666) + femmesh.addNode(2766.122188467889, 1486.495618993757, 0.0, 667) + femmesh.addNode(3673.5563823242337, 521.2676894471987, 0.0, 668) + femmesh.addNode(2228.228261392753, 312.62307561223724, 0.0, 669) + femmesh.addNode(2305.6993767083177, 1905.3655050958337, 0.0, 670) + femmesh.addNode(1311.4340596468815, 1893.2954439213888, 0.0, 671) + femmesh.addNode(2875.1613746529574, 1069.5769580001172, 0.0, 672) + femmesh.addNode(2639.8925156923938, 621.8960916419592, 0.0, 673) + femmesh.addNode(2739.8830011231, 656.0080221501489, 0.0, 674) + femmesh.addNode(2654.72998324577, 746.4774182989346, 0.0, 675) + femmesh.addNode(1883.4947724792783, 1396.1033091310494, 0.0, 676) + femmesh.addNode(1753.0395067577872, 1412.0703867588381, 0.0, 677) + femmesh.addNode(1964.2963822119802, 1417.798181003635, 0.0, 678) + femmesh.addNode(2239.587958694249, 851.4156332996357, 0.0, 679) + femmesh.addNode(2094.708682076544, 831.08464255269, 0.0, 680) + femmesh.addNode(2235.0563641897397, 1556.8446477839718, 0.0, 681) + femmesh.addNode(2189.2750507362443, 1692.0737121659467, 0.0, 682) + femmesh.addNode(1477.3911704277443, 876.2689105841479, 0.0, 683) + femmesh.addNode(1421.9501351494446, 809.4633001915254, 0.0, 684) + femmesh.addNode(1561.9076749873839, 932.0344441883764, 0.0, 685) + femmesh.addNode(1461.7904733168277, 955.4673393741346, 0.0, 686) + femmesh.addNode(1035.919157956577, 1133.8350690483471, 0.0, 687) + femmesh.addNode(1043.17718435279, 1023.7674799921143, 0.0, 688) + femmesh.addNode(1143.9574763181595, 1101.227089271106, 0.0, 689) + femmesh.addNode(2227.687660517428, 1777.1520918722106, 0.0, 690) + femmesh.addNode(2818.0782085660194, 700.8996582959252, 0.0, 691) + femmesh.addNode(3510.8550872525384, 202.49658975529945, 0.0, 692) + femmesh.addNode(3644.9859925110595, 246.45231220686702, 0.0, 693) + femmesh.addNode(3557.7104292481927, 76.96006582259173, 0.0, 694) + femmesh.addNode(1066.5097205733537, 932.8444107597898, 0.0, 695) + femmesh.addNode(1082.7357096473884, 809.0066955637157, 0.0, 696) + femmesh.addNode(1167.441491788407, 867.3217850187992, 0.0, 697) + femmesh.addNode(981.5871912050206, 784.7653991322535, 0.0, 698) + femmesh.addNode(927.4469176979046, 1723.6945343700313, 0.0, 699) + femmesh.addNode(1050.5456009826862, 1699.6308357433313, 0.0, 700) + femmesh.addNode(585.7902114810297, 1171.2596016592215, 0.0, 701) + femmesh.addNode(888.7971247509754, 817.8811859887564, 0.0, 702) + femmesh.addNode(888.5803775236609, 728.1172638163039, 0.0, 703) + femmesh.addNode(3259.4496196090467, 421.08058486148786, 0.0, 704) + femmesh.addNode(2989.3815373219163, 1074.836654360728, 0.0, 705) + femmesh.addNode(1861.9330326513636, 487.31635133851387, 0.0, 706) + femmesh.addNode(1956.3018028657457, 427.0770036979378, 0.0, 707) + femmesh.addNode(643.1274514534958, 555.3733991750951, 0.0, 708) + femmesh.addNode(2031.1043113268252, 348.1588335551304, 0.0, 709) + femmesh.addNode(1280.4707248098148, 821.5929377963156, 0.0, 710) + femmesh.addNode(1264.2447357357803, 945.4306529923897, 0.0, 711) + femmesh.addNode(89.46945219352767, 951.7412954916135, 0.0, 712) + femmesh.addNode(2743.4044527801075, 1682.6092076912876, 0.0, 713) + femmesh.addNode(2745.2549226512433, 1581.4556065185864, 0.0, 714) + femmesh.addNode(880.0309833927339, 902.9130087228705, 0.0, 715) + femmesh.addNode(787.0241697113743, 846.2648734069207, 0.0, 716) + femmesh.addNode(1676.9179023577676, 79.80127191738595, 0.0, 717) + femmesh.addNode(1551.9179023577676, 79.80127191738595, 0.0, 718) + femmesh.addNode(1831.1334026894747, 907.3130176253524, 0.0, 719) + femmesh.addNode(1748.6673061580725, 817.0103018152672, 0.0, 720) + femmesh.addNode(879.5658102268367, 1646.6715909597174, 0.0, 721) + femmesh.addNode(817.8801189584283, 1574.3941606433596, 0.0, 722) + femmesh.addNode(1437.423633620477, 1164.1388796508154, 0.0, 723) + femmesh.addNode(1435.6230616578764, 1265.1081882321168, 0.0, 724) + femmesh.addNode(1344.636347442633, 1205.0135945624015, 0.0, 725) + femmesh.addNode(1446.3719486408504, 1057.6385794797316, 0.0, 726) + femmesh.addNode(1853.306101998708, 1001.7673168225379, 0.0, 727) + femmesh.addNode(2669.473046388524, 858.1736671166902, 0.0, 728) + femmesh.addNode(943.1562245269362, 545.942793547679, 0.0, 729) + femmesh.addNode(867.7339570652662, 470.11747746905314, 0.0, 730) + femmesh.addNode(907.9942620927546, 631.2463376653094, 0.0, 731) + femmesh.addNode(324.5244975561173, 1921.5493392573383, 0.0, 732) + femmesh.addNode(449.5244975561173, 1921.5493392573383, 0.0, 733) + femmesh.addNode(3247.590014507062, 803.2941017060745, 0.0, 734) + femmesh.addNode(3318.624297034102, 881.1375447443227, 0.0, 735) + femmesh.addNode(1937.1048923720377, 970.3722308173558, 0.0, 736) + femmesh.addNode(2029.100277914687, 906.452423288159, 0.0, 737) + femmesh.addNode(1653.573664935375, 1674.4335885703917, 0.0, 738) + femmesh.addNode(1765.0652508756893, 1610.8204100080902, 0.0, 739) + femmesh.addNode(1752.0538998398179, 1721.8520787136167, 0.0, 740) + femmesh.addNode(2584.3234676052602, 531.1123381861696, 0.0, 741) + femmesh.addNode(3397.96019017875, 912.4854117262288, 0.0, 742) + femmesh.addNode(3913.9435412865064, 958.1235944479633, 0.0, 743) + femmesh.addNode(1580.8685649559998, 1591.3481869864033, 0.0, 744) + femmesh.addNode(511.20835113244084, 1818.7826224136988, 0.0, 745) + femmesh.addNode(406.0556636014328, 1746.8004962426921, 0.0, 746) + femmesh.addNode(1757.080520946468, 1816.7608318208866, 0.0, 747) + femmesh.addNode(1811.7993639967162, 1924.0282031829274, 0.0, 748) + femmesh.addNode(707.4703968527081, 1608.672340329594, 0.0, 749) + femmesh.addNode(2124.3213909675533, 278.73657266723154, 0.0, 750) + femmesh.addNode(3933.6411729107767, 1933.6411729107767, 0.0, 751) + femmesh.addNode(3682.7104292481927, 76.96006582259173, 0.0, 752) + femmesh.addNode(1361.8554440812109, 1001.873045875503, 0.0, 753) + femmesh.addNode(1248.826211059803, 1047.6018930979867, 0.0, 754) + femmesh.addNode(1241.5681846635903, 1157.6694821542192, 0.0, 755) + femmesh.addNode(1604.83017391786, 1285.9448616602654, 0.0, 756) + femmesh.addNode(1517.0303272294914, 1326.2525533591602, 0.0, 757) + femmesh.addNode(1593.4501533116313, 1387.9639416988948, 0.0, 758) + femmesh.addNode(1424.2430410516477, 1367.1272682707463, 0.0, 759) + femmesh.addNode(815.2041956387095, 664.3621245218123, 0.0, 760) + femmesh.addNode(3928.5362108672816, 436.7929408961907, 0.0, 761) + femmesh.addNode(3928.5362108672816, 311.7929408961907, 0.0, 762) + femmesh.addNode(3402.3285337217894, 564.7500365535047, 0.0, 763) + femmesh.addNode(3401.7369740096065, 805.7986534648805, 0.0, 764) + femmesh.addNode(1662.4214922072226, 895.772059514462, 0.0, 765) + femmesh.addNode(3277.102476410255, 541.2945482292881, 0.0, 766) + femmesh.addNode(3319.943190670664, 628.8812109389553, 0.0, 767) + femmesh.addNode(757.4140113120498, 521.4148809499658, 0.0, 768) + femmesh.addNode(643.765094027996, 1458.4702682429738, 0.0, 769) + femmesh.addNode(554.6024550779284, 1393.976227772971, 0.0, 770) + femmesh.addNode(1685.3143589345677, 185.8195819235741, 0.0, 771) + femmesh.addNode(1503.5114302638422, 206.99071457826216, 0.0, 772) + femmesh.addNode(1601.5174296637306, 245.5998788372513, 0.0, 773) + femmesh.addNode(376.7938538433402, 1356.3458400712107, 0.0, 774) + femmesh.addNode(328.9909239281961, 1467.2437471118394, 0.0, 775) + femmesh.addNode(320.30902645263615, 520.9047457451477, 0.0, 776) + femmesh.addNode(576.2163956303472, 1296.2822517771538, 0.0, 777) + femmesh.addNode(2615.0250127401205, 1716.5524173279139, 0.0, 778) + femmesh.addNode(740.642253325052, 1529.3400964997809, 0.0, 779) + femmesh.addNode(305.1086044714256, 1816.066304457956, 0.0, 780) + femmesh.addNode(3765.8117741301494, 356.285187280466, 0.0, 781) + femmesh.addNode(3822.211197048748, 457.12307059638005, 0.0, 782) + femmesh.addNode(3730.950549444334, 439.8223760844646, 0.0, 783) + femmesh.addNode(1586.1176612972547, 1495.8367766313274, 0.0, 784) + femmesh.addNode(1673.9175079856234, 1455.5290849324326, 0.0, 785) + femmesh.addNode(1500.401210282008, 1523.7830437528655, 0.0, 786) + femmesh.addNode(1416.0622419447682, 1496.269437264713, 0.0, 787) + femmesh.addNode(692.3009280693152, 810.4396832255514, 0.0, 788) + femmesh.addNode(700.9176357801555, 698.3206427469418, 0.0, 789) + femmesh.addNode(3383.7851644235784, 713.3937428730732, 0.0, 790) + femmesh.addNode(3258.559107112044, 689.9382545488565, 0.0, 791) + femmesh.addNode(958.4714022117712, 965.4523905370307, 0.0, 792) + femmesh.addNode(1745.7070147434106, 1519.9432216912705, 0.0, 793) + femmesh.addNode(1844.1872496478532, 1567.3617118344957, 0.0, 794) + femmesh.addNode(3709.1612122852894, 175.50928278549492, 0.0, 795) + femmesh.addNode(473.52119387161537, 1336.9362192501924, 0.0, 796) + femmesh.addNode(720.3315203492492, 601.4497165959474, 0.0, 797) + femmesh.addNode(3829.9869939043792, 285.3421578590939, 0.0, 798) + femmesh.addNode(3738.7263462999645, 268.0414633471785, 0.0, 799) + femmesh.addNode(1905.6306232482764, 1498.1793953902616, 0.0, 800) + femmesh.addNode(2322.986143635452, 1725.6526304854035, 0.0, 801) + femmesh.addNode(2368.912619491457, 1656.7244860718467, 0.0, 802) + femmesh.addNode(2353.5578507388273, 1578.5788384269713, 0.0, 803) + femmesh.addNode(251.59438775510205, -1642.5382653061224, 0.0, 804) + femmesh.addNode(250.0, -1125.0, 0.0, 805) + femmesh.addNode(244.79166666666666, -621.527777777778, 0.0, 806) + femmesh.addNode(253.65823412698398, -349.26835317460336, 0.0, 807) + femmesh.addNode(250.26573129251702, -1377.9230442176872, 0.0, 808) + femmesh.addNode(249.1319444444444, -874.4212962962965, 0.0, 809) + femmesh.addNode(183.5156907411028, -1822.3611654157708, 0.0, 810) + femmesh.addNode(175.62426452602392, -169.8009014101267, 0.0, 811) + femmesh.addNode(340.96396806154064, -151.6577109724219, 0.0, 812) + femmesh.addNode(337.022015699241, -1842.9798861443787, 0.0, 813) + femmesh.addNode(375.1328656462585, -1313.9615221088436, 0.0, 814) + femmesh.addNode(375.1328656462585, -1438.9615221088436, 0.0, 815) + femmesh.addNode(374.5659722222222, -812.2106481481483, 0.0, 816) + femmesh.addNode(374.5659722222222, -937.2106481481483, 0.0, 817) + femmesh.addNode(250.1328656462585, -1251.4615221088436, 0.0, 818) + femmesh.addNode(375.0, -1187.5, 0.0, 819) + femmesh.addNode(250.93005952380952, -1510.2306547619048, 0.0, 820) + femmesh.addNode(375.797193877551, -1571.2691326530612, 0.0, 821) + femmesh.addNode(249.5659722222222, -999.7106481481483, 0.0, 822) + femmesh.addNode(375.0, -1062.5, 0.0, 823) + femmesh.addNode(246.96180555555554, -747.9745370370374, 0.0, 824) + femmesh.addNode(372.3958333333333, -685.7638888888891, 0.0, 825) + femmesh.addNode(249.2249503968253, -485.3980654761908, 0.0, 826) + femmesh.addNode(126.82911706349199, -424.6341765873017, 0.0, 827) + femmesh.addNode(122.39583333333333, -560.7638888888891, 0.0, 828) + femmesh.addNode(376.829117063492, -424.6341765873017, 0.0, 829) + femmesh.addNode(372.3958333333333, -560.7638888888891, 0.0, 830) + femmesh.addNode(126.82911706349199, -299.6341765873017, 0.0, 831) + femmesh.addNode(376.829117063492, -299.6341765873017, 0.0, 832) + femmesh.addNode(125.79719387755102, -1696.2691326530612, 0.0, 833) + femmesh.addNode(125.79719387755102, -1571.2691326530612, 0.0, 834) + femmesh.addNode(125.0, -1187.5, 0.0, 835) + femmesh.addNode(125.0, -1062.5, 0.0, 836) + femmesh.addNode(122.39583333333333, -685.7638888888891, 0.0, 837) + femmesh.addNode(375.797193877551, -1696.2691326530612, 0.0, 838) + femmesh.addNode(124.5659722222222, -937.2106481481483, 0.0, 839) + femmesh.addNode(125.13286564625851, -1313.9615221088436, 0.0, 840) + femmesh.addNode(124.5659722222222, -812.2106481481483, 0.0, 841) + femmesh.addNode(125.13286564625851, -1438.9615221088436, 0.0, 842) + femmesh.addNode(294.30820172717154, -1742.7590757252506, 0.0, 843) + femmesh.addNode(418.5110078496205, -1796.4899430721894, 0.0, 844) + femmesh.addNode(91.7578453705514, -1911.1805827078854, 0.0, 845) + femmesh.addNode(91.7578453705514, -1786.1805827078854, 0.0, 846) + femmesh.addNode(216.7578453705514, -1911.1805827078854, 0.0, 847) + femmesh.addNode(217.55503924810242, -1732.4497153609466, 0.0, 848) + femmesh.addNode(420.4819840307703, -200.82885548621107, 0.0, 849) + femmesh.addNode(297.3111010942623, -250.46303207351275, 0.0, 850) + femmesh.addNode(214.64124932650395, -259.53462729236503, 0.0, 851) + femmesh.addNode(87.81213226301196, -209.90045070506335, 0.0, 852) + femmesh.addNode(87.81213226301196, -84.90045070506335, 0.0, 853) + femmesh.addNode(212.81213226301196, -84.90045070506335, 0.0, 854) + femmesh.addNode(260.2688532201719, -1832.6705257800747, 0.0, 855) + femmesh.addNode(295.4819840307703, -75.82885548621107, 0.0, 856) + femmesh.addNode(420.4819840307703, -75.82885548621107, 0.0, 857) + femmesh.addNode(418.5110078496205, -1921.4899430721894, 0.0, 858) + femmesh.addNode(293.5110078496205, -1921.4899430721894, 0.0, 859) + femmesh.addNode(258.2941162937823, -160.7293061912742, 0.0, 860) + femmesh.addNode(3751.594387755102, -1642.5382653061224, 0.0, 861) + femmesh.addNode(3750.0, -1125.0, 0.0, 862) + femmesh.addNode(3744.7916666666665, -621.527777777778, 0.0, 863) + femmesh.addNode(3753.658234126984, -349.26835317460336, 0.0, 864) + femmesh.addNode(3750.265731292517, -1377.9230442176872, 0.0, 865) + femmesh.addNode(3749.1319444444443, -874.4212962962965, 0.0, 866) + femmesh.addNode(3683.515690741103, -1822.3611654157708, 0.0, 867) + femmesh.addNode(3675.624264526024, -169.8009014101267, 0.0, 868) + femmesh.addNode(3840.9639680615405, -151.6577109724219, 0.0, 869) + femmesh.addNode(3837.022015699241, -1842.9798861443787, 0.0, 870) + femmesh.addNode(3875.1328656462583, -1313.9615221088436, 0.0, 871) + femmesh.addNode(3875.1328656462583, -1438.9615221088436, 0.0, 872) + femmesh.addNode(3874.565972222222, -812.2106481481483, 0.0, 873) + femmesh.addNode(3874.565972222222, -937.2106481481483, 0.0, 874) + femmesh.addNode(3750.1328656462583, -1251.4615221088436, 0.0, 875) + femmesh.addNode(3875.0, -1187.5, 0.0, 876) + femmesh.addNode(3746.9618055555557, -747.9745370370374, 0.0, 877) + femmesh.addNode(3872.395833333333, -685.7638888888891, 0.0, 878) + femmesh.addNode(3750.9300595238096, -1510.2306547619048, 0.0, 879) + femmesh.addNode(3875.797193877551, -1571.2691326530612, 0.0, 880) + femmesh.addNode(3749.565972222222, -999.7106481481483, 0.0, 881) + femmesh.addNode(3875.0, -1062.5, 0.0, 882) + femmesh.addNode(3876.829117063492, -424.6341765873017, 0.0, 883) + femmesh.addNode(3749.224950396825, -485.3980654761908, 0.0, 884) + femmesh.addNode(3872.395833333333, -560.7638888888891, 0.0, 885) + femmesh.addNode(3626.829117063492, -424.6341765873017, 0.0, 886) + femmesh.addNode(3622.395833333333, -560.7638888888891, 0.0, 887) + femmesh.addNode(3626.829117063492, -299.6341765873017, 0.0, 888) + femmesh.addNode(3876.829117063492, -299.6341765873017, 0.0, 889) + femmesh.addNode(3625.797193877551, -1696.2691326530612, 0.0, 890) + femmesh.addNode(3625.797193877551, -1571.2691326530612, 0.0, 891) + femmesh.addNode(3625.0, -1187.5, 0.0, 892) + femmesh.addNode(3625.0, -1062.5, 0.0, 893) + femmesh.addNode(3622.395833333333, -685.7638888888891, 0.0, 894) + femmesh.addNode(3875.797193877551, -1696.2691326530612, 0.0, 895) + femmesh.addNode(3624.565972222222, -937.2106481481483, 0.0, 896) + femmesh.addNode(3625.1328656462583, -1438.9615221088436, 0.0, 897) + femmesh.addNode(3625.1328656462583, -1313.9615221088436, 0.0, 898) + femmesh.addNode(3624.565972222222, -812.2106481481483, 0.0, 899) + femmesh.addNode(3794.3082017271718, -1742.7590757252506, 0.0, 900) + femmesh.addNode(3918.5110078496205, -1796.4899430721894, 0.0, 901) + femmesh.addNode(3591.7578453705514, -1911.1805827078854, 0.0, 902) + femmesh.addNode(3591.7578453705514, -1786.1805827078854, 0.0, 903) + femmesh.addNode(3716.7578453705514, -1911.1805827078854, 0.0, 904) + femmesh.addNode(3717.5550392481027, -1732.4497153609466, 0.0, 905) + femmesh.addNode(3920.48198403077, -200.82885548621107, 0.0, 906) + femmesh.addNode(3797.311101094262, -250.46303207351275, 0.0, 907) + femmesh.addNode(3714.6412493265043, -259.53462729236503, 0.0, 908) + femmesh.addNode(3587.8121322630122, -209.90045070506335, 0.0, 909) + femmesh.addNode(3587.8121322630122, -84.90045070506335, 0.0, 910) + femmesh.addNode(3712.8121322630122, -84.90045070506335, 0.0, 911) + femmesh.addNode(3760.268853220172, -1832.6705257800747, 0.0, 912) + femmesh.addNode(3795.48198403077, -75.82885548621107, 0.0, 913) + femmesh.addNode(3920.48198403077, -75.82885548621107, 0.0, 914) + femmesh.addNode(3918.5110078496205, -1921.4899430721894, 0.0, 915) + femmesh.addNode(3793.5110078496205, -1921.4899430721894, 0.0, 916) + femmesh.addNode(3758.2941162937823, -160.7293061912742, 0.0, 917) + return True + + +def create_elements(femmesh): + # elements + femmesh.addFace([174, 230, 204, 315, 316, 317], 21) + femmesh.addFace([11, 263, 258, 318, 319, 320], 22) + femmesh.addFace([259, 264, 17, 321, 322, 323], 23) + femmesh.addFace([201, 261, 65, 324, 325, 326], 24) + femmesh.addFace([39, 211, 40, 327, 328, 55], 25) + femmesh.addFace([176, 235, 217, 329, 330, 331], 26) + femmesh.addFace([87, 248, 212, 332, 333, 334], 27) + femmesh.addFace([237, 280, 172, 335, 336, 337], 28) + femmesh.addFace([211, 247, 40, 338, 339, 328], 29) + femmesh.addFace([209, 279, 269, 340, 341, 342], 30) + femmesh.addFace([235, 296, 217, 343, 344, 330], 31) + femmesh.addFace([11, 258, 12, 320, 345, 19], 32) + femmesh.addFace([16, 259, 17, 346, 323, 24], 33) + femmesh.addFace([209, 269, 188, 342, 347, 348], 34) + femmesh.addFace([214, 277, 191, 349, 350, 351], 35) + femmesh.addFace([214, 301, 277, 352, 353, 349], 36) + femmesh.addFace([88, 248, 87, 354, 332, 95], 37) + femmesh.addFace([65, 242, 201, 355, 356, 326], 38) + femmesh.addFace([180, 255, 204, 357, 358, 359], 39) + femmesh.addFace([13, 258, 207, 360, 361, 362], 40) + femmesh.addFace([206, 259, 15, 363, 364, 365], 41) + femmesh.addFace([200, 246, 227, 366, 367, 368], 42) + femmesh.addFace([227, 246, 168, 367, 369, 370], 43) + femmesh.addFace([216, 248, 89, 371, 372, 373], 44) + femmesh.addFace([177, 225, 208, 374, 375, 376], 45) + femmesh.addFace([34, 262, 234, 377, 378, 379], 46) + femmesh.addFace([69, 209, 68, 380, 381, 80], 47) + femmesh.addFace([172, 279, 237, 382, 383, 337], 48) + femmesh.addFace([176, 284, 208, 384, 385, 386], 49) + femmesh.addFace([226, 289, 262, 387, 388, 389], 50) + femmesh.addFace([204, 243, 180, 390, 391, 359], 51) + femmesh.addFace([230, 281, 204, 392, 393, 316], 52) + femmesh.addFace([89, 248, 88, 372, 354, 96], 53) + femmesh.addFace([180, 243, 205, 391, 394, 395], 54) + femmesh.addFace([173, 249, 207, 396, 397, 398], 55) + femmesh.addFace([207, 249, 182, 397, 399, 400], 56) + femmesh.addFace([60, 214, 3, 401, 402, 71], 57) + femmesh.addFace([205, 289, 180, 403, 404, 395], 58) + femmesh.addFace([215, 270, 170, 405, 406, 407], 59) + femmesh.addFace([204, 255, 174, 358, 408, 317], 60) + femmesh.addFace([232, 270, 178, 409, 410, 411], 61) + femmesh.addFace([207, 277, 173, 412, 413, 398], 62) + femmesh.addFace([222, 232, 178, 414, 411, 415], 63) + femmesh.addFace([213, 238, 85, 416, 417, 418], 64) + femmesh.addFace([270, 282, 170, 419, 420, 406], 65) + femmesh.addFace([184, 247, 211, 421, 338, 422], 66) + femmesh.addFace([176, 299, 284, 423, 424, 384], 67) + femmesh.addFace([210, 241, 179, 425, 426, 427], 68) + femmesh.addFace([234, 262, 194, 378, 428, 429], 69) + femmesh.addFace([222, 267, 61, 430, 431, 432], 70) + femmesh.addFace([180, 289, 226, 404, 387, 433], 71) + femmesh.addFace([41, 218, 42, 434, 435, 57], 72) + femmesh.addFace([67, 266, 221, 436, 437, 438], 73) + femmesh.addFace([182, 252, 207, 439, 440, 400], 74) + femmesh.addFace([212, 223, 183, 441, 442, 443], 75) + femmesh.addFace([181, 223, 212, 444, 441, 445], 76) + femmesh.addFace([15, 239, 206, 446, 447, 365], 77) + femmesh.addFace([62, 222, 61, 448, 432, 73], 78) + femmesh.addFace([67, 221, 66, 438, 449, 78], 79) + femmesh.addFace([219, 225, 177, 450, 374, 451], 80) + femmesh.addFace([38, 283, 244, 452, 453, 454], 81) + femmesh.addFace([197, 302, 224, 455, 456, 457], 82) + femmesh.addFace([224, 302, 274, 456, 458, 459], 83) + femmesh.addFace([269, 279, 172, 341, 382, 460], 84) + femmesh.addFace([244, 283, 203, 453, 461, 462], 85) + femmesh.addFace([229, 273, 178, 463, 464, 465], 86) + femmesh.addFace([198, 280, 237, 466, 335, 467], 87) + femmesh.addFace([169, 240, 233, 468, 469, 470], 88) + femmesh.addFace([233, 240, 198, 469, 471, 472], 89) + femmesh.addFace([12, 258, 13, 345, 360, 20], 90) + femmesh.addFace([15, 259, 16, 364, 346, 23], 91) + femmesh.addFace([207, 252, 13, 440, 473, 362], 92) + femmesh.addFace([206, 239, 182, 447, 474, 475], 93) + femmesh.addFace([179, 227, 210, 476, 477, 427], 94) + femmesh.addFace([182, 304, 206, 478, 479, 475], 95) + femmesh.addFace([228, 285, 31, 480, 481, 482], 96) + femmesh.addFace([65, 261, 64, 325, 483, 76], 97) + femmesh.addFace([202, 273, 229, 484, 463, 485], 98) + femmesh.addFace([208, 284, 177, 385, 486, 376], 99) + femmesh.addFace([5, 224, 70, 487, 488, 82], 100) + femmesh.addFace([169, 236, 217, 489, 490, 491], 101) + femmesh.addFace([217, 236, 184, 490, 492, 493], 102) + femmesh.addFace([196, 281, 230, 494, 392, 495], 103) + femmesh.addFace([224, 268, 70, 496, 497, 488], 104) + femmesh.addFace([214, 287, 3, 498, 499, 402], 105) + femmesh.addFace([209, 266, 68, 500, 501, 381], 106) + femmesh.addFace([85, 238, 84, 417, 502, 92], 107) + femmesh.addFace([188, 266, 209, 503, 500, 348], 108) + femmesh.addFace([69, 268, 209, 504, 505, 380], 109) + femmesh.addFace([209, 268, 190, 505, 506, 507], 110) + femmesh.addFace([189, 267, 222, 508, 430, 509], 111) + femmesh.addFace([181, 236, 223, 510, 511, 444], 112) + femmesh.addFace([208, 235, 176, 512, 329, 386], 113) + femmesh.addFace([181, 307, 236, 513, 514, 510], 114) + femmesh.addFace([221, 266, 188, 437, 503, 515], 115) + femmesh.addFace([186, 225, 219, 516, 450, 517], 116) + femmesh.addFace([168, 313, 225, 518, 519, 520], 117) + femmesh.addFace([215, 229, 178, 521, 465, 522], 118) + femmesh.addFace([30, 228, 31, 523, 482, 46], 119) + femmesh.addFace([213, 295, 183, 524, 525, 526], 120) + femmesh.addFace([225, 313, 208, 519, 527, 375], 121) + femmesh.addFace([190, 279, 209, 528, 340, 507], 122) + femmesh.addFace([218, 276, 42, 529, 530, 435], 123) + femmesh.addFace([36, 220, 37, 531, 532, 52], 124) + femmesh.addFace([192, 264, 259, 533, 321, 534], 125) + femmesh.addFace([258, 263, 191, 319, 535, 536], 126) + femmesh.addFace([223, 233, 183, 537, 538, 442], 127) + femmesh.addFace([169, 233, 223, 470, 537, 539], 128) + femmesh.addFace([231, 253, 187, 540, 541, 542], 129) + femmesh.addFace([199, 285, 228, 543, 480, 544], 130) + femmesh.addFace([43, 276, 216, 545, 546, 547], 131) + femmesh.addFace([212, 245, 87, 548, 549, 334], 132) + femmesh.addFace([180, 303, 255, 550, 551, 357], 133) + femmesh.addFace([182, 249, 230, 399, 552, 553], 134) + femmesh.addFace([230, 249, 196, 552, 554, 495], 135) + femmesh.addFace([188, 257, 221, 555, 556, 515], 136) + femmesh.addFace([221, 257, 179, 556, 557, 558], 137) + femmesh.addFace([253, 275, 187, 559, 560, 541], 138) + femmesh.addFace([170, 241, 210, 561, 425, 562], 139) + femmesh.addFace([212, 248, 181, 333, 563, 445], 140) + femmesh.addFace([62, 232, 222, 564, 414, 448], 141) + femmesh.addFace([190, 268, 224, 506, 496, 565], 142) + femmesh.addFace([210, 310, 170, 566, 567, 562], 143) + femmesh.addFace([175, 302, 213, 568, 569, 570], 144) + femmesh.addFace([216, 276, 181, 546, 571, 572], 145) + femmesh.addFace([193, 270, 232, 573, 409, 574], 146) + femmesh.addFace([214, 267, 189, 575, 508, 576], 147) + femmesh.addFace([60, 267, 214, 577, 575, 401], 148) + femmesh.addFace([181, 276, 218, 571, 529, 578], 149) + femmesh.addFace([241, 312, 179, 579, 580, 426], 150) + femmesh.addFace([39, 244, 211, 581, 582, 327], 151) + femmesh.addFace([1, 263, 11, 583, 318, 18], 152) + femmesh.addFace([26, 263, 1, 584, 583, 27], 153) + femmesh.addFace([17, 264, 2, 322, 585, 25], 154) + femmesh.addFace([2, 264, 29, 585, 586, 44], 155) + femmesh.addFace([211, 291, 184, 587, 588, 422], 156) + femmesh.addFace([192, 286, 228, 589, 590, 591], 157) + femmesh.addFace([32, 226, 33, 592, 593, 48], 158) + femmesh.addFace([181, 248, 216, 563, 371, 572], 159) + femmesh.addFace([201, 282, 261, 594, 595, 324], 160) + femmesh.addFace([183, 256, 213, 596, 597, 526], 161) + femmesh.addFace([213, 256, 175, 597, 598, 570], 162) + femmesh.addFace([183, 245, 212, 599, 548, 443], 163) + femmesh.addFace([191, 287, 214, 600, 498, 351], 164) + femmesh.addFace([262, 289, 194, 388, 601, 428], 165) + femmesh.addFace([42, 276, 43, 530, 545, 58], 166) + femmesh.addFace([235, 246, 185, 602, 603, 604], 167) + femmesh.addFace([195, 293, 220, 605, 606, 607], 168) + femmesh.addFace([278, 286, 192, 608, 589, 609], 169) + femmesh.addFace([26, 287, 263, 610, 611, 584], 170) + femmesh.addFace([63, 232, 62, 612, 564, 74], 171) + femmesh.addFace([170, 309, 215, 613, 614, 407], 172) + femmesh.addFace([189, 301, 214, 615, 352, 576], 173) + femmesh.addFace([220, 293, 177, 606, 616, 617], 174) + femmesh.addFace([85, 295, 213, 618, 524, 418], 175) + femmesh.addFace([34, 234, 35, 379, 619, 50], 176) + femmesh.addFace([185, 280, 240, 620, 621, 622], 177) + femmesh.addFace([220, 290, 195, 623, 624, 607], 178) + femmesh.addFace([183, 295, 245, 525, 625, 599], 179) + femmesh.addFace([284, 299, 203, 424, 626, 627], 180) + femmesh.addFace([3, 287, 26, 499, 610, 28], 181) + femmesh.addFace([36, 290, 220, 628, 623, 531], 182) + femmesh.addFace([217, 296, 169, 344, 629, 491], 183) + femmesh.addFace([235, 313, 246, 630, 631, 602], 184) + femmesh.addFace([219, 253, 186, 632, 633, 517], 185) + femmesh.addFace([171, 253, 219, 634, 632, 635], 186) + femmesh.addFace([222, 273, 189, 636, 637, 509], 187) + femmesh.addFace([178, 273, 222, 464, 636, 415], 188) + femmesh.addFace([14, 239, 15, 638, 446, 22], 189) + femmesh.addFace([89, 306, 216, 639, 640, 373], 190) + femmesh.addFace([216, 306, 43, 640, 641, 547], 191) + femmesh.addFace([251, 280, 185, 642, 620, 643], 192) + femmesh.addFace([6, 271, 98, 644, 645, 100], 193) + femmesh.addFace([83, 271, 6, 646, 644, 90], 194) + femmesh.addFace([41, 247, 218, 647, 648, 434], 195) + femmesh.addFace([218, 247, 184, 648, 421, 649], 196) + femmesh.addFace([223, 236, 169, 511, 489, 539], 197) + femmesh.addFace([225, 250, 168, 650, 651, 520], 198) + femmesh.addFace([261, 282, 193, 595, 652, 653], 199) + femmesh.addFace([87, 245, 86, 549, 654, 94], 200) + femmesh.addFace([239, 252, 182, 655, 439, 474], 201) + femmesh.addFace([218, 307, 181, 656, 513, 578], 202) + femmesh.addFace([221, 242, 66, 657, 658, 449], 203) + femmesh.addFace([184, 291, 217, 588, 659, 493], 204) + femmesh.addFace([186, 250, 225, 660, 650, 516], 205) + femmesh.addFace([179, 257, 227, 557, 661, 476], 206) + femmesh.addFace([178, 270, 215, 410, 405, 522], 207) + femmesh.addFace([227, 257, 200, 661, 662, 368], 208) + femmesh.addFace([237, 279, 190, 383, 528, 663], 209) + femmesh.addFace([32, 285, 226, 664, 665, 592], 210) + femmesh.addFace([184, 307, 218, 666, 656, 649], 211) + femmesh.addFace([217, 291, 176, 659, 667, 331], 212) + femmesh.addFace([213, 302, 238, 569, 668, 416], 213) + femmesh.addFace([179, 312, 221, 580, 669, 558], 214) + femmesh.addFace([37, 283, 38, 670, 452, 53], 215) + femmesh.addFace([33, 262, 34, 671, 377, 49], 216) + femmesh.addFace([185, 296, 235, 672, 343, 604], 217) + femmesh.addFace([200, 269, 251, 673, 674, 675], 218) + femmesh.addFace([219, 308, 171, 676, 677, 635], 219) + femmesh.addFace([177, 293, 219, 616, 678, 451], 220) + femmesh.addFace([168, 250, 227, 651, 679, 370], 221) + femmesh.addFace([227, 250, 210, 679, 680, 477], 222) + femmesh.addFace([177, 311, 220, 681, 682, 617], 223) + femmesh.addFace([215, 309, 305, 614, 683, 684], 224) + femmesh.addFace([305, 309, 187, 683, 685, 686], 225) + femmesh.addFace([204, 281, 243, 393, 687, 390], 226) + femmesh.addFace([243, 281, 167, 687, 688, 689], 227) + femmesh.addFace([220, 283, 37, 690, 670, 532], 228) + femmesh.addFace([251, 269, 172, 674, 460, 691], 229) + femmesh.addFace([224, 292, 197, 692, 693, 457], 230) + femmesh.addFace([5, 292, 224, 694, 692, 487], 231) + femmesh.addFace([167, 300, 229, 695, 696, 697], 232) + femmesh.addFace([229, 300, 202, 696, 698, 485], 233) + femmesh.addFace([66, 242, 65, 658, 355, 77], 234) + femmesh.addFace([285, 303, 226, 699, 700, 665], 235) + femmesh.addFace([38, 244, 39, 454, 581, 54], 236) + femmesh.addFace([230, 304, 182, 701, 478, 553], 237) + femmesh.addFace([202, 300, 294, 698, 702, 703], 238) + femmesh.addFace([224, 274, 190, 459, 704, 565], 239) + femmesh.addFace([169, 296, 240, 629, 705, 468], 240) + femmesh.addFace([226, 262, 33, 389, 671, 593], 241) + femmesh.addFace([40, 247, 41, 339, 647, 56], 242) + femmesh.addFace([241, 282, 201, 706, 594, 707], 243) + femmesh.addFace([277, 301, 173, 353, 708, 413], 244) + femmesh.addFace([201, 312, 241, 709, 579, 707], 245) + femmesh.addFace([193, 282, 270, 652, 419, 573], 246) + femmesh.addFace([229, 305, 167, 710, 711, 697], 247) + femmesh.addFace([13, 252, 14, 473, 712, 21], 248) + femmesh.addFace([211, 299, 291, 713, 714, 587], 249) + femmesh.addFace([294, 300, 196, 702, 715, 716], 250) + femmesh.addFace([64, 298, 63, 717, 718, 75], 251) + femmesh.addFace([170, 310, 231, 567, 719, 720], 252) + femmesh.addFace([226, 303, 180, 700, 550, 433], 253) + femmesh.addFace([255, 303, 199, 551, 721, 722], 254) + femmesh.addFace([265, 275, 205, 723, 724, 725], 255) + femmesh.addFace([187, 275, 265, 560, 723, 726], 256) + femmesh.addFace([186, 253, 231, 633, 540, 727], 257) + femmesh.addFace([200, 251, 246, 675, 728, 366], 258) + femmesh.addFace([189, 273, 260, 637, 729, 730], 259) + femmesh.addFace([260, 273, 202, 729, 484, 731], 260) + femmesh.addFace([68, 266, 67, 501, 436, 79], 261) + femmesh.addFace([61, 267, 60, 431, 577, 72], 262) + femmesh.addFace([29, 288, 30, 732, 733, 45], 263) + femmesh.addFace([198, 314, 233, 734, 735, 472], 264) + femmesh.addFace([291, 299, 176, 714, 423, 667], 265) + femmesh.addFace([186, 310, 250, 736, 737, 660], 266) + femmesh.addFace([250, 310, 210, 737, 566, 680], 267) + femmesh.addFace([263, 287, 191, 611, 600, 535], 268) + femmesh.addFace([234, 254, 195, 738, 739, 740], 269) + femmesh.addFace([70, 268, 69, 497, 504, 81], 270) + femmesh.addFace([257, 269, 200, 741, 673, 662], 271) + femmesh.addFace([188, 269, 257, 347, 741, 555], 272) + femmesh.addFace([233, 256, 183, 742, 596, 538], 273) + femmesh.addFace([86, 295, 85, 743, 618, 93], 274) + femmesh.addFace([194, 254, 234, 744, 738, 429], 275) + femmesh.addFace([30, 288, 228, 733, 745, 523], 276) + femmesh.addFace([228, 288, 192, 745, 746, 591], 277) + femmesh.addFace([236, 307, 184, 514, 666, 492], 278) + femmesh.addFace([234, 290, 35, 747, 748, 619], 279) + femmesh.addFace([195, 290, 234, 624, 747, 740], 280) + femmesh.addFace([14, 252, 239, 712, 655, 638], 281) + femmesh.addFace([228, 286, 199, 590, 749, 544], 282) + femmesh.addFace([221, 312, 242, 669, 750, 657], 283) + femmesh.addFace([43, 306, 4, 641, 751, 59], 284) + femmesh.addFace([4, 306, 89, 751, 639, 97], 285) + femmesh.addFace([98, 292, 5, 752, 694, 99], 286) + femmesh.addFace([167, 305, 265, 711, 753, 754], 287) + femmesh.addFace([246, 251, 185, 728, 643, 603], 288) + femmesh.addFace([167, 265, 243, 754, 755, 689], 289) + femmesh.addFace([243, 265, 205, 755, 725, 394], 290) + femmesh.addFace([31, 285, 32, 481, 664, 47], 291) + femmesh.addFace([35, 290, 36, 748, 628, 51], 292) + femmesh.addFace([171, 275, 253, 756, 559, 634], 293) + femmesh.addFace([272, 275, 171, 757, 756, 758], 294) + femmesh.addFace([205, 275, 272, 724, 757, 759], 295) + femmesh.addFace([215, 305, 229, 684, 710, 521], 296) + femmesh.addFace([202, 294, 260, 703, 760, 731], 297) + femmesh.addFace([84, 297, 83, 761, 762, 91], 298) + femmesh.addFace([274, 302, 175, 458, 568, 763], 299) + femmesh.addFace([233, 314, 256, 735, 764, 742], 300) + femmesh.addFace([187, 309, 231, 685, 765, 542], 301) + femmesh.addFace([240, 280, 198, 621, 466, 471], 302) + femmesh.addFace([237, 274, 175, 766, 763, 767], 303) + femmesh.addFace([190, 274, 237, 704, 766, 663], 304) + femmesh.addFace([260, 301, 189, 768, 615, 730], 305) + femmesh.addFace([174, 286, 278, 769, 608, 770], 306) + femmesh.addFace([261, 298, 64, 771, 717, 483], 307) + femmesh.addFace([199, 303, 285, 721, 699, 543], 308) + femmesh.addFace([63, 298, 232, 718, 772, 612], 309) + femmesh.addFace([232, 298, 193, 772, 773, 574], 310) + femmesh.addFace([206, 278, 259, 774, 775, 363], 311) + femmesh.addFace([259, 278, 192, 775, 609, 534], 312) + femmesh.addFace([191, 277, 258, 350, 776, 536], 313) + femmesh.addFace([258, 277, 207, 776, 412, 361], 314) + femmesh.addFace([174, 304, 230, 777, 701, 315], 315) + femmesh.addFace([246, 313, 168, 631, 518, 369], 316) + femmesh.addFace([244, 299, 211, 778, 713, 582], 317) + femmesh.addFace([255, 286, 174, 779, 769, 408], 318) + femmesh.addFace([199, 286, 255, 749, 779, 722], 319) + femmesh.addFace([231, 310, 186, 719, 736, 727], 320) + femmesh.addFace([231, 309, 170, 765, 613, 720], 321) + femmesh.addFace([264, 288, 29, 780, 732, 586], 322) + femmesh.addFace([197, 297, 238, 781, 782, 783], 323) + femmesh.addFace([170, 282, 241, 420, 706, 561], 324) + femmesh.addFace([254, 272, 171, 784, 758, 785], 325) + femmesh.addFace([194, 272, 254, 786, 784, 744], 326) + femmesh.addFace([272, 289, 205, 787, 403, 759], 327) + femmesh.addFace([249, 294, 196, 788, 716, 554], 328) + femmesh.addFace([173, 294, 249, 789, 788, 396], 329) + femmesh.addFace([240, 296, 185, 705, 672, 622], 330) + femmesh.addFace([208, 313, 235, 527, 630, 512], 331) + femmesh.addFace([175, 314, 237, 790, 791, 767], 332) + femmesh.addFace([237, 314, 198, 791, 734, 467], 333) + femmesh.addFace([238, 297, 84, 782, 761, 502], 334) + femmesh.addFace([172, 280, 251, 336, 642, 691], 335) + femmesh.addFace([238, 302, 197, 668, 455, 783], 336) + femmesh.addFace([245, 295, 86, 625, 743, 654], 337) + femmesh.addFace([196, 300, 281, 715, 792, 494], 338) + femmesh.addFace([203, 299, 244, 626, 778, 462], 339) + femmesh.addFace([192, 288, 264, 746, 780, 533], 340) + femmesh.addFace([254, 308, 195, 793, 794, 739], 341) + femmesh.addFace([271, 292, 98, 795, 752, 645], 342) + femmesh.addFace([242, 312, 201, 750, 709, 356], 343) + femmesh.addFace([206, 304, 278, 479, 796, 774], 344) + femmesh.addFace([278, 304, 174, 796, 777, 770], 345) + femmesh.addFace([260, 294, 173, 760, 789, 797], 346) + femmesh.addFace([271, 297, 197, 798, 781, 799], 347) + femmesh.addFace([193, 298, 261, 773, 771, 653], 348) + femmesh.addFace([194, 289, 272, 601, 787, 786], 349) + femmesh.addFace([197, 292, 271, 693, 795, 799], 350) + femmesh.addFace([173, 301, 260, 708, 768, 797], 351) + femmesh.addFace([171, 308, 254, 677, 793, 785], 352) + femmesh.addFace([83, 297, 271, 762, 798, 646], 353) + femmesh.addFace([256, 314, 175, 764, 790, 598], 354) + femmesh.addFace([265, 305, 187, 753, 686, 726], 355) + femmesh.addFace([293, 308, 219, 800, 676, 678], 356) + femmesh.addFace([195, 308, 293, 794, 800, 605], 357) + femmesh.addFace([281, 300, 167, 792, 695, 688], 358) + femmesh.addFace([220, 311, 283, 682, 801, 690], 359) + femmesh.addFace([283, 311, 203, 801, 802, 461], 360) + femmesh.addFace([203, 311, 284, 802, 803, 627], 361) + femmesh.addFace([284, 311, 177, 803, 681, 486], 362) + femmesh.addFace([121, 808, 120, 814, 815, 128], 363) + femmesh.addFace([123, 809, 122, 816, 817, 130], 364) + femmesh.addFace([805, 808, 121, 818, 814, 819], 365) + femmesh.addFace([120, 808, 804, 815, 820, 821], 366) + femmesh.addFace([122, 809, 805, 817, 822, 823], 367) + femmesh.addFace([806, 809, 123, 824, 816, 825], 368) + femmesh.addFace([806, 807, 106, 826, 827, 828], 369) + femmesh.addFace([124, 807, 806, 829, 826, 830], 370) + femmesh.addFace([106, 807, 107, 827, 831, 114], 371) + femmesh.addFace([125, 807, 124, 832, 829, 132], 372) + femmesh.addFace([101, 804, 102, 833, 834, 109], 373) + femmesh.addFace([103, 805, 104, 835, 836, 111], 374) + femmesh.addFace([105, 806, 106, 837, 828, 113], 375) + femmesh.addFace([120, 804, 119, 821, 838, 127], 376) + femmesh.addFace([122, 805, 121, 823, 819, 129], 377) + femmesh.addFace([124, 806, 123, 830, 825, 131], 378) + femmesh.addFace([805, 809, 104, 822, 839, 836], 379) + femmesh.addFace([103, 808, 805, 840, 818, 835], 380) + femmesh.addFace([105, 809, 806, 841, 824, 837], 381) + femmesh.addFace([804, 808, 102, 820, 842, 834], 382) + femmesh.addFace([102, 808, 103, 842, 840, 110], 383) + femmesh.addFace([104, 809, 105, 839, 841, 112], 384) + femmesh.addFace([804, 813, 119, 843, 844, 838], 385) + femmesh.addFace([7, 810, 101, 845, 846, 108], 386) + femmesh.addFace([116, 810, 7, 847, 845, 117], 387) + femmesh.addFace([101, 810, 804, 846, 848, 833], 388) + femmesh.addFace([125, 812, 807, 849, 850, 832], 389) + femmesh.addFace([807, 811, 107, 851, 852, 831], 390) + femmesh.addFace([1, 811, 26, 853, 854, 27], 391) + femmesh.addFace([107, 811, 1, 852, 853, 115], 392) + femmesh.addFace([810, 813, 804, 855, 843, 848], 393) + femmesh.addFace([26, 812, 3, 856, 857, 28], 394) + femmesh.addFace([3, 812, 125, 857, 849, 133], 395) + femmesh.addFace([8, 813, 116, 858, 859, 118], 396) + femmesh.addFace([119, 813, 8, 844, 858, 126], 397) + femmesh.addFace([807, 812, 811, 850, 860, 851], 398) + femmesh.addFace([116, 813, 810, 859, 855, 847], 399) + femmesh.addFace([811, 812, 26, 860, 856, 854], 400) + femmesh.addFace([154, 865, 153, 871, 872, 161], 401) + femmesh.addFace([156, 866, 155, 873, 874, 163], 402) + femmesh.addFace([862, 865, 154, 875, 871, 876], 403) + femmesh.addFace([863, 866, 156, 877, 873, 878], 404) + femmesh.addFace([153, 865, 861, 872, 879, 880], 405) + femmesh.addFace([155, 866, 862, 874, 881, 882], 406) + femmesh.addFace([157, 864, 863, 883, 884, 885], 407) + femmesh.addFace([863, 864, 139, 884, 886, 887], 408) + femmesh.addFace([139, 864, 140, 886, 888, 147], 409) + femmesh.addFace([158, 864, 157, 889, 883, 165], 410) + femmesh.addFace([134, 861, 135, 890, 891, 142], 411) + femmesh.addFace([136, 862, 137, 892, 893, 144], 412) + femmesh.addFace([138, 863, 139, 894, 887, 146], 413) + femmesh.addFace([153, 861, 152, 880, 895, 160], 414) + femmesh.addFace([155, 862, 154, 882, 876, 162], 415) + femmesh.addFace([157, 863, 156, 885, 878, 164], 416) + femmesh.addFace([862, 866, 137, 881, 896, 893], 417) + femmesh.addFace([861, 865, 135, 879, 897, 891], 418) + femmesh.addFace([136, 865, 862, 898, 875, 892], 419) + femmesh.addFace([138, 866, 863, 899, 877, 894], 420) + femmesh.addFace([135, 865, 136, 897, 898, 143], 421) + femmesh.addFace([137, 866, 138, 896, 899, 145], 422) + femmesh.addFace([861, 870, 152, 900, 901, 895], 423) + femmesh.addFace([9, 867, 134, 902, 903, 141], 424) + femmesh.addFace([149, 867, 9, 904, 902, 150], 425) + femmesh.addFace([134, 867, 861, 903, 905, 890], 426) + femmesh.addFace([158, 869, 864, 906, 907, 889], 427) + femmesh.addFace([864, 868, 140, 908, 909, 888], 428) + femmesh.addFace([5, 868, 98, 910, 911, 99], 429) + femmesh.addFace([140, 868, 5, 909, 910, 148], 430) + femmesh.addFace([867, 870, 861, 912, 900, 905], 431) + femmesh.addFace([98, 869, 6, 913, 914, 100], 432) + femmesh.addFace([6, 869, 158, 914, 906, 166], 433) + femmesh.addFace([10, 870, 149, 915, 916, 151], 434) + femmesh.addFace([152, 870, 10, 901, 915, 159], 435) + femmesh.addFace([864, 869, 868, 907, 917, 908], 436) + femmesh.addFace([149, 870, 867, 916, 912, 904], 437) + femmesh.addFace([868, 869, 98, 917, 913, 911], 438) + return True diff --git a/src/Mod/Fem/femexamples/rc_wall_2d.py b/src/Mod/Fem/femexamples/rc_wall_2d.py new file mode 100644 index 0000000000..a8d86b8167 --- /dev/null +++ b/src/Mod/Fem/femexamples/rc_wall_2d.py @@ -0,0 +1,165 @@ +# *************************************************************************** +# * Copyright (c) 2019 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. * +# * * +# * FreeCAD 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 FreeCAD; if not, write to the Free Software * +# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 * +# * USA * +# * * +# *************************************************************************** + + +import FreeCAD +import ObjectsFem +import Fem + +mesh_name = 'Mesh' # needs to be Mesh to work with unit tests + + +def init_doc(doc=None): + if doc is None: + doc = FreeCAD.newDocument() + return doc + + +def setup_rcwall2d(doc=None, solver='ccxtools'): + # setup reinfoced wall in 2D + + if doc is None: + doc = init_doc() + + # part + from FreeCAD import Vector as vec + import Part + from Part import makeLine as ln + + v1 = vec(0, -2000, 0) + v2 = vec(500, -2000, 0) + v3 = vec(500, 0, 0) + v4 = vec(3500, 0, 0) + v5 = vec(3500, -2000, 0) + v6 = vec(4000, -2000, 0) + v7 = vec(4000, 2000, 0) + v8 = vec(0, 2000, 0) + l1 = ln(v1, v2) + l2 = ln(v2, v3) + l3 = ln(v3, v4) + l4 = ln(v4, v5) + l5 = ln(v5, v6) + l6 = ln(v6, v7) + l7 = ln(v7, v8) + l8 = ln(v8, v1) + rcwall = doc.addObject("Part::Feature", "FIB_Wall") + rcwall.Shape = Part.Face(Part.Wire([l1, l2, l3, l4, l5, l6, l7, l8])) + + # analysis + analysis = ObjectsFem.makeAnalysis(doc, 'Analysis') + + solver + # TODO How to pass multiple solver for one analysis in one doc + if solver is None: + pass # no solver is added + elif solver is 'calculix': + solver = analysis.addObject( + ObjectsFem.makeSolverCalculix(doc, 'SolverCalculiX') + )[0] + solver.AnalysisType = 'static' + solver.GeometricalNonlinearity = 'linear' + solver.ThermoMechSteadyState = False + solver.MatrixSolverType = 'default' + solver.IterationsControlParameterTimeUse = False + elif solver is 'ccxtools': + solver = analysis.addObject( + ObjectsFem.makeSolverCalculixCcxTools(doc, 'CalculiXccxTools') + )[0] + solver.AnalysisType = 'static' + solver.GeometricalNonlinearity = 'linear' + solver.ThermoMechSteadyState = False + solver.MatrixSolverType = 'default' + solver.IterationsControlParameterTimeUse = False + solver.WorkingDir = u'' + + # shell thickness + thickness = analysis.addObject( + ObjectsFem.makeElementGeometry2D(doc, 0, 'ShellThickness') + )[0] + thickness.Thickness = 150.0 + + # material + matrixprop = {} + matrixprop['Name'] = "Concrete-EN-C35/45" + matrixprop['YoungsModulus'] = "32000 MPa" + matrixprop['PoissonRatio'] = "0.17" + matrixprop['CompressiveStrength'] = "15.75 MPa" + # make some hint on the possible angle units in material system + matrixprop['AngleOfFriction'] = "30 deg" + matrixprop['Density'] = '2500 kg/m^3' + reinfoprop = {} + reinfoprop['Name'] = "Reinforcement-FIB-B500" + reinfoprop['YieldStrength'] = "315 MPa" + # not an official FreeCAD material property + reinfoprop['ReinforcementRatio'] = "0.0" + material_reinforced = analysis.addObject( + ObjectsFem.makeMaterialReinforced(doc, 'MaterialReinforced') + )[0] + material_reinforced.Material = matrixprop + material_reinforced.Reinforcement = reinfoprop + + # fixed_constraint + fixed_constraint = analysis.addObject( + ObjectsFem.makeConstraintFixed(doc, name="ConstraintFixed") + )[0] + fixed_constraint.References = [(rcwall, "Edge1"), (rcwall, "Edge5")] + + # force constraint + force_constraint = doc.Analysis.addObject( + ObjectsFem.makeConstraintForce(doc, name="ConstraintForce") + )[0] + force_constraint.References = [(rcwall, "Edge7")] + force_constraint.Force = 1000000.0 + force_constraint.Direction = (rcwall, ["Edge8"]) + force_constraint.Reversed = False + + # displacement_constraint + displacement_constraint = doc.Analysis.addObject( + ObjectsFem.makeConstraintDisplacement(doc, name="ConstraintDisplacmentPrescribed") + )[0] + displacement_constraint.References = [(rcwall, "Face1")] + displacement_constraint.zFix = True + + # mesh + from femexamples.meshes.mesh_rc_wall_2d_tria6 import create_nodes, create_elements + fem_mesh = Fem.FemMesh() + control = create_nodes(fem_mesh) + if not control: + print('ERROR on creating nodes') + control = create_elements(fem_mesh) + if not control: + print('ERROR on creating elements') + femmesh_obj = analysis.addObject( + doc.addObject('Fem::FemMeshObject', mesh_name) + )[0] + femmesh_obj.FemMesh = fem_mesh + + doc.recompute() + return doc + + +''' +from femexamples import rc_wall_2d as rc +rc.setup_rcwall2d() + +''' From 99bca23ba1a9f0e529fe69a8637e0e359c0dc9bc Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:19 +0200 Subject: [PATCH 09/13] FEM: concrete, rho calculation unit test --- src/Mod/Fem/TestFem.py | 4 ++ src/Mod/Fem/femtest/testresult.py | 77 +++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index 4a127c4f79..c2412f51f5 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -128,6 +128,7 @@ gf() ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_von_mises" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_std" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_stress_principal_reinforced" +./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_rho" ./bin/FreeCADCmd --run-test "femtest.testresult.TestResult.test_disp_abs" ./bin/FreeCADCmd --run-test "femtest.testsolverframework.TestSolverFrameWork.test_solver_framework" @@ -220,6 +221,9 @@ unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.t import unittest unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_stress_principal_reinforced")) +import unittest +unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_rho")) + import unittest unittest.TextTestRunner().run(unittest.TestLoader().loadTestsFromName("femtest.testresult.TestResult.test_disp_abs")) diff --git a/src/Mod/Fem/femtest/testresult.py b/src/Mod/Fem/femtest/testresult.py index ba3fa8bc63..d03fb24588 100644 --- a/src/Mod/Fem/femtest/testresult.py +++ b/src/Mod/Fem/femtest/testresult.py @@ -351,6 +351,83 @@ class TestResult(unittest.TestCase): "Calculated principal reinforced stresses are not the expected values." ) + # ******************************************************************************************** + def test_rho( + self + ): + data = ( + ( + # Case1: Governing Eq.14 + (2.000, -2.000, 5.000, 6.000, -4.000, 2.000), + (0.02400, 0.00400, 0.01400) + ), + ( + # Case2: Governing Eq.10+ + (-3.000, -7.000, 0.000, 6.000, -4.000, 2.000), + (0.00886, 0.00000, 0.00571), + ), + ( + # Case3: Governing Eq.5 + (-1.000, -7.000, 10.000, 0.000, 0.000, 5.000), + (0.00000, 0.00000, 0.02714) + ), + ( + # Case4: Governing Eq.13 + (3.000, 0.000, 10.000, 0.000, 5.000, 0.000), + (0.01600, 0.00000, 0.03000) + ), + ( + # Case5: Governing Eq.11- + (10.000, 7.000, -3.000, 3.000, 1.000, -2.000), + (0.02533, 0.02133, 0.00000) + ), + ( + # Case6: Governing Eq.14 + (4.000, -7.000, 3.000, 7.000, 0.000, -5.000), + (0.02200, 0.01000, 0.01600) + ), + ( + # Case7: Governing Eq.14 + (8.000, -14.000, 6.000, 14.000, 0.000, -10.000), + (0.04400, 0.02000, 0.03200) + ), + ( + # Case8: Governing Eq.17 + (1.000, 0.000, 3.000, 10.000, -8.000, 7.000), + (0.02486, 0.01750, 0.01720) + ), + ( + # Case9: Governing Eq.13 + (0.000, 0.000, 0.000, 10.000, 8.000, 7.000), + (0.03600, 0.03400, 0.03000) + ), + ( + # Case10: Governing Eq.13 + (15.000, 0.000, 0.000, 0.000, 0.000, 0.000), + (0.03000, 0.00000, 0.00000) + ), + ( + # Case11: Governing Eq.13 + (0.000, 0.000, 0.000, 5.000, 0.000, 0.000), + (0.01000, 0.01000, 0.00000) + ) + ) + + from femresult.resulttools import calculate_rho as calrho + for i, case in enumerate(data): + res = calrho(case[0], 500) + rhores = ( + round(res[0], 5), + round(res[1], 5), + round(res[2], 5) + ) + # fcc_print('Case{}: {}'.format(i + 1 , rhores)) + self.assertEqual( + rhores, case[1], + "Calculated rho are not the expected Case{}." + .format(i + 1) + ) + # ******************************************************************************************** def test_disp_abs( self From f718c305587ed01b1fbfe6fc395753a5cc5aae6d Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:21 +0200 Subject: [PATCH 10/13] Materials: cards, add concrete matrix and reinforcement materials - safety factor is included in material params - this is for sure not a material parameter - but FreeCAD has no safety factor yet - workaround: directly include them in the material parameter - structural engineers have a lot of them in limeted state design --- .../StandardMaterial/Concrete-EN-C35_45.FCMat | 20 +++++++++++++++++++ .../Reinforcement-FIB-B500.FCMat | 15 ++++++++++++++ 2 files changed, 35 insertions(+) create mode 100644 src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat create mode 100644 src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat diff --git a/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat b/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat new file mode 100644 index 0000000000..a50f83a9d7 --- /dev/null +++ b/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat @@ -0,0 +1,20 @@ +; Concrete-EN-C35_45 +; (c) 2019 Bernd Hahnebach (CC-BY 3.0) +; information about the content of such cards can be found on the wiki: +; https://www.freecadweb.org/wiki/Material + + +[General] +Name = Concrete-EN-C35/45 +Description = Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311075) +Father = Aggregate + +[Mechanical] +AngleOfFriction = 30 deg +CompressiveStrength = 15.75 MPa +Density = 2500 kg/m^3 +PoissonRatio = 0.17 +YoungsModulus = 32000 MPa + +[Cost] +ProductURL = https://en.wikipedia.org/wiki/Concrete diff --git a/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat b/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat new file mode 100644 index 0000000000..6c9c913cfb --- /dev/null +++ b/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat @@ -0,0 +1,15 @@ +; Reinforcement-FIB-B500 +; (c) 2019 Bernd Hahnebach (CC-BY 3.0) +; information about the content of such cards can be found on the wiki: +; https://www.freecadweb.org/wiki/Material + + +[General] +Name = Reinforcement-Harry +Description = Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311705) + +[Mechanical] +Density = 7850 kg/m^3 +PoissonRatio = 0.3 +YieldStrength = 315 MPa +YoungsModulus = 210000 MPa From a95f2d615348a937d17b4ffed2c6e353dd8a8bf3 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:23 +0200 Subject: [PATCH 11/13] Materials: cards, recreate new cards and update csv and ods --- .../StandardMaterial/Concrete-EN-C35_45.FCMat | 2 +- .../Reinforcement-FIB-B500.FCMat | 2 +- .../StandardMaterial/Tools/Materials.csv | 2 ++ .../StandardMaterial/Tools/Materials.ods | Bin 24169 -> 24814 bytes 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat b/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat index a50f83a9d7..deede90fe5 100644 --- a/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat +++ b/src/Mod/Material/StandardMaterial/Concrete-EN-C35_45.FCMat @@ -2,7 +2,7 @@ ; (c) 2019 Bernd Hahnebach (CC-BY 3.0) ; information about the content of such cards can be found on the wiki: ; https://www.freecadweb.org/wiki/Material - +; file created by FreeCAD 0.19.16886 (Git) [General] Name = Concrete-EN-C35/45 diff --git a/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat b/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat index 6c9c913cfb..7898ffbf46 100644 --- a/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat +++ b/src/Mod/Material/StandardMaterial/Reinforcement-FIB-B500.FCMat @@ -2,7 +2,7 @@ ; (c) 2019 Bernd Hahnebach (CC-BY 3.0) ; information about the content of such cards can be found on the wiki: ; https://www.freecadweb.org/wiki/Material - +; file created by FreeCAD 0.19.16886 (Git) [General] Name = Reinforcement-Harry diff --git a/src/Mod/Material/StandardMaterial/Tools/Materials.csv b/src/Mod/Material/StandardMaterial/Tools/Materials.csv index 944f2de6ce..0d99b073d1 100644 --- a/src/Mod/Material/StandardMaterial/Tools/Materials.csv +++ b/src/Mod/Material/StandardMaterial/Tools/Materials.csv @@ -6,6 +6,7 @@ AlMgSi1F31|AlMgSi1F31|AlMgSi1F31|||||Metal|Aluminium|Aluminium|3.2315.72|DIN 172 Aluminum-6061-T6|Aluminum 6061-T6|||Precipitation-hardened, Nonferrous Aluminum alloy|||Metal|Aluminium|Aluminium||||||||2700 kg/m^3||0.33|||310 MPa||69000 MPa||167 W/m/K|||||||||||||||||||||||||https://en.wikipedia.org/wiki/6061_aluminium_alloy|| AlZn4-5Mg1F35|AlZn4,5Mg1F35|AlZn4,5Mg1F35|||||Metal|Aluminium|Aluminium|3.4335.71|DIN 1725||||||2700 kg/m^3||0.3|27000 MPa|10|350 MPa|290 MPa|70000 MPa|||0.000023 m/m/K|||||||||||||||||||||||||| CalculiX-Steel|CalculiX-Steel|||Standard steel material for CalculiX sample calculations|||Metal||||||||||7900 kg/m^3||0.3|||||210000 MPa|590 J/kg/K|43 W/m/K|0.000012 m/m/K|||||||||||||||||||||||||| +Concrete-EN-C35_45|Concrete-EN-C35/45|||Concrete matrix for reinforcement material examples, 0.6 x 0.75 x 35 MPa = 15.75 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311075)|||Aggregate||||||||30 deg|15.75 MPa|2500 kg/m^3||0.17|||||32000 MPa|||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Concrete|| Concrete-Generic|Concrete|||A standard C-25 construction concrete|||Aggregate|||||||Masterformat 03 33 13||25 MPa|2400 kg/m^3||0.17|||||32000 MPa|||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Concrete|| Glass-E-GlassFibre|Glass-E|||Glass Fibre|||Glass|||||||||1080 MPa|2580 kg/m^3|||||3445 MPa|||||||||||||||||||||||||||||https://en.wikipedia.org/wiki/Glass_fiber|| Glass-Generic|Glass|||Generic soda-lime glass|Normalglas|Szkło sodowe|Glass||||||||||2520 kg/m^3||0.22|||||72000 MPa|||0.000009 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Soda-lime_glass|| @@ -17,6 +18,7 @@ PLA-Generic|PLA|||Polylactic acid or polylactide (PLA, Poly) is a biodegradable PP-Generic|Polypropylene||||||||||||http://www.matweb.com/search/DataSheet.aspx?MatGUID=a882a1c603374e278d062f106dfda95b|||10 MPa|916 kg/m^3||0.44|||79.7 MPa|32.8 MPa|1470 MPa|1920 J/kg/K|0.249 W/m/K|0.000123 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polypropylene|| PTFE-Generic|PTFE||||||||||||http://www.matweb.com/search/datasheet.aspx?MatGUID=4d14eac958e5401a8fd152e1261b6843|||10.2 MPa|2070 kg/m^3||0.46|||34.6 MPa|20.5 MPa|564 MPa|1010 J/kg/K|0.263 W/m/K|0.000108 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polytetrafluoroethylene|| PVC-Generic|PVC||||||||||||http://www.matweb.com/search/DataSheet.aspx?MatGUID=1f650966ec834bb8833dd4c6e3116079||||1380 kg/m^3||0.38|||50 MPa||2800 MPa|1000 J/kg/K|0.150 W/m/K|0.000075 m/m/K||||||||||||||||||||||||https://en.wikipedia.org/wiki/Polyvinyl_chloride|| +Reinforcement-FIB-B500|Reinforcement-Harry|||Reinforcement inside concrete for reinforcement material examples, from fib examples, 0.84 x 0.75 x 500 MPa = 315 MPa (https://forum.freecadweb.org/viewtopic.php?f=18&t=33106&start=200#p311705)|||||||||||||7850 kg/m^3||0.3||||315 MPa|210000 MPa||||||||||||||||||||||||||||| Steel-15CrNi6|15CrNi6|||High-strength carbon steel|höchste Beanspruchung, Achsen, Wellen, Ritzel, Nocken, Kegelräder|Wysokowytrzymała stal węglowa|Metal|Case-hardened steel|Einsatzstahl|1.5919|EN 10084||||||7800 kg/m^3||0.3|81000 MPa|9|1000 MPa|680 MPa|210000 MPa|||0.000011 m/m/K|||||||||||||||||||||||||| Steel-17CrNiMo6|17CrNiMo6|17CrNiMo6|||höchste Beanspruchung, Wellen, Zahnräder||Metal|Case-hardened steel|Einsatzstahl|1.6587|EN 10084||||||7800 kg/m^3||0.3|81000 MPa|8|1150 MPa|830 MPa|210000 MPa|||0.000011 m/m/K|||||||||||||||||||||||||| Steel-1C22|1C22|C22||Case hardened alloy steel|kleiner Vergütungsdurchmesser, gut schweißbar|Stal stopowa do nawęglania|Metal|Heat-treatable steel|Vergütungsstahl|1.0402|EN 10083-1||||||7800 kg/m^3||0.3|81000 MPa|27|400 MPa|230 MPa|210000 MPa|||0.000011 m/m/K|||||||||||||||||||||||||| diff --git a/src/Mod/Material/StandardMaterial/Tools/Materials.ods b/src/Mod/Material/StandardMaterial/Tools/Materials.ods index df9f0fa9b4b22dbcda206684be24ce4c73d7d43a..3972e8edd10cb4684791d3fbc2c7a264b6401351 100644 GIT binary patch delta 23119 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 C@aq-; delta 22390 zcmZ5{Wl)|m*Ctw^Xp!RX4&}j%ySux)yWYj!{lVSciWhfxC{Wy?xWo2+zuleL&5xWj znaG@El5-{J%0(~aaVI3Qq6{<)CIkdL1O!5ZQ3A3O%0D4L4lQ?SNd^I7NtR&C%6b3+ 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

=>%@hN>e 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 From 55fc22b4b890fdf63e6abf9291a80cf44059ca3d Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:25 +0200 Subject: [PATCH 12/13] FEM: concrete, add task panel to select matrix and reinforcement material --- src/Mod/Fem/Gui/CMakeLists.txt | 1 + .../Gui/Resources/ui/MaterialReinforcement.ui | 183 ++++++++ .../_ViewProviderFemMaterialReinforced.py | 417 +++++++++++++++++- 3 files changed, 598 insertions(+), 3 deletions(-) create mode 100755 src/Mod/Fem/Gui/Resources/ui/MaterialReinforcement.ui diff --git a/src/Mod/Fem/Gui/CMakeLists.txt b/src/Mod/Fem/Gui/CMakeLists.txt index e9076d55ee..722b5b287c 100755 --- a/src/Mod/Fem/Gui/CMakeLists.txt +++ b/src/Mod/Fem/Gui/CMakeLists.txt @@ -401,6 +401,7 @@ SET(FemGuiPythonUI_SRCS Resources/ui/FlowVelocity.ui Resources/ui/InitialFlowVelocity.ui Resources/ui/Material.ui + Resources/ui/MaterialReinforcement.ui Resources/ui/MeshBoundaryLayer.ui Resources/ui/MeshGmsh.ui Resources/ui/MeshGroup.ui diff --git a/src/Mod/Fem/Gui/Resources/ui/MaterialReinforcement.ui b/src/Mod/Fem/Gui/Resources/ui/MaterialReinforcement.ui new file mode 100755 index 0000000000..67fa6f6ec1 --- /dev/null +++ b/src/Mod/Fem/Gui/Resources/ui/MaterialReinforcement.ui @@ -0,0 +1,183 @@ + + + FemMaterial + + + + 0 + 0 + 396 + 448 + + + + FEM material + + + Qt::LeftToRight + + + + + + + 16777215 + 1677215 + + + + Matrix Material + + + + + + + + + Choose + + + + + + + + Material + + + + + + + Name + + + + + + + TextLabel + + + + + + + Edit + + + + + + + Properties + + + + + + + + + Description + + + true + + + + + + + + + + + 16777215 + 1677215 + + + + Reinforcement Material + + + + + + + + + Choose + + + + + + + + Material + + + + + + + Name + + + + + + + TextLabel + + + + + + + Edit + + + + + + + Properties + + + + + + + + + Description + + + true + + + + + + + + + + Qt::Vertical + + + + 20 + 40 + + + + + + + + + diff --git a/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py index 0a5c89f602..c3b40fd86d 100644 --- a/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py +++ b/src/Mod/Fem/femguiobjects/_ViewProviderFemMaterialReinforced.py @@ -33,6 +33,15 @@ import FemGui # needed to display the icons in TreeView False if False else FemGui.__name__ # flake8, dummy FemGui usage, returns 'FemGui' +# task panel +# from . import FemSelectionWidgets +from PySide import QtCore +from PySide import QtGui +import sys +if sys.version_info.major >= 3: + unicode = str + + class _ViewProviderFemMaterialReinforced: "A View Provider for the FemMaterialReinfocement object" def __init__(self, vobj): @@ -58,9 +67,19 @@ class _ViewProviderFemMaterialReinforced: return def setEdit(self, vobj, mode=0): - # avoid edit mode by return False - # https://forum.freecadweb.org/viewtopic.php?t=12139&start=10#p161062 - return False + # hide all meshes + for o in FreeCAD.ActiveDocument.Objects: + if o.isDerivedFrom("Fem::FemMeshObject"): + o.ViewObject.hide() + # hide all meshes + for o in FreeCAD.ActiveDocument.Objects: + if o.isDerivedFrom("Fem::FemMeshObject"): + o.ViewObject.hide() + # show task panel + taskd = _TaskPanelFemMaterialReinforced(self.Object) + taskd.obj = vobj.Object + FreeCADGui.Control.showDialog(taskd) + return True def unsetEdit(self, vobj, mode=0): FreeCADGui.Control.closeDialog() @@ -87,3 +106,395 @@ class _ViewProviderFemMaterialReinforced: def __setstate__(self, state): return None + + +class _TaskPanelFemMaterialReinforced: + '''The editmode TaskPanel for FemMaterialReinforced objects''' + + if sys.version_info.major >= 3: + unicode = str + + def __init__(self, obj): + + FreeCAD.Console.PrintMessage('\n') # empty line on start task panel + self.obj = obj + + # init matrix and reinforcement material + self.material_m = self.obj.Material + self.card_path_m = '' + self.has_transient_mat_m = False + self.material_r = self.obj.Reinforcement + self.card_path_r = '' + self.has_transient_mat_r = False + # mat_card is the FCMat file + # card_name is the file name of the mat_card + # card_path is the whole file path of the mat_card + # material_name is the value of the key name in FreeCAD material dictionary + # they might not match because of special letters in the material_name which are + # changed in the card_name to english standard characters + + # init for collecting all mat data and icons + self.materials = {} # { card_path : FreeCAD material dict } + self.cards = {} # { card_path : card_names, ... } + self.icons = {} # { card_path : icon_path } + + # parameter widget + self.parameterWidget = FreeCADGui.PySideUic.loadUi( + FreeCAD.getHomePath() + "Mod/Fem/Resources/ui/MaterialReinforcement.ui" + ) + + # globals + QtCore.QObject.connect( + self.parameterWidget.cb_materials_m, + QtCore.SIGNAL("activated(int)"), + self.choose_material_m + ) + QtCore.QObject.connect( + self.parameterWidget.pb_edit_m, + QtCore.SIGNAL("clicked()"), + self.edit_material_m + ) + QtCore.QObject.connect( + self.parameterWidget.cb_materials_r, + QtCore.SIGNAL("activated(int)"), + self.choose_material_r + ) + QtCore.QObject.connect( + self.parameterWidget.pb_edit_r, + QtCore.SIGNAL("clicked()"), + self.edit_material_r + ) + + # get all available materials (fill self.materials, self.cards and self.icons) + from materialtools.cardutils import import_materials as getmats + self.materials, self.cards, self.icons = getmats() + # fill the material comboboxes with material cards + self.add_cards_to_combo_boxes() + + # search for exact the mat_card_m and mat_card_r in all known cards + # choose the current matrix material + self.card_path_m = self.get_material_card(self.material_m) + FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_m)) + if not self.card_path_m: + # we have not found our material in self.materials dict :-( + # we're going to add a user-defined temporary material: a document material + FreeCAD.Console.PrintMessage( + "Previously used material card cannot be found in material directories. " + "Add document material.\n" + ) + self.card_path_m = '_Document_Matrix_Material' + self.materials[self.card_path_m] = self.material_m + self.parameterWidget.cb_materials_m.addItem( + QtGui.QIcon(":/icons/help-browser.svg"), + self.card_path_m, + self.card_path_m + ) + index = self.parameterWidget.cb_materials_m.findData(self.card_path_m) + # print(index) + # fill input fields and set the current material in the cb widget + self.choose_material_m(index) + else: + # we found our exact material in self.materials dict :-) + FreeCAD.Console.PrintLog( + "Previously used material card was found in material directories. " + "We will use this material.\n" + ) + index = self.parameterWidget.cb_materials_m.findData(self.card_path_m) + # set the current material in the cb widget + self.choose_material_m(index) + + # choose the current reinforcement material + self.card_path_r = self.get_material_card(self.material_r) + FreeCAD.Console.PrintLog('card_path: {}'.format(self.card_path_r)) + if not self.card_path_r: + # we have not found our material in self.materials dict :-( + # we're going to add a user-defined temporary material: a document material + FreeCAD.Console.PrintMessage( + "Previously used material card cannot be found in material directories. " + "Add document material.\n" + ) + self.card_path_r = '_Document_Reinforcement_Material' + self.materials[self.card_path_r] = self.material_r + self.parameterWidget.cb_materials_r.addItem( + QtGui.QIcon(":/icons/help-browser.svg"), + self.card_path_r, + self.card_path_r + ) + index = self.parameterWidget.cb_materials_r.findData(self.card_path_r) + # set the current material in the cb widget + self.choose_material_r(index) + else: + # we found our exact material in self.materials dict :-) + FreeCAD.Console.PrintLog( + "Previously used material card was found in material directories. " + "We will use this material.\n" + ) + index = self.parameterWidget.cb_materials_r.findData(self.card_path_r) + # print(index) + # fill input fields and set the current material in the cb widget + self.choose_material_r(index) + + # set up the form + self.form = self.parameterWidget + + # leave task panel *************************************************************************** + def accept(self): + from materialtools.cardutils import check_mat_units as checkunits + if checkunits(self.material_m) is True and checkunits(self.material_r) is True: + self.obj.Material = self.material_m + self.obj.Reinforcement = self.material_r + else: + error_message = ( + 'Due to some wrong material quantity units in the changed ' + 'material data, the task panel changes where not accepted.\n' + ) + FreeCAD.Console.PrintError(error_message) + QtGui.QMessageBox.critical(None, "Material data not changed", error_message) + self.recompute_and_set_back_all() + return True + + def reject(self): + self.recompute_and_set_back_all() + return True + + def recompute_and_set_back_all(self): + guidoc = FreeCADGui.getDocument(self.obj.Document) + guidoc.Document.recompute() + guidoc.resetEdit() + self.output_obj_mat_param() + + def output_obj_mat_param(self): + self.print_mat_dict(self.obj.Material) + self.print_mat_dict(self.obj.Reinforcement) + print('\n') + + def print_mat_dict(self, mat_dict): + if 'Name' in mat_dict: + print('Material: {}'.format(mat_dict['Name'])) + else: + print('Matrix material: no Name') + for key in mat_dict: + print(' {}: {}'.format(key, mat_dict[key])) + + # choose material card *********************************************************************** + def get_material_card(self, material): + for a_mat in self.materials: + unmatched_items = set(self.materials[a_mat].items()) ^ set(material.items()) + # print(a_mat + ' --> unmatched_items = ' + str(len(unmatched_items))) + if len(unmatched_items) < 4: + FreeCAD.Console.PrintLog('{}\n'.format(unmatched_items)) + if len(unmatched_items) == 0: + return a_mat + return "" + + def choose_material_m(self, index): + if index < 0: + return + # get the whole card path + self.card_path_m = self.parameterWidget.cb_materials_m.itemData(index) + FreeCAD.Console.PrintMessage( + 'choose_material in FEM material task panel:\n' + ' {}\n'.format(self.card_path_m) + ) + self.material_m = self.materials[self.card_path_m] + self.parameterWidget.cb_materials_m.setCurrentIndex(index) + gen_mat_desc = "" + gen_mat_name = "" + if 'Description' in self.material_m: + gen_mat_desc = self.material_m['Description'] + if 'Name' in self.material_m: + gen_mat_name = self.material_m['Name'] + self.parameterWidget.l_description_m.setText(gen_mat_desc) + self.parameterWidget.l_name_m.setText(gen_mat_name) + + def choose_material_r(self, index): + if index < 0: + return + # get the whole card path + self.card_path_r = self.parameterWidget.cb_materials_r.itemData(index) + FreeCAD.Console.PrintMessage( + 'choose_material in FEM material task panel:\n' + ' {}\n'.format(self.card_path_r) + ) + self.material_r = self.materials[self.card_path_r] + self.parameterWidget.cb_materials_r.setCurrentIndex(index) + gen_mat_desc = "" + gen_mat_name = "" + if 'Description' in self.material_r: + gen_mat_desc = self.material_r['Description'] + if 'Name' in self.material_r: + gen_mat_name = self.material_r['Name'] + self.parameterWidget.l_description_r.setText(gen_mat_desc) + self.parameterWidget.l_name_r.setText(gen_mat_name) + + # transient material is needed if the user changed mat parameter by the mat editor + def set_transient_material_m(self): + self.card_path_m = '_Transient_Matrix_Material' + self.materials[self.card_path_m] = self.material_m # = the current matrix mat dict + index = self.parameterWidget.cb_materials_m.findData(self.card_path_m) + self.choose_material_m(index) + + def add_transient_material_m(self): + self.has_transient_mat_m = True + self.card_path_m = '_Transient_Matrix_Material' + self.parameterWidget.cb_materials_m.addItem( + QtGui.QIcon(":/icons/help-browser.svg"), + self.card_path_m, + self.card_path_m + ) + self.set_transient_material_m() + + def set_transient_material_r(self): + self.card_path_r = '_Transient_Reinforcement_Material' + self.materials[self.card_path_r] = self.material_r # = the current reinforced mat dict + index = self.parameterWidget.cb_materials_r.findData(self.card_path_r) + self.choose_material_r(index) + + def add_transient_material_r(self): + self.has_transient_mat_r = True + self.card_path_r = '_Transient_Reinforcement_Material' + self.parameterWidget.cb_materials_r.addItem( + QtGui.QIcon(":/icons/help-browser.svg"), + self.card_path_r, + self.card_path_r + ) + self.set_transient_material_r() + + # edit material parameter ******************************************************************** + # TODO, also all mat parameter checks should be moved to material editor + # and mat parameter checks should be done on analysis precheck in according to the analysis + # should be checked if all needed parameter are defined and have all right values and units + def edit_material_m(self): + # opens the material editor to choose a material or edit material params + import MaterialEditor + if self.card_path_m not in self.cards: + FreeCAD.Console.PrintLog( + 'Card path not in cards, material dict will be used to open Material Editor.\n' + ) + new_material_params = MaterialEditor.editMaterial(material=self.material_m) + else: + new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_m) + # material editor returns the mat_dict only, not a card_path + # if the material editor was canceled a empty dict will be returned + # do not change the self.material + # check if dict is not empty (do not use 'is True') + if new_material_params: + # check material quantity units + from materialtools.cardutils import check_mat_units as checkunits + if checkunits(new_material_params) is True: + self.material_m = new_material_params + self.card_path_m = self.get_material_card(self.material_m) + FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_m)) + if not self.card_path_m: + FreeCAD.Console.PrintMessage( + "Material card chosen by the material editor " + "was not found in material directories.\n" + "Either the card does not exist or some material " + "parameter where changed in material editor.\n" + ) + if self.has_transient_mat_m is False: + self.add_transient_material_m() + else: + self.set_transient_material_m() + else: + # we found our exact material in self.materials dict :-) + FreeCAD.Console.PrintLog( + "Material card chosen by the material editor " + "was found in material directories. " + "The found material card will be used.\n" + ) + index = self.parameterWidget.cb_materials_m.findData(self.card_path_m) + # print(index) + # set the current material in the cb widget + self.choose_material_m(index) + else: + error_message = ( + 'Due to some wrong material quantity units in data passed ' + 'by the material editor, the material data was not changed.\n' + ) + FreeCAD.Console.PrintError(error_message) + QtGui.QMessageBox.critical(None, "Material data not changed", error_message) + else: + FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n') + + def edit_material_r(self): + # opens the material editor to choose a material or edit material params + import MaterialEditor + if self.card_path_r not in self.cards: + FreeCAD.Console.PrintLog( + 'Card path not in cards, material dict will be used to open Material Editor.\n' + ) + new_material_params = MaterialEditor.editMaterial(material=self.material_r) + else: + new_material_params = MaterialEditor.editMaterial(card_path=self.card_path_r) + # material editor returns the mat_dict only, not a card_path + # if the material editor was canceled a empty dict will be returned + # do not change the self.material + # check if dict is not empty (do not use 'is True') + if new_material_params: + # check material quantity units + from materialtools.cardutils import check_mat_units as checkunits + if checkunits(new_material_params) is True: + self.material_r = new_material_params + self.card_path_r = self.get_material_card(self.material_r) + FreeCAD.Console.PrintMessage('card_path: {}\n'.format(self.card_path_r)) + if not self.card_path_r: + FreeCAD.Console.PrintMessage( + "Material card chosen by the material editor " + "was not found in material directories.\n" + "Either the card does not exist or some material " + "parameter where changed in material editor.\n" + ) + if self.has_transient_mat_r is False: + self.add_transient_material_r() + else: + self.set_transient_material_r() + else: + # we found our exact material in self.materials dict :-) + FreeCAD.Console.PrintLog( + "Material card chosen by the material editor " + "was found in material directories. " + "The found material card will be used.\n" + ) + index = self.parameterWidget.cb_materials_r.findData(self.card_path_r) + # print(index) + # set the current material in the cb widget + self.choose_material_r(index) + else: + error_message = ( + 'Due to some wrong material quantity units in data passed ' + 'by the material editor, the material data was not changed.\n' + ) + FreeCAD.Console.PrintError(error_message) + QtGui.QMessageBox.critical(None, "Material data not changed", error_message) + else: + FreeCAD.Console.PrintMessage('No changes where made by the material editor.\n') + + # fill the combo box with cards ************************************************************** + def add_cards_to_combo_boxes(self): + # fill comboboxes, in combo box the card name is used not the material name + self.parameterWidget.cb_materials_m.clear() + self.parameterWidget.cb_materials_r.clear() + + mat_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Material/Cards") + sort_by_resources = mat_prefs.GetBool("SortByResources", False) + + card_name_list = [] # [ [card_name, card_path, icon_path], ... ] + + if sort_by_resources is True: + for a_path in sorted(self.materials.keys()): + card_name_list.append([self.cards[a_path], a_path, self.icons[a_path]]) + else: + card_names_tmp = {} + for path, name in self.cards.items(): + card_names_tmp[name] = path + for a_name in sorted(card_names_tmp.keys()): + a_path = card_names_tmp[a_name] + card_name_list.append([a_name, a_path, self.icons[a_path]]) + + for mat in card_name_list: + self.parameterWidget.cb_materials_m.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1]) + self.parameterWidget.cb_materials_r.addItem(QtGui.QIcon(mat[2]), mat[0], mat[1]) + # the whole card path is added to the combo box to make it unique + # see def choose_material: + # for assignment of self.card_path the path form the parameterWidget ist used From e9529b42f65a04bafbcb9ee8df93d76c66f77dc7 Mon Sep 17 00:00:00 2001 From: Bernd Hahnebach Date: Sun, 16 Jun 2019 18:26:27 +0200 Subject: [PATCH 13/13] FEM: ccx tools, pre checks for reinforced material object --- src/Mod/Fem/femtools/ccxtools.py | 41 ++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/Mod/Fem/femtools/ccxtools.py b/src/Mod/Fem/femtools/ccxtools.py index 52b21ae78b..48e6910829 100644 --- a/src/Mod/Fem/femtools/ccxtools.py +++ b/src/Mod/Fem/femtools/ccxtools.py @@ -411,6 +411,47 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): "Thermomechanical analysis: No SpecificHeat " "defined for at least one material.\n" # allowed to be 0.0 (in ccx) ) + if femutils.is_of_type(mat_obj, 'Fem::MaterialReinforced'): + # additional tests for reinforced materials, + # they are needed for result calculation not for ccx analysis + mat_map_m = mat_obj.Material + if 'AngleOfFriction' in mat_map_m: + # print(Units.Quantity(mat_map_m['AngleOfFriction']).Value) + if not Units.Quantity(mat_map_m['AngleOfFriction']).Value: + message += ( + "Value of AngleOfFriction is set to 0.0 " + "for the matrix of a reinforced material.\n" + ) + else: + message += ( + "No AngleOfFriction defined for the matrix " + "of at least one reinforced material.\n" + ) + if 'CompressiveStrength' in mat_map_m: + # print(Units.Quantity(mat_map_m['CompressiveStrength']).Value) + if not Units.Quantity(mat_map_m['CompressiveStrength']).Value: + message += ( + "Value of CompressiveStrength is set to 0.0 " + "for the matrix of a reinforced material.\n" + ) + else: + message += ( + "No CompressiveStrength defined for the matrinx " + "of at least one reinforced material.\n" + ) + mat_map_r = mat_obj.Reinforcement + if 'YieldStrength' in mat_map_r: + # print(Units.Quantity(mat_map_r['YieldStrength']).Value) + if not Units.Quantity(mat_map_r['YieldStrength']).Value: + message += ( + "Value of YieldStrength is set to 0.0 " + "for the reinforcement of a reinforced material.\n" + ) + else: + message += ( + "No YieldStrength defined for the reinforcement " + "of at least one reinforced material.\n" + ) if len(self.materials_linear) == 1: mobj = self.materials_linear[0]['Object'] if hasattr(mobj, 'References') and mobj.References: