Skip to content

Commit 91ebf1f

Browse files
author
Martin Kraska
committed
Add bolt example
1 parent c9912ab commit 91ebf1f

18 files changed

+456
-0
lines changed

NonLinear/3PB/Refs/PEexpanded.png

-19 Bytes
Loading

NonLinear/Bolt/Bolt.geo

+133
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
d = 10; // Nenndurchmesser
2+
s = 17; // Schluesselweite
3+
k = 7; // Kopfhoehe
4+
m = 0.8*d; // Mutternhoehe
5+
6+
db = 11; //Bohrungsdurchmesser
7+
t1 = 10; //Plattendicke 1
8+
b1 = 40;
9+
l1 = 40;
10+
t2 = 15; //Plattendicke 2
11+
b2 = 50;
12+
l2 = 45;
13+
14+
t3 = 10; //Stegdicke
15+
h3 = 30; //Steghoehe
16+
e = 20; //halber Schraubenabstand
17+
18+
Point(1) = {e,0,-t2}; // Mittelpunkt der Schraube
19+
Point(2) = {e,0,t1+k};
20+
Point(3) = {e,s/2,t1+k};
21+
Point(4) = {e,s/2,t1};
22+
Point(5) = {e,d/2,t1};
23+
Point(6) = {e,d/2,-t2};
24+
Point(7) = {e,0,-t2-m};
25+
Point(8) = {e,s/2,-t2-m};
26+
Point(9) = {e,s/2,-t2};
27+
Line(1) = {1,2};
28+
Line(2) = {2,3};
29+
Line(3) = {3,4};
30+
Line(4) = {4,5};
31+
Line(5) = {5,6};
32+
Line(6) = {6,1};
33+
Line Loop(1) = {1,2,3,4,5,6};
34+
Plane Surface(1) ={1};
35+
Line(7) = {1,7};
36+
Line(8) = {7,8};
37+
Line(9) = {8,9};
38+
Line(10) = {9,6};
39+
Line Loop(2) = {7,8,9,10,6};
40+
Plane Surface(2) ={2};
41+
42+
pc=newp;
43+
Point(pc) = {0,0,0};
44+
out[] = Extrude { {0,0,1}, {e,0,0}, Pi/2 } { Surface{1,2}; };
45+
out[] = Symmetry {0,1,0,0} { Duplicata{ Volume{1,2}; } };
46+
out[] = Symmetry {-1,0,0,20} { Duplicata{ Volume{1,2,98,60}; } };
47+
48+
//Reverse Surface {84,145,181,120};
49+
50+
Physical Surface("C_head") = {-84, 29, 245, -145};
51+
Physical Surface("C_nut") = {55, -120, -181, 212};
52+
53+
// Platten
54+
// Platte 1
55+
// Aussenrand
56+
pp1 = newp;
57+
Point(pp1) = {0,b1/2,0};
58+
Point(pp1+1) = {l1,b1/2,0};
59+
Point(pp1+2) = {l1,-b1/2,0};
60+
Point(pp1+3) = {0,-b1/2,0};
61+
ll1 = newl;
62+
Line(ll1) = {pp1,pp1+1};
63+
Line(ll1+1) = {pp1+1,pp1+2};
64+
Line(ll1+2) = {pp1+2,pp1+3};
65+
Line(ll1+3) = {pp1+3,pp1};
66+
ll = newll;
67+
Line Loop(ll) = {ll1,ll1+1,ll1+2,ll1+3};
68+
// Bohrung
69+
pp1 = newp;
70+
Point(pp1) = {e,0,0};
71+
Point(pp1+1) = {e,db/2,0};
72+
Point(pp1+2) = {e+db/2,0,0};
73+
Point(pp1+3) = {e,-db/2,0};
74+
Point(pp1+4) = {e-db/2,0,0};
75+
ll1 = newl;
76+
Circle(ll1) = {pp1+1,pp1,pp1+2};
77+
Circle(ll1+1) = {pp1+2,pp1,pp1+3};
78+
Circle(ll1+2) = {pp1+3,pp1,pp1+4};
79+
Circle(ll1+3) = {pp1+4,pp1,pp1+1};
80+
Line Loop(ll+1) = {ll1,ll1+1,ll1+2,ll1+3};
81+
ns = news;
82+
Plane Surface(ns) ={ll,ll+1};
83+
Out[] = Extrude {0,0,t1} { Surface{ns}; };
84+
85+
// Platte 2
86+
// Aussenrand
87+
eps = -0.001;
88+
pp1 = newp;
89+
Point(pp1) = {0,b2/2,eps};
90+
Point(pp1+1) = {l2,b2/2,eps};
91+
Point(pp1+2) = {l2,-b2/2,eps};
92+
Point(pp1+3) = {0,-b2/2,eps};
93+
ll1 = newl;
94+
Line(ll1) = {pp1,pp1+1};
95+
Line(ll1+1) = {pp1+1,pp1+2};
96+
Line(ll1+2) = {pp1+2,pp1+3};
97+
Line(ll1+3) = {pp1+3,pp1};
98+
ll = newll;
99+
Line Loop(ll) = {ll1,ll1+1,ll1+2,ll1+3};
100+
// Bohrung
101+
pp1 = newp;
102+
Point(pp1) = {e,0,eps};
103+
Point(pp1+1) = {e,db/2,eps};
104+
Point(pp1+2) = {e+db/2,0,eps};
105+
Point(pp1+3) = {e,-db/2,eps};
106+
Point(pp1+4) = {e-db/2,0,eps};
107+
ll1 = newl;
108+
Circle(ll1) = {pp1+1,pp1,pp1+2};
109+
Circle(ll1+1) = {pp1+2,pp1,pp1+3};
110+
Circle(ll1+2) = {pp1+3,pp1,pp1+4};
111+
Circle(ll1+3) = {pp1+4,pp1,pp1+1};
112+
Line Loop(ll+1) = {ll1,ll1+1,ll1+2,ll1+3};
113+
ns = news;
114+
Plane Surface(ns) = {ll,ll+1};
115+
Out[] = Extrude {0,0,-t2} { Surface{ns}; };
116+
117+
Physical Surface("sym1") = {285};
118+
Physical Surface("sym2") = {337};
119+
Physical Surface("c1o") = {302};
120+
Physical Surface("c1u") = {260};
121+
Physical Surface("c2o") = {312};
122+
Physical Surface("c2u") = {354};
123+
Physical Surface("c2r") = {329};
124+
Physical Volume("bolt") = {1,2,60,121,221,98,159,190};
125+
Physical Volume("p1") = {222};
126+
Physical Volume("p2") = {223};
127+
128+
Mesh.ElementOrder = 2;
129+
Mesh 3;
130+
131+
Mesh.SaveGroupsOfNodes = 1;
132+
133+
Save "Bolt-gmsh.inp";

