Boost.odeintで遊ぼう

@rydotyosh / Ryogo Yoshimura

2015.05.30

自己紹介

CAD/CAM

https://www.cgsys.co.jp/g/products/CAM-TOOL/3dcam_cl.htm

曲面/曲線

http://en.wikipedia.org/wiki/Tangent_space
http://en.wikipedia.org/wiki/Normal_(geometry)

曲面/曲線

http://en.wikipedia.org/wiki/Cross_section_(geometry)

Boost.odeint

http://www.boost.org/doc/libs/release/libs/numeric/odeint/doc/html/index.html

Boost.odeint

微分

http://en.wikipedia.org/wiki/Derivative

常微分方程式の初期値問題

http://en.wikipedia.org/wiki/Galaxy
http://en.wikipedia.org/wiki/Food_chain

常微分方程式の初期値問題

常微分方程式の初期値問題

解析解と数値近似

解析解が求まってくれる例

数値近似の基本的な考え方

陽的 Euler 法

陽的 Euler 法

陽的 Euler 法

陽的 Euler 法

#include <iostream>
#include <array>
#include <boost/numeric/odeint.hpp>
namespace odeint = boost::numeric::odeint;
using state_type = std::array< double, 1 >;

陽的 Euler 法

auto exponential = [](
  const state_type &x,
  state_type &dxdt,
  const double /* t */
) {
  dxdt[ 0 ] = x[ 0 ]; // x`(t) = x(t)
};

陽的 Euler 法

auto x0 = state_type{ 1.0 }; // 初期状態
auto t0 = 0.0; // 開始パラメータ
auto t1 = 1.0; // 終了パラメータ
auto dt = 0.1; // ステップ

陽的 Euler 法

auto stepper =
  odeint::euler< state_type >();
odeint::integrate_const(
  stepper, exponential, x0, t0, t1, dt,
  [](const state_type &x, const double t){
    std::cout << t << "\t"
              << x[ 0 ] << std::endl;
  } );

陽的 Euler 法

陽的 Euler 法

陽的 Euler 法

数値近似の基本的な考え方

Runge-Kutta 法

auto stepper =
  odeint::runge_kutta4< state_type >();
odeint::integrate_const(
  stepper, exponential, x0, t0, t1, dt,
  [](const state_type &x, const double t){
    std::cout << t << "\t"
              << x[ 0 ] << std::endl;
  } );

Runge-Kutta 法

Runge-Kutta 法

いろんな数値近似

いろんな数値近似

いろんな数値近似の考え方

次数

適応的

陽解法と陰解法

陽解法と陰解法

一般化 Runge-Kutta 法

一般化 Runge-Kutta 法

一般化 Runge-Kutta 法

一般化 Runge-Kutta 法

マルチステップ法

数列加速

クロソイド曲線を書いてみる

https://www.flickr.com/photos/jqpubliq/17180604744/

クロソイド曲線を書いてみる

クロソイド曲線を書いてみる

クロソイド曲線を書いてみる

クロソイド曲線を書いてみる

using state_type = std::array< double, 2 >;
auto clothoid = [](
  const state_type &/* x */,
  state_type &dxdt,
  const double t
) {
  dxdt[ 0 ] = cos( t * t / 2.0 ); // x`
  dxdt[ 1 ] = sin( t * t / 2.0 ); // y`
}

クロソイド曲線を書いてみる

auto x0 = state_type{ 0.0, 0.0 }; // 初期状態
auto t0 = 0.0;
auto t1 = 10.0;
auto dt = 0.01;
odeint::integrate(
  clothoid, x0, t0, t1, dt,
  []( const state_type &x, const double t ){
    std::cout << x[ 0 ] << "\t"
              << x[ 1 ] << std::endl;
  } );

クロソイド曲線を書いてみる

クロソイド曲線を書いてみる

クロソイド曲線を書いてみる

auto stepper =
  odeint::controlled_runge_kutta<
    odeint::runge_kutta_dopri5< state_type > >();
odeint::integrate_const(
  stepper, clothoid, x0, t0, t1, dt,
  []( const state_type &x, const double t ){
    std::cout << x[ 0 ] << "\t"
              << x[ 1 ] << std::endl;
  } );

クロソイド曲線を書いてみる

複素数表現にしてみる

\[ z^\prime(t) = \exp \frac{it^2}{2}, i = \sqrt {-1} \]

複素数表現にしてみる

//using state_type = std::array< double, 2 >;
  using state_type = std::complex< double >;
  auto clothoid = [](
    const state_type &/* x */,
    state_type &dxdt,
    const double t
  ) {
//  dxdt[ 0 ] = cos( t * t / 2.0 );
//  dxdt[ 1 ] = sin( t * t / 2.0 );
    dxdt = std::exp( 1i * t * t / 2.0 );
  };

複素数表現にしてみる

  auto stepper =
    odeint::controlled_runge_kutta<
      odeint::runge_kutta_dopri5< state_type > >();
  odeint::integrate_const(
    stepper, clothoid, x0, t0, t1, dt,
    [](const state_type &x, const double t){
//    std::cout << x[ 0 ] << "\t"
//              << x[ 1 ] << std::endl;
      std::cout << x.real() << "\t"
                << x.imag() << std::endl;
    } );

複素数表現にしてみる

天体の動き

天体の動き

天体の動き

天体の動き

天体の動き

using state_type = std::vector< double >;
auto astro = [](
  const state_type &x,
  state_type &dxdt,
  const double /*t*/
) {
  dxdt[ 0 ] = x[ 2 ]; // u`
  dxdt[ 1 ] = x[ 3 ]; // v`
  auto r2 = x[ 0 ] * x[ 0 ] + x[ 1 ] * x[ 1 ];
  auto r3 = pow( r2, 3.0 / 2.0 );
  dxdt[ 2 ] = -x[ 0 ] / r3; // x`
  dxdt[ 3 ] = -x[ 1 ] / r3; // y`
};

天体の動き

auto x0 = state_type{ 3.0, 0.0, 0.3, 0.2 };
auto t0 = 0.0, t1 = 16.0, dt = 0.01;
auto stepper =
  odeint::controlled_runge_kutta<
    odeint::runge_kutta_dopri5< state_type > >();
odeint::integrate_const(
  stepper, astro, x0, t0, t1, dt,
  [](const state_type &x, const double t){
    std::cout << t << "\t"
              << x[ 0 ] << "\t"
              << x[ 1 ] << std::endl;
  } );

天体の動き

天体の動き

天体の動き

auto x0 = state_type{ 3.0, 0.0, 0.3, 0.2 };
auto t0 = 0.0, t1 = 16.0, dt = 0.2;
auto stepper =
  odeint::controlled_runge_kutta<
    odeint::runge_kutta_dopri5< state_type > >();
odeint::integrate_const(
  stepper, astro, x0, t0, t1, dt,
  [](const state_type &x, const double t){
    std::cout << t << "\t"
              << x[ 0 ] << "\t"
              << x[ 1 ] << std::endl;
  } );

天体の動き

天体の動き

天体の動き

auto x0 = state_type{ 3.0, 0.0, 0.3, 0.2 };
auto t0 = 0.0, t1 = 16.0, dt = 0.2;
auto stepper =
  odeint::controlled_runge_kutta<
    odeint::runge_kutta_dopri5< state_type > >();
odeint::integrate_adaptive(
  stepper, astro, x0, t0, t1, dt,
  [](const state_type &x, const double t){
    std::cout << t << "\t"
              << x[ 0 ] << "\t"
              << x[ 1 ] << std::endl;
  } );

天体の動き

天体の動き

感想

蛇足