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

Анализ источника ошибки. Двумерная диффузия

12.12.2017, 17:30. Показов 781. Ответов 3
Метки нет (Все метки)

Author24 — интернет-сервис помощи студентам
Программа, реализующая уравнение детерминированной диффузии.
В моем случае, используется для наглядной реализации дифф. уравнения теплопроводности. Соответственно, в вкладке Params задаются значения в СИ.

В моей задаче примерные показатели kx, ky (коэф. диффузии) равны ~10-6
Площадь желательна 1000м:1000м (dx, dy)
dt - желательно ставить как можно больше. Для соответствия реальным условиям - порядка 10 тыс лет. В СИ 315360000000 сек.
TimeSteps не принципиален с точки зрения реальности задачи.
y0 - массив для высчитанных значений
C#
1
2
3
4
5
6
7
8
9
10
11
12
 public Params()
        {
            TimeSteps = 10000;
            dt = 5;
            dx = 100;
            dy = 100;
            kx = 0.000001;
            ky = 0.000001;
            y0 = new double[20, 20];
            y0[10, 10] = 100.0;
            y0[3, 3] = 50.0;
        }

Суть моей проблемы заключается в том, что данная система моделирования работает только, если соблюдается условие стабильности.

https://www.cyberforum.ru/cgi-bin/latex.cgi?0<\left( kx\frac{\Delta t}{(\Delta x)^2} +  ky\frac{\Delta t}{(\Delta y)^2}\right)<0.5

В противном случает происходит дестабилизация системы и график начинает амплитудно прыгать из + в -, что невозможно (теплообмен от холодного к теплому). И выскакивает ошибка.
Все мои попытки высчитать оптимальные значения не помогают, даже с учетом удовлетворения неравенству. Логическую ошибку я найти не могу. Все правильно работает, например, с такими параметрами.

C#
1
2
3
4
5
6
7
8
9
10
11
12
 public Params()
        {
            TimeSteps = 40;
            dt = 0.2;
            dx = 1.0;
            dy = 1.0;
            kx = 0.6;
            ky = 0.8;
            y0 = new double[20, 20];
            y0[10, 10] = 100.0;
            y0[3, 3] = 50.0;
        }
Сам проект в атаче.
Необходимо реализовать данную задачу либо в формате Bitmap, либо каким-то еще способом, о котором, я могу не знать.

Помогите нубу, пожалуйста.

Заранее, спасибо!
Вложения
Тип файла: rar дифуз_базовый.rar (178.9 Кб, 5 просмотров)
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
12.12.2017, 17:30
Ответы с готовыми решениями:

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

Поиск источника ошибки
Утоните как можно поймать источник ошибки...

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

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

3
0 / 0 / 0
Регистрация: 10.10.2017
Сообщений: 25
12.12.2017, 19:52  [ТС] 2
Если я не до конца понятно сформулировал проблему, то суть заключается получении такого dt, чтобы он с учётом остальных переменных удовлетворил неравенству
0
933 / 461 / 233
Регистрация: 02.06.2016
Сообщений: 732
12.12.2017, 19:59 3
Цитата Сообщение от optimizator98 Посмотреть сообщение
В противном случает происходит дестабилизация системы и график начинает амплитудно прыгать из + в -, что невозможно (теплообмен от холодного к теплому). И выскакивает ошибка.
Все мои попытки высчитать оптимальные значения не помогают, даже с учетом удовлетворения неравенству. Логическую ошибку я найти не могу. Все правильно работает, например, с такими параметрами.
нет, "многократное умножение" на числа kx = 0.000001, ky = 0.000001 не может дать бесконечноть и отрицательное число. Можно предположить, что там накапливается суммарная погрешность, ведущая к бесконечности, но в представленных тестах она всеравно гасится (сумма малых величин) умножением на близкое к нулю число.

Имхо, проблема первая - в размере картинки, она должна была реагировать на пропорции dx/dy, т.к. в примере dx=100 и dy=100, то размер картинки становится равным ~20000*20000 пикселей (почитай тут). И вторая - в том, что TimeSteps должен иметь порядок обратный порядку dt*коэффициент диффузии (в примере он 10^-6), т.е. диффузия есть, но на картинке её нифига не видно, в програме используется линейная растяжка, а чтобы увидеть нужна эквализация (про термины), либо правильно подбирать параметры мат.модели

* возможно, конечно же идет сильная потеря точности, из-за использования double. т.е. при малом коэф. диффузии маааленькая часть большого столбика должна перейти на соседний, но часть этого кусочка теряется при переносе. Это я не могу сейчас оценить, вроде используются числа, которые далеки от границ double.

вот, здесь я убрал влияние dx и dy (т.е. квадраты всегда будут квадратные) и записал числа в экспотенциальном формате, чтобы видеть, что они не нулевые и меняются:
Кликните здесь для просмотра всего текста
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
129
130
131
132
133
134
135
136
137
138
139
140
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
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 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;
        }
 
        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 = 40; // ширина и высота (размер) ячейки в пикселях
            var max = values.Cast<double>().Max(); // Максимальное значение ячейки (черный цвет)
            var bmp = new Bitmap((int)(Params.Width * dl), (int)(Params.Height * dl));
            var g = Graphics.FromImage(bmp);
            g.SmoothingMode = SmoothingMode.None; 
 
            for (int i = 0; i < Params.Width; i++)
                for (int j = 0; j < Params.Height; j++)
                {
                    var x = i * dl;
                    var y = 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]:##E+00}", Font, Brushes.Red, (float)x, (float)y);
                }
 
            g.Dispose();
            return bmp;
        }
 
        private void trackBar1_ValueChanged(object sender, EventArgs e)
        {
            var old_image = pictureBox1.Image;
            pictureBox1.Image = DrawBitmap(Values[trackBar1.Value]);
            old_image.Dispose();
        }
 
        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 = 10000;
            dt = 5;
            dx = 100;
            dy = 100;
            kx = 0.000001;
            ky = 0.000001;
            y0 = new double[20, 20];
            y0[10, 10] = 100.0;
            y0[3, 3] = 50.0;
        }
    }
}

Цитата Сообщение от optimizator98 Посмотреть сообщение
Необходимо реализовать данную задачу либо в формате Bitmap, либо каким-то еще способом, о котором, я могу не знать.
если картинка не нужна - не рисуй её, не сохраняй значения всех вызовов метода Tick, распечатай матрицу в текстовом формате для нужного TimeSteps(очень большого) и работай с ней. Кстати, этод метод, по сути, является обычным фильтром Гаусса, его можно разложить на строковую и столбцовую составляющую и заставить работать быстрее.

Добавлено через 7 минут
* попробуй существено увеличить dt, например, до 1000000
1
0 / 0 / 0
Регистрация: 10.10.2017
Сообщений: 25
12.12.2017, 21:16  [ТС] 4
Спасибо большое, что объяснил. Буду разбираться.
0
12.12.2017, 21:16
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
12.12.2017, 21:16
Помогаю со студенческими работами здесь

Анализ кода программы на ошибки
Подскажите что-нибудь по теме нахождения ошибок в тексте программы (языка Паскаль скорее всего). С...

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

Один Ping на чтение нескольких токенов и анализ ошибки
Прошу помочь, часа три рою поиск и походу еще пол-жизни уйдет ))) Вот приходится несколько раз...

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


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

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