Navigation Menu

Skip to content

Commit

Permalink
FEM: improve Python type checking and Python imports
Browse files Browse the repository at this point in the history
  • Loading branch information
berndhahnebach committed Mar 12, 2020
1 parent 8ddbd11 commit 0e04844
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 96 deletions.
29 changes: 14 additions & 15 deletions src/Mod/Fem/femcommands/commands.py
Expand Up @@ -22,7 +22,9 @@

import FreeCAD
import FreeCADGui

from .manager import CommandManager
from femtools.femutils import is_of_type


# Python command definitions
Expand Down Expand Up @@ -68,8 +70,11 @@ def __init__(self):
self.is_active = "with_document"

def Activated(self):
from femtools import femutils
overalboundbox = femutils.getBoundBoxOfAllDocumentShapes(FreeCAD.ActiveDocument)
from pivy import coin
from femtools.femutils import getBoundBoxOfAllDocumentShapes
from femtools.femutils import getSelectedFace

overalboundbox = getBoundBoxOfAllDocumentShapes(FreeCAD.ActiveDocument)
# print(overalboundbox)
min_bb_length = (min(set([
overalboundbox.XLength,
Expand All @@ -78,7 +83,7 @@ def Activated(self):
])))
dbox = min_bb_length * 0.2

aFace = femutils.getSelectedFace(FreeCADGui.Selection.getSelectionEx())
aFace = getSelectedFace(FreeCADGui.Selection.getSelectionEx())
if aFace:
f_CoM = aFace.CenterOfMass
f_uvCoM = aFace.Surface.parameter(f_CoM) # u,v at CoM for normalAt calculation
Expand All @@ -87,7 +92,6 @@ def Activated(self):
f_CoM = FreeCAD.Vector(0, 0, 0)
f_normal = FreeCAD.Vector(0, 0, 1)

