1_pendolo1.c


/* introduciamo le strutture, ripassiamo l'I/O, le funzioni */
/* impariamo ad evitare gli effetti collaterali nell'uso di funzioni */

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

#define SUCCESSO 0

/* Notate che il dannato ; alla fine della prossima riga e' cruciale! */

struct configurazione {double x; double v;};


/* I PROTOTIPI */

/* m_ nelle righe sotto ci ricorda che si tratta di variabili mute, */
/* li' solo per memoria (potremmo non metterle nel prototipo, */
/* ma indicare solo il tipo) */

struct configurazione *oa_inizializza(double m_x0, double m_v0);
struct configurazione *eulero(double m_dt, double m_omega2, 
			      struct configurazione *m_p_x_e_v);
struct configurazione *eulero_cromer(double m_dt, double m_omega2, 
			      struct configurazione *m_p_x_e_v);

/* notate che energia() e' generica, */
/* mentre oa_forza() e' proprio per l'oscillatore armonico (da cui il nome) */

double energia(double m_omega2, struct configurazione *m_p_x_e_v);
double oa_forza(double m_omega2, double m_x);
double oa_energia_potenziale(double m_omega2, double m_x);
double my_read_double(char *m_messaggio_print);
long my_read_long(char *m_messaggio_print);

/*****************************************************************************/
int main(void)
{
  double  x0, v0;
  double dt, omega2, tempo_totale, energia0, energia1;
  long n_passi, algoritmo;

  long i;

  struct configurazione x_e_v;

  /* I # sono per far piacere a gnuplot, per esempio, o ad aiutarci */
  /* ad usare un filtro per eliminare le righe che non ci */
  /* serviranno nella grafica */

  printf("# Integrazione Oscillatore Armonico v1.1.1 5 ottobre 2002\n");

  /* queste my_read sono li' per evitarci un po' di codice... */

  tempo_totale = 
    my_read_double(
       "Inserire il tempo totale di integrazione (variabile reale double)");
  algoritmo = 
    my_read_long("Inserire 0 per Eulero, 1 per Eulero-Cromer");
  dt = my_read_double("Inserire dt (variabile reale double)");
  x0 = my_read_double("Inserire x0 (variabile reale double)");
  v0 = my_read_double("Inserire v0 (variabile reale double)");
  omega2 = my_read_double("Inserire omega2 (variabile reale double)");

  /* Il cast lo facciamo noi esplicitamente, per tenere */
  /* le cose sotto controllo!! */

  n_passi = (long)(tempo_totale/dt);

  printf("# dt = %g tempo_totale = %g omega2 = %g numero passi = %d\n",
	 dt, tempo_totale, omega2, n_passi);

  /* una funzione senza effetti collaterali. quel che cambia cambia con = */

  x_e_v = *oa_inizializza(x0, v0);

  printf("# Abbiamo scelto condizioni iniziali x0 = %g v0 = %g\n", 
	 x_e_v.x, x_e_v.v);

  energia0 = energia(omega2, &x_e_v);
  printf("# L'energia al tempo t = 0 vale %g\n", energia0);

  if(algoritmo==0){
    printf("# Usiamo l'algoritmo di Eulero\n");
    for(i=0; i<n_passi;i++){

      /* un'altra funzione senza effetti collaterali... */

      x_e_v = *eulero(dt, omega2, &x_e_v);
      energia1 = energia(omega2, &x_e_v);
      printf("%g %g %g %g\n", 
	     (double)i*dt, x_e_v.x, x_e_v.v,energia1-energia0);
    }
  }else if(algoritmo==1){
    printf("# Usiamo l'algoritmo di Eulero-Cromer\n");
    for(i=0; i<n_passi;i++){

      /* un'altra funzione senza effetti collaterali... */

      x_e_v = *eulero_cromer(dt, omega2, &x_e_v);
      energia1 = energia(omega2, &x_e_v);
      printf("%g %g %g %g\n", 
	     (double)i*dt, x_e_v.x, x_e_v.v,energia1-energia0);
    }
  }else{
    printf("# TUONI E FULMINI:");
    printf("L'algoritmo n. %ld non e' ancora stato implementato. Abort.\n",
	   algoritmo);
    exit(-9);
  }

  energia1 = energia(omega2, &x_e_v);
  printf("# L'energia al tempo t = %d vale %g\n", n_passi, energia1);

  return SUCCESSO;
}

/*****************************************************************************/
struct configurazione  *oa_inizializza(double x0, double v0)
{
  static struct configurazione p_x_e_v;
  p_x_e_v.x = x0;
  p_x_e_v.v = v0;
  return &p_x_e_v;
}

/*****************************************************************************/
struct configurazione *eulero(double dt, double omega2, 
			      struct configurazione *p_x_e_v_old)
{
  static struct configurazione x_e_v_new;

  /* che succede se omettete le prime parentesi nella riga sotto ?*/

  x_e_v_new.v = (*p_x_e_v_old).v + oa_forza(omega2, (*p_x_e_v_old).x) * dt;

  /* perche' qui usiamo -> e non . ? */

  x_e_v_new.x = p_x_e_v_old->x + p_x_e_v_old->v * dt;
  return &x_e_v_new;
}

/*****************************************************************************/
/* Qual'e' la differenza fra eulero ed eulero-cromer? */
struct configurazione *eulero_cromer(double dt, double omega2, 
			      struct configurazione *p_x_e_v_old)
{
  static struct configurazione x_e_v_new;
  x_e_v_new.v = (*p_x_e_v_old).v + oa_forza(omega2, (*p_x_e_v_old).x) * dt;
  x_e_v_new.x = p_x_e_v_old->x + x_e_v_new.v * dt;
  return &x_e_v_new;
}

/*****************************************************************************/
double energia(double omega2, struct configurazione *p_x_e_v)
{

/* Calcoliamo in realta' 2 E / m */

  double l_energia;
  l_energia = (*p_x_e_v).v * (*p_x_e_v).v 
    + oa_energia_potenziale(omega2, (*p_x_e_v).x);
  return l_energia;
}

/*****************************************************************************/
double oa_forza(double omega2, double x)
{
  return - omega2 * x;
}

/*****************************************************************************/
double oa_energia_potenziale(double omega2, double x)
{
  return omega2 * x * x;
}

/*****************************************************************************/
long my_read_long(char *messaggio_print)
{
  long parola_letta;

  printf("# %s\n",messaggio_print); fflush(stdout);
  scanf("%ld",&parola_letta);

  return parola_letta;
}

/*****************************************************************************/
double my_read_double(char *messaggio_print)
{
  double parola_letta;

  printf("# %s\n",messaggio_print); fflush(stdout);
  scanf("%lg", &parola_letta);

  return parola_letta;
}

Generated by GNU enscript 1.6.1.