单摆的C代码';我不能给出预期的结果

单摆的C代码';我不能给出预期的结果,c,numerical-methods,differential-equations,runge-kutta,C,Numerical Methods,Differential Equations,Runge Kutta,我正试图用RK4积分器为C语言中的FitzHugh-NAgumo神经元网络编写一个代码。由于这不起作用,我决定尝试一些更简单的方法,一个单摆系统。我使用单独的函数——一个用于返回差分数组,一个用于积分器,还有几个函数用于对数组的每个元素进行加法和乘法 以下是返回所有“0”值的代码: #include <stdio.h> #include <math.h> #include <stdlib.h> #include <string.h> int N

我正试图用RK4积分器为C语言中的FitzHugh-NAgumo神经元网络编写一个代码。由于这不起作用,我决定尝试一些更简单的方法,一个单摆系统。我使用单独的函数——一个用于返回差分数组,一个用于积分器,还有几个函数用于对数组的每个元素进行加法和乘法

以下是返回所有“0”值的代码:

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#include <string.h>

int N = 2;

float h = 0.001;

struct t_y_couple{
    float t;
    float* y;
};


float* array_add(int len_array_in,float array_in[2], float array_add[2]);
struct t_y_couple integrator_rk4(float dt,float t, float* p1);

float* oscnetwork_opt(float t, float *y);
float* array_mul(int len_array_in,float array_in[2], float num);


int main(void){
    /* initializations*/
    struct t_y_couple t_y;


    int i,iter;

//  time span for which to run simulation
    int tspan = 20;


//  total number of time iterations = tspan*step_size   
    int tot_time = (int) ceil(tspan/h);

//  Time array
    float T[tot_time];

//  pointer definitions
    float *p, *q;


//  vector to hold values for each differential variable for all time iterations
    float Y[tot_time][2];
//  2*N+sum_adj = total number of coupled differential equations to solve   

//  initial conditions vector for time = 0

    Y[0][0] = 0;
    Y[0][1] = 0.1;
//  set the time array
    T[0] = 0;

//  This loop calls the RK4 code
    for (i=0;i<tot_time-1;i++){
        p = &Y[i][0];   // current time
        q = &Y[i+1][0]; // next time step
//      printf("\n\n");
//      for (j=0;j<2*N+sum_adj;j++)
//          printf("value passed in from main function: %f ,%d ",*(p+j),j);
//      printf("\n");

//      call the RK4 integrator with current time value, and current 
//      values of voltage           
        t_y = integrator_rk4(h,T[i],p);  

//      Return the time output of integrator into the next iteration of time
        T[i+1] = t_y.t; 

//      copy the output of the integrator into the next iteration of voltage        
        q = memcpy(q, t_y.y, (2) * sizeof(float));
//      q = memcpy(q, p, (2*N+sum_adj) * sizeof(float) );

        printf("%f ",T[i+1]);
        for (iter = 0;iter<N;iter++)
            printf("%f ",*(p+iter));
        printf("\n");
    }


    return 0;
}

struct t_y_couple integrator_rk4(float dt,float t, float y[2])
{   
//  initialize all the pointers
    float *y1,*y2,*y3, *yout;
    float tout,dt_half;
    float *k1,*k2,*k3,*k4;
//  initialize iterator
    int i;

//  printf("\n");
    struct t_y_couple ty1;
    tout = t+dt;
    dt_half = 0.5*dt;
    float addition[2];

//  return the differential array into k1
    k1 = oscnetwork_opt(t,y);
//  multiply the array k1 by dt_half    
    k1 = array_mul(2,k1,dt_half);
//  add k1 to each element of the array y passed in
    y1 = array_add(2,y,k1);

//  for (i=0;i<2*N+sum_adj;i++)
//      printf("k1: %f y: %f y1: %f\n",*(k1+i), *(y+i), *(y1+i));

//  do the same thing 3 times
    k2 = oscnetwork_opt(t+dt_half,y1);
    k2 = array_mul(2,k2,dt_half);
    y2 = array_add(2,y,k2); 
//  for (i=0;i<2*N+sum_adj;i++)
//      printf("k2: %f y: %f y2: %f\n",*(k2+i), *(y+i), *(y2+i));

    k3 = oscnetwork_opt(t+dt_half,y2);
    k3 = array_mul(2,k3,dt);
    y3 = array_add(2,y,k3);
//  for (i=0;i<2*N+sum_adj;i++)
//      printf("k3: %f y: %f y3: %f\n",*(k3+i), *(y+i), *(y3+i));

    k4 = oscnetwork_opt(tout,y3);
    k4 = array_mul(2,k4,dt);
    yout = array_add(2,y,k4);
//  for (i=0;i<2*N+sum_adj;i++)
//      printf("k4: %f y: %f y4: %f\n",*(k4+i), *(y+i), *(yout+i));     

//  Make the final additions with k1,k2,k3 and k4 according to the RK4 code
    for (i=0;i<2;i++){
        addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6;
//      printf("final result : addition %f  ", addition[i]);
    }
//  printf("\n");
//  add this to the original array
    yout = array_add(2,y,addition);

//  for (i=0;i<2*N+sum_adj;i++)
//      printf("yout: %f  ",*(yout+i));
//  printf("\n");
//  return a struct with the current time and the updated voltage array
    ty1.t = tout;
    ty1.y = yout;

    return ty1;
}