NonLinear/Bolt/README.md

+74
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
# Bolted Plates
2+
Tested with CGX 2.19 / CCX 2.19
3+
4+
+ Non-linear static analysis
5+
+ Surface-to-surface penalty contact
6+
+ Thermal shrinkage for bolt pre-tension.
7+
8+
9+
File | Contents
10+
:------------- | :-------------
11+
[Bolt.geo](Bolt.geo) | Gmsh script for geomentry and meshing
12+
[pre.fbd](pre.fbd) | CGX script, pre-processing
13+
[post.fbd](post.fbd) | CGX script, post-processing, movie
14+
[thermal.inp](thermal.inp) | CCX input
15+
[test.py](test.py) | python script to run the simulation
16+
17+
18+
The model represents one half of two plates and two bolts. The lower plate is fixed at the outer sides, the upper plate is pulled up vertically in the center. The bolt is pre-stressed by thermal shrinkage.
19+
20+
<img src="expansion.png" width="500" title="expanded model">
21+
22+
## Pre-Processing
23+
24+
Contact surfaces and node sets for constraints:
25+
26+
<img src="contact.png" width="400" title="Contact surfaces"> <img src="boundary.png" width="400" title="node sets">
27+
28+
- `nsym1` and `nsym2` are set to UX=0 (symmetry)
29+
- `nc2r` is constrained to UY=UZ=0 (support)
30+
- In step 1, the bolt is cooled down to pre-tighten it.
31+
- In step 2, `nsym1` is displaced to UZ=0.001 (displacement-controlled loading)
32+
33+
34+
| Parameter | Value | Meaning |
35+
| :-------- | :----- | :------------- |
36+
| `d` | 10 | nominal bolt diameter in mm |
37+
| `s` | 17 | key-width of head and nut in mm|
38+
| `k` | 7 | height of bolt head in mm |
39+
| `db` | 11 | diameter of holes in mm |
40+
| `t1` | 10 | thickness of upper plate in mm |
41+
| `b1` | 40 | width of upper plate in mm |
42+
| `l1` | 40 | length of upper plate in mm |
43+
| `t2` | 15 | thickness of lower plate in mm |
44+
| `b2` | 50 | width of lower plate in mm |
45+
| `l2` | 45 | length of lower plate in mm |
46+
| `e` | 20 | distance of bolt axis from plane of symmetry in mm |
47+
48+
You may adjust the parameter values in the file [Bolt.geo](Bolt.geo) and then run
49+
```
50+
> gmsh Bolt.geo
51+
> cgx -b pre.fbd
52+
```
53+
54+
## Solving
55+
56+
```
57+
> ccx thermal
58+
> monitor.py thermal
59+
```
60+
<img src="thermal.png" title="Convergence plot">
61+
62+
## Post-Processing
63+
64+
```
65+
> cgx -b post.fbl
66+
```
67+
Stress and contact pressure after pre-tensioning
68+
69+
<img width="400" src="se-bolt-pretension.png" title="Equivalent stress"><img width="400" src="cpress-pretension.png" title="contact pressure">
70+
71+
Stress and contact pressure under external load
72+
73+
<img width="400" src="se-bolt.png" title="Equivalent stress"><img width="400" src="cpress.png" title="contact pressure">
74+

