4

This is my code for attempting a while Loop to model a pendulum swing, however the values produced don't seem to help me:

#include <stdio.h>
#include <math.h>
#define PI 3.14159265

main()
{
    float theta = 0;   // initial value for angle
    float omega = 0.2; // initial value for angular speed
    float time = 0;    // initial time
    float dt = 0.01;   // time step

    while (theta < 2 * PI && -2*PI) {
        time = time + dt;
        theta = theta + omega*dt;

        printf("theta=%i, omega=%i, time=%i, and dt=%i\n", theta, omega, time, dt);
    }
    system("PAUSE");
}

How can I modify this to be more helpful? The while condition I have to use is that it should stop when the pendulum has made one revelation either forwards or backwards (-2PI or 2PI). I need to use the formula 'omega=omega-(g/l)dtsin(theta)' and NOT make the assumption that theta approximately equals sin(theta).

Josh Mulkeen
  • 59
  • 1
  • 7
  • 4
    Because this is not a pendulum that you are modelling. What is the equation of motion for a pendulum? – Iharob Al Asimi Jan 15 '16 at 21:16
  • T=2PI*sqrt(l/g) and I'm trying to follow a manual that isn't much help haha. – Josh Mulkeen Jan 15 '16 at 21:29
  • 1
    Please don't correct the question in response, unless it was to clarify the question. Rolled back. – Weather Vane Jan 15 '16 at 21:33
  • 1
    You should use "int main (void)" and "return 0" at the end of main. Moreover you are trying to print float values with %i format specifiers... you should use %f – Claudio Cortese Jan 15 '16 at 21:35
  • 2
    Please use the pre-defined and much more exact constant `M_PI` instead of defining your own less precise value of `Pi` (or use at least 17 correct digits). – Lutz Lehmann Jan 15 '16 at 21:36
  • 3
    ... and use `double` unless there is a good reason for `float` (such as a graphics library, or embedded processor limitation). Do you know that `0.01` is evaluated as `double` by default? – Weather Vane Jan 15 '16 at 21:36
  • @WeatherVane definitly double for physic simulation ;) – terence hill Jan 15 '16 at 21:39
  • Also, this is not a physics simulation. A simulation would be to solve the equation of motion with some numerical method. This is not a real physical system because this approximation is good for small displacements from the equilibrium position only. But it can accept any initial displacement in principle. – Iharob Al Asimi Jan 15 '16 at 21:41
  • @LutzL Note: pre-defined `M_PI` does not exist in standard C. Agree, no reason to not use a more precise value like 3.1415926535897932384626433832795. – chux - Reinstate Monica Jan 15 '16 at 22:31
  • Strange, I never had to use `#define _USE_MATH_DEFINES` for `math.h`. But that might be a lack of variety. And yes, I found that `M_PI` is non-standard, but often present. – Lutz Lehmann Jan 15 '16 at 23:02

5 Answers5

4
  1. while(theta <2*PI&&-2*PI)

    In c if we want to combine multiple expressions we can combine them using logical operators as

    while((theta < 2 * PI) && (theta > -2 * PI))  
    

    PS- I am no physics expert. Change conditions as per your requirement

rootkea
  • 1,474
  • 2
  • 12
  • 32
4

There are some problem in this code :

  1. According to the standard you shouldn't use

    main()
    

    But either

    1. int main()
    2. int main(void)
    3. int main(int argc, char *argv[])

    Also don't forget

    return 0;
    

    Sample program :

    #include <stdio.h>
    
    int main(void) {       
        /* Do stuff */        
        return 0;    
    }
    

    If you wish to read more information about that, click here.

  2. As LutzL pointed out you should use M_PI instead of your definition of PI. Just #include <math.h>

    That's how you would print the value for example :

    printf("\nValue of M_PI is %f\n\n", M_PI);
    

    Read more here.

  3. As pointed out by rootkea :

    In c if we want to combine multiple expressions we can combine them using logical operators as

    while((theta < 2 * PI) && (theta > -2 * PI))

  4. If you want greater precision (I think that this is the case) you should use double instead of float.

  5. You are trying to print float variables with the "%i" format specifier. That's wrong, "%i" is used to print int signed integer and using the wrong specifier invokes undefined behavior. You should use "%f" to print float or double signed decimal.

