Испытания на разрыв и сжатие плоского тела
Курсовой проект по Механике дискретных сред
Исполнитель: Старобинский Егор
Группа: 09 (43604/1)
Семестр: осень 2016
Описание
Проводятся эксперименты сжатия и растяжения плоского тела на примере поликристалла. Поликристалл моделируется множеством материальных точек, разделённых на области с разной жёсткостью связи (используется потенциал Леннард-Джонса с конечным радиусом обрезания). На плоскости строится диаграмма Вороного, каждая точка тела попадает в одну из областей и получает соответствующий коэффициент (различный для разных областей). При расчёте силы взаимодействия между двумя точками их коэффициенты складываются, получившиеся значение есть жёсткость связи в потенциале. Диаграмма напряжений строится вплоть до момента потери устойчивости.
В рамках эксперимента скорость деформации постоянна. Поликристалл может содержать до 17 областей. Уравнения динамики решаются с помощью метода интегрирования Верле.
Решение задачи и визуализация написаны нa JavaScript, диаграмма Вороного получается POST запросом к серверу (расчёты производятся программой на C++ с помощью алгоритма Форчуна, парсер написан на PHP).
Результат
1 var points = [{'x': 591, 'y':474},
2 {'x': 94, 'y':587},
3 {'x': 200, 'y':540},
4 {'x': 577, 'y':71},
5 {'x': 415, 'y':584},
6 {'x': 225, 'y':302},
7 {'x': 93, 'y':154},
8 {'x': 127, 'y':123},
9 {'x': 209, 'y':313},
10 {'x': 32, 'y':290}];
11 var pressureSign = 1;
12 var fragmentation = false;
13 var animationSpeed = 40;
14 var strainRate = 10;
15
16 var integrator = VerletIntegrator;
17 var t = 0;
18 var dt = 0.005;
19 var timeValue = document.getElementById('timeValue');
20
21 var particleRadius = 6;
22 var numberOfColumns = 29;
23 var numberOfRows = 29;
24 var cm = [ 0.754335746098413,
25 0.8107304103877537,
26 0.9306594025241637,
27 0.9667586023289361,
28 0.7504112576761824,
29 0.828054551661692,
30 0.9496843639510728,
31 0.9562931712096583,
32 0.8953204544716538,
33 0.7549681403247804,
34 0.892707460881279,
35 0.7946054751314912,
36 0.9651534693380119,
37 0.9753409489560376,
38 0.828824739204054,
39 0.7564226662369037,
40 0.8476944814390296];
41
42 var colors = ["Turquoise",
43 "Yellow",
44 "YellowGreen",
45 "Teal",
46 "White",
47 "BlueViolet",
48 "Tomato",
49 "Silver",
50 "Gray",
51 "Orange",
52 "SpringGreen",
53 "WhiteSmoke",
54 "Linen",
55 "PaleGreen",
56 "FireBrick",
57 "SlateGray",
58 "Bisque"];
59
60 function indexOfTheNearestPoint(x, y){
61 var squareLength = [];
62 for(var i = 0; i < points.length; ++i){
63 squareLength[i] = Math.pow(points[i].x - x, 2) + Math.pow(points[i].y - y, 2);
64 }
65 return squareLength.indexOf(Math.min.apply(null, squareLength));
66 }
67 var particles = [];
68
69 var stepBetweenColumns = (canvas.width / numberOfColumns);
70 var stepBetweenRows = stepBetweenColumns * Math.sin(Math.PI/3);
71 numberOfRows = Math.ceil(canvas.width / stepBetweenRows);
72 if(!(numberOfRows % 2)){
73 --numberOfRows;
74 }
75 canvas.height = numberOfRows * stepBetweenRows;
76 var halfOfStepBetweenColumns = 0.5 * stepBetweenColumns;
77 var halfOfStepBetweenRows = 0.5 * stepBetweenRows;
78
79 for(var k = 0, l = 0; k < numberOfRows; ++k){
80 if(k % 2){
81 for(var i = 0, j = halfOfStepBetweenColumns; i < numberOfColumns - 1; ++i){
82 var x = halfOfStepBetweenColumns + j;
83 var y = halfOfStepBetweenRows + l;
84 j += stepBetweenColumns;
85
86 var index = indexOfTheNearestPoint(x, y);
87 var particle = createVerletElement([x, y], null, 1, 'circle', [particleRadius], colors[index]);
88 particle.c = cm[index];
89 particles.push(particle);
90 }
91 }else{
92 for(var i = 0, j = 0; i < numberOfColumns; ++i){
93 var x = halfOfStepBetweenColumns + j;
94 var y = halfOfStepBetweenRows + l;
95 j += stepBetweenColumns;
96
97 var index = indexOfTheNearestPoint(x, y);
98 var particle = createVerletElement([x, y], null, 1, 'circle', [particleRadius], colors[index]);
99 particle.c = cm[index];
100 particles.push(particle);
101 }
102 }
103 l += stepBetweenRows;
104 }
105 var helper2 = [];
106 for(var i = 0; i < particles.length; i += 2 * numberOfColumns - 1){
107 helper2.push(i);
108 helper2.push(i - 1 + numberOfColumns);
109 helper2.push(i + numberOfColumns);
110 helper2.push(i - 2 + 2 * numberOfColumns);
111 }
112 for(var i = 0; i < particles.length; ++i){
113 if(helper2.indexOf(i) >= 0){
114 particles[i].color = 'rgb(255, 200, 40)';
115 }
116 }
117 function applyInitionalConditions(){
118 for(var i = 0; i < numberOfColumns; ++i){
119 particles[i].previousPosition.y = particles[i].position.y - strainRate * dt * pressureSign;
120 particles[particles.length - i - 1].previousPosition.y = particles[particles.length - i - 1].position.y + strainRate * dt * pressureSign;
121 particles[i].color = 'crimson';
122 particles[particles.length - i - 1].color = 'crimson';
123 }
124 }
125 applyInitionalConditions();
126 draw();
127 drawLine(460.258514, 276.798706, 600.000000, 271.944183,4, 'dodgerblue');
128 drawLine(410.950745, 381.721161, 547.375000, 600.000000,4, 'dodgerblue');
129 drawLine(254.635513, 600.000000, 254.635513, 600.000000,4, 'dodgerblue');
130 drawLine(0.000000, 451.651520, 89.154579, 433.040131,4, 'dodgerblue');
131 drawLine(0.000000, 193.966919, 127.067291, 250.960342,4, 'dodgerblue');
132 drawLine(0.000000, 17.854839, 176.980927, 211.962967,4, 'dodgerblue');
133 drawLine(340.791107, 0.000000, 354.080383, 115.003471,4, 'dodgerblue');
134 drawLine(333.749329, 433.736267, 299.723267, 600.000000,4, 'dodgerblue');
135 drawLine(89.154556, 433.040070, 163.183975, 600.000000,4, 'dodgerblue');
136 drawLine(333.749329, 433.736267, 410.950745, 381.721130,4, 'dodgerblue');
137 drawLine(301.455261, 430.344025, 333.749329, 433.736267,4, 'dodgerblue');
138 drawLine(89.154579, 433.040131, 104.770851, 422.545990,4, 'dodgerblue');
139 drawLine(460.258545, 276.798706, 410.950745, 381.721161,4, 'dodgerblue');
140 drawLine(161.072784, 226.151321, 301.455261, 430.344025,4, 'dodgerblue');
141 drawLine(104.770851, 422.545959, 301.455261, 430.344025,4, 'dodgerblue');
142 drawLine(127.067291, 250.960342, 104.770859, 422.545959,4, 'dodgerblue');
143 drawLine(354.080414, 115.003471, 460.258545, 276.798706,4, 'dodgerblue');
144 drawLine(127.067291, 250.960327, 161.072784, 226.151306,4, 'dodgerblue');
145 drawLine(176.980927, 211.962967, 354.080383, 115.003494,4, 'dodgerblue');
146 drawLine(161.072784, 226.151306, 176.980927, 211.962967,4, 'dodgerblue');
147 var textColor = 'rgb(255, 255, 255)';var D = 100;
148 if(-1 == pressureSign){
149 D *= 100;
150 }
151 var a = stepBetweenColumns;//23.131737698273685;// 1*32;
152 var cutLength = 1.5 * canvas.height;//Math.sqrt(2130);
153
154 var squareA = Math.pow(a, 2);
155 var squareCutLength = Math.pow(cutLength, 2);
156
157 var diagramData = {'x': [], 'y': []};
158 var diagramCanvas = document.getElementById('diagram');
159 var stepFromBoard = 7;
160 var step = 0;
161
162 function applyPhysics(){
163 var forces = [];
164 for(var j = 0; j < particles.length; ++j){
165 var forceX = 0;
166 var forceY = 0;
167 for(var i = 0; i < particles.length; ++i){
168 if(i == j){
169 continue;
170 }
171 var diffX = particles[j].position.x - particles[i].position.x;
172 var diffY = particles[j].position.y - particles[i].position.y;
173 var squareDiff = Math.pow(diffX, 2) + Math.pow(diffY, 2);
174 if(squareDiff > squareCutLength){
175 fragmentation = true;
176 continue;
177 }
178
179 var tmp = squareA / squareDiff;
180 var force = 0.5 * (particles[j].c + particles[i].c) * (12 * D / squareA) * (Math.pow(tmp, 7) - Math.pow(tmp, 4));
181 //-(particles[j].c + particles[i].c) * D * squareDiff / 100000;
182 forceX += force * diffX;
183 forceY += force * diffY;
184 }
185 forces[j] = {'x': 0, 'y': forceY};
186 }
187 var sigma = 0;
188 for(var i = 0; i < numberOfColumns; ++i){
189 sigma -= forces[i].y;// + forces[particles.length - i - 1].y;
190 forces[i] = {'x': 0, 'y': 0};
191 forces[particles.length - i - 1] = {'x': 0, 'y': 0};
192 }
193 if(!fragmentation){
194 var epsilon = pressureSign * (particles[1].position.y - halfOfStepBetweenRows) / (canvas.height - 2 * halfOfStepBetweenRows);
195 diagramData.x.push(epsilon);
196 diagramData.y.push(sigma / (numberOfColumns * 1));
197 plotFromData(diagramCanvas, diagramData, 'Stress-deformation diagram', 'rgb(56, 195, 237)', 2, textColor);
198 }
199 for(var j = 0; j < particles.length; ++ j){
200 integrator(particles[j], forces[j], dt);
201 }
202 timeValue.textContent = t.toFixed(2);
203 ++step;
204 }
205 function draw(){
206 ctx.clearRect(0, 0, canvas.width, canvas.height);
207 for(var i = 0; i < particles.length; ++i){
208 particles[i].draw();
209 }
210 }
211 document.getElementById('play').onclick = function(){
212 this.className = 'inprogress';
213 document.getElementById('conditions').className = 'hide';
214 document.getElementById('diagram').className = '';
215 animate(animationSpeed);
216 }
217 document.getElementById('strainRate').onchange = function(){
218 document.getElementById('strainRateValue').textContent = (+this.value).toFixed(1);
219 strainRate = (+this.value).toFixed(1);
220 applyInitionalConditions();
221 }
222 document.getElementById('animationSpeed').onchange = function(){
223 document.getElementById('animationSpeedValue').textContent = (+this.value).toFixed(0);
224 animationSpeed = (+this.value).toFixed(0);
225 }