Skip to content

Commit 10a6414

Browse files
committed
Fem: Add support for cyclic symmetry - fixes FreeCAD#12155
1 parent 31b40ce commit 10a6414

File tree

3 files changed

+116
-17
lines changed

3 files changed

+116
-17
lines changed

src/Mod/Fem/femobjects/base_fempythonobject.py

+16
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,19 @@ def dumps(self):
4747

4848
def loads(self, state):
4949
return None
50+
51+
52+
class _PropHelper:
53+
"""
54+
Helper class to manage property data inside proxy objects.
55+
Initialization keywords are the same used with PropertyContainer
56+
to add dynamics properties plus "value" for the initial value.
57+
"""
58+
def __init__(self, **kwds):
59+
self.value = kwds.pop("value")
60+
self.info = kwds
61+
self.name = kwds["name"]
62+
63+
def add_to_object(self, obj):
64+
obj.addProperty(**self.info)
65+
setattr(obj, self.name, self.value)

src/Mod/Fem/femobjects/constraint_tie.py

+67-13
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,10 @@
3131

3232
from . import base_fempythonobject
3333

34+
import FreeCAD
35+
36+
_PropHelper = base_fempythonobject._PropHelper
37+
3438

3539
class ConstraintTie(base_fempythonobject.BaseFemPythonObject):
3640
"""
@@ -42,18 +46,68 @@ class ConstraintTie(base_fempythonobject.BaseFemPythonObject):
4246
def __init__(self, obj):
4347
super(ConstraintTie, self).__init__(obj)
4448

45-
obj.addProperty(
46-
"App::PropertyLength",
47-
"Tolerance",
48-
"Geometry",
49-
"Set max gap between tied faces"
50-
)
51-
obj.Tolerance = "0.0 mm"
49+
for prop in self._get_properties():
50+
prop.add_to_object(obj)
5251

53-
obj.addProperty(
54-
"App::PropertyBool",
55-
"Adjust",
56-
"Geometry",
57-
"Adjust connected nodes"
52+
def _get_properties(self):
53+
prop = []
54+
55+
prop.append(_PropHelper(
56+
type = "App::PropertyLength",
57+
name = "Tolerance",
58+
group = "Geometry",
59+
doc = "Set max gap between tied faces",
60+
value = "0.0 mm"
61+
)
62+
)
63+
prop.append(_PropHelper(
64+
type = "App::PropertyBool",
65+
name = "Adjust",
66+
group = "Geometry",
67+
doc = "Adjust connected nodes",
68+
value = False
69+
)
70+
)
71+
prop.append(_PropHelper(
72+
type = "App::PropertyBool",
73+
name = "CyclicSymmetry",
74+
group = "Geometry",
75+
doc = "Define cyclic symmetry model",
76+
value = False
77+
)
5878
)
59-
obj.Adjust = False
79+
prop.append(_PropHelper(
80+
type = "App::PropertyPlacement",
81+
name = "SymmetryAxis",
82+
group = "Geometry",
83+
doc = "Placement of axis of symmetry",
84+
value = FreeCAD.Placement()
85+
)
86+
)
87+
prop.append(_PropHelper(
88+
type = "App::PropertyInteger",
89+
name = "Sectors",
90+
group = "Geometry",
91+
doc = "Number of sectors",
92+
value = 0
93+
)
94+
)
95+
prop.append(_PropHelper(
96+
type = "App::PropertyInteger",
97+
name = "ConnectedSectors",
98+
group = "Geometry",
99+
doc = "Number of connected sectors",
100+
value = 1
101+
)
102+
)
103+
104+
return prop
105+
106+
107+
def onDocumentRestored(self, obj):
108+
# update old proyect with new properties
109+
for prop in self._get_properties():
110+
try:
111+
obj.getPropertyByName(prop.name)
112+
except:
113+
prop.add_to_object(obj)

src/Mod/Fem/femsolver/calculix/write_constraint_tie.py

+33-4
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@
2626
__url__ = "https://www.freecad.org"
2727

2828

29+
from FreeCAD import Units, Vector
30+
31+
2932
def get_analysis_types():
3033
return "all" # write for all analysis types
3134

@@ -71,12 +74,38 @@ def write_constraint(f, femobj, tie_obj, ccxwriter):
7174

7275
tolerance = tie_obj.Tolerance.getValueAs("mm").Value
7376
adjust = ""
77+
symmetry = ""
78+
tie_name = tie_obj.Name
7479
if not tie_obj.Adjust:
7580
adjust = ", ADJUST=NO"
81+
82+
if tie_obj.CyclicSymmetry:
83+
symmetry = ", CYCLIC SYMMETRY"
84+
7685
f.write(
77-
"*TIE, POSITION TOLERANCE={:.13G}{}, NAME=TIE{}\n"
78-
.format(tolerance, adjust, tie_obj.Name)
86+
"*TIE, POSITION TOLERANCE={:.13G}{}{}, NAME=TIE{}\n"
87+
.format(tolerance, adjust, symmetry, tie_name)
7988
)
80-
ind_surf = "TIE_IND{}".format(tie_obj.Name)
81-
dep_surf = "TIE_DEP{}".format(tie_obj.Name)
89+
ind_surf = "TIE_IND{}".format(tie_name)
90+
dep_surf = "TIE_DEP{}".format(tie_name)
8291
f.write("{}, {}\n".format(dep_surf, ind_surf))
92+
93+
# write CYCLIC SYMMETRY MODEL card
94+
if tie_obj.CyclicSymmetry:
95+
f.write(
96+
"*CYCLIC SYMMETRY MODEL, N={}, NGRAPH={}, TIE=TIE{}, ELSET=Eall\n"
97+
.format(tie_obj.Sectors, tie_obj.ConnectedSectors, tie_name)
98+
)
99+
100+
# get symmetry axis points
101+
vec_a = tie_obj.SymmetryAxis.Base
102+
vec_b = tie_obj.SymmetryAxis * Vector(0, 0, 1)
103+
104+
set_unit = lambda x: Units.Quantity(x, Units.Length).getValueAs("mm").Value
105+
point_a = [set_unit(coord) for coord in vec_a]
106+
point_b = [set_unit(coord) for coord in vec_b]
107+
108+
f.write(
109+
"{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G}\n"
110+
.format(*point_a, *point_b)
111+
)

0 commit comments

Comments
 (0)