1 module des.math.method.calculus.integ; 2 3 public import des.math.basic.traits; 4 public import des.math.basic.mathstruct; 5 6 import std.math; 7 8 /// 9 T euler(T)( in T x, T delegate(in T,double) f, double time, double h ) 10 if( hasBasicMathOp!T ) 11 { 12 return x + f( x, time ) * h; 13 } 14 15 /// 16 T runge(T)( in T x, T delegate(in T,double) f, double time, double h ) 17 if( hasBasicMathOp!T ) 18 { 19 T k1 = f( x, time ) * h; 20 T k2 = f( x + k1 * 0.5, time + h * 0.5 ) * h; 21 T k3 = f( x + k2 * 0.5, time + h * 0.5 ) * h; 22 T k4 = f( x + k3, time + h ) * h; 23 return cast(T)( x + ( k1 + k2 * 2.0 + k3 * 2.0 + k4 ) / 6.0 ); 24 } 25 26 unittest 27 { 28 double a1 = 0, a2 = 0, pa = 5; 29 double time = 0, ft = 10, step = .01; 30 31 auto rpart( in double A, double time ) { return pa; } 32 33 foreach( i; 0 .. cast(ulong)(ft/step) ) 34 { 35 a1 = euler( a1, &rpart, time+=step, step ); 36 a2 = runge( a1, &rpart, time+=step, step ); 37 } 38 39 import std.math; 40 auto va = ft * pa; 41 assert( abs( va - a1 ) <= step * 2 * pa ); 42 assert( abs( va - a2 ) <= step * pa ); 43 44 auto rpart2( in float A, double time ) { return pa; } 45 46 static assert( !is(typeof( euler( a1, &rpart2, 0, 0 ) ))); 47 } 48 49 unittest 50 { 51 static struct Pos 52 { 53 double x=0, y=0; 54 mixin( BasicMathOp!"x y" ); 55 } 56 57 static struct Point 58 { 59 Pos pos, vel; 60 mixin( BasicMathOp!"pos vel" ); 61 } 62 63 Pos acc( in Pos p ) 64 { 65 return Pos( -(p.x * abs(p.x)), -(p.y * abs(p.y)) ); 66 } 67 68 Point rpart( in Point p, double time ) 69 { 70 return Point( p.vel, acc(p.pos) ); 71 } 72 73 auto state1 = Point( Pos(50,10), Pos(5,15) ); 74 auto state2 = Point( Pos(50,10), Pos(5,15) ); 75 76 double t = 0, ft = 10, dt = 0.01; 77 78 foreach( i; 0 .. cast(size_t)(ft/dt) ) 79 { 80 state1 = euler( state1, &rpart, t+=dt, dt ); 81 state2 = runge( state2, &rpart, t+=dt, dt ); 82 } 83 } 84 85 /// 86 unittest 87 { 88 import des.math.linear.vector; 89 90 static struct Point 91 { 92 vec3 pos, vel; 93 mixin( BasicMathOp!"pos vel" ); 94 } 95 96 auto v1 = Point( vec3(10,3,1), vec3(5,4,3) ); 97 auto v2 = Point( vec3(10,3,1), vec3(5,4,3) ); 98 assert( v1 + v2 == Point( vec3(20,6,2), vec3(10,8,6) ) ); 99 assert( v1 * 2.0 == Point( vec3(20,6,2), vec3(10,8,6) ) ); 100 101 Point rpart( in Point p, double time ) 102 { return Point( p.vel, vec3(0,0,0) ); } 103 104 auto v = Point( vec3(10,3,1), vec3(5,4,3) ); 105 106 double time = 0, ft = 10, step = .01; 107 foreach( i; 0 .. cast(ulong)(ft/step+1) ) 108 v = runge( v, &rpart, time+=step, step ); 109 110 assert( (v.pos - vec3(60,43,31)).len2 < 1e-5 ); 111 }