2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3  След.
 
 Программирую уравнение переноса
Сообщение17.01.2017, 19:25 


25/02/16
56
Продолжение темы topic114556.html я и спрашивал про сетки и про двумерный массив пытался что-то сказать

1)Задаю исходные параметры шаги по пространству,шаг по времени,скорость переноса,концентрат-q,количество разбиений по x(Nx),количество разбиений по thau(Nt)

Нахожу начальные условия
$q(x,t)$\left\lvert$_{t=0} = q_{0}(x)$
и граничные условия(которые были даны мне для выполнения)
$q(x,t)$\left\lvert$_{x=0}=q_{0}(t)$
Код:
Используется синтаксис C++
public:static double nach(double q,double hx)//Начальные условия
{
     return q*hx;
}

public:static double konc(double q,double ht)//Граничные условия
{
     return q*ht;
}
 


2) Как известно решение данного уравнения это $u_{0}(x-a\cdot t) $ .Следовательно добавляем отдельно функцию,учитывая уже известные начальные и граничные условия.

Используется синтаксис C++
public:static double Psi(double hx,double ht,double a)///Функция решения уравнения переноса
                   {
               double qq;
               return nach(qq,hx)-(a*konc(qq,ht));
                   }



А теперь моменты в которых у меня возник вопрос.
Согласно моему заданию мне нужно использовать для начала
явную разностную схему

$\frac{y^{j+1}_{i} - y^j_{i}}{\tau}$+a$\frac{y^j_{i+1} - y^j_{i}}{h}=0$ (формула 1)

$y^{j+1}_{k}=$\gamma$ \cdot y^{j}_{k+1}+(1+$\gamma$) \cdot y^{j}_{k}$(формула 2) , где $\gamma=\frac{a\tau}{h}$


Мой примерный алгоритм:

1)Для начала я нахожу число Куранта
Используется синтаксис C++
gama=(a*ht)/hx;//Число Куранта


2)После нахождения числа Куранта запрограммировал формулу-1 и формулу-2

Используется синтаксис C++
for(int i = 1;i<Nx+1;i++)      
                                         {
                                                 for(int j =1 ;j<Nt+1;j++)
                                                 {
                                                         wht[i][j]=((wht[j+1][i]-wht[j][i])/ht)+a*((wht[j][i+1]-wht[j][i])/hx);//формула 1
                                                 }
                                         }

                                         for(int i = 1;i<Nx+1;i++)     
                                         {
                                                 for(int j =1 ;j<Nt+1;j++)
                                                 {
                                                         wht[i][j]=gama*wht[j][i+1] + (1 + gama)*wht[j][i] + wht[j][i];//формула 2                                        
                                                 }     
                                         }


Пока значение wht у меня нули-нулями и поэтому вопрос
1)Правильный ли алгоритм?
2)Функция решения названное Psi(см. в коде) куда её применять?
Дело в том что $y^{j}_{i}$ обозначается и как сеточная функция и как отдельный массив где будут размещены полученные значения уравнений.

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение18.01.2017, 11:24 


25/02/16
56
Да вы правы я слишком много задал вопросов и сразу хочу получить ответы,что применительно к лени и нежеланию самому разобраться в своей проблеме.

Поэтому буду спрашивать по частям
1)Начну с задания граничных и начальных условий

Вместо q во многих учебниках пишут u,но суть не важна.
Вот эти 2 формулы.
$q(x,t)$$\left\lvert_{t=0} = q_{0}(x)$
и граничные условия(которые были даны мне для выполнения)
$q(x,t)$$\left\lvert_{x=0}=q_{0}(t)$


Что же я сам подразумеваю по этими формулами - q нулевое зависит от $\tau$ которое у меня ht(шаг по времени) и зависит от x(hx - шаг по пространству и сетке).

Иными словами это $y=f(x)$ но в более другой формулировке и не забываем про стремящиеся к нулю $(x = 0,t = 0)$.
После повторения теории я решил для того чтобы найти начальные и граничные условия по указанным формулам нужно в $q_{0}$ подставить значения вышеперечисленных шагов и умножить их на $q$- концентрат.

