#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; // Raumintervall [x_0,x_1] double x_0 = 0.0; double x_1 = 10.0; // Raum- und Zeitschritt. Aus diesen Größen wird weiter unten die // Anzahl der Schritte berechnet. double dx = 0.1; double dt = 0.1; // Framerate - So viele Bilder werden pro simulierter Sekunde ausgegeben int fps = 20; // Die Funktion startwert(i) legt die Anfangsbedingung fest, es gilt // also u(x_i,t=0) = startwert(i). double startwert(int i) { // Aufgabe a) // double linker_wert = 0.8; // double rechter_wert = 0.2; // Aufgabe b) double linker_wert = 0.2; double rechter_wert = 0.8; if ( x_0 + i*dx < (x_1 - x_0)/2.0 ) { return linker_wert; } return rechter_wert; } int main () { // Die folgenden beiden Strings werden für den Namen der // Ausgabedatei und für die Titelzeile der ausgegebenen Graphen // reserviert. char fname[25]; 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 Funktionswerte u(x_i) an den Stützszellen werden in einem // Array gespeichert. Gespeichert wird jeweils der aktuelle Wert (in // u) und derjenige vom vorangegangenen Zeitschritt (in u_alt). double u[x_steps + 1]; double u_alt[x_steps + 1]; // Berechne, nach wie vielen Zeitschritten ein Bild ausgegeben // werden soll. int steps_pro_frame = round(1.0 / fps / dt); if (steps_pro_frame == 0) { steps_pro_frame = 1; } int i = 0; // Indiziert den Ort int j = 0; // Indiziert die Zeit int x_plus = 0; int x_minus = 0; // Multiplikation ist relativ teuer, sollte deshalb nicht öfter als // nötig berechnet werden! double dt_durch_dx = dt / dx; // Initialisiere das Gitter (Anfangsbedingung) for (i = 0; i < x_steps; i++) { u[i] = startwert(i); } // Durchlaufe alle Zeitschritte von t_0 bis t_1. for ( j = 0; j <= t_steps; j++ ) { //--- Ausgabe --------------------------------------------- if ( j % steps_pro_frame == 0) { metafl("PNG"); filmod("DELETE"); scrmod("REVERSE"); // Die ausgegebenen Bilder sollen Burgers_frame1.png, // Burgers_frame2.png usw, heißen sprintf(fname, "Burgers_frame%d.png", round(j / steps_pro_frame) ); setfil(fname); disini(); texmod("ON"); // Lege die Überschrift des Graphen fest sprintf(titel, "%d Stuetzstellen, $t=%f$",x_steps + 1, t_0 + j * dt); titlin(titel, 4); graf(x_0, x_1, x_0, (x_1 - x_0)/10, -3.0, 3.0, -3.0, 1.0); title(); // Plotte die Funktionswerte hsymbl(5); for (i = 0; i <= x_steps; i++ ) { rlsymb(21,x_0 + i * dx, u[i]); } disfin(); } //--- Ausgabe Ende ------------------------------------------- // Kopiere den aktuellen Zustand. Daraus wird dann der neue // Zustand berechnet. for ( i = 0; i <= x_steps; i++ ) { u_alt[i] = u[i]; } for (i = 1; i <= x_steps-1; i++) { x_plus = i + 1; x_minus = i - 1; // Jetzt erfolgt die Zeitentwicklung. Wie in der Vorlesung // besprochen, wird das Upwind-Verfahren genutzt um für dt < // dt/|c| die Stabilität zu sichern. // Upwind-Verfahren // ================ // Advektionssgeschw. u | Örtlicher Differenzenquotient // | // < 0 | forward // > 0 | backward if ( u_alt[i] > 0 ) { u[i] = u_alt[i] - dt_durch_dx * u_alt[i] * (u_alt[i] - u_alt[x_minus]); } else { u[i] = u_alt[i] - dt_durch_dx * u_alt[i] * (u_alt[x_plus] - u_alt[i]); } } u[0] = startwert(0); u[x_steps] = startwert(x_steps); } return 1; }