Dotychczas zdobyta przez nas wiedza pozwala na uruchomienie "prawdziwego" programu używającego PETSc. Jak to zostało zapowiedziane, program będzie rozwiązywał układ równań powstałych z dyskretyzacji metodą różnic skończonych zadania Poissona na kwadracie jednostkowym:
przy czym rozważymy przypadek gdy .
Jak wiemy, dyskretyzacja taka prowadzi do następującej postaci macierzowej (patrz [6]):
gdzie macierz A ma postać:
static char help[] = "Rozwiązuje pięciodiagonalny układ z użyciem SLES.\n\n"; #include "sles.h" #include <stdio.h> int main(int argc,char **args) { Vec x, b, u; Mat A; /* macierz układu równań */ SLES sles; /* kontekst SLESu */ int ierr, i, n = 10, m = 10,col[5], its,flg,k,l; Scalar minus_one = -1.0, one = 1.0, val[5],h; double norm; PetscInitialize(&argc,&args,PETSC_NULL,help); OptionsGetInt(PETSC_NULL,"n",&n,&flg); OptionsGetInt(PETSC_NULL,"m",&m,&flg); /* Tworzenie wektorów */ VecCreate(MPI_COMM_WORLD,PETSC_DECIDE,n*m,&x); VecDuplicate(x,&b); VecDuplicate(x,&u); /* Wartości wektora prawej strony */ val[0]=1; VecSet(val,b); /* Tworzenie macierzy laplasjanu na prostokacie mxn */ MatCreate(MPI_COMM_WORLD,n*m,n*m,&A); h=1/(m*n+1); val[0] = -1.0/h; val[1] = -1.0/h; val[2] = 4.0/h; val[3] = -1.0/h; val[4] = -1.0/h; for (i=0; i<n*m; i++ ) { col[0]=i+1; col[1]=i-1; col[2]=i; col[3]=i+m; col[4]=i-m; l=0;k=5; if(i<m) k=4; if((i+1)>(n-1)*m){k=4;col[3]=i-m;} if((i%m)==0){l=1;k=k-1;col[1]=i+1;} if((i+1)%m==0)if(i!=0){l=1;k=k-1;} MatSetValues(A,1,&i,k,&col[l],&val[l],INSERT_VALUES); } MatSetValues(A,1,&i,k,&col[l],&val[l],INSERT_VALUES); MatAssemblyBegin(A,MAT_FINAL_ASSEMBLY); MatAssemblyEnd(A,MAT_FINAL_ASSEMBLY); /* Tworzenie kontekstu SLES */ SLESCreate(MPI_COMM_WORLD,&sles); /*Ustawienie operatorów */ SLESSetOperators(sles,A,A,DIFFERENT_NONZERO_PATTERN); SLESSetFromOptions(sles); /* rozwiązanie układu liniowego */ SLESSolve(sles,b,x,&its); /* Sprawdzenie błedu */ VecAXPY(&minus_one,u,x); VecNorm(x,NORM_2,&norm); PetscPrintf(MPI_COMM_WORLD,"Norma błędu %g, %d iteracji\n",norm,its); /* Zwolnienie przestrzeni roboczej */ VecDestroy(x);VecDestroy(u); VecDestroy(b);MatDestroy(A); SLESDestroy(sles); PetscFinalize(); return(0); }
Po uruchomieniu mamy:
hydra:/usr/home/students/bojko/> przyklad Norma błędu 0.00893566, 65 iteracji hydra:/usr/home/students/bojko/>