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:
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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 "
|
||||
|
||||
57
src/Mod/Fem/femobjects/constraint_centrif.py
Normal file
57
src/Mod/Fem/femobjects/constraint_centrif.py
Normal 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"
|
||||
)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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"
|
||||
)
|
||||
|
||||
40
src/Mod/Fem/femviewprovider/view_constraint_centrif.py
Normal file
40
src/Mod/Fem/femviewprovider/view_constraint_centrif.py
Normal 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
|
||||
Reference in New Issue
Block a user