В итоге я ввожу q-концентрат c клавиатуры(передаю в функции параметры в виде шагов и концентрата) и по отдельности получаю начальные и граничные условия.


Используется синтаксис C++
public:static double nach(double q,double hx)//Начальные условия
{
     return q*hx;
}

public:static double konc(double q,double ht)//Граничные условия
{
     return q*ht;
}


И мне хотелось бы узнать правильно ли я рассуждаю и двигаюсь?
И вновь говорю что знаю,что здесь никто ничего не напишет готовое,но мне это и не нужно.Нужно просто разобраться и понять правильно ли я делаю,а там уже по шагам доделаю своё задание.

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение18.01.2017, 12:06 
Заслуженный участник
Аватара пользователя


01/08/06
3131
Уфа
1) Неправильно обозначать одной и той же буквой ($q_0$) и начальное, и граничное условия. Хотя бы потому, что это функции от разных переменных. Пусть будет $q_{x0}$ и $q_{t0}$. Думаю, что это основная причина неразберихи.

2) Зачем-то тут $\tau$, оно же $h_t$. Лучше пусть будет $h_t$ и $h_x$, а $\tau$ не нужно.

3) $q_{x0}$ зависит от $x$, а не от $h_x$. Так же $q_{t0}$ зависит от $t$, а не от $h_t$. $h_x$ и $h_t$ — это шаги по пространственной переменной $x$ и по времени $t$, в данной задаче это постоянные величины.

4) Ваши функции nach и konc не годятся. Я так понимаю, здесь имеются в виду граничные и начальные условия ($q_{x0}$ и $q_{t0}$ соответственно). Тогда у этих функций должен быть один аргумент. Например:
Используется синтаксис C
double qx0(double x)
{
  return sin(x); // Тут должно стоять граничное условие из вашего задания
}

double qt0(double t)
{
  return cos(t); // Тут должно стоять начальное условие из вашего задания
}

5) Вопрос на засыпку. Что не так в выдуманной мной паре условий ($q_{x0}(x)=\sin x$, $q_{t0}(t)=\cos t$) ?

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение18.01.2017, 17:17 


25/02/16
56
Спасибо за подсказку а теперь я перехожу к следующему шагу-вопросу

Как известно решение данного уравнения это $$u_{0}(x-a\cdot t) $$ Волновое.

Я решил отдельно вынести эту функцию в код,учитывая уже известные начальные и граничные условия.

Используется синтаксис C++
public:static double funcsolve(double x,double t,double a)///Функция решения уравнения переноса
                   {
                           return qx0(x)-(a*qt0(t));
                   }


Почему я так сделал?
Обычно в программах которые настроены на решение диф.уравнений любого вида(обязательно встречается f,которая использует искомую функцию для дальнейших расчётов и решений по ней)

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

По поводу вопроса(я ещё подумаю,но пока такой ответ,возможно не чётко сформулирован)
1)Как я знаю в начальных\граничных условиях возможно экспоненциальное поведение,то есть оно может возрастать,а использование синусов и косинусов я не видел(по крайней мере в тех книгах,которые у меня под рукой)

2)Возможно должно быть так
$$q_{x0}(x)=\sin t,  $q_{t0}(t)=\cos x) $ так как при x  t=0 $а при $t$ следовательно x = 0$

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение18.01.2017, 17:59 
Заслуженный участник
Аватара пользователя


01/08/06
3131
Уфа
beginer писал(а):
$$u_{0}(x-a\cdot t) $$ Волновое.

Да, это общее решение уравнения переноса. Только я не помню, чтобы кто-то называл это решение волновым. Оно, действительно, похоже на волну тем, что распространяется с постоянной скоростью $a$. Но тут может возникнуть путаница с волновым уравнением. И ещё, я бы тут нолик убрал. Лишний он. $u$ — это и есть искомая функция, $u_0$ могла бы быть, например, функцией из граничных условий, а тут нолик сбивает с толку.

