/* introduciamo le strutture, ripassiamo l'I/O, le funzioni */ /* impariamo ad evitare gli effetti collaterali nell'uso di funzioni */ #include #include #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 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; }