-
Notifications
You must be signed in to change notification settings - Fork 2
/
Copy pathtorsion.html
400 lines (296 loc) · 17.9 KB
/
torsion.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
<body></body>
<!-----------------Imports GlowScript Libraries and NumJs------------------------>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<link type="text/css" href="https://www.glowscript.org/css/redmond/2.1/jquery-ui.custom.css" rel="stylesheet" />
<link type="text/css" href="https://www.glowscript.org/css/ide.css" rel="stylesheet" />
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.0/MathJax.js?config=TeX-MML-AM_CHTML"></script>
<script type="text/javascript" src="https://www.glowscript.org/lib/jquery/2.1/jquery.min.js"></script>
<script type="text/javascript" src="https://www.glowscript.org/lib/jquery/2.1/jquery-ui.custom.min.js"></script>
<script type="text/javascript" src="https://www.glowscript.org/package/glow.3.0.min.js"></script>
<script type="text/javascript" src="https://www.glowscript.org/package/RSrun.3.0.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/nicolaspanel/[email protected]/dist/numjs.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjs/8.1.0/math.js" integrity="sha512-ne87j5uORxbrU7+bsqeJJWfWj5in65R9PCjaQL161xtH5cesZgULVbeVAkzAAN7hnYOcrHeBas9Wbd/Lm8gXFA==" crossorigin="anonymous"></script>
<!---------------------------Adds Style-------------------------------------------------->
<link rel="stylesheet" href="app_pages.css">
<!------------------------Run make_page and change_under_text to define functions (changeUnderText is optional)------------------->
<script src="make_page.js"></script>
<script src="misc_funcs.js"></script>
<script src="widget_groups.js"></script>
<script src="surface.js"></script>
<!------------------------JavaScript------------------------------------------------>
<script type="text/javascript">
// Define your labels for the stages
var titles=["Intro","Torque-Stress","Stress-Strain","Strain-Deformation","Summary"]
var text=[]
text[0]=(
"<p>Torsion is a twisting action, the axial rotation of one part of a material relative to the other. While less common in civil engineering compared to bending, it is important to consider for certain structures. For example, the Tacoma Narrow Bridge failed due to torsion of the span. This topic will go over the basic principles behind it, using a cylindrical rod as an example.</p><p>Photo credit to mynorthwest.com")
text[1]=(
"<p>The torque on a rod consists of shear stresses acting on the ends. Since the material farther from the middle of the rod deforms more, the shear stress increases radially, 0 in the middle and a maximum at the edge.</p>").concat(
"<p>The procedure for relating torque to shear stress is almost identical to relating bending moment to normal stress (see <a href='https://www.seeciv.com/bending.html'>pure bending</a>):</p>").concat(
"<p>$$T=\\int r dF=\\int r \\tau dA$$ $$T=\\frac{\\tau}{r}\\int{r^2 dA}=\\frac{\\tau}{r}J$$ </p>").concat(
"<p>\\(J\\) equal to \\(\\int r^2 dA) is the polar moment of inertia, analogous to the moment of inertia around a point and is based on the cross-section's geometry.</p>").concat(
"<p>So, looking at the \\(\\tau_{max}\\) ,the shear stress at the end of the rod, where \\(R\\) is the rod radius:</p>").concat(
"<p>$$\\underbrace{\\tau_{max}}_{0.0}=\\underbrace{\\frac{R}{J}}_{0.0}\\underbrace{T}_{0.0}$$</p>").concat(
"<p>\\(J\\) is proportional to \\(R^4\\) so increasing \\(R\\) actually decreases \\(\\frac{R}{J}\\)").concat(//If the cross-section is a circle \\(J=\\frac{1}{2}\\pi R^4\\) (you can prove this for yourself) so:</p>").concat(
//"<p>$$\\underbrace{\\tau_{max}}_{0.0}=\\underbrace{\\frac{2}{\\pi R^3}}_{0.0}\\underbrace{T}_{0.0}$$</p>").concat(
"<p>For a thinner rod, more stress is required to produce the same torque, so as you would except a thinner rod twists more. The next stage relates these stresses to strains in the rod.</p>")
text[2]=(
"<p>The shear stress produces a proportional shear strain:</p>").concat(
"<p>$$\\underbrace{\\gamma}_{0.0}=\\underbrace{\\frac{1}{G}}_{0.0}\\underbrace{\\tau}_{0.0}$$</p>").concat(
"<p>\\( \\gamma\\), the shear strain, is the angle a section of the rod deforms.</p>").concat(
"<p>This equation relates the loads on the object with the deformation using the material properties. However, we generally care about rod twists at the end, not the shearing angle along the length. The two can be related through geometry.</p>")
text[3]=(
"<p>The shear strain \\(\\gamma\\) causes the overall twisting deformation of the rod. The relation between \\(\\gamma\\) and \\(\\phi\\) , the angle of twists, is a simple proportion which can be seen in the graphic:</p>").concat(
"<p>$$\\underbrace{L}_{0.0}\\underbrace{\\gamma}_{0.0}=\\underbrace{R}_{0.0}\\underbrace{\\phi}_{0.0}$$</p>").concat(
"<p>\\(\\phi\\) will be greater for a longer rod for the same strain. In other words, a longer rod twists more if you apply the same torque on it.</p>")
text[4]=(
"<p>The results from the previous slides are the following:</p>").concat(
"<p>$$\\tau_{max}=\\frac{TR}{J}$$</p>").concat(
"<p>$$\\gamma=\\frac{\\tau}{G}$$</p>").concat(
"<p>$$L\\gamma=R\\phi$$</p>").concat(
"<p>This can be combined to give the following result:</p>").concat(
"<p>$$\\phi=\\frac{LT}{GJ}$$</p>").concat(
"<p>The angle of twist is dependent on the rod geometry \\(L\\) and \\(J\\), shear modulus \\(G\\), and of course the applied torque \\(T\\).</p>").concat(
"<p>This topic goes through the process of determining the stress on the material, relating the stresses and strains, and relating the strains to deflection. You will see processes like this throughout your time studying structures in civil engineering.</p>")
// calls makePage with defined labels and function:
makePage(titles,text,makeYourGraphics)
// You can also create an array for the text in the text box and refer to it in the changeStageGraphics method
function makeYourGraphics(textDiv,graphDiv){
//! textDiv is never used
//#region <define initial values>
var initR=2
var initH=1
var s=.15 // approximate side length of square of grid (rounds to whole number of grids)
var initT=100
var initG=50
var nCoils=20
var nRings=6
var thick=.01
var wrapFrac=0
var gridColor=vec(.3,.3,1)
var arrowScale=.1
var nArrowsR=5 //number of arrowGroup radially
var nArrowsS=8 // number of arrowGroup around loop
var patchColor=color.green
var nPatchPoints=10 //number of points in each direction (total number is square of this)
var nYSec=2 // the section to highlight (1 would mean highlight second from bottom)
//#endregion
var strainCloseUp=document.createElement("div")
Object.assign(strainCloseUp.style,{
zIndex: 1,
bottom: 0,
width: "30%",
height: "30%"
})
graphDiv.appendChild(strainCloseUp)
//#region <set up canvas>
window.__context= {glowscript_container: graphDiv}
var scene=canvas({width: graphDiv.offsetWidth,height: graphDiv.offsetHeight,resizable: false,userzoom: false,autoscale: false})
// use scene.center scene.forward scene.range to change scene
scene.forward=vec(-3,-2,-1)
scene.range=5
//#endregion
//#region <Create GlowScript graphics and combine in arrays>
var rod=cylinder({pos: vec(0,0,0), opacity: 1})
var coils=[]
var nCoilPoints=10 // number of points on helix
for (let i=0;i<nCoils;i++){coils[i]=curve({pos: Array(nCoilPoints).fill(vec(0,0,0)),thickness: thick, color: gridColor})}
var rings=[]
for (let i=0;i<nRings;i++){rings[i]=ring({pos: vec(0,0,0), axis: vec(0,1,0),thickness: thick, color: gridColor})}
var xGrid=yGrid=zGrid=math.zeros(nPatchPoints,nPatchPoints)._data
var patch=makeSurf(xGrid,yGrid,zGrid,patchColor)
var arrowGroup=[]
for (let sideN=0;sideN<2;sideN++){
arrowGroup[sideN]=[]
for (let i=0;i<nArrowsS;i++){
arrowGroup[sideN][i]=[]
for (let j=0;j<nArrowsR;j++){
arrowGroup[sideN][i][j]=arrow({color: color.red})
}
}
}
//#endregion
//#region <create widgets and combine into array (onlick is update)>
var sliderLength=300
var torqueSlider=makeSliderGroup(graphDiv,"50%","80%","Torque",sliderLength,"horizontal",[-100,100],initT,update)
var radiusSlider=makeSliderGroup(graphDiv,"0%","80%","Radius",sliderLength,"horizontal",[2,5],initR,update)
var heightSlider=makeSliderGroup(graphDiv,"0%","90%","Height",sliderLength,"horizontal",[0,5],initH,update)
var gSlider=makeSliderGroup(graphDiv,"50%","90%","Shear Modulus",sliderLength,"horizontal",[10,100],initG,update)
radiusSlider.style.zIndex=heightSlider.style.zIndex=1
//#endregion
//#region <create labels and geometry lines>
var phiLabel=label({text: "Φ",box: false})
var gammaLabel=label({text: "γ",box:false})
var geometryLines=[]
for (let i=0;i<4;i++){geometryLines[i]= curve({pos: [vec(0,0,0),vec(0,0,0)], thickness: thick, color: color.black})}
//#endregion
//#region <create strain close up>
window.__context= {glowscript_container: strainCloseUp}
var strainScene=canvas({width: strainCloseUp.offsetWidth,height: strainCloseUp.offsetHeight,resizable: false,userzoom: false,autoscale: false})
strainScene.range=2
var vertices=[]
for (let i=0;i<4;i++){vertices[i]=vertex({pos: vec(0,0,0)})}
var patch2D=quad({vs: vertices})
var patchArrows=[]
for (let i=0;i<4;i++){patchArrows[i]=arrow({color: color.red})}
//#endregion
//create text with equations, combine into array and append on textDiv
MathJax.Hub.Queue(RS_list_decorate([ "Typeset", MathJax.Hub ]),update) // you could add multiple functions to update different things
//#region <create image>
var photo=document.createElement("img")
photo.src="torsion_tacoma.jpg"
photo.style.position="absolute"
photo.style.left=0
photo.style.height="100%"
photo.style.zIndex=2
graphDiv.appendChild(photo)
//#endregion
function update(){
//#region <get values from sliders and define phsyical variables>
var T=Number(torqueSlider.children[2].value)
var r=Number(radiusSlider.children[2].value)
var h=Number(heightSlider.children[2].value)
var G=Number(gSlider.children[2].value)
var J=1/2*Math.PI*r**4;
var phi=T*h/(J*G);
var gamma=phi*r/h;
var s_max=T*r/J;
//#endregion
//#region <change properties of cylinder, rings, and coils>
// change cylinder:
rod.axis=vec(0,h,0)
rod.radius=r
// change coils:
for (let i=0;i<nCoils;i++){
var coilPoints=[]
for (let j=0;j<nCoilPoints;j++){
var angle=-phi*j/(nCoilPoints-1)+2*Math.PI*i/nCoils
coilPoints[j]=vec(r*cos(angle),h*j/(nCoilPoints-1),r*sin(angle))
coils[i].modify(j,coilPoints[j])
}
}
// change ring height:
for (let i=0;i<nRings;i++){
rings[i].pos.y=h*i/(nRings-1)
rings[i].radius=r
}
//#endregion
//#region <change patch>
var theta=math.range(0,phi,.2)._data
var thetaShift=phi/(nRings-1)
var thetaGrid=[]
var yGrid=[]
var gap=0.001 // gap so it's not directly on cylinder
var rGrid=math.multiply(math.ones(nPatchPoints,nPatchPoints)._data,r+gap)
for (let i=0;i<nPatchPoints;i++){
yGrid[i]=Array(nPatchPoints).fill(h*i/((nRings-1)*(nPatchPoints-1))+h*nYSec/(nRings-1))
thetaGrid[i]=[]
for (let j=0;j<nPatchPoints;j++){
var shiftR=2*Math.PI/(nCoils)*j/(nPatchPoints-1)
var shiftY=phi/(nRings-1)*i/(nPatchPoints-1)
thetaGrid[i].push(-(shiftR+shiftY+nYSec/(nRings-1)*phi))
}
}
xGrid=math.dotMultiply(rGrid,math.cos(thetaGrid))
zGrid=math.dotMultiply(rGrid,math.sin(thetaGrid))
changeSurf(patch,xGrid,yGrid,zGrid)
//#endregion
//#region <change arrows>
for (let sideN=0;sideN<2;sideN++){
if (sideN==0){var y=h; var sign=-1}
else if (sideN==1){var y=0; var sign=1}
for (let i=0;i<nArrowsS;i++){
var thetaArrow=2*Math.PI*i/nArrowsS
for (let j=0;j<nArrowsR;j++){
var arrowSel=arrowGroup[sideN][i][j]
var arrowR=0.9*r*(j+1)/5
var mag=s_max*sign*arrowR/r
arrowSel.pos=vec(arrowR*cos(thetaArrow),y,arrowR*sin(thetaArrow))
arrowSel.axis=vec(-mag*sin(thetaArrow)*arrowScale,0,mag*cos(thetaArrow)*arrowScale)
}
}
}
//#endregion
//#region <change labels and geometry lines>
phiLabel.pos=vec(0,h+.1,0)
gammaLabel.pos=vec(r+.1,0,0)
geometryLines[0].modify(0,vec(r,0,0));geometryLines[0].modify(1,vec(r,h,0))
geometryLines[1].modify(0,vec(0,h,0));geometryLines[1].modify(1,vec(r,h,0))
geometryLines[2].modify(0,vec(0,h,0));geometryLines[2].modify(1,vec(r*cos(-phi),h,r*sin(-phi)))
//#endregion
//#region <change strain close up>
var quadPoints=[vec(-1,-1,0),vec(1,-1,0),vec(1+gamma*2,1,0),vec(-1+gamma*2,1,0)]
var quadVertices=[]
for (let i=0;i<4;i++){
quadVertices[i]=vertex({pos: quadPoints[i], color: patchColor})
}
patch2D.vs=quadVertices
for (let i=0;i<4;i++){
var i1=i
var i2=i1+1
if (i2==4){i2=0}
if (i1%2==0){[i1,i2]=[i2,i1]}
var u=quadPoints[i2].add(quadPoints[i1].multiply(-1)).hat.multiply(s_max/10)
var mid=quadPoints[i1].add(quadPoints[i2]).divide(2)
patchArrows[i].pos=mid.add(u.multiply(-0.5))
patchArrows[i].axis=u
}
//#endregion
var stageText=document.getElementsByClassName("stage-text") // accesses the divs containing the text for each stage
// use changeUnderText to change the underbrace values, with stageText[stage you want to change underbrace for]
changeUnderText(1,s_max,1,stageText[1])
changeUnderText(2,2/(Math.PI*r**3),2,stageText[1])
changeUnderText(3,T,2,stageText[1])
changeUnderText(1,gamma,2,stageText[2])
changeUnderText(2,1/G,2,stageText[2])
changeUnderText(3,s_max,1,stageText[2])
changeUnderText(1,h,1,stageText[3])
changeUnderText(2,gamma,2,stageText[3])
changeUnderText(3,r,2,stageText[3])
changeUnderText(4,phi,2,stageText[3])
}
// update functions for graphics (called when widgets toggled)
// change the graphic for each stage (must be named exactly changeStageGraphic):
makeYourGraphics.changeStageGraphic=function(stage){
var TS=arrowGroup // torque stress
var SS=[patch,patch2D,patchArrows] // stress strain
var SD=[phiLabel,gammaLabel,geometryLines] // strain deformation
var TI=torqueSlider.style // torque input
var RI=radiusSlider.style
var HI=heightSlider.style
var GI=gSlider.style
if (stage==0){
changeOpacity(TS,0)
changeVisibility([SS,SD],false)
TI.visibility=RI.visibility=HI.visibility=GI.visibility="hidden"
photo.style.visibility="visible"
}else if (stage==1){
changeOpacity([TS],1)
changeVisibility([SS,SD],0)
HI.visibility=GI.visibility="hidden";TI.visibility=RI.visibility="visible"
photo.style.visibility="hidden"
}else if (stage==2){
changeOpacity(TS,1);
changeVisibility(SS,1);changeVisibility(SD,0)
HI.visibility=RI.visibility="hidden";TI.visibility=GI.visibility="visible"
photo.style.visibility="hidden"
}else if (stage==3){
changeOpacity(TS,0.1)
changeVisibility(SD,1);changeVisibility(SS,0)
GI.visibility=RI.visibility="hidden";TI.visibility=HI.visibility="visible"
photo.style.visibility="hidden"
// change color of helix
}else if (stage==4){
changeOpacity([TS],1)
changeVisibility([SS,SD],0)
TI.visibility=RI.visibility=HI.visibility=GI.visibility="visible"
photo.style.visibility="hidden"
}
if (stage==3){coils[0].color=color.black}
else{coils[0].color=gridColor}
// variables with short names can be set to the style of the shapes (just less to write for branches)
// branches for each stage
// change opacity of shapes and visiblity of slider (call changeOpacity)
}
}
</script>