Aby go rozwiązać, musimy utworzyć wektory rozwiązania i prawej strony oraz macierz zadania, a następnie spiąć te wszystkie dane ze sobą i zlecić pakietowi rozwiązanie tego układu. Do tego służą właśnie obiekty typu SLES.
Aby utworzyć obiekt typu SLES trzeba, podobnie jak w poprzednich przypadkach, najpierw zadeklarować odpowiednią zmienną:
... SLES MojSles; ...
Pierwszy argument funkcji SLESCreate() to, podobnie jak w przypadku innych obiektów, kanał komunikatora MPI, u nas zawsze będzie to MPI_COMM_WORLD. Drugi to wskaźnik do uprzednio zadeklarowanej zmiennej typu SLES.
Następną czynnością, jaką należy wykonać, jest przekazanie macierzy zadania do SLESu. Robi się to przy pomocy funkcji:
SLESSetOperators(SLES MojSles,Mat A,Mat P, MatStructure flag);
|
|
SAME_PRECONDITIONER | Macierz P jest cały czas taka sama w czasie procesu iteracyjnego. Ta opcja jest dla tych, którzy używają różnych macierzy A i P. Opcja ta np. oszczędza pracę przy niekompletnym rozkładzie Choleskiego stosowanym jako preconditioner: rozkład jest robiony tylko raz. |
SAME_NONZERO_PATTERN | w trakcie iteracji macierz P ma taką samą strukturę miejsc niezerowych |
DIFFERENT_NONZERO_PATTERN | w trakcie iteracji macierz P zmienia strukturę |
Powyższe przygotowania wystarczają, aby SLES rozwiązał układ równań z macierzą A i prawą stroną b. W tym celu należy wywołać funkcję SLESSolve(SLES MojSles,Vec b,Vec x,int *its). Wynik zostanie zapisany w wektorze x.
W zmiennej its zostanie zapisana liczba wykonanych iteracji. Po zakończeniu obliczeń należy zwolnić pamięć zajmowaną przez SLES funkcją: SLESDestroy(SLES MojSles), gdzie argumentem jest (niepotrzebny już) obiekt MojSles. Ważne jest, że jeden SLES może służyć do rozwiązania wielu układów równań, na przykład kilku układów z tą samą macierzą i inną prawą stroną.
#include "sles.h" int main(int argc,char **args) { Vec x,b; Mat A; /* macierz układu równań */ SLES MojSles; /* kontekst SLESu */ int its; Scalar val; PetscInitialize(&argc,&args,PETSC_NULL,PETSC_NULL); /* Tworzenie kontekstu SLES */ SLESCreate(MPI_COMM_WORLD,&MojSles); /* tutaj trzeba utworzyć wektory (str. 12) i macierze, (str. 17) */ /*Ustawienie operatorów */ SLESSetOperators(MojSles,A,A,DIFFERENT_NONZERO_PATTERN); SLESSetFromOptions(MojSles); /* rozwiązanie układu liniowego */ SLESSolve(MojSles,b,x,&its); /*Tu z kolei należy zwolnić pamięć*/ SLESDestroy(MojSles); PetscFinalize(); return(0); }
na siatce o kroku h. Testuj błąd rozwiązania
w normie max i l2 dla f odpowiadającym
rozwiązaniu dokładnemu
a) sin(x),
b) x2+y2.
Sprawdź, jak zmienia się liczba iteracji w zależnościod h. Obejrzyj
wektory rozwiązania i błędu w okienku graficznym.
Eksperymentuj z różnymi sposobami implementacji macierzy (klasycznie i powłokowo).