// function to add two arrays together, element by element
float* array_add(int len_array_in,float array_in[2], float array_sum[2]){
    int i;
    static float *array_out_add= NULL;
    if (array_out_add != 0) {
        array_out_add = (float*) realloc(array_out_add, sizeof(float) * (2));
    } else {
        array_out_add = (float*) malloc(sizeof(float) * (2));
    }

    for (i=0;i<len_array_in;i++){
        array_out_add[i] = array_in[i]+array_sum[i];
//      printf("before adding: %f, add amount: %f , after adding: %f, iteration: %d\n ", array_in[i], array_sum[i], array_out[i],i);
    }
    return array_out_add;
//  return 0;
}


// function to multiply each element of the array by some number
float* array_mul(int len_array_in,float array_in[2], float num){
    int i;
    static float *array_out_mul= NULL;
    if (array_out_mul != 0) {
        array_out_mul = (float*) realloc(array_out_mul, sizeof(float) * (2));
    } else {
        array_out_mul = (float*) malloc(sizeof(float) * (2));
    }
    for (i=0;i<len_array_in;i++){
        array_out_mul[i] =array_in[i]*num;
    }
    return array_out_mul;
//  return 0;
}


// function to return the vector with coupled differential variables for each time iteration
float* oscnetwork_opt(float t, float *y){

//  define and allocate memory for the differential vector
    static float* dydt = NULL;
    if (dydt != 0) {
        dydt = (float*) realloc(dydt, sizeof(float) * (2));
    } else {
        dydt = (float*) malloc(sizeof(float) * (2));
    }


    dydt[0] = y[1];
    dydt[1] = -(0.1*0.1)*sin(y[0]);
    return dydt;
}
#包括
#包括
#包括
#包括
int N=2;
浮动h=0.001;
结构t_y_耦合{
浮动t;
浮动*y;
};
float*array_add(int len_array_in,float array_in[2],float array_add[2]);
结构t_y_耦合积分器_rk4(浮点dt、浮点t、浮点*p1);
浮点数*OSCU选项(浮点数t,浮点数*y);
float*array\u mul(int len\u array\u in,float array\u in[2],float num);
内部主(空){
/*初始化*/
结构t_y_偶t_y;
国际热核实验堆;
//运行模拟的时间跨度
int tspan=20;
//总时间迭代次数=tspan*步长
int tot_时间=(int)ceil(tspan/h);
//时间数组
浮动T[总时间];
//指针定义
浮点数*p,*q;
//用于在所有时间迭代中保存每个微分变量的值的向量
浮动Y[总时间][2];
//2*N+sum_adj=要求解的耦合微分方程总数
//时间向量的初始条件=0
Y[0][0]=0;
Y[0][1]=0.1;
//设置时间数组
T[0]=0;
//这个循环调用RK4代码

对于(i=0;i您的代码有未定义的行为。其核心是因为您在乘法和加法函数中使用静态指针。请允许我将其浓缩为有问题的部分:

k2 = array_mul(2,k2,dt_half);
k3 = array_mul(2,k3,dt); // This either makes k2 point to freed memory, or overwrites the values in the location it points to.

addition[i] = ((*(k1+i)) + (*(k2+i))*2 + (*(k3+i))*2 + (*(k4+i))) *dt/6; // This uses all four pointers as though they must point to distinct memory locations.
首先清除静电。然后可以执行以下两项操作之一:

  • 只需在函数内分配内存并返回指向它的指针。调用代码的责任是在最后释放内存,如下所示:

    free(k1);
    free(k2);
    // etc
    
  • 将指针传递到函数中,以便它们填充,将内存管理完全留给调用代码:

    // function to multiply each element of the array by some number
    void array_mul(int len_array_in,float *array_in, float num, float *array_out){
        int i;
        for (i=0;i<len_array_in;i++){
          array_out[i] =array_in[i]*num;
        }
    }
    
    //将数组的每个元素乘以某个数字的函数
    void数组\u mul(int len\u数组\u in,float*array_uin,float num,float*array\u out){
    int i;
    
    对于(i=0;i你展示了两个程序,但只问了第二个程序的一个问题。那么,第一个程序是做什么的?第二个程序的结果是什么?给出一些关于你得到的结果和预期结果的想法。我实际上是在问第一个程序。我想强调的是,有多个模块的程序没有给出期望的结果,而带有一个主函数的代码确实给出了期望的结果。期望的结果是-不同时间的θ和ω值,当绘制时间时形成正弦波。如果我用第二种方法修改代码,那么我如何返回差分数组?例如,函数oscnetwork_opt使用耦合微分方程设置一个数组,我返回该数组。如果我编写以下代码:
    void osc_opt(float y[2],float*dydt){dydt[0]=y[1];dydt[1]=-sin(y[0]);}
    那也不行。@SamyuktaRamnath-以哪种方式?我提供了两个选项。如果我尝试第二种方法,我会在调用函数中收到乘法的结果吗?事实上,尝试这种方法会给我一个分段错误。@SamyuktaRamnath-你会做类似于
    float arr[2];array\u mul的事情(2,array_in,num,arr);
    关键在于告诉函数在哪里写入,并从计算本身中取消对内存的管理。@SamyuktaRamnath-否。不能传递数组,因为传递总是通过值。这是新手程序员经常遇到的一个复杂问题。函数可以接受指针(可能是数组的第一个元素),数组在传递指针时会隐式地衰减为指针。但是你不会传递数组。
    void foo(int a[2])
    只是
    void foo(int*a)
    的语法糖。没有编译器检查来确保你准确地传递大小为2的数组。
    // function to multiply each element of the array by some number
    void array_mul(int len_array_in,float *array_in, float num, float *array_out){
        int i;
        for (i=0;i<len_array_in;i++){
          array_out[i] =array_in[i]*num;
        }
    }