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