Programa

De Física Computacional
Ir para navegação Ir para pesquisar

Para usar os scripts, o arquivo deve ser salvo como "fput.c".

// Libraries

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <assert.h>


// Defines

#define PI 3.14159265358979323846


// Prototypes

double *zero_array(int);
double *initial_condition(double, int);
double acceleration(double *, double, double, double);
double velocity(double, double, double, double);
double position(double, double, double, double);


// Constants

const double k      = 1.0;
const double m      = 1.0;
const double alpha  = 0.25;

const double dt         = 0.01;
const double tmax       = 11000.0;
const int step          = 10;       // Number of iterations needed to save one "frame"
const double start_reg  = 9000.0;   // Time before start saving the data

const double length = 20.0;
const int N         = 32;


// Main

int main(){

    // Variables

    int i;
    int count = 0;
    double t = 0.0;
    double *pos, *vel, *acc;
    double acc_new = 0.0;


    // Output

    FILE *file;
    // char output[50];
    char filename[] = "../data/output.dat";


    // Generate inicial conditions for
    pos = initial_condition(length, N); // position
    vel = zero_array(N);                // velocity
    acc = zero_array(N);                // acceleration

    // Output file
    // sprintf(output, filename);
    // file = fopen(output, "w");
    file = fopen(filename, "w");


    // Time loop
    while (t < tmax){

        // Velocity verlet
        for (i=1; i<N; i++){
            pos[i] = position(pos[i], vel[i], acc[i], dt);
        }

        for (i=1; i<N; i++){
            acc_new = acceleration((pos+i), k, m, alpha);
            vel[i] = velocity(vel[i], acc[i], acc_new, dt);
            acc[i] = acc_new;
        }

        // Save to file
        if (t >= start_reg && count >= step){
            for (i=0; i<=N; i++) fprintf(file, "%f %f\n", length/N*i, pos[i]);
            fprintf(file, "\n\n");
            count = 0;
        }
        else count++;
        

        // Update the current time
        t += dt;

    }


    // Close the output file
    fclose(file);


    // Free the pointers
    free(pos);
    free(vel);
    free(acc);


    return 0;

}


// Functions

// Generate an array of zeros (double) with size N
double *zero_array(int N){
    assert(N>0);
    int i;
    double *pointer;

    // Calloc initializes every element with 0.0
    pointer = (double *)calloc(N, sizeof(double));

    if (pointer != NULL){
        return(pointer);
    }
    else {
        fprintf(stderr,"Error in routine zero_array\n");
        exit(8);
    }
}

// Generate an array with the initial condition determined by the FPUT original problem, N elements with x values ranged from 0 to length.
double *initial_condition(double length, int N){
    assert(N>0);
    int i;
    double *pointer;
    double step = length/N;

    pointer = (double *)calloc(N, sizeof(double));

    if (pointer != NULL){
        for (i=0; i<=N; ++i) *(pointer+i) = sin(PI*(step*i)/length);
        return(pointer);
    }
    else {
        fprintf(stderr,"Error in routine initial_condition\n");
        exit(8);
    }
}

// Velocity-Verlet method

// Updates the acceleration
double acceleration(double *pos, double k, double m, double alpha){
    return k/m * (pos[1] + pos[-1] - 2*pos[0]) * (1.0 + alpha * (pos[1] - pos[-1]));
}

// Updates the velocity
double velocity(double vel_old, double acc, double acc_new, double dt){
    return vel_old + 0.5*(acc+acc_new)*dt;
}

// Updates the position
double position(double pos_old, double vel, double acc, double dt){
    return pos_old + vel*dt + 0.5*acc*dt*dt;
}