Skip to content

Commit 6899912

Browse files
Merge pull request #295 from TLCFEM/plugin-fibre-section
Plugin fibre section
2 parents 1a155be + f9af2b5 commit 6899912

File tree

3 files changed

+488
-0
lines changed

3 files changed

+488
-0
lines changed

docs/examples.rst

+1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ Analysis
3737
examples/analysis/warping_analysis
3838
examples/analysis/frame_analysis
3939
examples/analysis/stress_analysis
40+
examples/analysis/export_fibre_section
4041

4142
Results
4243
-------
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
{
2+
"cells": [
3+
{
4+
"cell_type": "markdown",
5+
"id": "db82db5006f2f216",
6+
"metadata": {},
7+
"source": [
8+
"# Export to Fibre Section\n",
9+
"\n",
10+
"This example shows how to export a section to a fibre section that can be used in [suanPan](https://github.com/TLCFEM/suanPan).\n",
11+
"\n",
12+
"[suanPan](https://github.com/TLCFEM/suanPan) is a finite element analysis framework. Sections can be exported and used to perform nonlinear analysis of frame structures.\n",
13+
"\n",
14+
"There are three analysis types available.\n",
15+
"\n",
16+
"1. '2D' ---> 2D planar analysis (axial force, bending moment). Elements: `B21`, `F21`.\n",
17+
"2. '3D' ---> 3D spatial analysis (axial force, bending moment). Elements: `B31`, `F31`.\n",
18+
"3. '3DOS' ---> 3D spatial analysis with warping and torsion (axial force, bending moment, torsion). Elements: `B31OS`.\n",
19+
"\n",
20+
"The section is discretised into triangular elements in `sectionproperties`. Each triangle can be deemed as a small cell/fibre. Its area and properties at the centre of the triangle are calculated and exported to create a fibre section.\n",
21+
"\n",
22+
"For '2D' and '3D' analyses, the location and area are used. For '3DOS' analysis, the additional warping function and its derivatives are used.\n",
23+
"\n",
24+
"## The Export Function\n",
25+
"\n",
26+
"One shall call the function with a geometry object with mesh created."
27+
]
28+
},
29+
{
30+
"cell_type": "code",
31+
"execution_count": null,
32+
"id": "1fe6766c73110947",
33+
"metadata": {},
34+
"outputs": [],
35+
"source": [
36+
"from sectionproperties.post.fibre import to_fibre_section\n",
37+
"from sectionproperties.pre.library import i_section\n",
38+
"\n",
39+
"geom = i_section(d=203, b=133, t_f=7.8, t_w=5.8, r=8.9, n_r=8)\n",
40+
"geom.create_mesh(mesh_sizes=10)\n",
41+
"\n",
42+
"commands = to_fibre_section(geom, analysis_type='3DOS')\n",
43+
"\n",
44+
"print(commands[:3000])"
45+
]
46+
},
47+
{
48+
"cell_type": "markdown",
49+
"id": "3e59149a988e3681",
50+
"metadata": {},
51+
"source": [
52+
"The output can be saved to a file and later be used to create beam elements."
53+
]
54+
},
55+
{
56+
"cell_type": "code",
57+
"execution_count": null,
58+
"id": "e62e5df634d337ed",
59+
"metadata": {},
60+
"outputs": [],
61+
"source": [
62+
"from shutil import which\n",
63+
"\n",
64+
"# write the fibre section to a file\n",
65+
"with open('200UB25.4.sp', 'w') as f:\n",
66+
" f.write(commands)\n",
67+
"\n",
68+
"# write the main analysis file\n",
69+
"# since we assigned '3DOS' analysis type, we need to use compatible elements, for example, 'B31OS'.\n",
70+
"model = '''# Example torsion analysis\n",
71+
"node 1 0 0 0\n",
72+
"node 2 1 0 0\n",
73+
"material ElasticOS 1 200. .25\n",
74+
"file 200UB25.4.sp\n",
75+
"orientation B3DOSL 1 0. 0. 1.\n",
76+
"element B31OS 1 1 2 1 1 6\n",
77+
"fix2 1 E 1\n",
78+
"displacement 1 0 1E-1 4 2\n",
79+
"plainrecorder 1 Node RF4 2\n",
80+
"plainrecorder 2 Element BEAMS 1\n",
81+
"step static 1\n",
82+
"set ini_step_size 1E-1\n",
83+
"set fixed_step_size true\n",
84+
"converger RelIncreDisp 1 1E-10 5 1\n",
85+
"analyze\n",
86+
"save recorder 1 2\n",
87+
"exit\n",
88+
"'''\n",
89+
"with open('torsion_analysis.sp', 'w') as f:\n",
90+
" f.write(model)"
91+
]
92+
},
93+
{
94+
"cell_type": "markdown",
95+
"id": "e3a7872e157397ad",
96+
"metadata": {},
97+
"source": [
98+
"For further details, check [this](https://tlcfem.github.io/suanPan-manual/3.2/Example/Structural/Statics/thin-walled-section/) example."
99+
]
100+
},
101+
{
102+
"cell_type": "markdown",
103+
"id": "a905cac642f4ba76",
104+
"metadata": {},
105+
"source": [
106+
"## A Bit More Details\n",
107+
"\n",
108+
"### Shift Section\n",
109+
"\n",
110+
"As the header states, the function computes properties in the local coordinate system of the section.\n",
111+
"\n",
112+
"For the above I-section, one may want to shift the section to the centroid of the section.\n",
113+
"The user shall explicitly perform this step."
114+
]
115+
},
116+
{
117+
"cell_type": "code",
118+
"execution_count": null,
119+
"id": "d0342167a9608431",
120+
"metadata": {},
121+
"outputs": [],
122+
"source": [
123+
"geom.plot_geometry()"
124+
]
125+
},
126+
{
127+
"cell_type": "code",
128+
"execution_count": null,
129+
"id": "72fd533e96ae001c",
130+
"metadata": {},
131+
"outputs": [],
132+
"source": [
133+
"from sectionproperties.analysis import Section\n",
134+
"\n",
135+
"sec = Section(geom)\n",
136+
"sec.calculate_geometric_properties()\n",
137+
"x, y = sec.get_c()\n",
138+
"geom = geom.shift_section(-x, -y) # or whatever shift you want\n",
139+
"geom.create_mesh(mesh_sizes=5)\n",
140+
"geom.plot_geometry()"
141+
]
142+
},
143+
{
144+
"cell_type": "markdown",
145+
"id": "c0091da299e91349",
146+
"metadata": {},
147+
"source": [
148+
"### Overwrite Material\n",
149+
"\n",
150+
"Material names shall be converted to material tags.\n",
151+
"\n",
152+
"One can provide such a mapping dictionary to the function.\n",
153+
"With the shifted geometry, one can do the following."
154+
]
155+
},
156+
{
157+
"cell_type": "code",
158+
"execution_count": null,
159+
"id": "381c615fd4cf7f58",
160+
"metadata": {},
161+
"outputs": [],
162+
"source": [
163+
"commands = to_fibre_section(geom, analysis_type='3DOS', material_mapping={'default': 1})\n",
164+
"print(commands[:5000])"
165+
]
166+
},
167+
{
168+
"cell_type": "markdown",
169+
"id": "6f3179efd747b6ff",
170+
"metadata": {},
171+
"source": [
172+
"## Run Analysis\n",
173+
"\n",
174+
"If `suanPan` is installed, one can run the analysis using the previously saved script."
175+
]
176+
},
177+
{
178+
"cell_type": "code",
179+
"execution_count": null,
180+
"id": "2997fa9f72909c12",
181+
"metadata": {},
182+
"outputs": [],
183+
"source": [
184+
"from os.path import exists\n",
185+
"\n",
186+
"# write the fibre section to a file with material tag replaced\n",
187+
"with open('200UB25.4.sp', 'w') as f:\n",
188+
" f.write(commands)\n",
189+
"\n",
190+
"# run the analysis\n",
191+
"if which('suanpan') is not None:\n",
192+
" from subprocess import run\n",
193+
"\n",
194+
" result_available = True\n",
195+
" run(['suanpan', '-f', 'torsion_analysis.sp'])\n",
196+
"else:\n",
197+
" result_available = exists('R1-RF42.txt')\n",
198+
" print('suanPan is not installed.')"
199+
]
200+
},
201+
{
202+
"cell_type": "markdown",
203+
"id": "d77fc35609b5228e",
204+
"metadata": {},
205+
"source": [
206+
"## Plot Results\n",
207+
"\n",
208+
"The results are stored in `R1-RF42.txt` (**R**ecorder **1** --> **RF4** for node **2**) and `R2-BEAMS1.txt` (**R**ecorder **2** --> **BEAMS** for element **1**).\n",
209+
"\n",
210+
"The sixth component of `BEAMS` is the St. Venant torsion."
211+
]
212+
},
213+
{
214+
"cell_type": "code",
215+
"execution_count": null,
216+
"id": "91298a718a2935a9",
217+
"metadata": {},
218+
"outputs": [],
219+
"source": [
220+
"if result_available:\n",
221+
" from matplotlib import pyplot as plt\n",
222+
" import numpy as np\n",
223+
"\n",
224+
" data = np.loadtxt('R1-RF42.txt')\n",
225+
" twist = data[:, 0] * .1\n",
226+
" torque = data[:, 1]\n",
227+
" plt.plot(twist, torque)\n",
228+
" plt.xlabel('twist (rad)')\n",
229+
" plt.ylabel('total torque')\n",
230+
" plt.legend(['200UB25.4'])\n",
231+
" plt.tight_layout()\n",
232+
" plt.show()"
233+
]
234+
},
235+
{
236+
"cell_type": "code",
237+
"execution_count": null,
238+
"id": "e93238cf396c115d",
239+
"metadata": {},
240+
"outputs": [],
241+
"source": [
242+
"if result_available:\n",
243+
" data = np.loadtxt('R2-BEAMS1.txt')\n",
244+
" twist = data[:, 0] * .1\n",
245+
" torque = data[:, 6]\n",
246+
" ref_torque = twist * 80 * 62.7e3 # G=80, J=62.7\n",
247+
" plt.plot(twist, torque)\n",
248+
" plt.plot(twist, ref_torque)\n",
249+
" plt.xlabel('twist (rad)')\n",
250+
" plt.ylabel('St. Venant torsion')\n",
251+
" plt.legend(['numerical', 'theoretical'])\n",
252+
" plt.tight_layout()\n",
253+
" plt.show()"
254+
]
255+
}
256+
],
257+
"metadata": {
258+
"kernelspec": {
259+
"display_name": "Python 3",
260+
"language": "python",
261+
"name": "python3"
262+
},
263+
"language_info": {
264+
"codemirror_mode": {
265+
"name": "ipython",
266+
"version": 2
267+
},
268+
"file_extension": ".py",
269+
"mimetype": "text/x-python",
270+
"name": "python",
271+
"nbconvert_exporter": "python",
272+
"pygments_lexer": "ipython2",
273+
"version": "2.7.6"
274+
}
275+
},
276+
"nbformat": 4,
277+
"nbformat_minor": 5
278+
}

0 commit comments

Comments
 (0)