Files
create/src/Mod/Fem/femtools/membertools.py
FEA-eng 2244a16790 FEM: Add defined temperature field with CalculiX (*TEMPERATURE) (#23277)
* FEM: add write_constraint_finaltemperature.py

* FEM: Update CMakeLists.txt

* FEM: Update membertools.py

* FEM: Update FemConstraintInitialTemperature.cpp

* FEM: Update FemConstraintInitialTemperature.h

* FEM: Update write_constraint_initialtemperature.py

* FEM: Update write_femelement_material.py

* FEM: Update writer.py

* FEM: Update write_constraint_finaltemperature.py

* FEM: Update write_femelement_material.py

* FEM: Update write_femelement_material.py

* FEM: Update box_static.inp

* FEM: Update ccx_cantilever_beam_circle.inp

* FEM: Update ccx_cantilever_beam_pipe.inp

* FEM: Update ccx_cantilever_beam_rect.inp

* FEM: Update ccx_cantilever_ele_hexa20.inp

* FEM: Update ccx_cantilever_ele_quad4.inp

* FEM: Update ccx_cantilever_ele_quad8.inp

* FEM: Update ccx_cantilever_ele_seg2.inp

* FEM: Update ccx_cantilever_ele_seg3.inp

* FEM: Update ccx_cantilever_ele_tria3.inp

* FEM: Update ccx_cantilever_ele_tria6.inp

* FEM: Update ccx_cantilever_faceload.inp

* FEM: Update ccx_cantilever_nodeload.inp

* FEM: Update ccx_cantilever_prescribeddisplacement.inp

* FEM: Update constraint_contact_shell_shell.inp

* FEM: Update constraint_sectionprint.inp

* FEM: Update constraint_selfweight_cantilever.inp

* FEM: Update constraint_tie.inp

* FEM: Update constraint_transform_beam_hinged.inp

* FEM: Update constraint_transform_torque.inp

* FEM: Update material_multiple_bendingbeam_fiveboxes.inp

* FEM: Update material_multiple_bendingbeam_fivefaces.inp

* FEM: Update material_multiple_tensionrod_twoboxes.inp

* FEM: Update material_nonlinear.inp

* FEM: Update square_pipe_end_twisted_edgeforces.inp

* FEM: Update square_pipe_end_twisted_nodeforces.inp

* FEM: Update write_constraint_finaltemperature.py

* FEM: Update write_femelement_material.py

* FEM: Update write_constraint_finaltemperature.py

* FEM: Update FemConstraintInitialTemperature.cpp

* FEM: Update FemConstraintInitialTemperature.h
2025-08-31 23:28:56 -05:00

293 lines
13 KiB
Python

# ***************************************************************************
# * Copyright (c) 2017 Markus Hovorka <m.hovorka@live.de> *
# * Copyright (c) 2018 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 *
# * *
# ***************************************************************************
"""Collection of functions for the Fem module.
This module contains function for managing a analysis and all the different
types of objects it contains, helper for executing a simulation.
"""
__title__ = "FEM analysis tools"
__author__ = "Markus Hovorka, Bernd Hahnebach"
__url__ = "https://www.freecad.org"
from . import femutils
def get_member(analysis, t):
"""Return list of all members of *analysis* of type *t*.
Search *analysis* for members of type *t*. This method checks the custom
python typesystem (BaseType class property) used by the Fem module if
possible. If the object does not use the python typesystem the usual
isDerivedFrom from the C++ dynamic type system is used.
:param analysis: only objects part of this analysis are considered
:param t: only objects of this type are returned
:note:
Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the
type is just checked for equality. If the type doesn't match
``obj.isDerivedFrom`` is called as usual. See
https://forum.freecad.org/viewtopic.php?f=10&t=32625
"""
if analysis is None:
raise ValueError("Analysis must not be None")
matching = []
for m in analysis.Group:
# since is _derived_from is used the father could be used
# to test too (ex. "Fem::FemMeshObject")
if femutils.is_derived_from(m, t) and not (
m.hasExtension("App::SuppressibleExtension") and m.Suppressed
):
matching.append(m)
return matching
def get_single_member(analysis, t):
"""Return one object of type *t* and part of *analysis*.
Search *analysis* for members of type *t* and return the first one that's
found. This method checks the custom python typesystem (BaseType class
property) used by the Fem module if possible. If the object doesn't use the
python typesystem the usual isDerivedFrom from the C++ dynamic type system
is used.
:param analysis: only objects part of this analysis are considered
:param t: only a object of this type is returned
:note:
Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the
type is just checked for equality. If the type doesn't match
``obj.isDerivedFrom`` is called as usual. See
https://forum.freecad.org/viewtopic.php?f=10&t=32625
"""
objs = get_member(analysis, t)
return objs[0] if objs else None
def get_several_member(analysis, t):
"""Get members and pack them for Calculix/Z88.
Collect members by calling :py:func:`get_member` and pack them into a
data structure that can be consumed by calculix and Z88 solver modules.
:param analysis: see :py:func:`get_member`
:param t: see :py:func:`get_member`
:returns:
A list containing one dict per member. Each dict has two entries:
``"Object"`` and ``"RefShapeType"``. ``dict["Object"]`` contains the
member document object. ``dict["RefShapeType"]`` contains the shape type
of the *References* property of the member (used by constraints) as a
string ("Vertex", "Edge", "Face" or "Solid"). If the member doesn't have a
*References* property ``dict["RefShapeType"]`` is the empty string ``""``.
:note:
Undefined behaviour if one of the members has a *References* property
which is empty.
:note:
Undefined behaviour if the type of the references of one object are not
all the same.
:note:
Inheritance of Fem types is not checked. If *obj* uses Fems typesystem the
type is just checked for equality. If the type doesn't match
``obj.isDerivedFrom`` is called as usual. See
https://forum.freecad.org/viewtopic.php?f=10&t=32625
"""
# if no member is found, an empty list is returned
objs = get_member(analysis, t)
members = []
for m in objs:
obj_dict = {}
obj_dict["Object"] = m
obj_dict["RefShapeType"] = femutils.get_refshape_type(m)
members.append(obj_dict)
return members
def get_mesh_to_solve(analysis):
"""Find one and only mesh object of *analysis*.
:returns:
A tuple ``(object, message)``. If and only if the analysis contains
exactly one mesh object the first value of the tuple is the mesh document
object. Otherwise the first value is ``None`` and the second value is a
error message indicating what went wrong.
"""
mesh_to_solve = None
for m in analysis.Group:
if m.isDerivedFrom("Fem::FemMeshObject") and not m.Suppressed:
if not mesh_to_solve:
mesh_to_solve = m
else:
return (None, "FEM: multiple mesh in analysis not yet supported!")
if mesh_to_solve is not None:
return (mesh_to_solve, "")
else:
return (None, "FEM: no mesh object found in analysis.")
class AnalysisMember:
def __init__(self, analysis):
self.analysis = analysis
"""
# members of the analysis. All except solvers and the mesh
materials:
materials_linear : list of dictionaries
list of nonlinear materials from the analysis.
[{"Object":materials_linear}, {}, ...]
materials_nonlinear : list of dictionaries
list of nonlinear materials from the analysis.
[{"Object":materials_nonlinear}, {}, ...]
geometries:
beam_sections : list of dictionaries
list of beam sections from the analysis.
[{"Object":beam_section_obj, "xxxxxxxx":value}, {}, ...]
beam_rotations : list of dictionaries
list of beam rotations from the analysis.
[{"Object":beam_rotation_obj, "xxxxxxxx":value}, {}, ...]
fluid_sections : list of dictionaries
list of fluid sections from the analysis.
[{"Object":fluid_section_obj, "xxxxxxxx":value}, {}, ...]
shell_thicknesses : list of dictionaries
list of shell thicknesses from the analysis.
[{"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}, {}, ...]
constraints_displacement : list of dictionaries
list of displacements for the analysis.
[{"Object":displacement_obj, "xxxxxxxx":value}, {}, ...]
constraints_fixed : list of dictionaries
list of fixed constraints from the analysis.
[{"Object":fixed_obj, "NodeSupports":bool}, {}, ...]
constraints_rigidbody : list of dictionaries
list of displacements for the analysis.
[{"Object":rigidbody_obj, "xxxxxxxx":value}, {}, ...]
constraints_force : list of dictionaries
list of force constraints from the analysis.
[{"Object":force_obj, "NodeLoad":value}, {}, ...
constraints_heatflux : list of dictionaries
list of heatflux constraints for the analysis.
[{"Object":heatflux_obj, "xxxxxxxx":value}, {}, ...]
constraints_initialtemperature : list of dictionaries
list of initial temperatures for the analysis.
[{"Object":initialtemperature_obj, "xxxxxxxx":value}, {}, ...]
constraints_planerotation : list of dictionaries
list of plane rotation constraints from the analysis.
[{"Object":planerotation_obj, "xxxxxxxx":value}, {}, ...]
constraints_pressure : list of dictionaries
list of pressure constraints from the analysis.
[{"Object":pressure_obj, "xxxxxxxx":value}, {}, ...]
constraints_sectionprint : list of dictionaries
list of sectionprints for the analysis.
[{"Object":sectionprint_obj, "xxxxxxxx":value}, {}, ...]
constraints_selfweight : list of dictionaries
list of selfweight constraints from the analysis.
[{"Object":selfweight_obj, "xxxxxxxx":value}, {}, ...]
constraints_temperature : list of dictionaries
list of temperatures for the analysis.
[{"Object":temperature_obj, "xxxxxxxx":value}, {}, ...]
constraints_tie : list of dictionaries
list of ties for the analysis.
[{"Object":tie_obj, "xxxxxxxx":value}, {}, ...]
constraints_transform : list of dictionaries
list of transform constraints from the analysis.
[{"Object":transform_obj, "xxxxxxxx":value}, {}, ...]
"""
# get member
# constants
self.cota_vacuumpermittivity = self.get_several_member("Fem::ConstantVacuumPermittivity")
# materials
std_mats = self.get_several_member("Fem::MaterialCommon")
rei_mats = self.get_several_member("Fem::MaterialReinforced")
self.mats_linear = std_mats + rei_mats
self.mats_nonlinear = self.get_several_member("Fem::MaterialMechanicalNonlinear")
# geometries
self.geos_beamsection = self.get_several_member("Fem::ElementGeometry1D")
self.geos_beamrotation = self.get_several_member("Fem::ElementRotation1D")
self.geos_fluidsection = self.get_several_member("Fem::ElementFluid1D")
self.geos_shellthickness = self.get_several_member("Fem::ElementGeometry2D")
# constraints
self.cons_centrif = self.get_several_member("Fem::ConstraintCentrif")
self.cons_bodyheatsource = self.get_several_member("Fem::ConstraintBodyHeatSource")
self.cons_contact = self.get_several_member("Fem::ConstraintContact")
self.cons_displacement = self.get_several_member("Fem::ConstraintDisplacement")
self.cons_fixed = self.get_several_member("Fem::ConstraintFixed")
self.cons_rigidbody = self.get_several_member("Fem::ConstraintRigidBody")
self.cons_rigidbody_step = self.get_several_member("Fem::ConstraintRigidBody")
self.cons_force = self.get_several_member("Fem::ConstraintForce")
self.cons_heatflux = self.get_several_member("Fem::ConstraintHeatflux")
self.cons_initialtemperature = self.get_several_member("Fem::ConstraintInitialTemperature")
self.cons_finaltemperature = self.get_several_member("Fem::ConstraintInitialTemperature")
self.cons_planerotation = self.get_several_member("Fem::ConstraintPlaneRotation")
self.cons_pressure = self.get_several_member("Fem::ConstraintPressure")
self.cons_sectionprint = self.get_several_member("Fem::ConstraintSectionPrint")
self.cons_selfweight = self.get_several_member("Fem::ConstraintSelfWeight")
self.cons_temperature = self.get_several_member("Fem::ConstraintTemperature")
self.cons_tie = self.get_several_member("Fem::ConstraintTie")
self.cons_transform = self.get_several_member("Fem::ConstraintTransform")
self.cons_electrostatic = self.get_several_member("Fem::ConstraintElectrostaticPotential")
self.cons_electricchargedensity = self.get_several_member(
"Fem::ConstraintElectricChargeDensity"
)
def get_several_member(self, t):
return get_several_member(self.analysis, t)