Symulacje komputerowe na dobre zadomowiły się w wielu dziedzinach badań naukowych, a tym bardziej w zastosowaniach modelowania matematycznego. Ufamy — ludzie matematyki stosowanej — wynikom symluacji tak bardzo, że przestaliśmy głośno wątpić w ich poprawność. Doszło do tego, że w pracach naukowych dotyczących analizy konkretnych modeli matematycznych rzeczywistości nagminnie pomija się szczegóły dokonanych obliczeń (zastępując je — jeśli w ogóle — zdawkowym ,,…wyniki komputerowych symulacji wykazują, że…”). Gdy porównamy to ze szczegółowym opisem narzędzi badawczych, technik pomiarowych i procedury eksperymentów, który jest nieodłączną częścią poważnych prac naukowych, będziemy mogli lepiej pojąć stopień bałwochwalczego uwielbienia i bezgranicznej ufności, jaką współcześni badacze obdarzają narzędzia i procedury prowadzenia eksperymentów obliczeniowych.
Występujący w Oceanie Atlantyckim stawonóg, o nazwie skrzypłocz
(Źródło: Wikipedia)Aby w życiu zawodowym uniknąć takiego — zdecydowanie niewłaściwego — stosunku do obliczeń naukowych, proponuję na zakończenie ,,zbadać” metodami komputerowymi kolejny model matematyczny: tym razem będzie to model reakcji oka skrzypłocza na światło, zaczerpnięty z pracy [5]33Dziękuję p. Wandzie Niemyskiej za przedstawienie modelu i wskazanie literatury.. Jest to układ równań różniczkowych na postaci
(12.1) |
(Jak zwykle w modelowaniu matematycznym, powyższe eleganckie równanie jest efektem wcześniejszych sprytnych manipulacji wzorami i dewymiarowania oryginalnego układu równań). Zadana z góry funkcja ma modelować przebieg natężenia światła zewnętrznego w czasie. W [5] jest to funkcja schodkowa, przyjmiemy więc konkretnie, że dla i zadanych czasów krytycznych
(por. rysunek 12.1).
Dodatkowo powinniśmy przyjąć, że jest małe. Dla badaczy interesująca jest przede wszystkim składowa rozwiązania, modelująca odpowiedź oka na bodziec.
Oryginalna praca [5] była na tyle stara, by — oprócz szczegółów sposobu przeprowadzania pomiarów fizycznych, służących jako porównawczy materiał eksperymentalny — wskazać użyte narzędzia obliczeniowe; oto one [5, strona 257]:
Solutions […] were obtained on EDSAC 2 at Cambridge using a Runge–Kutta method.
Każdy, kto choć trochę liznął metod numerycznych rozwiązywania równań różniczkowych zwyczajnych, natychmiast będzie miał wątpliwości: którą konkretnie metodę Rungego–Kutty mają na myśli autorzy? czy klasyczną metodę czteropoziomową, czy może tańszą, dwupoziomową? A może którąś z metod RKF (o ile mamy w ogóle świadomość istnienia takiego wariantu metody Rungego–Kutty…)? Czy stosowano automatyczne sterowanie długością kroku — jeśli tak, to na podstawie jakiego kryterium? A jeśli nie, to jakiej użyto długości kroku całkowania?
Na tym etapie nie wydaje się, by powyższe równanie mogło sprawić nam (to znaczy: naszemu systemowi obliczeń numerycznych) jakikolwiek poważniejszy problem. Wystarczy skorzystać z gotowych narzędzi rozwiązywania równań różniczkowych zwyczajnych dostępnych w Octave (lub w MATLABie): na przykład, z solvera ode45
zaimplementowanego w obu wspomnianych systemach obliczeń naukowych.
W naszych obliczeniach przyjmiemy na początek następujące wartości liczbowe parametrów zadania:
Parametr | Wartość |
---|---|
10 | |
3 | |
0.2 |
Rozwiązanie problemu i wizualizacja składowej mogłaby być na przykład zrealizowana poniższym, całkiem standardowym kodem:
Jeśli chcesz pracować w serwisie internetowym WebOctave, najpierw musisz zdefiniować funkcje prawej strony rhs
oraz v0
.
function dY = rhs(t,Y) % prawa strona rownania N = length(Y); q = [y0(t); Y(1:N-1)]; dY = -Y*(1+Y(N)) + q; end
function v = y0(t) % wymuszenie zewnetrzne; t musi byc skalarem! global tau; global Ti; v = (min(abs(t - Ti)) < tau); % krótkie ($2\tau$) pulsy wokół $T_i$ end
Program działa w Octave i wydaje się, że produkuje poprawne wyniki ( stabilizuje się), ale już dla obserwujemy ciekawe zjawisko: wyznaczone rozwiązanie wykazuje zachowanie oscylacyjne!
W symulacji powyżej połóż i sprawdź wyniki. Jak wygląda przebieg wszystkich składowych rozwiązania w czasie?
A więc mamy ,,numeryczny dowód”, że oczy skorupiaka (przynajmniej w ramach naszego modelu), poddane pulsacyjnemu działania światła zewnętrznego, reagują także w sposób periodyczny — co zasadniczo nie powinno nas dziwić… Warto więc byłoby zbadać okres tej reakcji, a następnie spróbować odnieść to zachowanie do wyników eksperymentów fizycznych. Jednak… fizyczny eksperyment nie może być przeprowadzony w tak długim czasie, pozostaje więc nam poruszać się na gruncie teorii.
Gdybyśmy byli nieco bardziej ostrożni, zauważylibyśmy (być może), iż nieco nadużyliśmy składni funkcji ode45
. Dokładniej, aby skorzystać z automatycznego sterowania długością kroku w tym solverze, powinniśmy34Wystarczy przeczytać opis funkcji! — nieco inaczej niż w lsode
— podać jako drugi argument jedynie dwuelementowy wektor ! W przeciwnym razie, solver zawsze wybiera stały krok długości tsmpl(i)-tsmpl(i-1)
, co przy daje krok całkowania — zdecydowanie za duży, na przykład, w porównaniu z !
Po rozwiązaniu zagadki oscylacji — nieistniejących w rzeczywistości — możemy teraz mieć ochotę na zabawę z wartością parametru , określającego długość trwania impulsu świetlnego. Z punktu widzenia modelowania, interesujące byłoby wyznaczenie wartości , przy której bezwładność oczu stwora jest na tyle duża, że przestają one reagować na (najwyraźniej zbyt krótkie) impulsy świetlne i ich reakcja wygasa.
W tym celu wystarczy stopniowo zmniejszać i obserwować, jak zmieni się odpowiedź układu; dla wystarczająco krótkich impulsów spodziewamy się, że bodźce będą zbyt słabe, by stabilnie wzbudzić niezerową wartość składowej : spodziewamy się gasnących do zera.
Przeprowadźmy zatem symulację dla — to znaczy dwudziestokrotnie mniejszej niż dotychczas.
Jak można zorientować się z przeprowadzonej symulacji, początkowo rośnie (eksponencjalnie?) i nie wiadomo, czy potem stabilizuje się, jak poprzednio, czy też może zachowanie jest inne. Dlatego należy wydłużyć czas symulacji:
Okazuje się, że faktycznie, rozwiązania po chwilowym wzbudzeniu szybko gasną do zera. Aby upewnić się, czy nie mamy czasami do czynienia z numerycznym artefaktem, rozwiążemy to samo równanie, drastycznie zaostrzając kryteria tolerancji błędu, używając do tego funkcji odeset
.
Jak widać, choć otrzymane krzywe nie pokrywają się idealnie, zgadzają się ze sobą co do charakteru: , po chwilowym wzroście, gaśnie do zera.
Gdybyśmy jednak wykazali mniej zaufania do wyników i rozwiązali zadanie… innym solverem, na przykład ode78
(dostępny w Octave, w MATLABie możesz wybrać na przykład ode115
)?
Wykonaj powyższą symulację z innym solverem.
Jeśli będziesz pracować z lsode
, pamiętaj o tym, że wymaga on innej składni wywołania oraz innej składni funkcji prawej strony!
Może okazać się, że otrzymamy zupełnie inny wykres! Co prawda pragmatycy staraliby się podkreślić, że ,,co do charakteru” dalej mamy zgodność, bo rozwiązania gasną (do zera?), ale większość z nas, widząc wykresy jak na rysunku 12.2, zaczęłaby powątpiewać w jakość prowadzonych obliczeń.
Może jednak problem leży w tym, że impulsy są na tyle krótkie, że nasz solver, stosując pewne strategie doboru kroku całkowania ,,opuszcza” część impulsu tak, że to z tego powodu rozwiązania gasną?
Gdyby bowiem zastosować jeszcze bardziej drastyczne parametry tolerancji błędu, na przykład
odeset('RelTol',1e-12,'AbsTol', 1e-12)to okazuje się, że co prawda czas obliczeń wydłuża się niepokojąco, ale też i wynik obliczeń zmienia się nie do poznania, zob. wykres 12.3.
Po doświadczeniu z większymi bylibyśmy zapewne skłonni uwierzyć bez zastrzeżeń, że otrzymaliśmy wynik wykazujący, że dla rozwiązania jednak nie zanikają w czasie.
Ale, jeśli przeprowadzilibyśmy symulację korzystając z dokładniejszej metody, ode78
i równie ostrych parametrach tolerancji błędu jak ostatnio, to zapewne zaskoczyłby nas przebieg tak wyznaczonego rozwiązania, przedstawiony na rysunku 12.4.
Bardzo możliwe, że jednak za bardzo przejęliśmy się narzędziami, a za mało samym problemem: przecież rozwiązania, które nas interesują, są bardzo mało regularne! A to z kolei znaczy, że stosowanie solvera wysokiego rzędu aproksymacji — takiego jak ode78
— nie bardzo ma sens; rzeczywiście, dla parametrów tolerancji błędu , wyniki symulacji (prawie) pokrywają się (por. rysunki 12.5 i 12.6: nie tylko dla obu dotychczas przez nas próbowanych solverów, ale także dla lsode
, który wykorzystuje nie tylko zmiany długości kroku, ale także dostosowuje rząd metody.
A jak Ty uważasz, poniżej jakiej wartości rozwiązania naprawdę dążą do zera, gdy ?
Zauważmy, że nasze zadanie jest mimo wszystko trudne do rozwiązania numerycznego! Wiąże się to z charakterem nieliniowości prawej strony równania, a dokładniej, z przebiegiem , która jest funkcją nieciągłą. Wszystkie używane przez nas metody (w postaci solverów typu ode45
) zakładają tymczasem, że aproksymowane rozwiązania są funkcjami dostatecznie gładkimi, co oczywiście w naszym przypadku nie jest założeniem spełnionym. To typowa dla obliczeń naukowych sytuacja, gdy istniejące oprogramowanie (i zaimplementowane w nim metody numeryczne) zmuszamy do pracy w warunkach wykraczających poza ich założone zastosowanie.
Gdyby na nasz problem rzucić okiem praktyka, natychmiast zwróciłby nam uwagę na to, że w ,,trudnej” wersji zadania (dla małych ) występują dwie skale czasowe: skala szybkozmienna, związana z zewnętrznymi impulsami i skala wolnozmienna, reakcji na wymuszenie. To zaś podpowiada nam, by w takiej sytuacji zastosować krok całkowania krótszy niż długość najkrótszej skali czasowej zadania.
Rozwiązaniem siłowym byłoby więc zmuszenie solvera do pracy z krokiem czasowym wyraźnie mniejszym niż . Jednak z drugiej strony oznacza to nieprawdopodobne zwiększenie kosztu obliczeniowego potrzebnego do wyznaczenia rozwiązania: dla i musielibyśmy wykonać co najmniej kroków czasowych (zapewne znacznie więcej).
I faktycznie, o ile uzyskanie (najprawdopodobniej) błędnego wykresu wymagało tylko kilku- kilkunastu sekund cierpliwości, to wygenerowanie (bliższego prawdy, miejmy nadzieję) wykresu kodem:
opts = odeset('RelTol', 1e-10, ... 'AbsTol', 1e-10, ... 'MaxStep', tau, ... % redukcja kroku całkowania do najmniejszej skali czasowej 'InitialStep', tau/3); [tcomp, Y] = ode45(@rhs, [0,T], Y0, opts);
ciągnie się niemalże w nieskończoność (sprawdź, ile herbat zdążysz sobie przyrządzić, gdy …).
Czy można byłoby więc jakoś temu zapobiec?
Musimy raz jeszcze spojrzeć na naturę naszych kłopotów. Wszystko zdaje się pochodzić stąd, że solvery, których używamy, dobrze działają, gdy rozwiązania są gładkie. Tymczasem nasze rozwiązania są niegładkie. No dobrze, ale przecież tym samym jest to nie tylko problem obliczeniowy, ale także problem czysto matematyczny: jak bowiem zdefiniować rozwiązania równania różniczkowego, w którym prawa strona jest… nieciągła?!
W naszym przypadku, ściślej rzecz biorąc, prawa strona jest kawałkami stała — ciągła z wyjątkiem punktów postaci — zatem, gdyby ograniczyć się do przedziałów postaci
tam moglibyśmy sensownie zdefiniować nasze równanie różniczkowe (za wartość początkową w danym przedziale biorąc wartość końcową z przedziału poprzedniego). Gdybyśmy więc postąpili identycznie w naszych obliczeniach, całkowicie uniknęlibyśmy w ten sposób kłopotów z nieciągłościami i ich automatyczną lokalizacją! Ceną za to jest wbudowanie w program pętli po pododcinkach, jednak — jak sami za chwilę się przekonamy — będzie warto ją zapłacić!
opts = odeset('RelTol', RTOL, ... 'AbsTol', ATOL, ... 'InitialStep', tau/3); tcomp = []; Y = []; Y0i = Y0; for i = 1:length(Ti)-1 opts = odeset(opts, 'MaxStep', (Ti(i+1)-Ti(i))*0.1); [tcompi, Yi] = ode45(@rhs, [Ti(i),Ti(i+1)-tau], Y0i, opts); tcomp = [tcomp; tcompi]; Y = [Y; Yi]; Y0i = Yi(end,:); opts = odeset(opts, 'MaxStep', tau*0.1); [tcompi, Yi] = ode45(@rhs, [Ti(i+1)-tau,Ti(i+1)], Y0i, opts); tcomp = [tcomp; tcompi]; Y = [Y; Yi]; Y0i = Yi(end,:); end I = Y(:,1); V = Y(:,N); plot(tcomp,[I,V]);
Czy teraz jesteś w stanie zbadać zależność ,,przy ” dla różnych ? Jaką możesz postawić hipotezę? Czy potrafisz ją udowodnić?
Treść automatycznie generowana z plików źródłowych LaTeXa za pomocą oprogramowania wykorzystującego LaTeXML.
strona główna | webmaster | o portalu | pomoc
© Wydział Matematyki, Informatyki i Mechaniki UW, 2009-2010. Niniejsze materiały są udostępnione bezpłatnie na licencji Creative Commons Uznanie autorstwa-Użycie niekomercyjne-Bez utworów zależnych 3.0 Polska.
Projekt współfinansowany przez Unię Europejską w ramach Europejskiego Funduszu Społecznego.
Projekt współfinansowany przez Ministerstwo Nauki i Szkolnictwa Wyższego i przez Uniwersytet Warszawski.