Merge pull request #1210 from berndhahnebach/bhbdev116

FEM: lots of small fixes, typos, unit test improvements, package improvements
This commit is contained in:
Yorik van Havre
2018-01-11 11:16:13 -02:00
committed by GitHub
54 changed files with 599 additions and 269 deletions

View File

@@ -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();

View File

@@ -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
)

View File

@@ -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>

View File

@@ -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

View 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

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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)):

View File

@@ -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

View File

@@ -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)

View File

@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
import FemConstraint
from . import FemConstraint
class Proxy(FemConstraint.Proxy):

View File

@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
import FemConstraint
from . import FemConstraint
class Proxy(FemConstraint.Proxy):

View File

@@ -26,7 +26,7 @@ __author__ = "Markus Hovorka, Bernd Hahnebach"
__url__ = "http://www.freecadweb.org"
import FemConstraint
from . import FemConstraint
class Proxy(FemConstraint.Proxy):

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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.")

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -27,3 +27,4 @@
from femtest.testfemcommon import FemTest
from femtest.testfemcommon import FemCcxAnalysisTest
from femtest.testfemcommon import SolverFrameWorkTest

View File

@@ -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:

View File

@@ -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

View File

@@ -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)

View File

@@ -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()

View File

@@ -31,7 +31,7 @@ import os
import glob
import FreeCAD
import FemUtils
import femtools.femutils as FemUtils
from .. import run
from .. import solverbase

View File

@@ -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)

View File

@@ -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')

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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")

View File

@@ -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

View File

@@ -31,7 +31,7 @@ import os
import glob
import FreeCAD
import FemUtils
import femtools.femutils as FemUtils
from .. import run
from .. import solverbase

View File

@@ -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)

View File

@@ -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):

View File

@@ -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()

View File

View 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)

View File

@@ -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