1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169
|
/*
* fpu.cpp
*
* This example demonstrates how one can use odeint to solve the Fermi-Pasta-Ulam system.
* Created on: July 13, 2011
*
* Copyright 2011-2012 Karsten Ahnert
* Copyright 2011 Mario Mulansky
* Distributed under the Boost Software License, Version 1.0. (See
* accompanying file LICENSE_1_0.txt or copy at
* http://www.boost.org/LICENSE_1_0.txt)
*/
#include <iostream>
#include <numeric>
#include <cmath>
#include <vector>
#include <boost/numeric/odeint.hpp>
#ifndef M_PI //not there on windows
#define M_PI 3.1415927 //...
#endif
using namespace std;
using namespace boost::numeric::odeint;
//[ fpu_system_function
typedef vector< double > container_type;
struct fpu
{
const double m_beta;
fpu( const double beta = 1.0 ) : m_beta( beta ) { }
// system function defining the ODE
void operator()( const container_type &q , container_type &dpdt ) const
{
size_t n = q.size();
double tmp = q[0] - 0.0;
double tmp2 = tmp + m_beta * tmp * tmp * tmp;
dpdt[0] = -tmp2;
for( size_t i=0 ; i<n-1 ; ++i )
{
tmp = q[i+1] - q[i];
tmp2 = tmp + m_beta * tmp * tmp * tmp;
dpdt[i] += tmp2;
dpdt[i+1] = -tmp2;
}
tmp = - q[n-1];
tmp2 = tmp + m_beta * tmp * tmp * tmp;
dpdt[n-1] += tmp2;
}
// calculates the energy of the system
double energy( const container_type &q , const container_type &p ) const
{
// ...
//<-
double energy = 0.0;
size_t n = q.size();
double tmp = q[0];
energy += 0.5 * tmp * tmp + 0.25 * m_beta * tmp * tmp * tmp * tmp;
for( size_t i=0 ; i<n-1 ; ++i )
{
tmp = q[i+1] - q[i];
energy += 0.5 * ( p[i] * p[i] + tmp * tmp ) + 0.25 * m_beta * tmp * tmp * tmp * tmp;
}
energy += 0.5 * p[n-1] * p[n-1];
tmp = q[n-1];
energy += 0.5 * tmp * tmp + 0.25 * m_beta * tmp * tmp * tmp * tmp;
return energy;
//->
}
// calculates the local energy of the system
void local_energy( const container_type &q , const container_type &p , container_type &e ) const
{
// ...
//<-
size_t n = q.size();
double tmp = q[0];
double tmp2 = 0.5 * tmp * tmp + 0.25 * m_beta * tmp * tmp * tmp * tmp;
e[0] = tmp2;
for( size_t i=0 ; i<n-1 ; ++i )
{
tmp = q[i+1] - q[i];
tmp2 = 0.25 * tmp * tmp + 0.125 * m_beta * tmp * tmp * tmp * tmp;
e[i] += 0.5 * p[i] * p[i] + tmp2 ;
e[i+1] = tmp2;
}
tmp = q[n-1];
tmp2 = 0.5 * tmp * tmp + 0.25 * m_beta * tmp * tmp * tmp * tmp;
e[n-1] += 0.5 * p[n-1] * p[n-1] + tmp2;
//->
}
};
//]
//[ fpu_observer
struct streaming_observer
{
std::ostream& m_out;
const fpu &m_fpu;
size_t m_write_every;
size_t m_count;
streaming_observer( std::ostream &out , const fpu &f , size_t write_every = 100 )
: m_out( out ) , m_fpu( f ) , m_write_every( write_every ) , m_count( 0 ) { }
template< class State >
void operator()( const State &x , double t )
{
if( ( m_count % m_write_every ) == 0 )
{
container_type &q = x.first;
container_type &p = x.second;
container_type energy( q.size() );
m_fpu.local_energy( q , p , energy );
for( size_t i=0 ; i<q.size() ; ++i )
{
m_out << t << "\t" << i << "\t" << q[i] << "\t" << p[i] << "\t" << energy[i] << "\n";
}
m_out << "\n";
clog << t << "\t" << accumulate( energy.begin() , energy.end() , 0.0 ) << "\n";
}
++m_count;
}
};
//]
int main( int argc , char **argv )
{
//[ fpu_integration
const size_t n = 64;
container_type q( n , 0.0 ) , p( n , 0.0 );
for( size_t i=0 ; i<n ; ++i )
{
p[i] = 0.0;
q[i] = 32.0 * sin( double( i + 1 ) / double( n + 1 ) * M_PI );
}
const double dt = 0.1;
typedef symplectic_rkn_sb3a_mclachlan< container_type > stepper_type;
fpu fpu_instance( 8.0 );
integrate_const( stepper_type() , fpu_instance ,
make_pair( boost::ref( q ) , boost::ref( p ) ) ,
0.0 , 1000.0 , dt , streaming_observer( cout , fpu_instance , 10 ) );
//]
return 0;
}
|