from pivy import coin
coin_normal_vector = coin.SbVec3f(-f_normal.x, -f_normal.y, -f_normal.z)
coin_bound_box = coin.SbBox3f(
f_CoM.x - dbox, f_CoM.y - dbox,
Expand Down Expand Up @@ -333,10 +337,7 @@ def Activated(self):
# test if there is a nonlinear material which has the selected material as base material
for o in self.selobj.Document.Objects:
if (
hasattr(o, "Proxy")
and o.Proxy is not None
and hasattr(o.Proxy, "Type")
and o.Proxy.Type == "Fem::MaterialMechanicalNonlinear"
is_of_type(o, "Fem::MaterialMechanicalNonlinear")
and o.LinearBaseMaterial == self.selobj
):
FreeCAD.Console.PrintError(
Expand Down Expand Up @@ -373,12 +374,10 @@ def Activated(self):
break
# set solver attribute for nonlinearity for ccxtools
# CalculiX solver or new frame work CalculiX solver
if solver_object \
and hasattr(solver_object, "Proxy") \
and (
solver_object.Proxy.Type == "Fem::FemSolverCalculixCcxTools"
or solver_object.Proxy.Type == "Fem::FemSolverObjectCalculix"
):
if solver_object and (
is_of_type(solver_object, "Fem::FemSolverCalculixCcxTools")
or is_of_type(solver_object, "Fem::FemSolverObjectCalculix")
):
FreeCAD.Console.PrintMessage(
"Set MaterialNonlinearity and GeometricalNonlinearity to nonlinear for {}\n"
.format(solver_object.Label)
Expand Down Expand Up @@ -654,7 +653,7 @@ def __init__(self):
def Activated(self):
has_nonlinear_material_obj = False
for m in self.active_analysis.Group:
if hasattr(m, "Proxy") and m.Proxy.Type == "Fem::MaterialMechanicalNonlinear":
if is_of_type(m, "Fem::MaterialMechanicalNonlinear"):
has_nonlinear_material_obj = True
FreeCAD.ActiveDocument.openTransaction("Create SolverCalculix")
FreeCADGui.addModule("ObjectsFem")
Expand Down
19 changes: 6 additions & 13 deletions src/Mod/Fem/femcommands/manager.py
Expand Up @@ -28,12 +28,13 @@
# @{

import FreeCAD
from femtools import femutils

from femtools.femutils import is_of_type

if FreeCAD.GuiUp:
from PySide import QtCore
import FreeCADGui
import FemGui
from PySide import QtCore


class CommandManager(object):
Expand Down Expand Up @@ -162,7 +163,7 @@ def result_mesh_present(self):
result_mesh = False
analysis_members = FemGui.getActiveAnalysis().Group
for o in analysis_members:
if femutils.is_of_type(o, "Fem::FemMeshResult"):
if is_of_type(o, "Fem::FemMeshResult"):
result_mesh = True
return result_mesh

Expand Down Expand Up @@ -193,11 +194,7 @@ def femmesh_selected(self):

def gmsh_femmesh_selected(self):
sel = FreeCADGui.Selection.getSelection()
if (
len(sel) == 1
and hasattr(sel[0], "Proxy")
and sel[0].Proxy.Type == "Fem::FemMeshGmsh"
):
if len(sel) == 1 and is_of_type(sel[0], "Fem::FemMeshGmsh"):
self.selobj = sel[0]
return True
else:
Expand Down Expand Up @@ -266,11 +263,7 @@ def solver_selected(self):

def solver_elmer_selected(self):
sel = FreeCADGui.Selection.getSelection()
if (
len(sel) == 1
and hasattr(sel[0], "Proxy")
and sel[0].Proxy.Type == "Fem::FemSolverObjectElmer"
):
if len(sel) == 1 and is_of_type(sel[0], "Fem::FemSolverObjectElmer"):
self.selobj = sel[0]
return True
else:
Expand Down
77 changes: 36 additions & 41 deletions src/Mod/Fem/femguiobjects/_ViewProviderFemMeshGmsh.py
Expand Up @@ -43,6 +43,7 @@
import FemGui
# from . import ViewProviderFemConstraint
from femobjects import _FemMeshGmsh
from femtools.femutils import is_of_type


# class _ViewProviderFemMeshGmsh(ViewProviderFemConstraint.ViewProxy):
Expand Down Expand Up @@ -212,16 +213,12 @@ def canDragObjects(self):
def canDropObjects(self):
return True

# TODO use femutils module methods for type checking
def canDragObject(self, dragged_object):
if hasattr(dragged_object, "Proxy") \
and dragged_object.Proxy.Type == "Fem::MeshBoundaryLayer":
return True
elif hasattr(dragged_object, "Proxy") \
and dragged_object.Proxy.Type == "Fem::MeshGroup":
return True
elif hasattr(dragged_object, "Proxy") \
and dragged_object.Proxy.Type == "Fem::MeshRegion":
if (
is_of_type(dragged_object, "Fem::MeshBoundaryLayer")
or is_of_type(dragged_object, "Fem::MeshGroup")
or is_of_type(dragged_object, "Fem::MeshRegion")
):
return True
else:
return False
Expand All @@ -230,33 +227,29 @@ def canDropObject(self, incoming_object):
return True

def dragObject(self, selfvp, dragged_object):
if hasattr(dragged_object, "Proxy") \
and dragged_object.Proxy.Type == "Fem::MeshBoundaryLayer":
if is_of_type(dragged_object, "Fem::MeshBoundaryLayer"):
objs = self.Object.MeshBoundaryLayerList
objs.remove(dragged_object)
self.Object.MeshBoundaryLayerList = objs
elif hasattr(dragged_object, "Proxy") and dragged_object.Proxy.Type == "Fem::MeshGroup":
elif is_of_type(dragged_object, "Fem::MeshGroup"):
objs = self.Object.MeshGroupList
objs.remove(dragged_object)
self.Object.MeshGroupList = objs
elif hasattr(dragged_object, "Proxy") and dragged_object.Proxy.Type == "Fem::MeshRegion":
elif is_of_type(dragged_object, "Fem::MeshRegion"):
objs = self.Object.MeshRegionList
objs.remove(dragged_object)
self.Object.MeshRegionList = objs

def dropObject(self, selfvp, incoming_object):
if hasattr(incoming_object, "Proxy") \
and incoming_object.Proxy.Type == "Fem::MeshBoundaryLayer":
if is_of_type(incoming_object, "Fem::MeshBoundaryLayer"):
objs = self.Object.MeshBoundaryLayerList
objs.append(incoming_object)
self.Object.MeshBoundaryLayerList = objs
elif hasattr(incoming_object, "Proxy") \
and incoming_object.Proxy.Type == "Fem::MeshGroup":
elif is_of_type(incoming_object, "Fem::MeshGroup"):
objs = self.Object.MeshGroupList
objs.append(incoming_object)
self.Object.MeshGroupList = objs
elif hasattr(incoming_object, "Proxy") \
and incoming_object.Proxy.Type == "Fem::MeshRegion":
elif is_of_type(incoming_object, "Fem::MeshRegion"):
objs = self.Object.MeshRegionList
objs.append(incoming_object)
self.Object.MeshRegionList = objs
Expand Down Expand Up @@ -383,28 +376,30 @@ def choose_dimension(self, index):
def run_gmsh(self):
QApplication.setOverrideCursor(Qt.WaitCursor)
part = self.mesh_obj.Part
if self.mesh_obj.MeshRegionList:
# other part obj might not have a Proxy, thus an exception would be raised
if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"):
if part.Proxy.Type == "FeatureBooleanFragments" \
or part.Proxy.Type == "FeatureSlice" \
or part.Proxy.Type == "FeatureXOR":
error_message = (
"The shape to mesh is a boolean split tools Compound "
"and the mesh has mesh region list. "
"Gmsh could return unexpected meshes in such circumstances. "
"It is strongly recommended to extract the shape "
"to mesh from the Compound and use this one."
)
qtbox_title = (
"Shape to mesh is a BooleanFragmentsCompound "
"and mesh regions are defined"
)
QtGui.QMessageBox.critical(
None,
qtbox_title,
error_message
)
if (
self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound"
and (
is_of_type(part, "FeatureBooleanFragments")
or is_of_type(part, "FeatureSlice")
or is_of_type(part, "FeatureXOR")
)
):
error_message = (
"The shape to mesh is a boolean split tools Compound "
"and the mesh has mesh region list. "
"Gmsh could return unexpected meshes in such circumstances. "
"It is strongly recommended to extract the shape "
"to mesh from the Compound and use this one."
)
qtbox_title = (
"Shape to mesh is a BooleanFragmentsCompound "
"and mesh regions are defined"
)
QtGui.QMessageBox.critical(
None,
qtbox_title,
error_message
)
self.Start = time.time()
self.form.l_time.setText("Time: {0:4.1f}: ".format(time.time() - self.Start))
self.console_message_gmsh = ""
Expand Down
36 changes: 19 additions & 17 deletions src/Mod/Fem/femmesh/gmshtools.py
Expand Up @@ -366,23 +366,25 @@ def get_region_data(self):
# http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&start=40#p149467
# http://forum.freecadweb.org/viewtopic.php?f=18&t=18780&p=149520#p149520
part = self.part_obj
if self.mesh_obj.MeshRegionList:
# other part obj might not have a Proxy, thus an exception would be raised
if part.Shape.ShapeType == "Compound" and hasattr(part, "Proxy"):
if part.Proxy.Type == "FeatureBooleanFragments" \
or part.Proxy.Type == "FeatureSlice" \
or part.Proxy.Type == "FeatureXOR":
error_message = (
" The mesh to shape is a boolean split tools Compound "
"and the mesh has mesh region list. "
"Gmsh could return unexpected meshes in such circumstances. "
"It is strongly recommended to extract the shape to mesh "
"from the Compound and use this one."
)
Console.PrintError(error_message + "\n")
# TODO: no gui popup because FreeCAD will be in a endless output loop
# as long as the pop up is on --> maybe find a better solution for
# either of both --> thus the pop up is in task panel
if (
self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound"
and (
femutils.is_of_type(part, "FeatureBooleanFragments")
or femutils.is_of_type(part, "FeatureSlice")
or femutils.is_of_type(part, "FeatureXOR")
)
):
error_message = (
" The mesh to shape is a boolean split tools Compound "
"and the mesh has mesh region list. "
"Gmsh could return unexpected meshes in such circumstances. "
"It is strongly recommended to extract the shape to mesh "
"from the Compound and use this one."
)
Console.PrintError(error_message + "\n")
# TODO: no gui popup because FreeCAD will be in a endless output loop
# as long as the pop up is on --> maybe find a better solution for
# either of both --> thus the pop up is in task panel
for mr_obj in self.mesh_obj.MeshRegionList:
# print(mr_obj.Name)
# print(mr_obj.CharacteristicLength)
Expand Down
20 changes: 10 additions & 10 deletions src/Mod/Fem/femresult/resulttools.py
Expand Up @@ -26,11 +26,13 @@
## \addtogroup FEM
# @{

import FreeCAD
from femtools import femutils
import numpy as np
from math import isnan

import FreeCAD

from femtools.femutils import is_of_type


def purge_results(analysis):
"""Removes all result objects and result meshes from an analysis group
Expand All @@ -42,10 +44,8 @@ def purge_results(analysis):
"""

for m in analysis.Group:
if (m.isDerivedFrom("Fem::FemResultObject")):
if m.Mesh \
and hasattr(m.Mesh, "Proxy") \
and m.Mesh.Proxy.Type == "Fem::FemMeshResult":
if m.isDerivedFrom("Fem::FemResultObject"):
if m.Mesh and is_of_type(m.Mesh, "Fem::FemMeshResult"):
analysis.Document.removeObject(m.Mesh.Name)
analysis.Document.removeObject(m.Name)
FreeCAD.ActiveDocument.recompute()
Expand All @@ -54,7 +54,7 @@ def purge_results(analysis):
# we could run into trouble in one loop because
# we will delete objects and try to access them later
for m in analysis.Group:
if femutils.is_of_type(m, "Fem::FemMeshResult"):
if is_of_type(m, "Fem::FemMeshResult"):
analysis.Document.removeObject(m.Name)
FreeCAD.ActiveDocument.recompute()

Expand Down Expand Up @@ -418,7 +418,7 @@ def get_concrete_nodes(res_obj):

for obj in res_obj.getParentGroup().Group:
if obj.isDerivedFrom("App::MaterialObjectPython") \
and femutils.is_of_type(obj, "Fem::MaterialReinforced"):
and is_of_type(obj, "Fem::MaterialReinforced"):
FreeCAD.Console.PrintMessage("ReinforcedMaterial\n")
if obj.References == []:
for iic in range(nsr):
Expand All @@ -430,7 +430,7 @@ def get_concrete_nodes(res_obj):
for cn in concrete_nodes:
ic[cn - 1] = 1
elif obj.isDerivedFrom("App::MaterialObjectPython") \
and femutils.is_of_type(obj, "Fem::Material"):
and is_of_type(obj, "Fem::Material"):
FreeCAD.Console.PrintMessage("No ReinforcedMaterial\n")
if obj.References == []:
for iic in range(nsr):
Expand Down Expand Up @@ -472,7 +472,7 @@ def add_principal_stress_reinforced(res_obj):

# material parameter
for obj in res_obj.getParentGroup().Group:
if femutils.is_of_type(obj, "Fem::MaterialReinforced"):
if is_of_type(obj, "Fem::MaterialReinforced"):
matrix_af = float(
FreeCAD.Units.Quantity(obj.Material["AngleOfFriction"]).getValueAs("rad")
)
Expand Down

0 comments on commit 0e04844

Please sign in to comment.