Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Формула дифференцирования назад, проблема сходимости 
:(
    Опции темы
w1zard350
Дата 16.4.2010, 18:07 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



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

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



Здравствуйте, форумчане! smile 

Пишу программу для решения систем дифференциальных уравнений методом ФДН (формула дифференцирования назад). Проблема в том, что уже который день мучаюсь, но процесс постоянно расходящийся. Объясню проблему на примере.

Необходимо решить задачу Коши для такой системы ДУ :

y_ = y + 5*z
z_ = - y - 3*z

где y_, z_ - производные. Отрезок интегрирования [0,4], начальные условия y(0)=1, z(0)=1.

Обычные одношаговые или многошаговые методы решают без проблем (или у меня просто не возникло там проблем).

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

#include <iostream>
using namespace std;
#include <vector>
#include <cmath>
#include "WSystemNewton.h"
#include "GaussMainColumn.h"
vector<double> X;
vector<double> Y;
vector<double> Z;
double f1(double x, double y, double z, double y_, double z_)
{
    return -y_ + y + 5 * z;
}
double f2(double x, double y, double z, double y_, double z_)
{
    return -z_ - y - 3 * z;
}
//--------------------------------------------------------------------------------//
double calcYn(int p, char func, double h, int k)
{
    double* A = new double[(p + 1) * (p + 1)];
    double* B = new double[p + 1];
    double* gamma = new double[p + 1];
    double xk1 = X[k] + h;

    // заполняем первую строку
    for (int j = 0; j < p + 1; j++)
        A[j] = 1;
    // заполняем 2..p строки матрицы
    for (int i = 1; i < p + 1; i++)
    {
        for (int j = 0; j < p + 1; j++)
        {
            A[i * (p + 1) + j] = pow((xk1 - X[k - j]) / (h), i);
        }
    }
    // заполняем вектор свободных членов
    B[0] = 1;
    for (int i = 1; i < p + 1; i++)
        B[i] = 0;

    GaussMainColumn gmc(p + 1, A, B);
    //    gmc.printMatrix();
    gmc.setDebugMode(false);
    gmc.process();
    //    gmc.printMatrix();
    gamma = gmc.getX();

    //    for(int i = 0; i < p + 1; i++)
    //        cout << "gamma[i] = " << gamma[i] << endl;
    //    cout << "-------------------" << endl;

    double yk1n = 0;
    double gammaI = 0;
    double yk1_i = 0;

    if (func == 'y')
        for (int i = 1; i <= p + 1; i++)
        {
            gammaI = gamma[i - 1];
            yk1_i = Y[k + 1 - i];
            yk1n += gammaI * yk1_i;
        }

    if (func == 'z')
        for (int i = 1; i <= p + 1; i++)
        {
            gammaI = gamma[i - 1];
            yk1_i = Z[k + 1 - i];
            yk1n += gammaI * yk1_i;
        }

    //    cout << "yk1n = " << yk1n << endl;

    delete[] A;
    delete[] B;
    return yk1n;
}
//--------------------------------------------------------------------------------//
double calcY_(int p, char func, double h, int k, double yk1)
{
    double* A = new double[(p + 1) * (p + 1)];
    double* B = new double[p + 1];
    double* alpha = new double[p + 1];
    double xk1 = X[k] + h;

    // заполняем первую строку
    for (int j = 0; j < p + 1; j++)
        A[j] = 1;
    // заполняем 2..p строки матрицы
    for (int i = 1; i < p + 1; i++)
    {
        for (int j = 0; j < p + 1; j++)
        {
            if (j != 0)
                A[i * (p + 1) + j] = pow((xk1 - X[k - j + 1]) / (h), i);
            else
                A[i * (p + 1) + j] = 0;
        }
    }
    // заполняем вектор свободных членов
    for (int i = 1; i < p + 1; i++)
        B[i] = 0;
    B[1] = 1;

    GaussMainColumn gmc(p + 1, A, B);
    //    gmc.printMatrix();
    gmc.setDebugMode(false);
    gmc.process();
    //    gmc.printMatrix();

    for (int i = 0; i < p + 1; i++)
        alpha[i] = gmc.getX()[i];

    //    for(int i = 0; i < p + 1; i++)
    //        cout << "alpha[i] = " << alpha[i] << endl;
    //    cout << "-------------------" << endl;

    double yk1_ = 0;
    double Yk1_i = 0;

    if (func == 'y')
        for (int i = 0; i <= p; i++)
            if (i != 0)
            {
                Yk1_i = Y[k + 1 - i];
                yk1_ += alpha[i] * Yk1_i;
            }
            else
                yk1_ += alpha[i] * yk1;

    if (func == 'z')
        for (int i = 0; i <= p; i++)
            if (i != 0)
                yk1_ += alpha[i] * Z[k + 1 - i];
            else
                yk1_ += alpha[i] * yk1;

    yk1_ *= -1.0 / h;

    //    out << "yk1_ = " << yk1_ << endl;

    delete[] A;
    delete[] B;
    delete[] alpha;
    return yk1_;
}
int main()
{
    //--------------------------------------------------//
    // Инициализация
    double a = 0;
    double b = 4;
    double x0 = a;
    double y0 = 1;
    double z0 = 1;
    double h = (b - a) / 1000;

    // минимальный и максимальный шаги интегрирования
    double hmin = (b - a) / 1000000.0;
    double hmax = (b - a) / 4.0;
    // минимальный и максимальный порядки методов
    double pmin = 2;
    double pmax = 6;

    double p = 3;

    WSystemNewton sys;
    sys.f1 = f1;
    sys.f2 = f2;

    double xk = x0, yk = y0, zk = z0;

    double xk1 = xk + h;
    double zk1 = 0, yk1 = 0;
    // коефициенты k для метода Рунге-Кутта 3 порядка
    double k1y = 0, k1z = 0, k2y = 0, k2z = 0, k3y = 0, k3z = 0;

    X.push_back(xk);
    Y.push_back(yk);
    Z.push_back(zk);
    int k = 0;
    cout << "xk1 = " << xk << "\tyk1 = " << yk << "\tzk1 = " << zk << endl;
    //--------------------------------------------------//
    // определение начальных значений для стартования
    for (int i = 0; i < p; i++)
    {
        xk1 = xk + h;
        // считаем коефициент k1 для всех уравнений
        k1y = h * f1(xk, yk, zk, 0, 0);
        k1z = h * f2(xk, yk, zk, 0, 0);
        // считаем коефициент k2 для всех уравнений
        k2y = h * f1(xk + h / 3.0, yk + k1y / 3.0, zk + k1z / 3.0, 0, 0);
        k2z = h * f2(xk + h / 3.0, yk + k1y / 3.0, zk + k1z / 3.0, 0, 0);
        // считаем коефициент k3 для всех уравнений
        k3y = h * f1(xk + (2 / 3.0) * h, yk + (2 / 3.0) * k2y, zk + (2 / 3.0)
                * k2z, 0, 0);
        k3z = h * f2(xk + (2 / 3.0) * h, yk + (2 / 3.0) * k2y, zk + (2 / 3.0)
                * k2z, 0, 0);

        // искомые функции
        yk1 = yk + (1 / 4.0) * (k1y + 3 * k3y);
        zk1 = zk + (1 / 4.0) * (k1z + 3 * k3z);

        xk += h;
        yk = yk1;
        zk = zk1;
        // запоминаем значения решения
        X.push_back(xk1);
        Y.push_back(yk1);
        Z.push_back(zk1);

        cout << "xk1 = " << X[k + 1] << "\tyk1 = " << Y[k + 1] << "\tzk1 = "
                << Z[k + 1] << endl;

        k++;
    }
    double yk1n = 0;
    double zk1n = 0;
    double yk1_ = 0;
    double zk1_ = 0;
    double alpha = 0;
    xk = xk1;
    while (xk1 + h <= b + 0.01)
    {
        xk1 = xk + h;

        yk1n = calcYn(p, 'y', h, k);
        zk1n = calcYn(p, 'z', h, k);

        yk1_ = calcY_(p, 'y', h, k, yk1n);
        zk1_ = calcY_(p, 'z', h, k, zk1n);

        cout << "yk1n = " << yk1n << "\tzk1n = " << zk1n << endl;
        cout << "yk1_ = " << yk1_ << "\tzk1_ = " << zk1_ << endl;

        sys.setFirstCondition(xk1, yk1n, zk1n, yk1_, zk1_);
        sys.calculate();

        yk1 = sys.getY();
        zk1 = sys.getZ();

        xk = xk1;

        X.push_back(xk1);
        Y.push_back(yk1);
        Z.push_back(zk1);
        cout << "xk1 = " << X[k + 1] << "\tyk1 = " << Y[k + 1] << "\tzk1 = "
                << Z[k + 1] << endl;
        cout << "------------------------------" << k << "------------------------------------" << endl;
        k++;
    }
    return 0;
}



Если нужна дополнительная информация - спрашивайте. Очень нужна помощь. Спасибо!


Это сообщение отредактировал(а) w1zard350 - 16.4.2010, 21:53
PM MAIL   Вверх
Фантом
Дата 17.4.2010, 10:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


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


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

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



Цитата(w1zard350 @  16.4.2010,  18:07 Найти цитируемый пост)

Если нужна дополнительная информация - спрашивайте. Очень нужна помощь. Спасибо!

Честно говоря, тут сложно что-то сказать, кроме того, что программа для такой задачи запредельно громоздкая. Было бы полезно посмотреть на ее поведение для разных вариантов систем, но это не сделать, поскольку часть реализации осталась "за кадром".
PM   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Алгоритмы"

maxim1000

Форум "Алгоритмы" предназначен для обсуждения вопросов, связанных только с алгоритмами и структурами данных, без привязки к конкретному языку программирования и/или программному продукту.


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

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


 




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


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

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