Implementación de la Factorización Incompleta ILU S(`, τ ) para matrices esparcidas Carlos A. Theran Suarez May 3, 2013 Abstract En este trabajo se mostrará una implementación de las de las factorizaciones ILU S(`, τ ) [1] el cual consiste en dos fases. La primera fase es conocida como factorización simbólica y la segunda fase factorización numérica para matrices esparcidas, dicha implementación se llevará acabo bajo el lenguaje de C++, con una estructura orientada a objetos. Para esto será necesario utilizar un formato de almacenamiento para matrices esparcidas, el formato utilizado en este trabajo es CSR (compressed sparse row) [2]. El código esta dividido por clases, clase CSR y la clase de los precondicionadores ILU (`, τ ) Para validar el código se proporciona una matriz esparcida y se calculará su fractorización ILU (`, τ ). 1 Estructura de almacenamiento CSR El formato CSR (compressed sparse row) permite almacenar solo los elementos diferentes de cero de una matriz A. Este formato hace uso de los vectores. nnzi: almacena el numero de elementos diferentes de cero de la matriz. nzi: almacena el numero de elementos diferentes de cero de la matriz en la fila i. ja: almacena el ı́ndice las columnas donde se encuentras los elementos diferentes del cero. aa: almacena los elementos diferentes de cero en forma de vector. 1 Interface CSR #ifndef _CSR_H #define _CSR_H #include <fstream> #include <iostream> class CSR { public: CSR(); ~CSR(); void Setup(const char *namefile); void MatVec(double x[],double y[]); void get(double **&uu, unsigned int **&ju, unsigned int *&unzi, unsigned int &nRow, unsigned int &nCol); unsigned int get_nnz(); double Cost_Memory(); private: void Bubblesort_increase(unsigned int k); unsigned int numRow_; unsigned int numColum_; int nnz; unsigned int *nzi_; unsigned int **ja_; double **aa_; }; #endif veamos una breve introducción de los métodos de la clase CSR. • void Setup(const char *namefile): Este inicializador toma como parámetro una cadena de caracteres la cual es la dirección donde se ha guardado el documento que contiene la data de la matriz a factorizar. 2 • void get(double **uu, unsigned int **ju,unsigned int *unzi, unsigned int nRow): Este método permite obtener la data privada de la clase CSR, y es utilizado para cargar la matriz U de la factorización ILU, de esta menra se conserva la matriz original. 2 Precondicionador ILU S(`, τ ) Este Precondicionador esencialmente lo que nos permite es realizar la factorización LU pero teniendo en cuenta los fill-in, los cuales son permitido asignando un nivel a cada entrada de la matriz por medio de la regla de la suma [1], la cual es la primera fase del método. Para asignar los niveles a las entradas de la matriz se comienza asignando nivel cero a todas aquellas entradas las cuales son diferentes de cero. luego se aplica la regla de la suma la cual viene dada por level(i, j) = min1≤min(i,j) max{level(i, h), level(h, j)}+1. El parámetro l es el permite filtrar entradas de llenado en la matriz hueca a la hora de la factorización numérica la cual es la segunda fase del método. Entre mayor sea l este permitirá mas entradas diferentes de cero, una de los inconvenientes para valores grandes de l es que se requiere una mayor capacidad de memoria para el almacenamiento de las entradas permitidas, además se requerirı́a una maquina con grande capacidad de memoria y un excelente procesador para que la fase 1 (factorización simbólica) no gaste demasiado tiempo en su ejecución, dado que se presenta el hecho que si estamos en la posición i y suponiendo que esta fila tiene todas sus entradas completas, se debe revisar i − 1 filas para actualizar el nivel de las entradas de la fila i. A continuación se presentará un seudo código para la fase 1 de la factorización ILU S(`, t). Algoritmo 2.1 Classic-ILU(`) #Loop sobre filas for j=1 a n #Inicializa fase: Se admiten entradas de A, y se asignan los niveles ceros adj’(j)<-vacio for t en adj(j) level(j,t)=0 insertar t en adj’(j) #fase actualizacion de fila for cada i en adj’(j) con i<j en orden ascendente 3 for t en adj’(i) con t>i wt = level(i,h),level(h,j)\}+1 if wt <= l if t no esta en adj’(j) insertar t en adj’(j) level(j,t)=wt else level(j,t)=min{level(j,t),wt} Interface ILU S(`, τ ) #ifndef _ILUS_H #define _ILUS_H #include <fstream> #include <iostream> #include "CSR.h" class ILUS { public: ILUS(); ~ILUS(); void Setup(CSR &A); void Apply(double x[], double y[]); unsigned int get_nnz(); double Cost_Memory(); private: void Simbolica_LUS(const double l); void Imcomplete_LUS(const unsigned int l, const double tao); bool pertenece1(unsigned int k,unsigned int i,unsigned int &index); bool pertenece(unsigned int k,unsigned int Level[], unsigned int i,unsigned int &index); double tao_i(const double tao, const unsigned i); void QuickSort(unsigned int ptr_j[],double ptr_u[], unsigned int ptr_level[],int izq, unsigned int der ); void Lx(double x[],const double b[]); 4 void Ux(double x[],const double b[]); unsigned int *lnzi_; unsigned int *unzi_; unsigned int **jl_; unsigned int **ju_; unsigned int **level_; double **uu_; double **ll_; unsigned int nRow_; unsigned int nCol_; unsigned int nnz; float diff; }; #endif Se realizará una breve descripción de los métodos mas importantes de la clase ILUS. • void Setup(CSR A): con esta función inicializo todas las variables privadas de la clase ILUS, copiando la estructura de la matriz A en la matriz U, para posteriormente no modificar la matriz A. • void SimbolicaLUS(const double l): esta función es la encargada de realizar la primera fase de la factorización, es decir se estará calculando el patrón del factor incompleto U . • void ImcompleteLUS(const unsigned int l, const double tao): Aquı́ se lleva a cabo la factorización numérica teniendo los niveles de cada entrada de la matriz. 3 Método del gradiente Precondicionado Este método sigue la misma idea del (GM), pero ahora se trabajará con la factorizacion incompleta, la precondicion se realizará por la izquierda es decir, se resolverá ahora el problema M −1 (b − Ax), donde M = (LU ) una 5 factorizacion incompleta de A, entonces el algoritmo es el mismo que el descrito en (5.1), pero ahora se trabaja con los siguientes elementos, b̄ = M −1 b, M −1 x̄ donde x̄ = Ax y r̄i = M −1 ri . Los elementos r̄i , b̄, se calculan mediante la solución de un sistema lineal. Algoritmo 3.1 PGM #ifndef _PGM_H #define _PGM_H #include <fstream> #include <iostream> #include "ILUS.h" using namespace std; class PGM { public: PGM(); ~PGM(); void Setup(const char *namefile,CSR &A,ILUS &LU, unsigned int max_iter,double err); void Solver(double x0[]); unsigned int NumIter(); private: double norm_inf(double r[]); double dotp(double x[], double y[]); double norm(double r[]); double *b_; double *r_; double *resd_; double err_; CSR *A_; ILUS *LU_; unsigned int Iter; unsigned int MaxIter_; }; 6 #endif 4 Experimentos Numéricos En esta sección se valida el código para la factorización incompleta ILU S(l, t), analizando consigo la convergencia del método MG y PMG. Las matrices utilizadas para los siguientes experimentos fueron la matriz de Durlosfky, P1-A2, P2-A2. Las cuales están generadas por métodos de diferencia finita y volumen finito. Las pruebas están realizadas con un numero máximo de iteraciones de 5000 donde el criterio de parada es el número maximo de iteraciones y el error relativo. En esta grafica se puede observar como el aumento del umbral permite obtener menos iteraciones al momento de aplicar el MGP. La matriz de dimensión 1600x1600 utilizada para este experimento fue obtenida por una discretización de diferencias finitas. 7 Con al discretización de elementos finitos se obtiene una matriz de 3416x3416. Es de notar que a medida que el umbral aumenta el número de iteraciones para la convergencia de la solución disminuye haciendo uso de un nivel ` = 0. Este experimento se ha realizado aumentando el parámetro ` = 1. Comparando estos resultado con los anteriores, se puede observar que el número de iteraciones disminuye para 10−3 y 10−4 . 8 Con ` = 2 se observa el mismo comportamiento que el anterior experimento. Con ` = 3 se obtiene los mismo resultados que ` = 1 y ` = 2. 9 La matriz utilizada para este experimento es generada por elementos finitos cuya dimensión es de 8540x8540. De igual manera se obtiene menos iteraciones al momento de aumentar el umbral. Con ` = 1 se obtiene los mismo resultados que ` = 0. En las siguientes tablas se presentan en detalle los resultados obtenidos de los experimentos. En este reporte se podrán observar el error residual 10 ` 0 1 2 3 En τ R. Error −1 10 9.89837e-11 10−2 8.98461e-11 10−3 6.5563e-11 10−4 2.65758e-11 10−1 9.89837e-11 10−2 8.98461e-11 10−3 6.5563e-11 10−4 2.65758e-11 10−1 9.89837e-11 10−2 8.98461e-11 10−3 6.5563e-11 10−4 2.65758e-11 10−1 9.89837e-11 10−2 8.98461e-11 10−3 6.5563e-11 10−4 2.65758e-11 esta tabla se utilizo NNZ Iter solver 4961 3659 22653 269 32504 46 42668 15 4961 3659 22653 269 32504 46 42668 15 4961 3659 22653 269 32504 46 42668 15 4961 3659 22653 269 32504 46 42668 15 una matriz de 1600x1600 (R. error), el cual ha siendo calculado por la norma infinita, la cantidad de elementos diferentes de ceros se ven en los NNZ, el número de iteraciones que emplea el solver para lograr alcanzar un error deseado el cual es uno de los criterios de parada. 11 ` 0 1 2 3 En ` 0 1 2 3 En τ R. Error −1 10 9.98543e-11 −2 10 3.18476e-11 10−3 9.7825e-12 10−4 5.85992e-11 10−1 9.98783e-11 10−2 3.97321e-11 10−3 1.01575e-12 10−4 4.48221e-13 10−1 9.98783e-11 10−2 3.97321e-11 10−3 1.01575e-12 10−4 4.48221e-13 10−1 9.98783e-11 10−2 3.97321e07 10−3 1.01575e-12 10−4 4.48221e-13 esta tabla se utilizo NNZ Iter solver 923257 48 1978614 12 2478121 9 2698786 7 923267 48 1978624 12 2478131 7 2698786 5 923267 48 1978624 12 2478131 7 2698786 5 923267 48 1978624 12 2478131 7 2698786 5 uuna matriz de 3416x3416 τ R. Error −1 10 7.30054e-11 −2 10 8.11754e-11 10−3 4.44308e-11 10−4 5.52347e-12 10−1 7.30054e-11 10−2 8.11754e-11 10−3 4.44308e-11 10−4 5.52347e-12 10−1 7.30054e-11 10−2 8.11754e-11 10−3 4.44308e-11 10−4 5.52347e-12 10−1 7.30054e-11 10−2 8.11754e-11 10−3 4.44308e-11 10−4 5.52347e-12 esta tabla se utilizo NNZ Iter solver 6293044 128 12653881 22 15367921 9 16611919 6 6293044 128 12653881 22 15367921 9 16611919 6 6293044 128 12653881 22 15367921 9 16611919 6 6293044 128 12653881 22 15367921 9 16611919 6 uuna matriz de 8540x8540 12 ` 0 1 2 3 En τ FS FN MGP T. time MG −1 10 0.02 0.41 0.23 0.66 0 10−2 0.04 1.37 0.12 1.55 0 −3 10 0.03 2.89 0.12 3.04 0 10−4 0.03 5.13 0.1 5.26 0 −1 10 0.35 0.53 0.27 1.15 0 −2 10 0.33 1.52 0.11 1.96 0 10−3 0.33 3.18 0.09 3.6 0 −4 10 0.34 5.48 0.07 5.89 0 −1 10 1.53 0.68 0.28 2.49 0 10−2 1.56 1.99 0.13 3.68 0 −3 10 1.48 6.01 0.07 7.56 0 10−4 1.47 8.9 0.06 10.43 0 −1 10 4.67 0.91 0.26 5.84 0 −2 10 76.7 52.26 0.64 129.6 0 10−3 76.7 52.26 0.64 129.6 0 −4 10 76.85 81.31 0.49 158.65 0 esta tabla se utilizo uuna matriz de 3416x3416 Ahora se realizará una tabla mostrando el tiempo de ejecución de las diferentes fases del codigo. • 1. Fase simbolica • 2. Fase númerica • 3. MGP. • 4. MG. 13 ` 0 1 2 3 En 5 τ FS FN MGP T. time MG −1 10 0.26 3.12 4.06 7.44 0 10−2 0.26 15.15 1.35 16.76 0 −3 10 0.26 33.3 0.64 34.2 0 10−4 0.26 60.95 0.49 61.7 0 −1 10 4.1 5 3.89 12.99 0 −2 10 17.86 17.86 1.25 36.97 0 10−3 4.14 37.49 0.62 42.25 0 −4 10 4.05 64.56 0.48 69.09 0 −1 10 22.03 7.31 3.96 33.3 0 10−2 22.01 13.26 1.26 36.53 0 −3 10 22.21 43.34 0.63 66.18 0 10−4 22.16 72.01 0.48 94.65 0 −1 10 4.67 0.91 4.02 9.6 0 −2 10 76.7 52.26 1.26 130.22 0 10−3 76.7 52.26 0.64 129.6 0 −4 10 76.85 81.31 0.48 158.64 0 esta tabla se utilizo uuna matriz de 8540x8540 Conclusion Haciendo uso del la factorización incompleta ILU (`, τ ), se puede observar que se obtiene una mejor convergencia a medida que se incrementa el parámetro ` y disminuye el parámetro τ , esto debido a que la matriz obtenida al variar estos parámetros es mas densa, a su ves implica menos iteraciones al momento de usar el método del gradiente precondicionado para obtener una solución aproximada del sistema. References [1] David Hysom and Alex Pothen, “Level-Based incomplete LU factorization: Graph model and algorithms ”, SIAM Journal On Matrix Analysis and Applications, November 2002. [2] Saad Youcef, “Iterative Method for Linear System”, University of Minnesota. [3] Jennifer Scott and Mirolav tůma, ”The importance of structure in algebraic preconditioners ”, Science and Technology Facilities Council, January 2010. 14 [4] Saad Youcef, “ILUT: A dual threshold incomplete LU factorization”, University of Minnesota. 15