Двумерное уравнение теплопроводности

Материал из Department of Theoretical and Applied Mechanics
Версия от 09:05, 11 марта 2015; Денис (обсуждение | вклад)

(разн.) ← Предыдущая | Текущая версия (разн.) | Следующая → (разн.)
Перейти к: навигация, поиск
Виртуальная лаборатория > Двумерное уравнение теплопроводности

Численное решение двумерного уравнения теплопроводности.

Управление:

  • Левая кнопка мыши - нагреть область
  • Средняя кнопка мыши - придать области нормальную температуру
  • Правая кнопка мыши - охладить область


Скачать Heat_2D_v1-4-mini_release.zip.

Текст программы на языке JavaScript (разработчики Цветков Денис, Кривцов Антон):

Файл "Heat_2D.js"

  1 window.addEventListener("load", main_heat, false);
  2 function main_heat() {
  3 
  4     // Предварительные установки
  5 
  6     var canv = init_canvas(Heat_2D_canvas);
  7 
  8     var a0 = 1;                             // масштаб расстояния
  9     var t0 = 1;                             // масштаб времени
 10     var m0 = 1;                             // масштаб массы
 11     var T0 = 1;                             // масштаб температуры
 12 
 13     var dx = 1 * a0;                        // шаг сетки по оси x
 14 
 15     var spf = 1;                            // steps per frame - сколько расчетов проходит за каждый кадр отображения
 16     var fps = 15;
 17     var dt = 0.005 * t0;                    // шаг интегрирования по времени
 18 
 19     var p0 = m0 / (a0 * a0 * a0);           // единица плотности, кг/м3
 20     var c0 = a0 * a0 / (t0 * t0 * T0);      // единица удельной теплоемкости, Дж/(кг * К)    (Дж = кг * м2 / с2)
 21     var kap0 = m0 * a0 / (t0 * t0 * t0 * T0);// единица теплопроводности (?, каппа)
 22 
 23     var p = 0.15 * p0;
 24     var c = 0.2 * c0;
 25     var k = 1 * kap0;
 26     var X = k / (c * p);                    // температуропроводность (?, хи)
 27 
 28     var Nx = 50 + 2;                        // количество узлов по оси x + 2 для ГУ
 29     var Ny = 50 + 2;
 30 
 31     var cell_w = canv.w / (Nx - 2);         // ширина клетки
 32     var cell_h = canv.h / (Ny - 2);         // высота клетки
 33 
 34     // Минимальная и максимальная температуры используются для подбора цветовой гаммы
 35     var T_min = 0 * T0;
 36     var T_max = 10 * T0;
 37 
 38     var T_mouse_max = 9;                    // температура для левой клавиши мыши
 39     var T_mouse_min = 1;                    // температура для правой клавиши мыши
 40 
 41     var color_N = 60;                       // цветов не больше, чем color_N, саму переменную color_N в расчетах лучше не использовать
 42     var colors = prepare_colors(color_N);
 43     var cell_pics = prepare_cell_pics(colors);
 44 
 45     var pause = false;
 46     button_pause.onclick = function () {pause = !pause;};
 47     button_clear.onclick = function () {
 48         for (var i = 0; i < Nx; i++) {
 49             for (var j = 0; j < Ny; j++) {
 50                 T[i][j].u = (T_max - T_min) / 2;
 51                 T[i][j].v = 0;
 52             }
 53         }
 54         draw_graph();
 55     };
 56 
 57     var T = [];
 58     for (var i = 0; i < Nx; i++) {
 59         T[i] = [];
 60         for (var j = 0; j < Ny; j++) {
 61             T[i][j] = {};
 62             var x = i / (Nx - 1);
 63             var y = j / (Ny - 1);
 64 
 65             var width = 0.05;
 66             var power = 5;
 67             var plus = 5;
 68 
 69             T[i][j].u = Math.exp(-Math.pow(x - 0.5, 2) / width) * Math.exp(-Math.pow(y - 0.5, 2) / width) * power + plus;
 70             T[i][j].v = 0;
 71         }
 72     }
 73 
 74     // периодические граничные условия
 75     for (i = 1; i < Nx - 1; i++) {
 76         T[i][0] = T[i][Ny - 2];
 77         T[i][Ny - 1] = T[i][1];
 78     }
 79     for (j = 0; j < Ny; j++) {
 80         T[0][j] = T[Nx - 2][j];
 81         T[Nx - 1][j] = T[1][j];
 82     }
 83 
 84     function prepare_cell_pics(col) {
 85         var pics = [];
 86         for (var i = 0; i < col.length; i++) {
 87             var cell = document.createElement('canvas');
 88             var cell_ctx = cell.getContext('2d');
 89 
 90             cell_ctx.fillStyle = col[i];
 91             cell_ctx.beginPath();
 92             cell_ctx.rect(0, 0, cell_w, cell_h);
 93             cell_ctx.fill();
 94             pics.push(cell);
 95         }
 96         return pics;
 97     }
 98 
 99 
100     function control() {
101         if (!pause) {
102             calculate_steps(spf, dt);
103             draw_graph();
104         }
105     }
106 
107     setInterval(control, 1000 / fps);                       // Запуск системы
108 
109 
110     // Работа с мышью
111 
112     Heat_2D_canvas.onmousedown = function(e){               // функция при нажатии клавиши мыши
113         var T1;
114         if (e.which == 1) T1 = T_mouse_max;                 // при нажатии левой клавиши мыши клетка нагревается
115         else if (e.which == 2) T1 = (T_max - T_min) / 2;    // при нажатии средней клавиши мыши клетка получает среднюю температуру
116         else if (e.which == 3) T1 = T_mouse_min;            // при нажатии правой клавиши мыши клетка остывает
117         else return;
118 
119         set_cell(e, T1);
120         Heat_2D_canvas.onmousemove = function(e) {set_cell(e, T1);};   // функция, выполняющаяся при перемещении курсора мыши
121         return false;
122     };
123 
124     document.onmouseup = function(e){                   // функция при отпускании клавиши мыши
125         Heat_2D_canvas.onmousemove = null;              // когда клавиша отпущена - функции перемещения нету
126     };
127 
128     function set_cell(e, T1){                           // придать клетке определенное состояние с нажатия клавиши мыши
129         var m = mouse_coords(e);                        // обновить координаты в переменных mouseX, mouseY
130         if (m.x < 0 || m.x >= canv.w || m.y < 0 || m.y >= canv.h) return;         // проверка на ошибочные координаты
131         // везде прибавляем 1 - из за периодических условий массив сдвинут на 1
132         var i = Math.floor(m.x / cell_w) + 1;           // получаем ячейку по горизонтали
133         var j = Math.floor(m.y / cell_h) + 1;           // получаем ячейку по вертикали
134         T[i][j].u = T1;
135         draw_cell(i, j);
136     }
137 
138     function mouse_coords(e) {                          // функция возвращает экранные координаты курсора мыши
139         var m = [];
140         var rect = Heat_2D_canvas.getBoundingClientRect();
141         m.x = e.clientX - rect.left;
142         m.y = e.clientY - rect.top;
143         return m;
144     }
145 
146     function calculate_steps(spf, dt) {
147         var koeff1 = X / (dx * dx)     * dt;
148         for (var s = 0; s < spf; s++) {
149             for (var i = 1; i < Nx - 1; i++) {
150                 for (var j = 1; j < Ny - 1; j++) {
151                     T[i][j].v = (T[i + 1][j].u + T[i][j + 1].u - 4 * T[i][j].u + T[i - 1][j].u + T[i][j - 1].u) * koeff1;
152                 }
153             }
154 
155             for (var i = 1; i < Nx - 1; i++) {
156                 for (var j = 1; j < Ny - 1; j++) {
157                     T[i][j].u += T[i][j].v;
158                 }
159             }
160         }
161     }
162 
163 
164     function draw_graph() {
165         // график
166         canv.ctx.clearRect(0, 0, canv.w, canv.h);
167         for (var i = 1; i <= Nx - 1; i++) {
168             for (var j = 1; j <= Ny - 1; j++) {
169                 var col = Math.round((T[i][j].u - T_min) * (colors.length - 1) / (T_max - T_min));            // 0 <= col <= color_N
170                 if (col < 0) col = 0;
171                 if (col >  (colors.length - 1)) col =  (colors.length - 1);
172                 canv.ctx.drawImage(cell_pics[col], (i - 1) * cell_w, (j - 1) * cell_h);
173             }
174         }
175     }
176 
177     function draw_cell(i, j) {
178         var col = Math.round((T[i][j].u - T_min) * (colors.length - 1) / (T_max - T_min));            // 0 < col < color_N
179         canv.ctx.drawImage(cell_pics[col], (i - 1) * cell_w, (j - 1) * cell_h);
180     }
181     function RGBtoHEX(r, g, b) {
182         return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1);
183     }
184 
185     function prepare_colors(N) {
186         var col = [];
187         var n = N / 6 - 1;
188         for (var i = 0; i < 256; i += Math.floor(255 / n))
189             col.push(RGBtoHEX(255 - i, 255, 255));
190         for (var i = 0; i < 256; i += Math.floor(255 / n))
191             col.push(RGBtoHEX(0, 255 - i, 255));
192         for (var i = 0; i < 256; i += Math.floor(255 / n))
193             col.push(RGBtoHEX(0, 0, 255 - i));
194         for (var i = 0; i < 256; i += Math.floor(255 / n))
195             col.push(RGBtoHEX(i, 0, 0));
196         for (var i = 0; i < 256; i += Math.floor(255 / n))
197             col.push(RGBtoHEX(255, i, 0));
198         for (var i = 0; i < 256; i += Math.floor(255 / n))
199             col.push(RGBtoHEX(255, 255, i));
200         return col;
201     }
202 
203     function init_canvas(canvas) {
204         canvas.onselectstart = function () {return false;};     // запрет выделения canvas
205         canvas.oncontextmenu = function () {return false;};      // блокировка контекстного меню
206 
207         var canv_obj = {};
208         canv_obj.ctx = canvas.getContext("2d");                  // на context происходит рисование
209         canv_obj.w = canvas.width;          // ширина окна в расчетных координатах
210         canv_obj.h = canvas.height;         // высота окна в расчетных координатах
211 
212         return canv_obj;
213     }
214 }

Файл "Heat_2D.html"

 1 <!DOCTYPE html>
 2 <html>
 3 <head>
 4     <meta charset="UTF-8" />
 5     <title>Heat 2D</title>
 6     <script src="Heat_2D.js"></script>
 7 </head>
 8 <body>
 9     <canvas id="Heat_2D_canvas" width="700" height="700" style="border:1px solid #000000; border-radius:6px; margin-bottom: -5px"></canvas>
10     <br><br>
11     <input type="button" id="button_pause" value="Пауза/Старт"/>
12     <input type="button" id="button_clear" value="Очистить"/>
13 </body>
14 </html>