Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
Карта форума Темы раздела Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 5.00/8: Рейтинг темы: голосов - 8, средняя оценка - 5.00
0 / 0 / 0
Регистрация: 10.10.2017
Сообщений: 25
1
.NET 4.x

Двумерная диффузия, теплообмен

18.11.2018, 13:53. Показов 1661. Ответов 5
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Товарищи, вновь обращаюсь к Вам за помощью, как-то стыдно уже даже.

В прошлый раз мне уже существенно помогли, в результате у меня теперь есть работающая модель для отрисовки в bitmap процесса теплообмена на двумерной карте. Мой руководитель вконец офигел и выдвинул новое требование, не соизволив его разъяснить, необходимо метод расчета через матрицу поменять на расчет, как он выразился, "в лоб", циклом.
C#
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
 // Вычисляет итерацию (y_i+1 по y_i)
        double[,] Tick(double[,] y)
        {
            var fx = Params.dt * Params.kx / Params.dx / Params.dx;
            var fy = Params.dt * Params.ky / Params.dy / Params.dy;
            var c = new double[,]
            {
                { 0, fy , 0 },
                { fx, -2*(fx + fy), fx },
                { 0, fy , 0 },
            };
 
            var r = new double[Params.Height, Params.Width];
            for (int row = 1; row < Params.Height - 1; row++)
            {
                for (int col = 1; col < Params.Width - 1; col++)
                {
                    // к старому значению в текущей ячейки внизу
                    r[row, col] = y[row, col];
 
                    // прибавляем соседние ячейки умноженные на коэффициенты из окна c
                    // границы не учитываем
                    for (int i = -1; i <= 1; i++) 
                        for (int j = -1; j <= 1; j++)
                            r[row, col] += y[row + i, col + j] * c[1 + i, 1 + j];
                }
            }
 
            return r;
        }
В атаче я прикреплю pdf с алгоритмом на fortran для данной проги и сам проект. Если вы понимаете, о чем речь, то, покажите и расскажите, пожалуйста. Я геолог, руководитель математик, мне сложно

Спасибо.
Вложения
Тип файла: rar 6476833_дифуз_базовый (1).rar (183.3 Кб, 8 просмотров)
Тип файла: pdf fortran.pdf (2.16 Мб, 17 просмотров)
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
18.11.2018, 13:53
Ответы с готовыми решениями:

Анализ источника ошибки. Двумерная диффузия
Программа, реализующая уравнение детерминированной диффузии. В моем случае, используется для...

Теплообмен
Здравствуйте! Нужна помощь в решении следующей задачки. В качестве нагревательного элемента...

Диффузия
Добрый день, подскажите пожалуйста. Имеются 2 решетки атомов отличающиеся расстоянием между атомами...

