4

我有一个程序应该用四阶 runge kutta 方法和 eulercromer 方法计算钟摆的轨迹,不幸的是......我有一个段错误。

我不知道如何解决这个问题,你可以看到我有一些 std::cout 来尝试调试,但它们甚至不输出。这使我相信该函数永远不会执行 main();

我目前的直觉说它在函数声明期间出错,但如果我错了,我想知道。如果可能的话,你能描述一下你用来调试的技术吗?

#include <iostream>
#include <cmath>
#include <string>
#include <vector>
#include <stdlib.h>
#include <fstream>

#define N 1

// Pendulum Variables
double d_pendLength = 1.0, d_pendMass = 1.0; // Pendulum Properties
double d_viscParam = 1.0, d_gravity = 1.0; //9.80665; // Enviromental Factors
double d_dAmp = 0.0, d_dFreq = 0.0; // Driving Force

double d_initTheta = 0.0, d_initAVel = 0.0; //Initial Conditions

void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step);
void v_eulercromer(double d_time, std::vector<double> d_pendulum, double d_step);
double d_derivative(double d_time, std::vector<double> d_pendulum, int i_de);

int main(void)
{
    // Numerical Variables
    double d_step = 0.01, d_mTime = -1, d_mPeriod  = 300;

    // Global Variables
    double d_time = 0.0, d_period = 0.0, d_limit;

    // Function Vectors
    std::vector<double> d_pendulum (2);

    // Settings
    std::string plot = "theta", algo = "rk4";


    std::cout << "START!";
    std::ofstream file_output;
    std::cout << "HAIDATA!";
    file_output.open("pendulum.data");

    std::cout << "HAI!";
    d_pendulum.at(0)= d_initTheta;  //Initial Theta
    d_pendulum.at(1)= d_initAVel;   //Initial Omega
    std::cout <<"BAI!";

    if (d_mPeriod > 0)
    {
        d_limit = d_mPeriod;
    }
    else if (d_mTime > 0)
    {
        d_limit = d_mTime;
    }
    else
    {
        std::cout << "No Limit Specified";
        exit(1);
    }

    for (int i_currentStep=1; i_currentStep*d_step<=d_limit;i_currentStep++)       
    {
        d_time = i_currentStep*d_step;

        if (algo == "rk4")
        {
            v_rungekutta(d_time, d_pendulum, d_step);
        }
        else if (algo == "ec")
        {
            v_eulercromer(d_time, d_pendulum, d_step);
        }
        file_output << d_time << d_pendulum.at(0) << d_pendulum.at(1) << std::endl;
    }


    file_output.close();
    d_pendulum.clear();

    return 0;
}


void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step)
{
    double h=d_step/2.0;  
    std::vector<double> t1, t2, t3, k1, k2, k3, k4;
    int i;

    for (i=N;i>0;i--) t1[i]=d_pendulum.at(i)+0.5*(k1[i]=d_step*d_derivative(d_time, d_pendulum, i));
    for (i=N;i>0;i--) t2[i]=d_pendulum.at(i)+0.5*(k2[i]=d_step*d_derivative(d_time+h, t1, i));
    for (i=N;i>0;i--) t3[i]=d_pendulum.at(i)+ (k3[i]=d_step*d_derivative(d_time+h, t2, i));
    for (i=N;i>0;i--) k4[i]=d_step*d_derivative(d_time+d_step, t3, i);

    for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
}

void v_eulercromer(double d_time, std::vector<double> d_pendulum, double d_step)
{
    int i;
    for (i=N;i>0;i--) d_pendulum.at(i) += d_derivative(d_time, d_pendulum, i)*d_step;
}

double d_derivative(double d_time, std::vector<double> d_pendulum, int i_de)
 {
    double dtheta = d_pendulum.at(1);
  if (i_de==0) return dtheta;
  double domega = d_pendulum.at(1)+((-d_gravity/d_pendLength)*sin(d_pendulum.at(0)))+(-d_viscParam*(d_pendulum.at(1)))+(d_dAmp*sin(d_dFreq*d_time));
  if (i_de==1) return domega; 
  if (i_de < 0) return 0; // 0 is a possible value, exit with exit func.
}

解决方案

我的问题是我没有正确访问 rungekutta 中的向量,也没有给它们一个起始大小。

    void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step)
    {
        double h=d_step/2.0;  
        std::vector<double> t1, t2, t3, k1, k2, k3, k4;
        int i;

        for (i=N;i>0;i--) t1[i]=d_pendulum.at(i)+0.5*(k1[i]=d_step*d_derivative(d_time, d_pendulum, i));
        for (i=N;i>0;i--) t2[i]=d_pendulum.at(i)+0.5*(k2[i]=d_step*d_derivative(d_time+h, t1, i));
        for (i=N;i>0;i--) t3[i]=d_pendulum.at(i)+ (k3[i]=d_step*d_derivative(d_time+h, t2, i));
        for (i=N;i>0;i--) k4[i]=d_step*d_derivative(d_time+d_step, t3, i);

        for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
    }

后:

    void v_rungekutta(double d_time, std::vector<double> d_pendulum, double d_step)
    {
        double h=d_step/2.0;  
        std::vector<double> t1 (2), t2 (2), t3 (2), k1 (2), k2 (2), k3 (2), k4 (2);
        int i;

        for (i=N;i>0;i--) t1.at(i)=d_pendulum.at(i)+0.5*(k1.at(i)=d_step*d_derivative(d_time, d_pendulum, i));
        for (i=N;i>0;i--) t2.at(i)=d_pendulum.at(i)+0.5*(k2.at(i)=d_step*d_derivative(d_time+h, t1, i));
        for (i=N;i>0;i--) t3.at(i)=d_pendulum.at(i)+ (k3.at(i)=d_step*d_derivative(d_time+h, t2, i));
        for (i=N;i>0;i--) k4.at(i)=d_step*d_derivative(d_time+d_step, t3, i);

        for (i=N;i>0;i--) d_pendulum.at(i) += (k1[i]+2*k2[i]+2*k3[i]+k4[i])/6.0;
    }
4

1 回答 1

4

乍一看,您正在尝试访问空向量中的元素。尝试[]用方法替换运算符at()。不同之处在于前者不会检查可能产生段错误的边界,而后者会检查,如果索引超出范围则抛出异常。

于 2013-10-27T07:03:58.313 回答