2014 dxdy logo

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

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




Начать новую тему Ответить на тему На страницу 1, 2  След.
 
 Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 05:14 


20/11/16
8
Добрый день. Решение есть, но оно где-то неверное, не могу понять где. Необходимо решить задачу на отрезке [0, 1]. Шаг сетки h = 0.01. Количество разбиений N = 1/h = 100.
Итого мы имеем 101 узел сетки и 101 уравнение.
$
$$\left\{
\begin{array}{rcl}
 -4\frac{d^2u}{dx^2}+\sin x * u(x)=\sin (\frac{\pi}{2}x) \\
 \frac{du}{dx}(0)=0 \\
 u(1)=2$ \\
\end{array}
\right.$$$

Первым шагом заменяю производную 2-го порядка разностным отношением:
$\frac{d^2u}{dx^2}$\approx\frac{u(x+h)-2u(x)+(x-h)}{h^2}$$
Также заменяю производную 1-го порядка на начальном условии разностным отношением вперед и выполняю преобразования над ним:
$\frac{du}{dx}$\approx\frac{u(x+h)-u(x)}{h}$$
$\frac{u(x+h)-u(x)}{h}=0$
$u(x)=u(x+h)$ - т.к. это граничное условие для x[0] узла, значит мы имеем решение для u[0] и u[1] (1-го и 2-го уравнения) в узлах x[0] и x[1] соответственно.
Формула нахождения решения для u(0) выглядит следующим образом, отсюда выразим $\chi[0] и \nu[0]$
${u}_{0}={\chi}_{0}*{u}_{1}+{\nu}_{0}$ - отсюда имеем:
{\chi}_{0}=1, {\nu}_{0}=0


После всех преобразований имеем такую систему:
$
$$\left\{
\begin{array}{rcl}
 -4{u}_{j+1}+{u}_{j}*(8+{h}^{2}\sin x) - 4{u}_{j-1}={h}^{2}\sin(\frac{\pi}{2}x) \\
 u_0=u_1=0 \\
 u_N=2$ \\
\end{array}
\right.$$$

Далее методом прогонки я решаю СЛАУ из 98 уравнений, т.к. решения u(0), u(1) и u(n) известны. Решаю с помощью C++(если нужно, код прилагаю), но результаты мне не очень нравятся. Т.к. значение u(n) не равно 2.
Пожалуйста, подскажите, в чем ошибка.
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
#include <iostream>
#include <cmath>
using namespace std;
int main() {
    double h = 0.01;
    int N = 100; int k=0;
    double x[100] = {0}, f[100] = {0}, u[100] = {0};
    double X[100] = {0}, V[100] = {0};
    double C[100] = {0};
    double A = -4.0, B = -4.0;
    u[N] = 2;
    u[0] = u[1] = 0;
    X[0] = 1;
    V[0] = 0;
    cout << "du/dx(0) =  " << u[0] << ",  u[N] = " << u[N] <<", h = " << h << endl << endl;
 
    for ( int i = 0; i <= N; i++) {
        x[i] = i*h;
        f[i] = h*h*(sin(((M_PI)/2)*x[i]));
        C[i] = 8+h*h*sin(x[i]);
    }
 
    for (int i = 0; i < N; i++) {
        if (abs(C[i]) < abs(A)+abs(B))
            cout << "Uslovie sxodimosti ne vipolneno!" << endl;
 
    }
 
    for (int i = 2; i <= N; i++) {
        X[i] = B/(C[i]-A*X[i-1]);
        V[i] = (A*V[i-1]-f[i])/(C[i]-A*X[i-1]);
        X[N] = A/C[N];
        V[N] = -f[N]/C[N];
    }
 
    for ( int i = N; i >= 2; i--) {
        u[i] = X[i]*u[i+1]+V[i];
       }
 
    cout << "i | " << "    X    | " << "    V    | " <<  "     u | " << endl;
    cout << "----------------------------------" << endl;
 
    for (int i = 0; i < N; i++)
        cout << i << " | " << X[i] << " | " << V[i] << " | " << u[i] << " | " << endl;
 
    cout << N << " | " << X[N] << " | " << V[N] << " | " << u[N] << " | " << endl;
    cout<<"Proverka: "<<endl;
    cout<< A*u[49]-C[50]*u[50]+B*u[51] << " = " << f[50] <<endl;
}

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 11:21 
Модератор


19/10/15
1196
Наберите формулы местным редактором, поправьте код и объясните, чем именно Вам не нравится результат.

 Профиль  
                  
 
 Posted automatically
Сообщение20.11.2016, 11:21 
Модератор


19/10/15
1196
 i  Тема перемещена из форума «Математика (общие вопросы)» в форум «Карантин»
по следующим причинам:

- неправильно набраны формулы (краткие инструкции: «Краткий FAQ по тегу [math]» и видеоролик Как записывать формулы);
- неправильно набран код

Исправьте все Ваши ошибки и сообщите об этом в теме Сообщение в карантине исправлено.
Настоятельно рекомендуется ознакомиться с темами Что такое карантин и что нужно делать, чтобы там оказаться и Правила научного форума.

 Профиль  
                  
 
 Posted automatically
Сообщение20.11.2016, 15:41 
Модератор


19/10/15
1196
 i  Тема перемещена из форума «Карантин» в форум «Computer Science»


-- 20.11.2016, 13:48 --

Во-первых, у Вас массивы длины 100, $N = 100$, поэтому когда у Вас в цикле $i = N$, у Вас выход за границы массива.
Во-вторых, я не вижу, где у Вас в коде кусок, отвечающий за граничные условия. Я так понимаю, где-то должно устанавливаться f[N] = 2 или u[N] = 2

 Профиль  
                  
 
 Re: Posted automatically
Сообщение20.11.2016, 15:50 


20/11/16
8
Karan в сообщении #1170316 писал(а):
 i  Тема перемещена из форума «Карантин» в форум «Computer Science»


-- 20.11.2016, 13:48 --

Во-первых, у Вас массивы длины 100, $N = 100$, поэтому когда у Вас в цикле $i = N$, у Вас выход за границы массива.
Во-вторых, я не вижу, где у Вас в коде кусок, отвечающий за граничные условия. Я так понимаю, где-то должно устанавливаться f[N] = 2 или u[N] = 2

Ну так индексы массивов с 0 начинаются, а не с 1, если в нем последний индекс 100, то включая нулевой в нем 101 элемент.
Оно и устанавливается там так.

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 15:56 
Заслуженный участник
Аватара пользователя


06/10/08
6422
fretyno в сообщении #1170319 писал(а):
Ну так индексы массивов с 0 начинаются, а не с 1, если в нем последний индекс 100, то включая нулевой в нем 101 элемент.
Если массив объявлен как double x[100], то в нем последний индекс 99.
А вот в последнем цикле вообще идет обращение к u[101] в первой итерации:
Код:
    for ( int i = N; i >= 2; i--) {
        u[i] = X[i]*u[i+1]+V[i];
       }

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 16:06 


20/11/16
8
Xaositect в сообщении #1170322 писал(а):
fretyno в сообщении #1170319 писал(а):
Ну так индексы массивов с 0 начинаются, а не с 1, если в нем последний индекс 100, то включая нулевой в нем 101 элемент.
Если массив объявлен как double x[100], то в нем последний индекс 99.
А вот в последнем цикле вообще идет обращение к u[101] в первой итерации:
Код:
    for ( int i = N; i >= 2; i--) {
        u[i] = X[i]*u[i+1]+V[i];
       }

Тогда почему у меня не возникает ошибки выхода за границу массива?

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 16:09 
Заслуженный участник
Аватара пользователя


06/10/08
6422
fretyno в сообщении #1170328 писал(а):
Тогда почему у меня не возникает ошибки выхода за границу массива?
Ее нет в большинстве реализаций C++. Он просто тихо берет значение из соседней области памяти, там находится либо мусор, либо соседний массив.

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение20.11.2016, 16:26 


20/11/16
8
Xaositect в сообщении #1170330 писал(а):
fretyno в сообщении #1170328 писал(а):
Тогда почему у меня не возникает ошибки выхода за границу массива?
Ее нет в большинстве реализаций C++. Он просто тихо берет значение из соседней области памяти, там находится либо мусор, либо соседний массив.

Ладно, программа меня не сильно сама интересует. Важен ход решения до кода. Верно ли я все сделал?

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение22.11.2016, 16:41 
Заслуженный участник


09/05/12
25179
fretyno в сообщении #1170223 писал(а):
После всех преобразований имеем такую систему:
$$\left\{
\begin{array}{rcl}
-4{u}_{j+1}+{u}_{j}*(8+{h}^{2}\sin x) - 4{u}_{j-1}={h}^{2}\sin(\frac{\pi}{2}x) \\
u_0=u_1=0 \\
u_N=2$ \\
\end{array}
\right.$$

Далее методом прогонки я решаю СЛАУ из 98 уравнений, т.к. решения u(0), u(1) и u(n) известны.
Вы каким-то хитрым образом сделали вывод, что $u_0=u_1=0$, который ниоткуда не следует. Из нулевого значения производной на левой границе можно получить только то, что $u_0=u_1$. В том же виде, к которому Вы переделали задачу, она оказывается задачей Коши с условиями, заданными на левой границе, которые, естественно, могут оказаться согласованными с условием на правой границе только в том случае, если Вам очень сильно повезет.

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение24.11.2016, 16:08 


20/11/16
8
Pphantom в сообщении #1170858 писал(а):
Вы каким-то хитрым образом сделали вывод, что $u_0=u_1=0$, который ниоткуда не следует. Из нулевого значения производной на левой границе можно получить только то, что $u_0=u_1$. В том же виде, к которому Вы переделали задачу, она оказывается задачей Коши с условиями, заданными на левой границе, которые, естественно, могут оказаться согласованными с условием на правой границе только в том случае, если Вам очень сильно повезет.

Пересмотрел размеры массивов и индексы. Убрал что u[0]=u[1]=0. Вроде теперь правильно. Для наглядности построил график по значениям, думаю, что-то такое и должно было выйти.
Изображение
Код:
#include <iostream>
#include <cmath>
using namespace std;
int main() {
    double h = 0.01;
    int N = 100;
    double x[102] = {0}, f[102] = {0}, u[102] = {0};
    double X[102] = {0}, V[102] = {0};
    double C[102] = {0};
    double A = -4.0, B = -4.0;
    u[N] = 2;
    X[0] = 1;
    V[0] = 0;
    cout << "du/dx(0) =  " << u[0] << ",  u[N] = " << u[N] <<", h = " << h << endl << endl;

    for (int i = 0; i <= N; i++) {
        x[i] = i*h;
        f[i] = h*h*(sin(((M_PI)/2)*x[i]));
        C[i] = 8+h*h*sin(x[i]);
    }

    for (int i = 0; i <= N; i++)
        if (abs(C[i]) < abs(A)+abs(B))
            cout << "Uslovie sxodimosti ne vipolneno!" << endl;

    for (int i = 1; i <= N; i++) {
        X[i] = B/(C[i]-A*X[i-1]);
        V[i] = (A*V[i-1]-f[i])/(C[i]-A*X[i-1]);
    }

    for (int i = N-1; i >= 0; i--)
        u[i] = X[i]*u[i+1]+V[i];

    cout << "i | " << "    X    | " << "       V      | " <<  "   u   | " << endl;
    cout << "----------------------------------" << endl;
    cout << 0 << " | " << X[0] << "         | " << V[0] << "            | " << u[0] << " | " << endl;
    for (int i = 1; i < N; i++)
        cout << i << " | " << X[i] << " | " << V[i] << " | " << u[i] << " | " << endl;

    cout << N << " | " << X[N] << " | " << V[N] << " | " << u[N] << " | " << endl;
    cout<<"Proverka: "<<endl;
    cout<< A*u[49]-C[50]*u[50]+B*u[51] << " = " << f[50] <<endl;

}

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение24.11.2016, 16:22 
Заслуженный участник


09/05/12
25179
Нет, это явно неправильный результат, ищите ошибку.

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение25.11.2016, 12:00 


20/11/16
8
Поставил перед коэффициентом С знак -. Как раз сомневался, нужно ли менять знак у него. График такой вышел
Изображение

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение25.11.2016, 15:10 
Заслуженный участник


09/05/12
25179
Вот это похоже на правильное решение существенно больше. Правда, подписи на осях не разобрать, поэтому количественный результат не проверить.

 Профиль  
                  
 
 Re: Решение одномерной краевой задачи методом разностных схем
Сообщение25.11.2016, 15:29 


20/11/16
8
Pphantom в сообщении #1171600 писал(а):
Вот это похоже на правильное решение существенно больше. Правда, подписи на осях не разобрать, поэтому количественный результат не проверить.

Изображение

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

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



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

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


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

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