Две жидкости в калориметрах, теплообмен
В калориметре смешали две жидкости, имеющие одинаковые удельные теплоемкости, но разные массы (m2...

5
Эксперт .NETАвтор FAQ
10411 / 5141 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
18.11.2018, 15:27 2
optimizator98,
Ну по правде говоря, считалось у вас неправильно.
По крайней мере на границах - так точно.

Вот так нужно:
C#
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
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Linq;
using System.Windows.Forms;
 
namespace Diffuse2d
{
    public partial class Form1 : Form
    {
        // параметры системы
        Params Params = new Params();
 
        // вычисленные значения системы для каждого тика времени
        double[][,] Values = new double[][,] { };
 
        public Form1()
        {
            InitializeComponent();
            Calculate();
            trackBar1.Maximum = Params.TimeSteps - 1;
            pictureBox1.Image = DrawBitmap(Values[0]);
        }
 
        // Вычисляет итерацию (y_i+1 по y_i)
        double[,] Tick(double[,] y)
        {
            var fx = Params.dt * Params.kx / Params.dx / Params.dx;
            var fy = Params.dt * Params.ky / Params.dy / Params.dy;
 
            var r = new double[Params.Height, Params.Width];
            for (int row = 0; row < Params.Height; row++)
            {
                for (int col = 0; col < Params.Width; col++)
                {
                    var v = r[row, col] = y[row, col];
 
                    // . a .
                    // b v c
                    // . d .
                    var a = row == 0 ? v : y[row - 1, col];
                    var b = col == 0 ? v : y[row, col - 1];
                    var c = col == Params.Width - 1  ? v : y[row, col + 1];
                    var d = row == Params.Height - 1 ? v : y[row + 1, col];
 
                    r[row, col] += fx * (b + c - 2 * v) + fy * (a + d - 2 * v);
                }
            }
 
            return r;
        }
 
        void Calculate()
        {
            Values = new double[Params.TimeSteps][,];
            Values[0] = Params.y0;
            for (int i = 1; i < Params.TimeSteps; i++)
                Values[i] = Tick(Values[i - 1]);
        }
 
        Bitmap DrawBitmap(double[,] values)  
        {
            int dl = 300; // ширина и высота (размер) ячейки в пикселях
            var max = values.Cast<double>().Max(); // Максимальное значение ячейки (черный цвет)
            var bmp = new Bitmap((int)(Params.dx * Params.Width * dl), (int)(Params.dy * Params.Height * dl));
            var g = Graphics.FromImage(bmp);
            g.SmoothingMode = SmoothingMode.HighQuality; //можно HighSpeed
 
            for (int i = 0; i < Params.Width; i++)
                for (int j = 0; j < Params.Height; j++)
                {
                    var x = Params.dx * i * dl;
                    var y = Params.dy * j * dl;
 
                    var c = (int)(255.0 * values[i, j] / max);
                    if (c > 255) c = 255;
 
                    g.FillRectangle(
                        new SolidBrush(Color.FromArgb(c, c, c)),
                        (float)x, (float)y, (float)dl, (float)dl);
 
                    g.DrawString($"{values[i, j]:F2}", Font, Brushes.Red, (float)x, (float)y);
                }
 
            g.Dispose();
            return bmp;
        }
 
        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            pictureBox1.Image = DrawBitmap(Values[trackBar1.Value]);
        }
 
        private void Form1_Load(object sender, EventArgs e)
        {
 
        }
    }
 
    class Params
    {
        public int TimeSteps { get; set; }
        public int Width => y0.GetLength(0);
        public int Height => y0.GetLength(1);
 
        public double dx { get; set; }
        public double dy { get; set; }
        public double dt { get; set; }
 
        public double kx { get; set; }
        public double ky { get; set; }
 
        public double[,] y0 { get; set; }
 
        public Params()
        {
            TimeSteps = 1000;
            dt = 1000;
            dx = 0.1;
            dy = 0.1;
            kx = 0.000001;
            ky = 0.000001;
            y0 = new double[50, 50];
            y0[10, 10] = 10.0;
            y0[3, 3] = 5.0;
        }
    }
}
Это эквивалентно фортрановской программе.

Двумерная диффузия, теплообмен
0
0 / 0 / 0
Регистрация: 10.10.2017
Сообщений: 25
18.11.2018, 16:56  [ТС] 3
Storm23, действительно.. Спасибо большое, увидел.

Еще один вопрос, если позволите, при попытке подставить в Params значения, приближенные к природным
C#
1
2
3
4
5
6
7
8
9
10
11
12
 public Params()
        {
            TimeSteps = 1000;
            dt = 31536000; //если мы хотим смоделировать процесс в теч. 1000 лет
            dx = 0.1;
            dy = 0.1;
            kx = 0.000001;
            ky = 0.000001;
            y0 = new double[50, 50];
            y0[10, 10] = 1000.0; 
            y0[3, 3] = 800; //природные температуры внедрения тел в среду
        }
