Моделирование нестационарного распределения тепла
Материал из Department of Theoretical and Applied Mechanics
Содержание
Описание[править]
Моделирование процесса распределения тепла в прямоугольному образце Исполнители: Алексеенко Егор, Тюнин Павел
Математическая модель[править]
Основные допущения[править]
При моделировании образца были сделаны следующие допущения:
- Не учитываются воздействия среды
Входные данные[править]
Перед началом моделирования задаются следующие данные:
- Источники тепла
- Граничные условия
Управление[править]
- Левая кнопка мыши - увеличение температуры;
- Правая кнопка мыши - уменьшение температуры;
Визуализация[править]
Код программы[править]
Текст программы на языке JavaScript:
1 // канвас
2 var ctx = canvasEx.getContext("2d");
3 var w = canvasEx.width;
4 var h = canvasEx.height;
5 var clr = colorbar.getContext("2d");
6 var wc = colorbar.width;
7 var hc = colorbar.height;
8 // константы
9 var isStarted = 0;
10 var isPaused = 0;
11 var t = 0;
12 var dt = 0.01;
13 var fps = 1/dt;
14 var L = 10;
15 var Nx = 22;
16 var Ny = 22;
17 var dx = L/(Nx-2);
18 var dy = L/(Ny-2);
19 var T0 = 15;
20 var DT = 10;
21 var a = 0.1; // Коэффициент температуропроводности
22 var TMax = 100;
23 var TMin = 0;
24 var TAv = (TMax-TMin)/2;
25 var xscale = w / L;
26 var yscale = h / L;
27 var fx = 1;
28 var fy = 1;
29 // задание начальных условий
30 var T = new Array(Ny);
31 for (var i = 0; i < Ny; i++)
32 {
33 T[i] = new Array(Nx);
34 }
35 for (var i = 0; i < Ny; i++)
36 {
37 for (j = 0; j < Nx; j++)
38 {
39 T[i][j] = T0;
40 }
41 }
42 T[1][1] = 50;
43 //
44 var cyan = {
45 r: 0,
46 g: 1,
47 b: 1,
48 }
49 var yellow = {
50 r: 1,
51 g: 1,
52 b: 0,
53 }
54 var green = {
55 r: 0,
56 g: 1,
57 b: 0,
58 }
59 var brown = {
60 r: 110/255,
61 g: 67/255,
62 b: 6/255,
63 }
64 var blue = {
65 r: 0,
66 g: 0,
67 b: 1,
68 }
69 var red = {
70 r: 1,
71 g: 0,
72 b: 0,
73 }
74 var N = 5+5*4;
75 for (var i=0; i<N; i++) {
76 clr.fillStyle = gradient([blue, cyan, green, yellow, red], i/(N-1));
77 clr.fillRect(wc/N*i, 0, wc/N, hc);
78 }
79 function gradient(colors, a) {
80 var n = colors.length-1;
81 if (Math.floor(a*n)==n) {
82 let i = n-1;
83 let j = n;
84 var color1 = colors[i];
85 var color2 = colors[j];
86 var a = 1;
87 } else {
88 let i = Math.floor(a*n)==n ? n-1 : Math.floor(a*n);
89 let j = i+1;
90 var color1 = colors[i];
91 var color2 = colors[j];
92 var a = a*n - Math.floor(a*n);
93 }
94 return 'rgb('+Math.floor(255*(color1.r+(color2.r-color1.r)*a))+', '+Math.floor(255*(color1.g+(color2.g-color1.g)*a))+', '+Math.floor(255*(color1.b+(color2.b-color1.b)*a))+')';
95 }
96 // функция просчитывания температурного поля
97 function phys()
98 {
99 for (var i = 1+fy; i < Ny-1-fy; i++)
100 {
101 for (var j = 1+fx; j < Nx-1-fx; j++)
102 {
103 T[i][j] = T[i][j] + a*dt*((T[i+1][j] + T[i-1][j] -2*T[i][j])/(dx*dx) + (T[i][j+1] + T[i][j-1] -2*T[i][j])/(dy*dy));
104 }
105 }
106 if (c2.checked)
107 {
108 for (var i = 1; i<20; i++)
109 {
110 T[i][0] = T[i][20];
111 T[i][21] = T[i][1];
112 }
113 }
114 if (c1.checked)
115 {
116 for (j=1; j<20; j++)
117 {
118 T[21][j]=T[1][j];
119 T[0][j]=T[20][j];
120 }
121 }
122 if ((c1.checked) && (c2.checked))
123 {
124 for (var i = 1; i<20; i++)
125 {
126 T[i][0] = T[i][20];
127 T[i][21] = T[i][1];
128 }
129 for (j=1; j<20; j++)
130 {
131 T[21][j]=T[1][j];
132 T[0][j]=T[20][j];
133 }
134 }
135 }
136 // отрисовка температурного поля
137 function draw()
138 {
139 ctx.clearRect(0,0,w,h);
140 for (var i = 1; i < Ny-1; i++)
141 {
142 for (var j = 1; j < Nx-1; j++)
143 {
144 var imageData = clr.getImageData(wc*(T[i][j]/TMax)-1,1, 1,1).data;
145 ctx.fillStyle = "rgb("+imageData[0]+","+imageData[1]+","+imageData[2]+")";
146 ctx.fillRect((j-1)*dx*xscale, (i-1)*dy*yscale, (j)*dx*xscale,(i)*dy*yscale);
147 }
148 }
149 }
150 function control()
151 {
152 phys();
153 draw();
154 }
155 // функция старта
156 start.onclick = function ()
157 {
158 if (isStarted == 0 || isPaused == 1)
159 {
160 t = setInterval(control,1/fps);
161 isStarted = 1;
162 isPaused = 0;
163 document.getElementById("c1").setAttribute("disabled", "true");
164 document.getElementById("c2").setAttribute("disabled", "true");
165 if (c2.checked)
166 {
167 fx = 0;
168 }
169 else fx = 1;
170 if (c1.checked)
171 {
172 fy = 0;
173 }
174 else fy = 1;
175 }
176 };
177 // функция паузы
178 pause.onclick = function()
179 {
180 if (isPaused == 0)
181 {
182 clearTimeout(t);
183 isPaused = 1;
184 }
185 };
186 // получение координат курсора, с пересчетом в координаты ячейки
187 function getMouseCoords(e)
188 {
189 let m = {};
190 let rect = canvasEx.getBoundingClientRect();
191 m.x = Math.floor((e.clientX - rect.left)/(dx*xscale))+1;
192 m.y = Math.floor((e.clientY - rect.top)/(dy*xscale))+1;
193 return m;
194 }
195 // функция добавления моментальных источников тепла
196 canvasEx.onclick = function(e)
197 {
198 if (isStarted == 0)
199 {
200 var m = getMouseCoords(e);
201 if (T[m.y][m.x] + DT <= TMax)
202 {
203 T[m.y][m.x] += DT;
204 draw();
205 }
206 }
207 };
208 //функция моментального охлаждения
209 canvasEx.oncontextmenu = function(e)
210 {
211 if (isStarted == 0)
212 {
213 var m = getMouseCoords(e);
214 if (T[m.y][m.x] - DT >= TMin)
215 {
216 T[m.y][m.x] -= DT;
217 draw();
218 }
219 }
220 };
221 //функция отключения контекстного меню
222 document.body.oncontextmenu = function (e) {
223 return false;
224 };
225 // функция сброса состояния
226 reset.onclick = function()
227 {
228 document.getElementById('c1').removeAttribute("disabled");
229 document.getElementById('c2').removeAttribute("disabled");
230 isPaused = 0;
231 isStarted = 0;
232 clearTimeout(t);
233 var fx = 1;
234 var fy = 1;
235 for (var i = 0; i < Ny; i++)
236 {
237 for (j = 0; j < Nx; j++)
238 {
239 T[i][j] = T0;
240 }
241 }
242 draw();
243 };
244 draw();