AdamátorZápiskyHlášky

Cvičení z Numerické matematiky 2

  1. Metoda konečných diferencí
    1. Cauchyho úloha a Rungovy-Kuttovy metody
      1. Rungova-Kuttova metoda pro n=1
        1. Rungova-Kuttova metoda pro n=2
          1. Cauchyho úloha vyššího řádu
          2. Objektově orientované programování
            1. Řešení okrajových úloh

              Materiály

              Metoda konečných diferencí

              Oberhuberova prezentace

              Definice Nechť x0, Hx0 je jeho okolí a f,g:Hx0. f aproximuje g s přesností řádu r, pokud existuje C+ takové, že
              limxx0|f(x)g(x)||xx0|r=C
              Definice Nechť x0, Hx0 je jeho okolí, f:Hx0, h+ a l1,l2. Potom budeme značit
              Věta Nechť f𝒞2((x0,x1)). Potom
              f1f0h=f(x0)+𝒪(h)
              Věta Nechť f𝒞2((x1,x0)). Potom
              f0f1h=f(x0)+𝒪(h)
              Věta Nechť f𝒞2((x1,x1)). Potom
              f1f12h=f(x0)+𝒪(h)
              Věta Nechť f𝒞3((x1,x1)). Potom
              f1f12h=f(x0)+𝒪(h2)
              Věta Nechť f𝒞4((x1,x1)). Potom
              f12f0+f1h2=f(x0)+𝒪(h2)
              Věta Nechť f𝒞n+1((xl1,xl2)). Potom pro každé kn^ lze k-tou derivaci aproximovat pomocí konečných diferencí s přesností řádu n+1k.

              Cauchyho úloha a Rungovy-Kuttovy metody

              Oberhuberova prezentace

              Mějme obyčejnou diferenciální rovnici s počáteční podmínkou:

              x(t)=f(t,x(t)),t(0,T)
              x(0)=x0

              Zkusíme ji vyřešit „simulací“ s diskrétními časovými intervaly. Zvolíme si časový krok τ, tedy budeme mít NTτ kroků. Budeme počítat:

              xi+1xi+Δx(iτ,τ)

              Otázkou je, jak zvolit vhodné Δx. Chtěli bychom, aby platilo:

              Δx(t,τ)=x(t+τ)x(t)=Taylorτx(t)+τ22x(t)+

              První derivaci si můžeme spočítat přímo ze zadání. S druhou už to bude horší:

              x(t)=1f(t,x(t))+2f(t,x(t))x(t)=1f(t,x(t))+2f(t,x(t))f(t,x(t))

              K tomu už potřebujeme znát derivace f. A s dalšími derivacemi by to bylo ještě horší. Pokud se vykašleme na všechny derivace kromě první, dostaneme známou Eulerovu metodu. Ale tento postup je obecně dost numericky nestabilní. Radši použijeme Rungovu-Kuttovu metodu. Ta funguje tak, že přírůstky budeme hledat ve tvaru:

              Δx(t,τ)=i=1npiki(t,τ)
              k1(t,τ)τf(t,x(t))
              ki(t,τ)τf(t+αiτ,x(t)+j=1i1βi,jkj(t,τ)),i>1

              Teď je samozřejmě otázkou, jak vhodně zvolit koeficienty pi,ai,βi,j. Obecně je chceme zvolit tak, aby se přírůstek shodoval s Taylorem do co nejvyššího stupně. Detaily viz prezentace.

              Rungova-Kuttova metoda pro n=1

              Δx(t,τ)=p1k1(t,τ)=p1τf(t,x(t))
              φ1(τ)=x(t+τ)x(t)p1τf(t,x(t))=τx(t)+τ22x(s)p1τf(t,x(t))=(1p1)τf(t,x(t))+τ22x(s)
              φ1(τ)=(1p1)f(t,x(t))+τx(s)
              φ1(0)=(1p1)f(t,x(t))=0p1=1
              Δx(t,τ)=τf(t,x(t))

              Tím jsme opět dostali známou Eulerovu metodu.

              Rungova-Kuttova metoda pro n=2

              Δx(t,τ)=p1k1(t,τ)+p2k2(t,τ)=p1τf(t,x(t))+p2τf(t+α2τ,x(t)+β2,1k1(t,τ))
              φ2(τ)=τx(τ)+τ22x(t)+(τ36x(s))zp1τf(t,x(t))p2τf(t,x(t)+β2,1k1(t,τ))=τf(t,x(t))+τ22(tf(t,x(t))+xf(t,x(t))f(t,x(t)))+zp1τf(r,x(t))p2τf(t,x(t)+β2,1τf(t,x(t)))
              φ2(τ)=f(t,x(t))+τ(tf(t,x(t))+xf(t,x(t))f(t,x(t)))p1f(t,x(t))p2f(t,x(t)+β2,1τf(t,x(t)))p2τ(tf()α2+xf()β2,1f(t,x(t)))
              φ2(τ)=τf(t,x(t))+xf(t,x(t))f(t,x(t))2p2(tf()α2+xf()β2,1f(t,x(t)))p2τt()
              φ2(0)==01p1p2=0
              φ2(0)==012α2p2=12β2,1p2=0
              První možnost:
              p1=p2=12,α2=β2,1=1
              Druhá možnost:
              p1=0,p2=1,α2=β2,1=12
              Vidíme, že pro každý řád se to počítá výrazně pracněji.

              Cauchyho úloha vyššího řádu

              xn(t)=f(t,x(t),,xn1t)

              Použijeme substituci, čímž to převedeme na soustavu:

              ui(t)xi(t)
              un(t)=f(t,u0(t),,un1(t))
              u(i1)(t)=ui(t)

              Musíme znát počáteční podmínky pro každé u, tedy počáteční derivace až do řádu n1.

              Runge-Kuttovy metody můžeme přepsat do vektorového tvaru:

              Δu(t,τ)=i=1npiki(t,τ)
              ki(t,τ)=τF(t+j=2iαjτ,u(t)+j=1i1βi,jkj(t,τ))

              Objektově orientované programování

              Oberhuberova prezentace

              Když chceme v C++ vykreslit graf funkce, normální člověk by napsal něco takového:

              void drawFunction(std::function<double(double)> f, double left, double right, double step) {
                for (double x = left; x <= right; x += step) {
                  std::cout << x << " " << f(x) << "\n";
                }
              }
              
              int main() {
                drawFunction([](double x) { return (2 * x + 3) * x + 1; }, 0.0, 1.0, 0.1);
                drawFunction([](double x) { return 2 * sin(5 * x + 1); }, 0.0, 1.0, 0.1);
              }

              Ale Oberhuber radši napíše tohle:

              struct Function
              {
                  virtual double getFx( double x );
              }
              
              struct Quadratic : public Function    // !!!!
              {
                  double a, b, c;
              
                  double getFx ( double x )
                  {
                      return ( a * x + b ) * x + c;
                  }
              }
              
              struct Sinus : public Function    // !!!!
              {
                  double A, f, p;
              
                  double getFx ( double x )
                  {
                      fx = A * sin ( f * x + p );
                  }
              }
              
              void drawFunction( Function * function ,
                                 double left , double right , double step )
              {
                  for ( double x = left ; x <= right ; x += step )
                  {
                      printf( " %f %f \n", x, function−>getFx( x ) );
                  }
              }
              
              int main ( int argc , char * argv[] )
              {
                      /****
                       * Evaluate f (x) = 2 x^2 + 3 x + 1 on <0,1>
                       */
                       Quadratic f1;
                       f1.a = 2.0;
                       f1.b = 3.0;
                       f1.c = 1.0;
                       drawFunction ( &f1, // WE DO NOT NEED TO CARE ABOUT FUNCTION TYPE
                                      0.0, 1.0,     // on interval <0, 1>
                                      0.1,          // we draw it with resolution 0.1
                                                    //    −> 11 points on the interval
                                       );
              
                      /****
                       * Evaluate f(x) = 2 sin( 5 *x + 1 ) on <0,1>
                       */
                       Sinus f2;
                       f2.A = 2.0;
                       f2.f = 5.0;
                       f2.p = 1.0;
                       drawFunction ( &f2, // WE DO NOT NEED TO CARE ABOUT FUNCTION TYPE
                                      0.0, 1.0,     // on interval <0, 1>
                                      0.1,          // we draw it with resolution 0.1
                                                    //    −> 11 points on the interval
                                       );
              
              }

              Řešení okrajových úloh

              Oberhuberova prezentace

              Mame-li úlohu se dvěma stupni volnosti, potřebujeme dvě počáteční podmínky. Místo toho ale často máme zadané okrajové podmínky. Z přednášky známe metodu střelby, ale ta nejde zobecnit do více dimenzí (parciální diferenciální rovnice). Místo toho použijeme metodu sítí: provedeme diskretizaci a vyřešíme soustavu lineárních rovnic. Detaily viz prezentace a přednáška.