NonLinear/Bolt/boundary.png

22.6 KB
Loading

NonLinear/Bolt/contact.png

7.98 KB
Loading

NonLinear/Bolt/cpress-pretension.png

24.4 KB
Loading

NonLinear/Bolt/cpress.png

24.4 KB
Loading

NonLinear/Bolt/expansion.png

41.1 KB
Loading

NonLinear/Bolt/parts.png

8.23 KB
Loading

NonLinear/Bolt/post.fbd

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
read thermal.frd
2+
read thermal.inp nom
3+
# document pre-tension
4+
comp Nbolt do
5+
6+
view ill
7+
8+
rot y
9+
rot u 20
10+
rot l 20
11+
view disp
12+
scal d 100
13+
14+
ds 6 e 7
15+
plot fv Nbolt
16+
min 0
17+
max 200
18+
hcpy png se-bolt-pretension
19+
20+
ds -3 e 7
21+
plot fv Nbolt
22+
min 0
23+
max 200
24+
hcpy png se-bolt
25+
26+
27+
plot fv all
28+
min 0
29+
max 200
30+
hcpy png se-all
31+
32+
ds 7 e 4
33+
plot fv +cont1
34+
min 0
35+
max 200
36+
hcpy png cpress-pretension
37+
38+
39+
ds -2 e 4
40+
plot fv +cont1
41+
min 0
42+
max 200
43+
hcpy png cpress

NonLinear/Bolt/pre-tension.png

25.4 KB
Loading

NonLinear/Bolt/pre.fbd