Итак, мы знаем общее решение уравнения переноса. Как его теперь получить из начального и граничного условий? Подставить сначала $x=0$, а потом $t=0$. Помня, что $q_{x0}$ задано только при $x\geqslant0$, а $q_{t0}$ задано только при $t\geqslant0$.
Цитата:
2)Возможно должно быть так $q_{x0}(x)=\sin t$, $q_{t0}(t)=\cos x$
Нетушки, если мы пишем (x), значит, зависит от $x$, а не от $t$. Вот попробуйте для моего примера найти решение $u$. Найдите в учебнике определение понятия "характеристика" для уравнения переноса.

-- Ср янв 18, 2017 20:01:26 --

Цитата:
1)Как я знаю в начальных\граничных условиях возможно экспоненциальное поведение...
Тоже неправильно. С точки зрения математики, возможно всякое, точнее не всякое, а математика тут накладывает свои ограничения, но они не такие.

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение18.01.2017, 22:50 


25/02/16
56
И так используя функцию

Используется синтаксис C++
public:static double funcsolve(double x,double t,double a)///Функция решения уравнения переноса
                   {
                           return x -(a*t);
                   }


получился такой график(уже почти похож на бегущую волну)
Изображение

Оранжевая линия это функция,представленная кодом выше,а синяя это метод Рунге-Кутта(зачем он нужен это объясню позже)

А теперь перехожу такому моменту.
Согласно заданию даны следующие формулы
$\frac{y^{j+1}_{i} - y^j_{i}}{\tau}+a\frac{y^j_{i+1} - y^j_{i}}{h}=0$ (формула 1)

$y^{j+1}_{k}=$\gamma$ \cdot y^{j}_{k+1}+(1+$\gamma$) \cdot y^{j}_{k}$(формула 2) , где $\gamma=\frac{a\tau}{h}$ - это Число Куранта.

Для начала нахожу Число Куранта
Используется синтаксис C++
gama=(a*ht)/hx;//Число Куранта


А теперь перехожу к формуле явной разностной схемы(формула 1)
Используется синтаксис C++
for(int i = 1;i<Nx+1;i++)      
                                         {
                                                 for(int j =1 ;j<Nt+1;j++)
                                                 {
                                                         res[i]=((wht[j+1][i]-wht[j][i])/ht)+a*((wht[j][i+1]-wht[j][i])/hx);//формула 1
                                                 }
                                         }
                                         

И формула-2 это формула один после аппроксимации 1-ого порядка
Используется синтаксис C++
for(int i = 1;i<Nx+1;i++)      
                                         {
                                                 for(int j =1 ;j<Nt+1;j++)
                                                 {
                                                         res[i]=gama*wht[j][i+1] + (1 + gama)*wht[j][i] + wht[j][i];//формула 2                                        
                                                 }      
                                         }


После нескольких опытов и полученных странных значений возник вопрос

Куда мне подставить решение моей функции в формулы-1 и 2(не код)?
Дело в том что $y^j_{i}$ может быть так и двумерным массивом или же функцией решения уравнения переноса.
Если сказать честно то вот здесь я запутался.

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение22.01.2017, 22:01 


25/02/16
56
На основе вводимых параметров
Изображение

и следующего кода

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
for(int i = 0;i<Nx;i++)
                                         {
                                                 wx[i+1]=wx[i]+hx;//массив
                                                 wht[0][i]=qx0(wx[i]);
                                         }     
                                         for(int j = 0;j<Nt;j++) //N+1 j+1
                                         {
                                                 wt[j+1]=wt[j]+ht;
                                                 wht[j+1][0] = qt0(wt[j+1]);
                                                 for(int i = 1;i<Nx+1;i++)
                                                 {
                                                wht[j+1][i]=((wht[j+1][i]-wht[j][i])/ht)+a*((wht[j][i+1]-wht[j][i])/hx);
                                                //формула явной схемы после аппроксимации
                                                wht[j+1][i]=gama*wht[j][i+1] + (1 + gama)*wht[j][i] + wht[j][i]+ht*fn(wx[i],wt[j]);
                                         }
                                 }
 

