Search code examples
cverlet-integration

Assigning value to C array with iterative formula


Context

I would like to simulate the trajectory of a particle in an electrical field. I want its position, velocity and acceleration at each time step. Each of these variables will be stored in an array so I can write it on a file and plot it later. My problem is that I can't modify the values of the arrays, when I print I only get the initial values repeated over the whole arrays.

My code

int main(){
    ////// Some variable definitions for the physics //////
    const float m_Ca  = 40*1.66053886e-27;
    const float Q_Ca  = 1.60217646e-19; 
    const float U_dc  = 1000;
    const float z0_2  = 20*20; // mm
    const float w_z_2 = 2*Q_Ca*U_dc/m_Ca/z0_2;
    
    // time step
    const float dt = 5e-9;
    const float dt1 = 0.5*5e-9;
    // simulation number of steps
    const int i_free_fly = round(10/sqrtf(w_z_2)/dt);
    ///////////////////////////////////////////////////////
    
    // allocating position, velocity and acceleration arrays
    float* r_z = (float*)malloc(i_free_fly*sizeof(float));
    float* v_z = (float*)malloc(i_free_fly*sizeof(float));
    float* a_z = (float*)malloc(i_free_fly*sizeof(float));
    // initializing arrays
    r_z[0] = 1;
    v_z[0] = 0;
    a_z[0] = 0;
    
    // Velocity-Verlet algorithm
    // here I calculate the next steps position, velocity and acceleration
    // for the current time step i I need info from the previous time step i-1
    for (int i=1;i<i_free_fly;++i){
        // update position
        r_z[i] = r_z[i-1] + v_z[i-1]*dt + 0.5*a_z[i-1]*dt1*dt1;
        // update acceleration
        a_z[i] = m_Ca*w_z_2*r_z[i];
        // update velocity
        v_z[i] = v_z[i-1] + dt1 * (a_z[i-1] + a_z[i]);
    }

    return 0;
}

My problem

When printing r_z, v_z and a_z I get 1, 0, 0 and zero anytime. I do this to print the arrays.

for (int i=1;i<150;++i){    
    printf("%f\n",r_z[i]);
    printf("%f\n",v_z[i]);
    printf("%f\n",a_z[i]);
}

I'm new to C and pointers are still something weird to me. I don't know if using them is the proper way to do this but looking on internet I thought it was the best way to achieve my purpose but I may have missed something.


Solution

  • When working with very small numbers in C like this, you can't trust the %f format operator for printf. Instead, use something like %e to give you an exponent output which then won't be rounded:

    for (int i=1;i<150;++i){    
        printf("%e\n",r_z[i]);
        printf("%e\n",v_z[i]);
        printf("%e\n",a_z[i]);
    }
    

    With a modified version we can see the acceleration as constant (to begin with) and the velocity increasing:

        for( int i = 0; i < 156; i++ ) {
            printf("r_z: %e a_z: %e v_z: %e\n", r_z[i], a_z[i], v_z[i]);
        }
    
    $ ./a.out 
    r_z: 1.000000e+00 a_z: 0.000000e+00 v_z: 0.000000e+00
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.002721e-27
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.008162e-27
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.001360e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.401904e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 1.802449e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.202993e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 2.603537e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.004081e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.404625e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 3.805169e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 4.205713e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 4.606257e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.006802e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.407346e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 5.807890e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.208434e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 6.608978e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 7.009522e-26
    r_z: 1.000000e+00 a_z: 8.010882e-19 v_z: 7.410066e-26
    

    Or you could choose to use the %g type field instead so printf will decide whether to use an exponent representation or not depending on the value.