+71
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
read Bolt-gmsh.inp
2+
zap +CPS6
3+
# contact surfaces
4+
comp C_head do
5+
send C_head abq surf
6+
comp C_nut do
7+
send C_nut abq surf
8+
comp c1o do
9+
send c1o abq surf
10+
comp c1u do
11+
send c1u abq surf
12+
comp c2o do
13+
send c2o abq surf
14+
comp c2u do
15+
send c2u abq surf
16+
17+
# node sets for boundary conditions
18+
seta nc2r n c2r
19+
send nc2r abq nam
20+
seta nsym1 n sym1
21+
send nsym1 abq nam
22+
seta nsym2 n sym2
23+
send nsym2 abq nam
24+
25+
# correct position of p2
26+
move p2 tra 0 0 0.001
27+
28+
# constraint node for the bolt
29+
seta nbolt n bolt
30+
enq nbolt nfix rec 20 0 17 1
31+
send nfix abq nam
32+
enq nbolt nfix1 rec 28.5 0 17 1
33+
send nfix1 abq nam
34+
35+
#constraint node for p1
36+
seta np1 n p1
37+
enq np1 nfixp1 rec 0 20 0 1
38+
send nfixp1 abq nam
39+
40+
# elements
41+
send p1 abq
42+
send p2 abq
43+
send bolt abq
44+
45+
# parts plot
46+
seta ! all
47+
rot y
48+
rot l 15
49+
rot u 15
50+
hcpy png parts
51+
52+
# plot contact
53+
ulin slave (red), master (blue)
54+
view ill on
55+
plot fb C_head r 50
56+
plus fb c1o b 50
57+
plus fb c1u r 50
58+
plus fb c2o b 50
59+
plus fb c2u b 50
60+
plus fb C_nut r 50
61+
hcpy png contact
62+
63+
# plot boundary
64+
ulin nsym1 (red), nsym2 (green), nc2r (blue)
65+
plot n nsym1 r
66+
plus n nsym2 g
67+
plus n nc2r b
68+
plus fb all n 20
69+
hcpy png boundary
70+
71+

NonLinear/Bolt/se-all.png

12.4 KB
Loading

NonLinear/Bolt/se-bolt-pretension.png

25.4 KB
Loading

NonLinear/Bolt/se-bolt.png

25.4 KB
Loading

NonLinear/Bolt/test.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#!/usr/bin/env python
2+
import os
3+
import multiprocessing
4+
import shutil
5+
6+
7+
# Provide access to the helper scripts
8+
def modify_path():
9+
scripts_dir = os.path.dirname(__file__)
10+
while not 'Scripts' in os.listdir(scripts_dir):
11+
scripts_dir = os.path.abspath(os.path.join(scripts_dir, '..'))
12+
scripts_dir = os.path.join(scripts_dir, 'Scripts')
13+
if not scripts_dir in os.environ['PATH']:
14+
os.environ['PATH'] += os.pathsep + scripts_dir
15+
print('\nPATH = {}\n'.format(os.environ['PATH']))
16+
17+
18+
# Move new files and folders to 'Refs'
19+
def move(old_snap):
20+
new_snap = os.listdir(os.curdir)
21+
if not os.path.exists('Refs'):
22+
os.mkdir('Refs')
23+
for f in new_snap:
24+
if not f in old_snap:
25+
fname = os.path.basename(f)
26+
new_name = os.path.join(os.curdir, 'Refs', fname)
27+
if os.path.isfile(new_name):
28+
os.remove(new_name)
29+
if os.path.isdir(new_name):
30+
shutil.rmtree(new_name)
31+
os.rename(f, new_name)
32+
33+
34+
if __name__ == '__main__':
35+
36+
# Enable multithreading for ccx
37+
os.environ['OMP_NUM_THREADS'] = str(multiprocessing.cpu_count())
38+
39+
# Explicitly move to example's directory
40+
os.chdir(os.path.dirname(__file__))
41+
42+
# Run the example
43+
modify_path()
44+
snap = os.listdir(os.curdir)
45+
os.system("gmsh Bolt.geo")
46+
os.system("cgx -b pre.fbd")
47+
os.system("ccx thermal")
48+
os.system("monitor.py thermal")
49+
os.system("cgx -b post.py")
50+
#move(snap)

0 commit comments

Comments
 (0)