Kinematics problem (codeblocks)

Pages: 12
I'm guessing that your argument is "it might never reach point B because in the numerical approximation the speed becomes negative right before it gets there and it starts heading back towards A, even though the exact correct answer is that it stops exactly at 20km." I didn't run your code; I'm guessing that's what you're saying.

Yes, that's correct.

I'm guessing you're saying that the forward-euler is more likely to suffer that problem than the runge-kutta.

Actually, for once, Forward-Euler is more forgiving than Runge-Kutta. Its tendency to overshoot (for this problem) means that it tends to get past the 20km limit before it realises it should be going backwards.

I sound dismissive here so by all means have a rant

I didn't think you were or are dismissive, I wasn't remotely offended, and, if I was, I could just leave the thread rather than rant.

you could have just said it in words instead of presenting code

I tried the words (and the exact analysis) and probably didn't put any point across very well. The code is there to play ... or not. It can be adapted for plenty of other problems if not used here.

The main problems are that (1) the OP hasn't described the problem or the required approach required very clearly; (2) I still think the problem isn't well-posed. If the exact answer is ignored then an arbitrary negative acceleration a3 would lead to either the train failing to reach its destination, or reaching it while still moving forward at some speed.
Hello every one I believe I have made some progress with my exercise.


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
  #include <iostream>
#include <cmath>

using namespace std;

int main()
{
    cout << "Task 3 - Kinematics \n" << endl;
    float a1,a2,a3,dt,vi,v,si,s,t,T,tgr1,tgr2,tgr3,tgr4,vgr1,vgr2,vgr3;
    int i;

    cout<<"input time (seconds): "; cin>>T; cout<<"\n"<<endl;
    cout<<"a1:"; cin>>a1;
    cout<<"a2:"; cin>>a2;
    dt=1;
    vi=0;
    si=0;


    t=0;
    tgr1=sqrt(20000/a1);
    vgr1=vi+a1*tgr1;
    for(i=1; i<=tgr1; i++)
    {
         t=t+dt;
         s=si+vi*t+(1/2)*a1*t*t;
        if(t==T)
        {
            cout<<s;
        }

    }


    t=0;
    tgr2=-vgr1*sqrt(v*v+20000*a2);
    vgr2=vgr1+a2*tgr2;
    for(i=1; i<=tgr2; i++)
    {
        t=t+dt;
        s=10000+vgr1*t+(1/2)*a2*t*t;
        if(t+tgr1==T)
            cout<<s;

    }


    t=0;
    tgr3=1/vgr2;
    vgr3=vgr2;
    for(i=1; i<=tgr3; i++)
    {
        t=t+dt;
        s=15000+vgr2*t;
        if(t+tgr1+tgr2==T)
            cout<<s;
    }

    t=0;
    tgr4=8000/vgr3;
    a3=-vgr3/tgr4;
    for(i=1;i<=tgr4;i++)
    {
        t=t+dt;
        s=16000+vgr3*t+(1/2)*(a3)*t*t;
        if(t+tgr1+tgr2+tgr3==T)
            cout<<s;
    }


    return 0;
}


Although this seems reasonable to me I'd still like to recieve your opinion on it. It seems to be working. The big numbers are the reason becasue my units are meters and seconds.  
 


@polishprogrammer,

This is only a skim through. General comments are that you are using a mix of exact solutions (to get tgr1, vgr1 etc) to get the segment end points and stepping to get the intermediate results. Your only inputs are a1 and a2, which is correct. a3 would follow from everything else.

You are using a lot of "magic numbers", which make it tricky to follow with the large numbers involved because of the metre-second units.

You will be wrong because of integer division at several places. Some of your intermediate values are also wrong.


1
2
    tgr1=sqrt(20000/a1);
    vgr1=vi+a1*tgr1;

This is correct: t1 = sqrt( 2s1/a1 ) and v = u + at. However, it would be easier to follow if you defined a variable s1 = 10000 (to represent your initial distance in metres).


for(i=1; i<=tgr1; i++)
Sorry, but that just isn't going to work. i is just a counter; it is the time t you should be comparing with tgr1.
- This occurs in multiple places; I won't repeat the comments again.


s=si+vi*t+(1/2)*a1*t*t;
Corresponds to exact solution s = ut + (1/2)at2. However, it will be WRONG here in code because of integer division. Writing 1/2 in code has to give an int, so truncates to 0. Just write 0.5 instead.



1
2
    tgr2=-vgr1*sqrt(v*v+20000*a2);
    vgr2=vgr1+a2*tgr2;

No idea where the first formula comes from, but it is dimensionally wrong and impossible to see how tgr2 could be negative. Also, v hasn't been set. Better to find vgr2 first as
vgr2 = sqrt( vgr1*vgr1 + 2 * a2 * s2 );
with s2 = 5000. Then
tgr2 = ( vgr2 - vgr1 ) / a2;


s=10000+vgr1*t+(1/2)*a2*t*t;
would be correct, except that (1/2) -> 0 again, by integer division. Also, 10000 is a magic number.



1
2
        if(t+tgr1==T)
            cout<<s;

No idea what this is supposed to do. (Several similar like this).



1
2
    tgr3=1/vgr2;
    vgr3=vgr2;

In metres, "1" should actually be 1000, or, better still, s3.



s=15000+vgr2*t;
This is the exact solution and OK (but 15000 is another "magic number")



1
2
    tgr4=8000/vgr3;
    a3=-vgr3/tgr4;

OK, first corresponds to t = s / (0.5(u+v) ). But would be easier to see if you didn't have 8000 as a magic number. Second is correct.


s=16000+vgr3*t+(1/2)*(a3)*t*t;
Corresponds to "s=ut + (1/2)at2". Suffers from integer division again, as 1/2 -> 0 in code.



You are only outputting anything at a small number of points. I don't think that is what your assignment asked.
Last edited on
Topic archived. No new replies allowed.
Pages: 12