Получаю сначала исходную матрицу(с отображением осей x t с шагами)
Изображение
После применения 2 формул получаю такие значения
Изображение

Потом я буду исследовать её на устойчивость и Рунге-Кутт(но это потом)
Вновь интересно мнение,правильно ли я всё делаю.

-- 22.01.2017, 23:42 --

Единственное что я сам заметил так это сдвиги(смотрим последний блокнотовский файл)

И следовательно каждая строка это возможно очередной слой

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение04.02.2017, 17:53 


25/02/16
56
Сформулировалась такая задача по перенос

С помощью уравнения переноса нужно Единичную Функцию Хэвисайда "перенести"
Результат у меня должен быть сдвиг по оси и отрисовка функции Хэвисайда несколько раз(иными словами перенос по оси)

Функцию Хэвисайда запрограммировал вот так
Используется синтаксис C++
public:static double fn(double T,double x)//Функция Хэвисайда
                   {
                           if (x>=0)
                                   return T;
                           else if(x<0)
                                   return 0;  
                   }

Результат выполнения кода
Изображение

Но дальше возник вопрос

Данные формулы нужно использовать
$\frac{y^{j+1}_{i} - y^j_{i}}{\tau}+a\frac{y^j_{i+1} - y^j_{i}}{h}=0$ (формула 1)

$y^{j+1}_{k}=\gamma \cdot y^{j}_{k+1}+(1+\gamma) \cdot y^{j}_{k}$(формула 2) , где $\gamma=\frac{a\tau}{h}$

В коде выглядит это так
Используется синтаксис C++
 gama=(a*ht)/hx; //Число Куранта
               for(int i = 0;i<Nx;i++)
                           {
                        for(int j = 0;j<Nx;ij++)
                                {
                                wht[j+1][i]=((wht[j+1][i]-wht[j][i])/ht)+a*((wht[j][i+1]-wht[j][i])/hx);
                                 wht[j+1][i]=gama*wht[j][i+1] + (1 + gama)*wht[j][i];
                                }
                        }


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

1)В каком направлении нужно мне двигаться чтобы прийти к правильному ответу?
2)Функцию Хэвисайда нужно в любом случае кроме вывода на экран куда-то применять и мне её подставлять в формулу где разностная схема или нужно выразить какой-либо коэффициент?

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение04.02.2017, 18:13 
Заслуженный участник


09/05/12
25179
beginer в сообщении #1189729 писал(а):
$y^{j+1}_{k}=\gamma \cdot y^{j}_{k+1}+(1+\gamma) \cdot y^{j}_{k}$(формула 2) , где $\gamma=\frac{a\tau}{h}$
Не надо использовать эту формулу, она неверна.
beginer в сообщении #1189729 писал(а):
В коде выглядит это так
Простите, но это чушь. Даже если отвлечься от попыток реализации неправильной модели.

Я Вам это уже писал, но повторюсь, и учтите, что это не преувеличение, а суровая реальность: Вам нужно пока забыть про "уравнения переноса" и тому подобные сложные вещи и изучить нормально школьную математику 7-9 классов. А заодно, как выясняется, и программирование (школьное или первого курса, где оно у Вас там было). Пытаться получить осмысленный результат, случайным образом комбинируя действия, смысл которых Вы не понимаете и не пытаетесь понять, невозможно.

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение04.02.2017, 21:22 


25/02/16
56
Спасибо за ответ про формулу.
Значит будут другие попытки и выложу сюда

P.S(ОФФТОП)
А вот по поводу вспомнить,я вспоминаю медленно но верно,но мне главное это сдать,а как это сдам уже вспомню многое и без нервов

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение05.02.2017, 12:34 


25/02/16
56
Пока вот что получилось

Изображение

Для правильности решения нужно выровнять и убрать скачки которые остаются внизу

Для нынешнего результата применил формулу(Спасибо учебнику Лебедева)
Используется синтаксис C++
for(int i = 0;i<Nx;i++)
                         {
                                for(int j = 0;j<Nt;j++)
                                        {                                                              
                                                wht[j+1][i]=(1-a \cdot (ht/hx)) \cdot wht[j][i]+a \cdot (ht/hx)*wht[j][i]+ht \cdot fn(wx[i],wt[j]);
                                        }
}


