Модераторы: bsa

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Уравнение теплопроводности, Численное решение квазилинейного уравнен 
:(
    Опции темы
Kafari
Дата 3.4.2011, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Здравствуйте!
Я вот решаю квазилинейное уравнение теплопроводности, а именно dT/dt = k d/dx ( T^s *dT/dx ). Прошу прощения, не знаю как здесь нормально вставить формулу...
В общем, проблема в том, что обычная разностная схема не работает. Вот такая:
Код

T2[x]= oldT2[x] + (k*dt/(dh*dh))*pow(oldT2[x],s)*((oldT2[x+1] - oldT2[x]) - pow(oldT2[x-1],s)*(oldT2[x] - oldT2[x-1]));

где Т2 - температура в данный момент времени, oldT2 - температура в предыдущий момент времени, dt - промежуток по времени, dh - промежуток по координате. А именно, температура вовсе не распространяется.
Гугл показывал мне Самарского, вроде там что-то на эту тему есть, но я не нашла. То есть поняла, что существует такой интегро-итерационый метод (если я правильно запомнила его название) но он меня стабильно приводит к системе нелинейных уравнений, которую я решать вообще не знаю как.
Посоветуйте что-нибудь, пожалуйста!
PM MAIL   Вверх
Фантом
Дата 3.4.2011, 22:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Что такое "обычный разностный метод"? Подсчет тепловой волны с помощью т.н. "наилучшей аппроксимации"? Он и не должен работать, это нормально. Воспользуйтесь аппроксимацией потока в виде J_n= \frac{T^s_{n-1/2}+T^s_{n+1/2}}{2} \cdot \frac{T_{n+1/2}-T_{n-1/2}}{(h_{n-1/2}+h_{n+1/2})/2}. Для степенного коэффициента теплопроводности эта аппроксимация точна.
PM   Вверх
Kafari
Дата 3.4.2011, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Фантом, спасибо за подсказку!
А можно спросить пару вопросов, например, что такое J_n ? Температура в следующий момент времени?
И потом, T_{n+1/2}, это имеется в виду, индекс по координате? И температуру там считать как среднее от температуры в двух узлах?
PM MAIL   Вверх
Фантом
Дата 3.4.2011, 22:47 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(Kafari @  3.4.2011,  22:19 Найти цитируемый пост)

А можно спросить пару вопросов, например, что такое J_n ? Температура в следующий момент времени?

Поток в узле n. Т.е. то, что находится внутри "внешней" производной.

Цитата(Kafari @  3.4.2011,  22:19 Найти цитируемый пост)

И потом, T_{n+1/2}, это имеется в виду, индекс по координате? И температуру там считать как среднее от температуры в двух узлах? 

Да. В таких задачах обычно используют "полуцелые" сетки, так удобнее.
PM   Вверх
Kafari
Дата 3.4.2011, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Понятно, спасибо! Попробую.
И еще вот: (h_{n-1/2}+h_{n+1/2})/2 - это зачем? Это если расстояние между узлами не одинаковое? Я правильно поняла, что h - это расстояние между узлами по координате?

Это сообщение отредактировал(а) Kafari - 3.4.2011, 22:54
PM MAIL   Вверх
Фантом
Дата 3.4.2011, 23:11 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(Kafari @  3.4.2011,  22:51 Найти цитируемый пост)
И еще вот: (h_{n-1/2}+h_{n+1/2})/2 - это зачем? Это если расстояние между узлами не одинаковое? Я правильно поняла, что h - это расстояние между узлами по координате?

Да. Поскольку я не знаю, используете Вы равномерную сетку или нет, на всякий случай написал более общий вариант.
PM   Вверх
Kafari
Дата 4.4.2011, 13:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Наверное, я жестоко туплю, но у меня все равно ничего не работает. Код выглядит так вот:
Код

for (int x=1; x<N-2; x++){
            double Ts1 = (oldT2[x-1]+oldT2[x])/2;                                         \\ температура между х-1 и х
            double Ts2 = (oldT2[x]+oldT2[x+1])/2;                                        \\ температура между х и х+1
            double Ts3 = (oldT2[x+1]+oldT2[x+2])/2;                                  \\ температура между х+1 и х+2
            double J1 = 1/2 * (pow(Ts1,s) + pow(Ts2,s))*(Ts2 - Ts1)/dh;             \\ поток в х
            double J2 = 1/2 * (pow(Ts2,s) + pow(Ts3,s))*(Ts3 - Ts2)/dh;             \\ поток в х+1
            T2[x]= oldT2[x] + A*dt*(J2-J1)/dh;
}


Помогите найти ошибку, пожалуйста!
PM MAIL   Вверх
borisbn
Дата 4.4.2011, 17:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Kafari @  4.4.2011,  13:37 Найти цитируемый пост)
J1 = 1/2 * (pow(Ts1,s) + pow(Ts2,s))*(Ts2 - Ts1)/dh;       

