/*****************************************************************************1*2* Elmer, A Finite Element Software for Multiphysical Problems3*4* Copyright 1st April 1995 - , CSC - IT Center for Science Ltd., Finland5*6* This library is free software; you can redistribute it and/or7* modify it under the terms of the GNU Lesser General Public8* License as published by the Free Software Foundation; either9* version 2.1 of the License, or (at your option) any later version.10*11* This library is distributed in the hope that it will be useful,12* but WITHOUT ANY WARRANTY; without even the implied warranty of13* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU14* Lesser General Public License for more details.15*16* You should have received a copy of the GNU Lesser General Public17* License along with this library (in file ../LGPL-2.1); if not, write18* to the Free Software Foundation, Inc., 51 Franklin Street,19* Fifth Floor, Boston, MA 02110-1301 USA20*21*****************************************************************************/2223/*******************************************************************************24*25* LU decomposition.26*27*******************************************************************************28*29* Author: Juha Ruokolainen30*31* Address: CSC - IT Center for Science Ltd.32* Keilaranta 14, P.O. BOX 40533* 02101 Espoo, Finland34* Tel. +358 0 457 272335* Telefax: +358 0 457 230236* EMail: [email protected]37*38* Date: 30 May 199639*40* Modified by:41*42* Date of modification:43*44******************************************************************************/45/***********************************************************************46|47| LU.C - Last Edited 8. 8. 198848|49***********************************************************************/5051/*======================================================================52|Syntax of the manual pages:53|54|FUNCTION NAME(...) params ...55|56$ usage of the function and type of the parameters57? explain the effects of the function58= return value and the type of value if not of type int59@ globals effected directly by this routine60! current known bugs or limitations61& functions called by this function62~ these functions may interest you as an alternative function or63| because they control this function somehow64^=====================================================================*/656667/*68* $Id: lu.c,v 1.1.1.1 2005/04/14 13:29:14 vierinen Exp $69*70* $Log: lu.c,v $71* Revision 1.1.1.1 2005/04/14 13:29:14 vierinen72* initial matc automake package73*74* Revision 1.2 1998/08/01 12:34:45 jpr75*76* Added Id, started Log.77*78*79*/8081#include "elmer/matc.h"8283#define A(i,j) a[n * (i) + (j)]8485VARIABLE *mtr_LUD(VARIABLE *var)86{87VARIABLE *res;88int i, n, *pivot;89double *a;9091if (NCOL(var) != NROW(var))92{93error("LUD: Matrix must be square.\n");94}9596res = var_temp_copy(var);97a = MATR(res); n = NROW(res);9899pivot = (int *)ALLOCMEM(n * sizeof(int));100101LUDecomp(a, n, pivot);102103FREEMEM((char *)pivot);104105return res;106}107108VARIABLE *mtr_det(VARIABLE *var)109{110VARIABLE *tmp, *res;111int i, n, *pivot;112double det, *a;113114if (NCOL(var) != NROW(var))115{116error("Det: Matrix must be square.\n");117}118119tmp = var_temp_copy(var);120121a = MATR(tmp); n = NROW(tmp);122123pivot = (int *)ALLOCMEM(n * sizeof(int));124125LUDecomp(a, n, pivot);126127det = 1.0;128for(i = 0; i < n; i++)129{130det *= A(i,i);131if (pivot[i] != i) det = -det;132}133134FREEMEM((char *)pivot); var_delete_temp(tmp);135136res = var_temp_new(TYPE_DOUBLE,1,1);137138M(res,0,0) = det;139140return res;141}142143VARIABLE *mtr_inv(VARIABLE *var)144{145VARIABLE *ptr;146147int i, j , k, n, *pivot;148double s, *a;149150if (NCOL(var) != NROW(var))151{152error("Inv: Matrix must be square.\n");153}154155ptr = var_temp_copy(var);156157a = MATR(ptr); n = NROW(ptr);158159pivot = (int *)ALLOCMEM(n * sizeof(int));160161/*162* AP = LU163*/164LUDecomp(a, n, pivot);165for(i = 0; i < n; i++)166{167if (A(i,i) == 0)168error("Inv: Matrix is singular.\n");169A(i,i) = 1.0 / A(i,i);170}171172/*173* INV(U)174*/175for(i = n - 2; i >= 0; i--)176for(j = n - 1; j > i; j--)177{178s = -A(i,j);179for(k = i+1; k<j; k++)180s = s - A(i,k) * A(k,j);181A(i,j) = s;182}183184/*185* INV(L)186*/187for(i = n - 2; i >= 0; i--)188for(j = n - 1; j > i; j--)189{190s = 0.0;191for(k = i + 1; k <= j; k++)192s = s - A(j,k) * A(k,i);193A(j,i) = A(i,i) * s;194}195196/*197* A = INV(AP)198*/199for(i = 0; i < n; i++)200for(j = 0; j < n; j++)201{202s = 0.0;203for(k = max(i,j); k < n; k++)204if (k != i)205s += A(i,k) * A(k,j);206else207s += A(k,j);208A(i,j) = s;209}210211/*212* A = INV(A) (at last)213*/214for(i = n-1; i >= 0; i--)215if (pivot[i] != i)216for(j = 0; j < n; j++)217{218s = A(i,j);219A(i,j) = A(pivot[i],j);220A(pivot[i],j) = s;221}222223224FREEMEM((char *)pivot);225226return ptr;227}228229/*230* LU- decomposition by gaussian elimination. Row pivoting is used.231*232* result : AP = L'U ; L' = LD; pivot[i] is the swapped column233* number for column i (for pivoting).234*235* Result is stored in place of original matrix.236*237*/238void LUDecomp(double *a, int n, int pivot[])239{240double swap;241int i, j, k, l;242243for (i = 0; i<n; i++)244{245j = i;246for(k=i+1; k<n; k++)247if (abs(A(i,k)) > abs(A(i,j))) j = k;248249if (A(i,j) == 0.0)250{251error("LUDecomp: Matrix is singular.\n");252}253254pivot[i] = j;255256if (j != i)257{258for(k=0; k<=i; k++ )259{260swap = A(k,i);261A(k,i) = A(k,j);262A(k,j) = swap;263}264}265266for(k = i + 1; k < n; k++)267A(i,k) = A(i,k) / A(i,i);268269for(k = i+1; k<n; k++)270{271if (j != i)272{273swap = A(k,i);274A(k,i) = A(k,j);275A(k,j) = swap;276}277for(l = i + 1; l < n; l++)278A(k,l) = A(k,l) - A(i,l) * A(k,i);279}280}281282pivot[n - 1] = n - 1;283if ( A(n-1,n-1) == 0.0)284{285error("LUDecomp: Matrix is singular.\n");286}287}288289290