Ćwiczenie 1 Rozwiązanie równań różniczkowych zwyczajnych
Transkrypt
Ćwiczenie 1 Rozwiązanie równań różniczkowych zwyczajnych
Ćwiczenie 1 Rozwiązanie równań różniczkowych zwyczajnych metodami numerycznymi 28 października 2004 roku 1 Cel ćwiczenia Celem ćwiczenia jest zapoznanie się z metodami rozwiązywania numerycznego (przybliżonego) równań różniczkowych zwyczajnych, a w szczególności praktyczne zastosowanie do tego celu metody Runge-Kutty rzędu pierwszego, drugiego i czwartego. 2 Wprowadzenie (Część teoretyczna znajduje się w pliku teoria.pdf lub jest dostępna w formie papierowej u prowadzącego ćwiczenia) 3 Szczegółowy plan przeprowadzenia ćwiczenia Zadaniem studenta jest napisanie programu do numerycznego rozwiązywania następujących równań różniczkowych: y0 = y (1) y0 = xy (2) 0 y = 2x √ y0 = 2 y (3) (4) przy użyciu wymienionych we wstępie teoretycznym metod Runge-Kutta. Językiem programowania jest C++, a praca będzie realizowana w środowisku Microsoft Visual Studio 6.0 (MSV) w odpowiednio przygotowanym dla studenta interfejsie. Wymaga się podstawowej znajomości języka C++, a w szczególności opanowanie: • deklaracji zmiennych i tablic • indeksacji tablic • tablice dynamiczne (komenda ”new”) • tworzenie funkcji • konstrukcji ”for” • konstrukcji ”if - else” Funkcjonujący program powinien być przetestowany ze względu na dokładność obliczeń dla różnych konfiguracji (krok całkowania, obszar obliczeniowy) - rozwiązanie dokładne oraz błąd rozwiązania numerycznego jest wyliczany automatycznie w proponowanym interfejsie. Wnioski, spostrzeżenia oraz algorytm R-K winny być zawarte w sprawozdaniu. Rysunek 1: Okno główne MVS 4 Interfejs użytkownika Interfejs służy do wprowadzania parametrów wejściowych oraz prezentacji wyników obliczeń w formie graficznej i stabularyzowanej, obie formy zawierają obok rozwiązania numerycznego (proponowanego przez studenta) rozwiązanie dokładne oraz błąd. Student otrzymuje kod źródłowy interfejsu w którym to, w przeznaczonej do tego celu funkcji o nazwie ”Obliczenia()”, wpisuje algorytm Runge-Kutty. Aplikacja przekazuje poprzez argumenty funkcji ”Obliczenia()” parametry potrzebne do realizacji kodu odpowiedzialnego za całkowanie numeryczne, a w zamian oczekuje tablicy zawierającej rozwiązanie. Poniżej znajduje się dokładny plan działania pozwalający na szybkie poznanie omówionej struktury. Po przeprowadzeniu czynności wstępnych podanych przez prowadzącego i załadowaniu projektu ”Rozwiazanie.dsw” student zobaczy okno główne MVS z trzema podoknami jak na rysunku 1 a w nich: 1. okno z trzema zakładkami, z których najważniejsza jest zakładka ”ClassView” zawierająca listę wszystkich obiektów, funkcji. Student może dzięki niej szybko poruszać się w kodzie. Do zlokalizowania miejsca w którym należy wpisać algorytm proszę dwa razy kliknąć na ”Obliczenia(int m nNumerRownania, int ...” (podświetlone na jasno zielony) Rysunek 2: Okno interfejsu użytkownika 2. okno zawiera kod. Jeśli student wybierze klasę, lub funkcje z ”ClassView” to w tym miejscu zostanie wyświetlona definicja tego obiektu; i tak dwukrotne kliknięcie na ”Obliczenia(int m nNumerRownania, int ...” pokaże tą funkcję (jak na rysunku 1, podświetlenie fioletowe) 3. okno wielo-zakładkowe w których znaleźć można informacje o kompilacji (błędach kompilacji), debugowaniu itp. Użytkownik może teraz skompiliować i uruchomić program ”wykrzyknikiem” (niebieskie podświetlenie). Pojawi się interfejs użytkownika jak na rysunku 2. W tym momencie program pracuje w trybie demonstracyjnym i nie bierze pod uwagę obecnie istniejącego kodu w funkcji ”Obliczenia()”, pozwala to na zapoznanie się z samym interfejsem jak i poprawnym rozwiązaniem. Można więc: 1. Wybrać równanie 2. Wybrać metode całkowania 3. zobaczyć warunek początkowy (niezmienne w ogóle) Rysunek 3: Przejście w tryb pracy 4. dobrać krok całkowania 5. dobrać dziedzinę (można tylko zmienić Xmax ) następnie, po wybraniu parametrów rozwiązania 6. żądać wykonania obliczeń 7. żądać wykresu graficznego pokazanego w 10 8. żądać wyników w tabeli 9 Po kilku próbach można przejść do trybu roboczego (rys. 3), w którym to po naciśnięciu przycisku obliczeń (6) wszystkie parametry 1-5 zostaną przekazane do procedury ”Obliczenia()”, zostanie wykonany kod w tej procedurze i po wybraniu wyników graficznych (cyfrowych) zostaną przedstawione dane uzyskane w rezultacie proponowanego przez studenta rozwiązania, a dokładniej z wektora zwróconego przez funkcję ”Obliczenia()”. W tym momencie wykonanie tych operacji da rozwiązanie błędne (brak zaimplementowanej metody R-K). Przystąpmy do omówienia funkcji ”Obliczenia()”. Po jej zlokalizowaniu możemy przyjrzeć się jej argumentom i wartości zwracanej. Argumentami przekazywanymi do tej funkcji (a definiowanymi w interfejsie) są: - ”int m nNumerRownania” - zmienna całkowita z przedziału 0-3 mówiąca o wybranym przez użytkownika równaniu do rozwiązania (równania są numerowane od zera) - ”int m nNumerMetody” - zmienna całkowita z przedziału 0-3 mówiąca o wybranej przez użytkownika metodzie całkowania - ”float m nXZero” - lokalizacja warunku początkowego, czyli x0 - ”float m nYZero” - warunek początkowy, czyli y(x0 ) - ”float m nKrokCalkowania” - krok całkowania - ”float m nXmin” - początek obszaru obliczeniowego Xmin Rysunek 4: Wybór metody całkowania - ”float m nXmax” - koniec obszaru obliczeniowego Xmax wartością zwracaną przez procedurę jest adres tablicy typu float, w której mają się znajdować kolejne wartości funkcji y(x). Tablicę taką trzeba stworzyć, zaalokować dla niej pamięć, wypełnić i na końcu zwrócić komendą ”return”. Jak tworzymy tablicę? Poprzez instrukcję ”float* wynik=NULL;” tworzymy pustą tablicę o nazwie ”wynik”, a komendą ”wynik=new float[m LiczbaKrokow+1]” alokujemy pamięć dla ”m LiczbaKrokow+1” elementow (tablica ma zawierać rozwiązanie oraz jeden dodatkowy element informujący interfejs o liczbie punktów rozwiązania). ”m LiczbaKrokow” to ilość kroków potrzebnych do całkowania w zadanym przedziale i przy ustalonym kroku, jest to wartość typu integer i wylicza się ją ze wzoru: m LiczbaKrokow = Xmax − Xmin +1 KrokCalkowania (5) Jako pierwszy element tablicy wpisujemy liczbę elementów rozwiązania ”wynik[0]=m LiczbaKrokow”, a dalej kolejne wartości rozwiązania, czyli będziemy mieli tablicę z elementami [m LiczbaKrokow, y0 = y(xmin ), y1 , y2 , ..., yN = y(xmax )]. Tak stworzoną tablicę ”wynik” należy ’odpowiednio wypełnić’, czyli skorzystać z odpowiedniej metody i równania różniczkowego. Jako, że w funkcji ”Obliczenia()” będą wszystkie cztery równania i cztery metody to tablicę ”wynik” oraz kod ją wypełniający najlepiej jest umieścić w konstrukcjach ”if”. Przykład, jeśli wybraliśmy metodę czwartą (rys. 4, RungeKutty czwartego rzędu) to ”m nNumerMetody” jest równe 3 (liczymy od zera) i jeśli wybraliśmy równanie pierwsze to ”m nNumerRownania” jest równe 0, a kod dla tej metody i tego równania umieszczamy w: if(m nNumerMetody==3 && m nNumerRownania==0) { //kod } Tak samo dla pozostałych typów równań i metod całkowania. Nie zapomnij na końcu o zwróceniu tablicy poprzez ”return wynik;”