FEM: reformat codebase

This commit is contained in:
lyphrowny
2024-06-19 14:29:15 +03:00
parent 8675aa87b4
commit 359c1ae2bb
302 changed files with 6702 additions and 9421 deletions

View File

@@ -29,19 +29,19 @@
// Fem
#ifndef FemExport
#ifdef Fem_EXPORTS
# define FemExport FREECAD_DECL_EXPORT
#define FemExport FREECAD_DECL_EXPORT
#else
# define FemExport FREECAD_DECL_IMPORT
#define FemExport FREECAD_DECL_IMPORT
#endif
#endif
// FemGui
#ifndef FemGuiExport
#ifdef FemGui_EXPORTS
# define FemGuiExport FREECAD_DECL_EXPORT
#define FemGuiExport FREECAD_DECL_EXPORT
#else
# define FemGuiExport FREECAD_DECL_IMPORT
#define FemGuiExport FREECAD_DECL_IMPORT
#endif
#endif
#endif //FEM_GLOBAL_H
#endif // FEM_GLOBAL_H

View File

@@ -63,11 +63,10 @@ FreeCAD.addExportType("FEM mesh TetGen (*.poly)", "feminout.convert2TetGen")
# see FemMesh::read() and FemMesh::write() methods in src/Mod/Fem/App/FemMesh.cpp
FreeCAD.addImportType(
"FEM mesh formats (*.bdf *.BDF *.dat *.DAT *.inp *.INP *.med *.MED *.unv *.UNV *.vtk *.VTK *.vtu *.VTU *.pvtu *.PVTU *.z88 *.Z88)", "Fem"
)
FreeCAD.addExportType(
"FEM mesh formats (*.dat *.inp *.med *.stl *.unv *.vtk *.vtu *.z88)", "Fem"
"FEM mesh formats (*.bdf *.BDF *.dat *.DAT *.inp *.INP *.med *.MED *.unv *.UNV *.vtk *.VTK *.vtu *.VTU *.pvtu *.PVTU *.z88 *.Z88)",
"Fem",
)
FreeCAD.addExportType("FEM mesh formats (*.dat *.inp *.med *.stl *.unv *.vtk *.vtu *.z88)", "Fem")
FreeCAD.addExportType("FEM mesh Nastran (*.bdf)", "feminout.exportNastranMesh")
@@ -77,17 +76,26 @@ FreeCAD.addImportType("FEM mesh Fenics (*.xml *.XML *.xdmf *.XDMF)", "feminout.i
FreeCAD.addExportType("FEM mesh Fenics (*.xml *.xdmf)", "feminout.importFenicsMesh")
FreeCAD.addImportType(
"FEM mesh YAML/JSON (*.meshyaml *.MESHYAML *.meshjson *.MESHJSON *.yaml *.YAML *.json *.JSON)", "feminout.importYamlJsonMesh"
"FEM mesh YAML/JSON (*.meshyaml *.MESHYAML *.meshjson *.MESHJSON *.yaml *.YAML *.json *.JSON)",
"feminout.importYamlJsonMesh",
)
FreeCAD.addExportType(
"FEM mesh YAML/JSON (*.meshyaml *.meshjson *.yaml *.json)", "feminout.importYamlJsonMesh"
"FEM mesh YAML/JSON (*.meshyaml *.meshjson *.yaml *.json)",
"feminout.importYamlJsonMesh",
)
FreeCAD.addImportType("FEM mesh Z88 (*i1.txt *I1.TXT)", "feminout.importZ88Mesh")
FreeCAD.addExportType("FEM mesh Z88 (*i1.txt)", "feminout.importZ88Mesh")
FreeCAD.addImportType("FEM result Z88 displacements (*o2.txt *O2.TXT)", "feminout.importZ88O2Results")
FreeCAD.addImportType(
"FEM result Z88 displacements (*o2.txt *O2.TXT)", "feminout.importZ88O2Results"
)
if "BUILD_FEM_VTK" in FreeCAD.__cmake__:
FreeCAD.addImportType("FEM result VTK (*.vtk *.VTK *.vtu *.VTU *.pvtu *.PVTU)", "feminout.importVTKResults")
FreeCAD.addExportType("FEM result VTK (*.vtu *.vtp *.vts *.vtr *.vti)", "feminout.importVTKResults")
FreeCAD.addImportType(
"FEM result VTK (*.vtk *.VTK *.vtu *.VTU *.pvtu *.PVTU)",
"feminout.importVTKResults",
)
FreeCAD.addExportType(
"FEM result VTK (*.vtu *.vtp *.vts *.vtr *.vti)", "feminout.importVTKResults"
)

View File

@@ -71,6 +71,7 @@ class FemWorkbench(Workbench):
import Fem
import FemGui
import femcommands.commands
# dummy usage to get flake8 and lgtm quiet
False if Fem.__name__ else True
False if FemGui.__name__ else True

View File

@@ -46,10 +46,7 @@ import FreeCAD
# ********* analysis objects *********************************************************************
def makeAnalysis(
doc,
name="Analysis"
):
def makeAnalysis(doc, name="Analysis"):
"""makeAnalysis(document, [name]):
makes a Fem Analysis object"""
obj = doc.addObject("Fem::FemAnalysis", name)
@@ -57,343 +54,281 @@ def makeAnalysis(
# ********* constant objects *********************************************************************
def makeConstantVacuumPermittivity(
doc,
name="ConstantVacuumPermittivity"
):
def makeConstantVacuumPermittivity(doc, name="ConstantVacuumPermittivity"):
"""makeConstantVacuumPermittivity(document, [name]):
makes a Fem ConstantVacuumPermittivity object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constant_vacuumpermittivity
constant_vacuumpermittivity.ConstantVacuumPermittivity(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constant_vacuumpermittivity
view_constant_vacuumpermittivity.VPConstantVacuumPermittivity(obj.ViewObject)
return obj
# ********* constraint objects *******************************************************************
def makeConstraintBearing(
doc,
name="ConstraintBearing"
):
def makeConstraintBearing(doc, name="ConstraintBearing"):
"""makeConstraintBearing(document, [name]):
makes a Fem ConstraintBearing object"""
obj = doc.addObject("Fem::ConstraintBearing", name)
return obj
def makeConstraintBodyHeatSource(
doc,
name="ConstraintBodyHeatSource"
):
def makeConstraintBodyHeatSource(doc, name="ConstraintBodyHeatSource"):
"""makeConstraintBodyHeatSource(document, [name]):
makes a Fem ConstraintBodyHeatSource object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_bodyheatsource
constraint_bodyheatsource.ConstraintBodyHeatSource(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_bodyheatsource as viewprov
viewprov.VPConstraintBodyHeatSource(obj.ViewObject)
return obj
def makeConstraintCentrif(
doc,
name="ConstraintCentrif"
):
def makeConstraintCentrif(doc, name="ConstraintCentrif"):
"""makeConstraintCentrif(document, [name]):
creates a centrif object to define centrifugal body load constraint"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_centrif
constraint_centrif.ConstraintCentrif(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_centrif
view_constraint_centrif.VPConstraintCentrif(obj.ViewObject)
return obj
def makeConstraintCurrentDensity(
doc,
name="ConstraintCurrentDensity"
):
def makeConstraintCurrentDensity(doc, name="ConstraintCurrentDensity"):
"""makeConstraintCurrentDensity(document, [name]):
makes a Fem CurrentDensity object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_currentdensity
constraint_currentdensity.ConstraintCurrentDensity(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_currentdensity
view_constraint_currentdensity.VPConstraintCurrentDensity(obj.ViewObject)
return obj
def makeConstraintContact(
doc,
name="ConstraintContact"
):
def makeConstraintContact(doc, name="ConstraintContact"):
"""makeConstraintContact(document, [name]):
makes a Fem ConstraintContact object"""
obj = doc.addObject("Fem::ConstraintContact", name)
return obj
def makeConstraintDisplacement(
doc,
name="ConstraintDisplacement"
):
def makeConstraintDisplacement(doc, name="ConstraintDisplacement"):
"""makeConstraintDisplacement(document, [name]):
makes a Fem ConstraintDisplacement object"""
obj = doc.addObject("Fem::ConstraintDisplacement", name)
return obj
def makeConstraintElectrostaticPotential(
doc,
name="ConstraintElectrostaticPotential"
):
def makeConstraintElectrostaticPotential(doc, name="ConstraintElectrostaticPotential"):
"""makeConstraintElectrostaticPotential(document, [name]):
makes a Fem ElectrostaticPotential object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_electrostaticpotential
constraint_electrostaticpotential.ConstraintElectrostaticPotential(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_electrostaticpotential
view_constraint_electrostaticpotential.VPConstraintElectroStaticPotential(obj.ViewObject)
return obj
def makeConstraintFixed(
doc,
name="ConstraintFixed"
):
def makeConstraintFixed(doc, name="ConstraintFixed"):
"""makeConstraintFixed(document, [name]):
makes a Fem ConstraintFixed object"""
obj = doc.addObject("Fem::ConstraintFixed", name)
return obj
def makeConstraintRigidBody(
doc,
name="ConstraintRigidBody"
):
def makeConstraintRigidBody(doc, name="ConstraintRigidBody"):
"""makeConstraintRigidBody(document, [name]):
makes a Fem ConstraintRigidBody object"""
obj = doc.addObject("Fem::ConstraintRigidBody", name)
return obj
def makeConstraintFlowVelocity(
doc,
name="ConstraintFlowVelocity"
):
def makeConstraintFlowVelocity(doc, name="ConstraintFlowVelocity"):
"""makeConstraintFlowVelocity(document, [name]):
makes a Fem ConstraintFlowVelocity object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_flowvelocity
constraint_flowvelocity.ConstraintFlowVelocity(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_flowvelocity
view_constraint_flowvelocity.VPConstraintFlowVelocity(obj.ViewObject)
return obj
def makeConstraintFluidBoundary(
doc,
name="ConstraintFluidBoundary"
):
def makeConstraintFluidBoundary(doc, name="ConstraintFluidBoundary"):
"""makeConstraintFluidBoundary(document, name):
makes a Fem ConstraintFluidBoundary object"""
obj = doc.addObject("Fem::ConstraintFluidBoundary", name)
return obj
def makeConstraintForce(
doc,
name="ConstraintForce"
):
def makeConstraintForce(doc, name="ConstraintForce"):
"""makeConstraintForce(document, [name]):
makes a Fem ConstraintForce object"""
obj = doc.addObject("Fem::ConstraintForce", name)
return obj
def makeConstraintGear(
doc,
name="ConstraintGear"
):
def makeConstraintGear(doc, name="ConstraintGear"):
"""makeConstraintGear(document, [name]):
makes a Fem ConstraintGear object"""
obj = doc.addObject("Fem::ConstraintGear", name)
return obj
def makeConstraintHeatflux(
doc,
name="ConstraintHeatflux"
):
def makeConstraintHeatflux(doc, name="ConstraintHeatflux"):
"""makeConstraintHeatflux(document, [name]):
makes a Fem ConstraintHeatflux object"""
obj = doc.addObject("Fem::ConstraintHeatflux", name)
return obj
def makeConstraintInitialFlowVelocity(
doc,
name="ConstraintInitialFlowVelocity"
):
def makeConstraintInitialFlowVelocity(doc, name="ConstraintInitialFlowVelocity"):
"""makeConstraintInitialFlowVelocity(document, [name]):
makes a Fem ConstraintInitialFlowVelocity object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_initialflowvelocity
constraint_initialflowvelocity.ConstraintInitialFlowVelocity(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_initialflowvelocity
view_constraint_initialflowvelocity.VPConstraintInitialFlowVelocity(obj.ViewObject)
return obj
def makeConstraintInitialPressure(
doc,
name="ConstraintInitialPressure"
):
def makeConstraintInitialPressure(doc, name="ConstraintInitialPressure"):
"""makeConstraintInitialPressure(document, [name]):
makes a Fem ConstraintInitialPressure object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_initialpressure
constraint_initialpressure.ConstraintInitialPressure(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_initialpressure
view_constraint_initialpressure.VPConstraintInitialPressure(obj.ViewObject)
return obj
def makeConstraintInitialTemperature(
doc,
name="ConstraintInitialTemperature"
):
def makeConstraintInitialTemperature(doc, name="ConstraintInitialTemperature"):
"""makeConstraintInitialTemperature(document, name):
makes a Fem ConstraintInitialTemperature object"""
obj = doc.addObject("Fem::ConstraintInitialTemperature", name)
return obj
def makeConstraintMagnetization(
doc,
name="ConstraintMagnetization"
):
def makeConstraintMagnetization(doc, name="ConstraintMagnetization"):
"""makeConstraintMagnetization(document, [name]):
makes a Fem Magnetization object"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_magnetization
constraint_magnetization.ConstraintMagnetization(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_magnetization
view_constraint_magnetization.VPConstraintMagnetization(obj.ViewObject)
return obj
def makeConstraintPlaneRotation(
doc,
name="ConstraintPlaneRotation"
):
def makeConstraintPlaneRotation(doc, name="ConstraintPlaneRotation"):
"""makeConstraintPlaneRotation(document, [name]):
makes a Fem ConstraintPlaneRotation object"""
obj = doc.addObject("Fem::ConstraintPlaneRotation", name)
return obj
def makeConstraintPressure(
doc,
name="ConstraintPressure"
):
def makeConstraintPressure(doc, name="ConstraintPressure"):
"""makeConstraintPressure(document, [name]):
makes a Fem ConstraintPressure object"""
obj = doc.addObject("Fem::ConstraintPressure", name)
return obj
def makeConstraintPulley(
doc,
name="ConstraintPulley"
):
def makeConstraintPulley(doc, name="ConstraintPulley"):
"""makeConstraintPulley(document, [name]):
makes a Fem ConstraintPulley object"""
obj = doc.addObject("Fem::ConstraintPulley", name)
return obj
def makeConstraintSelfWeight(
doc,
name="ConstraintSelfWeight"
):
def makeConstraintSelfWeight(doc, name="ConstraintSelfWeight"):
"""makeConstraintSelfWeight(document, [name]):
creates a self weight object to define a gravity load"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_selfweight
constraint_selfweight.ConstraintSelfWeight(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_selfweight
view_constraint_selfweight.VPConstraintSelfWeight(
obj.ViewObject
)
view_constraint_selfweight.VPConstraintSelfWeight(obj.ViewObject)
return obj
def makeConstraintTemperature(
doc,
name="ConstraintTemperature"
):
def makeConstraintTemperature(doc, name="ConstraintTemperature"):
"""makeConstraintTemperature(document, [name]):
makes a Fem ConstraintTemperature object"""
obj = doc.addObject("Fem::ConstraintTemperature", name)
return obj
def makeConstraintTie(
doc,
name="ConstraintTie"
):
def makeConstraintTie(doc, name="ConstraintTie"):
"""makeConstraintTie(document, [name]):
creates a tie object to define bonded faces constraint"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_tie
constraint_tie.ConstraintTie(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_tie
view_constraint_tie.VPConstraintTie(obj.ViewObject)
return obj
def makeConstraintTransform(
doc,
name="ConstraintTransform"
):
def makeConstraintTransform(doc, name="ConstraintTransform"):
"""makeConstraintTransform(document, [name]):
makes a Fem ConstraintTransform object"""
obj = doc.addObject("Fem::ConstraintTransform", name)
return obj
def makeConstraintSectionPrint(
doc,
name="ConstraintSectionPrint"
):
def makeConstraintSectionPrint(doc, name="ConstraintSectionPrint"):
"""makeConstraintSectionPrint(document, [name]):
creates a section print object to evaluate forces and moments of defined face"""
obj = doc.addObject("Fem::ConstraintPython", name)
from femobjects import constraint_sectionprint
constraint_sectionprint.ConstraintSectionPrint(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_constraint_sectionprint
view_constraint_sectionprint.VPConstraintSectionPrint(obj.ViewObject)
return obj
def makeConstraintSpring(
doc,
name="ConstraintSpring"
):
def makeConstraintSpring(doc, name="ConstraintSpring"):
"""makeConstraintSpring(document, [name]):
makes a Fem ConstraintSpring object"""
obj = doc.addObject("Fem::ConstraintSpring", name)
@@ -401,32 +336,28 @@ def makeConstraintSpring(
# ********* element definition objects ***********************************************************
def makeElementFluid1D(
doc,
name="ElementFluid1D"
):
def makeElementFluid1D(doc, name="ElementFluid1D"):
"""makeElementFluid1D(document, [name]):
creates a 1D fluid element object to define 1D flow"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import element_fluid1D
element_fluid1D.ElementFluid1D(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_element_fluid1D
view_element_fluid1D.VPElementFluid1D(obj.ViewObject)
return obj
def makeElementGeometry1D(
doc,
sectiontype="Rectangular",
width=10.0,
height=25.0,
name="ElementGeometry1D"
doc, sectiontype="Rectangular", width=10.0, height=25.0, name="ElementGeometry1D"
):
"""makeElementGeometry1D(document, [width], [height], [name]):
creates a 1D geometry element object to define a cross section"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import element_geometry1D
element_geometry1D.ElementGeometry1D(obj)
sec_types = element_geometry1D.ElementGeometry1D.known_beam_types
if sectiontype not in sec_types:
@@ -441,119 +372,107 @@ def makeElementGeometry1D(
obj.PipeThickness = width
if FreeCAD.GuiUp:
from femviewprovider import view_element_geometry1D
view_element_geometry1D.VPElementGeometry1D(obj.ViewObject)
return obj
def makeElementGeometry2D(
doc,
thickness=1.0,
name="ElementGeometry2D"
):
def makeElementGeometry2D(doc, thickness=1.0, name="ElementGeometry2D"):
"""makeElementGeometry2D(document, [thickness], [name]):
creates a 2D geometry element object to define a plate thickness"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import element_geometry2D
element_geometry2D.ElementGeometry2D(obj)
obj.Thickness = thickness
if FreeCAD.GuiUp:
from femviewprovider import view_element_geometry2D
view_element_geometry2D.VPElementGeometry2D(obj.ViewObject)
return obj
def makeElementRotation1D(
doc,
name="ElementRotation1D"
):
def makeElementRotation1D(doc, name="ElementRotation1D"):
"""makeElementRotation1D(document, [name]):
creates a 1D geometry rotation element object to rotate a 1D cross section"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import element_rotation1D
element_rotation1D.ElementRotation1D(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_element_rotation1D
view_element_rotation1D.VPElementRotation1D(obj.ViewObject)
return obj
# ********* material objects *********************************************************************
def makeMaterialFluid(
doc,
name="MaterialFluid"
):
def makeMaterialFluid(doc, name="MaterialFluid"):
"""makeMaterialFluid(document, [name]):
makes a FEM Material for fluid"""
obj = doc.addObject("App::MaterialObjectPython", name)
from femobjects import material_common
material_common.MaterialCommon(obj)
obj.Category = "Fluid"
if FreeCAD.GuiUp:
from femviewprovider import view_material_common
view_material_common.VPMaterialCommon(obj.ViewObject)
return obj
def makeMaterialMechanicalNonlinear(
doc,
base_material,
name="MaterialMechanicalNonlinear"
):
def makeMaterialMechanicalNonlinear(doc, base_material, name="MaterialMechanicalNonlinear"):
"""makeMaterialMechanicalNonlinear(document, base_material, [name]):
creates a nonlinear material object"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import material_mechanicalnonlinear
material_mechanicalnonlinear.MaterialMechanicalNonlinear(obj)
obj.LinearBaseMaterial = base_material
if FreeCAD.GuiUp:
from femviewprovider import view_material_mechanicalnonlinear
view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear(
obj.ViewObject
)
view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear(obj.ViewObject)
return obj
def makeMaterialReinforced(
doc,
name="MaterialReinforced"
):
def makeMaterialReinforced(doc, name="MaterialReinforced"):
"""makeMaterialReinforced(document, [matrix_material], [reinforcement_material], [name]):
creates a reinforced material object"""
obj = doc.addObject("App::MaterialObjectPython", name)
from femobjects import material_reinforced
material_reinforced.MaterialReinforced(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_material_reinforced
view_material_reinforced.VPMaterialReinforced(obj.ViewObject)
return obj
def makeMaterialSolid(
doc,
name="MaterialSolid"
):
def makeMaterialSolid(doc, name="MaterialSolid"):
"""makeMaterialSolid(document, [name]):
makes a FEM Material for solid"""
obj = doc.addObject("App::MaterialObjectPython", name)
from femobjects import material_common
material_common.MaterialCommon(obj)
obj.Category = "Solid"
if FreeCAD.GuiUp:
from femviewprovider import view_material_common
view_material_common.VPMaterialCommon(obj.ViewObject)
return obj
# ********* mesh objects *************************************************************************
def makeMeshBoundaryLayer(
doc,
base_mesh,
name="MeshBoundaryLayer"
):
def makeMeshBoundaryLayer(doc, base_mesh, name="MeshBoundaryLayer"):
"""makeMeshBoundaryLayer(document, base_mesh, [name]):
creates a FEM mesh BoundaryLayer object to define boundary layer properties"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import mesh_boundarylayer
mesh_boundarylayer.MeshBoundaryLayer(obj)
# obj.BaseMesh = base_mesh
# App::PropertyLinkList does not support append
@@ -563,35 +482,32 @@ def makeMeshBoundaryLayer(
base_mesh.MeshBoundaryLayerList = tmplist
if FreeCAD.GuiUp:
from femviewprovider import view_mesh_boundarylayer
view_mesh_boundarylayer.VPMeshBoundaryLayer(obj.ViewObject)
return obj
def makeMeshGmsh(
doc,
name="MeshGmsh"
):
def makeMeshGmsh(doc, name="MeshGmsh"):
"""makeMeshGmsh(document, [name]):
makes a Gmsh FEM mesh object"""
obj = doc.addObject("Fem::FemMeshObjectPython", name)
from femobjects import mesh_gmsh
mesh_gmsh.MeshGmsh(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_mesh_gmsh
view_mesh_gmsh.VPMeshGmsh(obj.ViewObject)
return obj
def makeMeshGroup(
doc,
base_mesh,
use_label=False,
name="MeshGroup"
):
def makeMeshGroup(doc, base_mesh, use_label=False, name="MeshGroup"):
"""makeMeshGroup(document, base_mesh, [use_label], [name]):
creates a FEM mesh refinement object to define properties for a region of a FEM mesh"""
creates a FEM mesh refinement object to define properties for a region of a FEM mesh
"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import mesh_group
mesh_group.MeshGroup(obj)
obj.UseLabel = use_label
# obj.BaseMesh = base_mesh
@@ -602,30 +518,25 @@ def makeMeshGroup(
base_mesh.MeshGroupList = tmplist
if FreeCAD.GuiUp:
from femviewprovider import view_mesh_group
view_mesh_group.VPMeshGroup(obj.ViewObject)
return obj
def makeMeshNetgen(
doc,
name="MeshNetgen"
):
def makeMeshNetgen(doc, name="MeshNetgen"):
"""makeMeshNetgen(document, [name]):
makes a Fem MeshShapeNetgenObject object"""
obj = doc.addObject("Fem::FemMeshShapeNetgenObject", name)
return obj
def makeMeshRegion(
doc,
base_mesh,
element_length=0.0,
name="MeshRegion"
):
def makeMeshRegion(doc, base_mesh, element_length=0.0, name="MeshRegion"):
"""makeMeshRegion(document, base_mesh, [element_length], [name]):
creates a FEM mesh refinement object to define properties for a refinement of a FEM mesh"""
creates a FEM mesh refinement object to define properties for a refinement of a FEM mesh
"""
obj = doc.addObject("Fem::FeaturePython", name)
from femobjects import mesh_region
mesh_region.MeshRegion(obj)
obj.CharacteristicLength = element_length
# obj.BaseMesh = base_mesh
@@ -636,45 +547,40 @@ def makeMeshRegion(
base_mesh.MeshRegionList = tmplist
if FreeCAD.GuiUp:
from femviewprovider import view_mesh_region
view_mesh_region.VPMeshRegion(obj.ViewObject)
return obj
def makeMeshResult(
doc,
name="MeshResult"
):
def makeMeshResult(doc, name="MeshResult"):
"""makeMeshResult(document, name): makes a Fem MeshResult object"""
obj = doc.addObject("Fem::FemMeshObjectPython", name)
from femobjects import mesh_result
mesh_result.MeshResult(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_mesh_result
view_mesh_result.VPFemMeshResult(obj.ViewObject)
return obj
# ********* post processing objects **************************************************************
def makeResultMechanical(
doc,
name="ResultMechanical"
):
def makeResultMechanical(doc, name="ResultMechanical"):
"""makeResultMechanical(document, [name]):
creates a mechanical result object to hold FEM results"""
obj = doc.addObject("Fem::FemResultObjectPython", name)
from femobjects import result_mechanical
result_mechanical.ResultMechanical(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_result_mechanical
view_result_mechanical.VPResultMechanical(obj.ViewObject)
return obj
def makePostVtkFilterClipRegion(
doc,
base_vtk_result,
name="VtkFilterClipRegion"
):
def makePostVtkFilterClipRegion(doc, base_vtk_result, name="VtkFilterClipRegion"):
"""makePostVtkFilterClipRegion(document, base_vtk_result, [name]):
creates a FEM post processing region clip filter object (vtk based)"""
obj = doc.addObject("Fem::FemPostClipFilter", name)
@@ -685,11 +591,7 @@ def makePostVtkFilterClipRegion(
return obj
def makePostVtkFilterClipScalar(
doc,
base_vtk_result,
name="VtkFilterClipScalar"
):
def makePostVtkFilterClipScalar(doc, base_vtk_result, name="VtkFilterClipScalar"):
"""makePostVtkFilterClipScalar(document, base_vtk_result, [name]):
creates a FEM post processing scalar clip filter object (vtk based)"""
obj = doc.addObject("Fem::FemPostScalarClipFilter", name)
@@ -700,11 +602,7 @@ def makePostVtkFilterClipScalar(
return obj
def makePostVtkFilterCutFunction(
doc,
base_vtk_result,
name="VtkFilterCutFunction"
):
def makePostVtkFilterCutFunction(doc, base_vtk_result, name="VtkFilterCutFunction"):
"""makePostVtkFilterCutFunction(document, base_vtk_result, [name]):
creates a FEM post processing cut function filter object (vtk based)"""
obj = doc.addObject("Fem::FemPostClipFilter", name)
@@ -715,11 +613,7 @@ def makePostVtkFilterCutFunction(
return obj
def makePostVtkFilterWarp(
doc,
base_vtk_result,
name="VtkFilterWarp"
):
def makePostVtkFilterWarp(doc, base_vtk_result, name="VtkFilterWarp"):
"""makePostVtkFilterWarp(document, base_vtk_result, [name]):
creates a FEM post processing warp filter object (vtk based)"""
obj = doc.addObject("Fem::FemPostWarpVectorFilter", name)
@@ -730,11 +624,7 @@ def makePostVtkFilterWarp(
return obj
def makePostVtkFilterContours(
doc,
base_vtk_result,
name="VtkFilterContours"
):
def makePostVtkFilterContours(doc, base_vtk_result, name="VtkFilterContours"):
"""makePostVtkFilterContours(document, base_vtk_result, [name]):
creates a FEM post processing contours filter object (vtk based)"""
obj = doc.addObject("Fem::FemPostContoursFilter", name)
@@ -745,11 +635,7 @@ def makePostVtkFilterContours(
return obj
def makePostVtkResult(
doc,
base_result,
name="VtkResult"
):
def makePostVtkResult(doc, base_result, name="VtkResult"):
"""makePostVtkResult(document, base_result, [name]):
creates a FEM post processing result object (vtk based) to hold FEM results"""
Pipeline_Name = "Pipeline_" + name
@@ -763,187 +649,151 @@ def makePostVtkResult(
# ********* solver objects ***********************************************************************
def makeEquationDeformation(
doc,
base_solver=None,
name="Deformation"
):
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,
name="Elasticity"
):
def makeEquationElasticity(doc, base_solver=None, name="Elasticity"):
"""makeEquationElasticity(document, [base_solver], [name]):
creates a FEM elasticity equation for a solver"""
from femsolver.elmer.equations import elasticity
obj = elasticity.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationElectricforce(
doc,
base_solver=None,
name="Electricforce"
):
def makeEquationElectricforce(doc, base_solver=None, name="Electricforce"):
"""makeEquationElectricforce(document, [base_solver], [name]):
creates a FEM Electricforce equation for a solver"""
from femsolver.elmer.equations import electricforce
obj = electricforce.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationElectrostatic(
doc,
base_solver=None,
name="Electrostatic"
):
def makeEquationElectrostatic(doc, base_solver=None, name="Electrostatic"):
"""makeEquationElectrostatic(document, [base_solver], [name]):
creates a FEM electrostatic equation for a solver"""
from femsolver.elmer.equations import electrostatic
obj = electrostatic.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationFlow(
doc,
base_solver=None,
name="Flow"
):
def makeEquationFlow(doc, base_solver=None, name="Flow"):
"""makeEquationFlow(document, [base_solver], [name]):
creates a FEM flow equation for a solver"""
from femsolver.elmer.equations import flow
obj = flow.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationFlux(
doc,
base_solver=None,
name="Flux"
):
def makeEquationFlux(doc, base_solver=None, name="Flux"):
"""makeEquationFlux(document, [base_solver], [name]):
creates a FEM flux equation for a solver"""
from femsolver.elmer.equations import flux
obj = flux.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationHeat(
doc,
base_solver=None,
name="Heat"
):
def makeEquationHeat(doc, base_solver=None, name="Heat"):
"""makeEquationHeat(document, [base_solver], [name]):
creates a FEM heat equation for a solver"""
from femsolver.elmer.equations import heat
obj = heat.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationMagnetodynamic(
doc,
base_solver=None,
name="Magnetodynamic"
):
def makeEquationMagnetodynamic(doc, base_solver=None, name="Magnetodynamic"):
"""makeEquationMagnetodynamic(document, [base_solver], [name]):
creates a FEM magnetodynamic equation for a solver"""
from femsolver.elmer.equations import magnetodynamic
obj = magnetodynamic.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeEquationMagnetodynamic2D(
doc,
base_solver=None,
name="Magnetodynamic2D"
):
def makeEquationMagnetodynamic2D(doc, base_solver=None, name="Magnetodynamic2D"):
"""makeEquationMagnetodynamic2D(document, [base_solver], [name]):
creates a FEM magnetodynamic2D equation for a solver"""
from femsolver.elmer.equations import magnetodynamic2D
obj = magnetodynamic2D.create(doc, name)
if base_solver:
base_solver.addObject(obj)
return obj
def makeSolverCalculiXCcxTools(
doc,
name="SolverCcxTools"
):
def makeSolverCalculiXCcxTools(doc, name="SolverCcxTools"):
"""makeSolverCalculiXCcxTools(document, [name]):
makes a Calculix solver object for the ccx tools module"""
obj = doc.addObject("Fem::FemSolverObjectPython", name)
from femobjects import solver_ccxtools
solver_ccxtools.SolverCcxTools(obj)
if FreeCAD.GuiUp:
from femviewprovider import view_solver_ccxtools
view_solver_ccxtools.VPSolverCcxTools(obj.ViewObject)
return obj
def makeSolverCalculix(
doc,
name="SolverCalculix"
):
def makeSolverCalculix(doc, name="SolverCalculix"):
"""makeSolverCalculix(document, [name]):
makes a Calculix solver object"""
import femsolver.calculix.solver
obj = femsolver.calculix.solver.create(doc, name)
return obj
def makeSolverElmer(
doc,
name="SolverElmer"
):
def makeSolverElmer(doc, name="SolverElmer"):
"""makeSolverElmer(document, [name]):
makes a Elmer solver object"""
import femsolver.elmer.solver
obj = femsolver.elmer.solver.create(doc, name)
return obj
def makeSolverMystran(
doc,
name="SolverMystran"
):
def makeSolverMystran(doc, name="SolverMystran"):
"""makeSolverMystran(document, [name]):
makes a Mystran solver object"""
import femsolver.mystran.solver
obj = femsolver.mystran.solver.create(doc, name)
return obj
def makeSolverZ88(
doc,
name="SolverZ88"
):
def makeSolverZ88(doc, name="SolverZ88"):
"""makeSolverZ88(document, [name]):
makes a Z88 solver object"""
import femsolver.z88.solver
obj = femsolver.z88.solver.create(doc, name)
return obj

View File

@@ -4,7 +4,7 @@ These coding rules apply to FEM module code only. Other modules or the base syst
## Spelling
- Be mindful of spelling. Spell checks are quite often neglected.
- Utilize [codespell](https://github.com/codespell-project/codespell) to discover and quickly correct spelling errors.
- Utilize [codespell](https://github.com/codespell-project/codespell) to discover and quickly correct spelling errors.
```bash
# Find typos
@@ -14,9 +14,9 @@ These coding rules apply to FEM module code only. Other modules or the base syst
codespell -i 3 -w -S *.ts -S *.dyn -S *.svg -L childs,dof,dum,freez,methode,nd,normaly,programm,som,uint,vertexes,inout src/Mod/Fem/
```
**Notes:**
1) We recommend running the dev version as it uses the most up to date typo dictionaries.
2) To find the most amount of typos we recommend running a quick `pip install --upgrade`
**Notes:**
1) We recommend running the dev version as it uses the most up to date typo dictionaries.
2) To find the most amount of typos we recommend running a quick `pip install --upgrade`
See the [codespell docs](https://github.com/codespell-project/codespell#updating) for more info.
@@ -68,7 +68,7 @@ These coding rules apply to FEM module code only. Other modules or the base syst
- One empty line
- relative imports
- One empty line
- FreeCAD Gui imports:
- FreeCAD Gui imports:
- The import of Gui modules should be guarded by a 'if FreeCAD.GuiUp:'
- On Gui only modules the guard is not needed
- Same as above but without a empty line
@@ -99,7 +99,7 @@ find src/Mod/Fem/ -name "*\.py" | xargs -I [] flake8 --ignore=E266,W503 --max-li
- print() vs. FreeCAD.Console.PrintMessage()
- `FreeCAD.Console.PrintMessage()` or Log or Error should be used
- `print()` should be used for debugging only
- [forum topic](https://forum.freecad.org/viewtopic.php?f=10&t=39110)
- [forum topic](https://forum.freecad.org/viewtopic.php?f=10&t=39110)
- BTW: Console prints need a new line where as print does not need one
- type checking:
- do not use hasattr(obj, "Proxy") and obj.Proxy.Type
@@ -114,7 +114,7 @@ find src/Mod/Fem/ -name "*\.py" | xargs -I [] flake8 --ignore=E266,W503 --max-li
- FreeCAD Python console
- in code examples which will be copied in FreeCAD Python console
- it is common to use App.ActiveDocument.some_obj or method
### Documenting
Python style is preferred over Doxygen style
- see `ccx` tools module in fem tools package

File diff suppressed because it is too large Load Diff

View File

@@ -41,7 +41,7 @@ if FreeCAD.GuiUp:
import FemGui
class CommandManager(object):
class CommandManager:
def __init__(self):
@@ -49,7 +49,7 @@ class CommandManager(object):
self.pixmap = self.command
self.menutext = self.__class__.__name__.lstrip("_")
self.accel = ""
self.tooltip = "Creates a {}".format(self.menutext)
self.tooltip = f"Creates a {self.menutext}"
self.resources = None
self.is_active = None
@@ -64,7 +64,7 @@ class CommandManager(object):
"Pixmap": self.pixmap,
"MenuText": QtCore.QT_TRANSLATE_NOOP(self.command, self.menutext),
"Accel": self.accel,
"ToolTip": QtCore.QT_TRANSLATE_NOOP(self.command, self.tooltip)
"ToolTip": QtCore.QT_TRANSLATE_NOOP(self.command, self.tooltip),
}
return self.resources
@@ -76,10 +76,7 @@ class CommandManager(object):
elif self.is_active == "with_document":
active = FreeCADGui.ActiveDocument is not None
elif self.is_active == "with_analysis":
active = (
FemGui.getActiveAnalysis() is not None
and self.active_analysis_in_active_doc()
)
active = FemGui.getActiveAnalysis() is not None and self.active_analysis_in_active_doc()
elif self.is_active == "with_results":
active = (
FemGui.getActiveAnalysis() is not None
@@ -93,24 +90,14 @@ class CommandManager(object):
and self.result_selected()
)
elif self.is_active == "with_part_feature":
active = (
FreeCADGui.ActiveDocument is not None
and self.part_feature_selected()
)
active = FreeCADGui.ActiveDocument is not None and self.part_feature_selected()
elif self.is_active == "with_femmesh":
active = (
FreeCADGui.ActiveDocument is not None
and self.femmesh_selected()
)
active = FreeCADGui.ActiveDocument is not None and self.femmesh_selected()
elif self.is_active == "with_gmsh_femmesh":
active = (
FreeCADGui.ActiveDocument is not None
and self.gmsh_femmesh_selected()
)
active = FreeCADGui.ActiveDocument is not None and self.gmsh_femmesh_selected()
elif self.is_active == "with_femmesh_andor_res":
active = (
FreeCADGui.ActiveDocument is not None
and self.with_femmesh_andor_res_selected()
FreeCADGui.ActiveDocument is not None and self.with_femmesh_andor_res_selected()
)
elif self.is_active == "with_material":
active = (
@@ -301,20 +288,12 @@ class CommandManager(object):
# methods to add the objects to the document in FreeCADGui mode
def add_obj_on_gui_set_edit(self, objtype):
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCADGui.addModule(
"FemGui"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.addModule("FemGui")
FreeCADGui.doCommand(
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
"make{}(FreeCAD.ActiveDocument))"
.format(objtype)
"make{}(FreeCAD.ActiveDocument))".format(objtype)
)
# no other obj should be selected if we go in task panel
FreeCADGui.Selection.clearSelection()
@@ -324,20 +303,12 @@ class CommandManager(object):
FreeCAD.ActiveDocument.recompute()
def add_obj_on_gui_noset_edit(self, objtype):
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCADGui.addModule(
"FemGui"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.addModule("FemGui")
FreeCADGui.doCommand(
"FemGui.getActiveAnalysis().addObject(ObjectsFem."
"make{}(FreeCAD.ActiveDocument))"
.format(objtype)
"make{}(FreeCAD.ActiveDocument))".format(objtype)
)
# FreeCAD.ActiveDocument.commitTransaction() # solver command class had this line
# no clear selection is done
@@ -347,23 +318,15 @@ class CommandManager(object):
# like add_obj_on_gui_noset_edit but the parent object
# is expanded in the tree to see the added obj
# the added obj is also selected to enable direct additions to it
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCADGui.addModule(
"FemGui"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.addModule("FemGui")
# expand parent obj in tree view if selected
expandParentObject()
# add the object
FreeCADGui.doCommand(
"addedObj = FemGui.getActiveAnalysis().addObject(ObjectsFem."
"make{}(FreeCAD.ActiveDocument))[0]"
.format(objtype)
"make{}(FreeCAD.ActiveDocument))[0]".format(objtype)
)
# select only added object
FreeCADGui.Selection.clearSelection()
@@ -372,17 +335,11 @@ class CommandManager(object):
FreeCAD.ActiveDocument.recompute()
def add_obj_on_gui_selobj_set_edit(self, objtype):
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.doCommand(
"ObjectsFem.make{}("
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
.format(objtype, self.selobj.Name)
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})".format(objtype, self.selobj.Name)
)
FreeCADGui.Selection.clearSelection()
FreeCADGui.doCommand(
@@ -391,17 +348,11 @@ class CommandManager(object):
FreeCAD.ActiveDocument.recompute()
def add_obj_on_gui_selobj_noset_edit(self, objtype):
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.doCommand(
"ObjectsFem.make{}("
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
.format(objtype, self.selobj.Name)
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})".format(objtype, self.selobj.Name)
)
FreeCADGui.Selection.clearSelection()
FreeCAD.ActiveDocument.recompute()
@@ -409,17 +360,11 @@ class CommandManager(object):
def add_obj_on_gui_selobj_expand_noset_edit(self, objtype):
# like add_obj_on_gui_selobj_noset_edit but the selection is kept
# and the selobj is expanded in the tree to see the added obj
FreeCAD.ActiveDocument.openTransaction(
"Create Fem{}"
.format(objtype)
)
FreeCADGui.addModule(
"ObjectsFem"
)
FreeCAD.ActiveDocument.openTransaction(f"Create Fem{objtype}")
FreeCADGui.addModule("ObjectsFem")
FreeCADGui.doCommand(
"ObjectsFem.make{}("
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})"
.format(objtype, self.selobj.Name)
"FreeCAD.ActiveDocument, FreeCAD.ActiveDocument.{})".format(objtype, self.selobj.Name)
)
# expand selobj in tree view
expandParentObject()

View File

@@ -63,6 +63,7 @@ def setup_boxanalysisbase(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_boxanalysis_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -37,12 +37,14 @@ def get_information():
"constraints": [],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["frequency"]
"equations": ["frequency"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.boxanalysis_frequency import setup
@@ -53,6 +55,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -72,7 +75,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
if solvertype == "ccxtools":
solver_obj.AnalysisType = "frequency"
solver_obj.GeometricalNonlinearity = "linear"

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "force", "pressure"],
"solvers": ["ccxtools", "elmer"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.boxanalysis_static import setup
@@ -55,6 +57,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -75,7 +78,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
ObjectsFem.makeEquationElasticity(doc, solver_obj)

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["displacement", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["buckling"]
"equations": ["buckling"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.buckling_lateraltorsionalbuckling import setup
@@ -65,6 +67,7 @@ flange load for a buckling factor of 1.00:
43280000 Nmm / 278.6 mm = 155348 N
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -108,7 +111,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -125,10 +128,10 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# shell thicknesses
thickness_flanges = ObjectsFem.makeElementGeometry2D(doc, 10.7, 'Thickness_Flanges')
thickness_flanges = ObjectsFem.makeElementGeometry2D(doc, 10.7, "Thickness_Flanges")
thickness_flanges.References = [(geom_obj, ("Face1", "Face2", "Face3", "Face4"))]
analysis.addObject(thickness_flanges)
thickness_web = ObjectsFem.makeElementGeometry2D(doc, 7.1, 'Thickness_Web')
thickness_web = ObjectsFem.makeElementGeometry2D(doc, 7.1, "Thickness_Web")
thickness_web.References = [(geom_obj, "Face5")]
analysis.addObject(thickness_web)
@@ -173,6 +176,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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["displacement", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["buckling"]
"equations": ["buckling"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.buckling_platebuckling import setup
@@ -55,6 +57,7 @@ See forum topic post:
https://forum.freecad.org/viewtopic.php?f=18&t=20217&start=110#p509935
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -82,7 +85,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -100,7 +103,7 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# shell thickness
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 50, 'Thickness')
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 50, "Thickness")
analysis.addObject(thickness_obj)
# material
@@ -146,6 +149,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:

View File

@@ -40,12 +40,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["buckling"]
"equations": ["buckling"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_buckling_flexuralbuckling import setup
@@ -59,6 +61,7 @@ This example is based on a CalculiX verification example.
http://www.feacluster.com/CalculiX/ccx_2.13/doc/ccx/input_deck_viewer.php?input_deck=beam8b.inp
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -87,7 +90,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver,
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -126,6 +129,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:

View File

@@ -69,7 +69,7 @@ def setup_cantilever_base_edge(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "mystran":
solver_obj = ObjectsFem.makeSolverMystran(doc, "SolverMystran")
else:
@@ -92,7 +92,7 @@ def setup_cantilever_base_edge(doc=None, solvertype="ccxtools"):
sectiontype="Rectangular",
width=1000.0,
height=1000.0,
name="BeamCrossSection"
name="BeamCrossSection",
)
analysis.addObject(beamsection_obj)
@@ -113,13 +113,14 @@ def setup_cantilever_base_edge(doc=None, solvertype="ccxtools"):
# constraint force
con_force = ObjectsFem.makeConstraintForce(doc, "ConstraintForce")
con_force.References = [(geom_obj, "Vertex2")]
con_force.Force = "9000000.0 N" # 9 MN
con_force.Force = "9000000.0 N" # 9 MN
con_force.Direction = (load_line, ["Edge1"])
con_force.Reversed = False
analysis.addObject(con_force)
# mesh
from .meshes.mesh_canticcx_seg3 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -58,7 +58,7 @@ def setup_cantilever_base_face(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "mystran":
solver_obj = ObjectsFem.makeSolverMystran(doc, "SolverMystran")
elif solvertype == "z88":
@@ -78,7 +78,7 @@ def setup_cantilever_base_face(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# shell thickness
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 1000, 'Thickness')
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 1000, "Thickness")
analysis.addObject(thickness_obj)
# material
@@ -105,6 +105,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:

View File

@@ -54,7 +54,7 @@ def setup_cantilever_base_solid(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
ObjectsFem.makeEquationElasticity(doc, solver_obj)
@@ -92,6 +92,7 @@ def setup_cantilever_base_solid(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_canticcx_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -36,12 +36,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_beam_circle import setup
@@ -73,6 +75,7 @@ CalculiX FEM max deflection:
- Delta ca. 1.5 %
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -36,12 +36,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_beam_pipe import setup
@@ -77,6 +79,7 @@ CalculiX FEM max deflection:
- Delta ca. 1.0 %
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -36,12 +36,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_beam_rect import setup
@@ -74,6 +76,7 @@ CalculiX FEM max deflection:
- but the rotation seems 90 degree rotated (FIXME)
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -40,12 +40,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_hexa20 import setup
@@ -57,6 +59,7 @@ hexa20 elements and face load
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -80,6 +83,7 @@ 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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "mystran"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_quad4 import setup
@@ -57,6 +59,7 @@ See forum topic post:
CalculiX cantilever modeled with quad4 face elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -76,6 +79,7 @@ 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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_quad8 import setup
@@ -57,6 +59,7 @@ See forum topic post:
CalculiX cantilever modeled with quad8 face elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -76,6 +79,7 @@ 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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "mystran"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_seg2 import setup
@@ -57,6 +59,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=16044
CalculiX cantilever modeled with seg2 beam elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -76,6 +79,7 @@ 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:

View File

@@ -34,12 +34,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_seg3 import setup
@@ -52,6 +54,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=16044
CalculiX cantilever modeled with seg3 beam elements
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -38,12 +38,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "mystran", "z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_tetra4 import setup
@@ -55,6 +57,7 @@ Mesh before run the example.
...
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "mystran"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_tria3 import setup
@@ -57,6 +59,7 @@ See forum topic post:
CalculiX cantilever modeled with tria3 face elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -76,6 +79,7 @@ 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:

View File

@@ -34,12 +34,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_ele_tria6 import setup
@@ -51,6 +53,7 @@ See forum topic post:
CalculiX cantilever modeled with face elements
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -37,12 +37,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "mystran", "z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_faceload import setup
@@ -53,6 +55,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -37,12 +37,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "mystran", "z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_nodeload import setup
@@ -53,6 +55,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -76,7 +79,7 @@ def setup(doc=None, solvertype="ccxtools"):
(geom_obj, "Vertex5"),
(geom_obj, "Vertex6"),
(geom_obj, "Vertex7"),
(geom_obj, "Vertex8")
(geom_obj, "Vertex8"),
]
con_force.Force = "9000000.0 N"
con_force.Direction = (doc.Box, ["Edge5"])

View File

@@ -37,12 +37,14 @@ def get_information():
"constraints": ["fixed", "displacement"],
"solvers": ["ccxtools", "elmer"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.ccx_cantilever_prescribeddisplacement import setup
@@ -53,6 +55,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):

View File

@@ -44,12 +44,14 @@ def get_information():
"constraints": ["centrif", "fixed"],
"solvers": ["ccxtools"],
"material": "multimaterial",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_centrif import setup
@@ -62,6 +64,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=57770
constraint centrif, concerning CENTRIF label from ccx's *DLOAD card
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -129,7 +132,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -178,6 +181,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:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["fixed", "force", "contact"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_contact_shell_shell import setup
@@ -62,6 +64,7 @@ based on https://forum.freecad.org/viewtopic.php?f=18&t=42228#p359488
contact example shell to shell elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -109,7 +112,7 @@ def setup(doc=None, solvertype="ccxtools"):
force_point.ViewObject.PointColor = (1.0, 0.0, 0.0)
# boolean fragment of upper tubo and force point
boolfrag = SplitFeatures.makeBooleanFragments(name='BooleanFragments')
boolfrag = SplitFeatures.makeBooleanFragments(name="BooleanFragments")
boolfrag.Objects = [upper_tube, force_point]
if FreeCAD.GuiUp:
upper_tube.ViewObject.hide()
@@ -138,7 +141,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -156,7 +159,7 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# shell thickness
shell_thick = ObjectsFem.makeElementGeometry2D(doc, 0.5, 'ShellThickness')
shell_thick = ObjectsFem.makeElementGeometry2D(doc, 0.5, "ShellThickness")
analysis.addObject(shell_thick)
# material
@@ -197,6 +200,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:

View File

@@ -44,12 +44,14 @@ def get_information():
"constraints": ["fixed", "pressure", "contact"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_contact_solid_solid import setup
@@ -61,6 +63,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=20276
constraint contact for solid to solid mesh
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -91,7 +94,7 @@ def setup(doc=None, solvertype="ccxtools"):
top_halfcyl_obj.Radius = 30
top_halfcyl_obj.Height = 500
top_halfcyl_obj.Angle = 180
top_halfcyl_sh = Part.getShape(top_halfcyl_obj, '', needSubElement=False, refine=True)
top_halfcyl_sh = Part.getShape(top_halfcyl_obj, "", needSubElement=False, refine=True)
top_halfcyl_obj.Shape = top_halfcyl_sh
top_halfcyl_obj.Placement = FreeCAD.Placement(
Vector(0, -42, 0),
@@ -118,7 +121,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -180,7 +183,11 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(con_contact)
# mesh
from .meshes.mesh_contact_box_halfcylinder_tetra10 import create_nodes, create_elements
from .meshes.mesh_contact_box_halfcylinder_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -50,12 +50,14 @@ def get_information():
"constraints": ["section_print", "fixed", "pressure"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_section_print import setup
@@ -68,6 +70,7 @@ https://forum.freecad.org/viewtopic.php?t=43044
constraint section print with volume elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -83,27 +86,20 @@ def setup(doc=None, solvertype="ccxtools"):
# geometric objects
# the part sketch
arc_sketch = doc.addObject("Sketcher::SketchObject", "Arc_Sketch")
arc_sketch.Placement = FreeCAD.Placement(
Vector(0, 0, 0),
Rotation(0, 0, 0, 1)
)
arc_sketch.Placement = FreeCAD.Placement(Vector(0, 0, 0), Rotation(0, 0, 0, 1))
arc_sketch.MapMode = "Deactivated"
# not the exact geometry which makes a closed wire
# exact geometry will be made by the constraints
# the order is important for the constraints definition
geoList = [
Part.ArcOfCircle(
Part.Circle(Vector(0, 0, 0), Vector(0, 0, 1), 47),
0,
math.pi
),
Part.ArcOfCircle(Part.Circle(Vector(0, 0, 0), Vector(0, 0, 1), 47), 0, math.pi),
Part.ArcOfCircle(
Part.Circle(Vector(-19, -22, 0), Vector(0, 0, 1), 89),
math.pi / 12,
math.pi / 1.1
math.pi / 1.1,
),
Part.LineSegment(Vector(-105, 0, 0), Vector(-47, 0, 0)),
Part.LineSegment(Vector(47, 0, 0), Vector(67, 0, 0))
Part.LineSegment(Vector(47, 0, 0), Vector(67, 0, 0)),
]
arc_sketch.addGeometry(geoList, False)
# https://wiki.freecad.org/Sketcher_ConstrainCoincident
@@ -122,7 +118,7 @@ def setup(doc=None, solvertype="ccxtools"):
Sketcher.Constraint("DistanceX", 2, 2, 2, 1, 58),
Sketcher.Constraint("DistanceX", 3, 2, 3, 1, 20),
Sketcher.Constraint("Radius", 0, 47),
Sketcher.Constraint("Radius", 1, 89)
Sketcher.Constraint("Radius", 1, 89),
]
arc_sketch.addConstraint(conList)
@@ -144,12 +140,12 @@ def setup(doc=None, solvertype="ccxtools"):
section_sketch = doc.addObject("Sketcher::SketchObject", "Section_Sketch")
section_sketch.Placement = FreeCAD.Placement(
Vector(0.000000, 0.000000, 0.000000),
Rotation(0.000000, 0.000000, 0.000000, 1.000000)
Rotation(0.000000, 0.000000, 0.000000, 1.000000),
)
section_sketch.MapMode = "Deactivated"
section_sketch.addGeometry(
Part.LineSegment(Vector(-6.691961, -16.840161, 0), Vector(75.156087, 79.421394, 0)),
False
False,
)
# section_sketch.ExternalGeometry = extrude_part
@@ -223,7 +219,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -266,6 +262,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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed", "self weight"],
"solvers": ["ccxtools", "elmer"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_selfweight_cantilever import setup
@@ -59,6 +61,7 @@ l = 32 m, yields just from self weight, means max sigma around 235 n/mm2
max deformation = 576.8 mm
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -86,7 +89,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
eq_obj = ObjectsFem.makeEquationElasticity(doc, solver_obj)
@@ -127,6 +130,7 @@ def setup(doc=None, solvertype="ccxtools"):
# mesh
from .meshes.mesh_selfweight_cantilever_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -44,12 +44,14 @@ def get_information():
"constraints": ["fixed", "force", "tie"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_tie import setup
@@ -62,6 +64,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=42783
constraint tie, bond two surfaces together (solid mesh only)
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -108,7 +111,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -156,6 +159,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:

View File

@@ -44,12 +44,14 @@ def get_information():
"constraints": ["pressure", "displacement", "transform"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_transform_beam_hinged import setup
@@ -62,6 +64,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=20238#p157643
Constraint transform on a beam
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -83,7 +86,9 @@ def setup(doc=None, solvertype="ccxtools"):
cylinder.Height = "20 mm"
cylinder.Radius = "6 mm"
cylinder.Placement = FreeCAD.Placement(
Vector(10, 12, 10), Rotation(0, 0, 90), Vector(0, 0, 0),
Vector(10, 12, 10),
Rotation(0, 0, 90),
Vector(0, 0, 0),
)
cut = doc.addObject("Part::Cut", "Cut")
cut.Base = cube
@@ -102,9 +107,9 @@ def setup(doc=None, solvertype="ccxtools"):
fusion.Refine = True
# compound filter
geom_obj = CompoundFilter.makeCompoundFilter(name='CompoundFilter')
geom_obj = CompoundFilter.makeCompoundFilter(name="CompoundFilter")
geom_obj.Base = fusion
geom_obj.FilterType = 'window-volume'
geom_obj.FilterType = "window-volume"
doc.recompute()
if FreeCAD.GuiUp:
@@ -118,7 +123,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -169,6 +174,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:
@@ -180,7 +186,7 @@ def setup(doc=None, solvertype="ccxtools"):
femmesh_obj.FemMesh = fem_mesh
femmesh_obj.Part = geom_obj
femmesh_obj.SecondOrderLinear = False
femmesh_obj.CharacteristicLengthMax = '7 mm'
femmesh_obj.CharacteristicLengthMax = "7 mm"
doc.recompute()
return doc

View File

@@ -52,12 +52,14 @@ def get_information():
"constraints": ["fixed", "force", "transform"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.constraint_transform_torque import setup
@@ -72,6 +74,7 @@ https://forum.freecad.org/viewtopic.php?t=18970
constraint transform with a constraint force
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -115,7 +118,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -160,6 +163,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:

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": [],
"solvers": ["ccxtools", "elmer"],
"material": "solid",
"equations": ["elasticity"] # "frequency", but list not allowed here
"equations": ["elasticity"], # "frequency", but list not allowed here
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.elmer_nonguitutorial01_eigenvalue_of_elastic_beam import setup
@@ -55,6 +57,7 @@ See forum topic post:
https://forum.freecad.org/viewtopic.php?t=56590
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -83,7 +86,7 @@ def setup(doc=None, solvertype="elmer"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
eq_obj = ObjectsFem.makeEquationElasticity(doc, solver_obj)
@@ -118,15 +121,13 @@ def setup(doc=None, solvertype="elmer"):
# constraint fixed
con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed")
con_fixed.References = [
(geom_obj, "Face1"),
(geom_obj, "Face2")
]
con_fixed.References = [(geom_obj, "Face1"), (geom_obj, "Face2")]
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:

View File

@@ -42,12 +42,14 @@ def get_information():
"constraints": ["displacement", "spring"],
"solvers": ["elmer"],
"material": "solid",
"equations": ["deformation"]
"equations": ["deformation"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_deformation_spring_elmer import setup
@@ -56,6 +58,7 @@ setup()
Deformation equation - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -75,18 +78,24 @@ def setup(doc=None, solvertype="elmer"):
SketchPath = body.newObject("Sketcher::SketchObject", "Spring_Path")
SketchPath.AttachmentSupport = (doc.getObject("XY_Plane"), [""])
SketchPath.MapMode = "FlatFace"
SketchPath.addGeometry(Part.LineSegment(Vector(
-20.0, 30.0, 0.0), Vector(-20.0, 0.0, 0.0)), False)
SketchPath.addConstraint(Sketcher.Constraint('PointOnObject', 0, 2, -1))
SketchPath.addConstraint(Sketcher.Constraint('Vertical', 0))
SketchPath.addGeometry(Part.ArcOfCircle(Part.Circle(
Vector(0.0, 0.0, 0.0), Vector(0, 0, 1), 20.0), 3.141593, 6.283185), False)
SketchPath.addConstraint(Sketcher.Constraint('Tangent', 0, 2, 1, 1))
SketchPath.addConstraint(Sketcher.Constraint('PointOnObject', 1, 2, -1))
SketchPath.addGeometry(Part.LineSegment(
Vector(20.0, 0.0, 0.0), Vector(20.0, 30.0, 0.0)), False)
SketchPath.addConstraint(Sketcher.Constraint('Tangent', 1, 2, 2, 1))
SketchPath.addConstraint(Sketcher.Constraint('Equal', 2, 0))
SketchPath.addGeometry(
Part.LineSegment(Vector(-20.0, 30.0, 0.0), Vector(-20.0, 0.0, 0.0)), False
)
SketchPath.addConstraint(Sketcher.Constraint("PointOnObject", 0, 2, -1))
SketchPath.addConstraint(Sketcher.Constraint("Vertical", 0))
SketchPath.addGeometry(
Part.ArcOfCircle(
Part.Circle(Vector(0.0, 0.0, 0.0), Vector(0, 0, 1), 20.0),
3.141593,
6.283185,
),
False,
)
SketchPath.addConstraint(Sketcher.Constraint("Tangent", 0, 2, 1, 1))
SketchPath.addConstraint(Sketcher.Constraint("PointOnObject", 1, 2, -1))
SketchPath.addGeometry(Part.LineSegment(Vector(20.0, 0.0, 0.0), Vector(20.0, 30.0, 0.0)), False)
SketchPath.addConstraint(Sketcher.Constraint("Tangent", 1, 2, 2, 1))
SketchPath.addConstraint(Sketcher.Constraint("Equal", 2, 0))
SketchPath.ViewObject.Visibility = False
# sketch defining the spring cross section
@@ -94,11 +103,11 @@ def setup(doc=None, solvertype="elmer"):
SketchCircle.AttachmentSupport = (doc.getObject("XZ_Plane"), [""])
SketchCircle.MapMode = "FlatFace"
SketchCircle.addGeometry(Part.Circle(Vector(-20.0, 0.0, 0.0), Vector(0, 0, 1), 7.5), False)
SketchCircle.addConstraint(Sketcher.Constraint('PointOnObject', 0, 3, -1))
SketchCircle.addConstraint(Sketcher.Constraint("PointOnObject", 0, 3, -1))
SketchCircle.ViewObject.Visibility = False
# the spring object
SpringObject = body.newObject('PartDesign::AdditivePipe', 'Spring')
SpringObject = body.newObject("PartDesign::AdditivePipe", "Spring")
SpringObject.Profile = SketchCircle
SpringObject.Spine = SketchPath
@@ -112,6 +121,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -148,7 +158,7 @@ def setup(doc=None, solvertype="elmer"):
DisplaceLeft = doc.addObject("Fem::ConstraintDisplacement", "DisplacementLeft")
DisplaceLeft.xFree = False
DisplaceLeft.hasXFormula = True
DisplaceLeft.xDisplacementFormula = "Variable \"time\"; Real MATC \"0.006*tx\""
DisplaceLeft.xDisplacementFormula = 'Variable "time"; Real MATC "0.006*tx"'
DisplaceLeft.yFree = False
DisplaceLeft.yFix = True
DisplaceLeft.zFree = False
@@ -159,7 +169,7 @@ def setup(doc=None, solvertype="elmer"):
DisplaceRight = doc.addObject("Fem::ConstraintDisplacement", "DisplacementRight")
DisplaceRight.xFree = False
DisplaceRight.hasXFormula = True
DisplaceRight.xDisplacementFormula = "Variable \"time\"; Real MATC \"-0.006*tx\""
DisplaceRight.xDisplacementFormula = 'Variable "time"; Real MATC "-0.006*tx"'
DisplaceRight.yFree = False
DisplaceRight.yFix = True
DisplaceRight.zFree = False
@@ -189,15 +199,13 @@ def setup(doc=None, solvertype="elmer"):
# 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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["electrostatic potential"],
"solvers": ["elmer"],
"material": "fluid",
"equations": ["electrostatic"]
"equations": ["electrostatic"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_electrostatics_capacitance_two_balls import setup
@@ -61,6 +63,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=41488&start=90#p412047
Electrostatics equation in FreeCAD FEM-Elmer
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -102,6 +105,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -174,18 +178,20 @@ def setup(doc=None, solvertype="elmer"):
# 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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
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
from .meshes.mesh_capacitance_two_balls_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -46,12 +46,14 @@ def get_information():
"constraints": ["electrostatic potential"],
"solvers": ["elmer"],
"material": "fluid",
"equations": ["electrostatic"]
"equations": ["electrostatic"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_electrostatics_electricforce_elmer_nongui6 import setup
@@ -64,6 +66,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=41488&start=40#p373292
Electrostatics equation in FreeCAD FEM-Elmer
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -86,7 +89,8 @@ def setup(doc=None, solvertype="elmer"):
Part.LineSegment(Vector(0.000000, 0.000000, 0), Vector(57.407921, 0.000000, 0)),
Part.LineSegment(Vector(57.407921, 0.000000, 0), Vector(57.407921, 35.205284, 0)),
Part.LineSegment(Vector(57.407921, 35.205284, 0), Vector(0.000000, 35.205284, 0)),
Part.LineSegment(Vector(0.000000, 35.205284, 0), Vector(0.000000, 0.000000, 0))]
Part.LineSegment(Vector(0.000000, 35.205284, 0), Vector(0.000000, 0.000000, 0)),
]
base_sketch.addGeometry(base_geoList, False)
base_conList = [
Sketcher.Constraint("Coincident", 0, 2, 1, 1),
@@ -99,7 +103,8 @@ def setup(doc=None, solvertype="elmer"):
Sketcher.Constraint("Vertical", 3),
Sketcher.Constraint("Coincident", 0, 1, -1, 1),
Sketcher.Constraint("DistanceY", 1, 1, 1, 2, 35.205284),
Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 57.407921)]
Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 57.407921),
]
base_sketch.addConstraint(base_conList)
base_sketch.setDatum(9, Units.Quantity("5000.000000 mm"))
base_sketch.setDatum(10, Units.Quantity("5000.000000 mm"))
@@ -120,7 +125,8 @@ def setup(doc=None, solvertype="elmer"):
Part.LineSegment(Vector(5037.082520, 0.000000, 0), Vector(1309.763672, -21.422216, 0)),
Part.LineSegment(Vector(1309.763672, 0.000000, 0), Vector(1372.406982, 1544.678467, 0)),
Part.LineSegment(Vector(1372.406982, 1544.678467, 0), Vector(-37.083382, 1544.678467, 0)),
Part.LineSegment(Vector(0.000000, 1544.678467, 0), Vector(25.560951, 4958.778320, 0))]
Part.LineSegment(Vector(0.000000, 1544.678467, 0), Vector(25.560951, 4958.778320, 0)),
]
upper_sketch.addGeometry(upper_geoList, False)
upper_conList = [
Sketcher.Constraint("Horizontal", 0),
@@ -140,7 +146,8 @@ def setup(doc=None, solvertype="elmer"):
Sketcher.Constraint("DistanceX", 0, 1, 0, 2, 5037.082520),
Sketcher.Constraint("DistanceY", 1, 2, 1, 1, 4958.778320),
Sketcher.Constraint("DistanceY", 3, 1, 3, 2, 1544.678467),
Sketcher.Constraint("DistanceX", 4, 2, 4, 1, 1309.763672)]
Sketcher.Constraint("DistanceX", 4, 2, 4, 1, 1309.763672),
]
upper_sketch.addConstraint(upper_conList)
upper_sketch.setDatum(14, Units.Quantity("5000.000000 mm"))
upper_sketch.setDatum(15, Units.Quantity("5000.000000 mm"))
@@ -163,6 +170,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -209,7 +217,8 @@ def setup(doc=None, solvertype="elmer"):
(geom_obj, "Face4"),
(geom_obj, "Face5"),
(geom_obj, "Face6"),
(geom_obj, "Face11")]
(geom_obj, "Face11"),
]
con_elect_pot2.Potential = "1 V"
con_elect_pot2.CapacitanceBody = 2
con_elect_pot2.CapacitanceBodyEnabled = True
@@ -231,23 +240,26 @@ def setup(doc=None, solvertype="elmer"):
(geom_obj, "Face4"),
(geom_obj, "Face5"),
(geom_obj, "Face6"),
(geom_obj, "Face11")]
(geom_obj, "Face11"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
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
from .meshes.mesh_electricforce_elmer_nongui6_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -41,16 +41,22 @@ def get_information():
"name": "Flow - Elmer 2D",
"meshtype": "solid",
"meshelement": "Tet10",
"constraints": ["initial pressure", "initial temperature",
"temperature", "velocity"],
"constraints": [
"initial pressure",
"initial temperature",
"temperature",
"velocity",
],
"solvers": ["elmer"],
"material": "fluid",
"equations": ["flow", "heat"]
"equations": ["flow", "heat"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_flow_elmer_2D import setup
@@ -59,6 +65,7 @@ setup()
Flow and Heat equation - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -118,6 +125,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -185,7 +193,7 @@ def setup(doc=None, solvertype="elmer"):
FlowVelocity_Inlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Inlet")
FlowVelocity_Inlet.References = [(BooleanFragments, "Edge5")]
FlowVelocity_Inlet.VelocityXFormula = (
"Variable Coordinate 2; Real MATC \"10*(tx+50e-3)*(50e-3-tx)\""
'Variable Coordinate 2; Real MATC "10*(tx+50e-3)*(50e-3-tx)"'
)
FlowVelocity_Inlet.VelocityXUnspecified = False
FlowVelocity_Inlet.VelocityXHasFormula = True
@@ -198,7 +206,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
FlowVelocity_Wall.VelocityXUnspecified = False
FlowVelocity_Wall.VelocityYUnspecified = False
analysis.addObject(FlowVelocity_Wall)
@@ -216,7 +225,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
analysis.addObject(Temperature_Wall)
# constraint inlet temperature
@@ -254,20 +264,19 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge1"),
(BooleanFragments, "Vertex2"),
(BooleanFragments, "Vertex4"),
(BooleanFragments, "Vertex6")]
(BooleanFragments, "Vertex6"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -41,16 +41,23 @@ def get_information():
"name": "Initial Flow - Elmer 2D",
"meshtype": "solid",
"meshelement": "Tet10",
"constraints": ["initial pressure", "initial temperature", "initial velocity",
"temperature", "velocity"],
"constraints": [
"initial pressure",
"initial temperature",
"initial velocity",
"temperature",
"velocity",
],
"solvers": ["elmer"],
"material": "fluid",
"equations": ["flow", "heat"]
"equations": ["flow", "heat"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_flow_initial_elmer_2D import setup
@@ -59,6 +66,7 @@ setup()
Flow and Heat equation with initial velocity - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -118,6 +126,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -196,7 +205,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
FlowVelocity_Wall.VelocityXUnspecified = False
FlowVelocity_Wall.VelocityYUnspecified = False
analysis.addObject(FlowVelocity_Wall)
@@ -223,7 +233,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
analysis.addObject(Temperature_Wall)
# constraint inlet temperature
@@ -261,20 +272,19 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge1"),
(BooleanFragments, "Vertex2"),
(BooleanFragments, "Vertex4"),
(BooleanFragments, "Vertex6")]
(BooleanFragments, "Vertex6"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -41,16 +41,22 @@ def get_information():
"name": "Turbulent Flow - Elmer 2D",
"meshtype": "solid",
"meshelement": "Tet10",
"constraints": ["initial pressure", "initial temperature",
"temperature", "velocity"],
"constraints": [
"initial pressure",
"initial temperature",
"temperature",
"velocity",
],
"solvers": ["elmer"],
"material": "fluid",
"equations": ["flow", "heat"]
"equations": ["flow", "heat"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_flow_turbulent_elmer_2D import setup
@@ -59,6 +65,7 @@ setup()
Flow and Heat equation in turbulent flow - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -118,6 +125,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -191,7 +199,7 @@ def setup(doc=None, solvertype="elmer"):
FlowVelocity_Inlet = ObjectsFem.makeConstraintFlowVelocity(doc, "FlowVelocity_Inlet")
FlowVelocity_Inlet.References = [(BooleanFragments, "Edge5")]
FlowVelocity_Inlet.VelocityXFormula = (
"Variable Coordinate 2; Real MATC \"10*(tx+50e-3)*(50e-3-tx)\""
'Variable Coordinate 2; Real MATC "10*(tx+50e-3)*(50e-3-tx)"'
)
FlowVelocity_Inlet.VelocityXUnspecified = False
FlowVelocity_Inlet.VelocityXHasFormula = True
@@ -204,7 +212,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
FlowVelocity_Wall.VelocityXUnspecified = False
FlowVelocity_Wall.VelocityYUnspecified = False
analysis.addObject(FlowVelocity_Wall)
@@ -222,7 +231,8 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge2"),
(BooleanFragments, "Edge3"),
(BooleanFragments, "Edge4"),
(BooleanFragments, "Edge7")]
(BooleanFragments, "Edge7"),
]
analysis.addObject(Temperature_Wall)
# constraint inlet temperature
@@ -260,20 +270,19 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Edge1"),
(BooleanFragments, "Vertex2"),
(BooleanFragments, "Vertex4"),
(BooleanFragments, "Vertex6")]
(BooleanFragments, "Vertex6"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -40,12 +40,14 @@ def get_information():
"constraints": ["electrostatic potential", "temperature"],
"solvers": ["elmer"],
"material": "solid",
"equations": ["electrostatic", "flux", "heat"]
"equations": ["electrostatic", "flux", "heat"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_flux_elmer import setup
@@ -54,6 +56,7 @@ setup()
Potential flux and heat flux - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -80,6 +83,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -155,15 +159,13 @@ def setup(doc=None, solvertype="elmer"):
# 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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["current density"],
"solvers": ["elmer"],
"material": "solid",
"equations": ["electromagnetic"]
"equations": ["electromagnetic"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_magnetodynamics_2D_elmer import setup
@@ -57,6 +59,7 @@ setup()
Magnetodynamic2D equation - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -120,8 +123,7 @@ def setup(doc=None, solvertype="elmer"):
Powder.ViewObject.Visibility = False
# a half circle defining later the air volume
Air_Circle = Part.makeCircle(
140.0, Vector(0.0, 60.0, 0.0), Vector(0.0, 0.0, 1.0), -90.0, 90.0)
Air_Circle = Part.makeCircle(140.0, Vector(0.0, 60.0, 0.0), Vector(0.0, 0.0, 1.0), -90.0, 90.0)
Air_Line = Part.makeLine((0.0, -80.0, 0.0), (0.0, 200.0, 0.0))
Air_Area = doc.addObject("Part::Feature", "Air_Area")
Air_Area.Shape = Part.Face([Part.Wire([Air_Circle, Air_Line])])
@@ -175,6 +177,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -212,7 +215,8 @@ def setup(doc=None, solvertype="elmer"):
material_obj.References = [
(BooleanFragments, "Face2"),
(BooleanFragments, "Face5"),
(BooleanFragments, "Face6")]
(BooleanFragments, "Face6"),
]
analysis.addObject(material_obj)
# graphite of the crucible
@@ -265,20 +269,19 @@ def setup(doc=None, solvertype="elmer"):
(BooleanFragments, "Face1"),
(BooleanFragments, "Face2"),
(BooleanFragments, "Face3"),
(BooleanFragments, "Face4")]
(BooleanFragments, "Face4"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -42,12 +42,14 @@ def get_information():
"constraints": ["electrostatic potential", "magnetization"],
"solvers": ["elmer"],
"material": "solid",
"equations": ["electromagnetic"]
"equations": ["electromagnetic"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_magnetodynamics_elmer import setup
@@ -56,6 +58,7 @@ setup()
Magnetodynamic equation - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -99,6 +102,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -157,7 +161,8 @@ def setup(doc=None, solvertype="elmer"):
AxialField.References = [
(BooleanFragments, "Face4"),
(BooleanFragments, "Face5"),
(BooleanFragments, "Face6")]
(BooleanFragments, "Face6"),
]
AxialField.PotentialEnabled = False
AxialField.AV_im_1_Disabled = False
AxialField.AV_im_2_Disabled = False
@@ -209,18 +214,20 @@ def setup(doc=None, solvertype="elmer"):
# 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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
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
from .meshes.mesh_capacitance_two_balls_tetra10 import (
create_nodes,
create_elements,
)
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["magnetization"],
"solvers": ["elmer"],
"material": "solid",
"equations": ["magnetostatic"]
"equations": ["magnetostatic"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.equation_magnetostatics_2D_elmer import setup
@@ -57,6 +59,7 @@ setup()
Magnetodynamic2D equation - Elmer solver
"""
)
def setup(doc=None, solvertype="elmer"):
@@ -93,25 +96,43 @@ def setup(doc=None, solvertype="elmer"):
# the U-part of the horse shoe
# credits: https://forum.freecad.org/viewtopic.php?p=663051#p663051
vpairs = [[Vector(340.0, 200.0, 0.0), Vector(200.0, 200.0, 0.0)],
[Vector(200.0, 200.0, 0.0), Vector(200.0, 100.0, 0.0)],
[Vector(200.0, 100.0, 0.0), Vector(325.0, 100.0, 0.0)],
[Vector(325.0, 100.0, 0.0), Vector(325.0, -100.0, 0.0)],
[Vector(325.0, -100.0, 0.0), Vector(200.0, -100.0, 0.0)],
[Vector(200.0, -100.0, 0.0), Vector(200.0, -200.0, 0.0)],
[Vector(200.0, -200.0, 0.0), Vector(340.0, -200.0, 0.0)],
[Vector(340.0, 200.0, 0.0), Vector(340.0, -200.0, 0.0)]]
typeId = ['Part::GeomLine', 'Part::GeomLine', 'Part::GeomLine', 'Part::GeomBSplineCurve',
'Part::GeomLine', 'Part::GeomLine', 'Part::GeomLine', 'Part::GeomBSplineCurve']
e3Poles = [Vector(325.0, 100.0, 0.0), Vector(400.0, 100.0, 0.0),
Vector(400.0, 0.0, 0.0), Vector(400.0, -100.0, 0.0),
Vector(325.0, -100.0, 0.0)]
vpairs = [
[Vector(340.0, 200.0, 0.0), Vector(200.0, 200.0, 0.0)],
[Vector(200.0, 200.0, 0.0), Vector(200.0, 100.0, 0.0)],
[Vector(200.0, 100.0, 0.0), Vector(325.0, 100.0, 0.0)],
[Vector(325.0, 100.0, 0.0), Vector(325.0, -100.0, 0.0)],
[Vector(325.0, -100.0, 0.0), Vector(200.0, -100.0, 0.0)],
[Vector(200.0, -100.0, 0.0), Vector(200.0, -200.0, 0.0)],
[Vector(200.0, -200.0, 0.0), Vector(340.0, -200.0, 0.0)],
[Vector(340.0, 200.0, 0.0), Vector(340.0, -200.0, 0.0)],
]
typeId = [
"Part::GeomLine",
"Part::GeomLine",
"Part::GeomLine",
"Part::GeomBSplineCurve",
"Part::GeomLine",
"Part::GeomLine",
"Part::GeomLine",
"Part::GeomBSplineCurve",
]
e3Poles = [
Vector(325.0, 100.0, 0.0),
Vector(400.0, 100.0, 0.0),
Vector(400.0, 0.0, 0.0),
Vector(400.0, -100.0, 0.0),
Vector(325.0, -100.0, 0.0),
]
e3Knots = [0.0, 0.5, 1.0]
e3Mults = [4, 1, 4]
e3Degree = 3
e7Poles = [Vector(340.0, 200.0, 0.0), Vector(500.0, 200.0, 0.0),
Vector(500.0, 0.0, 0.0), Vector(500.0, -200.0, 0.0),
Vector(340.0, -200.0, 0.0)]
e7Poles = [
Vector(340.0, 200.0, 0.0),
Vector(500.0, 200.0, 0.0),
Vector(500.0, 0.0, 0.0),
Vector(500.0, -200.0, 0.0),
Vector(340.0, -200.0, 0.0),
]
e7Knots = [0.0, 0.5, 1.0]
e7Mults = [4, 1, 4]
e7Degree = 3
@@ -121,7 +142,7 @@ def setup(doc=None, solvertype="elmer"):
c7.buildFromPolesMultsKnots(e7Poles, e7Mults, e7Knots, False, e7Degree)
edges = [c3.toShape(), c7.toShape()]
for i in range(len(typeId)):
if typeId[i] == 'Part::GeomLine':
if typeId[i] == "Part::GeomLine":
edges.append(Part.makeLine(*vpairs[i]))
sedges = Part.__sortEdges__(edges)
@@ -175,6 +196,7 @@ def setup(doc=None, solvertype="elmer"):
analysis = ObjectsFem.makeAnalysis(doc, "Analysis")
if FreeCAD.GuiUp:
import FemGui
FemGui.setActiveAnalysis(analysis)
# solver
@@ -218,7 +240,8 @@ def setup(doc=None, solvertype="elmer"):
material_obj.References = [
(BooleanFragments, "Face1"),
(BooleanFragments, "Face2"),
(BooleanFragments, "Face3")]
(BooleanFragments, "Face3"),
]
analysis.addObject(material_obj)
# magnetization lower
@@ -247,20 +270,19 @@ def setup(doc=None, solvertype="elmer"):
mesh_region.References = [
(BooleanFragments, "Face1"),
(BooleanFragments, "Face2"),
(BooleanFragments, "Face3")]
(BooleanFragments, "Face3"),
]
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(
"Unexpected error when creating mesh: {}\n"
.format(error)
)
FreeCAD.Console.PrintError(f"Unexpected error when creating mesh: {error}\n")
doc.recompute()
return doc

View File

@@ -38,10 +38,12 @@ import FreeCADGui
class FemExamples(QtGui.QWidget):
def __init__(self):
super(FemExamples, self).__init__()
super().__init__()
self.init_ui()
def __del__(self,):
def __del__(
self,
):
# need as fix for qt event error
# --> see https://forum.freecad.org/viewtopic.php?f=18&t=10732&start=10#p86493
return
@@ -205,9 +207,9 @@ class FemExamples(QtGui.QWidget):
if grand_parent_name == "Solvers":
solver = parent.text(0)
# if done this way the Python commands are printed in Python console
FreeCADGui.doCommand("from femexamples.{} import setup".format(str(example)))
FreeCADGui.doCommand(f"from femexamples.{str(example)} import setup")
if solver is not None:
FreeCADGui.doCommand("setup(solvertype=\"{}\")".format(str(solver)))
FreeCADGui.doCommand(f'setup(solvertype="{str(solver)}")')
else:
FreeCADGui.doCommand("setup()")
QtGui.QApplication.restoreOverrideCursor()
@@ -236,10 +238,11 @@ class FemExamples(QtGui.QWidget):
# if done this way the Python commands are printed in Python console
FreeCADGui.doCommand("from femexamples.manager import run_example")
if solver is not None:
FreeCADGui.doCommand("run_example(\"{}\", solver=\"{}\", run_solver=True)"
.format(str(example), str(solver)))
FreeCADGui.doCommand(
f'run_example("{str(example)}", solver="{str(solver)}", run_solver=True)'
)
else:
FreeCADGui.doCommand("run_example(\"{}\", run_solver=True)".format(str(example)))
FreeCADGui.doCommand(f'run_example("{str(example)}", run_solver=True)')
QtGui.QApplication.restoreOverrideCursor()
def enable_buttons(self):

View File

@@ -39,12 +39,14 @@ def get_information():
"constraints": ["fixed"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["frequency"]
"equations": ["frequency"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.frequency_beamsimple import setup
@@ -57,6 +59,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=58959#p506565
simple frequency analysis
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -85,7 +88,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -104,9 +107,7 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# material
material_obj = analysis.addObject(
ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial")
)[0]
material_obj = analysis.addObject(ObjectsFem.makeMaterialSolid(doc, "MechanicalMaterial"))[0]
mat = material_obj.Material
mat["Name"] = "Steel-Generic"
mat["YoungsModulus"] = "200000 MPa"
@@ -145,6 +146,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:

View File

@@ -148,6 +148,7 @@ def run_analysis(doc, base_name, filepath="", run_solver=False):
# find the first solver
# thus ATM only one solver per analysis is supported
from femtools.femutils import is_derived_from
for m in doc.Analysis.Group:
if is_derived_from(m, "Fem::FemSolverObjectPython"):
solver = m
@@ -155,17 +156,17 @@ def run_analysis(doc, base_name, filepath="", run_solver=False):
# a file name is needed for the besides dir to work
save_fc_file = join(filepath, (base_name + ".FCStd"))
FreeCAD.Console.PrintMessage(
"Save FreeCAD file for {} analysis to {}\n.".format(base_name, save_fc_file)
)
FreeCAD.Console.PrintMessage(f"Save FreeCAD file for {base_name} analysis to {save_fc_file}\n.")
doc.saveAs(save_fc_file)
# get analysis workig dir
from femtools.femutils import get_beside_dir
working_dir = get_beside_dir(solver)
# run analysis
from femsolver.run import run_fem_solver
if run_solver is True:
run_fem_solver(solver, working_dir)
@@ -176,9 +177,10 @@ def run_analysis(doc, base_name, filepath="", run_solver=False):
def run_example(example, solver=None, base_name=None, run_solver=False):
from importlib import import_module
module = import_module("femexamples." + example)
if not hasattr(module, "setup"):
FreeCAD.Console.PrintError("Setup method not found in {}\n".format(example))
FreeCAD.Console.PrintError(f"Setup method not found in {example}\n")
return None
if solver is None:
@@ -215,7 +217,9 @@ def get_meshname():
def get_header(information):
return """{name}
{information}""".format(name=information["name"], information=print_info_dict(information))
{information}""".format(
name=information["name"], information=print_info_dict(information)
)
def print_info_dict(information):
@@ -224,11 +228,11 @@ def print_info_dict(information):
value_text = ""
if isinstance(v, list):
for j in v:
value_text += "{}, ".format(j)
value_text += f"{j}, "
value_text = value_text.rstrip(", ")
else:
value_text = v
the_text += "{} --> {}\n".format(k, value_text)
the_text += f"{k} --> {value_text}\n"
# print(the_text)
return the_text

View File

@@ -42,12 +42,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "multimaterial",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.material_multiple_bendingbeam_fiveboxes import setup
@@ -58,6 +60,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -124,7 +127,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -179,7 +182,7 @@ def setup(doc=None, solvertype="ccxtools"):
(doc.Box2, "Face6"),
(doc.Box3, "Face6"),
(doc.Box4, "Face6"),
(doc.Box5, "Face6")
(doc.Box5, "Face6"),
]
con_force.Force = "10000.00 N"
con_force.Direction = (doc.Box1, ["Edge1"])
@@ -188,6 +191,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:

View File

@@ -40,12 +40,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "multimaterial",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.material_multiple_bendingbeam_fivefaces import setup
@@ -56,6 +58,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -113,7 +116,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -143,10 +146,7 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(material_obj1)
material_obj2 = ObjectsFem.makeMaterialSolid(doc, "FemMaterial2")
material_obj2.References = [
(doc.Face2, "Face1"),
(doc.Face4, "Face1")
]
material_obj2.References = [(doc.Face2, "Face1"), (doc.Face4, "Face1")]
mat = material_obj2.Material
mat["Name"] = "PLA"
mat["YoungsModulus"] = "3640 MPa"
@@ -165,10 +165,7 @@ def setup(doc=None, solvertype="ccxtools"):
# constraint fixed
con_fixed = ObjectsFem.makeConstraintFixed(doc, "ConstraintFixed")
con_fixed.References = [
(doc.Face1, "Edge1"),
(doc.Face5, "Edge3")
]
con_fixed.References = [(doc.Face1, "Edge1"), (doc.Face5, "Edge3")]
analysis.addObject(con_fixed)
# constraint force
@@ -178,7 +175,7 @@ def setup(doc=None, solvertype="ccxtools"):
(doc.Face2, "Edge4"),
(doc.Face3, "Edge4"),
(doc.Face4, "Edge4"),
(doc.Face5, "Edge4")
(doc.Face5, "Edge4"),
]
con_force.Force = "10000.00 N"
con_force.Direction = (doc.Face1, ["Edge1"])
@@ -187,6 +184,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:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["fixed", "pressure"],
"solvers": ["ccxtools"],
"material": "multimaterial",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.material_multiple_tensionrod_twoboxes import setup
@@ -59,6 +61,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -109,7 +112,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -157,6 +160,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:

View File

@@ -51,12 +51,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "nonlinear",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.material_nl_platewithhole import setup
@@ -80,6 +82,7 @@ TODO nonlinear material: give more information, use values from harry
TODO compare results with example from HarryvL
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -118,7 +121,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -131,8 +134,8 @@ def setup(doc=None, solvertype="ccxtools"):
solver_obj.ThermoMechSteadyState = False
solver_obj.MatrixSolverType = "default"
solver_obj.IterationsControlParameterTimeUse = False
solver_obj.GeometricalNonlinearity = 'nonlinear'
solver_obj.MaterialNonlinearity = 'nonlinear'
solver_obj.GeometricalNonlinearity = "nonlinear"
solver_obj.MaterialNonlinearity = "nonlinear"
analysis.addObject(solver_obj)
# linear material
@@ -147,7 +150,7 @@ def setup(doc=None, solvertype="ccxtools"):
# nonlinear material
name_nlm = "Material_nonlin"
nonlinear_mat = ObjectsFem.makeMaterialMechanicalNonlinear(doc, material_obj, name_nlm)
nonlinear_mat.YieldPoints = ['240.0, 0.0', '270.0, 0.025']
nonlinear_mat.YieldPoints = ["240.0, 0.0", "270.0, 0.025"]
analysis.addObject(nonlinear_mat)
# check solver attributes, Nonlinearity needs to be set to nonlinear
@@ -165,6 +168,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:

View File

@@ -266,129 +266,804 @@ def create_nodes(femmesh):
def create_elements(femmesh):
# elements
femmesh.addVolume([
192, 61, 105, 222, 19, 1, 10, 95, 193, 104, 220, 221, 20, 9, 93, 94, 190, 62, 103, 219
], 1)
femmesh.addVolume([
222, 105, 34, 134, 95, 10, 2, 13, 220, 106, 133, 223, 93, 11, 12, 96, 219, 103, 33, 132
], 2)
femmesh.addVolume([
79, 192, 222, 163, 4, 19, 95, 16, 191, 221, 224, 164, 18, 94, 97, 17, 78, 190, 219, 161
], 3)
femmesh.addVolume([
163, 222, 134, 64, 16, 95, 13, 3, 224, 223,
135, 162, 97, 96, 14, 15, 161, 219, 132, 63
], 4)
femmesh.addVolume([
196, 59, 109, 228, 192, 61, 105, 222, 197,
108, 226, 227, 193, 104, 220, 221, 194, 60, 107, 225
], 5)
femmesh.addVolume([
228, 109, 36, 138, 222, 105, 34, 134, 226,
110, 137, 229, 220, 106, 133, 223, 225, 107, 35, 136
], 6)
femmesh.addVolume([
81, 196, 228, 167, 79, 192, 222, 163, 195, 227,
230, 168, 191, 221, 224, 164, 80, 194, 225, 165
], 7)
femmesh.addVolume([
167, 228, 138, 66, 163, 222, 134, 64, 230, 229,
139, 166, 224, 223, 135, 162, 165, 225, 136, 65
], 8)
femmesh.addVolume([
200, 57, 113, 234, 196, 59, 109, 228, 201, 112,
232, 233, 197, 108, 226, 227, 198, 58, 111, 231
], 9)
femmesh.addVolume([
234, 113, 38, 142, 228, 109, 36, 138, 232, 114,
141, 235, 226, 110, 137, 229, 231, 111, 37, 140
], 10)
femmesh.addVolume([
83, 200, 234, 171, 81, 196, 228, 167, 199, 233,
236, 172, 195, 227, 230, 168, 82, 198, 231, 169
], 11)
femmesh.addVolume([
171, 234, 142, 68, 167, 228, 138, 66, 236, 235,
143, 170, 230, 229, 139, 166, 169, 231, 140, 67
], 12)
femmesh.addVolume([
204, 55, 117, 240, 200, 57, 113, 234, 205, 116,
238, 239, 201, 112, 232, 233, 202, 56, 115, 237
], 13)
femmesh.addVolume([
240, 117, 40, 146, 234, 113, 38, 142, 238, 118,
145, 241, 232, 114, 141, 235, 237, 115, 39, 144
], 14)
femmesh.addVolume([
85, 204, 240, 175, 83, 200, 234, 171, 203, 239,
242, 176, 199, 233, 236, 172, 84, 202, 237, 173
], 15)
femmesh.addVolume([
175, 240, 146, 70, 171, 234, 142, 68, 242, 241,
147, 174, 236, 235, 143, 170, 173, 237, 144, 69
], 16)
femmesh.addVolume([
208, 53, 121, 246, 204, 55, 117, 240, 209, 120,
244, 245, 205, 116, 238, 239, 206, 54, 119, 243
], 17)
femmesh.addVolume([
246, 121, 42, 150, 240, 117, 40, 146, 244, 122,
149, 247, 238, 118, 145, 241, 243, 119, 41, 148
], 18)
femmesh.addVolume([
87, 208, 246, 179, 85, 204, 240, 175, 207, 245,
248, 180, 203, 239, 242, 176, 86, 206, 243, 177
], 19)
femmesh.addVolume([
179, 246, 150, 72, 175, 240, 146, 70, 248, 247,
151, 178, 242, 241, 147, 174, 177, 243, 148, 71
], 20)
femmesh.addVolume([
212, 51, 125, 252, 208, 53, 121, 246, 213, 124,
250, 251, 209, 120, 244, 245, 210, 52, 123, 249
], 21)
femmesh.addVolume([
252, 125, 44, 154, 246, 121, 42, 150, 250, 126,
153, 253, 244, 122, 149, 247, 249, 123, 43, 152
], 22)
femmesh.addVolume([
89, 212, 252, 183, 87, 208, 246, 179, 211, 251,
254, 184, 207, 245, 248, 180, 88, 210, 249, 181
], 23)
femmesh.addVolume([
183, 252, 154, 74, 179, 246, 150, 72, 254, 253,
155, 182, 248, 247, 151, 178, 181, 249, 152, 73
], 24)
femmesh.addVolume([
216, 49, 129, 258, 212, 51, 125, 252, 217, 128,
256, 257, 213, 124, 250, 251, 214, 50, 127, 255
], 25)
femmesh.addVolume([
258, 129, 46, 158, 252, 125, 44, 154, 256, 130,
157, 259, 250, 126, 153, 253, 255, 127, 45, 156
], 26)
femmesh.addVolume([
91, 216, 258, 187, 89, 212, 252, 183, 215, 257,
260, 188, 211, 251, 254, 184, 90, 214, 255, 185
], 27)
femmesh.addVolume([
187, 258, 158, 76, 183, 252, 154, 74, 260, 259,
159, 186, 254, 253, 155, 182, 185, 255, 156, 75
], 28)
femmesh.addVolume([
31, 5, 22, 100, 216, 49, 129, 258, 32, 21,
98, 99, 217, 128, 256, 257, 218, 48, 131, 261
], 29)
femmesh.addVolume([
100, 22, 6, 25, 258, 129, 46, 158, 98, 23,
24, 101, 256, 130, 157, 259, 261, 131, 47, 160
], 30)
femmesh.addVolume([
8, 31, 100, 28, 91, 216, 258, 187, 30, 99,
102, 29, 215, 257, 260, 188, 92, 218, 261, 189
], 31)
femmesh.addVolume([
28, 100, 25, 7, 187, 258, 158, 76, 102, 101,
26, 27, 260, 259, 159, 186, 189, 261, 160, 77
], 32)
femmesh.addVolume(
[
192,
61,
105,
222,
19,
1,
10,
95,
193,
104,
220,
221,
20,
9,
93,
94,
190,
62,
103,
219,
],
1,
)
femmesh.addVolume(
[
222,
105,
34,
134,
95,
10,
2,
13,
220,
106,
133,
223,
93,
11,
12,
96,
219,
103,
33,
132,
],
2,
)
femmesh.addVolume(
[
79,
192,
222,
163,
4,
19,
95,
16,
191,
221,
224,
164,
18,
94,
97,
17,
78,
190,
219,
161,
],
3,
)
femmesh.addVolume(
[
163,
222,
134,
64,
16,
95,
13,
3,
224,
223,
135,
162,
97,
96,
14,
15,
161,
219,
132,
63,
],
4,
)
femmesh.addVolume(
[
196,
59,
109,
228,
192,
61,
105,
222,
197,
108,
226,
227,
193,
104,
220,
221,
194,
60,
107,
225,
],
5,
)
femmesh.addVolume(
[
228,
109,
36,
138,
222,
105,
34,
134,
226,
110,
137,
229,
220,
106,
133,
223,
225,
107,
35,
136,
],
6,
)
femmesh.addVolume(
[
81,
196,
228,
167,
79,
192,
222,
163,
195,
227,
230,
168,
191,
221,
224,
164,
80,
194,
225,
165,
],
7,
)
femmesh.addVolume(
[
167,
228,
138,
66,
163,
222,
134,
64,
230,
229,
139,
166,
224,
223,
135,
162,
165,
225,
136,
65,
],
8,
)
femmesh.addVolume(
[
200,
57,
113,
234,
196,
59,
109,
228,
201,
112,
232,
233,
197,
108,
226,
227,
198,
58,
111,
231,
],
9,
)
femmesh.addVolume(
[
234,
113,
38,
142,
228,
109,
36,
138,
232,
114,
141,
235,
226,
110,
137,
229,
231,
111,
37,
140,
],
10,
)
femmesh.addVolume(
[
83,
200,
234,
171,
81,
196,
228,
167,
199,
233,
236,
172,
195,
227,
230,
168,
82,
198,
231,
169,
],
11,
)
femmesh.addVolume(
[
171,
234,
142,
68,
167,
228,
138,
66,
236,
235,
143,
170,
230,
229,
139,
166,
169,
231,
140,
67,
],
12,
)
femmesh.addVolume(
[
204,
55,
117,
240,
200,
57,
113,
234,
205,
116,
238,
239,
201,
112,
232,
233,
202,
56,
115,
237,
],
13,
)
femmesh.addVolume(
[
240,
117,
40,
146,
234,
113,
38,
142,
238,
118,
145,
241,
232,
114,
141,
235,
237,
115,
39,
144,
],
14,
)
femmesh.addVolume(
[
85,
204,
240,
175,
83,
200,
234,
171,
203,
239,
242,
176,
199,
233,
236,
172,
84,
202,
237,
173,
],
15,
)
femmesh.addVolume(
[
175,
240,
146,
70,
171,
234,
142,
68,
242,
241,
147,
174,
236,
235,
143,
170,
173,
237,
144,
69,
],
16,
)
femmesh.addVolume(
[
208,
53,
121,
246,
204,
55,
117,
240,
209,
120,
244,
245,
205,
116,
238,
239,
206,
54,
119,
243,
],
17,
)
femmesh.addVolume(
[
246,
121,
42,
150,
240,
117,
40,
146,
244,
122,
149,
247,
238,
118,
145,
241,
243,
119,
41,
148,
],
18,
)
femmesh.addVolume(
[
87,
208,
246,
179,
85,
204,
240,
175,
207,
245,
248,
180,
203,
239,
242,
176,
86,
206,
243,
177,
],
19,
)
femmesh.addVolume(
[
179,
246,
150,
72,
175,
240,
146,
70,
248,
247,
151,
178,
242,
241,
147,
174,
177,
243,
148,
71,
],
20,
)
femmesh.addVolume(
[
212,
51,
125,
252,
208,
53,
121,
246,
213,
124,
250,
251,
209,
120,
244,
245,
210,
52,
123,
249,
],
21,
)
femmesh.addVolume(
[
252,
125,
44,
154,
246,
121,
42,
150,
250,
126,
153,
253,
244,
122,
149,
247,
249,
123,
43,
152,
],
22,
)
femmesh.addVolume(
[
89,
212,
252,
183,
87,
208,
246,
179,
211,
251,
254,
184,
207,
245,
248,
180,
88,
210,
249,
181,
],
23,
)
femmesh.addVolume(
[
183,
252,
154,
74,
179,
246,
150,
72,
254,
253,
155,
182,
248,
247,
151,
178,
181,
249,
152,
73,
],
24,
)
femmesh.addVolume(
[
216,
49,
129,
258,
212,
51,
125,
252,
217,
128,
256,
257,
213,
124,
250,
251,
214,
50,
127,
255,
],
25,
)
femmesh.addVolume(
[
258,
129,
46,
158,
252,
125,
44,
154,
256,
130,
157,
259,
250,
126,
153,
253,
255,
127,
45,
156,
],
26,
)
femmesh.addVolume(
[
91,
216,
258,
187,
89,
212,
252,
183,
215,
257,
260,
188,
211,
251,
254,
184,
90,
214,
255,
185,
],
27,
)
femmesh.addVolume(
[
187,
258,
158,
76,
183,
252,
154,
74,
260,
259,
159,
186,
254,
253,
155,
182,
185,
255,
156,
75,
],
28,
)
femmesh.addVolume(
[
31,
5,
22,
100,
216,
49,
129,
258,
32,
21,
98,
99,
217,
128,
256,
257,
218,
48,
131,
261,
],
29,
)
femmesh.addVolume(
[
100,
22,
6,
25,
258,
129,
46,
158,
98,
23,
24,
101,
256,
130,
157,
259,
261,
131,
47,
160,
],
30,
)
femmesh.addVolume(
[
8,
31,
100,
28,
91,
216,
258,
187,
30,
99,
102,
29,
215,
257,
260,
188,
92,
218,
261,
189,
],
31,
)
femmesh.addVolume(
[
28,
100,
25,
7,
187,
258,
158,
76,
102,
101,
26,
27,
260,
259,
159,
186,
189,
261,
160,
77,
],
32,
)
return True

View File

@@ -41,12 +41,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools", "elmer", "mystran"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.buckling_platebuckling import setup
@@ -64,6 +66,7 @@ one each mesh node on one edge 100 N tension force
Does not work on Z88 because Z88 does not support quad4 elements
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -95,7 +98,7 @@ def setup(doc=None, solvertype="ccxtools"):
doc.recompute()
# all geom boolean fragment
geom_obj = SplitFeatures.makeBooleanFragments(name='ThePointPlate')
geom_obj = SplitFeatures.makeBooleanFragments(name="ThePointPlate")
geom_obj.Objects = [plate, force_pt1, force_pt2, force_pt3, force_pt4]
doc.recompute()
if FreeCAD.GuiUp:
@@ -117,7 +120,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = ObjectsFem.makeSolverElmer(doc, "SolverElmer")
ObjectsFem.makeEquationElasticity(doc, solver_obj)
@@ -141,7 +144,7 @@ def setup(doc=None, solvertype="ccxtools"):
analysis.addObject(solver_obj)
# shell thickness
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 0.3, 'Thickness')
thickness_obj = ObjectsFem.makeElementGeometry2D(doc, 0.3, "Thickness")
analysis.addObject(thickness_obj)
# material
@@ -175,6 +178,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:

View File

@@ -44,12 +44,14 @@ def get_information():
"constraints": ["fixed", "force", "displacement"],
"solvers": ["ccxtools"],
"material": "reinforced",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.rc_wall_2d import setup
@@ -62,6 +64,7 @@ https://forum.freecad.org/viewtopic.php?f=18&t=33106&start=80#p296469
example from Harry's epic topic: Concrete branch ready for testing
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -104,7 +107,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -163,6 +166,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:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["force", "fixed"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.square_pipe_end_twisted_edgeforces import setup
@@ -59,6 +61,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -93,7 +96,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -127,7 +130,8 @@ def setup(doc=None, solvertype="ccxtools"):
(doc.SquareTube, "Edge4"),
(doc.SquareTube, "Edge7"),
(doc.SquareTube, "Edge10"),
(doc.SquareTube, "Edge12")]
(doc.SquareTube, "Edge12"),
]
analysis.addObject(con_fixed)
# con_force1
@@ -164,6 +168,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:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["force", "fixed"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.square_pipe_end_twisted_nodeforces import setup
@@ -59,6 +61,7 @@ See forum topic post:
...
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -203,7 +206,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
else:
FreeCAD.Console.PrintWarning(
"Unknown or unsupported solver type: {}. "
@@ -281,7 +284,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geofixes_obj, "Vertex45"),
(geofixes_obj, "Vertex27"),
(geofixes_obj, "Vertex2"),
(geofixes_obj, "Vertex25")]
(geofixes_obj, "Vertex25"),
]
analysis.addObject(con_fixed)
# con_force1
@@ -307,7 +311,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex21"),
(geoforces_obj, "Vertex22"),
(geoforces_obj, "Vertex23"),
(geoforces_obj, "Vertex24"), ]
(geoforces_obj, "Vertex24"),
]
con_force3.Force = "27777.78 N"
con_force3.Direction = (geom_obj, ["Edge9"])
con_force3.Reversed = False
@@ -320,7 +325,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex10"),
(geoforces_obj, "Vertex11"),
(geoforces_obj, "Vertex12"),
(geoforces_obj, "Vertex13"), ]
(geoforces_obj, "Vertex13"),
]
con_force4.Force = "27777.78 N"
con_force4.Direction = (geom_obj, ["Edge3"])
con_force4.Reversed = False
@@ -334,7 +340,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex45"),
(geoforces_obj, "Vertex46"),
(geoforces_obj, "Vertex47"),
(geoforces_obj, "Vertex48"), ]
(geoforces_obj, "Vertex48"),
]
con_force5.Force = "66666.67 N"
con_force5.Direction = (geom_obj, ["Edge9"])
con_force5.Reversed = False
@@ -348,7 +355,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex33"),
(geoforces_obj, "Vertex34"),
(geoforces_obj, "Vertex35"),
(geoforces_obj, "Vertex36"), ]
(geoforces_obj, "Vertex36"),
]
con_force6.Force = "66666.67 N"
con_force6.Direction = (geom_obj, ["Edge3"])
con_force6.Reversed = False
@@ -377,7 +385,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex4"),
(geoforces_obj, "Vertex5"),
(geoforces_obj, "Vertex6"),
(geoforces_obj, "Vertex7"), ]
(geoforces_obj, "Vertex7"),
]
con_force9.Force = "27777.78 N"
con_force9.Direction = (geom_obj, ["Edge11"])
con_force9.Reversed = False
@@ -390,7 +399,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex16"),
(geoforces_obj, "Vertex17"),
(geoforces_obj, "Vertex18"),
(geoforces_obj, "Vertex19"), ]
(geoforces_obj, "Vertex19"),
]
con_force10.Force = "27777.78 N"
con_force10.Direction = (geom_obj, ["Edge6"])
con_force10.Reversed = False
@@ -404,7 +414,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex27"),
(geoforces_obj, "Vertex28"),
(geoforces_obj, "Vertex29"),
(geoforces_obj, "Vertex30"), ]
(geoforces_obj, "Vertex30"),
]
con_force11.Force = "66666.67 N"
con_force11.Direction = (geom_obj, ["Edge11"])
con_force11.Reversed = False
@@ -418,7 +429,8 @@ def setup(doc=None, solvertype="ccxtools"):
(geoforces_obj, "Vertex39"),
(geoforces_obj, "Vertex40"),
(geoforces_obj, "Vertex41"),
(geoforces_obj, "Vertex42"), ]
(geoforces_obj, "Vertex42"),
]
con_force12.Force = "66666.67 N"
con_force12.Direction = (geom_obj, ["Edge6"])
con_force12.Reversed = False
@@ -426,6 +438,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:

View File

@@ -51,12 +51,14 @@ def get_information():
"constraints": ["fixed", "initial temperature", "temperature"],
"solvers": ["ccxtools", "elmer"],
"material": "multimaterial",
"equations": ["thermomechanical"]
"equations": ["thermomechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
To run the example from Python console use:
from femexamples.thermomech_bimetall import setup
@@ -73,6 +75,7 @@ this file has 7.15 mm max deflection
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -105,7 +108,7 @@ def setup(doc=None, solvertype="ccxtools"):
doc.recompute()
# all geom boolean fragment
geom_obj = SplitFeatures.makeBooleanFragments(name='BooleanFragments')
geom_obj = SplitFeatures.makeBooleanFragments(name="BooleanFragments")
geom_obj.Objects = [bottom_box_obj, top_box_obj]
if FreeCAD.GuiUp:
bottom_box_obj.ViewObject.hide()
@@ -122,7 +125,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "elmer":
solver_obj = analysis.addObject(ObjectsFem.makeSolverElmer(doc, "SolverElmer"))[0]
solver_obj.SteadyStateMinIterations = 1
@@ -189,25 +192,20 @@ def setup(doc=None, solvertype="ccxtools"):
# constraint temperature
con_temp = ObjectsFem.makeConstraintTemperature(doc, "ConstraintTemperatureHot")
con_temp.References = [
(geom_obj, "Face5"),
(geom_obj, "Face11")
]
con_temp.References = [(geom_obj, "Face5"), (geom_obj, "Face11")]
con_temp.Temperature = 373.0
con_temp.CFlux = 0.0
analysis.addObject(con_temp)
con_temp = ObjectsFem.makeConstraintTemperature(doc, "ConstraintTemperatureNormal")
con_temp.References = [
(geom_obj, "Face1"),
(geom_obj, "Face7")
]
con_temp.References = [(geom_obj, "Face1"), (geom_obj, "Face7")]
con_temp.Temperature = 273.0
con_temp.CFlux = 0.0
analysis.addObject(con_temp)
# mesh
from .meshes.mesh_thermomech_bimetall_tetra10 import create_nodes, create_elements
fem_mesh = Fem.FemMesh()
control = create_nodes(fem_mesh)
if not control:

View File

@@ -38,7 +38,7 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["z88"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
@@ -58,6 +58,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:

View File

@@ -43,12 +43,14 @@ def get_information():
"constraints": ["fixed", "force"],
"solvers": ["ccxtools"],
"material": "solid",
"equations": ["mechanical"]
"equations": ["mechanical"],
}
def get_explanation(header=""):
return header + """
return (
header
+ """
# To run the example from Python console use,
# (works even after an edit without restart of FreeCAD):
@@ -69,6 +71,7 @@ Z88 official example 2, crane beam
- max deflection Mystran : x.xx mm
- max deflection Z88 : 8.19 mm # one seg2 truss element foreach bar
"""
)
def setup(doc=None, solvertype="ccxtools"):
@@ -401,7 +404,7 @@ def setup(doc=None, solvertype="ccxtools"):
# solver
if solvertype == "ccxtools":
solver_obj = ObjectsFem.makeSolverCalculiXCcxTools(doc, "CalculiXCcxTools")
solver_obj.WorkingDir = u""
solver_obj.WorkingDir = ""
elif solvertype == "z88":
solver_obj = ObjectsFem.makeSolverZ88(doc, "SolverZ88")
else:
@@ -420,10 +423,7 @@ def setup(doc=None, solvertype="ccxtools"):
# beam section
beamsection_obj = ObjectsFem.makeElementGeometry1D(
doc,
sectiontype="Circular",
height=25.0,
name="CrossSectionCircular"
doc, sectiontype="Circular", height=25.0, name="CrossSectionCircular"
)
analysis.addObject(beamsection_obj)
@@ -451,6 +451,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:

View File

@@ -31,7 +31,7 @@ __author__ = "Bernd Hahnebach"
__url__ = "https://www.freecad.org"
class FemMigrateGui(object):
class FemMigrateGui:
def find_module(self, fullname, path):
@@ -168,220 +168,308 @@ class FemMigrateGui(object):
module.__path__ = "femguiobjects"
if module.__name__ == "femguiobjects._ViewProviderFemConstraintBodyHeatSource":
import femviewprovider.view_constraint_bodyheatsource
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_bodyheatsource.VPConstraintBodyHeatSource
)
if module.__name__ == "femguiobjects._ViewProviderFemConstraintElectrostaticPotential":
import femviewprovider.view_constraint_electrostaticpotential
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_electrostaticpotential.VPConstraintElectroStaticPotential
)
if module.__name__ == "femguiobjects._ViewProviderFemConstraintFlowVelocity":
import femviewprovider.view_constraint_flowvelocity
module.ViewProxy = \
femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity
module.ViewProxy = femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity
if module.__name__ == "femguiobjects._ViewProviderFemConstraintInitialFlowVelocity":
import femviewprovider.view_constraint_initialflowvelocity
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_initialflowvelocity.VPConstraintInitialFlowVelocity
)
if module.__name__ == "femguiobjects._ViewProviderFemConstraintSelfWeight":
import femviewprovider.view_constraint_selfweight
module._ViewProviderFemConstraintSelfWeight = \
module._ViewProviderFemConstraintSelfWeight = (
femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight
)
if module.__name__ == "femguiobjects._ViewProviderFemConstraintTie":
import femviewprovider.view_constraint_tie
module._ViewProviderFemConstraintTie = \
module._ViewProviderFemConstraintTie = (
femviewprovider.view_constraint_tie.VPConstraintTie
)
if module.__name__ == "femguiobjects._ViewProviderFemElementFluid1D":
import femviewprovider.view_element_fluid1D
module._ViewProviderFemElementFluid1D = \
module._ViewProviderFemElementFluid1D = (
femviewprovider.view_element_fluid1D.VPElementFluid1D
)
if module.__name__ == "femguiobjects._ViewProviderFemElementGeometry1D":
import femviewprovider.view_element_geometry1D
module._ViewProviderFemElementGeometry1D = \
module._ViewProviderFemElementGeometry1D = (
femviewprovider.view_element_geometry1D.VPElementGeometry1D
)
if module.__name__ == "femguiobjects._ViewProviderFemElementGeometry2D":
import femviewprovider.view_element_geometry2D
module._ViewProviderFemElementGeometry2D = \
module._ViewProviderFemElementGeometry2D = (
femviewprovider.view_element_geometry2D.VPElementGeometry2D
)
if module.__name__ == "femguiobjects._ViewProviderFemElementRotation1D":
import femviewprovider.view_element_rotation1D
module._ViewProviderFemElementRotation1D = \
module._ViewProviderFemElementRotation1D = (
femviewprovider.view_element_rotation1D.VPElementRotation1D
)
if module.__name__ == "femguiobjects._ViewProviderFemMaterial":
import femviewprovider.view_material_common
module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon
if module.__name__ == "femguiobjects._ViewProviderFemMaterialMechanicalNonlinear":
import femviewprovider.view_material_mechanicalnonlinear
module._ViewProviderFemMaterialMechanicalNonlinear = \
module._ViewProviderFemMaterialMechanicalNonlinear = (
femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear
)
if module.__name__ == "femguiobjects._ViewProviderFemMaterialReinforced":
import femviewprovider.view_material_reinforced
module._ViewProviderFemMaterialReinforced = \
module._ViewProviderFemMaterialReinforced = (
femviewprovider.view_material_reinforced.VPMaterialReinforced
)
if module.__name__ == "femguiobjects._ViewProviderFemMeshBoundaryLayer":
import femviewprovider.view_mesh_boundarylayer
module._ViewProviderFemMeshBoundaryLayer = \
module._ViewProviderFemMeshBoundaryLayer = (
femviewprovider.view_mesh_boundarylayer.VPMeshBoundaryLayer
)
if module.__name__ == "femguiobjects._ViewProviderFemMeshGmsh":
import femviewprovider.view_mesh_gmsh
module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh
if module.__name__ == "femguiobjects._ViewProviderFemMeshGroup":
import femviewprovider.view_mesh_group
module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup
if module.__name__ == "femguiobjects._ViewProviderFemMeshRegion":
import femviewprovider.view_mesh_region
module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion
if module.__name__ == "femguiobjects._ViewProviderFemMeshResult":
import femviewprovider.view_mesh_result
module._ViewProviderFemMeshResult = femviewprovider.view_mesh_result.VPFemMeshResult
if module.__name__ == "femguiobjects._ViewProviderFemResultMechanical":
import femviewprovider.view_result_mechanical
module._ViewProviderFemResultMechanical = \
module._ViewProviderFemResultMechanical = (
femviewprovider.view_result_mechanical.VPResultMechanical
)
if module.__name__ == "femguiobjects._ViewProviderFemSolverCalculix":
import femviewprovider.view_solver_ccxtools
module._ViewProviderFemSolverCalculix = \
module._ViewProviderFemSolverCalculix = (
femviewprovider.view_solver_ccxtools.VPSolverCcxTools
)
if module.__name__ == "PyGui":
module.__path__ = "PyGui"
if module.__name__ == "PyGui._ViewProviderFemConstraintBodyHeatSource":
import femviewprovider.view_constraint_bodyheatsource
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_bodyheatsource.VPConstraintBodyHeatSource
)
if module.__name__ == "PyGui._ViewProviderFemConstraintElectrostaticPotential":
import femviewprovider.view_constraint_electrostaticpotential
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_electrostaticpotential.VPConstraintElectroStaticPotential
)
if module.__name__ == "PyGui._ViewProviderFemConstraintFlowVelocity":
import femviewprovider.view_constraint_flowvelocity
module.ViewProxy = \
femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity
module.ViewProxy = femviewprovider.view_constraint_flowvelocity.VPConstraintFlowVelocity
if module.__name__ == "PyGui._ViewProviderFemConstraintInitialFlowVelocity":
import femviewprovider.view_constraint_initialflowvelocity
module.ViewProxy = \
module.ViewProxy = (
femviewprovider.view_constraint_initialflowvelocity.VPConstraintInitialFlowVelocity
)
if module.__name__ == "PyGui._ViewProviderFemConstraintSelfWeight":
import femviewprovider.view_constraint_selfweight
module._ViewProviderFemConstraintSelfWeight = \
module._ViewProviderFemConstraintSelfWeight = (
femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight
)
if module.__name__ == "PyGui._ViewProviderFemElementFluid1D":
import femviewprovider.view_element_fluid1D
module._ViewProviderFemElementFluid1D = \
module._ViewProviderFemElementFluid1D = (
femviewprovider.view_element_fluid1D.VPElementFluid1D
)
if module.__name__ == "PyGui._ViewProviderFemElementGeometry1D":
import femviewprovider.view_element_geometry1D
module._ViewProviderFemElementGeometry1D = \
module._ViewProviderFemElementGeometry1D = (
femviewprovider.view_element_geometry1D.VPElementGeometry1D
)
if module.__name__ == "PyGui._ViewProviderFemElementGeometry2D":
import femviewprovider.view_element_geometry2D
module._ViewProviderFemElementGeometry2D = \
module._ViewProviderFemElementGeometry2D = (
femviewprovider.view_element_geometry2D.VPElementGeometry2D
)
if module.__name__ == "PyGui._ViewProviderFemElementRotation1D":
import femviewprovider.view_element_rotation1D
module._ViewProviderFemElementRotation1D = \
module._ViewProviderFemElementRotation1D = (
femviewprovider.view_element_rotation1D.VPElementRotation1D
)
if module.__name__ == "PyGui._ViewProviderFemMaterial":
import femviewprovider.view_material_common
module._ViewProviderFemMaterial = \
femviewprovider.view_material_common.VPMaterialCommon
module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon
if module.__name__ == "PyGui._ViewProviderFemMaterialMechanicalNonlinear":
import femviewprovider.view_material_mechanicalnonlinear
module._ViewProviderFemMaterialMechanicalNonlinear = \
module._ViewProviderFemMaterialMechanicalNonlinear = (
femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear
)
if module.__name__ == "PyGui._ViewProviderFemMeshBoundaryLayer":
import femviewprovider.view_mesh_boundarylayer
module._ViewProviderFemMeshBoundaryLayer = \
module._ViewProviderFemMeshBoundaryLayer = (
femviewprovider.view_mesh_boundarylayer.VPMeshBoundaryLayer
)
if module.__name__ == "PyGui._ViewProviderFemMeshGmsh":
import femviewprovider.view_mesh_gmsh
module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh
if module.__name__ == "PyGui._ViewProviderFemMeshGroup":
import femviewprovider.view_mesh_group
module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup
if module.__name__ == "PyGui._ViewProviderFemMeshRegion":
import femviewprovider.view_mesh_region
module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion
if module.__name__ == "PyGui._ViewProviderFemMeshResult":
import femviewprovider.view_mesh_result
module._ViewProviderFemMeshResult = femviewprovider.view_mesh_result.VPFemMeshResult
if module.__name__ == "PyGui._ViewProviderFemResultMechanical":
import femviewprovider.view_result_mechanical
module._ViewProviderFemResultMechanical = \
module._ViewProviderFemResultMechanical = (
femviewprovider.view_result_mechanical.VPResultMechanical
)
if module.__name__ == "PyGui._ViewProviderFemSolverCalculix":
import femviewprovider.view_solver_ccxtools
module._ViewProviderFemSolverCalculix = \
module._ViewProviderFemSolverCalculix = (
femviewprovider.view_solver_ccxtools.VPSolverCcxTools
)
if module.__name__ == "PyGui._ViewProviderFemSolverZ88":
import femsolver.z88.solver
module._ViewProviderFemSolverZ88 = femsolver.z88.solver.ViewProxy
if module.__name__ == "PyGui._ViewProviderFemBeamSection":
import femviewprovider.view_element_geometry1D
module._ViewProviderFemBeamSection = \
module._ViewProviderFemBeamSection = (
femviewprovider.view_element_geometry1D.VPElementGeometry1D
)
if module.__name__ == "PyGui._ViewProviderFemFluidSection":
import femviewprovider.view_element_fluid1D
module._ViewProviderFemFluidSection = \
module._ViewProviderFemFluidSection = (
femviewprovider.view_element_fluid1D.VPElementFluid1D
)
if module.__name__ == "PyGui._ViewProviderFemShellThickness":
import femviewprovider.view_element_geometry2D
module._ViewProviderFemShellThickness = \
module._ViewProviderFemShellThickness = (
femviewprovider.view_element_geometry2D.VPElementGeometry2D
)
if module.__name__ == "_ViewProviderFemBeamSection":
import femviewprovider.view_element_geometry1D
module._ViewProviderFemBeamSection = \
module._ViewProviderFemBeamSection = (
femviewprovider.view_element_geometry1D.VPElementGeometry1D
)
if module.__name__ == "_ViewProviderFemConstraintSelfWeight":
import femviewprovider.view_constraint_selfweight
module._ViewProviderFemConstraintSelfWeight = \
module._ViewProviderFemConstraintSelfWeight = (
femviewprovider.view_constraint_selfweight.VPConstraintSelfWeight
)
if module.__name__ == "_ViewProviderFemMaterial":
import femviewprovider.view_material_common
module._ViewProviderFemMaterial = \
femviewprovider.view_material_common.VPMaterialCommon
module._ViewProviderFemMaterial = femviewprovider.view_material_common.VPMaterialCommon
if module.__name__ == "_ViewProviderFemMaterialMechanicalNonlinear":
import femviewprovider.view_material_mechanicalnonlinear
module._ViewProviderFemMaterialMechanicalNonlinear = \
module._ViewProviderFemMaterialMechanicalNonlinear = (
femviewprovider.view_material_mechanicalnonlinear.VPMaterialMechanicalNonlinear
)
if module.__name__ == "_ViewProviderFemMeshGmsh":
import femviewprovider.view_mesh_gmsh
module._ViewProviderFemMeshGmsh = femviewprovider.view_mesh_gmsh.VPMeshGmsh
if module.__name__ == "_ViewProviderFemMeshGroup":
import femviewprovider.view_mesh_group
module._ViewProviderFemMeshGroup = femviewprovider.view_mesh_group.VPMeshGroup
if module.__name__ == "_ViewProviderFemMeshRegion":
import femviewprovider.view_mesh_region
module._ViewProviderFemMeshRegion = femviewprovider.view_mesh_region.VPMeshRegion
if module.__name__ == "_ViewProviderFemResultMechanical":
import femviewprovider.view_result_mechanical
module._ViewProviderFemResultMechanical = \
module._ViewProviderFemResultMechanical = (
femviewprovider.view_result_mechanical.VPResultMechanical
)
if module.__name__ == "_ViewProviderFemShellThickness":
import femviewprovider.view_element_geometry2D
module._ViewProviderFemShellThickness = \
module._ViewProviderFemShellThickness = (
femviewprovider.view_element_geometry2D.VPElementGeometry2D
)
if module.__name__ == "_ViewProviderFemSolverCalculix":
import femviewprovider.view_solver_ccxtools
module._ViewProviderFemSolverCalculix = \
module._ViewProviderFemSolverCalculix = (
femviewprovider.view_solver_ccxtools.VPSolverCcxTools
)
if module.__name__ == "_ViewProviderFemSolverZ88":
import femsolver.z88.solver
module._ViewProviderFemSolverZ88 = femsolver.z88.solver.ViewProxy
if module.__name__ == "_ViewProviderFemMechanicalResult":
import femviewprovider.view_result_mechanical
module._ViewProviderFemMechanicalResult = \
module._ViewProviderFemMechanicalResult = (
femviewprovider.view_result_mechanical.VPResultMechanical
)
if module.__name__ == "ViewProviderFemResult":
import femviewprovider.view_result_mechanical
module.ViewProviderFemResult = \
femviewprovider.view_result_mechanical.VPResultMechanical
module.ViewProviderFemResult = femviewprovider.view_result_mechanical.VPResultMechanical
if module.__name__ == "_ViewProviderMechanicalMaterial":
import femviewprovider.view_material_common
module._ViewProviderMechanicalMaterial = \
module._ViewProviderMechanicalMaterial = (
femviewprovider.view_material_common.VPMaterialCommon
)
return None

View File

@@ -43,7 +43,7 @@ from femtools import geomtools
class _Selector(QtGui.QWidget):
def __init__(self):
super(_Selector, self).__init__()
super().__init__()
self._references = []
self._register = dict()
@@ -92,7 +92,7 @@ class _Selector(QtGui.QWidget):
obj, sub = self._register[identifier]
refIndex = self._getIndex(obj)
entry = self._references[refIndex]
newSub = tuple((x for x in entry[1] if x != sub))
newSub = tuple(x for x in entry[1] if x != sub)
self._references[refIndex] = (obj, newSub)
self._model.removeRow(index.row())
@@ -107,7 +107,7 @@ class _Selector(QtGui.QWidget):
self._references[index] = newEntry
def _addToWidget(self, obj, sub):
identifier = "%s::%s" % (obj.Name, sub)
identifier = f"{obj.Name}::{sub}"
item = QtGui.QStandardItem(identifier)
self._model.appendRow(item)
self._register[identifier] = (obj, sub)
@@ -126,12 +126,9 @@ class _Selector(QtGui.QWidget):
class BoundarySelector(_Selector):
def __init__(self):
super(BoundarySelector, self).__init__()
super().__init__()
self.setWindowTitle(self.tr("Select Faces/Edges/Vertexes"))
self.setHelpText(self.tr(
"To add references: select them in the 3D view "
' and click "Add".'
))
self.setHelpText(self.tr('To add references: select them in the 3D view and click "Add".'))
def getSelection(self):
selection = []
@@ -145,12 +142,14 @@ class BoundarySelector(_Selector):
class SolidSelector(_Selector):
def __init__(self):
super(SolidSelector, self).__init__()
super().__init__()
self.setWindowTitle(self.tr("Select Solids"))
self.setHelpText(self.tr(
"Select elements part of the solid that shall be added"
' to the list. To add the solid click "Add".'
))
self.setHelpText(
self.tr(
"Select elements part of the solid that shall be added"
' to the list. To add the solid click "Add".'
)
)
def getSelection(self):
selection = []
@@ -172,9 +171,7 @@ class SolidSelector(_Selector):
def _getObjects(self, obj, names):
objects = []
if not hasattr(obj, "Shape"):
FreeCAD.Console.PrintMessage(
"Selected object has no Shape.\n"
)
FreeCAD.Console.PrintMessage("Selected object has no Shape.\n")
return objects
shape = obj.Shape
for n in names:
@@ -227,7 +224,7 @@ class SmallListView(QtGui.QListView):
class GeometryElementsSelection(QtGui.QWidget):
def __init__(self, ref, eltypes, multigeom, showHintEmptyList):
super(GeometryElementsSelection, self).__init__()
super().__init__()
# init ui stuff
FreeCADGui.Selection.clearSelection()
self.sel_server = None
@@ -264,9 +261,9 @@ class GeometryElementsSelection(QtGui.QWidget):
def initUI(self):
# ArchPanel is coded without ui-file too
# title
self.setWindowTitle(self.tr(
"Geometry reference selector for a {}"
).format(self.sel_elem_text))
self.setWindowTitle(
self.tr("Geometry reference selector for a {}").format(self.sel_elem_text)
)
# button
self.pushButton_Add = QtGui.QPushButton(self.tr("Add"))
# label
@@ -280,13 +277,9 @@ class GeometryElementsSelection(QtGui.QWidget):
"{}If no geometry is added to the list, all remaining ones are used."
).format("<br>")
if self.showHintEmptyList is True:
self._helpTextLbl.setText(
helpTextPart1 + helpTextEmpty
)
self._helpTextLbl.setText(helpTextPart1 + helpTextEmpty)
else:
self._helpTextLbl.setText(
helpTextPart1
)
self._helpTextLbl.setText(helpTextPart1)
# list
self.list_References = QtGui.QListWidget()
# radiobutton down the list
@@ -324,22 +317,14 @@ class GeometryElementsSelection(QtGui.QWidget):
self.list_References.connect(
self.list_References,
QtCore.SIGNAL("customContextMenuRequested(QPoint)"),
self.references_list_right_clicked
self.references_list_right_clicked,
)
QtCore.QObject.connect(self.pushButton_Add, QtCore.SIGNAL("clicked()"), self.add_references)
QtCore.QObject.connect(
self.rb_standard, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_standard
)
QtCore.QObject.connect(
self.pushButton_Add,
QtCore.SIGNAL("clicked()"),
self.add_references
)
QtCore.QObject.connect(
self.rb_standard,
QtCore.SIGNAL("toggled(bool)"),
self.choose_selection_mode_standard
)
QtCore.QObject.connect(
self.rb_solid,
QtCore.SIGNAL("toggled(bool)"),
self.choose_selection_mode_solid
self.rb_solid, QtCore.SIGNAL("toggled(bool)"), self.choose_selection_mode_solid
)
def get_references(self):
@@ -408,8 +393,7 @@ class GeometryElementsSelection(QtGui.QWidget):
FreeCADGui.Selection.addSelection(ref[0], ref[1])
def setback_listobj_visibility(self):
"""set back Visibility of the list objects
"""
"""set back Visibility of the list objects"""
FreeCADGui.Selection.clearSelection()
for obj in self.obj_notvisible:
obj.ViewObject.Visibility = False
@@ -423,15 +407,9 @@ class GeometryElementsSelection(QtGui.QWidget):
menu_item_remove_selected.setDisabled(True)
menu_item_remove_all.setDisabled(True)
self.connect(
menu_item_remove_selected,
QtCore.SIGNAL("triggered()"),
self.remove_selected_reference
)
self.connect(
menu_item_remove_all,
QtCore.SIGNAL("triggered()"),
self.remove_all_references
menu_item_remove_selected, QtCore.SIGNAL("triggered()"), self.remove_selected_reference
)
self.connect(menu_item_remove_all, QtCore.SIGNAL("triggered()"), self.remove_all_references)
parentPosition = self.list_References.mapToGlobal(QtCore.QPoint(0, 0))
self.contextMenu.move(parentPosition + QPos)
self.contextMenu.show()
@@ -479,11 +457,11 @@ class GeometryElementsSelection(QtGui.QWidget):
def selectionParser(self, selection):
if hasattr(selection[0], "Shape") and selection[1]:
FreeCAD.Console.PrintMessage("Selection: {} {} {}\n".format(
selection[0].Shape.ShapeType,
selection[0].Name,
selection[1]
))
FreeCAD.Console.PrintMessage(
"Selection: {} {} {}\n".format(
selection[0].Shape.ShapeType, selection[0].Name, selection[1]
)
)
sobj = selection[0]
elt = sobj.Shape.getElement(selection[1])
ele_ShapeType = elt.ShapeType
@@ -502,8 +480,7 @@ class GeometryElementsSelection(QtGui.QWidget):
# could be more than two solids, think of polar pattern
FreeCAD.Console.PrintMessage(
" Edge belongs to at least two solids: "
" Solid{}, Solid{}\n"
.format(solid_to_add, str(i + 1))
" Solid{}, Solid{}\n".format(solid_to_add, str(i + 1))
)
solid_to_add = None
found_eltedge_in_other_solid = True
@@ -517,8 +494,9 @@ class GeometryElementsSelection(QtGui.QWidget):
else:
# AFAIK (bernd) a face can only belong to two solids
FreeCAD.Console.PrintMessage(
" Face belongs to two solids: Solid{}, Solid{}\n"
.format(solid_to_add, str(i + 1))
" Face belongs to two solids: Solid{}, Solid{}\n".format(
solid_to_add, str(i + 1)
)
)
solid_to_add = None
found_eltface_in_other_solid = True
@@ -526,14 +504,16 @@ class GeometryElementsSelection(QtGui.QWidget):
selection = (sobj, "Solid" + solid_to_add)
ele_ShapeType = "Solid"
FreeCAD.Console.PrintMessage(
" Selection variable adapted to hold the Solid: {} {} {}\n"
.format(sobj.Shape.ShapeType, sobj.Name, selection[1])
" Selection variable adapted to hold the Solid: {} {} {}\n".format(
sobj.Shape.ShapeType, sobj.Name, selection[1]
)
)
else:
return
if ele_ShapeType in self.sel_elem_types:
if (self.selection_mode_solid and ele_ShapeType == "Solid") \
or self.selection_mode_solid is False:
if (
self.selection_mode_solid and ele_ShapeType == "Solid"
) or self.selection_mode_solid is False:
if selection not in self.references:
# only equal shape types are allowed to add
if self.allow_multiple_geom_types is False:
@@ -553,15 +533,12 @@ class GeometryElementsSelection(QtGui.QWidget):
else:
# selected shape will not added to the list
FreeCADGui.Selection.clearSelection()
message = (
" Selection {} is in reference list already!\n"
.format(self.get_item_text(selection))
message = " Selection {} is in reference list already!\n".format(
self.get_item_text(selection)
)
FreeCAD.Console.PrintMessage(message)
QtGui.QMessageBox.critical(
None,
"Geometry already in list",
message.lstrip(" ")
None, "Geometry already in list", message.lstrip(" ")
)
else:
# selected shape will not added to the list
@@ -575,13 +552,12 @@ class GeometryElementsSelection(QtGui.QWidget):
# the method getElement(element) does not return Solid elements
r = geomtools.get_element(ref[0], ref[1])
if not r:
FreeCAD.Console.PrintError(
"Problem in retrieving element: {} \n".format(ref[1])
)
FreeCAD.Console.PrintError(f"Problem in retrieving element: {ref[1]} \n")
continue
FreeCAD.Console.PrintLog(
" ReferenceShape : {}, {}, {} --> {}\n"
.format(r.ShapeType, ref[0].Name, ref[0].Label, ref[1])
" ReferenceShape : {}, {}, {} --> {}\n".format(
r.ShapeType, ref[0].Name, ref[0].Label, ref[1]
)
)
if not ref_shty:
ref_shty = r.ShapeType
@@ -600,6 +576,7 @@ class GeometryElementsSelection(QtGui.QWidget):
class FemSelectionObserver:
"""selection observer especially for the needs of geometry reference selection of FEM"""
def __init__(self, parseSelectionFunction, print_message=""):
self.parseSelectionFunction = parseSelectionFunction
FreeCADGui.Selection.addObserver(self)

View File

@@ -37,6 +37,7 @@ import Mesh
App = FreeCAD # shortcut
if FreeCAD.GuiUp:
import FreeCADGui
Gui = FreeCADGui # shortcut
## \addtogroup FEM
@@ -54,23 +55,25 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1):
f.write("# Part 1 - node list\n")
f.write(
"TotalNumOfPoints: {}, NumOfDimensions; {}, "
"NumOfProperties: {}, BoundaryMarkerExists: {}\n"
.format(len(allVertices), 3, 0, 0)
"NumOfProperties: {}, BoundaryMarkerExists: {}\n".format(len(allVertices), 3, 0, 0)
)
for PointIndex in range(len(allVertices)):
f.write("%(PointIndex)5i %(x) e %(y) e %(z) e\n" % {
"PointIndex": PointIndex,
"x": allVertices[PointIndex].x,
"y": allVertices[PointIndex].y,
"z": allVertices[PointIndex].z
})
f.write(
"%(PointIndex)5i %(x) e %(y) e %(z) e\n"
% {
"PointIndex": PointIndex,
"x": allVertices[PointIndex].x,
"y": allVertices[PointIndex].y,
"z": allVertices[PointIndex].z,
}
)
# Find out BoundaryMarker for each facet. If edge connects only two facets,
# then this facets should have the same BoundaryMarker
BoundaryMarkerExists = 1
PointList = [allFacets[0][1], allFacets[0][0]]
PointList.sort()
EdgeFacets = {(PointList[0], PointList[1]): set([0])}
EdgeFacets = {(PointList[0], PointList[1]): {0}}
Edge = []
# Find all facets for each edge
@@ -85,7 +88,7 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1):
if EdgeIndex in EdgeFacets:
EdgeFacets[EdgeIndex].add(FacetIndex)
else:
EdgeFacets[EdgeIndex] = set([FacetIndex])
EdgeFacets[EdgeIndex] = {FacetIndex}
Edge = []
# Find BoundaryMarker for each facet
@@ -120,7 +123,7 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1):
if (BoundaryMarker[FacetPair[0]] != 0) and (BoundaryMarker[FacetPair[1]] != 0):
removeEdge = 1
break
if (BoundaryMarker[FacetPair[0]] != 0):
if BoundaryMarker[FacetPair[0]] != 0:
BoundaryMarker[FacetPair[1]] = BoundaryMarker[FacetPair[0]]
else:
BoundaryMarker[FacetPair[0]] = BoundaryMarker[FacetPair[1]]
@@ -156,10 +159,10 @@ def exportMeshToTetGenPoly(meshToExport, filePath, beVerbose=1):
# ********** Part 2 - write all facets to *.poly file
f.write("# Part 2 - facet list\n")
f.write("%(TotalNumOfFacets)i %(BoundaryMarkerExists)i\n" % {
"TotalNumOfFacets": len(allFacets),
"BoundaryMarkerExists": BoundaryMarkerExists
})
f.write(
"%(TotalNumOfFacets)i %(BoundaryMarkerExists)i\n"
% {"TotalNumOfFacets": len(allFacets), "BoundaryMarkerExists": BoundaryMarkerExists}
)
for FacetIndex in range(len(allFacets)):
f.write("# FacetIndex = %(Index)i\n" % {"Index": FacetIndex})
f.write("%(NumOfPolygons)3i " % {"NumOfPolygons": 1})
@@ -215,14 +218,7 @@ def createMesh():
AdsorbtionBox = AppPyDoc.addObject("Part::Box", AdsorbtionBoxName)
pnMesh = AppPyDoc.addObject("Mesh::Feature", pnMeshName)
BoxList = [
NSideBox,
DepletionBox,
PSideBox,
OxideBox,
AdsorbtionBox,
SurfDepletionBox
]
BoxList = [NSideBox, DepletionBox, PSideBox, OxideBox, AdsorbtionBox, SurfDepletionBox]
NSideBoxMesh = Mesh.Mesh()
PSideBoxMesh = Mesh.Mesh()
DepletionBoxMesh = Mesh.Mesh()
@@ -235,7 +231,7 @@ def createMesh():
PSideBoxMesh,
OxideBoxMesh,
AdsorbtionBoxMesh,
SurfDepletionBoxMesh
SurfDepletionBoxMesh,
]
if beVerbose == 1:
if len(BoxList) != len(BoxMeshList):
@@ -280,30 +276,14 @@ def createMesh():
# Object placement
Rot = App.Rotation(0, 0, 0, 1)
NSideBox.Placement = App.Placement(
App.Vector(0, 0, -BulkHeight),
Rot
)
NSideBox.Placement = App.Placement(App.Vector(0, 0, -BulkHeight), Rot)
PSideBox.Placement = App.Placement(
App.Vector(DepletionSize * 2 + BulkLength, 0, -BulkHeight),
Rot
)
DepletionBox.Placement = App.Placement(
App.Vector(BulkLength, 0, -BulkHeight),
Rot
)
SurfDepletionBox.Placement = App.Placement(
App.Vector(0, 0, 0),
Rot
)
OxideBox.Placement = App.Placement(
App.Vector(0, 0, DepletionSize),
Rot
)
AdsorbtionBox.Placement = App.Placement(
App.Vector(0, 0, DepletionSize + OxideThickness),
Rot
App.Vector(DepletionSize * 2 + BulkLength, 0, -BulkHeight), Rot
)
DepletionBox.Placement = App.Placement(App.Vector(BulkLength, 0, -BulkHeight), Rot)
SurfDepletionBox.Placement = App.Placement(App.Vector(0, 0, 0), Rot)
OxideBox.Placement = App.Placement(App.Vector(0, 0, DepletionSize), Rot)
AdsorbtionBox.Placement = App.Placement(App.Vector(0, 0, DepletionSize + OxideThickness), Rot)
# Unite
if beVerbose == 1:
@@ -316,9 +296,7 @@ def createMesh():
# for index in range(len(BoxList)):
for index in range(len(BoxList) - 1): # Manual hack
BoxMeshList[index].addFacets(
BoxList[index].Shape.tessellate(tessellationTollerance)
)
BoxMeshList[index].addFacets(BoxList[index].Shape.tessellate(tessellationTollerance))
nmesh.addMesh(BoxMeshList[index])
nmesh.removeDuplicatedPoints()
@@ -348,4 +326,5 @@ def createMesh():
if beVerbose == 1:
Console.PrintMessage("\nScript finished without errors.")
## @}

View File

@@ -49,10 +49,8 @@ from femmesh import meshtools
# names are fix given from FreeCAD, these methods are called from FreeCAD
# they are set in FEM modules Init.py
def export(
objectslist,
filename
):
def export(objectslist, filename):
"called when freecad exports a file"
if len(objectslist) != 1:
Console.PrintError("This exporter can only export one object.\n")
@@ -72,10 +70,7 @@ def export(
# ********* writer *******************************************************************************
def write(
fem_mesh,
filename
):
def write(fem_mesh, filename):
"""directly write a FemMesh to a pyNastran mesh file format
fem_mesh: a FemMesh"""
@@ -91,17 +86,14 @@ def write(
mesh_pynas_code += missing_code_pnynasmesh
# pynas file
basefilename = filename[:len(filename) - 4] # TODO basename is more failsafe
basefilename = filename[: len(filename) - 4] # TODO basename is more failsafe
pynasf = open(basefilename + ".py", "w")
pynasf.write("# written by FreeCAD\n\n\n")
pynasf.write("from pyNastran.bdf.bdf import BDF\n")
pynasf.write("model = BDF()\n\n\n")
pynasf.write(mesh_pynas_code)
pynasf.write(
"model.write_bdf('{}', enddata=True)\n"
.format(basefilename + "_pyNas.bdf")
)
pynasf.write("model.write_bdf('{}', enddata=True)\n".format(basefilename + "_pyNas.bdf"))
pynasf.close()
# execute pyNastran code to add grid to the model
@@ -128,7 +120,7 @@ def get_pynastran_mesh(
pynas_nodes = "# grid cards, geometric mesh points\n"
for node in femnodes_mesh:
vec = femnodes_mesh[node]
pynas_nodes += "model.add_grid({}, [{}, {}, {}])\n".format(node, vec.x, vec.y, vec.z)
pynas_nodes += f"model.add_grid({node}, [{vec.x}, {vec.y}, {vec.z}])\n"
# print(pynas_nodes)
# elements
@@ -142,14 +134,13 @@ def get_pynastran_mesh(
if export_element_type == "cbar":
pynas_elements += (
"model.add_{ele_keyword}({eid}, {pid}, {nodes}, "
"{orientation_vec}, {gnull})\n"
.format(
"{orientation_vec}, {gnull})\n".format(
ele_keyword=export_element_type,
eid=element,
pid=1,
nodes=nodes,
orientation_vec="x=[0.0, 0.0, 1.0]",
gnull="g0=None"
gnull="g0=None",
)
)
else:
@@ -161,28 +152,31 @@ def get_pynastran_mesh(
ele_keyword = "ctetra"
# N1, N3, N2, N4, N7, N6, N5, N8, N10, N9
the_nodes = [
nodes[0], nodes[2], nodes[1], nodes[3],
nodes[6], nodes[5], nodes[4],
nodes[7], nodes[9], nodes[8],
nodes[0],
nodes[2],
nodes[1],
nodes[3],
nodes[6],
nodes[5],
nodes[4],
nodes[7],
nodes[9],
nodes[8],
]
else:
ele_keyword = export_element_type
the_nodes = nodes
pynas_elements += (
"model.add_{ele_keyword}({eid}, {pid}, {nodes})\n"
.format(ele_keyword=ele_keyword, eid=element, pid=1, nodes=the_nodes)
pynas_elements += "model.add_{ele_keyword}({eid}, {pid}, {nodes})\n".format(
ele_keyword=ele_keyword, eid=element, pid=1, nodes=the_nodes
)
# print(pynas_elements)
mesh_pynas_code = "{}\n\n{}\n\n".format(pynas_nodes, pynas_elements)
mesh_pynas_code = f"{pynas_nodes}\n\n{pynas_elements}\n\n"
return mesh_pynas_code
# Helper
def get_export_element_type(
femmesh,
femelement_table=None
):
def get_export_element_type(femmesh, femelement_table=None):
return nastran_ele_types[meshtools.get_femmesh_eletype(femmesh, femelement_table)]

View File

@@ -43,19 +43,13 @@ EIGENVALUE_OUTPUT_SECTION = " E I G E N V A L U E O U T P U T"
# ********* generic FreeCAD import and export methods *********
def open(
filename
):
def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"called when freecad wants to import a file"
try:
doc = FreeCAD.getDocument(docname)
@@ -66,19 +60,14 @@ def insert(
# ********* module specific methods *********
def import_dat(
filename,
Analysis=None
):
def import_dat(filename, Analysis=None):
r = readResult(filename)
return r
# read a calculix result file and extract the data
def readResult(
dat_input
):
Console.PrintMessage("Read ccx results from dat file: {}\n".format(dat_input))
def readResult(dat_input):
Console.PrintMessage(f"Read ccx results from dat file: {dat_input}\n")
dat_file = pyopen(dat_input, "r")
eigenvalue_output_section_found = False
mode_reading = False

View File

@@ -41,17 +41,13 @@ from builtins import open as pyopen
# ********* generic FreeCAD import and export methods *********
def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"called when freecad wants to import a file"
try:
doc = FreeCAD.getDocument(docname)
@@ -62,12 +58,7 @@ def insert(
# ********* module specific methods *********
def importFrd(
filename,
analysis=None,
result_name_prefix="",
result_analysis_type=""
):
def importFrd(filename, analysis=None, result_name_prefix="", result_analysis_type=""):
import ObjectsFem
from . import importToolsFem
@@ -86,9 +77,7 @@ def importFrd(
nodenumbers_for_compacted_mesh = []
number_of_increments = len(m["Results"])
Console.PrintLog(
"Increments: " + str(number_of_increments) + "\n"
)
Console.PrintLog("Increments: " + str(number_of_increments) + "\n")
def make_result_mesh(result_name):
res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
@@ -107,26 +96,18 @@ def importFrd(
step_time = result_set["time"]
step_time = round(step_time, 2)
if eigenmode_number > 0:
results_name = (
"{}EigenMode_{}_Results"
.format(result_name_prefix, eigenmode_number)
results_name = "{}EigenMode_{}_Results".format(
result_name_prefix, eigenmode_number
)
elif number_of_increments > 1:
if result_analysis_type == "buckling":
results_name = (
"{}BucklingFactor_{}_Results"
.format(result_name_prefix, step_time)
results_name = "{}BucklingFactor_{}_Results".format(
result_name_prefix, step_time
)
else:
results_name = (
"{}Time_{}_Results"
.format(result_name_prefix, step_time)
)
results_name = f"{result_name_prefix}Time_{step_time}_Results"
else:
results_name = (
"{}Results"
.format(result_name_prefix)
)
results_name = f"{result_name_prefix}Results"
res_obj = make_result_mesh(results_name)
res_obj = importToolsFem.fill_femresult_mechanical(res_obj, result_set)
@@ -138,6 +119,7 @@ def importFrd(
# more result object calculations
from femresult import resulttools
from femtools import femutils
if not res_obj.MassFlowRate:
# information 1:
# only compact result if not Flow 1D results
@@ -220,7 +202,7 @@ def importFrd(
pipeline_obj.ViewObject.Visibility = pipeline_visibility
elif result_analysis_type == "check":
results_name = "{}Check".format(result_name_prefix)
results_name = f"{result_name_prefix}Check"
res_obj = make_result_mesh(results_name)
if analysis:
analysis.addObject(res_obj)
@@ -241,7 +223,7 @@ def importFrd(
# see error message above for more information
if not res_obj:
if result_name_prefix:
results_name = "{}_Results".format(result_name_prefix)
results_name = f"{result_name_prefix}_Results"
else:
results_name = "Results"
res_obj = ObjectsFem.makeResultMechanical(doc, results_name)
@@ -253,13 +235,12 @@ def importFrd(
if FreeCAD.GuiUp:
if analysis:
import FemGui
FemGui.setActiveAnalysis(analysis)
doc.recompute()
else:
Console.PrintError(
"Problem on frd file import. No nodes found in frd file.\n"
)
Console.PrintError("Problem on frd file import. No nodes found in frd file.\n")
# None will be returned
# or would it be better to raise an exception if there are not even nodes in frd file?
@@ -268,26 +249,19 @@ def importFrd(
# read a calculix result file and extract the nodes
# displacement vectors and stress values.
def read_frd_result(
frd_input
):
Console.PrintMessage(
"Read ccx results from frd file: {}\n"
.format(frd_input)
)
def read_frd_result(frd_input):
Console.PrintMessage(f"Read ccx results from frd file: {frd_input}\n")
inout_nodes = []
inout_nodes_file = frd_input.rsplit(".", 1)[0] + "_inout_nodes.txt"
if os.path.exists(inout_nodes_file):
Console.PrintMessage(
"Read special 1DFlow nodes data form: {}\n".format(inout_nodes_file)
)
Console.PrintMessage(f"Read special 1DFlow nodes data form: {inout_nodes_file}\n")
f = pyopen(inout_nodes_file, "r")
lines = f.readlines()
for line in lines:
a = line.split(",")
inout_nodes.append(a)
f.close()
Console.PrintMessage("{}\n".format(inout_nodes))
Console.PrintMessage(f"{inout_nodes}\n")
frd_file = pyopen(frd_input, "r")
nodes = {}
elements_hexa8 = {}
@@ -443,8 +417,26 @@ def read_frd_result(
hexa20 import works with the following frd file node assignment
"""
elements_hexa20[elem] = (
nd8, nd5, nd6, nd7, nd4, nd1, nd2, nd3, nd20, nd17,
nd18, nd19, nd12, nd9, nd10, nd11, nd16, nd13, nd14, nd15
nd8,
nd5,
nd6,
nd7,
nd4,
nd1,
nd2,
nd3,
nd20,
nd17,
nd18,
nd19,
nd12,
nd9,
nd10,
nd11,
nd16,
nd13,
nd14,
nd15,
)
elif elemType == 5 and input_continues is False:
# first line
@@ -479,8 +471,21 @@ def read_frd_result(
) # order of the *.inp file
"""
elements_penta15[elem] = (
nd5, nd6, nd4, nd2, nd3, nd1, nd14, nd15, nd13, nd8,
nd9, nd7, nd11, nd12, nd10
nd5,
nd6,
nd4,
nd2,
nd3,
nd1,
nd14,
nd15,
nd13,
nd8,
nd9,
nd7,
nd11,
nd12,
nd10,
)
elif elemType == 6:
# C3D10 Calculix --> tetra10 FreeCAD
@@ -632,7 +637,7 @@ def read_frd_result(
# we found an equivalent plastic strain line
elem = int(line[4:13])
peeq = float(line[13:25])
mode_peeq[elem] = (peeq)
mode_peeq[elem] = peeq
# Check if we found a temperature section
if line[5:11] == "NDTEMP":
@@ -641,7 +646,7 @@ def read_frd_result(
# we found a temperature line
elem = int(line[4:13])
temperature = float(line[13:25])
mode_temp[elem] = (temperature)
mode_temp[elem] = temperature
# Check if we found heat flux section
if line[5:9] == "FLUX":
@@ -654,8 +659,6 @@ def read_frd_result(
mode_heatflux_z = float(line[37:49])
mode_heatflux[elem] = FreeCAD.Vector(mode_heatflux_x, mode_heatflux_y, mode_heatflux_z)
# Check if we found a mass flow section
if line[5:11] == "MAFLOW":
mode_massflow_found = True
@@ -663,13 +666,13 @@ def read_frd_result(
# we found a mass flow line
elem = int(line[4:13])
massflow = float(line[13:25])
mode_massflow[elem] = (massflow * 1000) # convert units to kg/s from t/s
mode_massflow[elem] = massflow * 1000 # convert units to kg/s from t/s
if inout_nodes:
for i in range(len(inout_nodes)):
if elem == int(inout_nodes[i][1]):
node = int(inout_nodes[i][2])
# convert units to kg/s from t/s
mode_massflow[node] = (massflow * 1000)
mode_massflow[node] = massflow * 1000
# Check if we found a network pressure section
if line[5:11] == "STPRES":
@@ -678,12 +681,12 @@ def read_frd_result(
# we found a network pressure line
elem = int(line[4:13])
networkpressure = float(line[13:25])
mode_networkpressure[elem] = (networkpressure)
mode_networkpressure[elem] = networkpressure
if inout_nodes:
for i in range(len(inout_nodes)):
if elem == int(inout_nodes[i][1]):
node = int(inout_nodes[i][2])
mode_networkpressure[node] = (networkpressure)
mode_networkpressure[node] = networkpressure
# Check if we found the end of a section
if line[1:3] == "-3":
@@ -760,9 +763,11 @@ def read_frd_result(
if line[1:5] == "9999":
end_of_frd_data_found = True
if (mode_eigen_changed or mode_time_changed or end_of_frd_data_found) \
and end_of_section_found \
and not node_element_section:
if (
(mode_eigen_changed or mode_time_changed or end_of_frd_data_found)
and end_of_section_found
and not node_element_section
):
"""
print("\n\n----Append mode_results to results")
@@ -813,9 +818,7 @@ def read_frd_result(
if not inout_nodes:
if results:
if "mflow" in results[0] or "npressure" in results[0]:
Console.PrintError(
"We have mflow or npressure, but no inout_nodes file.\n"
)
Console.PrintError("We have mflow or npressure, but no inout_nodes file.\n")
if not nodes:
Console.PrintError("FEM: No nodes found in Frd file.\n")
@@ -833,5 +836,5 @@ def read_frd_result(
"Hexa20Elem": elements_hexa20,
"Penta6Elem": elements_penta6,
"Penta15Elem": elements_penta15,
"Results": results
"Results": results,
}

View File

@@ -50,6 +50,7 @@ if FreeCAD.GuiUp:
if FreeCAD.GuiUp:
class WriteXDMFTaskPanel:
"""
This task panel is used to write mesh groups with user defined values.
@@ -57,10 +58,9 @@ if FreeCAD.GuiUp:
"""
def __init__(self, fem_mesh_obj, fileString):
self.form = FreeCADGui.PySideUic.loadUi(os.path.join(
FreeCAD.getHomePath(),
"Mod/Fem/Resources/ui/MeshGroupXDMFExport.ui"
))
self.form = FreeCADGui.PySideUic.loadUi(
os.path.join(FreeCAD.getHomePath(), "Mod/Fem/Resources/ui/MeshGroupXDMFExport.ui")
)
self.result_dict = {}
self.fem_mesh_obj = fem_mesh_obj
self.fileString = fileString
@@ -73,34 +73,27 @@ if FreeCAD.GuiUp:
item.setFlags(~QtCore.Qt.ItemIsEditable & ~QtCore.Qt.ItemIsEnabled)
return item
gmshgroups = importToolsFem.get_FemMeshObjectMeshGroups(
self.fem_mesh_obj
)
gmshgroups = importToolsFem.get_FemMeshObjectMeshGroups(self.fem_mesh_obj)
fem_mesh = self.fem_mesh_obj.FemMesh
self.form.tableGroups.setRowCount(0)
self.form.tableGroups.setRowCount(len(gmshgroups))
for (ind, gind) in enumerate(gmshgroups):
for ind, gind in enumerate(gmshgroups):
# group number
self.form.tableGroups.setItem(ind, 0,
ro(QtGui.QTableWidgetItem(
str(gind))))
self.form.tableGroups.setItem(ind, 0, ro(QtGui.QTableWidgetItem(str(gind))))
# group name
self.form.tableGroups.setItem(ind, 1,
ro(QtGui.QTableWidgetItem(
fem_mesh.getGroupName(gind))))
self.form.tableGroups.setItem(
ind, 1, ro(QtGui.QTableWidgetItem(fem_mesh.getGroupName(gind)))
)
# group elements
self.form.tableGroups.setItem(ind, 2,
ro(QtGui.QTableWidgetItem(
fem_mesh.getGroupElementType(
gind))))
self.form.tableGroups.setItem(
ind, 2, ro(QtGui.QTableWidgetItem(fem_mesh.getGroupElementType(gind)))
)
# default value for not marked elements
self.form.tableGroups.setItem(ind, 3,
QtGui.QTableWidgetItem(str(0)))
self.form.tableGroups.setItem(ind, 3, QtGui.QTableWidgetItem(str(0)))
# default value for marked elements
self.form.tableGroups.setItem(ind, 4,
QtGui.QTableWidgetItem(str(1)))
self.form.tableGroups.setItem(ind, 4, QtGui.QTableWidgetItem(str(1)))
header = self.form.tableGroups.horizontalHeader()
header.setResizeMode(0, QtGui.QHeaderView.ResizeToContents)
@@ -136,8 +129,8 @@ if FreeCAD.GuiUp:
group_values_dict = self.convert_table_to_group_dict()
writeFenicsXDMF.write_fenics_mesh_xdmf(
self.fem_mesh_obj, self.fileString,
group_values_dict=group_values_dict)
self.fem_mesh_obj, self.fileString, group_values_dict=group_values_dict
)
FreeCADGui.Control.closeDialog()
@@ -165,8 +158,7 @@ def export(objectslist, fileString, group_values_dict_nogui=None):
of (marked_value (default=1), default_value (default=0))
"""
if len(objectslist) != 1:
Console.PrintError(
"This exporter can only export one object.\n")
Console.PrintError("This exporter can only export one object.\n")
return
obj = objectslist[0]
if not obj.isDerivedFrom("Fem::FemMeshObject"):
@@ -178,9 +170,10 @@ def export(objectslist, fileString, group_values_dict_nogui=None):
if fileExtension.lower() == ".xml":
if obj.ElementOrder != "1st":
Console.PrintWarning(
"XML is not designed to save higher order elements.\n" +
"Reducing order for second order mesh.\n" +
"Tri6 -> Tri3, Tet10 -> Tet4, etc.\n")
"XML is not designed to save higher order elements.\n"
+ "Reducing order for second order mesh.\n"
+ "Tri6 -> Tri3, Tet10 -> Tet4, etc.\n"
)
writeFenicsXML.write_fenics_mesh_xml(obj, fileString)
elif fileExtension.lower() == ".xdmf":
mesh_groups = importToolsFem.get_FemMeshObjectMeshGroups(obj)
@@ -192,19 +185,17 @@ def export(objectslist, fileString, group_values_dict_nogui=None):
else:
# create default dict if groupdict_nogui is not None
if group_values_dict_nogui is None:
group_values_dict_nogui = dict([(g, (1, 0))
for g in mesh_groups])
group_values_dict_nogui = {g: (1, 0) for g in mesh_groups}
writeFenicsXDMF.write_fenics_mesh_xdmf(
obj, fileString,
group_values_dict=group_values_dict_nogui)
obj, fileString, group_values_dict=group_values_dict_nogui
)
else:
writeFenicsXDMF.write_fenics_mesh_xdmf(obj, fileString)
# ********* module specific methods *********
def import_fenics_mesh(filename, analysis=None):
"""insert a FreeCAD FEM Mesh object in the ActiveDocument
"""
"""insert a FreeCAD FEM Mesh object in the ActiveDocument"""
mesh_data = readFenicsXML.read_fenics_mesh_xml(filename)
# xdmf not operational

View File

@@ -41,7 +41,6 @@ from builtins import open as pyopen
# ********* generic FreeCAD import and export methods *********
def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
@@ -60,17 +59,16 @@ def insert(filename, docname):
# ********* module specific methods *********
def read(filename):
"""read a FemMesh from a inp mesh file and return the FemMesh
"""
"""read a FemMesh from a inp mesh file and return the FemMesh"""
# no document object is created, just the FemMesh is returned
mesh_data = read_inp(filename)
from . import importToolsFem
return importToolsFem.make_femmesh(mesh_data)
def import_inp(filename):
"""read a FEM mesh from a Z88 mesh file and insert a FreeCAD FEM Mesh object in the ActiveDocument
"""
"""read a FEM mesh from a Z88 mesh file and insert a FreeCAD FEM Mesh object in the ActiveDocument"""
femmesh = read(filename)
mesh_name = os.path.splitext(os.path.basename(filename))[0]
if femmesh:
@@ -79,10 +77,10 @@ def import_inp(filename):
def read_inp(file_name):
"""read .inp file """
"""read .inp file"""
# ATM only mesh reading is supported (no boundary conditions)
class elements():
class elements:
tria3 = {}
tria6 = {}
@@ -96,6 +94,7 @@ def read_inp(file_name):
penta15 = {}
seg2 = {}
seg3 = {}
error_seg3 = False # to print "not supported"
nodes = {}
model_definition = True
@@ -161,12 +160,10 @@ def read_inp(file_name):
elif elm_type in ["S6", "CPS6", "CPE6", "CAX6"]:
elm_category = elements.tria6
number_of_nodes = 6
elif elm_type in ["S4", "S4R", "CPS4", "CPS4R", "CPE4", "CPE4R",
"CAX4", "CAX4R"]:
elif elm_type in ["S4", "S4R", "CPS4", "CPS4R", "CPE4", "CPE4R", "CAX4", "CAX4R"]:
elm_category = elements.quad4
number_of_nodes = 4
elif elm_type in ["S8", "S8R", "CPS8", "CPS8R", "CPE8", "CPE8R",
"CAX8", "CAX8R"]:
elif elm_type in ["S8", "S8R", "CPS8", "CPS8R", "CPE8", "CPE8R", "CAX8", "CAX8R"]:
elm_category = elements.quad8
number_of_nodes = 8
elif elm_type == "C3D4":
@@ -219,7 +216,7 @@ def read_inp(file_name):
if error_seg3 is True: # to print "not supported"
Console.PrintError("Error: seg3 (3-node beam element type) not supported, yet.\n")
elif error_not_supported_elemtype is True:
Console.PrintError("Error: {} not supported.\n".format(elm_type))
Console.PrintError(f"Error: {elm_type} not supported.\n")
f.close()
# switch from the CalculiX node numbering to the FreeCAD node numbering
@@ -229,24 +226,56 @@ def read_inp(file_name):
elements.tetra4[en] = [n[1], n[0], n[2], n[3]]
for en in elements.tetra10:
n = elements.tetra10[en]
elements.tetra10[en] = [n[1], n[0], n[2], n[3], n[4], n[6], n[5],
n[8], n[7], n[9]]
elements.tetra10[en] = [n[1], n[0], n[2], n[3], n[4], n[6], n[5], n[8], n[7], n[9]]
for en in elements.hexa8:
n = elements.hexa8[en]
elements.hexa8[en] = [n[5], n[6], n[7], n[4], n[1], n[2], n[3], n[0]]
for en in elements.hexa20:
n = elements.hexa20[en]
elements.hexa20[en] = [n[5], n[6], n[7], n[4], n[1], n[2], n[3], n[0],
n[13], n[14], n[15], n[12], n[9], n[10], n[11],
n[8], n[17], n[18], n[19], n[16]]
elements.hexa20[en] = [
n[5],
n[6],
n[7],
n[4],
n[1],
n[2],
n[3],
n[0],
n[13],
n[14],
n[15],
n[12],
n[9],
n[10],
n[11],
n[8],
n[17],
n[18],
n[19],
n[16],
]
for en in elements.penta6:
n = elements.penta6[en]
elements.penta6[en] = [n[4], n[5], n[3], n[1], n[2], n[0]]
for en in elements.penta15:
n = elements.penta15[en]
elements.penta15[en] = [n[4], n[5], n[3], n[1], n[2], n[0],
n[10], n[11], n[9], n[7], n[8], n[6], n[13],
n[14], n[12]]
elements.penta15[en] = [
n[4],
n[5],
n[3],
n[1],
n[2],
n[0],
n[10],
n[11],
n[9],
n[7],
n[8],
n[6],
n[13],
n[14],
n[12],
]
for en in elements.seg3:
n = elements.seg3[en]
elements.seg3[en] = [n[0], n[2], n[1]]
@@ -264,5 +293,5 @@ def read_inp(file_name):
"Hexa8Elem": elements.hexa8,
"Hexa20Elem": elements.hexa20,
"Penta6Elem": elements.penta6,
"Penta15Elem": elements.penta15
"Penta15Elem": elements.penta15,
}

View File

@@ -40,13 +40,8 @@ from builtins import open as pyopen
# they are set in FEM modules Init.py
# export mesh to python
def export(
objectslist,
filename
):
def export(objectslist, filename):
"called when freecad exports a file"
if len(objectslist) != 1:
FreeCAD.Console.PrintError("This exporter can only export one object.\n")
@@ -79,10 +74,8 @@ def export(
# ********* writer *******************************************************************************
def write(
fem_mesh,
filename
):
def write(fem_mesh, filename):
"""directly write a FemMesh to a Python mesh file
fem_mesh: a FemMesh"""
@@ -115,10 +108,7 @@ def write_python_mesh_to_file(femnodes_mesh, femelement_table, fem_mesh_type, f)
for node in femnodes_mesh:
# print(node, ' --> ', femnodes_mesh[node])
vec = femnodes_mesh[node]
f.write(
" {0}.addNode({1}, {2}, {3}, {4})\n"
.format(mesh_name, vec.x, vec.y, vec.z, node)
)
f.write(f" {mesh_name}.addNode({vec.x}, {vec.y}, {vec.z}, {node})\n")
f.write(" return True\n")
f.write("\n\n")
@@ -129,17 +119,20 @@ def write_python_mesh_to_file(femnodes_mesh, femelement_table, fem_mesh_type, f)
# print(element, ' --> ', femelement_table[element])
if fem_mesh_type == "Solid":
f.write(
" {0}.addVolume({1}, {2})\n"
.format(mesh_name, list(femelement_table[element]), element)
" {}.addVolume({}, {})\n".format(
mesh_name, list(femelement_table[element]), element
)
)
elif fem_mesh_type == "Face":
f.write(
" {0}.addFace({1}, {2})\n"
.format(mesh_name, list(femelement_table[element]), element)
" {}.addFace({}, {})\n".format(
mesh_name, list(femelement_table[element]), element
)
)
elif fem_mesh_type == "Edge":
f.write(
" {0}.addEdge({1}, {2})\n"
.format(mesh_name, list(femelement_table[element]), element)
" {}.addEdge({}, {})\n".format(
mesh_name, list(femelement_table[element]), element
)
)
f.write(" return True\n")

View File

@@ -33,11 +33,9 @@ import FreeCAD
from FreeCAD import Console
def get_FemMeshObjectMeshGroups(
fem_mesh_obj
):
def get_FemMeshObjectMeshGroups(fem_mesh_obj):
"""
Get mesh groups from mesh.
Get mesh groups from mesh.
"""
# this method is not really needed. It is used in Fenics mesh only.
# there was an exception handling if there was no Group property, but
@@ -47,16 +45,14 @@ def get_FemMeshObjectMeshGroups(
return fem_mesh_obj.FemMesh.Groups
def get_FemMeshObjectOrder(
fem_mesh_obj
):
def get_FemMeshObjectOrder(fem_mesh_obj):
"""
Gets element order. Element order counting based on number of nodes on
edges. Edge with 2 nodes -> linear elements, Edge with 3 nodes ->
quadratic elements, and so on. No edges in mesh -> not determined.
(Is this possible? Seems to be a very degenerate case.)
If there are edges with different number of nodes appearing, return
list of orders.
Gets element order. Element order counting based on number of nodes on
edges. Edge with 2 nodes -> linear elements, Edge with 3 nodes ->
quadratic elements, and so on. No edges in mesh -> not determined.
(Is this possible? Seems to be a very degenerate case.)
If there are edges with different number of nodes appearing, return
list of orders.
"""
presumable_order = None
@@ -78,11 +74,9 @@ def get_FemMeshObjectOrder(
return presumable_order
def get_FemMeshObjectDimension(
fem_mesh_obj
):
""" Count all entities in an abstract sense, to distinguish which dimension the mesh is
(i.e. linemesh, facemesh, volumemesh)
def get_FemMeshObjectDimension(fem_mesh_obj):
"""Count all entities in an abstract sense, to distinguish which dimension the mesh is
(i.e. linemesh, facemesh, volumemesh)
"""
dim = None
@@ -98,21 +92,28 @@ def get_FemMeshObjectDimension(
return dim
def get_FemMeshObjectElementTypes(
fem_mesh_obj,
remove_zero_element_entries=True
):
def get_FemMeshObjectElementTypes(fem_mesh_obj, remove_zero_element_entries=True):
"""
Spit out all elements in the mesh with their appropriate dimension.
Spit out all elements in the mesh with their appropriate dimension.
"""
FreeCAD_element_names_dims = {
"Node": 0, "Edge": 1, "Hexa": 3, "Polygon": 2, "Polyhedron": 3,
"Prism": 3, "Pyramid": 3, "Quadrangle": 2, "Tetra": 3, "Triangle": 2}
"Node": 0,
"Edge": 1,
"Hexa": 3,
"Polygon": 2,
"Polyhedron": 3,
"Prism": 3,
"Pyramid": 3,
"Quadrangle": 2,
"Tetra": 3,
"Triangle": 2,
}
eval_dict = locals() # to access local variables from eval
elements_list_with_zero = [(
eval("fem_mesh_obj.FemMesh." + s + "Count", eval_dict), s, d
) for (s, d) in FreeCAD_element_names_dims.items()]
elements_list_with_zero = [
(eval("fem_mesh_obj.FemMesh." + s + "Count", eval_dict), s, d)
for (s, d) in FreeCAD_element_names_dims.items()
]
# ugly but necessary
if remove_zero_element_entries:
elements_list = [(num, s, d) for (num, s, d) in elements_list_with_zero if num > 0]
@@ -122,22 +123,18 @@ def get_FemMeshObjectElementTypes(
return elements_list
def get_MaxDimElementFromList(
elem_list
):
def get_MaxDimElementFromList(elem_list):
"""
Gets element with the maximal dimension in the mesh to determine cells.
Gets element with the maximal dimension in the mesh to determine cells.
"""
elem_list.sort(key=lambda t: t[2])
return elem_list[-1]
def make_femmesh(
mesh_data
):
""" makes an FreeCAD FEM Mesh object from FEM Mesh data
"""
def make_femmesh(mesh_data):
"""makes an FreeCAD FEM Mesh object from FEM Mesh data"""
import Fem
mesh = Fem.FemMesh()
m = mesh_data
if ("Nodes" in m) and (len(m["Nodes"]) > 0):
@@ -181,15 +178,54 @@ def make_femmesh(
elms_penta15 = m["Penta15Elem"]
for i in elms_penta15:
e = elms_penta15[i]
mesh.addVolume([e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9],
e[10], e[11], e[12], e[13], e[14]], i)
mesh.addVolume(
[
e[0],
e[1],
e[2],
e[3],
e[4],
e[5],
e[6],
e[7],
e[8],
e[9],
e[10],
e[11],
e[12],
e[13],
e[14],
],
i,
)
elms_hexa20 = m["Hexa20Elem"]
for i in elms_hexa20:
e = elms_hexa20[i]
mesh.addVolume([
e[0], e[1], e[2], e[3], e[4], e[5], e[6], e[7], e[8], e[9],
e[10], e[11], e[12], e[13], e[14], e[15], e[16], e[17], e[18], e[19]
], i)
mesh.addVolume(
[
e[0],
e[1],
e[2],
e[3],
e[4],
e[5],
e[6],
e[7],
e[8],
e[9],
e[10],
e[11],
e[12],
e[13],
e[14],
e[15],
e[16],
e[17],
e[18],
e[19],
],
i,
)
elms_tria3 = m["Tria3Elem"]
for i in elms_tria3:
e = elms_tria3[i]
@@ -215,27 +251,25 @@ def make_femmesh(
e = elms_seg3[i]
mesh.addEdge([e[0], e[1], e[2]], i)
Console.PrintLog(
"imported mesh: {} nodes, {} HEXA8, {} PENTA6, {} TETRA4, {} TETRA10, {} PENTA15\n"
.format(
"imported mesh: {} nodes, {} HEXA8, {} PENTA6, {} TETRA4, {} TETRA10, {} PENTA15\n".format(
len(nds),
len(elms_hexa8),
len(elms_penta6),
len(elms_tetra4),
len(elms_tetra10),
len(elms_penta15)
len(elms_penta15),
)
)
Console.PrintLog(
"imported mesh: {} "
"HEXA20, {} TRIA3, {} TRIA6, {} QUAD4, {} QUAD8, {} SEG2, {} SEG3\n"
.format(
"HEXA20, {} TRIA3, {} TRIA6, {} QUAD4, {} QUAD8, {} SEG2, {} SEG3\n".format(
len(elms_hexa20),
len(elms_tria3),
len(elms_tria6),
len(elms_quad4),
len(elms_quad8),
len(elms_seg2),
len(elms_seg3)
len(elms_seg3),
)
)
else:
@@ -245,9 +279,7 @@ def make_femmesh(
return mesh
def make_dict_from_femmesh(
femmesh
):
def make_dict_from_femmesh(femmesh):
"""
Converts FemMesh into dictionary structure which can immediately used
from importToolsFem.make_femmesh(mesh_data) to create a valid FEM mesh.
@@ -277,14 +309,7 @@ def make_dict_from_femmesh(
len_to_edge = {2: seg2, 3: seg3}
len_to_face = {3: tri3, 6: tri6, 4: quad4, 8: quad8}
len_to_volume = {
4: tet4,
10: tet10,
8: hex8,
20: hex20,
6: pent6,
15: pent15
}
len_to_volume = {4: tet4, 10: tet10, 8: hex8, 20: hex20, 6: pent6, 15: pent15}
# analyze edges
@@ -305,42 +330,31 @@ def make_dict_from_femmesh(
len_to_volume[len(t)].append((v, t))
mesh_data = {
"Nodes": dict([(k, (v.x, v.y, v.z))
for (k, v) in femmesh.Nodes.items()]),
"Nodes": {k: (v.x, v.y, v.z) for (k, v) in femmesh.Nodes.items()},
"Seg2Elem": dict(seg2),
"Seg3Elem": dict(seg3),
"Tria3Elem": dict(tri3),
"Tria6Elem": dict(tri6),
"Quad4Elem": dict(quad4),
"Quad8Elem": dict(quad8),
"Tetra4Elem": dict(tet4),
"Tetra10Elem": dict(tet10),
"Hexa8Elem": dict(hex8),
"Hexa20Elem": dict(hex20),
"Penta6Elem": dict(pent6),
"Penta15Elem": dict(pent15),
"Groups": dict([(
group_num, (
femmesh.getGroupName(group_num),
femmesh.getGroupElements(group_num)
)
) for group_num in femmesh.Groups])
"Groups": {
group_num: (femmesh.getGroupName(group_num), femmesh.getGroupElements(group_num))
for group_num in femmesh.Groups
},
}
# no pyr5, pyr13?
# no groups?
return mesh_data
def fill_femresult_mechanical(
res_obj,
result_set
):
""" fills a FreeCAD FEM mechanical result object with result data
"""
def fill_femresult_mechanical(res_obj, result_set):
"""fills a FreeCAD FEM mechanical result object with result data"""
if "number" in result_set:
eigenmode_number = result_set["number"]
else:

View File

@@ -42,19 +42,13 @@ from builtins import open as pyopen
# ********* generic FreeCAD import and export methods *********
def open(
filename
):
def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"called when freecad wants to import a file"
try:
doc = FreeCAD.getDocument(docname)
@@ -64,15 +58,10 @@ def insert(
importVtk(filename)
def export(
objectslist,
filename
):
def export(objectslist, filename):
"called when freecad exports an object to vtk"
if len(objectslist) > 1: # the case of no selected obj is caught by FreeCAD already
Console.PrintError(
"This exporter can only export one object at once\n"
)
Console.PrintError("This exporter can only export one object at once\n")
return
obj = objectslist[0]
@@ -80,29 +69,19 @@ def export(
obj.writeVTK(filename)
return
elif obj.isDerivedFrom("Fem::FemMeshObject"):
Console.PrintError(
"Use export to FEM mesh formats to export a FEM mesh object to vtk!\n"
)
Console.PrintError("Use export to FEM mesh formats to export a FEM mesh object to vtk!\n")
return
elif obj.isDerivedFrom("Fem::FemResultObject"):
Fem.writeResult(filename, obj)
else:
Console.PrintError(
"Selected object is not supported by export to VTK.\n"
)
Console.PrintError("Selected object is not supported by export to VTK.\n")
return
# ********* module specific methods *********
def importVtk(
filename,
object_name=None,
object_type=None
):
def importVtk(filename, object_name=None, object_type=None):
if not object_type:
vtkinout_prefs = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/InOutVtk"
)
vtkinout_prefs = FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/InOutVtk")
object_type = vtkinout_prefs.GetInt("ImportObject", 0)
if not object_name:
object_name = os.path.splitext(os.path.basename(filename))[0]
@@ -116,16 +95,10 @@ def importVtk(
# FreeCAD result object
importVtkFCResult(filename, object_name)
else:
Console.PrintError(
"Error, wrong parameter in VTK import pref: {}\n"
.format(object_type)
)
Console.PrintError(f"Error, wrong parameter in VTK import pref: {object_type}\n")
def importVtkVtkResult(
filename,
resultname
):
def importVtkVtkResult(filename, resultname):
vtk_result_obj = FreeCAD.ActiveDocument.addObject("Fem::FemPostPipeline", resultname)
vtk_result_obj.read(filename)
# set display mode to "Surface" like for any other new pipeline to assure the user sees
@@ -136,10 +109,7 @@ def importVtkVtkResult(
return vtk_result_obj
def importVtkFemMesh(
filename,
meshname
):
def importVtkFemMesh(filename, meshname):
meshobj = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject", meshname)
meshobj.FemMesh = Fem.read(filename)
meshobj.touch()
@@ -147,16 +117,12 @@ def importVtkFemMesh(
return meshobj
def importVtkFCResult(
filename,
resultname,
analysis=None,
result_name_prefix=None
):
def importVtkFCResult(filename, resultname, analysis=None, result_name_prefix=None):
# only fields from vtk are imported if they exactly named as the FreeCAD result properties
# See _getFreeCADMechResultProperties() in FemVTKTools.cpp for the supported names
import ObjectsFem
if result_name_prefix is None:
result_name_prefix = ""
if analysis:
@@ -170,6 +136,7 @@ def importVtkFCResult(
# add missing DisplacementLengths (They should have been added by Fem.readResult)
if not result_obj.DisplacementLengths:
import femresult.resulttools as restools
result_obj = restools.add_disp_apps(result_obj) # DisplacementLengths
""" seems unused at the moment

View File

@@ -42,10 +42,7 @@ has_yaml = True
try:
import yaml
except ImportError:
Console.PrintMessage(
"No YAML available (import yaml failure), "
"yaml import/export won't work\n"
)
Console.PrintMessage("No YAML available (import yaml failure), yaml import/export won't work\n")
has_yaml = False
@@ -55,11 +52,7 @@ except ImportError:
# they are set in FEM modules Init.py
def open(
filename
):
def open(filename):
"""called when freecad opens a file
a FEM mesh object is created in a new document"""
@@ -67,10 +60,7 @@ def open(
return insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"""called when freecad wants to import a file"
a FEM mesh object is created in a existing document"""
@@ -87,9 +77,7 @@ def insert(
def export(objectslist, fileString):
"called when freecad exports a file"
if len(objectslist) != 1:
Console.PrintError(
"This exporter can only "
"export one object.\n")
Console.PrintError("This exporter can only export one object.\n")
return
obj = objectslist[0]
if not obj.isDerivedFrom("Fem::FemMeshObject"):
@@ -113,10 +101,9 @@ def export(objectslist, fileString):
# writer:
# - a method directly writes a FemMesh to the mesh file
# ********* reader ***********************************************************
def import_yaml_json_mesh(
fileString
):
def import_yaml_json_mesh(fileString):
"""
read a FemMesh from a yaml/json mesh file
insert a FreeCAD FEM Mesh object in the ActiveDocument
@@ -127,43 +114,34 @@ def import_yaml_json_mesh(
femmesh = read(fileString)
if femmesh:
mesh_object = FreeCAD.ActiveDocument.addObject(
"Fem::FemMeshObject",
mesh_name
)
mesh_object = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject", mesh_name)
mesh_object.FemMesh = femmesh
return mesh_object
def read(
fileString
):
"""read a FemMesh from a yaml/json mesh file and return the FemMesh
"""
def read(fileString):
"""read a FemMesh from a yaml/json mesh file and return the FemMesh"""
# no document object is created, just the FemMesh is returned
fileExtension = os.path.basename(os.path.splitext(fileString)[1])
raw_mesh_data = {}
if fileExtension.lower() == ".meshjson" or\
fileExtension.lower() == ".json":
if fileExtension.lower() == ".meshjson" or fileExtension.lower() == ".json":
fp = pyopen(fileString, "rt")
raw_mesh_data = json.load(fp)
fp.close()
elif (
fileExtension.lower() == ".meshyaml"
or fileExtension.lower() == ".meshyml"
or fileExtension.lower() == ".yaml"
or fileExtension.lower() == ".yml"
fileExtension.lower() == ".meshyaml"
or fileExtension.lower() == ".meshyml"
or fileExtension.lower() == ".yaml"
or fileExtension.lower() == ".yml"
) and has_yaml:
fp = pyopen(fileString, "rt")
raw_mesh_data = yaml.load(fp, Loader=yaml.SafeLoader)
fp.close()
else:
Console.PrintError(
"Unknown extension, "
"please select other importer.\n")
Console.PrintError("Unknown extension, please select other importer.\n")
Console.PrintMessage("Converting indices to integer numbers ...")
mesh_data = convert_raw_data_to_mesh_data(raw_mesh_data)
@@ -172,9 +150,7 @@ def read(
return importToolsFem.make_femmesh(mesh_data)
def convert_raw_data_to_mesh_data(
raw_mesh_data
):
def convert_raw_data_to_mesh_data(raw_mesh_data):
"""
Converts raw dictionary data from JSON or YAML file to proper dict
for importToolsFem.make_femmesh(mesh_data). This is necessary since
@@ -183,19 +159,14 @@ def convert_raw_data_to_mesh_data(
"""
mesh_data = {}
for (type_key, type_dict) in raw_mesh_data.items():
for type_key, type_dict in raw_mesh_data.items():
if type_key.lower() != "groups":
mesh_data[type_key] = dict([
(int(k), v) for (k, v) in type_dict.items()
])
mesh_data[type_key] = {int(k): v for (k, v) in type_dict.items()}
return mesh_data
# ********* writer ***********************************************************
def write(
fileString,
fem_mesh
):
def write(fileString, fem_mesh):
"""directly write a FemMesh to a yaml/json mesh file
fem_mesh: a FemMesh"""
@@ -203,8 +174,7 @@ def write(
if fileString != "":
fileName, fileExtension = os.path.splitext(fileString)
if fileExtension.lower() == ".json" \
or fileExtension.lower() == ".meshjson":
if fileExtension.lower() == ".json" or fileExtension.lower() == ".meshjson":
fp = pyopen(fileString, "wt")
json.dump(mesh_data, fp, indent=4)
fp.close()

View File

@@ -43,11 +43,7 @@ from builtins import open as pyopen
# they are set in FEM modules Init.py
def open(
filename
):
def open(filename):
"""called when freecad opens a file
a FEM mesh object is created in a new document"""
@@ -55,10 +51,7 @@ def open(
return insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"""called when freecad wants to import a file
a FEM mesh object is created in a existing document"""
@@ -72,10 +65,7 @@ def insert(
return doc
def export(
objectslist,
filename
):
def export(objectslist, filename):
"called when freecad exports a file"
if len(objectslist) != 1:
Console.PrintError("This exporter can only export one object.\n")
@@ -103,12 +93,9 @@ def export(
# - a method directly writes a FemMesh to the mesh file
# - a method takes a file handle, mesh data and writes to the file handle
# ********* reader *******************************************************************************
def import_z88_mesh(
filename,
analysis=None,
docname=None
):
def import_z88_mesh(filename, analysis=None, docname=None):
"""read a FEM mesh from a Z88 mesh file and
insert a FreeCAD FEM Mesh object in the ActiveDocument
"""
@@ -132,11 +119,8 @@ def import_z88_mesh(
return mesh_object
def read(
filename
):
"""read a FemMesh from a Z88 mesh file and return the FemMesh
"""
def read(filename):
"""read a FemMesh from a Z88 mesh file and return the FemMesh"""
# no document object is created, just the FemMesh is returned
mesh_data = read_z88_mesh(filename)
@@ -145,11 +129,9 @@ def read(
return importToolsFem.make_femmesh(mesh_data)
def read_z88_mesh(
z88_mesh_input
):
""" reads a z88 mesh file z88i1.txt (Z88OSV14) or z88structure.txt (Z88AuroraV3)
and extracts the nodes and elements
def read_z88_mesh(z88_mesh_input):
"""reads a z88 mesh file z88i1.txt (Z88OSV14) or z88structure.txt (Z88AuroraV3)
and extracts the nodes and elements
"""
nodes = {}
elements_hexa8 = {}
@@ -178,20 +160,18 @@ def read_z88_mesh(
kflag = int(mesh_info[4])
# for non rotational elements is --> kflag = 0 --> cartesian, kflag = 1 polar coordinates
if kflag:
Console.PrintError(
"KFLAG = 1, Rotational coordinates not supported at the moment\n"
)
Console.PrintError("KFLAG = 1, Rotational coordinates not supported at the moment\n")
return {}
nodes_first_line = 2 # first line is mesh_info
nodes_last_line = nodes_count + 1
elemts_first_line = nodes_last_line + 1
elements_last_line = elemts_first_line - 1 + elements_count * 2
Console.PrintLog("{}\n".format(nodes_count))
Console.PrintLog("{}\n".format(elements_count))
Console.PrintLog("{}\n".format(nodes_last_line))
Console.PrintLog("{}\n".format(elemts_first_line))
Console.PrintLog("{}\n".format(elements_last_line))
Console.PrintLog(f"{nodes_count}\n")
Console.PrintLog(f"{elements_count}\n")
Console.PrintLog(f"{nodes_last_line}\n")
Console.PrintLog(f"{elemts_first_line}\n")
Console.PrintLog(f"{elements_last_line}\n")
z88_mesh_file.seek(0) # go back to the beginning of the file
for no, line in enumerate(z88_mesh_file):
@@ -221,66 +201,44 @@ def read_z88_mesh(
# not supported elements
if z88_element_type == 8:
# torus8
Console.PrintError(
"Z88 Element No. 8, torus8\n"
)
Console.PrintError(
"Rotational elements are not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 8, torus8\n")
Console.PrintError("Rotational elements are not supported at the moment\n")
return {}
elif z88_element_type == 12:
# torus12
Console.PrintError(
"Z88 Element No. 12, torus12\n"
)
Console.PrintError(
"Rotational elements are not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 12, torus12\n")
Console.PrintError("Rotational elements are not supported at the moment\n")
return {}
elif z88_element_type == 15:
# torus6
Console.PrintError(
"Z88 Element No. 15, torus6\n"
)
Console.PrintError(
"Rotational elements are not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 15, torus6\n")
Console.PrintError("Rotational elements are not supported at the moment\n")
return {}
elif z88_element_type == 19:
# platte16
Console.PrintError(
"Z88 Element No. 19, platte16\n"
)
Console.PrintError(
"Not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 19, platte16\n")
Console.PrintError("Not supported at the moment\n")
return {}
elif z88_element_type == 21:
# schale16, mixture made from hexa8 and hexa20 (thickness is linear)
Console.PrintError(
"Z88 Element No. 21, schale16\n"
)
Console.PrintError(
"Not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 21, schale16\n")
Console.PrintError("Not supported at the moment\n")
return {}
elif z88_element_type == 22:
# schale12, mixtrue made from prism6 and prism15 (thickness is linear)
Console.PrintError(
"Z88 Element No. 22, schale12\n"
)
Console.PrintError(
"Not supported at the moment\n"
)
Console.PrintError("Z88 Element No. 22, schale12\n")
Console.PrintError("Not supported at the moment\n")
return {}
# supported elements
elif z88_element_type == 2 \
or z88_element_type == 4 \
or z88_element_type == 5 \
or z88_element_type == 9 \
or z88_element_type == 13 \
or z88_element_type == 25:
elif (
z88_element_type == 2
or z88_element_type == 4
or z88_element_type == 5
or z88_element_type == 9
or z88_element_type == 13
or z88_element_type == 25
):
# stab4 or stab5 or welle5 or beam13 or beam25 Z88 --> seg2 FreeCAD
# N1, N2
nd1 = int(linecolumns[0])
@@ -334,9 +292,7 @@ def read_z88_mesh(
nd8 = int(linecolumns[7])
nd9 = int(linecolumns[8])
nd10 = int(linecolumns[9])
elements_tetra10[elem_no] = (
nd1, nd2, nd4, nd3, nd5, nd8, nd10, nd7, nd6, nd9
)
elements_tetra10[elem_no] = (nd1, nd2, nd4, nd3, nd5, nd8, nd10, nd7, nd6, nd9)
input_continues = False
elif z88_element_type == 1:
# volume1 Z88 --> hexa8 FreeCAD
@@ -379,8 +335,26 @@ def read_z88_mesh(
nd19 = int(linecolumns[18])
nd20 = int(linecolumns[19])
elements_hexa20[elem_no] = (
nd1, nd2, nd3, nd4, nd5, nd6, nd7, nd8, nd9, nd10,
nd11, nd12, nd13, nd14, nd15, nd16, nd17, nd18, nd19, nd20
nd1,
nd2,
nd3,
nd4,
nd5,
nd6,
nd7,
nd8,
nd9,
nd10,
nd11,
nd12,
nd13,
nd14,
nd15,
nd16,
nd17,
nd18,
nd19,
nd20,
)
input_continues = False
@@ -411,15 +385,12 @@ def read_z88_mesh(
"Hexa8Elem": elements_hexa8,
"Hexa20Elem": elements_hexa20,
"Penta6Elem": elements_penta6,
"Penta15Elem": elements_penta15
"Penta15Elem": elements_penta15,
}
# ********* writer *******************************************************************************
def write(
fem_mesh,
filename
):
def write(fem_mesh, filename):
"""directly write a FemMesh to a Z88 mesh file format
fem_mesh: a FemMesh"""
@@ -434,12 +405,7 @@ def write(
f.close()
def write_z88_mesh_to_file(
femnodes_mesh,
femelement_table,
z88_element_type,
f
):
def write_z88_mesh_to_file(femnodes_mesh, femelement_table, z88_element_type, f):
node_dimension = 3 # 2 for 2D not supported
if (
z88_element_type == 4
@@ -449,10 +415,7 @@ def write_z88_mesh_to_file(
or z88_element_type == 10
):
node_dof = 3
elif (
z88_element_type == 23
or z88_element_type == 24
):
elif z88_element_type == 23 or z88_element_type == 24:
node_dof = 6 # schalenelemente
else:
Console.PrintError("Error: wrong z88_element_type.\n")
@@ -464,16 +427,15 @@ def write_z88_mesh_to_file(
written_by = "written by FreeCAD"
# first line, some z88 specific stuff
f.write("{0} {1} {2} {3} {4} {5}\n".format(
node_dimension, node_count, element_count, dofs, unknown_flag, written_by)
f.write(
"{} {} {} {} {} {}\n".format(
node_dimension, node_count, element_count, dofs, unknown_flag, written_by
)
)
# nodes
for node in femnodes_mesh:
vec = femnodes_mesh[node]
f.write(
"{0} {1} {2:.6f} {3:.6f} {4:.6f}\n"
.format(node, node_dof, vec.x, vec.y, vec.z)
)
f.write(f"{node} {node_dof} {vec.x:.6f} {vec.y:.6f} {vec.z:.6f}\n")
# elements
for element in femelement_table:
# z88_element_type is checked for every element
@@ -489,39 +451,37 @@ def write_z88_mesh_to_file(
):
# seg2 FreeCAD --> stab4 Z88
# N1, N2
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1}\n".format(
n[0], n[1]))
f.write(f"{element} {z88_element_type}\n")
f.write(f"{n[0]} {n[1]}\n")
elif z88_element_type == 3 or z88_element_type == 14 or z88_element_type == 24:
# tria6 FreeCAD --> schale24 Z88
# N1, N2, N3, N4, N5, N6
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1} {2} {3} {4} {5}\n".format(
n[0], n[1], n[2], n[3], n[4], n[5]))
f.write(f"{element} {z88_element_type}\n")
f.write(f"{n[0]} {n[1]} {n[2]} {n[3]} {n[4]} {n[5]}\n")
elif z88_element_type == 7 or z88_element_type == 20 or z88_element_type == 23:
# quad8 FreeCAD --> schale23 Z88
# N1, N2, N3, N4, N5, N6, N7, N8
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1} {2} {3} {4} {5} {6} {7}\n".format(
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]))
f.write(f"{element} {z88_element_type}\n")
f.write(f"{n[0]} {n[1]} {n[2]} {n[3]} {n[4]} {n[5]} {n[6]} {n[7]}\n")
elif z88_element_type == 17:
# tetra4 FreeCAD --> volume17 Z88
# N4, N2, N3, N1
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1} {2} {3}\n".format(
n[3], n[1], n[2], n[0]))
f.write(f"{element} {z88_element_type}\n")
f.write(f"{n[3]} {n[1]} {n[2]} {n[0]}\n")
elif z88_element_type == 16:
# tetra10 FreeCAD --> volume16 Z88
# N1, N2, N4, N3, N5, N9, N8, N6, N10, N7, FC to Z88 is different as Z88 to FC
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1} {2} {3} {4} {5} {6} {7} {8} {9}\n".format(
n[0], n[1], n[3], n[2], n[4], n[8], n[7], n[5], n[9], n[6]))
f.write(f"{element} {z88_element_type}\n")
f.write(
"{} {} {} {} {} {} {} {} {} {}\n".format(
n[0], n[1], n[3], n[2], n[4], n[8], n[7], n[5], n[9], n[6]
)
)
elif z88_element_type == 1:
# hexa8 FreeCAD --> volume1 Z88
# N1, N2, N3, N4, N5, N6, N7, N8
f.write("{0} {1}\n".format(element, z88_element_type))
f.write("{0} {1} {2} {3} {4} {5} {6} {7}\n".format(
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7]))
f.write(f"{element} {z88_element_type}\n")
f.write(f"{n[0]} {n[1]} {n[2]} {n[3]} {n[4]} {n[5]} {n[6]} {n[7]}\n")
elif z88_element_type == 10:
# hexa20 FreeCAD --> volume10 Z88
# N2, N3, N4, N1, N6, N7, N8, N5, N10, N11
@@ -529,28 +489,40 @@ def write_z88_mesh_to_file(
# or turn by 90 degree and they match !
# N1, N2, N3, N4, N5, N6, N7, N8, N9, N10
# N11, N12, N13, N14, N15, N16, N17, N18, N19, N20
f.write("{0} {1}\n".format(element, z88_element_type))
f.write(f"{element} {z88_element_type}\n")
f.write(
"{0} {1} {2} {3} {4} {5} {6} {7} {8} {9} "
"{10} {11} {12} {13} {14} {15} {16} {17} {18} {19}\n"
.format(
n[0], n[1], n[2], n[3], n[4], n[5], n[6], n[7], n[8], n[9],
n[10], n[11], n[12], n[13], n[14], n[15], n[16], n[17], n[18], n[19]
"{} {} {} {} {} {} {} {} {} {} "
"{} {} {} {} {} {} {} {} {} {}\n".format(
n[0],
n[1],
n[2],
n[3],
n[4],
n[5],
n[6],
n[7],
n[8],
n[9],
n[10],
n[11],
n[12],
n[13],
n[14],
n[15],
n[16],
n[17],
n[18],
n[19],
)
)
else:
Console.PrintError(
"Writing of Z88 elementtype {0} not supported.\n".format(z88_element_type)
)
Console.PrintError(f"Writing of Z88 elementtype {z88_element_type} not supported.\n")
# TODO support schale12 (made from prism15) and schale16 (made from hexa20)
return
# Helper
def get_z88_element_type(
femmesh,
femelement_table=None
):
def get_z88_element_type(femmesh, femelement_table=None):
return z88_ele_types[meshtools.get_femmesh_eletype(femmesh, femelement_table)]

View File

@@ -39,19 +39,13 @@ from builtins import open as pyopen
# ********* generic FreeCAD import and export methods *********
def open(
filename
):
def open(filename):
"called when freecad opens a file"
docname = os.path.splitext(os.path.basename(filename))[0]
insert(filename, docname)
def insert(
filename,
docname
):
def insert(filename, docname):
"called when freecad wants to import a file"
try:
doc = FreeCAD.getDocument(docname)
@@ -62,11 +56,7 @@ def insert(
# ********* module specific methods *********
def import_z88_disp(
filename,
analysis=None,
result_name_prefix=None
):
def import_z88_disp(filename, analysis=None, result_name_prefix=None):
"""insert a FreeCAD FEM mechanical result object in the ActiveDocument
pure usage:
import feminout.importZ88O2Results as importZ88O2Results
@@ -80,6 +70,7 @@ def import_z88_disp(
from . import importZ88Mesh
from . import importToolsFem
from femresult import resulttools
if result_name_prefix is None:
result_name_prefix = ""
disp_read = read_z88_disp(filename)
@@ -93,10 +84,7 @@ def import_z88_disp(
mesh_file = filename.replace("o2", "i1")
mesh_data = importZ88Mesh.read_z88_mesh(mesh_file)
femmesh = importToolsFem.make_femmesh(mesh_data)
result_mesh_object = ObjectsFem.makeMeshResult(
FreeCAD.ActiveDocument,
"Result_mesh"
)
result_mesh_object = ObjectsFem.makeMeshResult(FreeCAD.ActiveDocument, "Result_mesh")
result_mesh_object.FemMesh = femmesh
else:
Console.PrintError("Z88 mesh file z88i1.txt not found.\n")
@@ -118,6 +106,7 @@ def import_z88_disp(
if FreeCAD.GuiUp:
if analysis:
import FemGui
FemGui.setActiveAnalysis(analysis_object)
FreeCAD.ActiveDocument.recompute()
@@ -129,9 +118,7 @@ def import_z88_disp(
return res_obj
def read_z88_disp(
z88_disp_input
):
def read_z88_disp(z88_disp_input):
"""
read a z88 disp file and extract the nodes and elements
z88 Displacement output file is z88o2.txt

View File

@@ -48,5 +48,5 @@ def read_fenics_mesh_xdmf(xdmffilename):
"Tria6Elem": {},
"Quad4Elem": {},
"Quad8Elem": {},
"Seg2Elem": {}
"Seg2Elem": {},
}

View File

@@ -38,7 +38,7 @@ from FreeCAD import Console
def read_fenics_mesh_xml(xmlfilename):
"""
Returns element dictionary to be evaluated by make_femmesh later
Returns element dictionary to be evaluated by make_femmesh later
"""
Fenics_to_FreeCAD_dict = {
@@ -51,8 +51,8 @@ def read_fenics_mesh_xml(xmlfilename):
def read_mesh_block(mesh_block):
"""
Reading mesh block from XML file.
The mesh block only contains cells and vertices.
Reading mesh block from XML file.
The mesh block only contains cells and vertices.
"""
dim = int(mesh_block.get("dim"))
cell_type = mesh_block.get("celltype")
@@ -64,12 +64,14 @@ def read_fenics_mesh_xml(xmlfilename):
# every cell type contains a dict with key=dimension and value=number
cells_parts_dim = {"point": {0: 1},
"interval": {0: 2, 1: 1},
"triangle": {0: 3, 1: 3, 2: 1},
"tetrahedron": {0: 4, 1: 6, 2: 4, 3: 1},
"quadrilateral": {0: 4, 1: 4, 2: 1},
"hexahedron": {0: 8, 1: 12, 2: 6, 3: 1}}
cells_parts_dim = {
"point": {0: 1},
"interval": {0: 2, 1: 1},
"triangle": {0: 3, 1: 3, 2: 1},
"tetrahedron": {0: 4, 1: 6, 2: 4, 3: 1},
"quadrilateral": {0: 4, 1: 4, 2: 1},
"hexahedron": {0: 8, 1: 12, 2: 6, 3: 1},
}
find_vertices = mesh_block.find("vertices")
find_cells = mesh_block.find("cells")
@@ -88,7 +90,7 @@ def read_fenics_mesh_xml(xmlfilename):
if vertex.tag.lower() == "vertex":
[node_x, node_y, node_z] = [
float(vertex.get(coord, 0.)) for coord in ["x", "y", "z"]
float(vertex.get(coord, 0.0)) for coord in ["x", "y", "z"]
]
nodes_dict[ind + 1] = FreeCAD.Vector(node_x, node_y, node_z)
@@ -105,14 +107,14 @@ def read_fenics_mesh_xml(xmlfilename):
ind = int(cell.get("index"))
if cell.tag.lower() != cell_type.lower():
Console.PrintWarning("Strange mismatch between cell type " +
f"{cell_type} and " +
f"cell tag {cell.tag.lower()}\n")
Console.PrintWarning(
"Strange mismatch between cell type "
+ f"{cell_type} and "
+ f"cell tag {cell.tag.lower()}\n"
)
num_vertices = cells_parts_dim[cell_type][0]
vtupel = tuple([
int(cell.get("v" + str(vnum))) + 1 for vnum in range(num_vertices)
])
vtupel = tuple([int(cell.get("v" + str(vnum))) + 1 for vnum in range(num_vertices)])
# generate "v0", "v1", ... from dimension lookup table
# increase numbers by one to match FC numbering convention
@@ -127,14 +129,14 @@ def read_fenics_mesh_xml(xmlfilename):
def correct_volume_det(element_dict):
"""
Checks whether the cell elements
all have the same volume (<0?)
sign (is necessary to avoid negative
Jacobian errors).
Works only with tet4 and tri3 elements at the moment
Checks whether the cell elements
all have the same volume (<0?)
sign (is necessary to avoid negative
Jacobian errors).
Works only with tet4 and tri3 elements at the moment
"""
if dim == 3:
for (ind, tet) in list(element_dict["tetra4"].items()):
for ind, tet in list(element_dict["tetra4"].items()):
v0 = nodes[tet[0]]
v1 = nodes[tet[1]]
v2 = nodes[tet[2]]
@@ -145,8 +147,8 @@ def read_fenics_mesh_xml(xmlfilename):
if a.dot(b.cross(c)) > 0:
element_dict["tetra4"][ind] = (tet[1], tet[0], tet[2], tet[3])
if dim == 2:
nz = FreeCAD.Vector(0., 0., 1.)
for (ind, tria) in list(element_dict["tria3"].items()):
nz = FreeCAD.Vector(0.0, 0.0, 1.0)
for ind, tria in list(element_dict["tria3"].items()):
v0 = nodes[tria[0]]
v1 = nodes[tria[1]]
v2 = nodes[tria[2]]
@@ -159,7 +161,7 @@ def read_fenics_mesh_xml(xmlfilename):
element_counter = {}
# TODO: remove upper level lookup
for (key, val) in list(Fenics_to_FreeCAD_dict.items()):
for key, val in list(Fenics_to_FreeCAD_dict.items()):
element_dict[val] = {}
element_counter[key] = 0 # count every distinct element and sub element type
@@ -172,43 +174,46 @@ def read_fenics_mesh_xml(xmlfilename):
def invertdict(dic):
invdic = {}
for (key, it) in list(dic.items()):
for key, it in list(dic.items()):
invdic[it] = key
return invdic
num_vert_dict = {"interval": 2,
"triangle": 3,
"tetrahedron": 4,
"hexahedron": 8,
"quadrilateral": 4}
lower_dims_dict = {"interval": [],
"triangle": ["interval"],
"tetrahedron": ["triangle", "interval"],
"hexahedron": ["quadrilateral", "interval"],
"quadrilateral": ["interval"]}
num_vert_dict = {
"interval": 2,
"triangle": 3,
"tetrahedron": 4,
"hexahedron": 8,
"quadrilateral": 4,
}
lower_dims_dict = {
"interval": [],
"triangle": ["interval"],
"tetrahedron": ["triangle", "interval"],
"hexahedron": ["quadrilateral", "interval"],
"quadrilateral": ["interval"],
}
# generate cell list from file
# read vertex list from cells
# generate lower dimensional objects in mesh from cell
for (cell_index, cell) in list(cell_dict.items()):
for cell_index, cell in list(cell_dict.items()):
cell_lower_dims = lower_dims_dict[cell_type]
element_counter[cell_type] += 1
element_dict[Fenics_to_FreeCAD_dict[cell_type]][cell] = element_counter[cell_type]
for ld in cell_lower_dims:
for vertextuple in itertools.combinations(cell, num_vert_dict[ld]):
element_counter[ld] = addtupletodict(
element_dict[Fenics_to_FreeCAD_dict[ld]],
vertextuple,
element_counter[ld])
element_dict[Fenics_to_FreeCAD_dict[ld]], vertextuple, element_counter[ld]
)
length_counter = len(nodes) # maintain distinct counting values
# print("nodes")
# print("len & len counter", length_counter)
for (key, val_dict) in list(element_dict.items()):
for key, val_dict in list(element_dict.items()):
# to ensure distinct indices for FreeCAD
# print("key: ", key)
for (vkey, it) in list(val_dict.items()):
for vkey, it in list(val_dict.items()):
val_dict[vkey] = it + length_counter # maintain distinct element numbers
len_val_dict = len(val_dict)
if len_val_dict > 0:
@@ -240,7 +245,7 @@ def read_fenics_mesh_xml(xmlfilename):
(nodes, cells_dict, cell_type, dim) = read_mesh_block(find_mesh)
element_dict = generate_lower_dimensional_structures(nodes, cells_dict, cell_type, dim)
Console.PrintMessage("Show min max element dict\n")
for (elm, numbers) in list(element_dict.items()):
for elm, numbers in list(element_dict.items()):
lst = sorted(list(numbers.items()), key=lambda x: x[0])
if lst != []:
Console.PrintMessage(f"{elm} min: {lst[0]} max: {lst[-1]}\n")
@@ -263,5 +268,5 @@ def read_fenics_mesh_xml(xmlfilename):
"Hexa8Elem": {},
"Hexa20Elem": {},
"Penta6Elem": {},
"Penta15Elem": {}
"Penta15Elem": {},
}

View File

@@ -44,12 +44,7 @@ from .importToolsFem import get_MaxDimElementFromList
ENCODING_ASCII = "ASCII"
ENCODING_HDF5 = "HDF5"
FreeCAD_Group_Dimensions = {
"Vertex": 0,
"Edge": 1,
"Face": 2,
"Volume": 3
}
FreeCAD_Group_Dimensions = {"Vertex": 0, "Edge": 1, "Face": 2, "Volume": 3}
FreeCAD_to_Fenics_XDMF_dict = {
("Node", 1): ("Polyvertex", 1),
@@ -58,16 +53,14 @@ FreeCAD_to_Fenics_XDMF_dict = {
("Triangle", 1): ("Triangle", 3),
("Triangle", 2): ("Tri_6", 6),
("Tetra", 1): ("Tetrahedron", 4),
("Tetra", 2): ("Tet_10", 10)
("Tetra", 2): ("Tet_10", 10),
}
# we need numpy functions to later access and process large data sets in a fast manner
# also the hd5 support works better together with numpy
def numpy_array_to_str(
npa
):
def numpy_array_to_str(npa):
res = ""
dt = str(npa.dtype)
if "int" in dt:
@@ -77,27 +70,17 @@ def numpy_array_to_str(
return res
def points_to_numpy(
pts,
dim=3
):
def points_to_numpy(pts, dim=3):
return np.array([[p.x, p.y, p.z] for p in pts])[:, :dim]
def tuples_to_numpy(
tpls,
numbers_per_line
):
def tuples_to_numpy(tpls, numbers_per_line):
return np.array([list(t) for t in tpls])[:, :numbers_per_line]
def write_fenics_mesh_points_xdmf(
fem_mesh_obj,
geometrynode,
encoding=ENCODING_ASCII
):
def write_fenics_mesh_points_xdmf(fem_mesh_obj, geometrynode, encoding=ENCODING_ASCII):
"""
Writes either into hdf5 file or into open mesh file
Writes either into hdf5 file or into open mesh file
"""
numnodes = fem_mesh_obj.FemMesh.NodeCount
@@ -114,13 +97,10 @@ def write_fenics_mesh_points_xdmf(
if encoding == ENCODING_ASCII:
dataitem = ET.SubElement(
geometrynode,
"DataItem",
Dimensions="%d %d" % (numnodes, effective_dim),
Format="XML"
geometrynode, "DataItem", Dimensions="%d %d" % (numnodes, effective_dim), Format="XML"
)
nodes = []
for (ind, (key, node)) in enumerate(list(fem_mesh_obj.FemMesh.Nodes.items())):
for ind, (key, node) in enumerate(list(fem_mesh_obj.FemMesh.Nodes.items())):
nodes.append(node)
recalc_nodes_ind_dict[key] = ind
@@ -132,11 +112,7 @@ def write_fenics_mesh_points_xdmf(
def write_fenics_mesh_codim_xdmf(
fem_mesh_obj,
topologynode,
nodes_dict,
codim=0,
encoding=ENCODING_ASCII
fem_mesh_obj, topologynode, nodes_dict, codim=0, encoding=ENCODING_ASCII
):
mesh_dimension = get_FemMeshObjectDimension(fem_mesh_obj)
@@ -151,7 +127,7 @@ def write_fenics_mesh_codim_xdmf(
writeout_element_dimension = mesh_dimension - codim
(num_topo, name_topo, dim_topo) = (0, "", 0)
for (num, name, dim) in element_types:
for num, name, dim in element_types:
if writeout_element_dimension == dim:
(num_topo, name_topo, dim_topo) = (num, name, dim)
@@ -171,19 +147,22 @@ def write_fenics_mesh_codim_xdmf(
fc_topo = fem_mesh_obj.FemMesh.Nodes
else:
fc_topo = []
Console.PrintError("Dimension of mesh incompatible with export" +
f" XDMF function: {dim_topo}\n")
Console.PrintError(
"Dimension of mesh incompatible with export" + f" XDMF function: {dim_topo}\n"
)
nodeindices = [(
nodes_dict[ind] for ind in fem_mesh_obj.FemMesh.getElementNodes(fc_topo_ind)
) for (fen_ind, fc_topo_ind) in enumerate(fc_topo)]
nodeindices = [
(nodes_dict[ind] for ind in fem_mesh_obj.FemMesh.getElementNodes(fc_topo_ind))
for (fen_ind, fc_topo_ind) in enumerate(fc_topo)
]
if encoding == ENCODING_ASCII:
dataitem = ET.SubElement(
topologynode, "DataItem",
topologynode,
"DataItem",
NumberType="UInt",
Dimensions="%d %d" % (num_topo, nodes_per_element),
Format="XML"
Format="XML",
)
dataitem.text = numpy_array_to_str(tuples_to_numpy(nodeindices, nodes_per_element))
elif encoding == ENCODING_HDF5:
@@ -193,9 +172,7 @@ def write_fenics_mesh_codim_xdmf(
def write_fenics_mesh_scalar_cellfunctions(
name, cell_array,
attributenode,
encoding=ENCODING_ASCII
name, cell_array, attributenode, encoding=ENCODING_ASCII
):
attributenode.set("AttributeType", "Scalar")
attributenode.set("Center", "Cell")
@@ -205,9 +182,7 @@ def write_fenics_mesh_scalar_cellfunctions(
if encoding == ENCODING_ASCII:
dataitem = ET.SubElement(
attributenode, "DataItem",
Dimensions="%d %d" % (num_cells, num_dims),
Format="XML"
attributenode, "DataItem", Dimensions="%d %d" % (num_cells, num_dims), Format="XML"
)
dataitem.text = numpy_array_to_str(cell_array)
elif encoding == ENCODING_HDF5:
@@ -253,14 +228,9 @@ Example: mesh with two topologies and one mesh function for the facet one
"""
def write_fenics_mesh_xdmf(
fem_mesh_obj,
outputfile,
group_values_dict={},
encoding=ENCODING_ASCII
):
def write_fenics_mesh_xdmf(fem_mesh_obj, outputfile, group_values_dict={}, encoding=ENCODING_ASCII):
"""
For the export of xdmf.
For the export of xdmf.
"""
Console.PrintMessage(f"Converting {fem_mesh_obj.Label} to fenics XDMF File\n")
@@ -283,16 +253,9 @@ def write_fenics_mesh_xdmf(
# ***********************************
# write base topo and geometry
nodes_dict = write_fenics_mesh_points_xdmf(
fem_mesh_obj,
base_geometry,
encoding=encoding
)
nodes_dict = write_fenics_mesh_points_xdmf(fem_mesh_obj, base_geometry, encoding=encoding)
write_fenics_mesh_codim_xdmf(
fem_mesh_obj, base_topology,
nodes_dict,
codim=0,
encoding=encoding
fem_mesh_obj, base_topology, nodes_dict, codim=0, encoding=encoding
)
# ***********************************
@@ -307,14 +270,14 @@ def write_fenics_mesh_xdmf(
mesh_function_codim = dim_cell - FreeCAD_Group_Dimensions[mesh_function_type]
mesh_function_name = fem_mesh.getGroupName(g)
Console.PrintMessage(f"group id: {g} (label: {mesh_function_name})" +
f" with element type {mesh_function_type} and" +
" codim {mesh_function_codim}\n")
Console.PrintMessage(
f"group id: {g} (label: {mesh_function_name})"
+ f" with element type {mesh_function_type} and"
+ " codim {mesh_function_codim}\n"
)
mesh_function_grid = ET.SubElement(
domain, "Grid",
Name=mesh_function_name + "_mesh",
GridType="Uniform"
domain, "Grid", Name=mesh_function_name + "_mesh", GridType="Uniform"
)
mesh_function_topology = ET.SubElement(mesh_function_grid, "Topology")
@@ -322,11 +285,11 @@ def write_fenics_mesh_xdmf(
fem_mesh_obj,
mesh_function_topology,
nodes_dict,
codim=mesh_function_codim, encoding=encoding
codim=mesh_function_codim,
encoding=encoding,
)
mesh_function_geometry = ET.SubElement(mesh_function_grid, "Geometry",
Reference="XML")
mesh_function_geometry = ET.SubElement(mesh_function_grid, "Geometry", Reference="XML")
mesh_function_geometry.text = "/Xdmf/Domain/Grid/Geometry"
mesh_function_attribute = ET.SubElement(mesh_function_grid, "Attribute")
@@ -341,21 +304,18 @@ def write_fenics_mesh_xdmf(
for e in fem_mesh.getGroupElements(g):
elem_dict[e] = elem_mark_group
val_array = np.array([
elem_dict.get(e, elem_mark_default) for e in mesh_function_topology_description
])
val_array = np.array(
[elem_dict.get(e, elem_mark_default) for e in mesh_function_topology_description]
)
topo_array = np.vstack((val_array,)).T
write_fenics_mesh_scalar_cellfunctions(
mesh_function_name,
topo_array,
mesh_function_attribute,
encoding=ENCODING_ASCII
mesh_function_name, topo_array, mesh_function_attribute, encoding=ENCODING_ASCII
)
# TODO: improve cell functions support
fp = open(outputfile, "wb")
fp.write(b'''<?xml version="1.0"?>\n<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>\n''')
fp.write(b"""<?xml version="1.0"?>\n<!DOCTYPE Xdmf SYSTEM "Xdmf.dtd" []>\n""")
fp.write(ET.tostring(root))
# xml core functionality does not support pretty printing
# so the output file looks quite ugly

View File

@@ -41,9 +41,9 @@ from .importToolsFem import get_MaxDimElementFromList
def write_fenics_mesh_xml(fem_mesh_obj, outputfile):
"""
For the export, we only have to use the highest dimensional entities and their
vertices to be exported.
For second order elements, we have to delete the mid element nodes.
For the export, we only have to use the highest dimensional entities and their
vertices to be exported.
For second order elements, we have to delete the mid element nodes.
"""
# TODO: check for second order elements
@@ -57,9 +57,10 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile):
"Edge": "interval",
"Node": "point",
"Quadrangle": "quadrilateral",
"Polygon": "unknown", "Polyhedron": "unknown",
"Prism": "unknown", "Pyramid": "unknown",
"Polygon": "unknown",
"Polyhedron": "unknown",
"Prism": "unknown",
"Pyramid": "unknown",
}
XML_Number_of_Nodes_dict = {
@@ -68,7 +69,7 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile):
"triangle": 3,
"quadrilateral": 4,
"tetrahedron": 4,
"hexahedron": 8
"hexahedron": 8,
}
Console.PrintMessage(f"Converting {fem_mesh_obj.Label} to fenics XML File\n")
@@ -80,18 +81,25 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile):
(num_cells, cellname_fc, dim_cell) = celltype_in_mesh
cellname_fenics = FreeCAD_to_Fenics_dict[cellname_fc]
num_verts_cell = XML_Number_of_Nodes_dict[cellname_fenics]
Console.PrintMessage(f"Celltype in mesh -> {str(celltype_in_mesh)} " +
f"and its Fenics name: {cellname_fenics}\n")
Console.PrintMessage(
f"Celltype in mesh -> {str(celltype_in_mesh)} "
+ f"and its Fenics name: {cellname_fenics}\n"
)
root = ET.Element("dolfin", dolfin="http://fenicsproject.org")
meshchild = ET.SubElement(root, "mesh", celltype=cellname_fenics, dim=str(dim_cell))
vertices = ET.SubElement(meshchild, "vertices", size=str(fem_mesh_obj.FemMesh.NodeCount))
for (nodeind, fc_vec) in list(fem_mesh_obj.FemMesh.Nodes.items()):
for nodeind, fc_vec in list(fem_mesh_obj.FemMesh.Nodes.items()):
ET.SubElement(
vertices, "vertex", index=str(nodeind - 1),
vertices,
"vertex",
index=str(nodeind - 1),
# FC starts from 1, fenics starts from 0 to size-1
x=str(fc_vec[0]), y=str(fc_vec[1]), z=str(fc_vec[2]))
x=str(fc_vec[0]),
y=str(fc_vec[1]),
z=str(fc_vec[2]),
)
cells = ET.SubElement(meshchild, "cells", size=str(num_cells))
if dim_cell == 3:
@@ -103,12 +111,12 @@ def write_fenics_mesh_xml(fem_mesh_obj, outputfile):
else:
fc_cells = ()
for (fen_ind, fc_volume_ind) in enumerate(fc_cells):
for fen_ind, fc_volume_ind in enumerate(fc_cells):
# FC starts after all other entities, fenics start from 0 to size-1
nodeindices = fem_mesh_obj.FemMesh.getElementNodes(fc_volume_ind)
cell_args = {}
for (vi, ni) in enumerate(nodeindices):
for vi, ni in enumerate(nodeindices):
if vi < num_verts_cell: # XML only supports first order meshs
cell_args["v" + str(vi)] = str(ni - 1)
# generate as many v entries in dict as nodes are listed in cell

View File

@@ -36,6 +36,7 @@ import time
import FreeCAD
import Fem
# import Mesh
@@ -55,33 +56,26 @@ Mesh.show(Mesh.Mesh(out_mesh))
# These dictionaries list the nodes, that define faces of an element.
# The key is the face number, used internally by FreeCAD.
# The list contains the nodes in the element for each face.
tetFaces = {
1: [0, 1, 2],
2: [0, 3, 1],
3: [1, 3, 2],
4: [2, 3, 0]}
tetFaces = {1: [0, 1, 2], 2: [0, 3, 1], 3: [1, 3, 2], 4: [2, 3, 0]}
pentaFaces = {
1: [0, 1, 2],
2: [3, 5, 4],
3: [0, 3, 4, 1],
4: [1, 4, 5, 2],
5: [0, 2, 5, 3]}
pentaFaces = {1: [0, 1, 2], 2: [3, 5, 4], 3: [0, 3, 4, 1], 4: [1, 4, 5, 2], 5: [0, 2, 5, 3]}
hexaFaces = { # hexa8 or hexa20 (ignoring mid-nodes)
hexaFaces = { # hexa8 or hexa20 (ignoring mid-nodes)
1: [0, 1, 2, 3],
2: [4, 7, 6, 5],
3: [0, 4, 5, 1],
4: [1, 5, 6, 2],
5: [2, 6, 7, 3],
6: [3, 7, 4, 0]}
6: [3, 7, 4, 0],
}
pyraFaces = { # pyra5 or pyra13 (ignoring mid-nodes)
pyraFaces = { # pyra5 or pyra13 (ignoring mid-nodes)
1: [0, 1, 2, 3],
2: [0, 4, 1],
3: [1, 4, 2],
4: [2, 4, 3],
5: [3, 4, 0]}
5: [3, 4, 0],
}
face_dicts = {
4: tetFaces,
@@ -91,7 +85,8 @@ face_dicts = {
10: tetFaces,
13: pyraFaces,
15: pentaFaces,
20: hexaFaces}
20: hexaFaces,
}
def femmesh_2_mesh(myFemMesh, myResults=None, myDispScale=1):
@@ -120,7 +115,7 @@ def femmesh_2_mesh(myFemMesh, myResults=None, myDispScale=1):
codeList.append(element_nodes[nodeIdx])
codeList.sort()
for node in codeList:
faceCode += (node << shifter)
faceCode += node << shifter
# x << n: x shifted left by n bits = Multiplication
shifter += shiftBits
# print("codeList: ", codeList)
@@ -142,7 +137,7 @@ def femmesh_2_mesh(myFemMesh, myResults=None, myDispScale=1):
codeList.append(element_nodes[nodeIdx])
codeList.sort()
for node in codeList:
faceCode += (node << shifter)
faceCode += node << shifter
# x << n: x shifted left by n bits = Multiplication
shifter += shiftBits
# print("codeList: ", codeList)
@@ -164,83 +159,90 @@ def femmesh_2_mesh(myFemMesh, myResults=None, myDispScale=1):
singleFaces.append(faceCodeList[actFaceIdx])
actFaceIdx += 1
else:
FreeCAD.Console.PrintMessage("Found a last Face: {}\n".format(faceCodeList[actFaceIdx]))
FreeCAD.Console.PrintMessage(f"Found a last Face: {faceCodeList[actFaceIdx]}\n")
singleFaces.append(faceCodeList[actFaceIdx])
actFaceIdx += 1
output_mesh = []
if myResults:
FreeCAD.Console.PrintMessage("{}\n".format(myResults.Name))
FreeCAD.Console.PrintMessage(f"{myResults.Name}\n")
for myFace in singleFaces:
face_nodes = faceCodeDict[myFace]
dispVec0 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[0])]
dispVec1 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[1])]
dispVec2 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[2])]
triangle = [myFemMesh.getNodeById(face_nodes[0]) + dispVec0 * myDispScale,
myFemMesh.getNodeById(face_nodes[1]) + dispVec1 * myDispScale,
myFemMesh.getNodeById(face_nodes[2]) + dispVec2 * myDispScale]
triangle = [
myFemMesh.getNodeById(face_nodes[0]) + dispVec0 * myDispScale,
myFemMesh.getNodeById(face_nodes[1]) + dispVec1 * myDispScale,
myFemMesh.getNodeById(face_nodes[2]) + dispVec2 * myDispScale,
]
output_mesh.extend(triangle)
# print("my triangle: ", triangle)
if len(face_nodes) == 4:
dispVec3 = myResults.DisplacementVectors[myResults.NodeNumbers.index(face_nodes[3])]
triangle = [myFemMesh.getNodeById(face_nodes[2]) + dispVec2 * myDispScale,
myFemMesh.getNodeById(face_nodes[3]) + dispVec3 * myDispScale,
myFemMesh.getNodeById(face_nodes[0]) + dispVec0 * myDispScale]
triangle = [
myFemMesh.getNodeById(face_nodes[2]) + dispVec2 * myDispScale,
myFemMesh.getNodeById(face_nodes[3]) + dispVec3 * myDispScale,
myFemMesh.getNodeById(face_nodes[0]) + dispVec0 * myDispScale,
]
output_mesh.extend(triangle)
# print("my 2. triangle: ", triangle)
else:
for myFace in singleFaces:
face_nodes = faceCodeDict[myFace]
triangle = [myFemMesh.getNodeById(face_nodes[0]),
myFemMesh.getNodeById(face_nodes[1]),
myFemMesh.getNodeById(face_nodes[2])]
triangle = [
myFemMesh.getNodeById(face_nodes[0]),
myFemMesh.getNodeById(face_nodes[1]),
myFemMesh.getNodeById(face_nodes[2]),
]
output_mesh.extend(triangle)
# print("my triangle: ", triangle)
if len(face_nodes) == 4:
triangle = [myFemMesh.getNodeById(face_nodes[2]),
myFemMesh.getNodeById(face_nodes[3]),
myFemMesh.getNodeById(face_nodes[0])]
triangle = [
myFemMesh.getNodeById(face_nodes[2]),
myFemMesh.getNodeById(face_nodes[3]),
myFemMesh.getNodeById(face_nodes[0]),
]
output_mesh.extend(triangle)
# print("my 2. triangle: ", triangle)
end_time = time.process_time()
FreeCAD.Console.PrintMessage(
"Mesh by surface search method: {}\n".format(end_time - start_time)
)
# call to mesh_2_femmesh to convert mesh to femmesh before return statement
FreeCAD.Console.PrintMessage(f"Mesh by surface search method: {end_time - start_time}\n")
# call to mesh_2_femmesh to convert mesh to femmesh before return statement
mesh2femmesh = mesh_2_femmesh(myFemMesh, singleFaces, faceCodeDict)
return output_mesh
# additional function to convert mesh to femmesh
def mesh_2_femmesh(myFemMesh, singleFaces, faceCodeDict):
start_time = time.process_time()
femmesh = Fem.FemMesh()
myfemmesh = myFemMesh.Nodes
# nodes contains the nodes that are used
# nodes contains the nodes that are used
nodes = {}
for myFace in singleFaces:
face_nodes = faceCodeDict[myFace]
for j in (0, 1, 2):
try:
nodes[face_nodes[j]] += 1
except:
nodes[face_nodes[j]] = 0
try:
nodes[face_nodes[j]] += 1
except:
nodes[face_nodes[j]] = 0
if len(face_nodes) == 4:
j = 3
try:
nodes[face_nodes[j]] += 1
except:
nodes[face_nodes[j]] = 0
j = 3
try:
nodes[face_nodes[j]] += 1
except:
nodes[face_nodes[j]] = 0
sfNode = femmesh.addNode
sfFace = femmesh.addFace
for key in myFemMesh.Nodes:
mynode = myfemmesh[key]
try:
if(nodes[key] >= 0):
sfNode(mynode[0], mynode[1], mynode[2], key)
if nodes[key] >= 0:
sfNode(mynode[0], mynode[1], mynode[2], key)
except:
pass
pass
output_mesh = []
@@ -248,13 +250,12 @@ def mesh_2_femmesh(myFemMesh, singleFaces, faceCodeDict):
face_nodes = faceCodeDict[myFace]
sfFace(face_nodes[0], face_nodes[1], face_nodes[2])
if len(face_nodes) == 4:
sfFace(face_nodes[2], face_nodes[3], face_nodes[0])
obj = FreeCAD.ActiveDocument.addObject(
"Fem::FemMeshObject", "Mesh2Fem")
sfFace(face_nodes[2], face_nodes[3], face_nodes[0])
obj = FreeCAD.ActiveDocument.addObject("Fem::FemMeshObject", "Mesh2Fem")
obj.FemMesh = femmesh
end_time = time.process_time()
FreeCAD.Console.PrintMessage(
"Convert to FemMesh: {}\n".format(end_time - start_time)
)
FreeCAD.Console.PrintMessage(f"Convert to FemMesh: {end_time - start_time}\n")
return obj
# end of mesh_2_femmesh

View File

@@ -44,7 +44,7 @@ class GmshError(Exception):
pass
class GmshTools():
class GmshTools:
def __init__(self, gmsh_mesh_obj, analysis=None):
# mesh obj
@@ -62,7 +62,7 @@ class GmshTools():
# clmax, CharacteristicLengthMax: float, 0.0 = 1e+22
self.clmax = Units.Quantity(self.mesh_obj.CharacteristicLengthMax).Value
if self.clmax == 0.0:
self.clmax = 1e+22
self.clmax = 1e22
# clmin, CharacteristicLengthMin: float
self.clmin = Units.Quantity(self.mesh_obj.CharacteristicLengthMin).Value
@@ -210,14 +210,14 @@ class GmshTools():
def start_logs(self):
Console.PrintLog("\nGmsh FEM mesh run is being started.\n")
Console.PrintLog(" Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}\n".format(
self.part_obj.Name,
self.part_obj.Label,
self.part_obj.Shape.ShapeType
))
Console.PrintLog(" CharacteristicLengthMax: {}\n".format(self.clmax))
Console.PrintLog(" CharacteristicLengthMin: {}\n".format(self.clmin))
Console.PrintLog(" ElementOrder: {}\n".format(self.order))
Console.PrintLog(
" Part to mesh: Name --> {}, Label --> {}, ShapeType --> {}\n".format(
self.part_obj.Name, self.part_obj.Label, self.part_obj.Shape.ShapeType
)
)
Console.PrintLog(f" CharacteristicLengthMax: {self.clmax}\n")
Console.PrintLog(f" CharacteristicLengthMin: {self.clmin}\n")
Console.PrintLog(f" ElementOrder: {self.order}\n")
def get_dimension(self):
# Dimension
@@ -269,36 +269,26 @@ class GmshTools():
if femutils.check_working_dir(self.working_dir) is not True:
if create is True:
Console.PrintMessage(
"Dir given as parameter \'{}\' doesn't exist, "
"Dir given as parameter '{}' doesn't exist, "
"but parameter to create it is set to True. "
"Dir will be created.\n".format(self.working_dir)
)
os.mkdir(param_working_dir)
else:
Console.PrintError(
"Dir given as parameter \'{}\' doesn't exist "
"and create parameter is set to False.\n"
.format(self.working_dir)
"Dir given as parameter '{}' doesn't exist "
"and create parameter is set to False.\n".format(self.working_dir)
)
self.working_dir = femutils.get_pref_working_dir(self.mesh_obj)
Console.PrintMessage(
"Dir \'{}\' will be used instead.\n"
.format(self.working_dir)
)
Console.PrintMessage(f"Dir '{self.working_dir}' will be used instead.\n")
else:
self.working_dir = femutils.get_pref_working_dir(self.mesh_obj)
# check working_dir exist, if not use a tmp dir and inform the user
if femutils.check_working_dir(self.working_dir) is not True:
Console.PrintError(
"Dir \'{}\' doesn't exist or cannot be created.\n"
.format(self.working_dir)
)
Console.PrintError(f"Dir '{self.working_dir}' doesn't exist or cannot be created.\n")
self.working_dir = femutils.get_temp_dir(self.mesh_obj)
Console.PrintMessage(
"Dir \'{}\' will be used instead.\n"
.format(self.working_dir)
)
Console.PrintMessage(f"Dir '{self.working_dir}' will be used instead.\n")
# file paths
_geometry_name = self.part_obj.Name + "_Geometry"
@@ -315,15 +305,16 @@ class GmshTools():
def get_gmsh_command(self):
from platform import system
gmsh_std_location = FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/Gmsh"
).GetBool("UseStandardGmshLocation")
if gmsh_std_location:
if system() == "Windows":
gmsh_path = FreeCAD.getHomePath() + "bin/gmsh.exe"
FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/Gmsh"
).SetString("gmshBinaryPath", gmsh_path)
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").SetString(
"gmshBinaryPath", gmsh_path
)
self.gmsh_bin = gmsh_path
elif system() == "Linux":
p1 = subprocess.Popen(["which", "gmsh"], stdout=subprocess.PIPE)
@@ -343,9 +334,9 @@ class GmshTools():
elif system() == "Darwin":
# https://forum.freecad.org/viewtopic.php?f=13&t=73041&p=642026#p642022
gmsh_path = "/Applications/Gmsh.app/Contents/MacOS/gmsh"
FreeCAD.ParamGet(
"User parameter:BaseApp/Preferences/Mod/Fem/Gmsh"
).SetString("gmshBinaryPath", gmsh_path)
FreeCAD.ParamGet("User parameter:BaseApp/Preferences/Mod/Fem/Gmsh").SetString(
"gmshBinaryPath", gmsh_path
)
self.gmsh_bin = gmsh_path
else:
error_message = (
@@ -396,10 +387,7 @@ class GmshTools():
"Are you really sure about this? You could run into trouble!\n"
)
self.group_nodes_export = True
new_group_elements = meshtools.get_analysis_group_elements(
self.analysis,
self.part_obj
)
new_group_elements = meshtools.get_analysis_group_elements(self.analysis, self.part_obj)
for ge in new_group_elements:
if ge not in self.group_elements:
self.group_elements[ge] = new_group_elements[ge]
@@ -428,7 +416,7 @@ class GmshTools():
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
universal_newlines=True
universal_newlines=True,
)
except Exception as e:
Console.PrintMessage(str(e) + "\n")
@@ -440,6 +428,7 @@ class GmshTools():
Console.PrintError("Gmsh: StdErr:\n" + gmsh_stderr + "\n")
from re import search
# use raw string mode to get pep8 quiet
# https://stackoverflow.com/q/61497292
# https://github.com/MathSci/fecon236/issues/6
@@ -465,7 +454,8 @@ class GmshTools():
# https://forum.freecad.org/viewtopic.php?f=18&t=18780&p=149520#p149520
part = self.part_obj
if (
self.mesh_obj.MeshRegionList and part.Shape.ShapeType == "Compound"
self.mesh_obj.MeshRegionList
and part.Shape.ShapeType == "Compound"
and (
femutils.is_of_type(part, "FeatureBooleanFragments")
or femutils.is_of_type(part, "FeatureSlice")
@@ -490,8 +480,7 @@ class GmshTools():
" One element of the mesh refinement {} is "
"not an element of the Part to mesh.\n"
"But we are going to try to find it in "
"the Shape to mesh :-)\n"
.format(mr_obj.Name)
"the Shape to mesh :-)\n".format(mr_obj.Name)
)
search_ele_in_shape_to_mesh = True
for elems in sub[1]:
@@ -510,8 +499,9 @@ class GmshTools():
else:
Console.PrintError(
"One element of the meshregion {} could not be found "
"in the Part to mesh. It will be ignored.\n"
.format(mr_obj.Name)
"in the Part to mesh. It will be ignored.\n".format(
mr_obj.Name
)
)
# print(elems) # element
if elems not in self.ele_length_map:
@@ -521,20 +511,19 @@ class GmshTools():
else:
Console.PrintError(
"The element {} of the mesh refinement {} has "
"been added to another mesh region.\n"
.format(elems, mr_obj.Name)
"been added to another mesh region.\n".format(
elems, mr_obj.Name
)
)
else:
Console.PrintError(
"The mesh refinement: {} is not used to create the mesh "
"because the reference list is empty.\n"
.format(mr_obj.Name)
"because the reference list is empty.\n".format(mr_obj.Name)
)
else:
Console.PrintError(
"The mesh refinement: {} is not used to create the "
"mesh because the CharacteristicLength is 0.0 mm.\n"
.format(mr_obj.Name)
"mesh because the CharacteristicLength is 0.0 mm.\n".format(mr_obj.Name)
)
for eleml in self.ele_length_map:
# the method getElement(element) does not return Solid elements
@@ -574,8 +563,7 @@ class GmshTools():
" One element of the mesh boundary layer {} is "
"not an element of the Part to mesh.\n"
"But we are going to try to find it in "
"the Shape to mesh :-)\n"
.format(mr_obj.Name)
"the Shape to mesh :-)\n".format(mr_obj.Name)
)
search_ele_in_shape_to_mesh = True
for elems in sub[1]:
@@ -586,8 +574,7 @@ class GmshTools():
# the method getElement(element) does not return Solid elements
ele_shape = geomtools.get_element(sub[0], elems)
found_element = geomtools.find_element_in_shape(
self.part_obj.Shape,
ele_shape
self.part_obj.Shape, ele_shape
)
if found_element: # also
elems = found_element
@@ -595,8 +582,7 @@ class GmshTools():
Console.PrintError(
"One element of the mesh boundary layer {} could "
"not be found in the Part to mesh. "
"It will be ignored.\n"
.format(mr_obj.Name)
"It will be ignored.\n".format(mr_obj.Name)
)
# print(elems) # element
if elems not in self.bl_boundary_list:
@@ -608,24 +594,28 @@ class GmshTools():
Console.PrintError(
"The element {} of the mesh boundary "
"layer {} has been added "
"to another mesh boundary layer.\n"
.format(elems, mr_obj.Name)
"to another mesh boundary layer.\n".format(
elems, mr_obj.Name
)
)
setting = {}
setting["hwall_n"] = Units.Quantity(mr_obj.MinimumThickness).Value
setting["ratio"] = mr_obj.GrowthRate
setting["thickness"] = sum([
setting["hwall_n"] * setting["ratio"] ** i for i in range(
mr_obj.NumberOfLayers
)
])
setting["thickness"] = sum(
[
setting["hwall_n"] * setting["ratio"] ** i
for i in range(mr_obj.NumberOfLayers)
]
)
# setting["hwall_n"] * 5 # tangential cell dimension
setting["hwall_t"] = setting["thickness"]
# hfar: cell dimension outside boundary
# should be set later if some character length is set
if self.clmax > setting["thickness"] * 0.8 \
and self.clmax < setting["thickness"] * 1.6:
if (
self.clmax > setting["thickness"] * 0.8
and self.clmax < setting["thickness"] * 1.6
):
setting["hfar"] = self.clmax
else:
# set a value for safety, it may works as background mesh cell size
@@ -644,16 +634,14 @@ class GmshTools():
else:
Console.PrintError(
"The mesh boundary layer: {} is not used to create "
"the mesh because the reference list is empty.\n"
.format(mr_obj.Name)
"the mesh because the reference list is empty.\n".format(mr_obj.Name)
)
else:
Console.PrintError(
"The mesh boundary layer: {} is not used to create "
"the mesh because the min thickness is 0.0 mm.\n"
.format(mr_obj.Name)
"the mesh because the min thickness is 0.0 mm.\n".format(mr_obj.Name)
)
Console.PrintMessage(" {}\n".format(self.bl_setting_list))
Console.PrintMessage(f" {self.bl_setting_list}\n")
def write_groups(self, geo):
if self.group_elements:
@@ -670,19 +658,19 @@ class GmshTools():
if gdata[0].startswith("Solid"):
physical_type = "Volume"
for ele in gdata:
ele_nr += (ele.lstrip("Solid") + ", ")
ele_nr += ele.lstrip("Solid") + ", "
elif gdata[0].startswith("Face"):
physical_type = "Surface"
for ele in gdata:
ele_nr += (ele.lstrip("Face") + ", ")
ele_nr += ele.lstrip("Face") + ", "
elif gdata[0].startswith("Edge"):
physical_type = "Line"
for ele in gdata:
ele_nr += (ele.lstrip("Edge") + ", ")
ele_nr += ele.lstrip("Edge") + ", "
elif gdata[0].startswith("Vertex"):
physical_type = "Point"
for ele in gdata:
ele_nr += (ele.lstrip("Vertex") + ", ")
ele_nr += ele.lstrip("Vertex") + ", "
if ele_nr:
ele_nr = ele_nr.rstrip(", ")
# print(ele_nr)
@@ -690,8 +678,9 @@ class GmshTools():
curly_br_e = "}"
# explicit use double quotes in geo file
geo.write(
'Physical {}("{}") = {}{}{};\n'
.format(physical_type, group, curly_br_s, ele_nr, curly_br_e)
'Physical {}("{}") = {}{}{};\n'.format(
physical_type, group, curly_br_s, ele_nr, curly_br_e
)
)
geo.write("\n")
@@ -706,7 +695,7 @@ class GmshTools():
geo.write(prefix + " = BoundaryLayer;\n")
for k in item:
v = item[k]
if k in set(["EdgesList", "FacesList"]):
if k in {"EdgesList", "FacesList"}:
# the element name of FreeCAD which starts
# with 1 (example: "Face1"), same as Gmsh
# el_id = int(el[4:]) # FIXME: strip `face` or `edge` prefix
@@ -716,7 +705,7 @@ class GmshTools():
else:
line = prefix + "." + str(k) + " = " + str(v) + ";\n"
geo.write(line)
Console.PrintMessage("{}\n".format(line))
Console.PrintMessage(f"{line}\n")
geo.write("BoundaryLayer Field = " + str(field_number) + ";\n")
geo.write("// end of this boundary layer setup \n")
field_number += 1
@@ -749,7 +738,7 @@ class GmshTools():
geo.write("// open brep geometry\n")
# explicit use double quotes in geo file
geo.write('Merge "{}";\n'.format(os.path.relpath(self.temp_file_geometry, temp_dir)))
geo.write(f'Merge "{os.path.relpath(self.temp_file_geometry, temp_dir)}";\n')
geo.write("\n")
# groups
@@ -762,19 +751,15 @@ class GmshTools():
# we need to add 1 for the index in Gmsh
geo.write("// Characteristic Length according CharacteristicLengthMap\n")
for e in self.ele_length_map:
ele_nodes = (
"".join((str(n + 1) + ", ") for n in self.ele_node_map[e])
).rstrip(", ")
ele_nodes = ("".join((str(n + 1) + ", ") for n in self.ele_node_map[e])).rstrip(
", "
)
geo.write("// " + e + "\n")
elestr1 = "{"
elestr2 = "}"
geo.write(
"Characteristic Length {} {} {} = {};\n"
.format(
elestr1,
ele_nodes,
elestr2,
self.ele_length_map[e]
"Characteristic Length {} {} {} = {};\n".format(
elestr1, ele_nodes, elestr2, self.ele_length_map[e]
)
)
geo.write("\n")
@@ -795,8 +780,9 @@ class GmshTools():
if hasattr(self.mesh_obj, "MeshSizeFromCurvature"):
geo.write(
"Mesh.MeshSizeFromCurvature = {}"
"; // number of elements per 2*pi radians, 0 to deactivate\n"
.format(self.mesh_obj.MeshSizeFromCurvature)
"; // number of elements per 2*pi radians, 0 to deactivate\n".format(
self.mesh_obj.MeshSizeFromCurvature
)
)
geo.write("\n")
if hasattr(self.mesh_obj, "RecombineAll") and self.mesh_obj.RecombineAll is True:
@@ -805,9 +791,8 @@ class GmshTools():
if hasattr(self.mesh_obj, "Recombine3DAll") and self.mesh_obj.Recombine3DAll is True:
geo.write("// recombination for volumes\n")
geo.write("Mesh.Recombine3DAll = 1;\n")
if (
(hasattr(self.mesh_obj, "RecombineAll") and self.mesh_obj.RecombineAll is True)
or (hasattr(self.mesh_obj, "Recombine3DAll") and self.mesh_obj.Recombine3DAll is True)
if (hasattr(self.mesh_obj, "RecombineAll") and self.mesh_obj.RecombineAll is True) or (
hasattr(self.mesh_obj, "Recombine3DAll") and self.mesh_obj.Recombine3DAll is True
):
geo.write("// recombination algorithm\n")
geo.write("Mesh.RecombinationAlgorithm = " + self.RecombinationAlgorithm + ";\n")
@@ -874,9 +859,11 @@ class GmshTools():
geo.write("\n")
geo.write("// incomplete second order elements\n")
if (self.SubdivisionAlgorithm == "1"
or self.SubdivisionAlgorithm == "2"
or self.mesh_obj.RecombineAll):
if (
self.SubdivisionAlgorithm == "1"
or self.SubdivisionAlgorithm == "2"
or self.mesh_obj.RecombineAll
):
sec_order_inc = "1"
else:
sec_order_inc = "0"
@@ -889,8 +876,7 @@ class GmshTools():
if hasattr(self.mesh_obj, "CoherenceMesh") and self.mesh_obj.CoherenceMesh is True:
geo.write(
"Geometry.Tolerance = {}; // set geometrical "
"tolerance (also used for merging nodes)\n"
.format(self.geotol)
"tolerance (also used for merging nodes)\n".format(self.geotol)
)
geo.write("Mesh " + self.dimension + ";\n")
geo.write("Coherence Mesh; // Remove duplicate vertices\n")
@@ -906,11 +892,12 @@ class GmshTools():
# belongs to Mesh.SaveAll but only needed if there are groups
geo.write(
"// Needed for Group meshing too, because "
"for one material there is no group defined;\n")
"for one material there is no group defined;\n"
)
geo.write("// Ignore Physical definitions and save all elements;\n")
geo.write("Mesh.SaveAll = 1;\n")
# explicit use double quotes in geo file
geo.write('Save "{}";\n'.format(os.path.relpath(self.temp_file_mesh, temp_dir)))
geo.write(f'Save "{os.path.relpath(self.temp_file_mesh, temp_dir)}";\n')
geo.write("\n\n")
# some useful information
@@ -935,10 +922,7 @@ class GmshTools():
# print(command_list)
try:
p = subprocess.Popen(
command_list,
shell=False,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
command_list, shell=False, stdout=subprocess.PIPE, stderr=subprocess.PIPE
)
output, error = p.communicate()
error = error.decode("utf-8")
@@ -950,7 +934,7 @@ class GmshTools():
if os.path.exists(self.gmsh_bin):
error = "Error executing: {}\n".format(" ".join(command_list))
else:
error = "Gmsh executable not found: {}\n".format(self.gmsh_bin)
error = f"Gmsh executable not found: {self.gmsh_bin}\n"
Console.PrintError(error)
self.error = True
@@ -986,6 +970,7 @@ class GmshTools():
)
Console.PrintWarning(error_message + "\n")
## @}

View File

@@ -36,7 +36,7 @@ from femmesh import meshtools
from femtools.femutils import type_of_obj
class MeshSetsGetter():
class MeshSetsGetter:
def __init__(
self,
analysis_obj,
@@ -74,12 +74,9 @@ class MeshSetsGetter():
)
# ATM only used in meshtools.get_femelement_direction1D_set
# TODO somehow this is not smart, pur mesh objects might be used often
if (
self.member.geos_beamsection
and (
type_of_obj(self.solver_obj) == "Fem::SolverCcxTools"
or type_of_obj(self.solver_obj) == "Fem::SolverCalculix"
)
if self.member.geos_beamsection and (
type_of_obj(self.solver_obj) == "Fem::SolverCcxTools"
or type_of_obj(self.solver_obj) == "Fem::SolverCalculix"
):
FreeCAD.Console.PrintError(
"The mesh does not know the geometry it is made from. "
@@ -156,9 +153,7 @@ class MeshSetsGetter():
self.get_constraints_heatflux_faces()
setstime = round((time.process_time() - time_start), 3)
FreeCAD.Console.PrintMessage(
"Getting mesh data time: {} seconds.\n".format(setstime)
)
FreeCAD.Console.PrintMessage(f"Getting mesh data time: {setstime} seconds.\n")
# ********************************************************************************************
# ********************************************************************************************
@@ -170,27 +165,18 @@ class MeshSetsGetter():
for femobj in self.member.cons_fixed:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
# add nodes to constraint_conflict_nodes, needed by constraint plane rotation
for node in femobj["Nodes"]:
self.constraint_conflict_nodes.append(node)
# if mixed mesh with solids the node set needs to be split
# because solid nodes do not have rotational degree of freedom
if (
self.femmesh.Volumes
and (
len(self.member.geos_shellthickness) > 0
or len(self.member.geos_beamsection) > 0
)
if self.femmesh.Volumes and (
len(self.member.geos_shellthickness) > 0 or len(self.member.geos_beamsection) > 0
):
FreeCAD.Console.PrintMessage("We need to find the solid nodes.\n")
if not self.femelement_volumes_table:
self.femelement_volumes_table = meshtools.get_femelement_volumes_table(
self.femmesh
)
self.femelement_volumes_table = meshtools.get_femelement_volumes_table(self.femmesh)
for femobj in self.member.cons_fixed:
# femobj --> dict, FreeCAD document object is femobj["Object"]
nds_solid = []
@@ -214,10 +200,7 @@ class MeshSetsGetter():
for femobj in self.member.cons_rigidbody:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
# add nodes to constraint_conflict_nodes, needed by constraint plane rotation
for node in femobj["Nodes"]:
self.constraint_conflict_nodes.append(node)
@@ -229,10 +212,7 @@ class MeshSetsGetter():
for femobj in self.member.cons_displacement:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
# add nodes to constraint_conflict_nodes, needed by constraint plane rotation
for node in femobj["Nodes"]:
self.constraint_conflict_nodes.append(node)
@@ -244,10 +224,7 @@ class MeshSetsGetter():
for femobj in self.member.cons_planerotation:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
def get_constraints_transform_nodes(self):
if not self.member.cons_transform:
@@ -256,10 +233,7 @@ class MeshSetsGetter():
for femobj in self.member.cons_transform:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
def get_constraints_temperature_nodes(self):
if not self.member.cons_temperature:
@@ -268,10 +242,7 @@ class MeshSetsGetter():
for femobj in self.member.cons_temperature:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
def get_constraints_fluidsection_nodes(self):
if not self.member.geos_fluidsection:
@@ -280,10 +251,7 @@ class MeshSetsGetter():
for femobj in self.member.geos_fluidsection:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(
self.femmesh,
femobj
)
femobj["Nodes"] = meshtools.get_femnodes_by_femobj_with_references(self.femmesh, femobj)
def get_constraints_force_nodeloads(self):
if not self.member.cons_force:
@@ -297,9 +265,11 @@ class MeshSetsGetter():
" load on vertices --> The femelement_table "
"and femnodes_mesh are not needed for node load calculation.\n"
)
elif femobj["RefShapeType"] == "Face" \
and meshtools.is_solid_femmesh(self.femmesh) \
and not meshtools.has_no_face_data(self.femmesh):
elif (
femobj["RefShapeType"] == "Face"
and meshtools.is_solid_femmesh(self.femmesh)
and not meshtools.has_no_face_data(self.femmesh)
):
FreeCAD.Console.PrintLog(
" solid_mesh with face data --> The femelement_table is not "
"needed but the femnodes_mesh is needed for node load calculation.\n"
@@ -314,9 +284,7 @@ class MeshSetsGetter():
if not self.femnodes_mesh:
self.femnodes_mesh = self.femmesh.Nodes
if not self.femelement_table:
self.femelement_table = meshtools.get_femelement_table(
self.femmesh
)
self.femelement_table = meshtools.get_femelement_table(self.femmesh)
# get node loads
FreeCAD.Console.PrintLog(
" Finite element mesh nodes will be retrieved by searching "
@@ -334,20 +302,15 @@ class MeshSetsGetter():
FreeCAD.Console.PrintMessage(" Warning --> Force = 0\n")
if femobj["RefShapeType"] == "Vertex": # point load on vertices
femobj["NodeLoadTable"] = meshtools.get_force_obj_vertex_nodeload_table(
self.femmesh,
frc_obj
self.femmesh, frc_obj
)
elif femobj["RefShapeType"] == "Edge": # line load on edges
femobj["NodeLoadTable"] = meshtools.get_force_obj_edge_nodeload_table(
self.femmesh,
self.femelement_table,
self.femnodes_mesh, frc_obj
self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj
)
elif femobj["RefShapeType"] == "Face": # area load on faces
femobj["NodeLoadTable"] = meshtools.get_force_obj_face_nodeload_table(
self.femmesh,
self.femelement_table,
self.femnodes_mesh, frc_obj
self.femmesh, self.femelement_table, self.femnodes_mesh, frc_obj
)
# ********************************************************************************************
@@ -377,17 +340,14 @@ class MeshSetsGetter():
self.femelement_table = meshtools.get_femelement_table(self.femmesh)
if not self.femnodes_ele_table:
self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
self.femnodes_mesh,
self.femelement_table
self.femnodes_mesh, self.femelement_table
)
for femobj in self.member.cons_pressure:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
pressure_faces = meshtools.get_pressure_obj_faces(
self.femmesh,
self.femelement_table,
self.femnodes_ele_table, femobj
self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj
)
# the data model is for compatibility reason with deprecated version
# get_pressure_obj_faces_depreciated returns the face ids in a tuple per ref_shape
@@ -406,17 +366,14 @@ class MeshSetsGetter():
self.femelement_table = meshtools.get_femelement_table(self.femmesh)
if not self.femnodes_ele_table:
self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
self.femnodes_mesh,
self.femelement_table
self.femnodes_mesh, self.femelement_table
)
for femobj in self.member.cons_contact:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
contact_slave_faces, contact_master_faces = meshtools.get_contact_obj_faces(
self.femmesh,
self.femelement_table,
self.femnodes_ele_table, femobj
self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj
)
# [ele_id, ele_face_id], [ele_id, ele_face_id], ...]
# whereas the ele_face_id might be ccx specific
@@ -441,17 +398,14 @@ class MeshSetsGetter():
self.femelement_table = meshtools.get_femelement_table(self.femmesh)
if not self.femnodes_ele_table:
self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
self.femnodes_mesh,
self.femelement_table
self.femnodes_mesh, self.femelement_table
)
for femobj in self.member.cons_tie:
# femobj --> dict, FreeCAD document object is femobj["Object"]
print_obj_info(femobj["Object"])
slave_faces, master_faces = meshtools.get_tie_obj_faces(
self.femmesh,
self.femelement_table,
self.femnodes_ele_table, femobj
self.femmesh, self.femelement_table, self.femnodes_ele_table, femobj
)
# [ele_id, ele_face_id], [ele_id, ele_face_id], ...]
# whereas the ele_face_id might be ccx specific
@@ -471,8 +425,9 @@ class MeshSetsGetter():
if len(sectionprint_obj.References) > 1:
FreeCAD.Console.PrintError(
"Only one reference shape allowed for a section print "
"but {} found: {}\n"
.format(len(sectionprint_obj.References), sectionprint_obj.References)
"but {} found: {}\n".format(
len(sectionprint_obj.References), sectionprint_obj.References
)
)
for o, elem_tup in sectionprint_obj.References:
for elem in elem_tup:
@@ -485,22 +440,25 @@ class MeshSetsGetter():
femobj["SectionPrintFaces"] = v
# volume elements found
FreeCAD.Console.PrintLog(
"{}, surface {}, {} touching volume elements found\n"
.format(sectionprint_obj.Label, sectionprint_obj.Name, len(v))
"{}, surface {}, {} touching volume elements found\n".format(
sectionprint_obj.Label, sectionprint_obj.Name, len(v)
)
)
else:
# no volume elements found, shell elements not allowed
FreeCAD.Console.PrintError(
"{}, surface {}, Error: "
"No volume elements found!\n"
.format(sectionprint_obj.Label, sectionprint_obj.Name)
"No volume elements found!\n".format(
sectionprint_obj.Label, sectionprint_obj.Name
)
)
else:
# in Gui only Faces can be added
FreeCAD.Console.PrintError(
"Wrong reference shape type for {} "
"Only Faces are allowed, but a {} was found.\n"
.format(sectionprint_obj.Name, ref_shape.ShapeType)
"Only Faces are allowed, but a {} was found.\n".format(
sectionprint_obj.Name, ref_shape.ShapeType
)
)
def get_constraints_heatflux_faces(self):
@@ -522,7 +480,7 @@ class MeshSetsGetter():
for elem in elem_tup:
ho = o.Shape.getElement(elem)
if ho.ShapeType == "Face":
elem_info = "{}:{}".format(o.Name, elem)
elem_info = f"{o.Name}:{elem}"
face_table = self.mesh_object.FemMesh.getccxVolumesByFace(ho)
femobj["HeatFluxFaceTable"].append((elem_info, face_table))
@@ -560,10 +518,7 @@ class MeshSetsGetter():
# get element ids and write them into the femobj
all_found = False
if self.femmesh.GroupCount:
all_found = meshtools.get_femelement_sets_from_group_data(
self.femmesh,
femobjs
)
all_found = meshtools.get_femelement_sets_from_group_data(self.femmesh, femobjs)
FreeCAD.Console.PrintMessage(all_found)
FreeCAD.Console.PrintMessage("\n")
if all_found is False:
@@ -575,14 +530,10 @@ class MeshSetsGetter():
self.femnodes_mesh = self.femmesh.Nodes
if not self.femnodes_ele_table:
self.femnodes_ele_table = meshtools.get_femnodes_ele_table(
self.femnodes_mesh,
self.femelement_table
self.femnodes_mesh, self.femelement_table
)
control = meshtools.get_femelement_sets(
self.femmesh,
self.femelement_table,
femobjs,
self.femnodes_ele_table
self.femmesh, self.femelement_table, femobjs, self.femnodes_ele_table
)
# we only need to set it, if it is still True
if (self.femelement_count_test is True) and (control is False):
@@ -592,26 +543,18 @@ class MeshSetsGetter():
# get element ids and write them into the objects
FreeCAD.Console.PrintMessage("Shell thicknesses\n")
if not self.femelement_faces_table:
self.femelement_faces_table = meshtools.get_femelement_faces_table(
self.femmesh
)
self.femelement_faces_table = meshtools.get_femelement_faces_table(self.femmesh)
meshtools.get_femelement_sets(
self.femmesh,
self.femelement_faces_table,
self.member.geos_shellthickness
self.femmesh, self.femelement_faces_table, self.member.geos_shellthickness
)
def get_element_geometry1D_elements(self):
# get element ids and write them into the objects
FreeCAD.Console.PrintMessage("Beam sections\n")
if not self.femelement_edges_table:
self.femelement_edges_table = meshtools.get_femelement_edges_table(
self.femmesh
)
self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh)
meshtools.get_femelement_sets(
self.femmesh,
self.femelement_edges_table,
self.member.geos_beamsection
self.femmesh, self.femelement_edges_table, self.member.geos_beamsection
)
def get_element_rotation1D_elements(self):
@@ -624,27 +567,18 @@ class MeshSetsGetter():
)
return
if not self.femelement_edges_table:
self.femelement_edges_table = meshtools.get_femelement_edges_table(
self.femmesh
)
self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh)
meshtools.get_femelement_direction1D_set(
self.femmesh,
self.femelement_edges_table,
self.member.geos_beamrotation,
self.theshape
self.femmesh, self.femelement_edges_table, self.member.geos_beamrotation, self.theshape
)
def get_element_fluid1D_elements(self):
# get element ids and write them into the objects
FreeCAD.Console.PrintMessage("Fluid sections\n")
if not self.femelement_edges_table:
self.femelement_edges_table = meshtools.get_femelement_edges_table(
self.femmesh
)
self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh)
meshtools.get_femelement_sets(
self.femmesh,
self.femelement_edges_table,
self.member.geos_fluidsection
self.femmesh, self.femelement_edges_table, self.member.geos_fluidsection
)
def get_material_elements(self):
@@ -665,23 +599,15 @@ class MeshSetsGetter():
self.get_solid_element_sets(self.member.mats_linear)
if self.member.geos_shellthickness:
if not self.femelement_faces_table:
self.femelement_faces_table = meshtools.get_femelement_faces_table(
self.femmesh
)
self.femelement_faces_table = meshtools.get_femelement_faces_table(self.femmesh)
meshtools.get_femelement_sets(
self.femmesh,
self.femelement_faces_table,
self.member.mats_linear
self.femmesh, self.femelement_faces_table, self.member.mats_linear
)
if self.member.geos_beamsection or self.member.geos_fluidsection:
if not self.femelement_edges_table:
self.femelement_edges_table = meshtools.get_femelement_edges_table(
self.femmesh
)
self.femelement_edges_table = meshtools.get_femelement_edges_table(self.femmesh)
meshtools.get_femelement_sets(
self.femmesh,
self.femelement_edges_table,
self.member.mats_linear
self.femmesh, self.femelement_edges_table, self.member.mats_linear
)
def get_element_sets_material_and_femelement_geometry(self):
@@ -777,7 +703,7 @@ class MeshSetsGetter():
{"short": "M0"},
{"short": "B0"},
{"short": beamrot_data["ShortName"]},
{"short": "D" + str(i)}
{"short": "D" + str(i)},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -804,7 +730,7 @@ class MeshSetsGetter():
{"short": "M0"},
{"short": beamsec_data["ShortName"]},
{"short": beamrot_data["ShortName"]},
{"short": "D" + str(i)}
{"short": "D" + str(i)},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -830,7 +756,7 @@ class MeshSetsGetter():
{"short": mat_data["ShortName"]},
{"short": "B0"},
{"short": beamrot_data["ShortName"]},
{"short": "D" + str(i)}
{"short": "D" + str(i)},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -853,15 +779,15 @@ class MeshSetsGetter():
for i, beamdirection in enumerate(beamrot_data["FEMRotations1D"]):
beamdir_ids = set(beamdirection["ids"])
# empty intersection sets possible
elset_data = list(sorted(
beamsec_ids.intersection(mat_ids).intersection(beamdir_ids)
))
elset_data = list(
sorted(beamsec_ids.intersection(mat_ids).intersection(beamdir_ids))
)
if elset_data:
names = [
{"short": mat_data["ShortName"]},
{"short": beamsec_data["ShortName"]},
{"short": beamrot_data["ShortName"]},
{"short": "D" + str(i)}
{"short": "D" + str(i)},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -927,7 +853,7 @@ class MeshSetsGetter():
if elset_data:
names = [
{"short": mat_data["ShortName"]},
{"short": fluidsec_data["ShortName"]}
{"short": fluidsec_data["ShortName"]},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -942,10 +868,7 @@ class MeshSetsGetter():
mat_obj = self.member.mats_linear[0]["Object"]
shellth_obj = self.member.geos_shellthickness[0]["Object"]
elset_data = self.ccx_efaces
names = [
{"long": mat_obj.Name, "short": "M0"},
{"long": shellth_obj.Name, "short": "S0"}
]
names = [{"long": mat_obj.Name, "short": "M0"}, {"long": shellth_obj.Name, "short": "S0"}]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
matgeoset["ccx_elset_name"] = get_elset_name_standard(names)
@@ -961,7 +884,7 @@ class MeshSetsGetter():
elset_data = shellth_data["FEMElements"]
names = [
{"long": mat_obj.Name, "short": "M0"},
{"long": shellth_obj.Name, "short": shellth_data["ShortName"]}
{"long": shellth_obj.Name, "short": shellth_data["ShortName"]},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -978,7 +901,7 @@ class MeshSetsGetter():
elset_data = mat_data["FEMElements"]
names = [
{"long": mat_obj.Name, "short": mat_data["ShortName"]},
{"long": shellth_obj.Name, "short": "S0"}
{"long": shellth_obj.Name, "short": "S0"},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -1000,7 +923,7 @@ class MeshSetsGetter():
if elset_data:
names = [
{"long": mat_obj.Name, "short": mat_data["ShortName"]},
{"long": shellth_obj.Name, "short": shellth_data["ShortName"]}
{"long": shellth_obj.Name, "short": shellth_data["ShortName"]},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -1014,10 +937,7 @@ class MeshSetsGetter():
def get_mat_geo_sets_single_mat_solid(self):
mat_obj = self.member.mats_linear[0]["Object"]
elset_data = self.ccx_evolumes
names = [
{"long": mat_obj.Name, "short": "M0"},
{"long": "Solid", "short": "Solid"}
]
names = [{"long": mat_obj.Name, "short": "M0"}, {"long": "Solid", "short": "Solid"}]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
matgeoset["ccx_elset_name"] = get_elset_name_standard(names)
@@ -1032,7 +952,7 @@ class MeshSetsGetter():
elset_data = mat_data["FEMElements"]
names = [
{"long": mat_obj.Name, "short": mat_data["ShortName"]},
{"long": "Solid", "short": "Solid"}
{"long": "Solid", "short": "Solid"},
]
matgeoset = {}
matgeoset["ccx_elset"] = elset_data
@@ -1072,8 +992,7 @@ def get_elset_name_standard(names):
else:
error = (
"FEM: Trouble in elset name, because an "
"elset name is longer than 80 character! {}\n"
.format(elset_name)
"elset name is longer than 80 character! {}\n".format(elset_name)
)
raise Exception(error)
@@ -1089,22 +1008,18 @@ def get_elset_name_short(names):
else:
error = (
"FEM: Trouble in elset name, because an"
"short elset name is longer than 20 characters! {}\n"
.format(elset_name)
"short elset name is longer than 20 characters! {}\n".format(elset_name)
)
raise Exception(error)
def print_obj_info(obj, log=False):
if log is False:
FreeCAD.Console.PrintMessage("{}:\n".format(obj.Label))
FreeCAD.Console.PrintMessage(
" Type: {}, Name: {}\n".format(type_of_obj(obj), obj.Name)
)
FreeCAD.Console.PrintMessage(f"{obj.Label}:\n")
FreeCAD.Console.PrintMessage(f" Type: {type_of_obj(obj)}, Name: {obj.Name}\n")
else:
FreeCAD.Console.PrintLog("{}:\n".format(obj.Label))
FreeCAD.Console.PrintLog(
" Type: {}, Name: {}\n".format(type_of_obj(obj), obj.Name)
)
FreeCAD.Console.PrintLog(f"{obj.Label}:\n")
FreeCAD.Console.PrintLog(f" Type: {type_of_obj(obj)}, Name: {obj.Name}\n")
## @}

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2024 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
# * *
# * This file is part of FreeCAD. *
@@ -34,6 +34,7 @@ from . import base_fempythonobject
_PropHelper = base_fempythonobject._PropHelper
class BaseFemElement(base_fempythonobject.BaseFemPythonObject):
BaseType = "Fem::BaseFemElement"
@@ -44,16 +45,16 @@ class BaseFemElement(base_fempythonobject.BaseFemPythonObject):
for prop in self._get_properties():
prop.add_to_object(obj)
def _get_properties(self):
prop = []
prop.append(_PropHelper(
type = "App::PropertyLinkSubList",
name = "References",
group = "Element",
doc = "List of element shapes",
value = []
prop.append(
_PropHelper(
type="App::PropertyLinkSubList",
name="References",
group="Element",
doc="List of element shapes",
value=[],
)
)

View File

@@ -1,6 +1,6 @@
# SPDX-License-Identifier: LGPL-2.1-or-later
#/***************************************************************************
# /***************************************************************************
# * Copyright (c) 2024 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
# * *
# * This file is part of FreeCAD. *
@@ -34,6 +34,7 @@ from . import base_fempythonobject
_PropHelper = base_fempythonobject._PropHelper
class BaseFemMeshElement(base_fempythonobject.BaseFemPythonObject):
BaseType = "Fem::BaseFemMeshElement"
@@ -44,16 +45,16 @@ class BaseFemMeshElement(base_fempythonobject.BaseFemPythonObject):
for prop in self._get_properties():
prop.add_to_object(obj)
def _get_properties(self):
prop = []
prop.append(_PropHelper(
type = "App::PropertyLinkSubList",
name = "References",
group = "Mesh Element",
doc = "List of reference shapes",
value = []
prop.append(
_PropHelper(
type="App::PropertyLinkSubList",
name="References",
group="Mesh Element",
doc="List of reference shapes",
value=[],
)
)

View File

@@ -31,7 +31,7 @@ __url__ = "https://www.freecad.org"
# \brief base object for FEM Python Features
class BaseFemPythonObject(object):
class BaseFemPythonObject:
BaseType = "Fem::BaseFemPythonObject"
@@ -55,6 +55,7 @@ class _PropHelper:
Initialization keywords are the same used with PropertyContainer
to add dynamics properties plus "value" for the initial value.
"""
def __init__(self, **kwds):
self.value = kwds.pop("value")
self.info = kwds

View File

@@ -40,12 +40,12 @@ class ConstantVacuumPermittivity(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstantVacuumPermittivity"
def __init__(self, obj):
super(ConstantVacuumPermittivity, self).__init__(obj)
super().__init__(obj)
obj.addProperty(
"App::PropertyVacuumPermittivity",
"VacuumPermittivity",
"Constants",
"Overwrites default permittivity of vacuum"
"Overwrites default permittivity of vacuum",
)
obj.setPropertyStatus("VacuumPermittivity", "LockDynamic")
# we must set an expression so that the small value can actually be entered

View File

@@ -43,43 +43,44 @@ class ConstraintBodyHeatSource(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintBodyHeatSource"
def __init__(self, obj):
super(ConstraintBodyHeatSource, self).__init__(obj)
super().__init__(obj)
for prop in self._get_properties():
prop.add_to_object(obj)
def _get_properties(self):
prop = []
prop.append(_PropHelper(
type = "App::PropertyDissipationRate",
name = "DissipationRate",
group = "Constraint Body Heat Source",
doc = "Power dissipated per unit mass",
value = "0 W/kg"
prop.append(
_PropHelper(
type="App::PropertyDissipationRate",
name="DissipationRate",
group="Constraint Body Heat Source",
doc="Power dissipated per unit mass",
value="0 W/kg",
)
)
prop.append(_PropHelper(
type = "App::PropertyPower",
name = "TotalPower",
group = "Constraint Body Heat Source",
doc = "Total power dissipated",
value = "0 W"
prop.append(
_PropHelper(
type="App::PropertyPower",
name="TotalPower",
group="Constraint Body Heat Source",
doc="Total power dissipated",
value="0 W",
)
)
prop.append(_PropHelper(
type = "App::PropertyEnumeration",
name = "Mode",
group = "Constraint Body Heat Source",
doc = "Switch quantity input mode",
value = ["Dissipation Rate", "Total Power"]
prop.append(
_PropHelper(
type="App::PropertyEnumeration",
name="Mode",
group="Constraint Body Heat Source",
doc="Switch quantity input mode",
value=["Dissipation Rate", "Total Power"],
)
)
return prop
def onDocumentRestored(self, obj):
# update old project with new properties
for prop in self._get_properties():

View File

@@ -40,13 +40,13 @@ class ConstraintCentrif(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintCentrif"
def __init__(self, obj):
super(ConstraintCentrif, self).__init__(obj)
super().__init__(obj)
obj.addProperty(
"App::PropertyFrequency",
"RotationFrequency",
"Constraint CENTRIF",
"set rotation frequency f<sub>rot"
"set rotation frequency f<sub>rot",
)
obj.setPropertyStatus("RotationFrequency", "LockDynamic")
@@ -54,6 +54,6 @@ class ConstraintCentrif(base_fempythonobject.BaseFemPythonObject):
"App::PropertyLinkSubList",
"RotationAxis",
"Constraint CENTRIF",
"set line as axis of rotation"
"set line as axis of rotation",
)
obj.setPropertyStatus("RotationAxis", "LockDynamic")

View File

@@ -37,7 +37,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintCurrentDensity"
def __init__(self, obj):
super(ConstraintCurrentDensity, self).__init__(obj)
super().__init__(obj)
self.add_properties(obj)
def onDocumentRestored(self, obj):
@@ -49,7 +49,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_re_1",
"Vector Potential",
"Real part of current density x-component"
"Real part of current density x-component",
)
obj.setPropertyStatus("CurrentDensity_re_1", "LockDynamic")
obj.CurrentDensity_re_1 = "0 A/m^2"
@@ -58,7 +58,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_re_2",
"Vector Potential",
"Real part of current density y-component"
"Real part of current density y-component",
)
obj.setPropertyStatus("CurrentDensity_re_2", "LockDynamic")
obj.CurrentDensity_re_2 = "0 A/m^2"
@@ -67,7 +67,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_re_3",
"Vector Potential",
"Real part of current density z-component"
"Real part of current density z-component",
)
obj.setPropertyStatus("CurrentDensity_re_3", "LockDynamic")
obj.CurrentDensity_re_3 = "0 A/m^2"
@@ -76,7 +76,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_im_1",
"Vector Potential",
"Imaginary part of current density x-component"
"Imaginary part of current density x-component",
)
obj.setPropertyStatus("CurrentDensity_im_1", "LockDynamic")
obj.CurrentDensity_im_1 = "0 A/m^2"
@@ -85,7 +85,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_im_2",
"Vector Potential",
"Imaginary part of current density y-component"
"Imaginary part of current density y-component",
)
obj.setPropertyStatus("CurrentDensity_im_2", "LockDynamic")
obj.CurrentDensity_im_2 = "0 A/m^2"
@@ -94,7 +94,7 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyCurrentDensity",
"CurrentDensity_im_3",
"Vector Potential",
"Imaginary part of current density z-component"
"Imaginary part of current density z-component",
)
obj.setPropertyStatus("CurrentDensity_im_3", "LockDynamic")
obj.CurrentDensity_im_3 = "0 A/m^2"
@@ -102,55 +102,37 @@ class ConstraintCurrentDensity(base_fempythonobject.BaseFemPythonObject):
# now the enable bools
if not hasattr(obj, "CurrentDensity_re_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_re_1_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_re_1_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_re_1_Disabled", "LockDynamic")
obj.CurrentDensity_re_1_Disabled = True
if not hasattr(obj, "CurrentDensity_re_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_re_2_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_re_2_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_re_2_Disabled", "LockDynamic")
obj.CurrentDensity_re_2_Disabled = True
if not hasattr(obj, "CurrentDensity_re_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_re_3_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_re_3_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_re_3_Disabled", "LockDynamic")
obj.CurrentDensity_re_3_Disabled = True
if not hasattr(obj, "CurrentDensity_im_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_im_1_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_im_1_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_im_1_Disabled", "LockDynamic")
obj.CurrentDensity_im_1_Disabled = True
if not hasattr(obj, "CurrentDensity_im_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_im_2_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_im_2_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_im_2_Disabled", "LockDynamic")
obj.CurrentDensity_im_2_Disabled = True
if not hasattr(obj, "CurrentDensity_im_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"CurrentDensity_im_3_Disabled",
"Vector Potential",
""
"App::PropertyBool", "CurrentDensity_im_3_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("CurrentDensity_im_3_Disabled", "LockDynamic")
obj.CurrentDensity_im_3_Disabled = True

View File

@@ -39,7 +39,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
Type = "Fem::ConstraintElectrostaticPotential"
def __init__(self, obj):
super(ConstraintElectrostaticPotential, self).__init__(obj)
super().__init__(obj)
self.add_properties(obj)
def onDocumentRestored(self, obj):
@@ -48,10 +48,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
def add_properties(self, obj):
if not hasattr(obj, "Potential"):
obj.addProperty(
"App::PropertyElectricPotential",
"Potential",
"Parameter",
"Electric Potential"
"App::PropertyElectricPotential", "Potential", "Parameter", "Electric Potential"
)
obj.setPropertyStatus("Potential", "LockDynamic")
# setting 1 V assures that the unit does not switch to mV
@@ -63,7 +60,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_re_1",
"Vector Potential",
"Real part of potential x-component"
"Real part of potential x-component",
)
obj.setPropertyStatus("AV_re_1", "LockDynamic")
obj.AV_re_1 = "0 V"
@@ -72,7 +69,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_re_2",
"Vector Potential",
"Real part of potential y-component"
"Real part of potential y-component",
)
obj.setPropertyStatus("AV_re_2", "LockDynamic")
obj.AV_re_2 = "0 V"
@@ -81,7 +78,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_re_3",
"Vector Potential",
"Real part of potential z-component"
"Real part of potential z-component",
)
obj.setPropertyStatus("AV_re_3", "LockDynamic")
obj.AV_re_3 = "0 V"
@@ -90,7 +87,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_im",
"Vector Potential",
"Imaginary part of scalar potential"
"Imaginary part of scalar potential",
)
obj.setPropertyStatus("AV_im", "LockDynamic")
obj.AV_im = "0 V"
@@ -99,7 +96,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_im_1",
"Vector Potential",
"Imaginary part of potential x-component"
"Imaginary part of potential x-component",
)
obj.setPropertyStatus("AV_im_1", "LockDynamic")
obj.AV_im_1 = "0 V"
@@ -108,7 +105,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_im_2",
"Vector Potential",
"Imaginary part of potential y-component"
"Imaginary part of potential y-component",
)
obj.setPropertyStatus("AV_im_2", "LockDynamic")
obj.AV_im_2 = "0 V"
@@ -117,7 +114,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyElectricPotential",
"AV_im_3",
"Vector Potential",
"Imaginary part of potential z-component"
"Imaginary part of potential z-component",
)
obj.setPropertyStatus("AV_im_3", "LockDynamic")
obj.AV_im_3 = "0 V"
@@ -125,93 +122,49 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
# now the enable bools
if not hasattr(obj, "PotentialEnabled"):
obj.addProperty(
"App::PropertyBool",
"PotentialEnabled",
"Parameter",
"Potential Enabled"
"App::PropertyBool", "PotentialEnabled", "Parameter", "Potential Enabled"
)
obj.setPropertyStatus("PotentialEnabled", "LockDynamic")
obj.PotentialEnabled = True
if not hasattr(obj, "AV_re_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_re_1_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_re_1_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_re_1_Disabled", "LockDynamic")
obj.AV_re_1_Disabled = True
if not hasattr(obj, "AV_re_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_re_2_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_re_2_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_re_2_Disabled", "LockDynamic")
obj.AV_re_2_Disabled = True
if not hasattr(obj, "AV_re_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_re_3_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_re_3_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_re_3_Disabled", "LockDynamic")
obj.AV_re_3_Disabled = True
if not hasattr(obj, "AV_im_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_im_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_im_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_im_Disabled", "LockDynamic")
obj.AV_im_Disabled = True
if not hasattr(obj, "AV_im_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_im_1_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_im_1_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_im_1_Disabled", "LockDynamic")
obj.AV_im_1_Disabled = True
if not hasattr(obj, "AV_im_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_im_2_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_im_2_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_im_2_Disabled", "LockDynamic")
obj.AV_im_2_Disabled = True
if not hasattr(obj, "AV_im_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"AV_im_3_Disabled",
"Vector Potential",
""
)
obj.addProperty("App::PropertyBool", "AV_im_3_Disabled", "Vector Potential", "")
obj.setPropertyStatus("AV_im_3_Disabled", "LockDynamic")
obj.AV_im_3_Disabled = True
if not hasattr(obj, "PotentialConstant"):
obj.addProperty(
"App::PropertyBool",
"PotentialConstant",
"Parameter",
"Potential Constant"
"App::PropertyBool", "PotentialConstant", "Parameter", "Potential Constant"
)
obj.setPropertyStatus("PotentialConstant", "LockDynamic")
obj.PotentialConstant = False
if not hasattr(obj, "ElectricInfinity"):
obj.addProperty(
"App::PropertyBool",
"ElectricInfinity",
"Parameter",
"Electric Infinity"
"App::PropertyBool", "ElectricInfinity", "Parameter", "Electric Infinity"
)
obj.setPropertyStatus("ElectricInfinity", "LockDynamic")
obj.ElectricInfinity = False
@@ -221,17 +174,14 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyBool",
"ElectricForcecalculation",
"Parameter",
"Electric Force Calculation"
"Electric Force Calculation",
)
obj.setPropertyStatus("ElectricForcecalculation", "LockDynamic")
obj.ElectricForcecalculation = False
if not hasattr(obj, "CapacitanceBody"):
obj.addProperty(
"App::PropertyInteger",
"CapacitanceBody",
"Parameter",
"Capacitance Body"
"App::PropertyInteger", "CapacitanceBody", "Parameter", "Capacitance Body"
)
obj.setPropertyStatus("CapacitanceBody", "LockDynamic")
obj.CapacitanceBody = 0
@@ -241,7 +191,7 @@ class ConstraintElectrostaticPotential(base_fempythonobject.BaseFemPythonObject)
"App::PropertyBool",
"CapacitanceBodyEnabled",
"Parameter",
"Capacitance Body Enabled"
"Capacitance Body Enabled",
)
obj.setPropertyStatus("CapacitanceBodyEnabled", "LockDynamic")
obj.CapacitanceBodyEnabled = False

View File

@@ -39,26 +39,20 @@ class ConstraintFlowVelocity(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintFlowVelocity"
def __init__(self, obj):
super(ConstraintFlowVelocity, self).__init__(obj)
super().__init__(obj)
obj.addProperty(
"App::PropertyVelocity",
"VelocityX",
"Parameter",
"Velocity in x-direction"
"App::PropertyVelocity", "VelocityX", "Parameter", "Velocity in x-direction"
)
obj.setPropertyStatus("VelocityX", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityXFormula",
"Parameter",
"Velocity formula in x-direction"
"Velocity formula in x-direction",
)
obj.setPropertyStatus("VelocityXFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityXUnspecified",
"Parameter",
"Use velocity in x-direction"
"App::PropertyBool", "VelocityXUnspecified", "Parameter", "Use velocity in x-direction"
)
obj.setPropertyStatus("VelocityXUnspecified", "LockDynamic")
obj.VelocityXUnspecified = True
@@ -66,29 +60,23 @@ class ConstraintFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityXHasFormula",
"Parameter",
"Use formula for velocity in x-direction"
"Use formula for velocity in x-direction",
)
obj.setPropertyStatus("VelocityXHasFormula", "LockDynamic")
obj.addProperty(
"App::PropertyVelocity",
"VelocityY",
"Parameter",
"Velocity in y-direction"
"App::PropertyVelocity", "VelocityY", "Parameter", "Velocity in y-direction"
)
obj.setPropertyStatus("VelocityY", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityYFormula",
"Parameter",
"Velocity formula in y-direction"
"Velocity formula in y-direction",
)
obj.setPropertyStatus("VelocityYFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityYUnspecified",
"Parameter",
"Use velocity in y-direction"
"App::PropertyBool", "VelocityYUnspecified", "Parameter", "Use velocity in y-direction"
)
obj.setPropertyStatus("VelocityYUnspecified", "LockDynamic")
obj.VelocityYUnspecified = True
@@ -96,29 +84,23 @@ class ConstraintFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityYHasFormula",
"Parameter",
"Use formula for velocity in y-direction"
"Use formula for velocity in y-direction",
)
obj.setPropertyStatus("VelocityYHasFormula", "LockDynamic")
obj.addProperty(
"App::PropertyVelocity",
"VelocityZ",
"Parameter",
"Velocity in z-direction"
"App::PropertyVelocity", "VelocityZ", "Parameter", "Velocity in z-direction"
)
obj.setPropertyStatus("VelocityZ", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityZFormula",
"Parameter",
"Velocity formula in z-direction"
"Velocity formula in z-direction",
)
obj.setPropertyStatus("VelocityZFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityZUnspecified",
"Parameter",
"Use velocity in z-direction"
"App::PropertyBool", "VelocityZUnspecified", "Parameter", "Use velocity in z-direction"
)
obj.setPropertyStatus("VelocityZUnspecified", "LockDynamic")
obj.VelocityZUnspecified = True
@@ -126,14 +108,11 @@ class ConstraintFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityZHasFormula",
"Parameter",
"Use formula for velocity in z-direction"
"Use formula for velocity in z-direction",
)
obj.setPropertyStatus("VelocityZHasFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"NormalToBoundary",
"Parameter",
"Flow is in normal direction"
"App::PropertyBool", "NormalToBoundary", "Parameter", "Flow is in normal direction"
)
obj.setPropertyStatus("NormalToBoundary", "LockDynamic")

View File

@@ -38,26 +38,20 @@ class ConstraintInitialFlowVelocity(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintInitialFlowVelocity"
def __init__(self, obj):
super(ConstraintInitialFlowVelocity, self).__init__(obj)
super().__init__(obj)
obj.addProperty(
"App::PropertyVelocity",
"VelocityX",
"Parameter",
"Velocity in x-direction"
"App::PropertyVelocity", "VelocityX", "Parameter", "Velocity in x-direction"
)
obj.setPropertyStatus("VelocityX", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityXFormula",
"Parameter",
"Velocity formula in x-direction"
"Velocity formula in x-direction",
)
obj.setPropertyStatus("VelocityXFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityXUnspecified",
"Parameter",
"Use velocity in x-direction"
"App::PropertyBool", "VelocityXUnspecified", "Parameter", "Use velocity in x-direction"
)
obj.setPropertyStatus("VelocityXUnspecified", "LockDynamic")
obj.VelocityXUnspecified = True
@@ -65,29 +59,23 @@ class ConstraintInitialFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityXHasFormula",
"Parameter",
"Use formula for velocity in x-direction"
"Use formula for velocity in x-direction",
)
obj.setPropertyStatus("VelocityXHasFormula", "LockDynamic")
obj.addProperty(
"App::PropertyVelocity",
"VelocityY",
"Parameter",
"Velocity in y-direction"
"App::PropertyVelocity", "VelocityY", "Parameter", "Velocity in y-direction"
)
obj.setPropertyStatus("VelocityY", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityYFormula",
"Parameter",
"Velocity formula in y-direction"
"Velocity formula in y-direction",
)
obj.setPropertyStatus("VelocityYFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityYUnspecified",
"Parameter",
"Use velocity in y-direction"
"App::PropertyBool", "VelocityYUnspecified", "Parameter", "Use velocity in y-direction"
)
obj.setPropertyStatus("VelocityYUnspecified", "LockDynamic")
obj.VelocityYUnspecified = True
@@ -95,29 +83,23 @@ class ConstraintInitialFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityYHasFormula",
"Parameter",
"Use formula for velocity in y-direction"
"Use formula for velocity in y-direction",
)
obj.setPropertyStatus("VelocityYHasFormula", "LockDynamic")
obj.addProperty(
"App::PropertyVelocity",
"VelocityZ",
"Parameter",
"Velocity in z-direction"
"App::PropertyVelocity", "VelocityZ", "Parameter", "Velocity in z-direction"
)
obj.setPropertyStatus("VelocityZ", "LockDynamic")
obj.addProperty(
"App::PropertyString",
"VelocityZFormula",
"Parameter",
"Velocity formula in z-direction"
"Velocity formula in z-direction",
)
obj.setPropertyStatus("VelocityZFormula", "LockDynamic")
obj.addProperty(
"App::PropertyBool",
"VelocityZUnspecified",
"Parameter",
"Use velocity in z-direction"
"App::PropertyBool", "VelocityZUnspecified", "Parameter", "Use velocity in z-direction"
)
obj.setPropertyStatus("VelocityZUnspecified", "LockDynamic")
obj.VelocityZUnspecified = True
@@ -125,6 +107,6 @@ class ConstraintInitialFlowVelocity(base_fempythonobject.BaseFemPythonObject):
"App::PropertyBool",
"VelocityZHasFormula",
"Parameter",
"Use formula for velocity in z-direction"
"Use formula for velocity in z-direction",
)
obj.setPropertyStatus("VelocityZHasFormula", "LockDynamic")

View File

@@ -37,7 +37,7 @@ class ConstraintInitialPressure(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintInitialPressure"
def __init__(self, obj):
super(ConstraintInitialPressure, self).__init__(obj)
super().__init__(obj)
self.add_properties(obj)
def onDocumentRestored(self, obj):
@@ -45,12 +45,7 @@ class ConstraintInitialPressure(base_fempythonobject.BaseFemPythonObject):
def add_properties(self, obj):
if not hasattr(obj, "Pressure"):
obj.addProperty(
"App::PropertyPressure",
"Pressure",
"Parameter",
"Initial Pressure"
)
obj.addProperty("App::PropertyPressure", "Pressure", "Parameter", "Initial Pressure")
obj.setPropertyStatus("Pressure", "LockDynamic")
# we initialize 1 bar
obj.Pressure = "100 kPa"

View File

@@ -37,7 +37,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintMagnetization"
def __init__(self, obj):
super(ConstraintMagnetization, self).__init__(obj)
super().__init__(obj)
self.add_properties(obj)
def onDocumentRestored(self, obj):
@@ -49,7 +49,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_re_1",
"Vector Potential",
"Real part of magnetization x-component"
"Real part of magnetization x-component",
)
obj.setPropertyStatus("Magnetization_re_1", "LockDynamic")
obj.Magnetization_re_1 = "0 A/m"
@@ -58,7 +58,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_re_2",
"Vector Potential",
"Real part of magnetization y-component"
"Real part of magnetization y-component",
)
obj.setPropertyStatus("Magnetization_re_2", "LockDynamic")
obj.Magnetization_re_2 = "0 A/m"
@@ -67,7 +67,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_re_3",
"Vector Potential",
"Real part of magnetization z-component"
"Real part of magnetization z-component",
)
obj.setPropertyStatus("Magnetization_re_3", "LockDynamic")
obj.Magnetization_re_3 = "0 A/m"
@@ -76,7 +76,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_im_1",
"Vector Potential",
"Imaginary part of magnetization x-component"
"Imaginary part of magnetization x-component",
)
obj.setPropertyStatus("Magnetization_im_1", "LockDynamic")
obj.Magnetization_im_1 = "0 A/m"
@@ -85,7 +85,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_im_2",
"Vector Potential",
"Imaginary part of magnetization y-component"
"Imaginary part of magnetization y-component",
)
obj.setPropertyStatus("Magnetization_im_2", "LockDynamic")
obj.Magnetization_im_2 = "0 A/m"
@@ -94,7 +94,7 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
"App::PropertyMagnetization",
"Magnetization_im_3",
"Vector Potential",
"Imaginary part of magnetization z-component"
"Imaginary part of magnetization z-component",
)
obj.setPropertyStatus("Magnetization_im_3", "LockDynamic")
obj.Magnetization_im_3 = "0 A/m"
@@ -102,55 +102,37 @@ class ConstraintMagnetization(base_fempythonobject.BaseFemPythonObject):
# now the enable bools
if not hasattr(obj, "Magnetization_re_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_re_1_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_re_1_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_re_1_Disabled", "LockDynamic")
obj.Magnetization_re_1_Disabled = True
if not hasattr(obj, "Magnetization_re_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_re_2_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_re_2_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_re_2_Disabled", "LockDynamic")
obj.Magnetization_re_2_Disabled = True
if not hasattr(obj, "Magnetization_re_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_re_3_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_re_3_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_re_3_Disabled", "LockDynamic")
obj.Magnetization_re_3_Disabled = True
if not hasattr(obj, "Magnetization_im_1_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_im_1_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_im_1_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_im_1_Disabled", "LockDynamic")
obj.Magnetization_im_1_Disabled = True
if not hasattr(obj, "Magnetization_im_2_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_im_2_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_im_2_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_im_2_Disabled", "LockDynamic")
obj.Magnetization_im_2_Disabled = True
if not hasattr(obj, "Magnetization_im_3_Disabled"):
obj.addProperty(
"App::PropertyBool",
"Magnetization_im_3_Disabled",
"Vector Potential",
""
"App::PropertyBool", "Magnetization_im_3_Disabled", "Vector Potential", ""
)
obj.setPropertyStatus("Magnetization_im_3_Disabled", "LockDynamic")
obj.Magnetization_im_3_Disabled = True

