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