Have a read about printf format specifiers here.

Community
  • 1
  • 1
Claudio Cortese
  • 1,372
  • 2
  • 10
  • 21
  • 1
    Thank you, Claudio! I realised where I'd gone wrong now and since changed this. However I'm struggling where to place the return function and whether to add an approximate number of PI after '#define M_PI'. – Josh Mulkeen Jan 15 '16 at 22:21
  • You are welcome. I have modified my question to provide you more details. Hope that this will help you! – Claudio Cortese Jan 15 '16 at 22:29
  • 1
    Concerning `M_PI`, see [comment](http://stackoverflow.com/questions/34819949/modelling-a-pendulum-in-c#comment57384515_34819949) – chux - Reinstate Monica Jan 15 '16 at 22:33
  • 2
    What standard says to use `int main()`? C11 lists: `int main(void)` and `int main(int argc, char *argv[])` and other implementation-defined` ones – chux - Reinstate Monica Jan 15 '16 at 22:36
  • 1
    Claudio, you should read about markdown to improve the formatting of your answers. – Iharob Al Asimi Jan 15 '16 at 22:43
  • @chux In early C, the void keyword and associated type did not exist. When programmers wanted to write procedures ("functions that have a side effect, but do not return anything"), they simulated it using this feature. They wrote a function without any keyword specifying the return type. They allowed the function to execute to it last statement without returning a value (or alternatively, they used return; to exit from the middle without supplying a value) [...] http://stackoverflow.com/questions/19583480/which-is-the-diferrence-between-main-and-int-main-and-int-mainvoid – Claudio Cortese Jan 15 '16 at 22:44
  • @Claudio Cortese Your comment is true but does not take away from the weakness in OP's comment about "the standard".. Without an attribution as to what standard, the current one C11 should be assumed. Even the preceding 17 year old C99 has `void`. Asserting "the standard" may refer to the 25+ year old C89/90 standard is tenuous. – chux - Reinstate Monica Jan 15 '16 at 23:33
  • 1
    @chux Since 1999, "An empty list in a function declarator that is part of a definition of that function specifies that the function has no parameters" [C99 6.7.5.3 (14) and C11 6.7.6.3(14)] – Claudio Cortese Jan 15 '16 at 23:51
  • @Claudio Cortese LSNED – chux - Reinstate Monica Jan 16 '16 at 05:19
  • @JoshMulkeen You don't have to define M_PI ,as it's already in your program when including math.h – Claudio Cortese Jan 16 '16 at 10:47
2

The angle equation that you use is not right. According to your expression it changes linearly with time, although the equation is harmonic:

        θ = θ0cos(ωt)

where ω = g/L, L is the length of the pendulum and g the acceleration due to gravity.

Where thetaMax is the max deflection angle, g is gravity const, L is length of pendulum and t is time. So, you want to know thetaMaxfrom energy conservation law, for example.

Alrught, let's revise energy conservation law here:

As you know Potential energy at max deflection equals Kinetic energy at the lowest point of the pendulum path:

KE = ПE
m*g*L*sin(thetaMax) = m*sqr(omega)*sqr(L)/2

Approximately, for small angles:

m*g*L*thetaMax = m*sqr(omega)*sqr(L)/2
thetaMax = sqr(omega)*L/(2*g)

that is it. Here is code that calculates this type of oscillatory motion. All absolute values:

#include <stdio.h>
#include <math.h>
#define PI 3.14159265
#define L 1 //length of the pendulum
#define g 9.8  //gravity const

int main()
{
    double theta = 0; // initial value for angle
    double omega = 0.2; // initial value for angular speed
    double time = 0; // initial time
    double dt = 0.01; // time step

    double thetaMax = omega*omega*L/(2*g);

    while (theta < thetaMax) {
        time = time + dt;
        theta = thetaMax * sin(omega*time);
        printf("theta=%f, omega=%f, time=%f, and thetaMax=%f\n", theta, omega, time, thetaMax);
     }
    return 0;
}

It is going to calculate these parameters infinitely, so just limit theta in the condition of the while-loop to a desired angle of deflection.

Petr Stepanov
  • 71
  • 2
  • 9
  • Thank you Petr, I will now add this into my code, I am a beginner with about a weeks worth experience of code – Josh Mulkeen Jan 15 '16 at 21:32
  • Not necessarily *sin*. Not that *sin(0)* is 0 that wouldn't be the appropriate initial condition, would it? – Iharob Al Asimi Jan 15 '16 at 21:34
  • No problem! Let me know if you're stuck on thetaMax. I can help you to derive it. – Petr Stepanov Jan 15 '16 at 21:34
  • @iharob, needs to be harmonic function, either one, just fix the phase if needed – Petr Stepanov Jan 15 '16 at 21:35
  • @PetrStepanove depends on the initial conditions, assuming that the pendulum is at rest initialize it's *cos*. Although the thing is that it should be sinusoidal. – Iharob Al Asimi Jan 15 '16 at 21:35
  • @iharob Agree. That is why you can fix it adding a constant phase inside the periodic function (no matter which one you use). Remember Sin(phi + Pi/2) = -Cos(Phi). – Petr Stepanov Jan 15 '16 at 21:38
  • @iharob Okay I have added this into my code however there's an error as I haven't defined ThetaMax, do I just add in '#define thetamax...' at the start then replace the ellipsis with the max value theta can be? – Josh Mulkeen Jan 15 '16 at 22:11
  • Don't see it as the max value, but instead the initial angle. The angle formed with the vertical when you release the pendulum. And not necessarily, you can just define a `double theta0 = 2.0` or whatever, remember that angles must be specified in radians. And that *x* and *y* coordinates should be calculated from (*L*, *theta*). – Iharob Al Asimi Jan 15 '16 at 22:38
  • @iharob Changed my code and now the values are not updating. – Josh Mulkeen Jan 15 '16 at 22:49
  • There's a mistake in your expression of omega. I suggest replacing it by omega = sqrt(g/L). – cromod Feb 07 '16 at 17:10
1

The equation for a (simple, point mass on string) physical pendulum is

θ'' + k·sin(θ) = 0

where the constant:

k = g / L

contains gravitational g and length L.

θ is the angle measured from the position of rest, which of course is pointing down, that is, in a Cartesian coordinate system with the usual angle convention, at -90°. Thus the pendulum oscillations translate to theta oscillations around zero.

You could solve that (conservative) differential equation using symplectic Euler or Verlet/Leapfrog. Symplectic Euler in one variant has the loop (using ω=θ', that is, (θ',ω')=(ω, -k·sin(θ))

for(...) {
    omega -= k*sin(theta) * dt;
    theta  += omega * dt;
    t += dt;
    printf(...);
}
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • 1
    Because `omega' = theta'' = -k*sin(theta)`. This gives the required negative feed-back so that the pendulum eventually swings back. – Lutz Lehmann Jan 15 '16 at 21:42
  • Incorrect!!!!! Completly wrong, do you know what the *sin* function is? Also, note that with *sin* at *t = 0* the pendulum would be in the vertical position. – Iharob Al Asimi Jan 15 '16 at 21:43
  • 1
    @iharob: Note that there is no explicit `t` inside the sine function. And please look up the usual definitions of the physical pendulum. Obviously, `theta` is the angle of the deviation from the position of rest, which is at -90° in a Cartesian coordinate system. – Lutz Lehmann Jan 15 '16 at 21:48
  • Trust me, I do understand what a pendulum is. And certainly this is not a [*physical pendulum*](http://hyperphysics.phy-astr.gsu.edu/hbase/pendp.html). Please don't try to teach something that you don't deeply understand. – Iharob Al Asimi Jan 15 '16 at 22:45
  • 2
    @iharob: You need to read more carefully, the web page gives the tangential part of the force as `m*g*sin(theta)` in concordance with my first equation and then adds that the small angle **approximation** uses `sin(theta) ≈ theta` to get the *mathematical* pendulum resp. harmonic oscillator. – Lutz Lehmann Jan 15 '16 at 23:06
  • I have to use the formula 'omega=omega-(g/l)*dt*sin(theta)' as my manual states but I have to use a while loop, not a for loop. – Josh Mulkeen Jan 15 '16 at 23:12
  • 1
    @JoshMulkeen: This is essentially the same operation, just resolving `omega -= (g/l)*sin(theta)*dt` into the longer form. `for` and `while` are essentially equivalent (up to more cases for code optimizations in the `for` case), I just had to put some indication of a loop head. – Lutz Lehmann Jan 15 '16 at 23:17
  • @LutzL What web page? What are you talking about? Certainly a *simple pendulum* is not the same as a *physical pendulum* whether you do some approximation to solve both for small angles is a different thing. Also, there is a very simple explanation for the `-` sign if you want it to be there, but it certainly has nothing to do with a restoring force. The relation between the equation of motion and the force is not that simple, I think you are confused about that.. – Iharob Al Asimi Jan 15 '16 at 23:35
  • @iharob: **Your** given link. All physical pendulums reduce to the equation given at the top, the only variation is the composition of the constant `k`. And of course, the motion along a constraint curved surface is always a little more complicated than free motion in a potential field, as one easily finds when deriving the equations for a double pendulum. – Lutz Lehmann Jan 15 '16 at 23:45
  • @LutzL I am not discussing that. I would like to hear about *composition of the constant k*. But not here, please be kind and continue this discusion iharob@gmail.com in an appropriate chat. – Iharob Al Asimi Jan 15 '16 at 23:47
  • 1
    @simplicisveritatis: There is no friction term, or dampening, that is why I wrote that this is a *conservative` equation that can be solved using symplectic solvers. – Lutz Lehmann Jan 15 '16 at 23:51
  • 2
    @iharob: You can read off the composition of the constant directly from the web page. For the solid body pendulum you get `k=m*g*L/I`, where `L` is the length to center of mass and `I` is the moment of inertia. For the string pendulum, `I=m*L²` resulting in the shorter `k=g/L`. – Lutz Lehmann Jan 15 '16 at 23:54
  • @LutzL Now your answer is worse. That constant is what you call *omega* in your equation. Where did you learn physics? – Iharob Al Asimi Jan 15 '16 at 23:56
  • 1
    @iharob: Please take a break and come back tomorrow. Nowhere did I use omega as a constant, it is always the angular velocity. – Lutz Lehmann Jan 16 '16 at 00:02
  • `-k * sin(theta) * dt` is terribly wrong, that's all no more chating with you as it's a waste of time. – Iharob Al Asimi Jan 16 '16 at 00:04
1

The idea of modelling, in simple terms, involves finding a mathematical representation of a physical phenomenon. In other words you need to "find" an equation that represents all the observable properties of the object in context, in your case a pendulum1.

All you need to describe a pendulum is its equation of motion. To find it you firstly try to qualify the motion, by observing it:

If you try to displace it (many times with a very small angle) from its equilibrium point, you will mostly observe few swings, along the same path, where its amplitude decreases and it is brought back to its stable equilibrium, as if by some kind of restoring force, in other words the pendulum performs regular and repeating motion, called periodic motion

Thus, you are looking for a mathematical function that can represent a periodic motion, as it turns out a great candidate for this role are the trigonometric functions: sin and cos, that have the needed property i.e. repeat themselves with a period T.

To find and quantify this restoring force you use Newton's Second Law, where after you express everything in terms of the very small angle theta << 1 (that allows using of the small-angle approximation: sin(theta) = theta) of displacement theta, you get the wanted equation of motion, which is represented by the following differential equation:

enter image description here

with a great surprise (and to the first order of approximation), when you solve the above equation you find:

enter image description here

which approximately2 matches the predictions from your observations (with some random error (standard deviation), preferably not systematic), i.e. the motion of the pendulum is described by the cosine function, it has periodic motion with an amplitude equal to the initial displacement and a period equal to:

enter image description here

and here is the catch,

the above equation for theta describes a pendulum that does not lose energy and its values repeat infinitely and that is why the loop in your program is an infinite loop harmonically oscillating pun intended with the same values!

If you want to observe a motion that slowly stops you need to add an additional damping force that will slowly subtract energy from the system. This damping force is represented by the following additional term in the equation of motion:

enter image description here

that again, can be expressed in terms of the angle theta. Now, when you solve the equation of motion, the amplitude gets multiplied by:

enter image description here

where b is the damping constant from which it depends how fast the motion will stop.

As a consequence of the above,

if you want to see something similar to the real pendulum you need to include this last exponential to your equation.

To do this just follow the great explanation offered by @Petr Stepanov, modifying thetaMax to include the above exponent.

#include <stdio.h>
#include <math.h>
#define PI 3.14159
#define E 2.71828      // Euler's number
#define L 1            // length of the pendulum
#define g  9.80665     // gravity const

int main() {

    double theta = 0.0; // initial value for angle
    double omega = 0.2; // initial value for angular speed
    double time = 0.0;  // initial time
    double dt = 0.01;   // time step
    double b = 0.5;     // modified damping constant

    double thetaMax = omega * omega * L / (2 * g);

    while (theta < thetaMax) {
        time = time + dt;
        theta = thetaMax * ldexp(E, (-b) * time) * sin(omega * time);

        printf("Deflection angle=%f, Angular frequency=%f, Time=%f\n", theta, omega, time);
    }

    return 0;
}

1. An object with mass m, hung on a fixed point with a non-elastic, "massless" thread with length l , that allows it to swing freely in a gravitational field, quantified by the gravitational acceleration constant g.

2. It should be noted that: "all models are wrong; the practical question is how wrong do they have to be to not be useful"

Ziezi
  • 6,375
  • 3
  • 39
  • 49
  • 1
    The cosine solution applies to the small angle approximation where `sinθ` got replaced by `θ`. The original equation does not have an easily expressible solution. And even the period of the original equation is only accessible as a series expansion. (no downvote from me) – Lutz Lehmann Jan 15 '16 at 23:58
  • *whit a great surprise, when you solve the above equation you find:* NO!!!! Where did you learn that? That solution is for small angles approximation. – Iharob Al Asimi Jan 15 '16 at 23:58
  • @iharob off course both of you guys are right! It was directed more towards a conceptual and _"ideological"_ explanation. I've edited it now. Thanks for the remarks! – Ziezi Jan 16 '16 at 00:05
  • Now *which matches the predictions from your observations* not entirely true. Have you been to a lab testing these *predictions* for large angles? Doesn't the period change? – Iharob Al Asimi Jan 16 '16 at 00:06
  • @iharob Well, to be honest with you I have been in a lab testing it :), when I was first year at the university and off course that your observations are within some error, you are right :) – Ziezi Jan 16 '16 at 00:20
  • @iharob did I covered all the remarks in your comments? – Ziezi Jan 16 '16 at 00:28
  • @simplicisveritatis Thanks for the message but the while condition I have to use is that it should stop when the pendulum has made one revelation either forwards or backwards (-2PI or 2PI). I need to use the formula 'omega=omega-(g/l)*dt*sin(theta)' and NOT make the assumption that theta approximately equals sin(theta). Then it goes on to say "Add relevant lines to your program to take account of the change in omega due to acceleration. You will need to change back to a for loop ". Thank you for your time. – Josh Mulkeen Jan 16 '16 at 14:42
  • @Josh Mulkeen well with that new additional information the things change a bit, however I hope you find something helpful within my answer. – Ziezi Jan 16 '16 at 15:00
  • @simplicisveritatis I definitely do find it helpful and I am grateful, however the physics used looks too complicated for my usage. – Josh Mulkeen Jan 16 '16 at 15:27
  • @Josh Mulkeen I was rightfully pushed to add some additional comments that will make sense to you in near future, I hope. I just felt the need to provide a answer that uses some theory related to the code, so that the code makes more sense. :) – Ziezi Jan 16 '16 at 15:31