[FEM] Elmer add support for nonlinear elasticity solver

- adds new equation "Deformation" (this name since the stress solver got in FreeCAD the misleading name "elasticity")

- this way change icon of elastic solver to make the difference clear
This commit is contained in:
Uwe
2023-03-21 18:05:33 +01:00
parent cb21604494
commit 2d3953f65f
13 changed files with 512 additions and 11 deletions

View File

@@ -259,6 +259,8 @@ SET(FemSolverElmer_SRCS
SET(FemSolverElmerEquations_SRCS
femsolver/elmer/equations/__init__.py
femsolver/elmer/equations/deformation.py
femsolver/elmer/equations/deformation_writer.py
femsolver/elmer/equations/elasticity.py
femsolver/elmer/equations/elasticity_writer.py
femsolver/elmer/equations/electricforce.py

View File

@@ -41,6 +41,7 @@
<file>icons/FEM_ElementGeometry1D.svg</file>
<file>icons/FEM_ElementGeometry2D.svg</file>
<file>icons/FEM_ElementRotation1D.svg</file>
<file>icons/FEM_EquationDeformation.svg</file>
<file>icons/FEM_EquationElasticity.svg</file>
<file>icons/FEM_EquationElectricforce.svg</file>
<file>icons/FEM_EquationElectrostatic.svg</file>

View File

@@ -0,0 +1,47 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" id="svg2" height="64" width="64" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs id="defs4">
<linearGradient id="linearGradient3802">
<stop id="stop3804" offset="0" style="stop-color:black;stop-opacity:1;" />
<stop id="stop3806" offset="1" style="stop-color:#555753;stop-opacity:1" />
</linearGradient>
<linearGradient gradientUnits="userSpaceOnUse" y2="42" x2="47" y1="58" x1="49" id="linearGradient3808" xlink:href="#linearGradient3802" />
</defs>
<metadata id="metadata7">
<rdf:RDF>
<cc:Work rdf:about="">
<dc:format>image/svg+xml</dc:format>
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
<dc:creator>
<cc:Agent>
<dc:title>[Alexander Gryson]</dc:title>
</cc:Agent>
</dc:creator>
<dc:date>2017-03-11</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
<cc:Agent>
<dc:title>FreeCAD</dc:title>
</cc:Agent>
</dc:publisher>
<dc:identifier>FreeCAD/src/Mod/</dc:identifier>
<dc:rights>
<cc:Agent>
<dc:title>FreeCAD LGPL2+</dc:title>
</cc:Agent>
</dc:rights>
<cc:license>https://www.gnu.org/copyleft/lesser.html</cc:license>
<dc:contributor>
<cc:Agent>
<dc:title>[agryson] Alexander Gryson</dc:title>
</cc:Agent>
</dc:contributor>
</cc:Work>
</rdf:RDF>
</metadata>
<g transform="translate(0,-988.36218)" id="layer1">
<rect transform="translate(0,988.36218)" y="39" x="3" height="22" width="58" id="rect2987" style="fill:url(#linearGradient3808);stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:9.6;fill-opacity:1" />
<rect y="1029.3622" x="5" height="18" width="54" id="rect2987-6" style="fill:none;stroke:#555753;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:9.6;stroke-opacity:1" />
<path id="rect2987-3" d="m 3,1027.3622 c 18,0 24,-20 30,-32.00002 l 20,10.00002 c -4,8 -18,44 -50,44 z" style="fill:#ffc000;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:9.6;fill-opacity:1" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -1,11 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg version="1.1" id="svg2" height="64" width="64" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" xmlns:svg="http://www.w3.org/2000/svg" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/">
<defs id="defs4">
<linearGradient id="linearGradient1124">
<stop style="stop-color:#555753;stop-opacity:1;" offset="0.46724442" id="stop1120" />
<stop style="stop-color:red;stop-opacity:1;" offset="1" id="stop1122" />
</linearGradient>
<linearGradient id="linearGradient3802">
<stop id="stop3804" offset="0" style="stop-color:#2e3436;stop-opacity:1" />
<stop id="stop3806" offset="1" style="stop-color:#555753;stop-opacity:1" />
</linearGradient>
<linearGradient gradientUnits="userSpaceOnUse" y2="42" x2="47" y1="58" x1="49" id="linearGradient3808" xlink:href="#linearGradient3802" />
<linearGradient gradientUnits="userSpaceOnUse" y2="42" x2="47" y1="58" x1="49" id="linearGradient3808" xlink:href="#linearGradient3802" gradientTransform="translate(-1.7637803,1024.9528)" />
<linearGradient xlink:href="#linearGradient1124" id="linearGradient1126" x1="3.2795276" y1="1022.3502" x2="60.972441" y2="1022.3502" gradientUnits="userSpaceOnUse" />
</defs>
<metadata id="metadata7">
<rdf:RDF>
@@ -17,7 +22,6 @@
<dc:title>[Alexander Gryson]</dc:title>
</cc:Agent>
</dc:creator>
<dc:title>fem-warp</dc:title>
<dc:date>2017-03-11</dc:date>
<dc:relation>http://www.freecadweb.org/wiki/index.php?title=Artwork</dc:relation>
<dc:publisher>
@@ -41,8 +45,6 @@
</rdf:RDF>
</metadata>
<g transform="translate(0,-988.36218)" id="layer1">
<rect transform="translate(0,988.36218)" y="39" x="3" height="22" width="58" id="rect2987" style="fill:url(#linearGradient3808);stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:9.6;fill-opacity:1" />
<rect y="1029.3622" x="5" height="18" width="54" id="rect2987-6" style="fill:none;stroke:#555753;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:9.6;stroke-opacity:1" />
<path id="rect2987-3" d="m 3,1027.3622 c 18,0 24,-20 30,-32.00002 l 20,10.00002 c -4,8 -18,44 -50,44 z" style="fill:#888a85;stroke:#172a04;stroke-width:2;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:9.6;fill-opacity:1" />
<path style="fill:url(#linearGradient1126);stroke:#172a04;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;fill-opacity:1" d="M 60.472441,1037.496 C 60.472441,1037.496 45.227698,1029.6494 3.7795276,1029.937 L 3.7795276,1007.2598 C 45.354331,1007.2598 60.472441,1014.8189 60.472441,1014.8189 V 1037.496" id="path484" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

@@ -180,6 +180,7 @@ Gui::ToolBarItem* Workbench::setupToolBars() const
<< "FEM_SolverZ88"
<< "Separator"
<< "FEM_EquationElasticity"
<< "FEM_EquationDeformation"
<< "FEM_CompEmEquations"
<< "FEM_EquationFlow"
<< "FEM_EquationFlux"
@@ -348,6 +349,7 @@ Gui::MenuItem* Workbench::setupMenuBar() const
<< "FEM_SolverZ88"
<< "Separator"
<< "FEM_EquationElasticity"
<< "FEM_EquationDeformation"
<< "FEM_CompEmEquations"
<< "FEM_EquationFlow"
<< "FEM_EquationFlux"

View File

@@ -753,6 +753,20 @@ def makePostVtkResult(
# ********* solver objects ***********************************************************************
def makeEquationDeformation(
doc,
base_solver=None,
name="Deformation"
):
"""makeEquationDeformation(document, [base_solver], [name]):
creates a FEM deformation (nonlinear elasticity) equation for a solver"""
from femsolver.elmer.equations import deformation
obj = deformation.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationElasticity(
doc,
base_solver=None,

View File

@@ -431,6 +431,23 @@ class _ElementRotation1D(CommandManager):
self.do_activated = "add_obj_on_gui_noset_edit"
class _EquationDeformation(CommandManager):
"The FEM_EquationDeformation command definition"
def __init__(self):
super(_EquationDeformation, self).__init__()
self.menutext = Qt.QT_TRANSLATE_NOOP(
"FEM_EquationDeformation",
"Deformation equation"
)
self.tooltip = Qt.QT_TRANSLATE_NOOP(
"FEM_EquationDeformation",
"Creates a FEM equation for\n deformation (nonlinear elasticity)"
)
self.is_active = "with_solver_elmer"
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
class _EquationElasticity(CommandManager):
"The FEM_EquationElasticity command definition"
@@ -442,7 +459,7 @@ class _EquationElasticity(CommandManager):
)
self.tooltip = Qt.QT_TRANSLATE_NOOP(
"FEM_EquationElasticity",
"Creates a FEM equation for elasticity"
"Creates a FEM equation for\n elasticity (stress)"
)
self.is_active = "with_solver_elmer"
self.do_activated = "add_obj_on_gui_selobj_noset_edit"
@@ -1232,6 +1249,10 @@ FreeCADGui.addCommand(
"FEM_ElementRotation1D",
_ElementRotation1D()
)
FreeCADGui.addCommand(
"FEM_EquationDeformation",
_EquationDeformation()
)
FreeCADGui.addCommand(
"FEM_EquationElasticity",
_EquationElasticity()

View File

@@ -0,0 +1,120 @@
# ***************************************************************************
# * Copyright (c) 2023 Uwe Stöhr <uwestoehr@lyx.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM solver Elmer equation object Deformation"
__author__ = "Uwe Stöhr"
__url__ = "https://www.freecadweb.org"
## \addtogroup FEM
# @{
from femtools import femutils
from ... import equationbase
from . import linear
def create(doc, name="Deformation"):
return femutils.createObject(
doc, name, Proxy, ViewProxy)
class Proxy(linear.Proxy, equationbase.DeformationProxy):
Type = "Fem::EquationElmerDeformation"
def __init__(self, obj):
super(Proxy, self).__init__(obj)
obj.addProperty(
"App::PropertyBool",
"CalculatePangle",
"Deformation",
"Compute principal stress angles"
)
obj.addProperty(
"App::PropertyBool",
"CalculatePrincipal",
"Deformation",
"Compute principal stress components"
)
obj.addProperty(
"App::PropertyBool",
"CalculateStrains",
"Deformation",
"Compute the strain tensor"
)
obj.addProperty(
"App::PropertyBool",
"CalculateStresses",
"Deformation",
"Compute stress tensor and vanMises"
)
obj.addProperty(
"App::PropertyBool",
"InitializeStateVariables",
"Deformation",
"See Elmer manual for info"
)
obj.addProperty(
"App::PropertyBool",
"MixedFormulation",
"Deformation",
"See Elmer manual for info"
)
obj.addProperty(
"App::PropertyBool",
"NeoHookeanMaterial",
"Deformation",
(
"Uses the neo-Hookean material model"
)
)
obj.addProperty(
"App::PropertyBool",
"PlaneStress",
"Equation",
(
"Computes solution according to plane\nstress situation.\n"
"Applies only for 2D geometry."
)
)
obj.addProperty(
"App::PropertyString",
"Variable",
"Deformation",
"Only for a 2D model change the '3' to '2'"
)
obj.Priority = 10
obj.CalculatePrincipal = True
# according to Elmer tutorial and forum, for stresses direct solving
# is recommended -> tests showed 10 times faster and even more accurate
obj.LinearSolverType = "Direct"
obj.LinearDirectMethod = "Umfpack"
obj.Variable = "-dofs 3 Displacement"
class ViewProxy(linear.ViewProxy, equationbase.DeformationViewProxy):
pass
## @}

View File

@@ -0,0 +1,222 @@
# ***************************************************************************
# * Copyright (c) 2023 Uwe Stöhr <uwestoehr@lyx.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM Elasticity Elmer writer"
__author__ = "Uwe Stöhr"
__url__ = "https://www.freecad.org"
## \addtogroup FEM
# @{
from FreeCAD import Console
from FreeCAD import Units
from .. import sifio
from .. import writer as general_writer
from femtools import femutils
class DeformationWriter:
def __init__(self, writer, solver):
self.write = writer
self.solver = solver
def getDeformationSolver(self, equation):
s = self.write.createLinearSolver(equation)
# output the equation parameters
s["Equation"] = "Nonlinear elasticity solver"
s["Procedure"] = sifio.FileAttr("ElasticSolve/ElasticSolver")
if equation.CalculateStrains is True:
s["Calculate Strains"] = equation.CalculateStrains
if equation.CalculateStresses is True:
s["Calculate Stresses"] = equation.CalculateStresses
if equation.CalculatePrincipal is True:
s["Calculate Principal"] = equation.CalculatePrincipal
if equation.CalculatePangle is True:
s["Calculate Pangle"] = equation.CalculatePangle
if equation.InitializeStateVariables is True:
s["Initialize State Variables"] = equation.InitializeStateVariables
if equation.MixedFormulation is True:
s["Mixed Formulation"] = equation.MixedFormulation
if equation.NeoHookeanMaterial is True:
s["Neo-Hookean Material"] = equation.NeoHookeanMaterial
s["Exec Solver"] = "Always"
s["Optimize Bandwidth"] = True
s["Stabilize"] = equation.Stabilize
s["Variable"] = equation.Variable
return s
def handleDeformationEquation(self, bodies, equation):
for b in bodies:
# not for bodies with fluid material
if not self.write.isBodyMaterialFluid(b):
if equation.PlaneStress:
self.write.equation(b, "Plane Stress", equation.PlaneStress)
def handleDeformationConstants(self):
pass
def handleDeformationBndConditions(self):
for obj in self.write.getMember("Fem::ConstraintPressure"):
if obj.References:
for name in obj.References[0][1]:
pressure = self.write.getFromUi(obj.Pressure, "MPa", "M/(L*T^2)")
if not obj.Reversed:
pressure *= -1
self.write.boundary(name, "Normal Force", pressure)
self.write.handled(obj)
for obj in self.write.getMember("Fem::ConstraintFixed"):
if obj.References:
for name in obj.References[0][1]:
self.write.boundary(name, "Displacement 1", 0.0)
self.write.boundary(name, "Displacement 2", 0.0)
self.write.boundary(name, "Displacement 3", 0.0)
self.write.handled(obj)
for obj in self.write.getMember("Fem::ConstraintForce"):
if obj.References:
for name in obj.References[0][1]:
force = self.write.getFromUi(obj.Force, "N", "M*L*T^-2")
self.write.boundary(name, "Force 1", obj.DirectionVector.x * force)
self.write.boundary(name, "Force 2", obj.DirectionVector.y * force)
self.write.boundary(name, "Force 3", obj.DirectionVector.z * force)
self.write.boundary(name, "Force 1 Normalize by Area", True)
self.write.boundary(name, "Force 2 Normalize by Area", True)
self.write.boundary(name, "Force 3 Normalize by Area", True)
self.write.handled(obj)
for obj in self.write.getMember("Fem::ConstraintDisplacement"):
if obj.References:
for name in obj.References[0][1]:
if not obj.xFree:
self.write.boundary(
name, "Displacement 1", obj.xDisplacement * 0.001)
elif obj.xFix:
self.write.boundary(name, "Displacement 1", 0.0)
if not obj.yFree:
self.write.boundary(
name, "Displacement 2", obj.yDisplacement * 0.001)
elif obj.yFix:
self.write.boundary(name, "Displacement 2", 0.0)
if not obj.zFree:
self.write.boundary(
name, "Displacement 3", obj.zDisplacement * 0.001)
elif obj.zFix:
self.write.boundary(name, "Displacement 3", 0.0)
self.write.handled(obj)
def handleDeformationInitial(self, bodies):
pass
def handleDeformationBodyForces(self, bodies):
obj = self.write.getSingleMember("Fem::ConstraintSelfWeight")
if obj is not None:
for name in bodies:
gravity = self.write.convert(self.write.constsdef["Gravity"], "L/T^2")
if self.write.getBodyMaterial(name) is None:
raise general_writer.WriteError(
"The body {} is not referenced in any material.\n\n".format(name)
)
m = self.write.getBodyMaterial(name).Material
densityQuantity = Units.Quantity(m["Density"])
dimension = "M/L^3"
if name.startswith("Edge"):
# not tested, bernd
# TODO: test
densityQuantity.Unit = Units.Unit(-2, 1)
dimension = "M/L^2"
density = self.write.convert(densityQuantity, dimension)
force1 = gravity * obj.Gravity_x * density
force2 = gravity * obj.Gravity_y * density
force3 = gravity * obj.Gravity_z * density
self.write.bodyForce(name, "Stress Bodyforce 1", force1)
self.write.bodyForce(name, "Stress Bodyforce 2", force2)
self.write.bodyForce(name, "Stress Bodyforce 3", force3)
self.write.handled(obj)
def handleDeformationMaterial(self, bodies):
# density
# is needed for self weight constraints and frequency analysis
density_needed = False
for equation in self.solver.Group:
if femutils.is_of_type(equation, "Fem::EquationElmerElasticity"):
if equation.EigenAnalysis is True:
density_needed = True
break # there could be a second equation without frequency
gravObj = self.write.getSingleMember("Fem::ConstraintSelfWeight")
if gravObj is not None:
density_needed = True
# temperature
tempObj = self.write.getSingleMember("Fem::ConstraintInitialTemperature")
if tempObj is not None:
refTemp = self.write.getFromUi(tempObj.initialTemperature, "K", "O")
for name in bodies:
self.write.material(name, "Reference Temperature", refTemp)
# get the material data for all bodies
for obj in self.write.getMember("App::MaterialObject"):
m = obj.Material
refs = (
obj.References[0][1]
if obj.References
else self.write.getAllBodies()
)
for name in (n for n in refs if n in bodies):
# don't evaluate fluid material
if self.write.isBodyMaterialFluid(name):
break
if "YoungsModulus" not in m:
Console.PrintMessage("m: {}\n".format(m))
# it is no fluid but also no solid
# -> user set no material reference at all
# that now material is known
raise general_writer.WriteError(
"There are two or more materials with empty references.\n\n"
"Set for the materials to what solid they belong to.\n"
)
self.write.material(name, "Name", m["Name"])
if density_needed is True:
self.write.material(
name, "Density",
self.write.getDensity(m)
)
self.write.material(
name, "Youngs Modulus",
self._getYoungsModulus(m)
)
self.write.material(
name, "Poisson ratio",
float(m["PoissonRatio"])
)
if tempObj:
self.write.material(
name, "Heat expansion Coefficient",
self.write.convert(m["ThermalExpansionCoefficient"], "O^-1")
)
def _getYoungsModulus(self, m):
youngsModulus = self.write.convert(m["YoungsModulus"], "M/(L*T^2)")
if self.write.getMeshDimension() == 2:
youngsModulus *= 1e3
return youngsModulus
## @}

View File

@@ -36,7 +36,7 @@ from .. import writer as general_writer
from femtools import femutils
from . import elasticity
class Elasticitywriter:
class ElasticityWriter:
def __init__(self, writer, solver):
self.write = writer

View File

@@ -48,6 +48,7 @@ from femmesh import gmshtools
from femtools import constants
from femtools import femutils
from femtools import membertools
from .equations import deformation_writer as DEF_writer
from .equations import elasticity_writer as EL_writer
from .equations import electricforce_writer as EF_writer
from .equations import electrostatic_writer as ES_writer
@@ -94,6 +95,7 @@ class Writer(object):
def write_solver_input(self):
self._handleRedifinedConstants()
self._handleSimulation()
self._handleDeformation()
self._handleElasticity()
self._handleElectricforce()
self._handleElectrostatic()
@@ -405,11 +407,39 @@ class Writer(object):
)
solver.TimestepSizes = [0.1]
#-------------------------------------------------------------------------------------------
# Deformation
def _handleDeformation(self):
DEFW = DEF_writer.DeformationWriter(self, self.solver)
activeIn = []
for equation in self.solver.Group:
if femutils.is_of_type(equation, "Fem::EquationElmerDeformation"):
if not self._haveMaterialSolid():
raise WriteError(
"The Deformation equation requires at least one body with a solid material!"
)
if equation.References:
activeIn = equation.References[0][1]
else:
activeIn = self.getAllBodies()
solverSection = DEFW.getDeformationSolver(equation)
for body in activeIn:
if not self.isBodyMaterialFluid(body):
self._addSolver(body, solverSection)
DEFW.handleDeformationEquation(activeIn, equation)
if activeIn:
DEFW.handleDeformationConstants()
DEFW.handleDeformationBndConditions()
DEFW.handleDeformationInitial(activeIn)
DEFW.handleDeformationBodyForces(activeIn)
DEFW.handleDeformationMaterial(activeIn)
#-------------------------------------------------------------------------------------------
# Elasticity
def _handleElasticity(self):
ELW = EL_writer.Elasticitywriter(self, self.solver)
ELW = EL_writer.ElasticityWriter(self, self.solver)
activeIn = []
for equation in self.solver.Group:
if femutils.is_of_type(equation, "Fem::EquationElmerElasticity"):

View File

@@ -69,6 +69,16 @@ class BaseViewProxy(object):
return mode
class DeformationProxy(BaseProxy):
pass
class DeformationViewProxy(BaseViewProxy):
def getIcon(self):
return ":/icons/FEM_EquationDeformation.svg"
class ElasticityProxy(BaseProxy):
pass

View File

@@ -84,14 +84,14 @@ class TestObjectCreate(unittest.TestCase):
# thus they are not added to the analysis group ATM
# https://forum.freecadweb.org/viewtopic.php?t=25283
# thus they should not be counted
# solver children: equations --> 8
# solver children: equations --> 9
# gmsh mesh children: group, region, boundary layer --> 3
# result children: mesh result --> 1
# post pipeline children: region, scalar, cut, wrap --> 5
# analysis itself is not in analysis group --> 1
# thus: -18
# thus: -19
self.assertEqual(len(doc.Analysis.Group), count_defmake - 18)
self.assertEqual(len(doc.Analysis.Group), count_defmake - 19)
self.assertEqual(len(doc.Objects), count_defmake)
fcc_print("doc objects count: {}, method: {}".format(
@@ -346,6 +346,10 @@ class TestObjectType(unittest.TestCase):
"Fem::SolverZ88",
type_of_obj(ObjectsFem.makeSolverZ88(doc))
)
self.assertEqual(
"Fem::EquationElmerDeformation",
type_of_obj(ObjectsFem.makeEquationDeformation(doc, solverelmer))
)
self.assertEqual(
"Fem::EquationElmerElasticity",
type_of_obj(ObjectsFem.makeEquationElasticity(doc, solverelmer))
@@ -589,6 +593,10 @@ class TestObjectType(unittest.TestCase):
ObjectsFem.makeSolverZ88(doc),
"Fem::SolverZ88"
))
self.assertTrue(is_of_type(
ObjectsFem.makeEquationDeformation(doc, solverelmer),
"Fem::EquationElmerDeformation"
))
self.assertTrue(is_of_type(
ObjectsFem.makeEquationElasticity(doc, solverelmer),
"Fem::EquationElmerElasticity"
@@ -1371,6 +1379,21 @@ class TestObjectType(unittest.TestCase):
"Fem::SolverZ88"
))
# EquationElmerDeformation
equation_deformation = ObjectsFem.makeEquationDeformation(doc, solver_elmer)
self.assertTrue(is_derived_from(
equation_deformation,
"App::DocumentObject"
))
self.assertTrue(is_derived_from(
equation_deformation,
"App::FeaturePython"
))
self.assertTrue(is_derived_from(
equation_deformation,
"Fem::EquationElmerDeformation"
))
# EquationElmerElasticity
equation_elasticity = ObjectsFem.makeEquationElasticity(doc, solver_elmer)
self.assertTrue(is_derived_from(
@@ -1744,6 +1767,12 @@ class TestObjectType(unittest.TestCase):
doc
).isDerivedFrom("Fem::FemSolverObjectPython")
)
self.assertTrue(
ObjectsFem.makeEquationDeformation(
doc,
solverelmer
).isDerivedFrom("App::FeaturePython")
)
self.assertTrue(
ObjectsFem.makeEquationElasticity(
doc,
@@ -1868,6 +1897,7 @@ def create_all_fem_objects_doc(
analysis.addObject(ObjectsFem.makeSolverMystran(doc))
analysis.addObject(ObjectsFem.makeSolverZ88(doc))
ObjectsFem.makeEquationDeformation(doc, sol)
ObjectsFem.makeEquationElasticity(doc, sol)
ObjectsFem.makeEquationElectricforce(doc, sol)
ObjectsFem.makeEquationElectrostatic(doc, sol)