Skip to content

Commit 20b7ffa

Browse files
committed
Fem: Add body heat source to CalculiX writer - fixes FreeCAD#11650
1 parent 91aac05 commit 20b7ffa

File tree

6 files changed

+118
-0
lines changed

6 files changed

+118
-0
lines changed

src/Mod/Fem/CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,7 @@ SET(FemSolverCalculix_SRCS
221221
femsolver/calculix/__init__.py
222222
femsolver/calculix/solver.py
223223
femsolver/calculix/tasks.py
224+
femsolver/calculix/write_constraint_bodyheatsource.py
224225
femsolver/calculix/write_constraint_centrif.py
225226
femsolver/calculix/write_constraint_contact.py
226227
femsolver/calculix/write_constraint_displacement.py

src/Mod/Fem/femmesh/meshsetsgetter.py

+13
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,7 @@ def get_mesh_sets(self):
135135

136136
# constraints element sets getter
137137
self.get_constraints_centrif_elements()
138+
self.get_constraints_bodyheatsource_elements()
138139

139140
# constraints node sets getter
140141
self.get_constraints_fixed_nodes()
@@ -540,6 +541,18 @@ def get_constraints_centrif_elements(self):
540541
else:
541542
self.get_solid_element_sets(self.member.cons_centrif)
542543

544+
def get_constraints_bodyheatsource_elements(self):
545+
# get element ids and write them into the femobj
546+
if not self.member.cons_bodyheatsource:
547+
return
548+
if (
549+
len(self.member.cons_bodyheatsource) == 1
550+
and not self.member.cons_bodyheatsource[0]["Object"].References
551+
):
552+
self.member.cons_bodyheatsource[0]["FEMElements"] = self.ccx_evolumes
553+
else:
554+
self.get_solid_element_sets(self.member.cons_bodyheatsource)
555+
543556
# ********************************************************************************************
544557
# ********************************************************************************************
545558
# element sets material and element geometry

src/Mod/Fem/femmesh/meshtools.py

+2
Original file line numberDiff line numberDiff line change
@@ -784,6 +784,8 @@ def get_elset_short_name(
784784
return "S" + str(i)
785785
elif is_of_type(obj, "Fem::ConstraintCentrif"):
786786
return "C" + str(i)
787+
elif is_of_type(obj, "Fem::ConstraintBodyHeatSource"):
788+
return "H" + str(i)
787789
else:
788790
FreeCAD.Console.PrintError(
789791
"Error in creating short elset name "
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
# SPDX-License-Identifier: LGPL-2.1-or-later
2+
3+
#/***************************************************************************
4+
# * Copyright (c) 2024 Mario Passaglia <mpassaglia[at]cbc.uba.ar> *
5+
# * *
6+
# * This file is part of FreeCAD. *
7+
# * *
8+
# * FreeCAD is free software: you can redistribute it and/or modify it *
9+
# * under the terms of the GNU Lesser General Public License as *
10+
# * published by the Free Software Foundation, either version 2.1 of the *
11+
# * License, or (at your option) any later version. *
12+
# * *
13+
# * FreeCAD is distributed in the hope that it will be useful, but *
14+
# * WITHOUT ANY WARRANTY; without even the implied warranty of *
15+
# * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU *
16+
# * Lesser General Public License for more details. *
17+
# * *
18+
# * You should have received a copy of the GNU Lesser General Public *
19+
# * License along with FreeCAD. If not, see *
20+
# * <https://www.gnu.org/licenses/>. *
21+
# * *
22+
# **************************************************************************
23+
24+
__title__ = "FreeCAD FEM calculix constraint body heat source"
25+
__author__ = "Mario Passaglia"
26+
__url__ = "https://www.freecad.org"
27+
28+
29+
import FreeCAD
30+
31+
32+
def get_analysis_types():
33+
return ["thermomech"]
34+
35+
36+
def get_sets_name():
37+
return "constraints_bodyheatsource_element_sets"
38+
39+
40+
def get_constraint_title():
41+
return "Body Heat Source Constraints"
42+
43+
44+
def get_before_write_meshdata_constraint():
45+
return ""
46+
47+
48+
def get_after_write_meshdata_constraint():
49+
return ""
50+
51+
52+
def get_before_write_constraint():
53+
return ""
54+
55+
56+
def get_after_write_constraint():
57+
return ""
58+
59+
60+
def write_meshdata_constraint(f, femobj, bodyheatsource_obj, ccxwriter):
61+
f.write("*ELSET,ELSET={}\n".format(bodyheatsource_obj.Name))
62+
if isinstance(femobj["FEMElements"], str):
63+
f.write("{}\n".format(femobj["FEMElements"]))
64+
else:
65+
for e in femobj["FEMElements"]:
66+
f.write("{},\n".format(e))
67+
68+
69+
def write_constraint(f, femobj, bodyheatsource_obj, ccxwriter):
70+
71+
# floats read from ccx should use {:.13G}, see comment in writer module
72+
# search referenced material
73+
ref = bodyheatsource_obj.References
74+
density = None
75+
for mat in ccxwriter.member.mats_linear:
76+
for mat_ref in mat["Object"].References:
77+
if mat_ref[0] == ref[0]:
78+
density = FreeCAD.Units.Quantity(mat["Object"].Material["Density"])
79+
break
80+
81+
if not density:
82+
# search material without references
83+
for mat in ccxwriter.member.mats_linear:
84+
if not mat["Object"].References:
85+
density = FreeCAD.Units.Quantity(mat["Object"].Material["Density"])
86+
87+
# get some data from the bodyheatsource_obj (is in power per unit mass)
88+
heat = FreeCAD.Units.Quantity(bodyheatsource_obj.HeatSource, "m^2/s^3") * density
89+
# write to file
90+
f.write("*DFLUX\n")
91+
f.write(
92+
"{},BF,{:.13G}\n".format(
93+
bodyheatsource_obj.Name, heat.getValueAs("t/(mm*s^3)").Value
94+
)
95+
)
96+
f.write("\n")

src/Mod/Fem/femsolver/calculix/writer.py

+3
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
from FreeCAD import Units
3737

3838
from . import write_constraint_centrif as con_centrif
39+
from . import write_constraint_bodyheatsource as con_bodyheatsource
3940
from . import write_constraint_contact as con_contact
4041
from . import write_constraint_displacement as con_displacement
4142
from . import write_constraint_fixed as con_fixed
@@ -160,6 +161,7 @@ def write_solver_input(self):
160161

161162
# element sets constraints
162163
self.write_constraints_meshsets(inpfile, self.member.cons_centrif, con_centrif)
164+
self.write_constraints_meshsets(inpfile, self.member.cons_bodyheatsource, con_bodyheatsource)
163165

164166
# node sets
165167
self.write_constraints_meshsets(inpfile, self.member.cons_fixed, con_fixed)
@@ -196,6 +198,7 @@ def write_solver_input(self):
196198
self.write_constraints_propdata(inpfile, self.member.cons_sectionprint, con_sectionprint)
197199
self.write_constraints_propdata(inpfile, self.member.cons_selfweight, con_selfweight)
198200
self.write_constraints_propdata(inpfile, self.member.cons_centrif, con_centrif)
201+
self.write_constraints_propdata(inpfile, self.member.cons_bodyheatsource, con_bodyheatsource)
199202
self.write_constraints_meshsets(inpfile, self.member.cons_force, con_force)
200203
self.write_constraints_meshsets(inpfile, self.member.cons_pressure, con_pressure)
201204
self.write_constraints_propdata(inpfile, self.member.cons_temperature, con_temperature)

src/Mod/Fem/femtools/membertools.py

+3
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,9 @@ def __init__(self, analysis):
289289
self.cons_centrif = self.get_several_member(
290290
"Fem::ConstraintCentrif"
291291
)
292+
self.cons_bodyheatsource = self.get_several_member(
293+
"Fem::ConstraintBodyHeatSource"
294+
)
292295
self.cons_contact = self.get_several_member(
293296
"Fem::ConstraintContact"
294297
)

0 commit comments

Comments
 (0)