单摆的C代码';我不能给出预期的结果
我正试图用RK4积分器为C语言中的FitzHugh-NAgumo神经元网络编写一个代码。由于这不起作用,我决定尝试一些更简单的方法,一个单摆系统。我使用单独的函数——一个用于返回差分数组,一个用于积分器,还有几个函数用于对数组的每个元素进行加法和乘法 以下是返回所有“0”值的代码:单摆的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
#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;
}
}