FEM: constraint centrif, App objects and methods:

- CalculiX centrifugal body loads
- CalculiX label CENTRIF from *DLOAD card
- implement FreeCAD NonGui code
- the object, ccx writer, etc
This commit is contained in:
UR-0
2021-06-23 07:55:52 +02:00
committed by Bernd Hahnebach
parent 8279d687fb
commit cc97865141
9 changed files with 244 additions and 1 deletions

View File

@@ -139,6 +139,7 @@ SET(FemObjects_SRCS
femobjects/base_fempythonobject.py
femobjects/constant_vacuumpermittivity.py
femobjects/constraint_bodyheatsource.py
femobjects/constraint_centrif.py
femobjects/constraint_electrostaticpotential.py
femobjects/constraint_flowvelocity.py
femobjects/constraint_initialflowvelocity.py
@@ -493,6 +494,7 @@ SET(FemGuiViewProvider_SRCS
femviewprovider/view_base_femobject.py
femviewprovider/view_constant_vacuumpermittivity.py
femviewprovider/view_constraint_bodyheatsource.py
femviewprovider/view_constraint_centrif.py
femviewprovider/view_constraint_electrostaticpotential.py
femviewprovider/view_constraint_flowvelocity.py
femviewprovider/view_constraint_initialflowvelocity.py

View File

@@ -98,6 +98,21 @@ def makeConstraintBodyHeatSource(
return obj
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 makeConstraintContact(
doc,
name="ConstraintContact"

View File

@@ -734,6 +734,7 @@ def get_elset_short_name(
obj,
i
):
# ATM for CalculiX needed for all objects which will write element sets into solver input file
from femtools.femutils import is_of_type
if is_of_type(obj, "Fem::MaterialCommon"):
return "M" + str(i)
@@ -745,6 +746,8 @@ def get_elset_short_name(
return "F" + str(i)
elif is_of_type(obj, "Fem::ElementGeometry2D"):
return "S" + str(i)
elif is_of_type(obj, "Fem::ConstraintCentrif"):
return "C" + str(i)
else:
FreeCAD.Console.PrintError(
"Error in creating short elset name "

View File

@@ -0,0 +1,57 @@
# ***************************************************************************
# * Copyright (c) 2021 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM constraint centrif document object"
__author__ = "Bernd Hahnebach"
__url__ = "https://www.freecadweb.org"
## @package constraint_centrif
# \ingroup FEM
# \brief constraint centrif object
from . import base_fempythonobject
class ConstraintCentrif(base_fempythonobject.BaseFemPythonObject):
"""
The ConstraintCentrif object
"""
Type = "Fem::ConstraintCentrif"
def __init__(self, obj):
super(ConstraintCentrif, self).__init__(obj)
obj.addProperty(
"App::PropertyFrequency",
"RotationFrequency",
"Constraint CENTRIF",
"set rotation frequency f<sub>rot"
)
obj.addProperty(
"App::PropertyLinkSubList",
"RotationAxis",
"Constraint CENTRIF",
"set line as axis of rotation"
)

View File

@@ -31,6 +31,7 @@ __url__ = "https://www.freecadweb.org"
# import io
import codecs
import math
import os
import six
import sys
@@ -150,6 +151,9 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
# some fluidsection objs need special treatment, ccx_elsets are needed for this
inpfile_main = self.handle_fluidsection_liquid_inlet_outlet(inpfile_main)
# element sets constraints
self.write_element_sets_constraints_centrif(inpfile_main)
# node sets and surface sets
self.write_node_sets_constraints_fixed(inpfile_main)
self.write_node_sets_constraints_displacement(inpfile_main)
@@ -180,6 +184,7 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
self.write_constraints_displacement(inpfile_main)
self.write_constraints_sectionprint(inpfile_main)
self.write_constraints_selfweight(inpfile_main)
self.write_constraints_centrif(inpfile_main)
self.write_constraints_force(inpfile_main)
self.write_constraints_pressure(inpfile_main)
self.write_constraints_temperature(inpfile_main)
@@ -791,6 +796,77 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
# different element sets for different density
# are written in the material element sets already
# ********************************************************************************************
# constraints centrif
def write_element_sets_constraints_centrif(self, f):
self.write_constraints_sets(
f,
femobjs=self.centrif_objects,
analysis_types=["buckling", "static", "thermomech"],
sets_getter_method=self.get_constraints_centrif_elements,
write_name="constraints_centrif_element_sets",
sets_writer_method=self.write_element_sets_elements_constraints_centrif,
caller_method_name=sys._getframe().f_code.co_name,
)
def write_constraints_centrif(self, f):
self.write_constraints_data(
f,
femobjs=self.centrif_objects,
analysis_types="all", # write for all analysis types
constraint_title_name="Centrif Constraints",
constraint_writer_method=self.constraint_centrif_writer,
caller_method_name=sys._getframe().f_code.co_name,
)
def write_element_sets_elements_constraints_centrif(self, f, femobj, centrif_obj):
f.write("*ELSET,ELSET={}\n".format(centrif_obj.Name))
# use six to be sure to be Python 2.7 and 3.x compatible
if isinstance(femobj["FEMElements"], six.string_types):
f.write("{}\n".format(femobj["FEMElements"]))
else:
for e in femobj["FEMElements"]:
f.write("{},\n".format(e))
def constraint_centrif_writer(self, f, femobj, centrif_obj):
# get some data from the centrif_obj
refobj = centrif_obj.RotationAxis[0][0]
subobj = centrif_obj.RotationAxis[0][1][0]
axis = refobj.Shape.getElement(subobj)
if axis.Curve.TypeId == "Part::GeomLine":
axiscopy = axis.copy() # apply global placement to copy
axiscopy.Placement = refobj.getGlobalPlacement()
direction = axiscopy.Curve.Direction
location = axiscopy.Curve.Location
else: # no line found, set default
# TODO: No test at all in the writer
# they should all be before in prechecks
location = FreeCAD.Vector(0., 0., 0.)
direction = FreeCAD.Vector(0., 0., 1.)
# write to file
f.write("*DLOAD\n")
# Why {:.13G} ...
# ccx uses F20.0 FORTRAN input fields, see in dload.f in ccx's source
# https://forum.freecadweb.org/viewtopic.php?f=18&t=22759&#p176578
# example "{:.13G}".format(math.sqrt(2.)*-1e100) and count chars
f.write(
"{},CENTRIF,{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G},{:.13G}\n"
.format(
centrif_obj.Name,
(2. * math.pi * float(centrif_obj.RotationFrequency.getValueAs("1/s"))) ** 2,
location.x,
location.y,
location.z,
direction.x,
direction.y,
direction.z
)
)
f.write("\n")
# ********************************************************************************************
# constraints force
def write_constraints_force(self, f):
@@ -1304,6 +1380,8 @@ class FemInputWriterCcx(writerbase.FemInputWriter):
return True
if self.analysis_type == "thermomech" and not self.solver_obj.ThermoMechSteadyState:
return True
if self.centrif_objects:
return True
if self.selfweight_objects:
return True
return False

View File

@@ -60,6 +60,7 @@ class FemInputWriter():
self.fluidsection_objects = member.geos_fluidsection
self.shellthickness_objects = member.geos_shellthickness
# constraints
self.centrif_objects = member.cons_centrif
self.contact_objects = member.cons_contact
self.displacement_objects = member.cons_displacement
self.fixed_objects = member.cons_fixed
@@ -456,9 +457,20 @@ class FemInputWriter():
face_table = self.mesh_object.FemMesh.getccxVolumesByFace(ho)
femobj["HeatFluxFaceTable"].append((elem_info, face_table))
# ********************************************************************************************
# ********************************************************************************************
# element sets
# element sets constraints
def get_constraints_centrif_elements(self):
# get element ids and write them into the femobj
if len(self.centrif_objects) == 1 and not self.centrif_objects[0]["Object"].References:
self.centrif_objects[0]["FEMElements"] = self.ccx_evolumes
else:
self.get_solid_element_sets(self.centrif_objects)
# ********************************************************************************************
# ********************************************************************************************
# element sets material and element geometry
def get_solid_element_sets(self, femobjs):
# get element ids and write them into the femobj
all_found = False

View File

@@ -233,6 +233,10 @@ class TestObjectType(unittest.TestCase):
"Fem::ConstraintSelfWeight",
type_of_obj(ObjectsFem.makeConstraintSelfWeight(doc))
)
self.assertEqual(
"Fem::ConstraintCentrif",
type_of_obj(ObjectsFem.makeConstraintCentrif(doc))
)
self.assertEqual(
"Fem::ConstraintTemperature",
type_of_obj(ObjectsFem.makeConstraintTemperature(doc))
@@ -442,6 +446,10 @@ class TestObjectType(unittest.TestCase):
ObjectsFem.makeConstraintSelfWeight(doc),
"Fem::ConstraintSelfWeight"
))
self.assertTrue(is_of_type(
ObjectsFem.makeConstraintCentrif(doc),
"Fem::ConstraintCentrif"
))
self.assertTrue(is_of_type(
ObjectsFem.makeConstraintTemperature(doc),
"Fem::ConstraintTemperature"
@@ -871,6 +879,21 @@ class TestObjectType(unittest.TestCase):
"Fem::ConstraintSelfWeight"
))
# ConstraintCentrif
constraint_centrif = ObjectsFem.makeConstraintCentrif(doc)
self.assertTrue(is_derived_from(
constraint_centrif,
"App::DocumentObject"
))
self.assertTrue(is_derived_from(
constraint_centrif,
"Fem::ConstraintPython"
))
self.assertTrue(is_derived_from(
constraint_centrif,
"Fem::ConstraintCentrif"
))
# ConstraintTemperature
constraint_temperature = ObjectsFem.makeConstraintTemperature(doc)
self.assertTrue(is_derived_from(
@@ -1415,6 +1438,11 @@ class TestObjectType(unittest.TestCase):
doc
).isDerivedFrom("Fem::ConstraintPython")
)
self.assertTrue(
ObjectsFem.makeConstraintCentrif(
doc
).isDerivedFrom("Fem::ConstraintPython")
)
self.assertTrue(
ObjectsFem.makeConstraintTemperature(
doc
@@ -1595,6 +1623,7 @@ def create_all_fem_objects_doc(
analysis.addObject(ObjectsFem.makeConstraintPulley(doc))
analysis.addObject(ObjectsFem.makeConstraintSectionPrint(doc))
analysis.addObject(ObjectsFem.makeConstraintSelfWeight(doc))
analysis.addObject(ObjectsFem.makeConstraintCentrif(doc))
analysis.addObject(ObjectsFem.makeConstraintTemperature(doc))
analysis.addObject(ObjectsFem.makeConstraintTie(doc))
analysis.addObject(ObjectsFem.makeConstraintTransform(doc))

View File

@@ -188,6 +188,10 @@ class AnalysisMember():
[{"Object":shell_thickness_obj, "xxxxxxxx":value}, {}, ...]
constraints:
constraints_centrif : list of dictionaries
list of centrifs for the analysis.
[{"Object":centrif_obj, "xxxxxxxx":value}, {}, ...]
constraints_contact : list of dictionaries
list of contact constraints from the analysis.
[{"Object":contact_obj, "xxxxxxxx":value}, {}, ...]
@@ -275,6 +279,9 @@ class AnalysisMember():
)
# constraints
self.cons_centrif = self.get_several_member(
"Fem::ConstraintCentrif"
)
self.cons_contact = self.get_several_member(
"Fem::ConstraintContact"
)

View File

@@ -0,0 +1,40 @@
# ***************************************************************************
# * Copyright (c) 2021 Bernd Hahnebach <bernd@bimstatik.org> *
# * *
# * This file is part of the FreeCAD CAx development system. *
# * *
# * This program is free software; you can redistribute it and/or modify *
# * it under the terms of the GNU Lesser General Public License (LGPL) *
# * as published by the Free Software Foundation; either version 2 of *
# * the License, or (at your option) any later version. *
# * for detail see the LICENCE text file. *
# * *
# * This program is distributed in the hope that it will be useful, *
# * but WITHOUT ANY WARRANTY; without even the implied warranty of *
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
# * GNU Library General Public License for more details. *
# * *
# * You should have received a copy of the GNU Library General Public *
# * License along with this program; if not, write to the Free Software *
# * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 *
# * USA *
# * *
# ***************************************************************************
__title__ = "FreeCAD FEM constraint centrif ViewProvider for the document object"
__author__ = "Bernd Hahnebach"
__url__ = "https://www.freecadweb.org"
## @package view_constraint_centrif
# \ingroup FEM
# \brief view provider for constraint centrif object
from . import view_base_femconstraint
class VPConstraintCentrif(view_base_femconstraint.VPBaseFemConstraint):
"""
A View Provider for the ConstraintCentrif object
"""
pass