/* Das Programm integriert die 1D Wellengleichung und gibt die Ergebnisse in Form von PNG-Grafiken aus, aus denen sich z.B. mit Programmen wie ffmpeg kleine Filme erzeugen lassen. Die Anzahl der ausgegebenen Bilder läßt sich über die Variable "fps" steuern (siehe unten). */ #include #include // Die folgende Zeile muss evtl. an Eure lokale Dislin-Installation // angepasst werden. #include "/usr/local/dislin/dislin.h" #define round(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5)) // Zeitintervall [t_0,t_0] double t_0 = 0.0; double t_1 = 20.0; // Raumbereich [x_0,x_1] double x_0 = 0.0; double x_1 = 1.0; // Raum- und Zeitschritt. Aus diesen Größen wird weiter unten die // Anzahl der Schritte berechnet. double dx = 0.0025; double dt = 0.025; // Die Ausbreitungsgeschwindigkeit double c = 0.003125; // fps ist die Anzahl der Bilder, die pro simulierter Sekunde ausgegeben werden sollen int fps = 20; // Die Funktionen startwert und startableitung werden zu Beginn des // Programms verwendet, um die Anfangsbedingung festzulegen. // In der Notation der Vorlesung entsprechen sie f(x) und g(x). double startwert(int i) { int n = 3; double x = x_0 + i * dx; return sin(n * M_PI / (x_1 - x_0) * (x_0 + i*dx)); } double startableitung(int i) { return 0.0; } int main () { // Die Variablen fname und titel werden für die Ausgabe mit Dislin // benötigt (siehe unten). char fname[80]; char titel[80]; // Die Anzahl der räumlichen und zeitlichen Iterationsschritte wird // aus der Größe der entsprechenden Intervalle und den Schrittweiten // berechnet. int x_steps = round( (x_1 - x_0) / dx); int t_steps = round( (t_1 - t_0) / dt); // Die zweifache Zeitableitung wird über den zentralen // Differenzenquotienten approximiert. Das heißt, dass jeweils die // Funktionswerte von drei Zeitpunkten benötigt werden: Der aktuelle // Funktionswert wird aus den Funktionswerten der beiden // vorangegangenen Zeitpunkte ermittelt. double u[x_steps + 1]; double u_alt[x_steps + 1]; double u_aelter[x_steps + 1]; // Je nach Wahl der globalen Variablen fps und dt wird die Zahl der // zeitlichen Iterationen berechnet, die zwischen zwei Ausgaben // durchgeführt werden sollen. int steps_pro_frame = round(1.0 / fps / dt); int i = 0; // i ist der x-Index int k = 0; // k ist der Zeitindex // Division und Potenzierung ist relativ teuer, sollte deshalb nicht // öfter als nötig berechnet werden! double alpha_quadrat = pow(c * dt / dx, 2); // Das Feld wird entsprechend der Anfangsbedingung mit startwert() // initialisiert. for (i = 0; i <= x_steps; i++) { u_aelter[i] = startwert(i); u[i] = u_aelter[i]; } int x_minus = 0; int x_plus = 0; for ( k = 0; k <= t_steps; k++ ) { // Die Raumindizes gehen von 1 bis x_steps-1, da feste // Randbedingungen erfüllt sein sollen for ( i = 1; i <= x_steps-1; i++ ) { x_minus = i-1; x_plus = i+1; // Im ersten Zeitschritt müssen die u_i,j aus Zeitschritt n=-1 // mit Hilfe der ersten Zeitableitung (Anfangsbedingung g(x)) // konstruiert werden. if ( k == 0 ) { u_alt[i] = dt * startableitung(i) + (1.0 - 2.0 * alpha_quadrat) * u_aelter[i] + 0.5 * alpha_quadrat * (u_aelter[x_minus] + u_aelter[x_plus]); } else { u[i] = -u_aelter[i] + 2.0 * (1.0-2.0*alpha_quadrat)*u_alt[i] + alpha_quadrat * (u_alt[x_plus] + u_alt[x_minus]); } } if (k != 0) { for (i = 0; i <= x_steps-1; i++) { u_aelter[i] = u_alt[i]; u_alt[i] = u[i]; } } // ---{ Ausgabe mit Dislin }------------------------- if ( k % steps_pro_frame == 0) { metafl("PNG"); filmod("DELETE"); scrmod("REVERSE"); sprintf(fname, "1Dwellengl_frame%d.png", round(k / steps_pro_frame) ); setfil(fname); disini(); texmod("ON"); sprintf(titel, "%d Stuetzstellen, $t=%f$",x_steps + 1, t_0 + (k + 1) * dt); titlin(titel, 4); graf(x_0, x_1, x_0, (x_1 - x_0)/10.0, -2.0, 2.0, -2.0, 1.0); title(); hsymbl(6); for (i = 0; i<=x_steps; i++) { rlsymb(21, x_0 + i*dx, u[i]); } disfin(); } //----------------------------------------------------- } return 1; }