Merge pull request #1210 from berndhahnebach/bhbdev116
FEM: lots of small fixes, typos, unit test improvements, package improvements
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>536</width>
|
||||
<height>768</height>
|
||||
<height>886</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@@ -28,7 +28,7 @@
|
||||
<enum>Qt::LeftToRight</enum>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>FreeCAD FEM Solver frame work</string>
|
||||
<string>CalculiX solver base</string>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop</set>
|
||||
@@ -73,7 +73,7 @@
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>General FEM solver framework</string>
|
||||
<string>General FEM solver framework (new)</string>
|
||||
</property>
|
||||
<property name="prefPath" stdset="0">
|
||||
<cstring>Mod/Fem/Ccx</cstring>
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
53
src/Mod/Fem/PyGui/ViewProviderFemConstraint.py
Normal file
53
src/Mod/Fem/PyGui/ViewProviderFemConstraint.py
Normal file
@@ -0,0 +1,53 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2017 - Markus Hovorka <m.hovorka@live.de> *
|
||||
# * *
|
||||
# * 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
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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)):
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
|
||||
import FemConstraint
|
||||
from . import FemConstraint
|
||||
|
||||
|
||||
class Proxy(FemConstraint.Proxy):
|
||||
|
||||
@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
|
||||
import FemConstraint
|
||||
from . import FemConstraint
|
||||
|
||||
|
||||
class Proxy(FemConstraint.Proxy):
|
||||
|
||||
@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
|
||||
__url__ = "http://www.freecadweb.org"
|
||||
|
||||
|
||||
import FemConstraint
|
||||
from . import FemConstraint
|
||||
|
||||
|
||||
class Proxy(FemConstraint.Proxy):
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.")
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -27,3 +27,4 @@
|
||||
|
||||
from femtest.testfemcommon import FemTest
|
||||
from femtest.testfemcommon import FemCcxAnalysisTest
|
||||
from femtest.testfemcommon import SolverFrameWorkTest
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -31,7 +31,7 @@ import os
|
||||
import glob
|
||||
|
||||
import FreeCAD
|
||||
import FemUtils
|
||||
import femtools.femutils as FemUtils
|
||||
|
||||
from .. import run
|
||||
from .. import solverbase
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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')
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -31,7 +31,7 @@ import os
|
||||
import glob
|
||||
|
||||
import FreeCAD
|
||||
import FemUtils
|
||||
import femtools.femutils as FemUtils
|
||||
|
||||
from .. import run
|
||||
from .. import solverbase
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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()
|
||||
|
||||
0
src/Mod/Fem/femtools/__init__.py
Normal file
0
src/Mod/Fem/femtools/__init__.py
Normal file
@@ -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)
|
||||
@@ -1,6 +1,7 @@
|
||||
# ***************************************************************************
|
||||
# * *
|
||||
# * Copyright (c) 2017 - Markus Hovorka <m.hovorka@live.de> *
|
||||
# * Copyright (c) 2018 - Bernd Hahnebach <bernd@bimstatik.org> *
|
||||
# * *
|
||||
# * 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
|
||||
Reference in New Issue
Block a user