2016-12-03 9 views
0

Я посетил сайт gnu gsl, и я не нашел здесь примера, чтобы решить дифференциальное уравнение как интуитивное (особенно потому, что оно использует дифференциальное уравнение 2-го порядка). https://www.gnu.org/software/gsl/manual/html_node/ODE-Example-programs.html#ODE-Example-programs Может ли кто-нибудь посоветовать, где найти описательное руководство по тому, как решить очень простой Первый заказ differetial equation.gsl gnu решение обыкновенного дифференциального уравнения первого порядка

Например, если моя функция равна y '= x + 2y (или любая такая функция), то как я могу написать код в gsl для его решения с заданным фиксированным размером шага и начальным условием.

+0

ли это требование о том, что решение будет в C? Попробуйте документацию для python 'scipy.integrate.odeint'. - Или просто внедрите фиксированные шаговые шейки Heun или RK4 в C как учебное упражнение. Попытайтесь найти оптимальный размер шага для заданной точности ... После этого вы поймете, почему интерфейс для общего решателя настолько сложный. – LutzL

+0

Да .. Требование находится в C. – ausworli

+0

Не могли бы вы привести пример примерного кода, который будет делать очень простую функцию, такую, что y '= x + 2y usin GSL? Будучи совершенно новым для этой библиотеки, я не могу сделать основной отправной точкой для такой простой функции, как выше. – ausworli

ответ

1

Для y'=f(x,y)=x+2y массивы имеют все размеры 1, что обычно является чем-то, чего следует избегать, но здесь это инструкция. Для явных решателей, то есть, не содержащие imp в названии, вам не нужно Якобиан

#include <stdio.h> 
#include <gsl/gsl_errno.h> 
#include <gsl/gsl_matrix.h> 
#include <gsl/gsl_odeiv2.h> 

int odefunc (double x, const double y[], double f[], void *params) 
{ 
    f[0] = x+2*y[0]; 
    return GSL_SUCCESS; 
} 


int * jac; 

int main() 
{ 
    int dim =1 
    gsl_odeiv2_system sys = {func, NULL, dim, NULL}; 

    gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys, gsl_odeiv2_step_rkf45, 1e-6, 1e-6, 0.0); 
    int i; 
    double x0 = 0.0, xf = 100.0; /* start and end of integration interval */ 
    double x = x0; 
    double y[1] = { 1.0 }; /* initial value */ 

    for (i = 1; i <= 100; i++) 
    { 
     double xi = x0 + i * (xf-x0)/100.0; 
     int status = gsl_odeiv2_driver_apply (d, &x, xi, y); 

     if (status != GSL_SUCCESS) 
     { 
      printf ("error, return value=%d\n", status); 
      break; 
     } 

     printf ("%.8e %.8e\n", x, y[0]); 
    } 

    gsl_odeiv2_driver_free (d); 
    return 0; 
} 

Вы можете посмотреть на «Введение в компьютерное моделирование с помощью C и инструментов с открытым кодом» книга Хосе М. Гарридо

+0

Hi LutzL, Ваша программа действительно очень полезный ресурс для новичка, подобного мне. Спасибо! Просьба сообщить о следующих вопросах, которые у меня есть: ** (1) **. Предположим, что размер шага равен 0,25, и я хочу оценить от x = 0 до x = 1, я полагаю, что мне нужно запустить цикл for от i = 1 до i = 4 (с 1-0/0.25 = 4). Это верно? ** (2) ** Я надеялся использовать функцию ** gsl_odeiv2_step_rk1imp **. Если я заменил функцию ** gsl_odeiv2_step_rkf45 ** на ** gsl_odeiv2_step_rk1imp **, я получаю ошибку «Ошибка сегментации (сбрасывание ядра)» при попытке ее запуска. Я что-то упускаю? – ausworli

+0

Для неявных методов вы должны предоставить оценку матрицы Якоби. На данный момент вместо этой функции имеется нулевой указатель. - Вы также можете заменить 'for (i = ...' loop на 'while (x LutzL

+0

Hi Lutzl, Ниже мой код. Я пытаюсь оценить y '= x + 2y между x = 0 до x = 1 с начальным условием (x, y) = (0,0), используя gsl_odeiv2_step_rk1imp. Я определил якобиана. Тем не менее, код не работает и бросает ошибки, которые я не могу понять. Любое предложение? – ausworli

0

Lutzl, Пожалуйста, ознакомьтесь с:

'#include <stdio.h> 
#include <gsl/gsl_errno.h> 
#include <gsl/gsl_matrix.h> 
#include <gsl/gsl_odeiv2.h> 

int odefunc (double x, const double y[], double f[], void *params) 
{ 
    f[0] = x+2*y[0]; 
    return GSL_SUCCESS; 
} 


int jac(double x , const double y[] ,double *dfdy , double dfdx[], void *params) { 
    gsl_matrix_view dfdy_mat= gsl_matrix_view_array(dfdy,1,1); 
    gsl_matrix *m= &dfdy_mat.matrix; 
    gsl_matrix_set(m,0,0,x); 
    dfdx[0]=2; 
    return GSL_SUCCESS; 
} 
int main() 
{ 
    int dim =1; 
    gsl_odeiv2_system sys = {odefunc, jac, dim, NULL}; 
    gsl_odeiv2_driver * d = gsl_odeiv2_driver_alloc_y_new (&sys,  gsl_odeiv2_step_rk1imp,1e-7,1e-7, 0.0); 
    int i; 
    double x0 = 0.0, xf =1.0; /*al value */ 

    while(x<xf) 
    { 
     double xi = x0 + 0.25; 
     int status = gsl_odeiv2_driver_apply (d, &x, xi, y); 

     if (status != GSL_SUCCESS) 
     { 
      printf ("error, return value=%d\n", status); 
      break; 
     } 

     printf ("%.8e %.8e\n", x, y[0]); 
    } 
    gsl_odeiv2_driver_free (d); 
    return 0; 
} 
' 
+0

Вы должны узнать, что такое матрица якобиана. В этом примере 'dfdy' и' dfdx' являются 1 × 1 матрицами соответственно. номера. - 'xi' - следующий шаг после позиции' x' и поэтому должен быть установлен на 'xi = x + dx'. Шаг/драйвер продвигается, если возможно, 'x' в позицию' xi' – LutzL

 Смежные вопросы

  • Нет связанных вопросов^_^