Merge pull request #27749 from marioalexis84/fem-elmer_examples_run

Fem: Run Elmer examples - fixes #27547
This commit is contained in:
Max Wilfinger
2026-02-21 22:04:22 +01:00
committed by GitHub
73 changed files with 457 additions and 595 deletions
+16
View File
@@ -46,6 +46,22 @@ FemMeshShapeBaseObject::FemMeshShapeBaseObject()
Prop_None,
"Geometry object, the mesh is made from. The geometry object has to have a Shape."
);
ADD_PROPERTY_TYPE(
Tool,
(Py::Object()),
"FEM Mesh",
App::PropertyType(
App::Prop_Transient | App::Prop_Hidden | App::Prop_ReadOnly | App::Prop_Output
),
"Tool object for run the mesher"
);
ADD_PROPERTY_TYPE(
WorkingDirectory,
(""),
"FEM Mesh",
App::PropertyType(App::Prop_Transient | App::Prop_Hidden | App::Prop_Output),
"Mesher working directory"
);
Shape.setScope(LinkScope::Global);
}
+2
View File
@@ -39,6 +39,8 @@ public:
~FemMeshShapeBaseObject() override;
App::PropertyLink Shape;
App::PropertyPythonObject Tool;
App::PropertyPath WorkingDirectory;
/// returns the type name of the ViewProvider
const char* getViewProviderName() const override
+9
View File
@@ -50,6 +50,15 @@ FemSolverObject::FemSolverObject()
App::PropertyType(App::Prop_Transient | App::Prop_Hidden | App::Prop_Output),
"Solver working directory"
);
ADD_PROPERTY_TYPE(
Tool,
(Py::Object()),
"Solver",
App::PropertyType(
App::Prop_Transient | App::Prop_Hidden | App::Prop_ReadOnly | App::Prop_Output
),
"Tool for run the solver"
);
}
FemSolverObject::~FemSolverObject() = default;
+1
View File
@@ -42,6 +42,7 @@ public:
~FemSolverObject() override;
App::PropertyLinkList Results;
App::PropertyPythonObject Tool;
App::PropertyPath WorkingDirectory;
// Attributes are implemented in the FemSolverObjectPython
+2
View File
@@ -116,6 +116,7 @@ SET(FemExamples_SRCS
SET(FemExampleMeshes_SRCS
femexamples/meshes/__init__.py
femexamples/meshes/generate_mesh.py
femexamples/meshes/mesh_beamsimple_tetra10.py
femexamples/meshes/mesh_boxanalysis_tetra10.py
femexamples/meshes/mesh_boxes_2_vertikal_tetra10.py
@@ -517,6 +518,7 @@ SET(FemTools_SRCS
femtools/geomtools.py
femtools/membertools.py
femtools/migrate_app.py
femtools/objecttools.py
femtools/tokrules.py
)
+4 -47
View File
@@ -29,9 +29,6 @@ __url__ = "https://www.freecad.org"
# \ingroup FEM
# \brief FreeCAD FEM command definitions
from PySide import QtCore
from PySide import QtGui
import FreeCAD
import FreeCADGui
from FreeCAD import Qt
@@ -1184,51 +1181,11 @@ class _SolverRun(CommandManager):
self.tool = None
def Activated(self):
if self.selobj.Proxy.Type in ["Fem::SolverCalculiX", "Fem::SolverElmer"]:
try:
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
self._set_tool()
self._conn(self.tool)
self.tool.prepare()
self.tool.compute()
except Exception as e:
QtGui.QApplication.restoreOverrideCursor()
FreeCAD.Console.PrintError(e)
return
from femsolver.run import run_fem_solver
else:
from femsolver.run import run_fem_solver
run_fem_solver(self.selobj)
FreeCADGui.Selection.clearSelection()
FreeCAD.ActiveDocument.recompute()
def _set_tool(self):
match self.selobj.Proxy.Type:
case "Fem::SolverCalculiX":
from femsolver.calculix.calculixtools import CalculiXTools
self.tool = CalculiXTools(self.selobj)
case "Fem::SolverElmer":
from femsolver.elmer.elmertools import ElmerTools
self.tool = ElmerTools(self.selobj)
def _conn(self, tool):
QtCore.QObject.connect(
tool.process,
QtCore.SIGNAL("finished(int, QProcess::ExitStatus)"),
self._process_finished,
)
def _process_finished(self, code, status):
if status == QtCore.QProcess.ExitStatus.NormalExit and code == 0:
self.tool.update_properties()
FreeCAD.ActiveDocument.recompute()
QtGui.QApplication.restoreOverrideCursor()
else:
QtGui.QApplication.restoreOverrideCursor()
FreeCAD.Console.PrintError("Process finished with errors. Result not updated\n")
run_fem_solver(self.selobj)
FreeCADGui.Selection.clearSelection()
FreeCAD.ActiveDocument.recompute()
class _SolverZ88(CommandManager):
+13 -11
View File
@@ -29,9 +29,10 @@ import ObjectsFem
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def setup_boxanalysisbase(doc=None, solvertype="ccxtools"):
def setup_boxanalysisbase(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -62,21 +63,22 @@ def setup_boxanalysisbase(doc=None, solvertype="ccxtools"):
analysis.addObject(material_obj)
# mesh
from .meshes.mesh_boxanalysis_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
femmesh_obj.SecondOrderLinear = False
femmesh_obj.CharacteristicLengthMin = "8.0 mm"
femmesh_obj.ElementOrder = "2nd"
# generate the mesh
success = False
if not test_mode:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_boxanalysis_tetra10 import create_nodes, create_elements
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
@@ -58,7 +58,7 @@ See forum topic post:
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -69,7 +69,7 @@ def setup(doc=None, solvertype="ccxtools"):
manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information())))
# setup box frequency, change solver attributes
doc = setup_boxanalysisbase(doc, solvertype)
doc = setup_boxanalysisbase(doc, solvertype, test_mode)
analysis = doc.Analysis
# solver
@@ -60,7 +60,7 @@ See forum topic post:
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -71,7 +71,7 @@ def setup(doc=None, solvertype="ccxtools"):
manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information())))
# setup box static, add a fixed, force and a pressure constraint
doc = setup_boxanalysisbase(doc, solvertype)
doc = setup_boxanalysisbase(doc, solvertype, test_mode)
geom_obj = doc.Box
analysis = doc.Analysis
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -177,13 +178,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_buckling_ibeam_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -150,13 +151,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_buckling_plate_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -30,6 +30,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -130,13 +131,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_flexural_buckling import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ import ObjectsFem
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def setup_cantilever_base_edge(doc=None, solvertype="ccxtools"):
@@ -121,13 +122,7 @@ def setup_cantilever_base_edge(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_canticcx_seg3 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -28,6 +28,7 @@ import ObjectsFem
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def setup_cantilever_base_face(doc=None, solvertype="ccxtools"):
@@ -106,13 +107,7 @@ def setup_cantilever_base_face(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_canticcx_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -29,9 +29,10 @@ import ObjectsFem
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def setup_cantilever_base_solid(doc=None, solvertype="ccxtools"):
def setup_cantilever_base_solid(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -91,19 +92,20 @@ def setup_cantilever_base_solid(doc=None, solvertype="ccxtools"):
analysis.addObject(con_fixed)
# mesh
from .meshes.mesh_canticcx_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
femmesh_obj.SecondOrderLinear = False
# generate the mesh
success = False
if not test_mode:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_canticcx_tetra10 import create_nodes, create_elements
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
@@ -30,6 +30,7 @@ from . import manager
from .ccx_cantilever_faceload import setup as setup_with_faceload
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -38,7 +39,7 @@ def get_information():
"meshtype": "solid",
"meshelement": "Hexa20",
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "z88"],
"solvers": ["ccxtools", "z88"], # elmer disabled until mesh has groups
"material": "solid",
"equations": ["mechanical"],
}
@@ -84,16 +85,8 @@ def setup(doc=None, solvertype="ccxtools"):
# load the hexa20 mesh
from .meshes.mesh_canticcx_hexa20 import create_nodes, create_elements
new_fem_mesh = Fem.FemMesh()
control = create_nodes(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
# overwrite mesh with the hexa20 mesh
femmesh_obj.FemMesh = new_fem_mesh
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
@@ -29,6 +29,7 @@ from . import manager
from .ccx_cantilever_base_face import setup_cantilever_base_face
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -80,16 +81,10 @@ def setup(doc=None, solvertype="ccxtools"):
# load the quad4 mesh
from .meshes.mesh_canticcx_quad4 import create_nodes, create_elements
new_fem_mesh = Fem.FemMesh()
control = create_nodes(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
# overwrite mesh with the quad4 mesh
femmesh_obj.FemMesh = new_fem_mesh
femmesh_obj.FemMesh = fem_mesh
# set mesh obj parameter
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ from . import manager
from .ccx_cantilever_base_face import setup_cantilever_base_face
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -80,16 +81,10 @@ def setup(doc=None, solvertype="ccxtools"):
# load the quad8 mesh
from .meshes.mesh_canticcx_quad8 import create_nodes, create_elements
new_fem_mesh = Fem.FemMesh()
control = create_nodes(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
# overwrite mesh with the quad8 mesh
femmesh_obj.FemMesh = new_fem_mesh
femmesh_obj.FemMesh = fem_mesh
# set mesh obj parameter
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ from . import manager
from .ccx_cantilever_base_edge import setup_cantilever_base_edge
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -80,16 +81,10 @@ def setup(doc=None, solvertype="ccxtools"):
# load the seg2 mesh
from .meshes.mesh_canticcx_seg2 import create_nodes, create_elements
new_fem_mesh = Fem.FemMesh()
control = create_nodes(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
# overwrite mesh with the seg2 mesh
femmesh_obj.FemMesh = new_fem_mesh
femmesh_obj.FemMesh = fem_mesh
# set mesh obj parameter
femmesh_obj.Shape = geom_obj
@@ -28,6 +28,7 @@ from . import manager
from .ccx_cantilever_faceload import setup as setup_with_faceload
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -52,8 +53,7 @@ from femexamples.ccx_cantilever_ele_tetra4 import setup
setup()
Tetra4 elements. There are really a lot needed thus mesh is cleared.
Mesh before run the example.
Cantilever modeled with tetra4 volume elements
...
"""
@@ -89,5 +89,8 @@ def setup(doc=None, solvertype="ccxtools"):
femmesh_obj.CharacteristicLengthMax = "150.0 mm"
femmesh_obj.CharacteristicLengthMin = "150.0 mm"
# generate the mesh
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -29,6 +29,7 @@ from . import manager
from .ccx_cantilever_base_face import setup_cantilever_base_face
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -80,16 +81,10 @@ def setup(doc=None, solvertype="ccxtools"):
# load the tria3 mesh
from .meshes.mesh_canticcx_tria3 import create_nodes, create_elements
new_fem_mesh = Fem.FemMesh()
control = create_nodes(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(new_fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
# overwrite mesh with the tria3 mesh
femmesh_obj.FemMesh = new_fem_mesh
femmesh_obj.FemMesh = fem_mesh
# set mesh obj parameter
femmesh_obj.Shape = geom_obj
@@ -58,7 +58,7 @@ See forum topic post:
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -69,7 +69,7 @@ def setup(doc=None, solvertype="ccxtools"):
manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information())))
# setup CalculiX cantilever
doc = setup_cantilever_base_solid(doc, solvertype)
doc = setup_cantilever_base_solid(doc, solvertype, test_mode)
analysis = doc.Analysis
geom_obj = doc.Box
@@ -58,7 +58,7 @@ See forum topic post:
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -69,7 +69,7 @@ def setup(doc=None, solvertype="ccxtools"):
manager.add_explanation_obj(doc, get_explanation(manager.get_header(get_information())))
# setup CalculiX cantilever, apply 9 MN on the 4 nodes of the front end face
doc = setup_cantilever_base_solid(doc, solvertype)
doc = setup_cantilever_base_solid(doc, solvertype, test_mode)
analysis = doc.Analysis
geom_obj = doc.Box
@@ -58,7 +58,7 @@ See forum topic post:
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
if solvertype == "z88":
# constraint displacement is not supported for Z88
@@ -75,7 +75,7 @@ def setup(doc=None, solvertype="ccxtools"):
# setup CalculiX cantilever
# apply a prescribed displacement of 250 mm in -z on the front end face
doc = setup_cantilever_base_solid(doc, solvertype)
doc = setup_cantilever_base_solid(doc, solvertype, test_mode)
analysis = doc.Analysis
geom_obj = doc.Box
@@ -30,6 +30,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -169,10 +170,7 @@ def setup(doc=None, solvertype="ccxtools"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
gmsh_mesh.create_mesh()
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -144,10 +145,7 @@ def setup(doc=None, solvertype="ccxtools"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
gmsh_mesh.create_mesh()
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
+2 -8
View File
@@ -30,6 +30,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -138,14 +139,7 @@ def setup(doc=None, solvertype="ccxtools"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -184,13 +185,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_constraint_centrif_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -204,13 +205,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_contact_tube_tube_tria3 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -189,13 +190,7 @@ def setup(doc=None, solvertype="ccxtools"):
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -40,6 +40,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -263,13 +264,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_section_print_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -64,7 +65,7 @@ max deformation = 576.8 mm
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -116,6 +117,7 @@ def setup(doc=None, solvertype="ccxtools"):
mat["PoissonRatio"] = "0.30"
mat["Density"] = "7900 kg/m^3"
material_obj.Material = mat
material_obj.References = [(geom_obj, "Solid1")]
analysis.addObject(material_obj)
# constraint fixed
@@ -129,19 +131,20 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(con_selfweight)
# mesh
from .meshes.mesh_selfweight_cantilever_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
femmesh_obj.SecondOrderLinear = False
# generate the mesh
success = False
if not test_mode:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_selfweight_cantilever_tetra10 import create_nodes, create_elements
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
+2 -7
View File
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -160,13 +161,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_constraint_tie_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -175,13 +176,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_transform_beam_hinged_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -42,6 +42,7 @@ from Part import makeLine
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -164,13 +165,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_transform_torque_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -125,21 +126,19 @@ def setup(doc=None, solvertype="elmer"):
analysis.addObject(con_fixed)
# mesh
from .meshes.mesh_eigenvalue_of_elastic_beam_tetra10 import create_nodes
from .meshes.mesh_eigenvalue_of_elastic_beam_tetra10 import create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
femmesh_obj.SecondOrderLinear = False
femmesh_obj.CharacteristicLengthMax = "40.80 mm"
# generate the mesh
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing mesh
from .meshes.mesh_eigenvalue_of_elastic_beam_tetra10 import create_nodes, create_elements
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
@@ -32,6 +32,7 @@ import Sketcher
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -198,14 +199,7 @@ def setup(doc=None, solvertype="elmer"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -177,28 +178,15 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
if error:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_capacitance_two_balls_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -182,28 +183,15 @@ def setup(doc=None, solvertype="calculix"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
if error:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_capacitance_two_balls_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
@@ -36,6 +36,7 @@ import Sketcher
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -44,7 +45,7 @@ def get_information():
"meshtype": "solid",
"meshelement": "Tet10",
"constraints": ["electrostatic potential"],
"solvers": ["elmer"],
"solvers": ["calculix", "elmer"],
"material": "fluid",
"equations": ["electrostatic"],
}
@@ -178,6 +179,9 @@ def setup(doc=None, solvertype="elmer"):
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
ObjectsFem.makeEquationElectrostatic(doc, solver_obj)
ObjectsFem.makeEquationElectricforce(doc, solver_obj)
elif solvertype == "calculix":
solver_obj = ObjectsFem.makeSolverCalculiX(doc, "SolverCalculiX")
solver_obj.AnalysisType = "electromagnetic"
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -213,12 +217,7 @@ def setup(doc=None, solvertype="elmer"):
# constraint potential 1V
name_pot2 = "ElectrostaticPotential2"
con_elect_pot2 = ObjectsFem.makeConstraintElectrostaticPotential(doc, name_pot2)
con_elect_pot2.References = [
(geom_obj, "Face4"),
(geom_obj, "Face5"),
(geom_obj, "Face6"),
(geom_obj, "Face11"),
]
con_elect_pot2.References = [(geom_obj, "Face4")]
con_elect_pot2.Potential = "1 V"
con_elect_pot2.CapacitanceBody = 2
con_elect_pot2.CapacitanceBodyEnabled = True
@@ -245,29 +244,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
if error:
# try to create from existing rough mesh
from .meshes.mesh_electricforce_elmer_nongui6_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj.FemMesh = fem_mesh
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -34,6 +34,7 @@ from BOPTools import SplitFeatures
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -269,14 +270,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -34,6 +34,7 @@ from BOPTools import SplitFeatures
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -277,14 +278,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -34,6 +34,7 @@ from BOPTools import SplitFeatures
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -275,14 +276,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -30,6 +30,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -158,14 +159,7 @@ def setup(doc=None, solvertype="elmer"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -33,6 +33,7 @@ from BOPTools import SplitFeatures
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -274,14 +275,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -32,6 +32,7 @@ from BasicShapes import Shapes
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -211,29 +212,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
if error:
# try to create from existing rough mesh
from .meshes.mesh_capacitance_two_balls_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj.FemMesh = fem_mesh
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -25,7 +25,6 @@ import sys
import FreeCAD
from FreeCAD import Vector
import Draft
import ObjectsFem
import Part
@@ -33,6 +32,7 @@ from BOPTools import SplitFeatures
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -79,9 +79,8 @@ def setup(doc=None, solvertype="elmer"):
p2 = Vector(200.0, -200.0, 0.0)
p3 = Vector(200.0, -100.0, 0.0)
p4 = Vector(0.0, -100.0, 0.0)
Horseshoe_lower = Draft.make_wire([p1, p2, p3, p4], closed=True)
Horseshoe_lower.MakeFace = True
Horseshoe_lower.Label = "Lower_End"
Horseshoe_lower = doc.addObject("Part::Feature", "Lower_End")
Horseshoe_lower.Shape = Part.makeFace(Part.makePolygon([p1, p2, p3, p4, p1]))
Horseshoe_lower.ViewObject.Visibility = False
# wire defining the upper horse shoe end
@@ -89,9 +88,8 @@ def setup(doc=None, solvertype="elmer"):
p2 = Vector(200.0, 100.0, 0.0)
p3 = Vector(200.0, 200.0, 0.0)
p4 = Vector(0.0, 200.0, 0.0)
Horseshoe_upper = Draft.make_wire([p1, p2, p3, p4], closed=True)
Horseshoe_upper.MakeFace = True
Horseshoe_upper.Label = "Upper_End"
Horseshoe_upper = doc.addObject("Part::Feature", "Upper_End")
Horseshoe_upper.Shape = Part.makeFace(Part.makePolygon([p1, p2, p3, p4, p1]))
Horseshoe_upper.ViewObject.Visibility = False
# the U-part of the horse shoe
@@ -275,14 +273,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
@@ -38,6 +38,7 @@ from BasicShapes import Shapes
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -159,14 +160,7 @@ def setup(doc=None, solvertype="elmer"):
femmesh_obj.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
error = gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
+1 -1
View File
@@ -239,7 +239,7 @@ class FemExamples(QtGui.QWidget):
FreeCADGui.doCommand("from femexamples.manager import run_example")
if solver is not None:
FreeCADGui.doCommand(
f'run_example("{str(example)}", solver="{str(solver)}", run_solver=True)'
f'run_example("{str(example)}", solver="{str(solver)}", run_solver=True, blocking=False)'
)
else:
FreeCADGui.doCommand(f'run_example("{str(example)}", run_solver=True)')
@@ -29,6 +29,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -141,13 +142,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_beamsimple_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -36,6 +36,7 @@ import Materials
import Part
from . import manager
from .meshes import generate_mesh
def get_information():
@@ -150,14 +151,7 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.ViewObject.Visibility = False
# generate the mesh
from femmesh import gmshtools
gmsh_mesh = gmshtools.GmshTools(femmesh_obj, analysis)
try:
gmsh_mesh.create_mesh()
except Exception:
error = sys.exc_info()[1]
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
doc.recompute()
return doc
+4 -4
View File
@@ -127,7 +127,7 @@ def setup_all():
run_example("thermomech_bimetal")
def run_analysis(doc, base_name, filepath="", run_solver=False):
def run_analysis(doc, base_name, filepath="", run_solver=False, blocking=True):
from os.path import join, exists
from os import makedirs
@@ -168,13 +168,13 @@ def run_analysis(doc, base_name, filepath="", run_solver=False):
from femsolver.run import run_fem_solver
if run_solver is True:
run_fem_solver(solver, working_dir)
run_fem_solver(solver, working_dir, blocking=blocking)
# save doc once again with results
doc.save()
def run_example(example, solver=None, base_name=None, run_solver=False):
def run_example(example, solver=None, base_name=None, run_solver=False, blocking=True):
from importlib import import_module
@@ -192,7 +192,7 @@ def run_example(example, solver=None, base_name=None, run_solver=False):
base_name = example
if solver is not None:
base_name += "_" + solver
run_analysis(doc, base_name, run_solver=run_solver)
run_analysis(doc, base_name, run_solver=run_solver, blocking=blocking)
doc.recompute()
return doc
@@ -32,6 +32,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -192,13 +193,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_multibodybeam_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -30,6 +30,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -185,13 +186,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_multibodybeam_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -161,13 +162,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_boxes_2_vertikal_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -41,6 +41,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -169,13 +170,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_platewithhole_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -0,0 +1,66 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2026 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD 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 *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
import sys
from FreeCAD import Console
import Fem
def mesh_from_mesher(femmesh_obj, mesher=""):
tool = None
success = False
match mesher:
case "netgen":
from femmesh import netgentools
tool = netgentools.NetgenTools(femmesh_obj)
case "gmsh" | "":
from femmesh import gmshtools
tool = gmshtools.GmshTools(femmesh_obj)
case _:
raise ValueError(f"Invalid mesher: {mesher}")
# Redirect process error to report view
print_error = lambda: Console.PrintError(
tool.process.readAllStandardError().data().decode("utf-8")
)
tool.process.readyReadStandardError.connect(print_error)
# generate the mesh
try:
success = tool.run(blocking=True)
except Exception as e:
error = sys.exc_info()[1]
Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
return success
def mesh_from_existing(create_nodes, create_elements):
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
Console.PrintError("Error on creating elements.\n")
return fem_mesh
+3 -8
View File
@@ -31,6 +31,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -39,7 +40,7 @@ def get_information():
"meshtype": "face",
"meshelement": "Quad4",
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "mystran"],
"solvers": ["ccxtools", "mystran"], # elmer disabled until mesh has groups
"material": "solid",
"equations": ["mechanical"],
}
@@ -179,13 +180,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_plate_mystran_quad4 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
+2 -7
View File
@@ -34,6 +34,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -167,13 +168,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_rc_wall_2d_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -169,13 +170,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_square_pipe_end_twisted_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -439,13 +440,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_square_pipe_end_twisted_tria6 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
+14 -11
View File
@@ -41,6 +41,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -78,7 +79,7 @@ this file has 7.15 mm max deflection
)
def setup(doc=None, solvertype="ccxtools"):
def setup(doc=None, solvertype="ccxtools", test_mode=False):
# init FreeCAD document
if doc is None:
@@ -206,19 +207,21 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(con_temp)
# mesh
from .meshes.mesh_thermomech_bimetal_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
femmesh_obj.SecondOrderLinear = False
femmesh_obj.CharacteristicLengthMax = "2 mm"
# generate the mesh
success = False
if not test_mode:
success = generate_mesh.mesh_from_mesher(femmesh_obj, "gmsh")
if not success:
# try to create from existing rough mesh
from .meshes.mesh_thermomech_bimetal_tetra10 import create_nodes, create_elements
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj.FemMesh = fem_mesh
doc.recompute()
return doc
@@ -28,6 +28,7 @@ import Fem
from .truss_3d_cs_circle_ele_seg3 import setup as setup_truss_seg3
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -59,13 +60,7 @@ def setup(doc=None, solvertype="z88"):
# mesh
from .meshes.mesh_truss_crane_seg2 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
# overwrite mesh with the hexa20 mesh
femmesh_obj.FemMesh = fem_mesh
@@ -33,6 +33,7 @@ import ObjectsFem
from . import manager
from .manager import get_meshname
from .manager import init_doc
from .meshes import generate_mesh
def get_information():
@@ -452,13 +453,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_truss_crane_seg3 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating nodes.\n")
control = create_elements(fem_mesh)
if not control:
FreeCAD.Console.PrintError("Error on creating elements.\n")
fem_mesh = generate_mesh.mesh_from_existing(create_nodes, create_elements)
femmesh_obj = analysis.addObject(ObjectsFem.makeMeshGmsh(doc, get_meshname()))[0]
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Shape = geom_obj
+8 -21
View File
@@ -41,32 +41,21 @@ import Fem
from . import meshtools
from femtools import femutils
from femtools import geomtools
from femtools.objecttools import ObjectTools
class GmshError(Exception):
pass
class GmshTools:
class GmshTools(ObjectTools):
name = "Gmsh"
def __init__(self, gmsh_mesh_obj, analysis=None):
# mesh obj
self.mesh_obj = gmsh_mesh_obj
self.process = QProcess()
# analysis
self.analysis = None
if analysis:
self.analysis = analysis
else:
for i in self.mesh_obj.InList:
if i.isDerivedFrom("Fem::FemAnalysis"):
self.analysis = i
break
def __init__(self, obj):
super().__init__(obj)
self.mesh_obj = obj
self.analysis = obj.getParentGroup()
self.load_properties()
self.error = False
@@ -232,10 +221,8 @@ class GmshTools:
self.rename_groups()
def create_mesh(self):
self.prepare()
p = self.compute()
p.waitForFinished()
self.update_properties()
# for backward compatibility only
self.run(True)
def start_logs(self):
Console.PrintLog("\nGmsh FEM mesh run is being started.\n")
+6 -4
View File
@@ -34,9 +34,10 @@ from PySide.QtCore import QProcess, QThread, QProcessEnvironment
import FreeCAD
import Fem
from freecad import utils
from femtools.objecttools import ObjectTools
class NetgenTools:
class NetgenTools(ObjectTools):
# to change order of nodes from netgen to smesh
order_edge = {
@@ -73,11 +74,9 @@ class NetgenTools:
__param_grp = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Netgen")
def __init__(self, obj):
self.obj = obj
super().__init__(obj)
self.fem_mesh = None
self.process = None
self.tmpdir = ""
self.process = QProcess()
self.mesh_params = {}
def write_geom(self):
@@ -267,6 +266,9 @@ def run_netgen(
np.save(result_file, [result, groups])
# remove traceback
sys.excepthook = lambda type, value, traceback: print(value)
run_netgen(**{kwds})
"""
@@ -37,42 +37,18 @@ import Fem
from . import writer
from .. import settings
# from feminout import importCcxDatResults
from femmesh import meshsetsgetter
from femtools import membertools
from femtools.objecttools import ObjectTools
class CalculiXTools:
class CalculiXTools(ObjectTools):
name = "CalculiX"
def __init__(self, obj):
self.obj = obj
self.process = QProcess()
super().__init__(obj)
self.model_file = ""
self.analysis = obj.getParentGroup()
self.fem_param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
self._create_working_directory(obj)
def _create_working_directory(self, obj):
"""
Create working directory according to preferences
"""
if not os.path.isdir(obj.WorkingDirectory):
gen_param = self.fem_param.GetGroup("General")
if gen_param.GetBool("UseTempDirectory"):
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseBesideDirectory"):
root, ext = os.path.splitext(obj.Document.FileName)
if root:
self.obj.WorkingDirectory = os.path.join(root, obj.Label)
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
else:
# file not saved, use temporary
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseCustomDirectory"):
self.obj.WorkingDirectory = gen_param.GetString("CustomDirectoryPath")
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
def prepare(self):
from femtools.checksanalysis import check_member_for_solver_calculix
+4 -28
View File
@@ -27,7 +27,6 @@ __url__ = "https://www.freecad.org"
from PySide.QtCore import QProcess, QProcessEnvironment
import tempfile
import os
import re
import shutil
@@ -38,41 +37,18 @@ from . import writer
from .. import settings
from femtools import membertools
from femtools.objecttools import ObjectTools
class ElmerTools:
class ElmerTools(ObjectTools):
name = "Elmer"
def __init__(self, obj):
self.obj = obj
self.process = QProcess()
super().__init__(obj)
self.model_file = ""
self.analysis = obj.getParentGroup()
self.fem_param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
self._create_working_directory(obj)
self._result_format = ""
def _create_working_directory(self, obj):
"""
Create working directory according to preferences
"""
if not os.path.isdir(obj.WorkingDirectory):
gen_param = self.fem_param.GetGroup("General")
if gen_param.GetBool("UseTempDirectory"):
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseBesideDirectory"):
root, ext = os.path.splitext(obj.Document.FileName)
if root:
self.obj.WorkingDirectory = os.path.join(root, obj.Label)
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
else:
# file not saved, use temporary
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseCustomDirectory"):
self.obj.WorkingDirectory = gen_param.GetString("CustomDirectoryPath")
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
def prepare(self):
w = writer.Writer(self.obj, self.obj.WorkingDirectory)
w.write_solver_input()
@@ -91,7 +67,7 @@ class ElmerTools:
p.setWorkingDirectory(self.obj.WorkingDirectory)
grid_args = ["8", "2", mesh_file, "-out", self.obj.WorkingDirectory]
p.start(grid_bin, grid_args)
p.waitForFinished()
p.waitForFinished(-1)
num_proc = self.fem_param.GetGroup("Elmer").GetInt("NumberOfTasks", 1)
if num_proc > 1:
# MPI parallel computing version
+44 -1
View File
@@ -40,6 +40,7 @@ import os
import os.path
import shutil
import tempfile
from PySide import QtCore
# import threading # not used ATM
@@ -48,6 +49,8 @@ import FreeCAD as App
from . import settings
from . import signal
from . import task
from femsolver.elmer import elmertools
from femsolver.calculix import calculixtools
from femtools import femutils
from femtools import membertools
from femtools.errors import DirectoryDoesNotExistError
@@ -69,7 +72,7 @@ _machines = {}
_dirTypes = {}
def run_fem_solver(solver, working_dir=None):
def run_fem_solver(solver, working_dir=None, blocking=False):
"""Execute *solver* of the solver framework.
Uses :meth:`getMachine <femsolver.solverbase.Proxy.getMachine>` to obtain a
@@ -100,6 +103,35 @@ def run_fem_solver(solver, working_dir=None):
use a :class:`Machine`.
"""
tool = None
if working_dir:
solver.WorkingDirectory = working_dir
match solver.Proxy.Type:
case "Fem::SolverElmer":
tool = elmertools.ElmerTools(solver)
case "Fem::SolverCalculiX":
tool = calculixtools.CalculiXTools(solver)
if tool is not None:
# Redirect process error to report view
print_error = lambda: App.Console.PrintError(
tool.process.readAllStandardError().data().decode("utf-8")
)
tool.process.readyReadStandardError.connect(print_error)
tool.process.finished.connect(_solver_finish(solver))
try:
if App.GuiUp:
QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
tool.run(blocking)
except Exception as e:
if App.GuiUp:
QtGui.QApplication.restoreOverrideCursor()
raise e
return
# code for old solver implementations
if solver.Proxy.Type == "Fem::SolverCcxTools":
from femtools.ccxtools import CcxTools as ccx
@@ -192,6 +224,17 @@ def getMachine(solver, path=None):
return m
def _solver_finish(obj):
def receiver(code, status):
if status != QtCore.QProcess.ExitStatus.NormalExit or code != 0:
App.Console.PrintError("Solver finished with errors. Result not updated\n")
if App.GuiUp:
QtGui.QApplication.restoreOverrideCursor()
obj.Document.recompute()
return receiver
def _isPathValid(m, path):
t = _dirTypes.get(m.directory) # setting default None
setting = settings.get_dir_setting()
@@ -138,7 +138,6 @@ class _BaseLogTaskPanel(base_femtaskpanel._BaseTaskPanel, ABC):
QtGui.QColor(getOutputWinColor("Error")),
)
return
self.tool.update_properties()
self.write_log("Process finished\n", QtGui.QColor(getOutputWinColor("Text")))
def process_started(self):
+7 -7
View File
@@ -76,7 +76,7 @@ class TestCcxTools(unittest.TestCase):
# set up
from femexamples.boxanalysis_frequency import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
base_name = get_namefromdef("test_")
res_obj_name = "CCX_EigenMode_1_Results"
analysis_dir = testtools.get_fem_test_tmp_dir(self.pre_dir_name + base_name)
@@ -100,7 +100,7 @@ class TestCcxTools(unittest.TestCase):
# set up
from femexamples.boxanalysis_static import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
base_name = get_namefromdef("test_")
res_obj_name = "CCX_Results"
analysis_dir = testtools.get_fem_test_tmp_dir(self.pre_dir_name + base_name)
@@ -201,21 +201,21 @@ class TestCcxTools(unittest.TestCase):
def test_ccx_cantilever_faceload(self):
from femexamples.ccx_cantilever_faceload import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
self.input_file_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
def test_ccx_cantilever_nodeload(self):
from femexamples.ccx_cantilever_nodeload import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
self.input_file_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
def test_ccx_cantilever_prescribeddisplacement(self):
from femexamples.ccx_cantilever_prescribeddisplacement import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
self.input_file_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
@@ -256,7 +256,7 @@ class TestCcxTools(unittest.TestCase):
def test_constraint_selfweight_cantilever(self):
from femexamples.constraint_selfweight_cantilever import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
self.input_file_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
@@ -333,7 +333,7 @@ class TestCcxTools(unittest.TestCase):
def test_thermomech_bimetal(self):
from femexamples.thermomech_bimetal import setup
setup(self.document, "ccxtools")
setup(self.document, "ccxtools", test_mode=True)
self.input_file_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
+2 -2
View File
@@ -89,14 +89,14 @@ class TestSolverZ88(unittest.TestCase):
def test_ccx_cantilever_faceload(self):
from femexamples.ccx_cantilever_faceload import setup
setup(self.document, "z88")
setup(self.document, "z88", test_mode=True)
self.inputfile_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
def test_ccx_cantilever_nodeload(self):
from femexamples.ccx_cantilever_nodeload import setup
setup(self.document, "z88")
setup(self.document, "z88", test_mode=True)
self.inputfile_writing_test(get_namefromdef("test_"))
# ********************************************************************************************
+91
View File
@@ -0,0 +1,91 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
# ***************************************************************************
# * Copyright (c) 2026 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
# * *
# * This file is part of FreeCAD. *
# * *
# * FreeCAD is free software: you can redistribute it and/or modify it *
# * under the terms of the GNU Lesser General Public License as *
# * published by the Free Software Foundation, either version 2.1 of the *
# * License, or (at your option) any later version. *
# * *
# * FreeCAD 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 *
# * Lesser General Public License for more details. *
# * *
# * You should have received a copy of the GNU Lesser General Public *
# * License along with FreeCAD. If not, see *
# * <https://www.gnu.org/licenses/>. *
# * *
# ***************************************************************************
__title__ = "Abstract base class for the work with solvers and meshers"
__author__ = "Mario Passaglia"
__url__ = "https://www.freecad.org"
from PySide.QtCore import QProcess
from abc import ABC, abstractmethod
import os
import tempfile
import FreeCAD
class ObjectTools(ABC):
"""Abstract base class for the work with solvers and meshers"""
def __init__(self, obj):
obj.Tool = self
self.obj = obj
self.process = QProcess()
self.analysis = obj.getParentGroup()
self.fem_param = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem")
self._create_working_directory(obj)
self.process.finished.connect(self._process_finished)
def _create_working_directory(self, obj):
"""
Create working directory according to preferences
"""
if not os.path.isdir(obj.WorkingDirectory):
gen_param = self.fem_param.GetGroup("General")
if gen_param.GetBool("UseTempDirectory"):
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseBesideDirectory"):
root, ext = os.path.splitext(obj.Document.FileName)
if root:
self.obj.WorkingDirectory = os.path.join(root, obj.Label)
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
else:
# file not saved, use temporary
self.obj.WorkingDirectory = tempfile.mkdtemp(prefix="fem_")
elif gen_param.GetBool("UseCustomDirectory"):
self.obj.WorkingDirectory = gen_param.GetString("CustomDirectoryPath")
os.makedirs(self.obj.WorkingDirectory, exist_ok=True)
@abstractmethod
def prepare(self):
pass
@abstractmethod
def compute(self):
pass
@abstractmethod
def update_properties(self):
pass
def run(self, blocking=False):
self.prepare()
self.compute()
if blocking:
return self.process.waitForFinished(-1)
return None
def _process_finished(self, code, status):
if status == QProcess.ExitStatus.NormalExit and code == 0:
self.update_properties()