где fn это моя функция Хэвисайда,а wx[i]-моя ось с шагами h=0.1, а wt[j]-ось t с шагами \tau

Пока мысль такова что я просто не те параметры передаю в свою функцию fn..

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение05.02.2017, 21:48 


25/02/16
56
В результате работы следующего кода,график функции немного изменился.

Используется синтаксис C++
 for(int i = 0;i<Nx;i++)
                         {
                             for(int j = 0;j<Nt;j++)
                             {
                                 wht[i+1][j]=((wht[i][j+1]-wht[i][j])/ht)+a*((wht[i][j]-wht[i][j-1])/hx);//
                             }
                         }
                         
                         for(int i = 0;i<Nx;i++)
                         {
                             for(int j = 0;j<Nt;j++)
                             {
                                 wht[i+1][j]=(1-a*(ht/hx))*wht[i][j]+a*(ht/hx)*wht[i][j]+ht*fn(T,x);
                             }
                         }


Как оказалось в функции fn нужно было другие параметры,а именно оригинальные параметры fn(T,x). А я просто вставил оси x,t.
Да график немного стал получше..
Но до "ступенек" ему ещё далеко

Изображение

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение05.02.2017, 22:13 
Заслуженный участник


09/05/12
25179
beginer в сообщении #1189885 писал(а):
Для нынешнего результата применил формулу(Спасибо учебнику Лебедева)
Она опять неверна.
beginer в сообщении #1190096 писал(а):
В результате работы следующего кода,график функции немного изменился.
Вот у Вас две пары вложенных циклов. Вы можете объяснить - зачем?

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение07.02.2017, 12:46 


25/02/16
56
Это было в качестве эксперимента(как выяснилось 2 цикла по отдельности делать это неудачное решение)

На данный момент я выразил $y^{j+1}_i$ (Здесь на форуме мне указали мои ошибки,спасибо)
Вот полная формула(Она была проверена руководителем и верна,процесс решения уравнения записан аналитически)

$y^{j+1}_i=\frac{-a\cdot \tau y^j_{i+1} + a\cdot \tau y^j_{i} +  y^j_{i+1} \cdot h}{h}$

Вопрос
до нахождения $y^{j+1}_i$

Получается я должен найти аппроксимацию,сходимость,устойчивость формулы явной разностной схемы и только потом выразить $y^{j+1}_i$?

Я прошу простой ответ наподобие да или нет?

P.S.
В учебниках Самарского и не только,в большинстве случаев идёт сначала формула схемы,а потом и последующие действия такие как аппроксимация,нахождения сходимости и устойчивости
но ключевое слово в большинстве(так как бывает сразу в метод гармоник уходит вычисление)

 Профиль  
                  
 
 Re: Программирую уравнение переноса
Сообщение07.02.2017, 15:01 
Заслуженный участник


09/05/12
25179
beginer в сообщении #1190452 писал(а):
Это было в качестве эксперимента(как выяснилось 2 цикла по отдельности делать это неудачное решение)
Делать их вместе - решение не менее неудачное.
beginer в сообщении #1190452 писал(а):
Вот полная формула(Она была проверена руководителем и верна,процесс решения уравнения записан аналитически)

$y^{j+1}_i=\frac{-a\cdot \tau y^j_{i+1} + a\cdot \tau y^j_{i} +  y^j_{i+1} \cdot h}{h}$
Ну слава богам. В этот раз действительно правильно.
beginer в сообщении #1190452 писал(а):
Получается я должен найти аппроксимацию,сходимость,устойчивость формулы явной разностной схемы и только потом выразить $y^{j+1}_i$?

Я прошу простой ответ наподобие да или нет?
Ха. Из этих двух вариантов, по-видимому, ближе "нет", но в целом вопрос почти лишен смысла.

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

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 32 ]  На страницу 1, 2, 3  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group