на вскидку (остальное не смотрел): 1/2 получается 0, т.к. деление будет целочисленное
замени либо на 0.5 либо 1.0/2.0 как больше нравится

вообще все деления должны приводиться к double
Код

(oldT2[x-1]+oldT2[x])/2.0;
...
A*dt*(J2-J1)/(double)dh;


Это сообщение отредактировал(а) borisbn - 4.4.2011, 17:07


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Фантом
Дата 4.4.2011, 17:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(Kafari @  4.4.2011,  13:37 Найти цитируемый пост)

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

Это, что, Ваша первая программа на C/С++? smile Результат вычисления 1/2 - это нуль. Соответственно, J1 и J2 всегда окажутся нулевыми.

Заодно уж уберите двукратное вычисление pow(Ts2,s) и создание/удаление переменных в каждой ветке цикла. На численный результат это не повлияет, но вычислительные программы с таким "качеством" оптимизации писать неприлично.
PM   Вверх
Kafari
Дата 4.4.2011, 21:25 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Цитата(borisbn @  4.4.2011,  17:05 Найти цитируемый пост)
замени либо на 0.5 либо 1.0/2.0 как больше нравится

Спасибо за подсказку! Исправила.

Цитата(Фантом @  4.4.2011,  17:08 Найти цитируемый пост)
Это, что, Ваша первая программа на C/С++?

Вторая. До этого был матлаб, поэтому у меня еще бывают всякие глюки.. В любом случае спасибо, буду знать.
Теперь код выглядит так:
Код

for (int x=1; x<N-2; x++){
            Ts1 = (oldT2[x-1]+oldT2[x])/2.0;
            Ts2 = (oldT2[x]+oldT2[x+1])/2.0;
            Ts3 = (oldT2[x+1]+oldT2[x+2])/2.0;
            J1 = 0.5 * (pow(Ts1,s) + pow(Ts2,s))*(Ts2 - Ts1)/(double)dh;
            J2 = 0.5 * (pow(Ts2,s) + pow(Ts3,s))*(Ts3 - Ts2)/(double)dh;
            T2[x]= oldT2[x] + A*dt*(J2-J1)/(double)dh;
        }

Теперь правильно?
PM MAIL   Вверх
Фантом
Дата 4.4.2011, 21:45 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



В принципе, да, хотя на самом деле использование "полуцелой" сетки обычно предполагает и хранение данных с ней же. Температуру тут проще считать на полуцелых узлах, а потоки - на целых. Кроме этого, от двукратного вычисления pow(Ts2,s) я бы все-таки избавился - возведение в степень штука дорогая. Ну и делать постоянно приведение типов для dh тоже как-то странно - не проще ли сразу объявить ее как double?
PM   Вверх
borisbn
Дата 4.4.2011, 22:01 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Фантом @  4.4.2011,  17:08 Найти цитируемый пост)
 уберите двукратное вычисление pow(Ts2,s) и создание/удаление переменных в каждой ветке цикла. 


Фантом, соптимизировать быстрее, чем Intel'овский компилятор или чем Intel Performance Primitives всё равно не получится. Перед тем как начинать гнаться за скоростью нужно полностью отладить алгоритм/логику/математику.
Мало того, создание переменной на стеке ("в каждой ветке цикла") быстрее, чем выделение в куче или даже в статике.
(С) Александреску - преждевременная оптимизация есть источник зла.
Думайте только о том, чтобы программа работала правильно.

Как-то патетически получилось... smile


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Фантом
Дата 4.4.2011, 22:53 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 4
Всего: 49



Цитата(borisbn @  4.4.2011,  22:01 Найти цитируемый пост)

Фантом, соптимизировать быстрее, чем Intel'овский компилятор или чем Intel Performance Primitives всё равно не получится. 

Хм... Ну что же, попробуем. Я приписал к этому куску какую-то обвязку (чтобы было что компилировать) и погонял в двух видах. В одном цикл был исходным, в другом - возведение в степень делалось один раз (из двух) и записывалось в промежуточную переменную, после чего результат два раза использовался. И то, и другое компилировалось ICC с ключом -fast. Прирост производительности, конечно, получился смешным (примерно 3%), но он систематический.  smile

Цитата(borisbn @  4.4.2011,  22:01 Найти цитируемый пост)
Перед тем как начинать гнаться за скоростью нужно полностью отладить алгоритм/логику/математику.

Возможно, но, во-первых, после такой отладки "логики" найти ее в программе будет затруднительно, и, во-вторых, это действие попросту уменьшает вероятность случайной ошибки.

Цитата(borisbn @  4.4.2011,  22:01 Найти цитируемый пост)
Мало того, создание переменной на стеке ("в каждой ветке цикла") быстрее, чем выделение в куче или даже в статике.

Да, тут согласен (хотя, вообще говоря, это до некоторой степени "компиляторозависимо"). Правда, там как минимум две переменных из пяти вообще не нужны (а при аккуратном расписывании логики удастся убрать и больше двух).

