-
Notifications
You must be signed in to change notification settings - Fork 2
/
stress3D.html
481 lines (314 loc) · 20.1 KB
/
stress3D.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
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
<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/numjs@0.15.1/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=["Zooming In","Normal","Normal: All Directions","Shear","All Stresses"]
var text=[]
text[0]=(
"<p>It's important, especially for civil engineers, to understand how things will deform when loads are applied. More specifically, it's useful to understand the relation between stress, load per area, and strain, the change in material dimensions. </p>").concat(
"<p>To analyze this relation, it's helpful to consider a tiny, or more precisely infinitesimal, piece and consider the stresses acting on that element. Because it's so small, it's assumed that the stress is the same throughout the element. This analysis assumes the material is linear elastic, meaning stress and strain are linearly proportional.</p><p>The analyzed cube can be part of a larger structure, like a bridge foundation. Photo credit to bristol.ac.uk</p>")
text[1]=(
"<p>In the graphic, a normal stress is applied in the x direction, leading to a strain in the same direction.</p>").concat(
"<p>$$\\underbrace{\\epsilon_x}_{0.0}=\\frac{\\color{red}{\\sigma_x}}{E}$$</p>").concat(
"<p>However, if you've ever stretched a piece of rubber, you'll notice that the material stretches contracts laterally. Similarly, if you squeeze it, it will bulge out laterally. This relation between the axial strain and the lateral strain is the following:</p>").concat(
"<p>$$\\nu=-\\frac{\\epsilon_{lateral}}{\\epsilon_{axial}}$$</p>").concat(
"<p>In general, \\(\\nu\\) is a positive number less than 0.5. There are cases where it is negative (stretching it one direction leads to expansion in others) as shown <a href='silver.neep.wisc.edu/~lakes/Poisson.html'>here</a>.</p>").concat(
"<p>So:</p>").concat(
"<p>$$\\underbrace{\\epsilon_y}_{0.0}=-\\nu\\frac{\\color{red}{\\sigma_x}}{E}$$</p>").concat(
"<p>$$\\underbrace{\\epsilon_z}_{0.0}=-\\nu\\frac{\\color{red}{\\sigma_x}}{E}$$</p>").concat(
"<p>This is for stress applied in one direction. What happens when a material's loaded in multiple directions?</p>")
text[2]=(
"<p>In general, stress would be applied in multiple directions, not just one. The strain due to each of the stresses can be added together to find the total strain. For example:</p>").concat(
"<p>$$\\underbrace{\\epsilon_x}_{0.0}=\\underbrace{\\frac{1}{E}\\color{red}{\\sigma_x}}_{0.0}\\underbrace{-\\frac{\\nu}{E}\\color{green}{\\sigma_y}}_{0.0}\\underbrace{-\\frac{\\nu}{E}\\color{blue}{\\sigma_z}}_{0.0}$$</p>").concat(
"<p>The strain caused by stress in the x,y, and z direction are added together to find the total stress. This same relation holds true for strain in the y and z direction:</p>").concat(
"<p>$$\\underbrace{\\epsilon_y}_{0.0}=\\underbrace{-\\frac{\\nu}{E}\\color{red}{\\sigma_x}}_{0.0}\\underbrace{+\\frac{1}{E}\\color{green}{\\sigma_y}}_{0.0}\\underbrace{-\\frac{\\nu}{E}\\color{blue}{\\sigma_z}}_{0.0}$$</p>").concat(
"<p>$$\\underbrace{\\epsilon_z}_{0.0}=\\underbrace{-\\frac{\\nu}{E}\\color{red}{\\sigma_x}}_{0.0}\\underbrace{-\\frac{\\nu}{E}\\color{green}{\\sigma_y}}_{0.0}\\underbrace{+\\frac{1}{E}\\color{blue}{\\sigma_z}}_{0.0}$$</p>").concat(
"<p>This is still missing half of the picture though. What happens when the stress isn't applied normal to the surface?</p>")
text[3]=(
"<p>Stress can also be applied along the surface instead of normal to it; this is called a shear stress.</p>").concat(
"<p>Shear stress is denoted with two subscripts, the first is the direction normal to the surface, and the second the direction the stress is applied. For example, \\(\\tau_{xy}\\) indicates a shear stress acting on the x plane in the y direction. To balance the forces in the y direction, there must be a stress applied on the other side in the opposite direction.</p>").concat(
"<p>Just as with normal stress and strain, there is a linear relation between shear stress and strain:</p>").concat(
"<p>$$\\underbrace{\\gamma}_{0.0}=\\frac{\\tau}{G}$$</p>").concat(
"<p>where \\(G\\) is the shear modulus. Note that \\(G\\) is dependent on \\(E\\) and \\(\\nu\\) as shown <a href='http://polymerdatabase.com/polymer%20physics/Moduli.html'>here</a></p>").concat(
"<p>If it was only those two stresses were applied though, there would be a force couple, and the element would start spinning. To balance this, there has to be shear stresses on the y plane in the x direction or \\(\\tau_{yx}\\). The two must balance each other, so in general:</p>").concat(
"<p>$$\\tau_{xy}=\\tau_{yx}$$</p>").concat(
"<p>Of course, nothing's special about the x and y directions: the same holds true for all directions...</p>")
text[4]=(
"<p>In total, there are three normal stresses and three shear stresses which produce the strains on a material element:</p>").concat(
"<p>$$\\epsilon_x=+\\frac{1}{E}\\sigma_x-\\frac{\\nu}{E}\\sigma_y-\\frac{\\nu}{E}\\sigma_z$$</p>").concat(
"<p>$$\\epsilon_y=-\\frac{\\nu}{E}\\sigma_x+\\frac{1}{E}\\sigma_y-\\frac{\\nu}{E}\\sigma_z$$</p>").concat(
"<p>$$\\epsilon_z=-\\frac{\\nu}{E}\\sigma_x-\\frac{\\nu}{E}\\sigma_y+\\frac{1}{E}\\sigma_z$$</p>").concat(
"<p>$$\\gamma_{xy}=\\frac{\\tau_{xy}}{G}$$</p>").concat(
"<p>$$\\gamma_{xz}=\\frac{\\tau_{xz}}{G}$$</p>").concat(
"<p>$$\\gamma_{yz}=\\frac{\\tau_{yz}}{G}$$</p>").concat(
"<p>The total strain is the sum of these normal and shear strains. </p>").concat(
"<p>This is more theoretical than other topics. We are simply considering some infinitesimal cube in a larger object. But it is also critical for understanding how the loads applied relates to the deformation for any structure, as one can always consider this tiny cube within any structure.</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){
//#region <define initial values>
//#endregion
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.range=4
//#region <Create GlowScript graphics and combine in array>
var colors=[vec(1,0,0),vec(0,1,0),vec(0,0,1),
vec(0,1,1),vec(1,0,1),vec(1,1,0)]
var sColorsN=["#f00","#0f0","#00f"]
var sColorsV=["#0ff","#f0f","#ff0"]
var scale=8
var coordShape=makeCoordShape(vec(1.2,1.2,1.2))
var box0=[]
var boxP=[]
for (let i=0;i<6;i++){
var vertices=[]
var verticesP=[]
for (let j=0;j<4;j++){
vertices[j]=vertex({pos: vec(0,0,0), opacity: 0.5})
verticesP[j]=vertex({pos: vec(0,0,0), opacity: 1})
}
box0[i]=quad({vs: vertices})
boxP[i]=quad({vs: verticesP})
}
var arrowsN=[]
for (let i=0;i<6;i++){arrowsN[i]=arrow({pos: vec(0,0,0),axis: vec(0,0,0), color: colors[floor(i/2)]})}
var arrowsV=[]
for (let i=0;i<12;i++){arrowsV[i]=arrow({pos: vec(0,0,0),axis: vec(0,0,0), color: colors[floor(i/4)+3]})}
var points=[
vec(-1,-1,-1),
vec(1,-1,-1),
vec(1,-1,1),
vec(-1,-1,1),
vec(-1,1,-1),
vec(1,1,-1),
vec(1,1,1),
vec(-1,1,1)]
var midPoints=[
vec(-1,0,0),
vec(1,0,0),
vec(0,-1,0),
vec(0,1,0),
vec(0,0,-1),
vec(0,0,1)]
var faces=[[0,1,5,4]
,[1,2,6,5]
,[2,3,7,6]
,[3,0,4,7]
,[3,2,1,0]
,[4,5,6,7]]
//#region
//#region <create widgets and combine into array (onlick is update)>
var sliderLength=200
var sliderPosHor=["-5%","28%","61%"]
var sliderPosVer=["80%","90%"]
var slidersN=[]
var slidersV=[]
var textN=["x","y","z"]
var textV=["xy","xz","yz"]
for (let i=0;i<3;i++){
slidersN[i]=makeSliderGroup(graphDiv,sliderPosHor[i],sliderPosVer[0],("\\(\\sigma_").concat(textN[i]).concat("\\)"),sliderLength,"horizontal",[-10,10],0,update,sColorsN[i])
slidersV[i]=makeSliderGroup(graphDiv,sliderPosHor[i],sliderPosVer[1],("\\(\\tau_{").concat(textV[i]).concat("}\\)"),sliderLength,"horizontal",[-10,10],0,update,sColorsV[i])
}
var ESlider=makeSliderGroup(graphDiv,"5%","65%","Young's Modulus",30,"vertical",[0,200],100,update,"#333",false,1)
var nuSlider=makeSliderGroup(graphDiv,"15%","65%","Poisson's Ratio",30,"vertical",[-1,0.5],0.3,update,"#333",false,0.05 )
var GSlider=makeSliderGroup(graphDiv,"25%","65%","Shear Modulus",30,"vertical",[0,500],0,update,"#333",false,0.1,true )
var resetButton=document.createElement("BUTTON")
resetButton.onclick=reset
resetButton.appendChild(document.createTextNode("RESET"))
Object.assign(resetButton.style,{
position: "absolute",
left: "5%",
top: "50%"
})
graphDiv.appendChild(resetButton)
//#endregion
//#region <create text with equations, combine into array and append on textDiv>
//#endregion
function reset(){
for (let i=0;i<3;i++){
slidersN[i].children[1].value=slidersN[i].children[2].value=0
slidersV[i].children[1].value=slidersV[i].children[2].value=0
}
ESlider.children[1].value=100
nuSlider.children[1].value=0.3
update()
}
var stressIMG=document.createElement("img")
stressIMG.src="stress3D.png"
stressIMG.style.position="absolute"
stressIMG.style.left=0
stressIMG.style.width="100%"
stressIMG.style.zIndex=2
graphDiv.appendChild(stressIMG)
MathJax.Hub.Queue(RS_list_decorate([ "Typeset", MathJax.Hub ]),update) // you could add multiple functions to update different things
function update(){
var s=[]
var t=[]
for (let i=0;i<3;i++){
s[i]=Number(slidersN[i].children[1].value)
t[i]=Number(slidersV[i].children[1].value)
}
var sx=s[0];var sy=s[1];var sz=s[2]
var txy=t[0];var txz=t[1];var tyz=t[2]
var E=Number(ESlider.children[1].value)
var nu=Number(nuSlider.children[1].value)
var G=E/(2*(1+nu))
GSlider.children[1].value=G
var sv=[[sx],[sy],[sz]]
var M=[[sx,txy,txz],[txy,sy,tyz],[txz,tyz,sz]]
var Eigen=math.eigs(M)
var D=Eigen.values
var W=Eigen.vectors
var stressPrinc=[[D[0]],[D[1]],[D[2]]]
var compM=math.multiply(-nu,math.ones(3,3)._data)
compM[0][0]=compM[1][1]=compM[2][2]=1
compM=math.divide(compM,E)
var strain=math.multiply(compM,stressPrinc)
var strainM=[[strain[0][0],0,0],[0,strain[1][0],0],[0,0,strain[2][0]]]
var strainpM=math.multiply(math.inv(math.transpose(W)),strainM,math.transpose(W))
var strainp=[[strainpM[0][0]],[strainpM[1][1]],[strainpM[2][2]]]
var disp=math.add(strainpM,math.identity(3)._data)
var pointsM=vecToMat(points)
var midPointsM=vecToMat(midPoints)
var pointsNM=math.transpose(math.multiply(disp,math.transpose(pointsM)))
var midPointsNM=math.transpose(math.multiply(disp,math.transpose(midPointsM)))
var vx=math.subtract(pointsNM[1],pointsNM[0])
var vy=math.subtract(pointsNM[4],pointsNM[0])
var vz=math.subtract(pointsNM[3],pointsNM[0])
var vnM=math.transpose([vx,vy,vz])
changeBox(box0,pointsM)
changeBox(boxP,pointsNM)
function changeBox(box,points){
var pointsV=matToVec(points)
for (let i=0;i<6;i++){
var vertices=[]
var sidePoints=[];for(let j=0;j<4;j++){sidePoints[j]=pointsV[faces[i][j]]}
var a=sidePoints[0];var b=sidePoints[1];var c=sidePoints[2]
var lightNorm=a.sub(b).cross(c.sub(b)).norm()
for (let j=0;j<4;j++){
box[i].vs[j].pos=pointsV[faces[i][j]]
box[i].vs[j].normal=lightNorm
}
}
}
// create quads:
// scale and colors are defined here in MATLAB
var snM=math.dotMultiply(math.identity(3)._data,math.transpose(Array(3).fill(math.transpose(sv).flat())))
var snMp=math.multiply(disp,snM)
for (let i=0;i<3;i++){
var snvp=math.transpose(snMp)[i]
if (math.norm(snvp)!=0){var usnvp=math.divide(snvp,math.norm(snvp))}
else{var usnvp=snvp}
var arrowStart=math.transpose(midPointsNM[2*i+1])
var arrowAxis=math.multiply(usnvp,sv[i]/scale)
if (snvp[i]<0){
arrowStart=math.add(arrowStart,arrowAxis)
arrowAxis=math.multiply(arrowAxis,-1)
}
arrowStartV=vec(arrowStart[0],arrowStart[1],arrowStart[2])
arrowAxisV=vec(arrowAxis[0],arrowAxis[1],arrowAxis[2])
arrowsN[2*i].pos=arrowStartV
arrowsN[2*i].axis=arrowAxisV
arrowsN[2*i+1].pos=arrowStartV.multiply(-1)
arrowsN[2*i+1].axis=arrowAxisV.multiply(-1)
for (let j=0;j<3;j++){
if(j>i){
var tau=M[i][j]
var vn=math.transpose(vnM)[j]
if (math.norm(vn)!=0){var uvn=math.divide(vn,math.norm(vn))}
else{var uvn=vn}
var arrowStart=math.subtract(math.transpose(midPointsNM[2*i+1]),math.multiply(uvn,tau/(2*scale)))
var arrowAxis=math.multiply(uvn,tau/scale)
var arrowStartV=vec(arrowStart[0],arrowStart[1],arrowStart[2])
var arrowAxisV=vec(arrowAxis[0],arrowAxis[1],arrowAxis[2])
arrowsV[4*(i+j-1)].pos=arrowStartV
arrowsV[4*(i+j-1)].axis=arrowAxisV
arrowsV[4*(i+j-1)+1].pos=arrowStartV.multiply(-1)
arrowsV[4*(i+j-1)+1].axis=arrowAxisV.multiply(-1)
vn=math.transpose(vnM)[i]
if (math.norm(vn)!=0){uvn=math.divide(vn,math.norm(vn))}
else{uvn=vn}
var arrowStart=math.subtract(math.transpose(midPointsNM[2*j+1]),math.multiply(uvn,tau/(2*scale)))
var arrowAxis=math.multiply(uvn,tau/scale)
var arrowStartV=vec(arrowStart[0],arrowStart[1],arrowStart[2])
var arrowAxisV=vec(arrowAxis[0],arrowAxis[1],arrowAxis[2])
arrowsV[4*(i+j-1)+2].pos=arrowStartV
arrowsV[4*(i+j-1)+2].axis=arrowAxisV
arrowsV[4*(i+j-1)+3].pos=arrowStartV.multiply(-1)
arrowsV[4*(i+j-1)+3].axis=arrowAxisV.multiply(-1)
}
}
}
//#region <get values from sliders and define phsyical values>
//#endregion
//#region <change shapes>
//#endregion
var stageText=document.getElementsByClassName("stage-text") // accesses the divs containing the text for each stage
//#region <use changeUnderText to change the underbrace values, with stageText[stage you want to change underbrace for]>
changeUnderText(1,strainp[0][0],2,stageText[1])
changeUnderText(2,strainp[1][0],2,stageText[1])
changeUnderText(3,strainp[2][0],2,stageText[1])
changeUnderText(1,t[0]/G,2,stageText[3])
for (let i=0;i<3;i++){
changeUnderText(i*4+1,strainp[i][0],2,stageText[2])
changeUnderText(i*5+2,sv[i][0]/E,2,stageText[2])
for (let j=0;j<3;j++){
if (i!=j){
changeUnderText(i*4+2+j,-sv[j][0]/E*nu,2,stageText[2])
}
}
}
//#endregion
}
// change the graphic for each stage (must be named exactly changeStageGraphic):
makeYourGraphics.changeStageGraphic=function(stage){
try{reset()}catch(err){}
// variables with short names can be set to the style of the shapes (just less to write for branches)
var IMG=stressIMG.style
if (stage==0){
for (let i=0;i<3;i++){slidersN[i].style.visibility=slidersV[i].style.visibility="hidden"}
IMG.visibility="visible"
GSlider.style.visibility="hidden"
}else if (stage==1){
for (let i=0;i<3;i++){slidersN[i].style.visibility=slidersV[i].style.visibility="hidden"}
IMG.visibility="hidden"
slidersN[0].style.visibility="visible"
GSlider.style.visibility="hidden"
}else if (stage==2){
for (let i=0;i<3;i++){slidersV[i].style.visibility="hidden";slidersN[i].style.visibility="visible"}
IMG.visibility="hidden"
GSlider.style.visibility="hidden"
}else if (stage==3){
for (let i=0;i<3;i++){slidersN[i].style.visibility=slidersV[i].style.visibility="hidden"}
slidersV[0].style.visibility="visible"
IMG.visibility="hidden"
GSlider.style.visibility="visible"
}else if (stage==4){
for (let i=0;i<3;i++){slidersN[i].style.visibility=slidersV[i].style.visibility="visible"}
IMG.visibility="hidden"
GSlider.style.visibility="visible"
}
}
}
//#endregion
</script>