From dfbc90d3516f9be0763a54652066a64f6b3817a5 Mon Sep 17 00:00:00 2001 From: marioalexis Date: Thu, 8 Feb 2024 00:42:10 -0300 Subject: [PATCH] Fem: Add support for cyclic symmetry - fixes #12155 --- .../Fem/femobjects/base_fempythonobject.py | 16 ++++ src/Mod/Fem/femobjects/constraint_tie.py | 80 ++++++++++++++++--- .../calculix/write_constraint_tie.py | 37 ++++++++- 3 files changed, 116 insertions(+), 17 deletions(-) diff --git a/src/Mod/Fem/femobjects/base_fempythonobject.py b/src/Mod/Fem/femobjects/base_fempythonobject.py index 83f7008eb026..2428e051757b 100644 --- a/src/Mod/Fem/femobjects/base_fempythonobject.py +++ b/src/Mod/Fem/femobjects/base_fempythonobject.py @@ -47,3 +47,19 @@ def dumps(self): def loads(self, state): return None + + +class _PropHelper: + """ + Helper class to manage property data inside proxy objects. + 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 + self.name = kwds["name"] + + def add_to_object(self, obj): + obj.addProperty(**self.info) + setattr(obj, self.name, self.value) diff --git a/src/Mod/Fem/femobjects/constraint_tie.py b/src/Mod/Fem/femobjects/constraint_tie.py index c9836567062b..d6a5878c6d72 100644 --- a/src/Mod/Fem/femobjects/constraint_tie.py +++ b/src/Mod/Fem/femobjects/constraint_tie.py @@ -31,6 +31,10 @@ from . import base_fempythonobject +import FreeCAD + +_PropHelper = base_fempythonobject._PropHelper + class ConstraintTie(base_fempythonobject.BaseFemPythonObject): """ @@ -42,18 +46,68 @@ class ConstraintTie(base_fempythonobject.BaseFemPythonObject): def __init__(self, obj): super(ConstraintTie, self).__init__(obj) - obj.addProperty( - "App::PropertyLength", - "Tolerance", - "Geometry", - "Set max gap between tied faces" - ) - obj.Tolerance = "0.0 mm" + for prop in self._get_properties(): + prop.add_to_object(obj) - obj.addProperty( - "App::PropertyBool", - "Adjust", - "Geometry", - "Adjust connected nodes" + def _get_properties(self): + prop = [] + + prop.append(_PropHelper( + type = "App::PropertyLength", + name = "Tolerance", + group = "Geometry", + doc = "Set max gap between tied faces", + value = "0.0 mm" + ) + ) + prop.append(_PropHelper( + type = "App::PropertyBool", + name = "Adjust", + group = "Geometry", + doc = "Adjust connected nodes", + value = False + ) + ) + prop.append(_PropHelper( + type = "App::PropertyBool", + name = "CyclicSymmetry", + group = "Geometry", + doc = "Define cyclic symmetry model", + value = False + ) ) - obj.Adjust = False + prop.append(_PropHelper( + type = "App::PropertyPlacement", + name = "SymmetryAxis", + group = "Geometry", + doc = "Placement of axis of symmetry", + value = FreeCAD.Placement() + ) + ) + prop.append(_PropHelper( + type = "App::PropertyInteger", + name = "Sectors", + group = "Geometry", + doc = "Number of sectors", + value = 0 + ) + ) + prop.append(_PropHelper( + type = "App::PropertyInteger", + name = "ConnectedSectors", + group = "Geometry", + doc = "Number of connected sectors", + value = 1 + ) + ) + + return prop + + + def onDocumentRestored(self, obj): + # update old proyect with new properties + for prop in self._get_properties(): + try: + obj.getPropertyByName(prop.name) + except: + prop.add_to_object(obj) diff --git a/src/Mod/Fem/femsolver/calculix/write_constraint_tie.py b/src/Mod/Fem/femsolver/calculix/write_constraint_tie.py index c75ab90be38a..a9d35893c8b3 100644 --- a/src/Mod/Fem/femsolver/calculix/write_constraint_tie.py +++ b/src/Mod/Fem/femsolver/calculix/write_constraint_tie.py @@ -26,6 +26,9 @@ __url__ = "https://www.freecad.org" +from FreeCAD import Units, Vector + + def get_analysis_types(): return "all" # write for all analysis types @@ -71,12 +74,38 @@ def write_constraint(f, femobj, tie_obj, ccxwriter): tolerance = tie_obj.Tolerance.getValueAs("mm").Value adjust = "" + symmetry = "" + tie_name = tie_obj.Name if not tie_obj.Adjust: adjust = ", ADJUST=NO" + + if tie_obj.CyclicSymmetry: + symmetry = ", CYCLIC SYMMETRY" + f.write( - "*TIE, POSITION TOLERANCE={:.13G}{}, NAME=TIE{}\n" - .format(tolerance, adjust, tie_obj.Name) + "*TIE, POSITION TOLERANCE={:.13G}{}{}, NAME=TIE{}\n" + .format(tolerance, adjust, symmetry, tie_name) ) - ind_surf = "TIE_IND{}".format(tie_obj.Name) - dep_surf = "TIE_DEP{}".format(tie_obj.Name) + ind_surf = "TIE_IND{}".format(tie_name) + dep_surf = "TIE_DEP{}".format(tie_name) f.write("{}, {}\n".format(dep_surf, ind_surf)) + + # write CYCLIC SYMMETRY MODEL card + if tie_obj.CyclicSymmetry: + f.write( + "*CYCLIC SYMMETRY MODEL, N={}, NGRAPH={}, TIE=TIE{}, ELSET=Eall\n" + .format(tie_obj.Sectors, tie_obj.ConnectedSectors, tie_name) + ) + + # get symmetry axis points + vec_a = tie_obj.SymmetryAxis.Base + vec_b = tie_obj.SymmetryAxis * Vector(0, 0, 1) + + set_unit = lambda x: Units.Quantity(x, Units.Length).getValueAs("mm").Value + point_a = [set_unit(coord) for coord in vec_a] + point_b = [set_unit(coord) for coord in vec_b] + + f.write( + "{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G}\n" + .format(*point_a, *point_b) + )