Цитата(borisbn @  4.4.2011,  22:01 Найти цитируемый пост)
(С) Александреску - преждевременная оптимизация есть источник зла.
Думайте только о том, чтобы программа работала правильно.

Если бы еще Александреску занимался вычислительным программированием...  smile 
PM   Вверх
Kafari
Дата 5.4.2011, 07:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 21.4.2010

Репутация: нет
Всего: нет



Цитата(Фантом @  4.4.2011,  21:45 Найти цитируемый пост)
Кроме этого, от двукратного вычисления pow(Ts2,s) я бы все-таки избавился - возведение в степень штука дорогая.

А это как? Сделать еще одну переменную?

Цитата(Фантом @  4.4.2011,  21:45 Найти цитируемый пост)
Ну и делать постоянно приведение типов для dh тоже как-то странно - не проще ли сразу объявить ее как double?

Ясно, сделано.

Вообще я понимаю, что промежуточные переменные не нужны, и можно было бы сразу написать длинную строчку. Возможно, так и сделаю, но пока так понятнее.

Вот, а теперь у меня проблема с визуализацией... Делается у меня это в Qt, там рисуется полосочка (пока одномерный случай), разделенная на узкие прямоугольники, закрашиваемые определенным цветом. Крайняя справа и крайняя слева фиксированы - там температура постоянна. Должен получиться градиент, но он не получается. Собственно, вот как оно выглядит, если это понятнее, чем на словах объяснять
Код

void MyView1::paintEvent(QPaintEvent *){
    if (!dataAvailable) return;
    if (data == 0) return;
    QPainter paint(this);
    QColor color(0,0,0,255);
    float ch = paint.viewport().height();
    float cw = paint.viewport().width() / data->N;

    for (int x=0; x<data->N; x++){
        
            int a = 255 - (data->oldT2[x])*225/data->T0;
            color.setAlpha(a);
            paint.fillRect(x * cw, 0, cw,ch,color);
        
    }
    dataAvailable = false;
}

Если что, dataAvailable - это такая переменная, чтобы отрисовка включалась именно тогда, когда надо, а не просто когда вдруг update вызовется, мало ли...

Но то, что рисуется, слабо похоже на правду. То есть правильно получается только в одном случае - когда s (степень) равна нулю. В остальном я наблюдаю схлопывающиеся белые полосы. Вроде такого вот
user posted image
Здесь нижняя часть окошка, вверху распространение нормального тепла...
И вот я думаю, то ли температура там становится отрицательная, то ли слишком большая наоборот, то ли у меня с визаулизатором проблема. Насколько я поняла из намеков компилятора, он пишет " "QColor::setAlpha": invalid value -2147483648 ". Что бы это могло значить?
PM MAIL   Вверх
borisbn
Дата 5.4.2011, 08:37 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 4875
Регистрация: 6.2.2010
Где: Ростов-на-Дону

Репутация: 21
Всего: 135



Цитата(Kafari @  5.4.2011,  07:37 Найти цитируемый пост)
Вообще я понимаю, что промежуточные переменные не нужны, и можно было бы сразу написать длинную строчку.

Неправильно понимаешь. Промежуточные переменные нужны. Так проще отлаживаться. Так понятней. 
Цитата(Kafari @  5.4.2011,  07:37 Найти цитируемый пост)
Возможно, так и сделаю, но пока так понятнее.

Ключевое слово - понятней. Код в разы чаще читается, чем компилируется...

Теперь к отрисовке:
1. Ты уверена, что у тебя получаются "правильные" данные ? Распечатай их в qDebug и посмотри.
2. "Насколько я поняла из намеков компилятора". Правильнее сказать не из компилятора, а из отладочного вывода Qt (компилятор уже отработал. программы выполняется). Так, вернёмся к нашим... 
     Посмотри (выведи в qDebug) чему равно (data->oldT2[x])*225/data->T0; если оно больше 255, то ессно ругается, что alpha < 0
3. Насколько я понял из алгоритма, ты устанавливаешь прозрачность чёрного цвета, в зависимости от значения функции. Может просто попробовать заливать цветом ?
Код

      color = qRgb( a, a, a );


В общем, попробуй это и покажи, что выводится в Output
Код

 for (int x=0; x<data->N; x++){
            int a_delta = (data->oldT2[x])*225/data->T0;
            int a = 255 - a_delta;
qDebug() << "oldT2[" << x << "] =" << data->oldT2[x] << "a_delta =" << a_delta << "a =" << a;
            color = qRgb( a, a, a );
            paint.fillRect(x * cw, 0, cw,ch,color);
    }


Это сообщение отредактировал(а) borisbn - 5.4.2011, 08:40


--------------------
Женщины отличаются от программистов тем, что у них чары состоят из стрингов
PM MAIL Jabber   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "C/C++: Для новичков"
JackYF
bsa

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

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


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, JackYF, bsa.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C/C++: Для новичков | Следующая тема »


 




[ Время генерации скрипта: 0.0673 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.