FEM: Add support for CalculiX truss elements (#23224)
* FEM: Update element_geometry1D.py * FEM: Update write_femelement_geometry.py * FEM: Update write_mesh.py * FEM: Update solver.py * FEM: Update solver_calculix.py * FEM: Update element_geometry1D.py
This commit is contained in:
@@ -175,7 +175,16 @@ class ElementGeometry1D(base_femelement.BaseFemElement):
|
||||
value=["Rectangular", "Circular", "Pipe", "Elliptical", "Box"],
|
||||
)
|
||||
)
|
||||
|
||||
prop.append(
|
||||
_PropHelper(
|
||||
type="App::PropertyArea",
|
||||
name="TrussArea",
|
||||
group="TrussSection",
|
||||
doc="Set cross-sectional area of truss elements\n"
|
||||
+ "(used if bending stiffness is excluded in the solver)",
|
||||
value=10.0,
|
||||
)
|
||||
)
|
||||
return prop
|
||||
|
||||
def onDocumentRestored(self, obj):
|
||||
|
||||
@@ -326,7 +326,7 @@ class SolverCalculiX(base_fempythonobject.BaseFemPythonObject):
|
||||
type="App::PropertyBool",
|
||||
name="ExcludeBendingStiffness",
|
||||
group="Solver",
|
||||
doc="Exclude bending stiffness to replace shells with membranes",
|
||||
doc="Exclude bending stiffness to replace shells with membranes or beams with trusses",
|
||||
value=False,
|
||||
)
|
||||
)
|
||||
|
||||
@@ -428,7 +428,7 @@ class _BaseSolverCalculix:
|
||||
"App::PropertyBool",
|
||||
"ExcludeBendingStiffness",
|
||||
"Fem",
|
||||
"Exclude bending stiffness to replace shells with membranes",
|
||||
"Exclude bending stiffness to replace shells with membranes or beams with trusses",
|
||||
locked=True,
|
||||
)
|
||||
obj.ExcludeBendingStiffness = False
|
||||
|
||||
@@ -45,52 +45,58 @@ def write_femelement_geometry(f, ccxwriter):
|
||||
section_nor = "{:.13G}, {:.13G}, {:.13G}\n".format(
|
||||
beam_axis_m[0], beam_axis_m[1], beam_axis_m[2]
|
||||
)
|
||||
if beamsec_obj.SectionType == "Rectangular":
|
||||
# see meshtools.get_beam_main_axis_m(beam_direction, defined_angle)
|
||||
# the method get_beam_main_axis_m() which calculates the beam_axis_m vector
|
||||
# unless rotated, this vector points towards +y axis
|
||||
# doesn't follow 1,2-direction order of CalculiX
|
||||
# ^ (n, 2-direction)
|
||||
# |
|
||||
# |
|
||||
# .----> (m, 1-direction)
|
||||
#
|
||||
len_beam_axis_n = beamsec_obj.RectHeight.getValueAs("mm").Value
|
||||
len_beam_axis_m = beamsec_obj.RectWidth.getValueAs("mm").Value
|
||||
section_type = ", SECTION=RECT"
|
||||
section_geo = f"{len_beam_axis_m:.13G},{len_beam_axis_n:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Circular":
|
||||
diameter = beamsec_obj.CircDiameter.getValueAs("mm").Value
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = f"{diameter:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Elliptical":
|
||||
axis1 = beamsec_obj.Axis1Length.getValueAs("mm").Value
|
||||
axis2 = beamsec_obj.Axis2Length.getValueAs("mm").Value
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = f"{axis1:.13G},{axis2:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Pipe":
|
||||
radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs("mm").Value
|
||||
thickness = beamsec_obj.PipeThickness.getValueAs("mm").Value
|
||||
section_type = ", SECTION=PIPE"
|
||||
section_geo = f"{radius:.13G},{thickness:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Box":
|
||||
box_width = beamsec_obj.BoxWidth.getValueAs("mm").Value
|
||||
box_height = beamsec_obj.BoxHeight.getValueAs("mm").Value
|
||||
box_t1 = beamsec_obj.BoxT1.getValueAs("mm").Value
|
||||
box_t2 = beamsec_obj.BoxT2.getValueAs("mm").Value
|
||||
box_t3 = beamsec_obj.BoxT3.getValueAs("mm").Value
|
||||
box_t4 = beamsec_obj.BoxT4.getValueAs("mm").Value
|
||||
section_type = ", SECTION=BOX"
|
||||
section_geo = f"{box_width:.13G},{box_height:.13G},{box_t1:.13G},{box_t2:.13G},{box_t3:.13G},{box_t4:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
if ccxwriter.solver_obj.ExcludeBendingStiffness:
|
||||
area = beamsec_obj.TrussArea.getValueAs("mm^2").Value
|
||||
section_def = f"*SOLID SECTION, {elsetdef}{material}\n"
|
||||
section_geo = f"{area:.13G}\n"
|
||||
else:
|
||||
if beamsec_obj.SectionType == "Rectangular":
|
||||
# see meshtools.get_beam_main_axis_m(beam_direction, defined_angle)
|
||||
# the method get_beam_main_axis_m() which calculates the beam_axis_m vector
|
||||
# unless rotated, this vector points towards +y axis
|
||||
# doesn't follow 1,2-direction order of CalculiX
|
||||
# ^ (n, 2-direction)
|
||||
# |
|
||||
# |
|
||||
# .----> (m, 1-direction)
|
||||
#
|
||||
len_beam_axis_n = beamsec_obj.RectHeight.getValueAs("mm").Value
|
||||
len_beam_axis_m = beamsec_obj.RectWidth.getValueAs("mm").Value
|
||||
section_type = ", SECTION=RECT"
|
||||
section_geo = f"{len_beam_axis_m:.13G},{len_beam_axis_n:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Circular":
|
||||
diameter = beamsec_obj.CircDiameter.getValueAs("mm").Value
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = f"{diameter:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Elliptical":
|
||||
axis1 = beamsec_obj.Axis1Length.getValueAs("mm").Value
|
||||
axis2 = beamsec_obj.Axis2Length.getValueAs("mm").Value
|
||||
section_type = ", SECTION=CIRC"
|
||||
section_geo = f"{axis1:.13G},{axis2:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Pipe":
|
||||
radius = 0.5 * beamsec_obj.PipeDiameter.getValueAs("mm").Value
|
||||
thickness = beamsec_obj.PipeThickness.getValueAs("mm").Value
|
||||
section_type = ", SECTION=PIPE"
|
||||
section_geo = f"{radius:.13G},{thickness:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
elif beamsec_obj.SectionType == "Box":
|
||||
box_width = beamsec_obj.BoxWidth.getValueAs("mm").Value
|
||||
box_height = beamsec_obj.BoxHeight.getValueAs("mm").Value
|
||||
box_t1 = beamsec_obj.BoxT1.getValueAs("mm").Value
|
||||
box_t2 = beamsec_obj.BoxT2.getValueAs("mm").Value
|
||||
box_t3 = beamsec_obj.BoxT3.getValueAs("mm").Value
|
||||
box_t4 = beamsec_obj.BoxT4.getValueAs("mm").Value
|
||||
section_type = ", SECTION=BOX"
|
||||
section_geo = f"{box_width:.13G},{box_height:.13G},{box_t1:.13G},{box_t2:.13G},{box_t3:.13G},{box_t4:.13G}\n"
|
||||
section_def = f"*BEAM SECTION, {elsetdef}{material}{section_type}\n"
|
||||
|
||||
f.write(section_def)
|
||||
f.write(section_geo)
|
||||
f.write(section_nor)
|
||||
if not ccxwriter.solver_obj.ExcludeBendingStiffness:
|
||||
f.write(section_nor)
|
||||
elif "fluidsection_obj" in matgeoset: # fluid mesh
|
||||
fluidsec_obj = matgeoset["fluidsection_obj"]
|
||||
if fluidsec_obj.SectionType == "Liquid":
|
||||
|
||||
@@ -37,14 +37,18 @@ def write_mesh(ccxwriter):
|
||||
element_param = 1 # highest element order only
|
||||
group_param = False # do not write mesh group data
|
||||
|
||||
# Use reduced integration beam elements if this option is enabled in ccx solver settings
|
||||
# Use reduced integration beam elements or truss elements if this is enabled in ccx solver settings
|
||||
vol_variant = "standard"
|
||||
edge_variant = "beam"
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
edge_variant = "beam reduced"
|
||||
# Check to see if fluid sections are in analysis and use D network element type
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
edge_variant = "network"
|
||||
if ccxwriter.solver_obj.ExcludeBendingStiffness:
|
||||
edge_variant = "truss"
|
||||
else:
|
||||
if ccxwriter.solver_obj.BeamReducedIntegration:
|
||||
edge_variant = "beam reduced"
|
||||
else:
|
||||
edge_variant = "beam"
|
||||
# Check to see if fluid sections are in analysis and use D network element type
|
||||
if ccxwriter.member.geos_fluidsection:
|
||||
edge_variant = "network"
|
||||
|
||||
# Use 2D elements if model space is not set to 3D
|
||||
if ccxwriter.solver_obj.ModelSpace == "3D":
|
||||
|
||||
Reference in New Issue
Block a user