odeint 流观察者和相关问题 [英] odeint streaming observer and related questions

查看:55
本文介绍了odeint 流观察者和相关问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个由 4 个耦合方程组成的系统需要求解,还有一个参数 Gamma[i] 需要迭代.由于我对 C++ 很陌生,因此我的代码非常简陋.如果它在某些部分看起来精致优雅,那只是因为我改编了 odeint 的作者的代码.:)

I have a system of 4 coupled equations to solve and a parameter Gamma[i] to iterate over. Since I am quite new to C++, my code is a very rudimentary. If it looks sophisticated and elegant in certain parts, it is only because I have adapted code from the author of odeint. :)

这个问题与(http://stackoverflow.com/questions/12060111/using-odeint-function-definition/12066958#comment16253600_12066958)有关,但并不完全相同.请不要删除此内容.:(

This question is related to (http://stackoverflow.com/questions/12060111/using-odeint-function-definition/12066958#comment16253600_12066958) but not exactly the same. Please do not delete this. :(

问题已插入代码行之间.

Questions have been inserted between the lines of code.

#include <iostream>
#include <iterator>
#include <algorithm>
#include <boost/numeric/odeint.hpp>
#include <cmath>
#include <vector>
#include <fstream>
#include <iomanip>

using namespace std;
using namespace boost::numeric::odeint;
class NLI_class {
private:
    double gamma;
public:
 NLI_class (double r) : gamma(r) {} 

 void operator()( vector<double> &u , vector<double> &du , double z ) {
            du[0] = u[0]*u[1]*cos(u[3]); //u1
            du[1] = -u[0]*u[0]*cos(u[3]); //u2
            du[2] = gamma * (2/(u[0]*u[0]) - 1/(u[1]*u[1])); //theta
            du[3] = gamma * (1.0/(u[0]*u[0])); //phi1
            du[4] = gamma * (1.0/(u[1]*u[1])); //phi2;

}
};

问题 1:

在我原来的程序中,我有这样的东西将输出通过管道传输到一个 csv 文件:

In my original program, I had something like this to pipe the output to a csv file:

 inline void save(vector<double>& v, string filename)
  {
ofstream output(filename);
for(int i=0;i<v.size();++i){ 
    output << setprecision(64) << v[i] << endl;
}
   }

我如何调整streaming_observer 来做我的save() 做什么?基本上,我想为每次迭代 i 生成 .csv 文件.在这一点上,我正在以丑陋的方式进行操作,即编译所有内容,打开 Windows 命令提示符,然后将 exe 输出通过管道传输到文本文件.这会生成一个包含所有迭代的大文件.

How do I adapt streaming_observer to do what my save() does? Basically, I want to generate .csv files for each iteration i. At this point, I am doing it the ugly way, i.e compiling everything, opening a windows command prompt and then piping the exe output to a text file. This generates one big file with all iterations thrown in there.

分析大量迭代会变得非常痛苦.

This becomes very painful to analyze for a large number of iterations.

struct streaming_observer {

 std::ostream &m_out;
 streaming_observer( std::ostream &out ) : m_out( out ) {}

 void operator()( const vector<double> &x , double t ) const
 {
      m_out << t;
      for( size_t i=0 ; i < x.size() ; ++i )
          m_out << "\t" << x[i];
      m_out << "\n";
 }
};




    int main(){

vector<double> x( 5 );
vector<double> Gamma;
vector<double>delta;
const double  pi=acos(-1.0); 
short delta_n=5;
const double delta_step=(2*pi)/delta_n;
const double dz = 0.01;
const double  zeta = 3.0;
const double  theta_initial=0.0;
const double  u20=tanh(zeta); 
const double  u10=sqrt(1.0-(u20*u20)); 

double d=0.0;
double G=0.0;

for(int i=0;i<=delta_n;i++){
    //When i=0, the d=0.0 and G=0.0 are pushed into the vector.
    delta.push_back(d);  
    Gamma.push_back(G);
    // Compute delta and Gamma
    d=d+delta_step; 
    G=-u10*u10*u20*sin(theta_initial+d);
}

save(delta,"delta.csv");
save(Gamma,"Gamma.csv");

问题#2:我在这里得到的结果与我使用简单的显式欧拉方法得到的结果不一致.因此,我想查看 RK4 系数(最好将它们转储到文件中)或中间步骤.我如何获得这些信息?

Question#2: The results I get here do not agree with what I get with what I get using a simple explicit Euler method. Hence, I would like to see the RK4 coefficients (preferably dump them to a file) or the intermediate steps. How can I get this information?

//Numeric Integration
    for (unsigned i = 0; i < Gamma.size(); ++i) {
        x[0] = u10;
        x[1] = u20;
        x[2] = 0.0;
        x[3] = 0.0;
        x[4] = 0.0;

        NLI_class nli_obj(Gamma[i]);
        integrate_const( runge_kutta4< vector<double > >(), nli_obj, x , 0.0 , 3.0 , dz,streaming_observer( std::cout ) );
}
    }

感谢所有帮助过你的人!

Thank you for all those who helped!

有没有办法获得运行误差估计?请注意 u[0]*u[0]+u[1]*u[1]=1.

Is there some way to get a running error estimate? Note that u[0]*u[0]+u[1]*u[1]=1 at all times.

推荐答案

问题 #1:

我不明白你需要什么样的输出.但是如果你想在每次迭代后写出结果,你可以像这样实现一个输出观察器:

I do not understand exactly what kind of output you need. But if you want to write the result after each iteration you can implement an output observer like this:

struct output_observer
{
    string filename_;
    size_t count_;
    output_observer( const string &filename ) : filename_( filename ) , count_( 0 ) { }
    void operator()( const state_type &x , time_type dt )
    {
        char fn[512] = "";
        sprintf( fn , "%s_%04lu.csv" , filename_.c_str() , count_ );
        ofstream fout( fn );
        for( size_t i=0 ; i<x.size() ; ++i ) fout << x[i] << "\n";
        ++count_;
    }
};

你可以简单地应用这个观察者

You can apply this observer simply by

integrate_const( runge_kutta4< vector<double > >() , nli_obj , x ,
    0.0 , 3.0 , dz , output_observer( "filename" ) );

这是想要的功能吗?

问题#2:

无法看到runge_kutta4的中间e步骤.系数是经典 Runge-Kutta 方法的标准系数:http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods

It is not possible to see the intermediate e steps of runge_kutta4. The coefficients are the standard ones for the classical Runge-Kutta method: http://en.wikipedia.org/wiki/Runge%E2%80%93Kutta_methods

问题 #3:

odeint 有几个错误步进器,可以估计在一个步骤中产生的错误.例如,您可以使用 Runge_Kutta Cash Karp 算法;

odeint has several error steppers, which estimate the error made during one step. You can use for example the Runge_Kutta Cash Karp algorithm;

runge_kutta_cash_karp54< state_type > rk;
state_type xerr;
rk.do_step( nli_obj , x , t , xerr );

执行 ONE step 并估计错误并将错误结果写入 xerr.

which makes ONE step and estimates the error and writes the error result in xerr.

这篇关于odeint 流观察者和相关问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