View File

@@ -33,6 +33,7 @@ from . import base_fempythonobject
_PropHelper = base_fempythonobject._PropHelper
class ConstraintSectionPrint(base_fempythonobject.BaseFemPythonObject):
"""
The FemConstraintSectionPrint object
@@ -41,27 +42,26 @@ class ConstraintSectionPrint(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintSectionPrint"
def __init__(self, obj):
super(ConstraintSectionPrint, self).__init__(obj)
super().__init__(obj)
for prop in self._get_properties():
prop.add_to_object(obj)
def _get_properties(self):
prop = []
prop.append(_PropHelper(
type = "App::PropertyEnumeration",
name = "Variable",
group = "Constraint Section Print",
doc = "Set facial variable",
value = ["Section Force", "Heat Flux", "Drag Stress"]
prop.append(
_PropHelper(
type="App::PropertyEnumeration",
name="Variable",
group="Constraint Section Print",
doc="Set facial variable",
value=["Section Force", "Heat Flux", "Drag Stress"],
)
)
return prop
def onDocumentRestored(self, obj):
# update old project with new properties
for prop in self._get_properties():

View File

@@ -42,7 +42,7 @@ class ConstraintSelfWeight(base_fempythonobject.BaseFemPythonObject):
Type = "Fem::ConstraintSelfWeight"
def __init__(self, obj):
super(ConstraintSelfWeight, self).__init__(obj)
super().__init__(obj)
self.addProperty(obj)
@@ -53,17 +53,15 @@ class ConstraintSelfWeight(base_fempythonobject.BaseFemPythonObject):
obj.setEditorMode("References", 2) # do not show in Editor
def addProperty(self, obj):
obj.addProperty("App::PropertyAcceleration",
"GravityAcceleration",
"Gravity",
"Gravity acceleration")
obj.addProperty(
"App::PropertyAcceleration", "GravityAcceleration", "Gravity", "Gravity acceleration"
)
obj.setPropertyStatus("GravityAcceleration", "LockDynamic")
obj.GravityAcceleration = constants.gravity()
obj.addProperty("App::PropertyVector",
"GravityDirection",
"Gravity",
"Normalized gravity direction")
obj.addProperty(
"App::PropertyVector", "GravityDirection", "Gravity", "Normalized gravity direction"
)
obj.setPropertyStatus("GravityDirection", "LockDynamic")
obj.GravityDirection = FreeCAD.Vector(0, 0, -1)

Some files were not shown because too many files have changed in this diff Show More