Вылетает ошибка
Кликните здесь для просмотра всего текста
System.ArgumentException
HResult=0x80070057
Сообщение = Значение '-815' недопустимо для 'red'. 'red' должно быть больше или равно 0 и меньше или равно 255.
Источник = System.Drawing
Трассировка стека:
в System.Drawing.Color.CheckByte(Int32 value, String name)
в System.Drawing.Color.FromArgb(Int32 alpha, Int32 red, Int32 green, Int32 blue)
в System.Drawing.Color.FromArgb(Int32 red, Int32 green, Int32 blue)
в Diffuse2d.Form1.DrawBitmap(Double[,] values) в C:\Users\...\дифуз_базовый\Diffuse2d\Form1.cs:строка 78
в Diffuse2d.Form1.trackBar1_ValueChanged(Object sender, EventArgs e) в C:\Users...\Diffuse2d\Form1.cs:строка 91
в System.Windows.Forms.TrackBar.OnValueChanged(EventArgs e)
в System.Windows.Forms.TrackBar.WndProc(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
в System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
в System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
в System.Windows.Forms.Control.WndProc(Message& m)
в System.Windows.Forms.ScrollableControl.WmHScroll(Message& m)
в System.Windows.Forms.ScrollableControl.WndProc(Message& m)
в System.Windows.Forms.Form.WndProc(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
в System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
в System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
в System.Windows.Forms.Control.DefWndProc(Message& m)
в System.Windows.Forms.Control.WmKeyChar(Message& m)
в System.Windows.Forms.Control.WndProc(Message& m)
в System.Windows.Forms.TrackBar.WndProc(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m)
в System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
в System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
в System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
в System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNat iveMethods.IMsoComponentManager.FPushMessageLoop(IntPtr dwComponentID, Int32 reason, Int32 pvLoopData)
в System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
в System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
в System.Windows.Forms.Application.Run(Form mainForm)
в Diffuse2d.Program.Main() в C:\Users...\дифуз_базовый\Diffuse2d\Program.cs:строка 17


Правильно ли я понимаю, что это вызвано Bitmap'ом и нарастающей погрешностью? И можно ли с этим бороться?
0
Эксперт .NETАвтор FAQ
10411 / 5141 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
18.11.2018, 17:23 4
Лучший ответ Сообщение было отмечено optimizator98 как решение

Решение

Цитата Сообщение от optimizator98 Посмотреть сообщение
dt = 31536000; //если мы хотим смоделировать процесс в теч. 1000 лет
dt - это шаг дифференцирования. Он должен быть как можно меньше, в идеале стремиться к нулю.
Дифференциальное уравнение нельзя решить в лоб численно. Для того, что бы это сделать применяется Метод конечных разностей, в которых производная заменяется конечной разностью. И dt - это шаг этих самых разностей. Чем он меньше, тем ближе разность к истинной производной, тем точнее расчеты.
Поэтому вам нельзя ставить такие огромные числа в dt. Вместо этого, нужно увеличивать число шагов моделирования TimeSteps.

Ну а если вас волнует только битмап, то после строки 76 добавьте такое:
C#
1
                    if (c < 0) c = 0;
Тогда ошибка исчезнет, но погрешность вычислений все равно будет огромной.
1
0 / 0 / 0
Регистрация: 10.10.2017
Сообщений: 25
10.12.2018, 11:21  [ТС] 5
Storm23, а можно ли увеличить "временной диапазон" моделирования в программе, добавив, например функцию очистки памяти после каждого цикла или поставить отрисовку в Bitmap только того тика, что выбран на scalebar, потому что как обходить SystemOutOfMem моя не понимай.
0
Эксперт .NETАвтор FAQ
10411 / 5141 / 1825
Регистрация: 11.01.2015
Сообщений: 6,226
Записей в блоге: 34
11.12.2018, 20:26 6
Цитата Сообщение от optimizator98 Посмотреть сообщение
а можно ли увеличить "временной диапазон" моделирования в программе, добавив, например функцию очистки памяти после каждого цикла или поставить отрисовку в Bitmap только того тика, что выбран на scalebar, потому что как обходить SystemOutOfMem моя не понимай.
Если ошибка возникает из-за большого числа битмапов, то да, их можно очистить.
Перед строкой 91 (в моем примере, в посте #2) нужно вставить:
C#
1
2
if (pictureBox1.Image != null)
    pictureBox1.Image.Dispose();
0
11.12.2018, 20:26
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
11.12.2018, 20:26
Помогаю со студенческими работами здесь

Диффузия в клеточных автоматах
может кто сталкивался уже есть какие нибудь алгоритмы или хорошая литература п.с. Бандман не...

Чем отличается понятия теплообмен, теплоотдача и теплопередача?
Объясните пожалуйста, чем отличается понятия теплообмен, теплоотдача и теплопередача? В...

Конвективный теплообмен при ламинарном течении жидкости в трубе
Добрый вечер, помогите пожалуйста найти ошибку

Разностная схема системы реакция-диффузия на диске
Добрый день, с численными методами знаком плохо, поэтому прошу Вашей помощи. Есть задача такого...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
6
Ответ Создать тему
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2024, CyberForum.ru