diff --git a/src/Mod/Fem/App/AppFem.cpp b/src/Mod/Fem/App/AppFem.cpp index e8c7d41139..2598144908 100644 --- a/src/Mod/Fem/App/AppFem.cpp +++ b/src/Mod/Fem/App/AppFem.cpp @@ -149,19 +149,20 @@ PyMOD_INIT_FUNC(Fem) Fem::Constraint ::init(); Fem::ConstraintPython ::init(); + Fem::ConstraintBearing ::init(); + Fem::ConstraintContact ::init(); Fem::ConstraintFixed ::init(); + Fem::ConstraintFluidBoundary ::init(); Fem::ConstraintForce ::init(); - Fem::ConstraintPressure ::init(); - Fem::ConstraintGear ::init(); - Fem::ConstraintPulley ::init(); Fem::ConstraintDisplacement ::init(); - Fem::ConstraintTemperature ::init(); + Fem::ConstraintGear ::init(); Fem::ConstraintHeatflux ::init(); Fem::ConstraintInitialTemperature ::init(); Fem::ConstraintPlaneRotation ::init(); - Fem::ConstraintContact ::init(); - Fem::ConstraintFluidBoundary ::init(); + Fem::ConstraintPressure ::init(); + Fem::ConstraintPulley ::init(); + Fem::ConstraintTemperature ::init(); Fem::ConstraintTransform ::init(); Fem::FemResultObject ::init(); diff --git a/src/Mod/Fem/CMakeLists.txt b/src/Mod/Fem/CMakeLists.txt index 3092bd89dc..ee392eae7e 100755 --- a/src/Mod/Fem/CMakeLists.txt +++ b/src/Mod/Fem/CMakeLists.txt @@ -22,10 +22,6 @@ endif(BUILD_GUI) SET(FemScripts_SRCS Init.py InitGui.py - FemConstraint.py - FemInputWriter.py - FemToolsCcx.py - FemUtils.py ObjectsFem.py TestFem.py ) @@ -75,6 +71,7 @@ SET(FemSolver_SRCS femsolver/signal.py femsolver/solverbase.py femsolver/task.py + femsolver/writerbase.py ) SET(FemSolverElmer_SRCS @@ -154,6 +151,12 @@ SET(FemTestsElmer_SRCS femtest/testfiles/elmer/ELMERSOLVER_STARTINFO ) +SET(FemTools_SRCS + femtools/__init__.py + femtools/ccxtools.py + femtools/femutils.py +) + SET(FemObjectsScripts_SRCS PyObjects/__init__.py PyObjects/_FemConstraintBodyHeatSource.py @@ -173,6 +176,7 @@ SET(FemObjectsScripts_SRCS PyObjects/_FemMeshResult.py PyObjects/_FemResultMechanical.py PyObjects/_FemSolverCalculix.py + PyObjects/FemConstraint.py ) SET(FemAllScripts @@ -190,6 +194,7 @@ SET(FemAllScripts ${FemTestsFiles_SRCS} ${FemTestsCcx_SRCS} ${FemTestsElmer_SRCS} + ${FemTools_SRCS} ${FemObjectsScripts_SRCS} ) @@ -216,6 +221,7 @@ INSTALL(FILES ${FemTests_SRCS} DESTINATION Mod/Fem/femtest) INSTALL(FILES ${FemTestsFiles_SRCS} DESTINATION Mod/Fem/femtest/testfiles) INSTALL(FILES ${FemTestsCcx_SRCS} DESTINATION Mod/Fem/femtest/testfiles/ccx) INSTALL(FILES ${FemTestsElmer_SRCS} DESTINATION Mod/Fem/femtest/testfiles/elmer) +INSTALL(FILES ${FemTools_SRCS} DESTINATION Mod/Fem/femtools) INSTALL(FILES ${FemObjectsScripts_SRCS} DESTINATION Mod/Fem/PyObjects) @@ -243,6 +249,7 @@ SET(FemGuiScripts_SRCS PyGui/_ViewProviderFemSolverCalculix.py PyGui/FemSelectionObserver.py PyGui/FemSelectionWidgets.py + PyGui/ViewProviderFemConstraint.py ) diff --git a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui index 53bc8275b5..cfb90ede56 100644 --- a/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui +++ b/src/Mod/Fem/Gui/DlgSettingsFemCcx.ui @@ -7,7 +7,7 @@ 0 0 536 - 768 + 886 @@ -28,7 +28,7 @@ Qt::LeftToRight - FreeCAD FEM Solver frame work + CalculiX solver base Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop @@ -73,7 +73,7 @@ - General FEM solver framework + General FEM solver framework (new) Mod/Fem/Ccx diff --git a/src/Mod/Fem/ObjectsFem.py b/src/Mod/Fem/ObjectsFem.py index 2cfd78d46d..c7da1677a3 100644 --- a/src/Mod/Fem/ObjectsFem.py +++ b/src/Mod/Fem/ObjectsFem.py @@ -96,8 +96,8 @@ def makeConstraintFlowVelocity(doc, name="ConstraintFlowVelocity"): def makeConstraintFluidBoundary(doc, name="ConstraintFluidBoundary"): - '''makeConstraintFluidBoundary(document, name): makes a Fem ConstraintForce object''' - obj = doc.addObject("Fem::ConstraintForce", name) + '''makeConstraintFluidBoundary(document, name): makes a Fem ConstraintFluidBoundary object''' + obj = doc.addObject("Fem::ConstraintFluidBoundary", name) return obj diff --git a/src/Mod/Fem/PyGui/ViewProviderFemConstraint.py b/src/Mod/Fem/PyGui/ViewProviderFemConstraint.py new file mode 100644 index 0000000000..340ad69d67 --- /dev/null +++ b/src/Mod/Fem/PyGui/ViewProviderFemConstraint.py @@ -0,0 +1,53 @@ +# *************************************************************************** +# * * +# * Copyright (c) 2017 - Markus Hovorka * +# * * +# * 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__ = "_Base ViewProvider" +__author__ = "Markus Hovorka" +__url__ = "http://www.freecadweb.org" + + +import FreeCAD +if FreeCAD.GuiUp: + from pivy import coin + + +class ViewProxy(object): + """Proxy View Provider for Pythons base constraint.""" + + def __init__(self, vobj): + vobj.Proxy = self + + def attach(self, vobj): + default = coin.SoGroup() + vobj.addDisplayMode(default, "Default") + + def getDisplayModes(self, obj): + "Return a list of display modes." + modes = ["Default"] + return modes + + def getDefaultDisplayMode(self): + return "Default" + + def setDisplayMode(self, mode): + return mode diff --git a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintBodyHeatSource.py b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintBodyHeatSource.py index 8d091f2ef0..93e0fb6724 100644 --- a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintBodyHeatSource.py +++ b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintBodyHeatSource.py @@ -26,10 +26,10 @@ __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -import FemConstraint +from . import ViewProviderFemConstraint -class ViewProxy(FemConstraint.ViewProxy): +class ViewProxy(ViewProviderFemConstraint.ViewProxy): def getIcon(self): return ":/icons/fem-constraint-heatflux.svg" diff --git a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintElectrostaticPotential.py b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintElectrostaticPotential.py index aaa919098a..4cdf6a216a 100644 --- a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintElectrostaticPotential.py +++ b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintElectrostaticPotential.py @@ -27,15 +27,15 @@ __url__ = "http://www.freecadweb.org" import FreeCAD as App -import FemUtils -import FemConstraint +import femtools.femutils as FemUtils +from . import ViewProviderFemConstraint from FreeCAD import Units import FreeCADGui as Gui from . import FemSelectionWidgets -class ViewProxy(FemConstraint.ViewProxy): +class ViewProxy(ViewProviderFemConstraint.ViewProxy): def getIcon(self): return ":/icons/fem-constraint-electrostatic-potential.svg" diff --git a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py index 24293946c6..debc854f96 100644 --- a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py +++ b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintFlowVelocity.py @@ -27,15 +27,15 @@ __url__ = "http://www.freecadweb.org" import FreeCAD as App -import FemUtils -import FemConstraint +import femtools.femutils as FemUtils +from . import ViewProviderFemConstraint from FreeCAD import Units import FreeCADGui as Gui from . import FemSelectionWidgets -class ViewProxy(FemConstraint.ViewProxy): +class ViewProxy(ViewProviderFemConstraint.ViewProxy): def getIcon(self): return ":/icons/fem-constraint-flow-velocity.svg" diff --git a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintInitialFlowVelocity.py b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintInitialFlowVelocity.py index e431f7f734..8734ec036d 100644 --- a/src/Mod/Fem/PyGui/_ViewProviderFemConstraintInitialFlowVelocity.py +++ b/src/Mod/Fem/PyGui/_ViewProviderFemConstraintInitialFlowVelocity.py @@ -27,14 +27,14 @@ __url__ = "http://www.freecadweb.org" import FreeCAD as App -import FemUtils -import FemConstraint +import femtools.femutils as FemUtils +from . import ViewProviderFemConstraint from FreeCAD import Units import FreeCADGui as Gui -class ViewProxy(FemConstraint.ViewProxy): +class ViewProxy(ViewProviderFemConstraint.ViewProxy): def getIcon(self): return ":/icons/fem-constraint-initial-flow-velocity.svg" diff --git a/src/Mod/Fem/PyGui/_ViewProviderFemSolverCalculix.py b/src/Mod/Fem/PyGui/_ViewProviderFemSolverCalculix.py index 5df358a9ac..19341d19a0 100644 --- a/src/Mod/Fem/PyGui/_ViewProviderFemSolverCalculix.py +++ b/src/Mod/Fem/PyGui/_ViewProviderFemSolverCalculix.py @@ -33,7 +33,7 @@ import FemGui # for the panel -import FemToolsCcx +from femtools import ccxtools from PySide import QtCore from PySide import QtGui from PySide.QtCore import Qt @@ -223,7 +223,7 @@ class _TaskPanelFemSolverCalculix: self.form.pb_run_ccx.setText("Re-run CalculiX") self.femConsoleMessage("Loading result sets...") self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start)) - fea = FemToolsCcx.FemToolsCcx(None, self.solver_object) + fea = ccxtools.FemToolsCcx(None, self.solver_object) fea.reset_mesh_purge_results_checked() fea.inp_file_name = self.inp_file_name QApplication.setOverrideCursor(Qt.WaitCursor) @@ -258,7 +258,7 @@ class _TaskPanelFemSolverCalculix: if self.check_prerequisites_helper(): QApplication.setOverrideCursor(Qt.WaitCursor) self.inp_file_name = "" - fea = FemToolsCcx.FemToolsCcx(None, self.solver_object) + fea = ccxtools.FemToolsCcx(None, self.solver_object) fea.set_analysis_type(self.solver_object.AnalysisType) fea.update_objects() fea.write_inp_file() @@ -277,7 +277,7 @@ class _TaskPanelFemSolverCalculix: self.femConsoleMessage("Check dependencies...") self.form.l_time.setText('Time: {0:4.1f}: '.format(time.time() - self.Start)) - fea = FemToolsCcx.FemToolsCcx(None, self.solver_object) + fea = ccxtools.FemToolsCcx(None, self.solver_object) fea.update_objects() message = fea.check_prerequisites() if message != "": @@ -336,7 +336,7 @@ class _TaskPanelFemSolverCalculix: def select_thermomech_analysis(self): self.select_analysis_type('thermomech') - # That function overlaps with FemToolsCcx setup_working_dir and could be removed when the one from FemToolsCcx would be used + # That function overlaps with ccxtools setup_working_dir and could be removed when the one from ccxtools would be used def setup_working_dir(self): wd = self.solver_object.WorkingDir if not (os.path.isdir(wd)): diff --git a/src/Mod/Fem/FemConstraint.py b/src/Mod/Fem/PyObjects/FemConstraint.py similarity index 79% rename from src/Mod/Fem/FemConstraint.py rename to src/Mod/Fem/PyObjects/FemConstraint.py index 38b981b9a5..f80436f4f0 100644 --- a/src/Mod/Fem/FemConstraint.py +++ b/src/Mod/Fem/PyObjects/FemConstraint.py @@ -37,25 +37,3 @@ class Proxy(object): def __init__(self, obj): obj.Proxy = self - - -class ViewProxy(object): - """Proxy for FemSolverElmers View Provider.""" - - def __init__(self, vobj): - vobj.Proxy = self - - def attach(self, vobj): - default = coin.SoGroup() - vobj.addDisplayMode(default, "Default") - - def getDisplayModes(self, obj): - "Return a list of display modes." - modes = ["Default"] - return modes - - def getDefaultDisplayMode(self): - return "Default" - - def setDisplayMode(self, mode): - return mode diff --git a/src/Mod/Fem/PyObjects/_FemConstraintBodyHeatSource.py b/src/Mod/Fem/PyObjects/_FemConstraintBodyHeatSource.py index ba4fa5d848..8cadfa1905 100644 --- a/src/Mod/Fem/PyObjects/_FemConstraintBodyHeatSource.py +++ b/src/Mod/Fem/PyObjects/_FemConstraintBodyHeatSource.py @@ -26,12 +26,12 @@ __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -import FemConstraint +from . import FemConstraint class Proxy(FemConstraint.Proxy): - Type = "Fem::FemConstraintBodyHeatSource" + Type = "Fem::ConstraintBodyHeatSource" def __init__(self, obj): super(Proxy, self).__init__(obj) diff --git a/src/Mod/Fem/PyObjects/_FemConstraintElectrostaticPotential.py b/src/Mod/Fem/PyObjects/_FemConstraintElectrostaticPotential.py index ca79cb3e8f..31dc1ab135 100644 --- a/src/Mod/Fem/PyObjects/_FemConstraintElectrostaticPotential.py +++ b/src/Mod/Fem/PyObjects/_FemConstraintElectrostaticPotential.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -import FemConstraint +from . import FemConstraint class Proxy(FemConstraint.Proxy): diff --git a/src/Mod/Fem/PyObjects/_FemConstraintFlowVelocity.py b/src/Mod/Fem/PyObjects/_FemConstraintFlowVelocity.py index 80b3e5a566..c483fb071e 100644 --- a/src/Mod/Fem/PyObjects/_FemConstraintFlowVelocity.py +++ b/src/Mod/Fem/PyObjects/_FemConstraintFlowVelocity.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -import FemConstraint +from . import FemConstraint class Proxy(FemConstraint.Proxy): diff --git a/src/Mod/Fem/PyObjects/_FemConstraintInitialFlowVelocity.py b/src/Mod/Fem/PyObjects/_FemConstraintInitialFlowVelocity.py index 59b09571e5..d5e44ab10f 100644 --- a/src/Mod/Fem/PyObjects/_FemConstraintInitialFlowVelocity.py +++ b/src/Mod/Fem/PyObjects/_FemConstraintInitialFlowVelocity.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" -import FemConstraint +from . import FemConstraint class Proxy(FemConstraint.Proxy): diff --git a/src/Mod/Fem/PyObjects/_FemConstraintSelfWeight.py b/src/Mod/Fem/PyObjects/_FemConstraintSelfWeight.py index e590dc8cd1..0006101c97 100644 --- a/src/Mod/Fem/PyObjects/_FemConstraintSelfWeight.py +++ b/src/Mod/Fem/PyObjects/_FemConstraintSelfWeight.py @@ -38,7 +38,7 @@ class _FemConstraintSelfWeight: obj.Gravity_y = 0.0 obj.Gravity_z = -1.0 obj.Proxy = self - self.Type = "FemConstraintSelfWeight" + self.Type = "Fem::ConstraintSelfWeight" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemElementFluid1D.py b/src/Mod/Fem/PyObjects/_FemElementFluid1D.py index fd11e76dfd..aed662ef63 100644 --- a/src/Mod/Fem/PyObjects/_FemElementFluid1D.py +++ b/src/Mod/Fem/PyObjects/_FemElementFluid1D.py @@ -116,7 +116,7 @@ class _FemElementFluid1D: obj.InletFlowRateActive = False obj.OutletFlowRateActive = False obj.Proxy = self - self.Type = "FemElementFluid1D" + self.Type = "Fem::FemElementFluid1D" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemElementGeometry1D.py b/src/Mod/Fem/PyObjects/_FemElementGeometry1D.py index 2f1d0aa170..afb1adf55d 100644 --- a/src/Mod/Fem/PyObjects/_FemElementGeometry1D.py +++ b/src/Mod/Fem/PyObjects/_FemElementGeometry1D.py @@ -44,7 +44,7 @@ class _FemElementGeometry1D: obj.SectionType = _FemElementGeometry1D.known_beam_types obj.SectionType = 'Rectangular' obj.Proxy = self - self.Type = "FemElementGeometry1D" + self.Type = "Fem::FemElementGeometry1D" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemElementGeometry2D.py b/src/Mod/Fem/PyObjects/_FemElementGeometry2D.py index 1152c9eb40..ff6d525b63 100644 --- a/src/Mod/Fem/PyObjects/_FemElementGeometry2D.py +++ b/src/Mod/Fem/PyObjects/_FemElementGeometry2D.py @@ -34,7 +34,7 @@ class _FemElementGeometry2D: obj.addProperty("App::PropertyLength", "Thickness", "ShellThickness", "set thickness of the shell elements") obj.addProperty("App::PropertyLinkSubList", "References", "ShellThickness", "List of shell thickness shapes") obj.Proxy = self - self.Type = "FemElementGeometry2D" + self.Type = "Fem::FemElementGeometry2D" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemMaterial.py b/src/Mod/Fem/PyObjects/_FemMaterial.py index 3e97f2a77c..9a3a952217 100644 --- a/src/Mod/Fem/PyObjects/_FemMaterial.py +++ b/src/Mod/Fem/PyObjects/_FemMaterial.py @@ -35,7 +35,7 @@ class _FemMaterial: obj.addProperty("App::PropertyEnumeration", "Category", "Material", "Material type: fluid or solid") obj.Category = ['Solid', 'Fluid'] # used in TaskPanel obj.Proxy = self - self.Type = "FemMaterial" + self.Type = "Fem::Material" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemMaterialMechanicalNonlinear.py b/src/Mod/Fem/PyObjects/_FemMaterialMechanicalNonlinear.py index f818e36a2b..bc0c9881c5 100644 --- a/src/Mod/Fem/PyObjects/_FemMaterialMechanicalNonlinear.py +++ b/src/Mod/Fem/PyObjects/_FemMaterialMechanicalNonlinear.py @@ -32,7 +32,7 @@ class _FemMaterialMechanicalNonlinear: "The FemMaterialMechanicalNonlinear object" def __init__(self, obj): obj.Proxy = self - self.Type = "FemMaterialMechanicalNonlinear" + self.Type = "Fem::MaterialMechanicalNonlinear" obj.addProperty("App::PropertyLink", "LinearBaseMaterial", "Base", "Set the linear material the nonlinear builds upon.") diff --git a/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py b/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py index 17d759a33d..48fe799e6b 100644 --- a/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py +++ b/src/Mod/Fem/PyObjects/_FemMeshBoundaryLayer.py @@ -31,7 +31,7 @@ __url__ = "http://www.freecadweb.org" class _FemMeshBoundaryLayer: "The FemMeshBoundaryLayer object" def __init__(self, obj): - self.Type = "FemMeshBoundaryLayer" + self.Type = "Fem::FemMeshBoundaryLayer" self.Object = obj # keep a ref to the DocObj for nonGui usage obj.Proxy = self # link between App::DocumentObject to this object diff --git a/src/Mod/Fem/PyObjects/_FemMeshGmsh.py b/src/Mod/Fem/PyObjects/_FemMeshGmsh.py index d1ed847dd1..a20220add7 100644 --- a/src/Mod/Fem/PyObjects/_FemMeshGmsh.py +++ b/src/Mod/Fem/PyObjects/_FemMeshGmsh.py @@ -39,7 +39,7 @@ class _FemMeshGmsh(): known_mesh_algorithm_3D = ['Automatic', 'Delaunay', 'New Delaunay', 'Frontal', 'Frontal Delaunay', 'Frontal Hex', 'MMG3D', 'R-tree'] def __init__(self, obj): - self.Type = "FemMeshGmsh" + self.Type = "Fem::FemMeshGmsh" self.Object = obj # keep a ref to the DocObj for nonGui usage obj.Proxy = self # link between App::DocumentObject to this object diff --git a/src/Mod/Fem/PyObjects/_FemMeshGroup.py b/src/Mod/Fem/PyObjects/_FemMeshGroup.py index 84380dac6a..40afdf2b98 100644 --- a/src/Mod/Fem/PyObjects/_FemMeshGroup.py +++ b/src/Mod/Fem/PyObjects/_FemMeshGroup.py @@ -34,7 +34,7 @@ class _FemMeshGroup: obj.addProperty("App::PropertyBool", "UseLabel", "MeshGroupProperties", "The identifier used for export (True: Label, False: Name)") obj.addProperty("App::PropertyLinkSubList", "References", "MeshGroupShapes", "List of FEM mesh group shapes") obj.Proxy = self - self.Type = "FemMeshGroup" + self.Type = "Fem::FemMeshGroup" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemMeshRegion.py b/src/Mod/Fem/PyObjects/_FemMeshRegion.py index 49f7e1dde1..b851302d31 100644 --- a/src/Mod/Fem/PyObjects/_FemMeshRegion.py +++ b/src/Mod/Fem/PyObjects/_FemMeshRegion.py @@ -34,7 +34,7 @@ class _FemMeshRegion: obj.addProperty("App::PropertyLength", "CharacteristicLength", "MeshRegionProperties", "set characteristic length of FEM elements for this region") obj.addProperty("App::PropertyLinkSubList", "References", "MeshRegionShapes", "List of FEM mesh region shapes") obj.Proxy = self - self.Type = "FemMeshRegion" + self.Type = "Fem::FemMeshRegion" def execute(self, obj): return diff --git a/src/Mod/Fem/PyObjects/_FemMeshResult.py b/src/Mod/Fem/PyObjects/_FemMeshResult.py index 1e2f94c991..1fd69cfc2c 100644 --- a/src/Mod/Fem/PyObjects/_FemMeshResult.py +++ b/src/Mod/Fem/PyObjects/_FemMeshResult.py @@ -33,7 +33,7 @@ class _FemMeshResult(): """ def __init__(self, obj): - self.Type = "FemMeshResult" + self.Type = "Fem::FemMeshResult" self.Object = obj # keep a ref to the DocObj for nonGui usage obj.Proxy = self # link between App::DocumentObject to this object diff --git a/src/Mod/Fem/PyObjects/_FemResultMechanical.py b/src/Mod/Fem/PyObjects/_FemResultMechanical.py index 45f7cf9e44..1571ef0a60 100644 --- a/src/Mod/Fem/PyObjects/_FemResultMechanical.py +++ b/src/Mod/Fem/PyObjects/_FemResultMechanical.py @@ -33,7 +33,7 @@ class _FemResultMechanical(): """The Fem::_FemResultMechanical's Proxy python type, add result specific properties """ def __init__(self, obj): - self.Type = "FemResultMechanical" + self.Type = "Fem::FemResultMechanical" self.Object = obj # keep a ref to the DocObj for nonGui usage obj.Proxy = self # link between App::DocumentObject to this object diff --git a/src/Mod/Fem/PyObjects/_FemSolverCalculix.py b/src/Mod/Fem/PyObjects/_FemSolverCalculix.py index 2b4242694f..e936656ab9 100644 --- a/src/Mod/Fem/PyObjects/_FemSolverCalculix.py +++ b/src/Mod/Fem/PyObjects/_FemSolverCalculix.py @@ -28,14 +28,14 @@ __url__ = "http://www.freecadweb.org" # \ingroup FEM import FreeCAD -import FemToolsCcx +from femtools import ccxtools class _FemSolverCalculix(): """The Fem::FemSolver's Proxy python type, add solver specific properties """ def __init__(self, obj): - self.Type = "FemSolverCalculix" + self.Type = "Fem::FemSolverCalculix" self.Object = obj # keep a ref to the DocObj for nonGui usage obj.Proxy = self # link between App::DocumentObject to this object @@ -49,9 +49,9 @@ class _FemSolverCalculix(): # the working directory is not set, the solver working directory is only used if the preferences working directory is left blank obj.addProperty("App::PropertyEnumeration", "AnalysisType", "Fem", "Type of the analysis") - obj.AnalysisType = FemToolsCcx.FemToolsCcx.known_analysis_types + obj.AnalysisType = ccxtools.FemToolsCcx.known_analysis_types analysis_type = ccx_prefs.GetInt("AnalysisType", 0) - obj.AnalysisType = FemToolsCcx.FemToolsCcx.known_analysis_types[analysis_type] + obj.AnalysisType = ccxtools.FemToolsCcx.known_analysis_types[analysis_type] choices_geom_nonlinear = ["linear", "nonlinear"] obj.addProperty("App::PropertyEnumeration", "GeometricalNonlinearity", "Fem", "Set geometrical nonlinearity") diff --git a/src/Mod/Fem/TestFem.py b/src/Mod/Fem/TestFem.py index 732035e0bc..c675fe1a37 100644 --- a/src/Mod/Fem/TestFem.py +++ b/src/Mod/Fem/TestFem.py @@ -27,3 +27,4 @@ from femtest.testfemcommon import FemTest from femtest.testfemcommon import FemCcxAnalysisTest +from femtest.testfemcommon import SolverFrameWorkTest diff --git a/src/Mod/Fem/femcommands/commands.py b/src/Mod/Fem/femcommands/commands.py index e90579912c..31a21e25be 100644 --- a/src/Mod/Fem/femcommands/commands.py +++ b/src/Mod/Fem/femcommands/commands.py @@ -554,12 +554,12 @@ class _CommandFemSolverCalculix(CommandManager): def Activated(self): ccx_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Ccx") - use_old_solver_frame_work = ccx_prefs.GetBool("useOldSolverFrameWork", False) - use_new_solver_frame_work = ccx_prefs.GetBool("useNewSolverFrameWork", True) + use_old_solver_frame_work = ccx_prefs.GetBool("useOldSolverFrameWork", True) + use_new_solver_frame_work = ccx_prefs.GetBool("useNewSolverFrameWork", False) if use_old_solver_frame_work and not use_new_solver_frame_work: has_nonlinear_material_obj = False for m in self.active_analysis.Group: - if hasattr(m, "Proxy") and m.Proxy.Type == "FemMaterialMechanicalNonlinear": + if hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear": has_nonlinear_material_obj = True FreeCAD.ActiveDocument.openTransaction("Create SolverCalculix") FreeCADGui.addModule("ObjectsFem") @@ -633,8 +633,8 @@ class _CommandFemSolverRun(CommandManager): self.solver = self.selobj if hasattr(self.solver, "SolverType") and self.solver.SolverType == "FemSolverCalculix": - import FemToolsCcx - self.fea = FemToolsCcx.FemToolsCcx(None, self.solver) + from femtools import ccxtools + self.fea = ccxtools.FemToolsCcx(None, self.solver) self.fea.reset_mesh_purge_results_checked() message = self.fea.check_prerequisites() if message: diff --git a/src/Mod/Fem/femcommands/manager.py b/src/Mod/Fem/femcommands/manager.py index be1bf26c16..97f4f2ba42 100644 --- a/src/Mod/Fem/femcommands/manager.py +++ b/src/Mod/Fem/femcommands/manager.py @@ -116,7 +116,7 @@ class CommandManager(object): def gmsh_femmesh_selected(self): sel = FreeCADGui.Selection.getSelection() - if len(sel) == 1 and hasattr(sel[0], "Proxy") and sel[0].Proxy.Type == "FemMeshGmsh": + if len(sel) == 1 and hasattr(sel[0], "Proxy") and sel[0].Proxy.Type == "Fem::FemMeshGmsh": self.selobj = sel[0] return True else: @@ -140,7 +140,7 @@ class CommandManager(object): def has_no_nonlinear_material(self): "check if an nonlinear material exists which is already based on the selected material" for o in FreeCAD.ActiveDocument.Objects: - if hasattr(o, "Proxy") and o.Proxy is not None and o.Proxy.Type == "FemMaterialMechanicalNonlinear" and o.LinearBaseMaterial == self.selobj: + if hasattr(o, "Proxy") and o.Proxy is not None and o.Proxy.Type == "Fem::MaterialMechanicalNonlinear" and o.LinearBaseMaterial == self.selobj: # FreeCAD.Console.PrintError(o.Name + ' is based on the selected material: ' + self.selobj + '. Only one nonlinear object for each material allowed.\n') return False return True diff --git a/src/Mod/Fem/femmesh/meshtools.py b/src/Mod/Fem/femmesh/meshtools.py index a98420d246..a67d298379 100644 --- a/src/Mod/Fem/femmesh/meshtools.py +++ b/src/Mod/Fem/femmesh/meshtools.py @@ -400,13 +400,13 @@ def get_femelement_sets_from_group_data(femmesh, fem_objects): def get_elset_short_name(obj, i): - if hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemMaterial': + if hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::Material': return 'Mat' + str(i) - elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemElementGeometry1D': + elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementGeometry1D': return 'Beam' + str(i) - elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemElementFluid1D': + elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementFluid1D': return 'Fluid' + str(i) - elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'FemElementGeometry2D': + elif hasattr(obj, "Proxy") and obj.Proxy.Type == 'Fem::FemElementGeometry2D': return 'Shell' + str(i) else: print('Error: ', obj.Name, ' --> ', obj.Proxy.Type) diff --git a/src/Mod/Fem/femresult/resulttools.py b/src/Mod/Fem/femresult/resulttools.py index 29a0005d8c..3ece17fc3d 100644 --- a/src/Mod/Fem/femresult/resulttools.py +++ b/src/Mod/Fem/femresult/resulttools.py @@ -35,7 +35,7 @@ import FreeCAD def purge_results(analysis): for m in analysis.Group: if (m.isDerivedFrom('Fem::FemResultObject')): - if m.Mesh and hasattr(m.Mesh, "Proxy") and m.Mesh.Proxy.Type == "FemMeshResult": + if m.Mesh and hasattr(m.Mesh, "Proxy") and m.Mesh.Proxy.Type == "Fem::FemMeshResult": analysis.Document.removeObject(m.Mesh.Name) analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute() diff --git a/src/Mod/Fem/femsolver/calculix/solver.py b/src/Mod/Fem/femsolver/calculix/solver.py index 2501795173..312e6e8feb 100644 --- a/src/Mod/Fem/femsolver/calculix/solver.py +++ b/src/Mod/Fem/femsolver/calculix/solver.py @@ -31,7 +31,7 @@ import os import glob import FreeCAD -import FemUtils +import femtools.femutils as FemUtils from .. import run from .. import solverbase diff --git a/src/Mod/Fem/femsolver/calculix/tasks.py b/src/Mod/Fem/femsolver/calculix/tasks.py index 0c9627539e..bbd59acaa0 100644 --- a/src/Mod/Fem/femsolver/calculix/tasks.py +++ b/src/Mod/Fem/femsolver/calculix/tasks.py @@ -32,7 +32,7 @@ import subprocess import os.path import FreeCAD as App -import FemUtils +import femtools.femutils as FemUtils import feminout.importCcxFrdResults as importCcxFrdResults import feminout.importCcxDatResults as importCcxDatResults @@ -69,6 +69,11 @@ class Prepare(run.Prepare): c.beam_sections, c.shell_thicknesses, c.fluid_sections, self.solver.AnalysisType, self.directory) path = w.write_calculix_input_file() + # report to user if task succeeded + if path is not None: + self.pushStatus("Write completed!") + else: + self.pushStatus("Writing CalculiX input file failed!") _inputFileName = os.path.splitext(os.path.basename(path))[0] @@ -180,7 +185,7 @@ class _Container(object): material_linear_dict = {} material_linear_dict['Object'] = m self.materials_linear.append(material_linear_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemMaterialMechanicalNonlinear": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear": material_nonlinear_dict = {} material_nonlinear_dict['Object'] = m self.materials_nonlinear.append(material_nonlinear_dict) @@ -188,7 +193,7 @@ class _Container(object): fixed_constraint_dict = {} fixed_constraint_dict['Object'] = m self.fixed_constraints.append(fixed_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemConstraintSelfWeight": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::ConstraintSelfWeight": selfweight_dict = {} selfweight_dict['Object'] = m self.selfweight_constraints.append(selfweight_dict) @@ -230,15 +235,15 @@ class _Container(object): transform_constraint_dict = {} transform_constraint_dict['Object'] = m self.transform_constraints.append(transform_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry1D": beam_section_dict = {} beam_section_dict['Object'] = m self.beam_sections.append(beam_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementFluid1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementFluid1D": fluid_section_dict = {} fluid_section_dict['Object'] = m self.fluid_sections.append(fluid_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry2D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry2D": shell_thickness_dict = {} shell_thickness_dict['Object'] = m self.shell_thicknesses.append(shell_thickness_dict) diff --git a/src/Mod/Fem/femsolver/calculix/writer.py b/src/Mod/Fem/femsolver/calculix/writer.py index fb08884ff1..150c2424db 100644 --- a/src/Mod/Fem/femsolver/calculix/writer.py +++ b/src/Mod/Fem/femsolver/calculix/writer.py @@ -33,7 +33,7 @@ import os import sys import time import femmesh.meshtools as FemMeshTools -import FemInputWriter +from .. import writerbase as FemInputWriter import six @@ -69,14 +69,15 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter): print('FemInputWriterCcx --> self.file_name --> ' + self.file_name) def write_calculix_input_file(self): + timestart = time.clock() if self.solver_obj.SplitInputWriter is True: self.write_calculix_splitted_input_file() else: self.write_calculix_one_input_file() + print("Writing time input file: " + str(time.clock() - timestart) + ' \n') return self.file_name def write_calculix_one_input_file(self): - timestart = time.clock() self.femmesh.writeABAQUS(self.file_name, 1, False) # reopen file with "append" and add the analysis definition @@ -163,11 +164,8 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter): # footer self.write_footer(inpfile) inpfile.close() - print("Writing time input file: " + str(time.clock() - timestart) + ' \n') def write_calculix_splitted_input_file(self): - timestart = time.clock() - # reopen file with "append" and add the analysis definition # first open file with "write" to ensure that each new iteration of writing of inputfile starts in new file # first open file with "write" to ensure that the .writeABAQUS also writes in inputfile @@ -333,7 +331,6 @@ class FemInputWriterCcx(FemInputWriter.FemInputWriter): # footer self.write_footer(inpfileMain) inpfileMain.close() - print("Writing time input file: " + str(time.clock() - timestart) + ' \n') def write_element_sets_material_and_femelement_type(self, f): f.write('\n***********************************************************\n') diff --git a/src/Mod/Fem/femsolver/elmer/equations/elasticity.py b/src/Mod/Fem/femsolver/elmer/equations/elasticity.py index a15c150c2d..6625decf7e 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/elasticity.py +++ b/src/Mod/Fem/femsolver/elmer/equations/elasticity.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from ... import equationbase from . import linear diff --git a/src/Mod/Fem/femsolver/elmer/equations/electrostatic.py b/src/Mod/Fem/femsolver/elmer/equations/electrostatic.py index 98f543ec92..448c071795 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/electrostatic.py +++ b/src/Mod/Fem/femsolver/elmer/equations/electrostatic.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from ... import equationbase from . import linear diff --git a/src/Mod/Fem/femsolver/elmer/equations/equation.py b/src/Mod/Fem/femsolver/elmer/equations/equation.py index 8253640c94..b87b2b84ec 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/equation.py +++ b/src/Mod/Fem/femsolver/elmer/equations/equation.py @@ -28,7 +28,7 @@ __url__ = "http://www.freecadweb.org" import FreeCAD as App from ... import equationbase -import FemUtils +import femtools.femutils as FemUtils if App.GuiUp: import FreeCADGui as Gui diff --git a/src/Mod/Fem/femsolver/elmer/equations/flow.py b/src/Mod/Fem/femsolver/elmer/equations/flow.py index 786474d586..966f0a4956 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/flow.py +++ b/src/Mod/Fem/femsolver/elmer/equations/flow.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from . import nonlinear from ... import equationbase diff --git a/src/Mod/Fem/femsolver/elmer/equations/fluxsolver.py b/src/Mod/Fem/femsolver/elmer/equations/fluxsolver.py index bc69e11edd..553ef9043f 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/fluxsolver.py +++ b/src/Mod/Fem/femsolver/elmer/equations/fluxsolver.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from ... import equationbase from . import linear diff --git a/src/Mod/Fem/femsolver/elmer/equations/heat.py b/src/Mod/Fem/femsolver/elmer/equations/heat.py index f992982ac7..dfe246525e 100644 --- a/src/Mod/Fem/femsolver/elmer/equations/heat.py +++ b/src/Mod/Fem/femsolver/elmer/equations/heat.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from . import nonlinear from ... import equationbase diff --git a/src/Mod/Fem/femsolver/elmer/solver.py b/src/Mod/Fem/femsolver/elmer/solver.py index 89fe136590..da87cade57 100644 --- a/src/Mod/Fem/femsolver/elmer/solver.py +++ b/src/Mod/Fem/femsolver/elmer/solver.py @@ -26,7 +26,7 @@ __author__ = "Markus Hovorka" __url__ = "http://www.freecadweb.org" -import FemUtils +import femtools.femutils as FemUtils from .. import run from .. import solverbase diff --git a/src/Mod/Fem/femsolver/elmer/tasks.py b/src/Mod/Fem/femsolver/elmer/tasks.py index 826f48b781..2b1aa2fcfd 100644 --- a/src/Mod/Fem/femsolver/elmer/tasks.py +++ b/src/Mod/Fem/femsolver/elmer/tasks.py @@ -28,7 +28,7 @@ __url__ = "http://www.freecadweb.org" import subprocess import os.path -import FemUtils +import femtools.femutils as FemUtils from .. import run from .. import settings diff --git a/src/Mod/Fem/femsolver/elmer/writer.py b/src/Mod/Fem/femsolver/elmer/writer.py index ece37dc380..ac7160887a 100644 --- a/src/Mod/Fem/femsolver/elmer/writer.py +++ b/src/Mod/Fem/femsolver/elmer/writer.py @@ -33,7 +33,7 @@ import tempfile from FreeCAD import Units import Fem -import FemUtils +import femtools.femutils as FemUtils import femmesh.gmshtools as gmshtools from .. import settings from . import sifio @@ -262,7 +262,7 @@ class Writer(object): self._handled(obj) def _handleHeatBodyForces(self, bodies): - obj = self._getSingleMember("Fem::FemConstraintBodyHeatSource") + obj = self._getSingleMember("Fem::ConstraintBodyHeatSource") if obj is not None: for name in bodies: heatSource = getFromUi(obj.HeatFlux, "W/kg", "L^2*T^-3") diff --git a/src/Mod/Fem/femsolver/run.py b/src/Mod/Fem/femsolver/run.py index e595244e21..0d29f8ad3d 100644 --- a/src/Mod/Fem/femsolver/run.py +++ b/src/Mod/Fem/femsolver/run.py @@ -33,7 +33,7 @@ import threading import shutil import FreeCAD as App -import FemUtils +import femtools.femutils as FemUtils from . import settings from . import signal from . import task @@ -59,7 +59,7 @@ def getMachine(solver, path=None): def _isPathValid(m, path): - t = _dirTypes[m.directory] + t = _dirTypes.get(m.directory) # setting default None setting = settings.getDirSetting() if path is not None: return t is None and m.directory == path @@ -94,7 +94,7 @@ def _createMachine(solver, path, testmode): _dirTypes[path] = settings.CUSTOM m = solver.Proxy.createMachine(solver, path, testmode) oldMachine = _machines.get(solver) - if oldMachine is not None: + if oldMachine is not None and _dirTypes.get(oldMachine.directory) is not None: del _dirTypes[oldMachine.directory] _machines[solver] = m return m diff --git a/src/Mod/Fem/FemInputWriter.py b/src/Mod/Fem/femsolver/writerbase.py similarity index 100% rename from src/Mod/Fem/FemInputWriter.py rename to src/Mod/Fem/femsolver/writerbase.py diff --git a/src/Mod/Fem/femsolver/z88/solver.py b/src/Mod/Fem/femsolver/z88/solver.py index 2dbc533319..7f32be7689 100644 --- a/src/Mod/Fem/femsolver/z88/solver.py +++ b/src/Mod/Fem/femsolver/z88/solver.py @@ -31,7 +31,7 @@ import os import glob import FreeCAD -import FemUtils +import femtools.femutils as FemUtils from .. import run from .. import solverbase diff --git a/src/Mod/Fem/femsolver/z88/tasks.py b/src/Mod/Fem/femsolver/z88/tasks.py index b20ffe9ca3..e811992db6 100644 --- a/src/Mod/Fem/femsolver/z88/tasks.py +++ b/src/Mod/Fem/femsolver/z88/tasks.py @@ -31,7 +31,7 @@ import subprocess import os.path import FreeCAD as App -import FemUtils +import femtools.femutils as FemUtils import feminout.importZ88O2Results as importZ88O2Results from .. import run @@ -67,9 +67,14 @@ class Prepare(run.Prepare): c.beam_sections, c.shell_thicknesses, c.fluid_sections, self.solver.AnalysisType, self.directory) path = w.write_z88_input() + # report to user if task succeeded + if path is not None: + self.pushStatus("Write completed!") + else: + self.pushStatus("Writing Z88 input files failed!") _inputFileName = os.path.splitext(os.path.basename(path))[0] # AFAIK empty for z88 - print(path) - print(_inputFileName) + # print(path) + # print(_inputFileName) class Solve(run.Solve): @@ -178,7 +183,7 @@ class _Container(object): material_linear_dict = {} material_linear_dict['Object'] = m self.materials_linear.append(material_linear_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemMaterialMechanicalNonlinear": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear": material_nonlinear_dict = {} material_nonlinear_dict['Object'] = m self.materials_nonlinear.append(material_nonlinear_dict) @@ -186,7 +191,7 @@ class _Container(object): fixed_constraint_dict = {} fixed_constraint_dict['Object'] = m self.fixed_constraints.append(fixed_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemConstraintSelfWeight": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::ConstraintSelfWeight": selfweight_dict = {} selfweight_dict['Object'] = m self.selfweight_constraints.append(selfweight_dict) @@ -228,15 +233,15 @@ class _Container(object): transform_constraint_dict = {} transform_constraint_dict['Object'] = m self.transform_constraints.append(transform_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry1D": beam_section_dict = {} beam_section_dict['Object'] = m self.beam_sections.append(beam_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementFluid1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementFluid1D": fluid_section_dict = {} fluid_section_dict['Object'] = m self.fluid_sections.append(fluid_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry2D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry2D": shell_thickness_dict = {} shell_thickness_dict['Object'] = m self.shell_thicknesses.append(shell_thickness_dict) diff --git a/src/Mod/Fem/femsolver/z88/writer.py b/src/Mod/Fem/femsolver/z88/writer.py index 1b47af5d9e..89c98ae9b8 100644 --- a/src/Mod/Fem/femsolver/z88/writer.py +++ b/src/Mod/Fem/femsolver/z88/writer.py @@ -28,9 +28,10 @@ __url__ = "http://www.freecadweb.org" # @{ import FreeCAD +import time import femmesh.meshtools as FemMeshTools import feminout.importZ88Mesh as importZ88Mesh -import FemInputWriter +from .. import writerbase as FemInputWriter class FemInputWriterZ88(FemInputWriter.FemInputWriter): @@ -61,6 +62,7 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): print('FemInputWriterZ88 --> self.file_name --> ' + self.file_name) def write_z88_input(self): + timestart = time.clock() if not self.femnodes_mesh: self.femnodes_mesh = self.femmesh.Nodes if not self.femelement_table: @@ -75,6 +77,7 @@ class FemInputWriterZ88(FemInputWriter.FemInputWriter): self.write_z88_integration_properties() self.write_z88_memory_parameter() self.write_z88_solver_parameter() + print("Writing time input file: " + str(time.clock() - timestart) + ' \n') return self.dir_name def set_z88_elparam(self): diff --git a/src/Mod/Fem/femtest/testfemcommon.py b/src/Mod/Fem/femtest/testfemcommon.py index 3e0199a5d2..5fa3f602f6 100644 --- a/src/Mod/Fem/femtest/testfemcommon.py +++ b/src/Mod/Fem/femtest/testfemcommon.py @@ -25,7 +25,7 @@ # ***************************************************************************/ import Fem -import FemToolsCcx +from femtools import ccxtools import femresult.resulttools as resulttools import FreeCAD import ObjectsFem @@ -47,31 +47,33 @@ test_file_dir_elmer = home_path + 'Mod/Fem/femtest/testfiles/elmer/' # define some locations fot the analysis tests # since they are also used in the helper def which create results they should stay global for the module static_base_name = 'cube_static' -static_analysis_dir = temp_dir + 'FEM_static/' +static_analysis_dir = temp_dir + 'FEM_ccx_static/' static_save_fc_file = static_analysis_dir + static_base_name + '.fcstd' static_analysis_inp_file = test_file_dir + static_base_name + '.inp' static_expected_values = test_file_dir + "cube_static_expected_values" -static2_analysis_dir = temp_dir + 'FEM_static2/' -static2_save_fc_file = static2_analysis_dir + static_base_name + '2.fcstd' frequency_base_name = 'cube_frequency' -frequency_analysis_dir = temp_dir + 'FEM_frequency/' +frequency_analysis_dir = temp_dir + 'FEM_ccx_frequency/' frequency_save_fc_file = frequency_analysis_dir + frequency_base_name + '.fcstd' frequency_analysis_inp_file = test_file_dir + frequency_base_name + '.inp' frequency_expected_values = test_file_dir + "cube_frequency_expected_values" thermomech_base_name = 'spine_thermomech' -thermomech_analysis_dir = temp_dir + 'FEM_thermomech/' +thermomech_analysis_dir = temp_dir + 'FEM_ccx_thermomech/' thermomech_save_fc_file = thermomech_analysis_dir + thermomech_base_name + '.fcstd' thermomech_analysis_inp_file = test_file_dir + thermomech_base_name + '.inp' thermomech_expected_values = test_file_dir + "spine_thermomech_expected_values" Flow1D_thermomech_base_name = 'Flow1D_thermomech' -Flow1D_thermomech_analysis_dir = temp_dir + 'FEM_Flow1D_thermomech/' +Flow1D_thermomech_analysis_dir = temp_dir + 'FEM_ccx_Flow1D_thermomech/' Flow1D_thermomech_save_fc_file = Flow1D_thermomech_analysis_dir + Flow1D_thermomech_base_name + '.fcstd' Flow1D_thermomech_analysis_inp_file = test_file_dir + Flow1D_thermomech_base_name + '.inp' Flow1D_thermomech_expected_values = test_file_dir + "Flow1D_thermomech_expected_values" +solverframework_analysis_dir = temp_dir + 'FEM_solverframework/' +solverframework_save_fc_file = solverframework_analysis_dir + static_base_name + '.fcstd' + + class FemTest(unittest.TestCase): def setUp(self): @@ -345,7 +347,7 @@ class FemTest(unittest.TestCase): self.assertEqual(read_mflow, expected_mflow, "Values of read mflow result data are unexpected") self.assertEqual(read_npressure, expected_npressure, "Values of read npressure result data are unexpected") - def test_makeFemObjects(self): + def test_femobjects_make(self): doc = self.active_doc analysis = ObjectsFem.makeAnalysis(doc) @@ -401,6 +403,206 @@ class FemTest(unittest.TestCase): doc.recompute() self.assertEqual(len(analysis.Group), get_defmake_count() - 1) # because of the analysis itself count -1 + def test_femobjects_type(self): + doc = self.active_doc + + from femtools.femutils import typeOfObj + self.assertEqual('Fem::FemAnalysis', typeOfObj(ObjectsFem.makeAnalysis(doc))) + self.assertEqual('Fem::ConstraintBearing', typeOfObj(ObjectsFem.makeConstraintBearing(doc))) + self.assertEqual('Fem::ConstraintBodyHeatSource', typeOfObj(ObjectsFem.makeConstraintBodyHeatSource(doc))) + self.assertEqual('Fem::ConstraintContact', typeOfObj(ObjectsFem.makeConstraintContact(doc))) + self.assertEqual('Fem::ConstraintDisplacement', typeOfObj(ObjectsFem.makeConstraintDisplacement(doc))) + self.assertEqual('Fem::ConstraintElectrostaticPotential', typeOfObj(ObjectsFem.makeConstraintElectrostaticPotential(doc))) + self.assertEqual('Fem::ConstraintFixed', typeOfObj(ObjectsFem.makeConstraintFixed(doc))) + self.assertEqual('Fem::ConstraintFlowVelocity', typeOfObj(ObjectsFem.makeConstraintFlowVelocity(doc))) + self.assertEqual('Fem::ConstraintFluidBoundary', typeOfObj(ObjectsFem.makeConstraintFluidBoundary(doc))) + self.assertEqual('Fem::ConstraintForce', typeOfObj(ObjectsFem.makeConstraintForce(doc))) + self.assertEqual('Fem::ConstraintGear', typeOfObj(ObjectsFem.makeConstraintGear(doc))) + self.assertEqual('Fem::ConstraintHeatflux', typeOfObj(ObjectsFem.makeConstraintHeatflux(doc))) + self.assertEqual('Fem::ConstraintInitialFlowVelocity', typeOfObj(ObjectsFem.makeConstraintInitialFlowVelocity(doc))) + self.assertEqual('Fem::ConstraintInitialTemperature', typeOfObj(ObjectsFem.makeConstraintInitialTemperature(doc))) + self.assertEqual('Fem::ConstraintPlaneRotation', typeOfObj(ObjectsFem.makeConstraintPlaneRotation(doc))) + self.assertEqual('Fem::ConstraintPressure', typeOfObj(ObjectsFem.makeConstraintPressure(doc))) + self.assertEqual('Fem::ConstraintPulley', typeOfObj(ObjectsFem.makeConstraintPulley(doc))) + self.assertEqual('Fem::ConstraintSelfWeight', typeOfObj(ObjectsFem.makeConstraintSelfWeight(doc))) + self.assertEqual('Fem::ConstraintTemperature', typeOfObj(ObjectsFem.makeConstraintTemperature(doc))) + self.assertEqual('Fem::ConstraintTransform', typeOfObj(ObjectsFem.makeConstraintTransform(doc))) + self.assertEqual('Fem::FemElementFluid1D', typeOfObj(ObjectsFem.makeElementFluid1D(doc))) + self.assertEqual('Fem::FemElementGeometry1D', typeOfObj(ObjectsFem.makeElementGeometry1D(doc))) + self.assertEqual('Fem::FemElementGeometry2D', typeOfObj(ObjectsFem.makeElementGeometry2D(doc))) + materialsolid = ObjectsFem.makeMaterialSolid(doc) + self.assertEqual('Fem::Material', typeOfObj(ObjectsFem.makeMaterialFluid(doc))) + self.assertEqual('Fem::Material', typeOfObj(materialsolid)) + self.assertEqual('Fem::MaterialMechanicalNonlinear', typeOfObj(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid))) + mesh = ObjectsFem.makeMeshGmsh(doc) + self.assertEqual('Fem::FemMeshGmsh', typeOfObj(mesh)) + self.assertEqual('Fem::FemMeshBoundaryLayer', typeOfObj(ObjectsFem.makeMeshBoundaryLayer(doc, mesh))) + self.assertEqual('Fem::FemMeshGroup', typeOfObj(ObjectsFem.makeMeshGroup(doc, mesh))) + self.assertEqual('Fem::FemMeshRegion', typeOfObj(ObjectsFem.makeMeshRegion(doc, mesh))) + self.assertEqual('Fem::FemMeshShapeNetgenObject', typeOfObj(ObjectsFem.makeMeshNetgen(doc))) + self.assertEqual('Fem::FemMeshResult', typeOfObj(ObjectsFem.makeMeshResult(doc))) + self.assertEqual('Fem::FemResultMechanical', typeOfObj(ObjectsFem.makeResultMechanical(doc))) + solverelmer = ObjectsFem.makeSolverElmer(doc) + self.assertEqual('Fem::FemSolverCalculix', typeOfObj(ObjectsFem.makeSolverCalculixCcxTools(doc))) + self.assertEqual('Fem::FemSolverObjectCalculix', typeOfObj(ObjectsFem.makeSolverCalculix(doc))) + self.assertEqual('Fem::FemSolverObjectElmer', typeOfObj(solverelmer)) + self.assertEqual('Fem::FemSolverObjectZ88', typeOfObj(ObjectsFem.makeSolverZ88(doc))) + self.assertEqual('Fem::FemEquationElmerElasticity', typeOfObj(ObjectsFem.makeEquationElasticity(doc, solverelmer))) + self.assertEqual('Fem::FemEquationElmerElectrostatic', typeOfObj(ObjectsFem.makeEquationElectrostatic(doc, solverelmer))) + self.assertEqual('Fem::FemEquationElmerFlow', typeOfObj(ObjectsFem.makeEquationFlow(doc, solverelmer))) + self.assertEqual('Fem::FemEquationElmerFluxsolver', typeOfObj(ObjectsFem.makeEquationFluxsolver(doc, solverelmer))) + self.assertEqual('Fem::FemEquationElmerHeat', typeOfObj(ObjectsFem.makeEquationHeat(doc, solverelmer))) + # TODO: equation linear missing, equation nonlinear missing, use different type for fluid and solid material + + def test_femobjects_isoftypenew(self): + doc = self.active_doc + + from femtools.femutils import isOfTypeNew + self.assertTrue(isOfTypeNew(ObjectsFem.makeAnalysis(doc), 'Fem::FemAnalysis')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintBearing(doc), 'Fem::ConstraintBearing')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintBodyHeatSource(doc), 'Fem::ConstraintBodyHeatSource')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintContact(doc), 'Fem::ConstraintContact')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintDisplacement(doc), 'Fem::ConstraintDisplacement')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintElectrostaticPotential(doc), 'Fem::ConstraintElectrostaticPotential')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintFixed(doc), 'Fem::ConstraintFixed')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintFlowVelocity(doc), 'Fem::ConstraintFlowVelocity')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintFluidBoundary(doc), 'Fem::ConstraintFluidBoundary')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintForce(doc), 'Fem::ConstraintForce')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintGear(doc), 'Fem::ConstraintGear')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintHeatflux(doc), 'Fem::ConstraintHeatflux')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintInitialFlowVelocity(doc), 'Fem::ConstraintInitialFlowVelocity')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintInitialTemperature(doc), 'Fem::ConstraintInitialTemperature')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintPlaneRotation(doc), 'Fem::ConstraintPlaneRotation')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintPressure(doc), 'Fem::ConstraintPressure')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintPulley(doc), 'Fem::ConstraintPulley')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintSelfWeight(doc), 'Fem::ConstraintSelfWeight')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintTemperature(doc), 'Fem::ConstraintTemperature')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeConstraintTransform(doc), 'Fem::ConstraintTransform')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeElementFluid1D(doc), 'Fem::FemElementFluid1D')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeElementGeometry1D(doc), 'Fem::FemElementGeometry1D')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeElementGeometry2D(doc), 'Fem::FemElementGeometry2D')) + materialsolid = ObjectsFem.makeMaterialSolid(doc) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMaterialFluid(doc), 'Fem::Material')) + self.assertTrue(isOfTypeNew(materialsolid, 'Fem::Material')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid), 'Fem::MaterialMechanicalNonlinear')) + mesh = ObjectsFem.makeMeshGmsh(doc) + self.assertTrue(isOfTypeNew(mesh, 'Fem::FemMeshGmsh')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMeshBoundaryLayer(doc, mesh), 'Fem::FemMeshBoundaryLayer')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMeshGroup(doc, mesh), 'Fem::FemMeshGroup')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMeshRegion(doc, mesh), 'Fem::FemMeshRegion')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMeshNetgen(doc), 'Fem::FemMeshShapeNetgenObject')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeMeshResult(doc), 'Fem::FemMeshResult')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeResultMechanical(doc), 'Fem::FemResultMechanical')) + solverelmer = ObjectsFem.makeSolverElmer(doc) + self.assertTrue(isOfTypeNew(ObjectsFem.makeSolverCalculixCcxTools(doc), 'Fem::FemSolverCalculix')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeSolverCalculix(doc), 'Fem::FemSolverObjectCalculix')) + self.assertTrue(isOfTypeNew(solverelmer, 'Fem::FemSolverObjectElmer')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeSolverZ88(doc), 'Fem::FemSolverObjectZ88')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeEquationElasticity(doc, solverelmer), 'Fem::FemEquationElmerElasticity')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeEquationElectrostatic(doc, solverelmer), 'Fem::FemEquationElmerElectrostatic')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeEquationFlow(doc, solverelmer), 'Fem::FemEquationElmerFlow')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeEquationFluxsolver(doc, solverelmer), 'Fem::FemEquationElmerFluxsolver')) + self.assertTrue(isOfTypeNew(ObjectsFem.makeEquationHeat(doc, solverelmer), 'Fem::FemEquationElmerHeat')) + + def test_femobjects_derivedfromfem(self): + doc = self.active_doc + + from femtools.femutils import isDerivedFrom as isDerivedFromFem + self.assertTrue(isDerivedFromFem(ObjectsFem.makeAnalysis(doc), 'Fem::FemAnalysis')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintBearing(doc), 'Fem::ConstraintBearing')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintBodyHeatSource(doc), 'Fem::ConstraintBodyHeatSource')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintContact(doc), 'Fem::ConstraintContact')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintDisplacement(doc), 'Fem::ConstraintDisplacement')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintElectrostaticPotential(doc), 'Fem::ConstraintElectrostaticPotential')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintFixed(doc), 'Fem::ConstraintFixed')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintFlowVelocity(doc), 'Fem::ConstraintFlowVelocity')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintFluidBoundary(doc), 'Fem::ConstraintFluidBoundary')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintForce(doc), 'Fem::ConstraintForce')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintGear(doc), 'Fem::ConstraintGear')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintHeatflux(doc), 'Fem::ConstraintHeatflux')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintInitialFlowVelocity(doc), 'Fem::ConstraintInitialFlowVelocity')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintInitialTemperature(doc), 'Fem::ConstraintInitialTemperature')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintPlaneRotation(doc), 'Fem::ConstraintPlaneRotation')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintPressure(doc), 'Fem::ConstraintPressure')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintPulley(doc), 'Fem::ConstraintPulley')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintSelfWeight(doc), 'Fem::ConstraintSelfWeight')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintTemperature(doc), 'Fem::ConstraintTemperature')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeConstraintTransform(doc), 'Fem::ConstraintTransform')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeElementFluid1D(doc), 'Fem::FemElementFluid1D')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeElementGeometry1D(doc), 'Fem::FemElementGeometry1D')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeElementGeometry2D(doc), 'Fem::FemElementGeometry2D')) + materialsolid = ObjectsFem.makeMaterialSolid(doc) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMaterialFluid(doc), 'Fem::Material')) + self.assertTrue(isDerivedFromFem(materialsolid, 'Fem::Material')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid), 'Fem::MaterialMechanicalNonlinear')) + mesh = ObjectsFem.makeMeshGmsh(doc) + self.assertTrue(isDerivedFromFem(mesh, 'Fem::FemMeshGmsh')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMeshBoundaryLayer(doc, mesh), 'Fem::FemMeshBoundaryLayer')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMeshGroup(doc, mesh), 'Fem::FemMeshGroup')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMeshRegion(doc, mesh), 'Fem::FemMeshRegion')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMeshNetgen(doc), 'Fem::FemMeshShapeNetgenObject')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeMeshResult(doc), 'Fem::FemMeshResult')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeResultMechanical(doc), 'Fem::FemResultMechanical')) + solverelmer = ObjectsFem.makeSolverElmer(doc) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeSolverCalculixCcxTools(doc), 'Fem::FemSolverCalculix')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeSolverCalculix(doc), 'Fem::FemSolverObjectCalculix')) + self.assertTrue(isDerivedFromFem(solverelmer, 'Fem::FemSolverObjectElmer')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeSolverZ88(doc), 'Fem::FemSolverObjectZ88')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeEquationElasticity(doc, solverelmer), 'Fem::FemEquationElmerElasticity')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeEquationElectrostatic(doc, solverelmer), 'Fem::FemEquationElmerElectrostatic')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeEquationFlow(doc, solverelmer), 'Fem::FemEquationElmerFlow')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeEquationFluxsolver(doc, solverelmer), 'Fem::FemEquationElmerFluxsolver')) + self.assertTrue(isDerivedFromFem(ObjectsFem.makeEquationHeat(doc, solverelmer), 'Fem::FemEquationElmerHeat')) + + def test_femobjects_derivedfromstd(self): + doc = self.active_doc + + self.assertTrue(ObjectsFem.makeAnalysis(doc).isDerivedFrom('Fem::FemAnalysis')) + self.assertTrue(ObjectsFem.makeConstraintBearing(doc).isDerivedFrom('Fem::ConstraintBearing')) + self.assertTrue(ObjectsFem.makeConstraintBodyHeatSource(doc).isDerivedFrom('Fem::ConstraintPython')) + self.assertTrue(ObjectsFem.makeConstraintContact(doc).isDerivedFrom('Fem::ConstraintContact')) + self.assertTrue(ObjectsFem.makeConstraintDisplacement(doc).isDerivedFrom('Fem::ConstraintDisplacement')) + self.assertTrue(ObjectsFem.makeConstraintElectrostaticPotential(doc).isDerivedFrom('Fem::ConstraintPython')) + self.assertTrue(ObjectsFem.makeConstraintFixed(doc).isDerivedFrom('Fem::ConstraintFixed')) + self.assertTrue(ObjectsFem.makeConstraintFlowVelocity(doc).isDerivedFrom('Fem::ConstraintPython')) + self.assertTrue(ObjectsFem.makeConstraintFluidBoundary(doc).isDerivedFrom('Fem::ConstraintFluidBoundary')) + self.assertTrue(ObjectsFem.makeConstraintForce(doc).isDerivedFrom('Fem::ConstraintForce')) + self.assertTrue(ObjectsFem.makeConstraintGear(doc).isDerivedFrom('Fem::ConstraintGear')) + self.assertTrue(ObjectsFem.makeConstraintHeatflux(doc).isDerivedFrom('Fem::ConstraintHeatflux')) + self.assertTrue(ObjectsFem.makeConstraintInitialFlowVelocity(doc).isDerivedFrom('Fem::ConstraintPython')) + self.assertTrue(ObjectsFem.makeConstraintInitialTemperature(doc).isDerivedFrom('Fem::ConstraintInitialTemperature')) + self.assertTrue(ObjectsFem.makeConstraintPlaneRotation(doc).isDerivedFrom('Fem::ConstraintPlaneRotation')) + self.assertTrue(ObjectsFem.makeConstraintPressure(doc).isDerivedFrom('Fem::ConstraintPressure')) + self.assertTrue(ObjectsFem.makeConstraintPulley(doc).isDerivedFrom('Fem::ConstraintPulley')) + self.assertTrue(ObjectsFem.makeConstraintSelfWeight(doc).isDerivedFrom('Fem::ConstraintPython')) + self.assertTrue(ObjectsFem.makeConstraintTemperature(doc).isDerivedFrom('Fem::ConstraintTemperature')) + self.assertTrue(ObjectsFem.makeConstraintTransform(doc).isDerivedFrom('Fem::ConstraintTransform')) + self.assertTrue(ObjectsFem.makeElementFluid1D(doc).isDerivedFrom('Fem::FeaturePython')) + self.assertTrue(ObjectsFem.makeElementGeometry1D(doc).isDerivedFrom('Fem::FeaturePython')) + self.assertTrue(ObjectsFem.makeElementGeometry2D(doc).isDerivedFrom('Fem::FeaturePython')) + materialsolid = ObjectsFem.makeMaterialSolid(doc) + self.assertTrue(ObjectsFem.makeMaterialFluid(doc).isDerivedFrom('App::MaterialObjectPython')) + self.assertTrue(materialsolid.isDerivedFrom('App::MaterialObjectPython')) + self.assertTrue(ObjectsFem.makeMaterialMechanicalNonlinear(doc, materialsolid).isDerivedFrom('Fem::FeaturePython')) + mesh = ObjectsFem.makeMeshGmsh(doc) + self.assertTrue(mesh.isDerivedFrom('Fem::FemMeshObjectPython')) + self.assertTrue(ObjectsFem.makeMeshBoundaryLayer(doc, mesh).isDerivedFrom('Fem::FeaturePython')) + self.assertTrue(ObjectsFem.makeMeshGroup(doc, mesh).isDerivedFrom('Fem::FeaturePython')) + self.assertTrue(ObjectsFem.makeMeshRegion(doc, mesh).isDerivedFrom('Fem::FeaturePython')) + self.assertTrue(ObjectsFem.makeMeshNetgen(doc).isDerivedFrom('Fem::FemMeshShapeNetgenObject')) + self.assertTrue(ObjectsFem.makeMeshResult(doc).isDerivedFrom('Fem::FemMeshObjectPython')) + self.assertTrue(ObjectsFem.makeResultMechanical(doc).isDerivedFrom('Fem::FemResultObjectPython')) + solverelmer = ObjectsFem.makeSolverElmer(doc) + self.assertTrue(ObjectsFem.makeSolverCalculixCcxTools(doc).isDerivedFrom('Fem::FemSolverObjectPython')) + self.assertTrue(ObjectsFem.makeSolverCalculix(doc).isDerivedFrom('Fem::FemSolverObjectPython')) + self.assertTrue(solverelmer.isDerivedFrom('Fem::FemSolverObjectPython')) + self.assertTrue(ObjectsFem.makeSolverZ88(doc).isDerivedFrom('Fem::FemSolverObjectPython')) + self.assertTrue(ObjectsFem.makeEquationElasticity(doc, solverelmer).isDerivedFrom('App::FeaturePython')) + self.assertTrue(ObjectsFem.makeEquationElectrostatic(doc, solverelmer).isDerivedFrom('App::FeaturePython')) + self.assertTrue(ObjectsFem.makeEquationFlow(doc, solverelmer).isDerivedFrom('App::FeaturePython')) + self.assertTrue(ObjectsFem.makeEquationFluxsolver(doc, solverelmer).isDerivedFrom('App::FeaturePython')) + self.assertTrue(ObjectsFem.makeEquationHeat(doc, solverelmer).isDerivedFrom('App::FeaturePython')) + def test_pyimport_all_FEM_modules(self): # we're going to try to import all python modules from FreeCAD Fem pymodules = [] @@ -520,7 +722,7 @@ class FemCcxAnalysisTest(unittest.TestCase): self.active_doc.recompute() - fea = FemToolsCcx.FemToolsCcx(analysis, solver_object, test_mode=True) + fea = ccxtools.FemToolsCcx(analysis, solver_object, test_mode=True) fcc_print('Setting up working directory {}'.format(static_analysis_dir)) fea.setup_working_dir(static_analysis_dir) self.assertTrue(True if fea.working_dir == static_analysis_dir else False, @@ -528,7 +730,7 @@ class FemCcxAnalysisTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for static analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) + self.assertFalse(error, "ccxtools check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') @@ -541,8 +743,8 @@ class FemCcxAnalysisTest(unittest.TestCase): self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(static_analysis_inp_file, static_analysis_dir, mesh_name)) - ret = compare_inp_files(static_analysis_inp_file, static_analysis_dir + "/" + mesh_name + '.inp') - self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) + ret = compare_inp_files(static_analysis_inp_file, static_analysis_dir + mesh_name + '.inp') + self.assertFalse(ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) @@ -584,15 +786,15 @@ class FemCcxAnalysisTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for frequency analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) + self.assertFalse(error, "ccxtools check_prerequisites returned error message: {}".format(error)) fcc_print('Writing {}/{}.inp for frequency analysis'.format(frequency_analysis_dir, mesh_name)) error = fea.write_inp_file() self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(frequency_analysis_inp_file, frequency_analysis_dir, mesh_name)) - ret = compare_inp_files(frequency_analysis_inp_file, frequency_analysis_dir + "/" + mesh_name + '.inp') - self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) + ret = compare_inp_files(frequency_analysis_inp_file, frequency_analysis_dir + mesh_name + '.inp') + self.assertFalse(ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) @@ -619,78 +821,6 @@ class FemCcxAnalysisTest(unittest.TestCase): fcc_print('Save FreeCAD file for frequency analysis to {}...'.format(frequency_save_fc_file)) self.active_doc.saveAs(frequency_save_fc_file) - - # use new solver frame work ccx solver - fcc_print('Checking FEM new solver for new solver frame work...') - solver_ccx2_object = ObjectsFem.makeSolverCalculix(self.active_doc, 'SolverCalculiX') - solver_ccx2_object.GeometricalNonlinearity = 'linear' - solver_ccx2_object.ThermoMechSteadyState = False - solver_ccx2_object.MatrixSolverType = 'default' - solver_ccx2_object.IterationsControlParameterTimeUse = False - solver_ccx2_object.EigenmodesCount = 10 - solver_ccx2_object.EigenmodeHighLimit = 1000000.0 - solver_ccx2_object.EigenmodeLowLimit = 0.0 - self.assertTrue(solver_ccx2_object, "FemTest of new ccx solver failed") - analysis.addObject(solver_ccx2_object) - - fcc_print('Checking inpfile writing for new solver frame work...') - if not os.path.exists(static2_analysis_dir): # new solver frameworkd does explicit not create a non existing directory - os.makedirs(static2_analysis_dir) - - fcc_print('machine_ccx') - machine = solver_ccx2_object.Proxy.createMachine(solver_ccx2_object, static2_analysis_dir) - fcc_print(machine.testmode) - machine.target = femsolver.run.PREPARE - machine.start() - machine.join() # wait for the machine to finish. - fcc_print('Comparing {} to {}/{}.inp'.format(static_analysis_inp_file, static2_analysis_dir, mesh_name)) - ret = compare_inp_files(static_analysis_inp_file, static2_analysis_dir + mesh_name + '.inp') - self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) - - # use new solver frame work elmer solver - solver_elmer_object = ObjectsFem.makeSolverElmer(self.active_doc, 'SolverElmer') - self.assertTrue(solver_elmer_object, "FemTest of elmer solver failed") - analysis.addObject(solver_elmer_object) - solver_elmer_eqobj = ObjectsFem.makeEquationElasticity(self.active_doc, solver_elmer_object) - self.assertTrue(solver_elmer_eqobj, "FemTest of elmer elasticity equation failed") - - # set ThermalExpansionCoefficient, current elmer seams to need it even on simple elasticity analysis - mat = material_object.Material - mat['ThermalExpansionCoefficient'] = "0 um/m/K" # FIXME elmer elasticity needs the dictionary key, otherwise it fails - material_object.Material = mat - - mesh_gmsh = ObjectsFem.makeMeshGmsh(self.active_doc) - mesh_gmsh.CharacteristicLengthMin = "9 mm" - mesh_gmsh.FemMesh = mesh_object.FemMesh # elmer needs a GMHS mesh object, FIXME error message on Python solver run - mesh_gmsh.Part = box - analysis.addObject(mesh_gmsh) - self.active_doc.removeObject(mesh_object.Name) - - fcc_print('machine_elmer') - machine_elmer = solver_elmer_object.Proxy.createMachine(solver_elmer_object, static2_analysis_dir, True) - fcc_print(machine_elmer.testmode) - machine_elmer.target = femsolver.run.PREPARE - machine_elmer.start() - machine_elmer.join() # wait for the machine to finish. - - fcc_print('Test writing STARTINFO file') - fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'ELMERSOLVER_STARTINFO', static2_analysis_dir + 'ELMERSOLVER_STARTINFO')) - ret = compare_files(test_file_dir_elmer + 'ELMERSOLVER_STARTINFO', static2_analysis_dir + 'ELMERSOLVER_STARTINFO') - self.assertFalse(ret, "STARTINFO write file test failed.\n{}".format(ret)) - - fcc_print('Test writing case file') - fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'case.sif', static2_analysis_dir + 'case.sif')) - ret = compare_files(test_file_dir_elmer + 'case.sif', static2_analysis_dir + 'case.sif') - self.assertFalse(ret, "case write file test failed.\n{}".format(ret)) - - fcc_print('Test writing GMSH geo file') - fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'group_mesh.geo', static2_analysis_dir + 'group_mesh.geo')) - ret = compare_files(test_file_dir_elmer + 'group_mesh.geo', static2_analysis_dir + 'group_mesh.geo') - self.assertFalse(ret, "GMSH geo write file test failed.\n{}".format(ret)) - - fcc_print('Save FreeCAD file for static2 analysis to {}...'.format(static2_save_fc_file)) - self.active_doc.saveAs(static2_save_fc_file) - fcc_print('--------------- End of FEM tests static and frequency analysis ---------------') def test_thermomech_analysis(self): @@ -770,7 +900,7 @@ class FemCcxAnalysisTest(unittest.TestCase): self.active_doc.recompute() - fea = FemToolsCcx.FemToolsCcx(analysis, test_mode=True) + fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fcc_print('Setting up working directory {}'.format(thermomech_analysis_dir)) fea.setup_working_dir(thermomech_analysis_dir) self.assertTrue(True if fea.working_dir == thermomech_analysis_dir else False, @@ -782,7 +912,7 @@ class FemCcxAnalysisTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for thermo-mechanical analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) + self.assertFalse(error, "ccxtools check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') @@ -791,8 +921,8 @@ class FemCcxAnalysisTest(unittest.TestCase): self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(thermomech_analysis_inp_file, thermomech_analysis_dir, mesh_name)) - ret = compare_inp_files(thermomech_analysis_inp_file, thermomech_analysis_dir + "/" + mesh_name + '.inp') - self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) + ret = compare_inp_files(thermomech_analysis_inp_file, thermomech_analysis_dir + mesh_name + '.inp') + self.assertFalse(ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) @@ -1018,7 +1148,7 @@ class FemCcxAnalysisTest(unittest.TestCase): self.active_doc.recompute() - fea = FemToolsCcx.FemToolsCcx(analysis, test_mode=True) + fea = ccxtools.FemToolsCcx(analysis, test_mode=True) fcc_print('Setting up working directory {}'.format(Flow1D_thermomech_analysis_dir)) fea.setup_working_dir(Flow1D_thermomech_analysis_dir) self.assertTrue(True if fea.working_dir == Flow1D_thermomech_analysis_dir else False, @@ -1030,7 +1160,7 @@ class FemCcxAnalysisTest(unittest.TestCase): fcc_print('Checking FEM inp file prerequisites for thermo-mechanical analysis...') error = fea.check_prerequisites() - self.assertFalse(error, "FemToolsCcx check_prerequisites returned error message: {}".format(error)) + self.assertFalse(error, "ccxtools check_prerequisites returned error message: {}".format(error)) fcc_print('Checking FEM inp file write...') @@ -1039,8 +1169,8 @@ class FemCcxAnalysisTest(unittest.TestCase): self.assertFalse(error, "Writing failed") fcc_print('Comparing {} to {}/{}.inp'.format(Flow1D_thermomech_analysis_inp_file, Flow1D_thermomech_analysis_dir, mesh_name)) - ret = compare_inp_files(Flow1D_thermomech_analysis_inp_file, Flow1D_thermomech_analysis_dir + "/" + mesh_name + '.inp') - self.assertFalse(ret, "FemToolsCcx write_inp_file test failed.\n{}".format(ret)) + ret = compare_inp_files(Flow1D_thermomech_analysis_inp_file, Flow1D_thermomech_analysis_dir + mesh_name + '.inp') + self.assertFalse(ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) fcc_print('Setting up working directory to {} in order to read simulated calculations'.format(test_file_dir)) fea.setup_working_dir(test_file_dir) @@ -1075,6 +1205,166 @@ class FemCcxAnalysisTest(unittest.TestCase): pass +class SolverFrameWorkTest(unittest.TestCase): + + def setUp(self): + try: + FreeCAD.setActiveDocument("FemTest") + except: + FreeCAD.newDocument("FemTest") + finally: + FreeCAD.setActiveDocument("FemTest") + self.active_doc = FreeCAD.ActiveDocument + + def test_solver_framework(self): + fcc_print('--------------- Start of FEM tests solver frame work ---------------') + box = self.active_doc.addObject("Part::Box", "Box") + fcc_print('Checking FEM new analysis...') + analysis = ObjectsFem.makeAnalysis(self.active_doc, 'Analysis') + self.assertTrue(analysis, "FemTest of new analysis failed") + + fcc_print('Checking FEM new solver...') + solver_object = ObjectsFem.makeSolverCalculixCcxTools(self.active_doc, 'CalculiX') + solver_object.GeometricalNonlinearity = 'linear' + solver_object.ThermoMechSteadyState = False + solver_object.MatrixSolverType = 'default' + solver_object.IterationsControlParameterTimeUse = False + solver_object.EigenmodesCount = 10 + solver_object.EigenmodeHighLimit = 1000000.0 + solver_object.EigenmodeLowLimit = 0.0 + self.assertTrue(solver_object, "FemTest of new solver failed") + analysis.addObject(solver_object) + + fcc_print('Checking FEM new material...') + material_object = ObjectsFem.makeMaterialSolid(self.active_doc, 'MechanicalMaterial') + mat = material_object.Material + mat['Name'] = "Steel-Generic" + mat['YoungsModulus'] = "200000 MPa" + mat['PoissonRatio'] = "0.30" + mat['Density'] = "7900 kg/m^3" + material_object.Material = mat + self.assertTrue(material_object, "FemTest of new material failed") + analysis.addObject(material_object) + + fcc_print('Checking FEM new fixed constraint...') + fixed_constraint = self.active_doc.addObject("Fem::ConstraintFixed", "FemConstraintFixed") + fixed_constraint.References = [(box, "Face1")] + self.assertTrue(fixed_constraint, "FemTest of new fixed constraint failed") + analysis.addObject(fixed_constraint) + + fcc_print('Checking FEM new force constraint...') + force_constraint = self.active_doc.addObject("Fem::ConstraintForce", "FemConstraintForce") + force_constraint.References = [(box, "Face6")] + force_constraint.Force = 40000.0 + force_constraint.Direction = (box, ["Edge5"]) + self.active_doc.recompute() + force_constraint.Reversed = True + self.active_doc.recompute() + self.assertTrue(force_constraint, "FemTest of new force constraint failed") + analysis.addObject(force_constraint) + + fcc_print('Checking FEM new pressure constraint...') + pressure_constraint = self.active_doc.addObject("Fem::ConstraintPressure", "FemConstraintPressure") + pressure_constraint.References = [(box, "Face2")] + pressure_constraint.Pressure = 1000.0 + pressure_constraint.Reversed = False + self.assertTrue(pressure_constraint, "FemTest of new pressure constraint failed") + analysis.addObject(pressure_constraint) + + fcc_print('Checking FEM new mesh...') + from .testfiles.ccx.cube_mesh import create_nodes_cube + from .testfiles.ccx.cube_mesh import create_elements_cube + mesh = Fem.FemMesh() + ret = create_nodes_cube(mesh) + self.assertTrue(ret, "Import of mesh nodes failed") + ret = create_elements_cube(mesh) + self.assertTrue(ret, "Import of mesh volumes failed") + mesh_object = self.active_doc.addObject('Fem::FemMeshObject', mesh_name) + mesh_object.FemMesh = mesh + self.assertTrue(mesh, "FemTest of new mesh failed") + analysis.addObject(mesh_object) + + self.active_doc.recompute() + + # solver frame work ccx solver + fcc_print('Checking FEM solver for solver frame work...') + solver_ccx2_object = ObjectsFem.makeSolverCalculix(self.active_doc, 'SolverCalculiX') + solver_ccx2_object.GeometricalNonlinearity = 'linear' + solver_ccx2_object.ThermoMechSteadyState = False + solver_ccx2_object.MatrixSolverType = 'default' + solver_ccx2_object.IterationsControlParameterTimeUse = False + solver_ccx2_object.EigenmodesCount = 10 + solver_ccx2_object.EigenmodeHighLimit = 1000000.0 + solver_ccx2_object.EigenmodeLowLimit = 0.0 + self.assertTrue(solver_ccx2_object, "FemTest of new ccx solver failed") + analysis.addObject(solver_ccx2_object) + + fcc_print('Checking inpfile writing for solverframework_save_fc_file frame work...') + if not os.path.exists(solverframework_analysis_dir): # solver frameworkd does explicit not create a non existing directory + os.makedirs(solverframework_analysis_dir) + + fcc_print('machine_ccx') + machine_ccx = solver_ccx2_object.Proxy.createMachine(solver_ccx2_object, solverframework_analysis_dir) + fcc_print('Machine testmode: ' + str(machine_ccx.testmode)) + machine_ccx.target = femsolver.run.PREPARE + machine_ccx.start() + machine_ccx.join() # wait for the machine to finish. + fcc_print('Comparing {} to {}/{}.inp'.format(static_analysis_inp_file, solverframework_analysis_dir, mesh_name)) + ret = compare_inp_files(static_analysis_inp_file, solverframework_analysis_dir + mesh_name + '.inp') + self.assertFalse(ret, "ccxtools write_inp_file test failed.\n{}".format(ret)) + + # use solver frame work elmer solver + solver_elmer_object = ObjectsFem.makeSolverElmer(self.active_doc, 'SolverElmer') + self.assertTrue(solver_elmer_object, "FemTest of elmer solver failed") + analysis.addObject(solver_elmer_object) + solver_elmer_eqobj = ObjectsFem.makeEquationElasticity(self.active_doc, solver_elmer_object) + self.assertTrue(solver_elmer_eqobj, "FemTest of elmer elasticity equation failed") + + # set ThermalExpansionCoefficient, current elmer seams to need it even on simple elasticity analysis + mat = material_object.Material + mat['ThermalExpansionCoefficient'] = "0 um/m/K" # FIXME elmer elasticity needs the dictionary key, otherwise it fails + material_object.Material = mat + + mesh_gmsh = ObjectsFem.makeMeshGmsh(self.active_doc) + mesh_gmsh.CharacteristicLengthMin = "9 mm" + mesh_gmsh.FemMesh = mesh_object.FemMesh # elmer needs a GMHS mesh object, FIXME error message on Python solver run + mesh_gmsh.Part = box + analysis.addObject(mesh_gmsh) + self.active_doc.removeObject(mesh_object.Name) + + fcc_print('machine_elmer') + machine_elmer = solver_elmer_object.Proxy.createMachine(solver_elmer_object, solverframework_analysis_dir, True) + fcc_print('Machine testmode: ' + str(machine_elmer.testmode)) + machine_elmer.target = femsolver.run.PREPARE + machine_elmer.start() + machine_elmer.join() # wait for the machine to finish. + + ''' + fcc_print('Test writing STARTINFO file') + fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'ELMERSOLVER_STARTINFO', solverframework_analysis_dir + 'ELMERSOLVER_STARTINFO')) + ret = compare_files(test_file_dir_elmer + 'ELMERSOLVER_STARTINFO', solverframework_analysis_dir + 'ELMERSOLVER_STARTINFO') + self.assertFalse(ret, "STARTINFO write file test failed.\n{}".format(ret)) + + fcc_print('Test writing case file') + fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'case.sif', solverframework_analysis_dir + 'case.sif')) + ret = compare_files(test_file_dir_elmer + 'case.sif', solverframework_analysis_dir + 'case.sif') + self.assertFalse(ret, "case write file test failed.\n{}".format(ret)) + + fcc_print('Test writing GMSH geo file') + fcc_print('Comparing {} to {}'.format(test_file_dir_elmer + 'group_mesh.geo', solverframework_analysis_dir + 'group_mesh.geo')) + ret = compare_files(test_file_dir_elmer + 'group_mesh.geo', solverframework_analysis_dir + 'group_mesh.geo') + self.assertFalse(ret, "GMSH geo write file test failed.\n{}".format(ret)) + ''' + + fcc_print('Save FreeCAD file for static2 analysis to {}...'.format(solverframework_save_fc_file)) + self.active_doc.saveAs(solverframework_save_fc_file) + fcc_print('--------------- End of FEM tests solver frame work ---------------') + + def tearDown(self): + FreeCAD.closeDocument("FemTest") + pass + + # helpers def fcc_print(message): FreeCAD.Console.PrintMessage('{} \n'.format(message)) @@ -1214,7 +1504,7 @@ def create_test_results(): # static and frequency cube FreeCAD.open(static_save_fc_file) FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) - fea = FemToolsCcx.FemToolsCcx() + fea = ccxtools.FemToolsCcx() print("create static result files") fea.reset_all() @@ -1259,7 +1549,7 @@ def create_test_results(): print("create thermomech result files") FreeCAD.open(thermomech_save_fc_file) FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) - fea = FemToolsCcx.FemToolsCcx() + fea = ccxtools.FemToolsCcx() fea.reset_all() fea.run() fea.load_results() @@ -1283,7 +1573,7 @@ def create_test_results(): print("create Flow1D result files") FreeCAD.open(Flow1D_thermomech_save_fc_file) FemGui.setActiveAnalysis(FreeCAD.ActiveDocument.Analysis) - fea = FemToolsCcx.FemToolsCcx() + fea = ccxtools.FemToolsCcx() fea.reset_all() fea.run() fea.load_results() diff --git a/src/Mod/Fem/femtools/__init__.py b/src/Mod/Fem/femtools/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/src/Mod/Fem/FemToolsCcx.py b/src/Mod/Fem/femtools/ccxtools.py similarity index 92% rename from src/Mod/Fem/FemToolsCcx.py rename to src/Mod/Fem/femtools/ccxtools.py index cd33505317..b65924185a 100644 --- a/src/Mod/Fem/FemToolsCcx.py +++ b/src/Mod/Fem/femtools/ccxtools.py @@ -89,7 +89,7 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): def purge_results(self): for m in self.analysis.Group: if (m.isDerivedFrom('Fem::FemResultObject')): - if m.Mesh and hasattr(m.Mesh, "Proxy") and m.Mesh.Proxy.Type == "FemMeshResult": + if m.Mesh and hasattr(m.Mesh, "Proxy") and m.Mesh.Proxy.Type == "Fem::FemMeshResult": self.analysis.Document.removeObject(m.Mesh.Name) self.analysis.Document.removeObject(m.Name) FreeCAD.ActiveDocument.recompute() @@ -124,72 +124,53 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): ## @var mesh # mesh of the analysis. Used to generate .inp file and to show results self.mesh = None - ## @var elmer_free_text - # Free text input used only by elmer (for sif file) - self.elmer_free_text = None ## @var materials_linear - # set of linear materials from the analysis. Updated with update_objects - # Individual materials are "App::MaterialObjectPython" type + # list of linear materials from the analysis. Updated with update_objects self.materials_linear = [] ## @var materials_nonlinear - # set of nonlinear materials from the analysis. Updated with update_objects - # Individual materials are Proxy.Type "FemMaterialMechanicalNonlinear" + # list of nonlinear materials from the analysis. Updated with update_objects self.materials_nonlinear = [] ## @var fixed_constraints - # set of fixed constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintFixed" type + # list of fixed constraints from the analysis. Updated with update_objects self.fixed_constraints = [] ## @var selfweight_constraints - # set of selfweight constraints from the analysis. Updated with update_objects - # Individual constraints are Proxy.Type "FemConstraintSelfWeight" + # list of selfweight constraints from the analysis. Updated with update_objects self.selfweight_constraints = [] ## @var force_constraints - # set of force constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintForce" type + # list of force constraints from the analysis. Updated with update_objects self.force_constraints = [] ## @var pressure_constraints - # set of pressure constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintPressure" type + # list of pressure constraints from the analysis. Updated with update_objects self.pressure_constraints = [] ## @var beam_sections - # set of beam sections from the analysis. Updated with update_objects - # Individual beam sections are Proxy.Type "FemElementGeometry1D" + # list of beam sections from the analysis. Updated with update_objects self.beam_sections = [] ## @var fluid_sections - # set of fluid sections from the analysis. Updated with update_objects - # Individual fluid sections are Proxy.Type "FemElementFluid1D" + # list of fluid sections from the analysis. Updated with update_objects self.fluid_sections = [] ## @var shell_thicknesses - # set of shell thicknesses from the analysis. Updated with update_objects - # Individual shell thicknesses are Proxy.Type "FemElementGeometry2D" + # list of shell thicknesses from the analysis. Updated with update_objects self.shell_thicknesses = [] ## @var displacement_constraints - # set of displacements for the analysis. Updated with update_objects - # Individual displacement_constraints are Proxy.Type "FemConstraintDisplacement" + # list of displacements for the analysis. Updated with update_objects self.displacement_constraints = [] ## @var temperature_constraints - # set of temperatures for the analysis. Updated with update_objects - # Individual temperature_constraints are Proxy.Type "FemConstraintTemperature" + # list of temperatures for the analysis. Updated with update_objects self.temperature_constraints = [] ## @var heatflux_constraints - # set of heatflux constraints for the analysis. Updated with update_objects - # Individual heatflux_constraints are Proxy.Type "FemConstraintHeatflux" + # list of heatflux constraints for the analysis. Updated with update_objects self.heatflux_constraints = [] ## @var initialtemperature_constraints - # set of initial temperatures for the analysis. Updated with update_objects - # Individual initialTemperature_constraints are Proxy.Type "FemConstraintInitialTemperature" + # list of initial temperatures for the analysis. Updated with update_objects self.initialtemperature_constraints = [] ## @var planerotation_constraints - # set of plane rotation constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintPlaneRotation" type + # list of plane rotation constraints from the analysis. Updated with update_objects self.planerotation_constraints = [] ## @var contact_constraints - # set of contact constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintContact" type + # list of contact constraints from the analysis. Updated with update_objects self.contact_constraints = [] ## @var transform_constraints - # set of transform constraints from the analysis. Updated with update_objects - # Individual constraints are "Fem::ConstraintTransform" type + # list of transform constraints from the analysis. Updated with update_objects self.transform_constraints = [] found_solver_for_use = False @@ -213,18 +194,11 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): self.mesh = m else: raise Exception('FEM: Multiple mesh in analysis not yet supported!') - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElmerFreeText": - if self.elmer_free_text is None: - self.elmer_free_text = m - else: - raise Exception( - 'FEM: Multiple free text objects ' - 'in analysis not supported!') elif m.isDerivedFrom("App::MaterialObjectPython"): material_linear_dict = {} material_linear_dict['Object'] = m self.materials_linear.append(material_linear_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemMaterialMechanicalNonlinear": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear": material_nonlinear_dict = {} material_nonlinear_dict['Object'] = m self.materials_nonlinear.append(material_nonlinear_dict) @@ -232,7 +206,7 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): fixed_constraint_dict = {} fixed_constraint_dict['Object'] = m self.fixed_constraints.append(fixed_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemConstraintSelfWeight": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::ConstraintSelfWeight": selfweight_dict = {} selfweight_dict['Object'] = m self.selfweight_constraints.append(selfweight_dict) @@ -273,15 +247,15 @@ class FemToolsCcx(QtCore.QRunnable, QtCore.QObject): transform_constraint_dict = {} transform_constraint_dict['Object'] = m self.transform_constraints.append(transform_constraint_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry1D": beam_section_dict = {} beam_section_dict['Object'] = m self.beam_sections.append(beam_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementFluid1D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementFluid1D": fluid_section_dict = {} fluid_section_dict['Object'] = m self.fluid_sections.append(fluid_section_dict) - elif hasattr(m, "Proxy") and m.Proxy.Type == "FemElementGeometry2D": + elif hasattr(m, "Proxy") and m.Proxy.Type == "Fem::FemElementGeometry2D": shell_thickness_dict = {} shell_thickness_dict['Object'] = m self.shell_thicknesses.append(shell_thickness_dict) diff --git a/src/Mod/Fem/FemUtils.py b/src/Mod/Fem/femtools/femutils.py similarity index 85% rename from src/Mod/Fem/FemUtils.py rename to src/Mod/Fem/femtools/femutils.py index 3177f9907b..6dccf67d47 100644 --- a/src/Mod/Fem/FemUtils.py +++ b/src/Mod/Fem/femtools/femutils.py @@ -1,6 +1,7 @@ # *************************************************************************** # * * # * Copyright (c) 2017 - Markus Hovorka * +# * Copyright (c) 2018 - 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) * @@ -22,7 +23,7 @@ __title__ = "FEM Utilities" -__author__ = "Markus Hovorka" +__author__ = "Markus Hovorka, Bernd Hahnebach" __url__ = "http://www.freecadweb.org" @@ -73,6 +74,21 @@ def getSingleMember(analysis, t): return objs[0] if objs else None +def typeOfObj(obj): + '''returns objects TypeId (C++ objects) or Proxy.Type (Python objects)''' + if hasattr(obj, "Proxy") and hasattr(obj.Proxy, "Type"): + return obj.Proxy.Type + return obj.TypeId + + +def isOfTypeNew(obj, ty): + '''returns if an object is of a given TypeId (C++ objects) or Proxy.Type (Python objects)''' + if typeOfObj(obj) == ty: + return True + else: + return False + + def isOfType(obj, t): if hasattr(obj, "Proxy") and hasattr(obj.Proxy, "Type"): return obj.Proxy.Type == t