Метод рунге-кутты-мерсона - C (СИ)

Узнай цену своей работы

Формулировка задачи:

нужно написать программу для решения систем из n дифф уравнений методом рунге-кутты-мерсона(он же пятиэтапный метод рунге кутта 4 порядка). вот кусок кода,который считает для одного уравнения.написан не идеально,только учусь..вот не могу понять как сделать для системы..уже сижу дня три и уже голову сломал..есть еще куски,пробовал написать для двух уравнений,но такое не принимают... спасите меня...хоть какой-нибудь идейкой...просто исчерпал все свои знания. у нас есть система вида y1'=a1*y1+b1*y2+..+N1*yn y2'=a2*y1+b2*y2+..+N2*yn ..................................... yn'=an*y1+bn*y2+..+Nn*yn и есть начальные условия,как для задачи коши
do
    {
        k1=f(x[i],y[i]);
        k2=f(x[i]+h/3,y[i]+h/3*k1);
        k3=f(x[i]+h/3,y[i]+h/6*k1+h/6*k2);
        k4=f(x[i]+h/2,y[i]+h/8*k1+3*h/8*k2);
        k5=f(x[i]+h,y[i]+h/2*k1-3*h/2*k3+2*h*k4);
        yx=y[i]+h/2*(k1-3*k3+4*k4);
        y=y[i]+h/6*(k1+4*k4+k5);
        r=0.2*abs(y-yx);
        if(r>e) h=h/2;
        else 
        {
            if((r<=e/64)&&(2*h<h0)) h=2*h;
            else h=h;
        }
        while(r>e)
        {
            k1=f(x[i],y[i]);
            k2=f(x[i]+h/3,y[i]+h/3*k1);
            k3=f(x[i]+h/3,y[i]+h/6*k1+h/6*k2);
            k4=f(xi]+h/2,y[i]+h/8*k1+3*h/8*k2);
            k5=f(x[i]+h,y[i]+h/2*k1-3*h/2*k3+2*h*k4);
            yx=y[i]+h/2*(k1-3*k3+4*k4);
            y=y[i]+h/6*(k1+4*k4+k5);
            r=0.2*abs(y-yx);
            if(r>e) h=h/2;
            else 
            {
                if((r<=e/64)&&(2*h<h0)) h=2*h;
                else h=h;
            }
        }
 
        y[i+1]=y;
        i=i+1;
        x[i]=x[i-1]+h;
        
    }
    while (x[i-1]<=xn);

Решение задачи: «Метод рунге-кутты-мерсона»

textual
Листинг программы
double X,X9,H, EH,EPS,H0,P,D,X1,Y[8];
//------------------------------------------------------ ïðîèçâîäГ*ûå *>
void RP(double X,double *Y,double *F)
{
   F[0] = Y[1];
   F[1] = P * (1.0 - Y[0]*Y[0])*Y[1]-Y[0];
}
//------------------------------------------------ ÌÅÒÎÄ ÐÓÍÃÅ-ÊÓÒÒÛ-ÌÅÐÑÎÍÀ *>
void RKM(int N,double *X,double *H,double *E, double *Y)
{
        int I;
        double H3,H4,R = 0.0,A,Z[8],F0[8],F[8],K1[8],K3[8];
        RP(*X,&Y[0],&F[0]);
        for (I=0;I<N ;I++)
           Z[I] = Y[I];
        do
        {
                H3 = *H / 3.0;
                H4 = 4 * H3;
                for (I=0; I<N; I++)
                {
                        K1[I] = H3 * F0[I];
                        Y[I] = Z[I] + K1[I];
                }
                RP(*X + H3,&Y[0],&F[0]);
                for (I=0; I<N; I++)
                   Y[I] = Z[I] + (K1[I] + H3*F[I])/2;
                RP(*X + H3,&Y[0],&F[0]);
                for (I=0; I<N; I++)
                {
                        K3[I] = *H * F[I];
                        Y[I] = Z[I] + 0.375 * (K1[I] + K3[I]);
                }
                RP((*X + *H/2),&Y[0],&F[0]);
                for (I=0; I<N; I++)
                {
                        K1[I] += H4 * F[I];
                        Y[I] = Z[I] + 1.5 * (K1[I] + K3[I]);
                }
                RP(*X + *H/2,&Y[0],&F[0]);
                for (I=0; I<N; I++)
                {
                        K1[I] += H4 * F[I];
                        Y[I] = Z[I] + 1.5 * (K1[I] - K3[I]);
                }
                RP(*X + *H,&Y[0],&F[0]);
                for (I=0; I<N; I++)
                {
                        A = H3 * F[I];
                        Y[I] = Z[I] + (K1[I] + A)/2;
                        A = 2 * K1[I] - 3.0 * K3[I] - A;
                        if ( Y[I] != 0.0)
                                A /= Y[I];
                        if ( abs(A) > R )
                                R=abs(A);
                }
                *H = *H/2;
        }
        while(R<*E);
        *H *= 2;
        *X += *H;
        if (32*R < *E)
                *H *= 2;
}
void __fastcall TForm1::run() 
{
//входящие данные
        X=Edit1->Text.ToDouble();
        X9=Edit2->Text.ToDouble();
        H=Edit3->Text.ToDouble();
        EH=Edit4->Text.ToDouble();
        EPS=Edit5->Text.ToDouble();
        H0=Edit6->Text.ToDouble();
        Y[0]=Edit7->Text.ToDouble();
        Y[1]=Edit8->Text.ToDouble();
        P=Edit9->Text.ToDouble();
//входящие данные
        X1 = X;
        RKM(2,&X,&H0,&EPS,Y);
        H0 =  Sign (H);
        D  = X1 + H - X;
        if (D < 0.0 == (H>0.0))
                H0 = D;
}

Объяснение кода листинга программы

  1. Входные данные:
    • X = Edit1->Text.ToDouble()
    • X9 = Edit2->Text.ToDouble()
    • H = Edit3->Text.ToDouble()
    • EH = Edit4->Text.ToDouble()
    • EPS = Edit5->Text.ToDouble()
    • H0 = Edit6->Text.ToDouble()
    • Y[0] = Edit7->Text.ToDouble()
    • Y[1] = Edit8->Text.ToDouble()
    • P = Edit9->Text.ToDouble()
  2. Код реализует метод RKM (Runge-Kutta-Merson) для решения обыкновенного дифференциального уравнения.
  3. Переменные, используемые в методе RKM:
    • Z[i] - временная переменная для хранения промежуточных значений
    • F0[i] - массив для хранения начальных значений функций
    • F[i] - массив для хранения текущих значений функций
    • K1[i] - массив для хранения первых приближений
    • K3[i] - массив для хранения третьих приближений
    • A - временная переменная для хранения значения величины приращения
  4. Выходные данные:
    • H0 - полученное приближение решения
    • D - ошибка при решении
  5. В методе TForm1::run() происходит следующее:
    • Входные данные считываются из текстовых полей и преобразуются в числовые значения.
    • Вызывается функция RKM с параметрами N=2 и указанием входных переменных X, H0, EPS, Y.
    • Значение H0 изменяется на знак числа H.
    • Вычисляется значение D как разность между X1 и X, где X1 - предыдущее значение X.
    • Если D меньше нуля и H больше нуля, то H0 присваивается значение D.

ИИ поможет Вам:


  • решить любую задачу по программированию
  • объяснить код
  • расставить комментарии в коде
  • и т.д
Попробуйте бесплатно

Оцени полезность:

9   голосов , оценка 4.111 из 5
Похожие ответы