/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
package amgframework;
import amgframework.SparseMatrix.IConnection;
/**
*
* @author mrupp
*/
public class LU
{
class DenseMatrix
{
double[] values;
int rows, cols;
void resize(int rows, int cols)
{
values = new double[rows*cols];
this.rows = rows;
this.cols = cols;
}
void set(int r, int c, double v)
{
assert(r >= 0 && r < rows && c >= 0 && c < cols );
values[r*cols+c] = v;
}
double get(int r, int c)
{
assert(r >= 0 && r < rows && c >= 0 && c < cols );
return values[r*cols+c];
}
int num_rows() { return rows; }
int num_cols() { return cols; }
}
DenseMatrix A;
boolean init(SparseMatrix M)
{
assert(M.num_rows() == M.num_cols());
A = new DenseMatrix();
A.resize(M.num_rows(), M.num_rows());
for(int r=0; r<M.num_rows(); r++)
for(IConnection con : M.row(r))
A.set(r, con.index(), con.value());
for(int i=0; i<A.num_rows(); i++)
{
if(Math.abs(A.get(i,i)) < 1e-10)
return false;
for(int k=0; k<i; k++)
{
// add row k to row i by A(i, .) -= A(k,.) A(i,k) / A(k,k)
// so that A(i,k) is zero (elements A(i, <k) are already "zero")
// safe A(i,k)/A(k,k) in A(i,k)
double a_ik = A.get(i,k) / A.get(k,k);
A.set(i,k, a_ik);
for(int j=k+1; j<A.num_rows(); j++)
A.set(i,j, A.get(i,j) - A.get(k,j) * a_ik);
}
}
return true;
}
void solve(Vector x, Vector b)
{
x.assign(1.0, b);
// LU x = b, -> U x = L^{-1} b
// solve lower left
double s;
for(int i=0; i<A.num_rows(); i++)
{
s = x.values[i];
for(int k=0; k<i; k++)
s -= A.get(i, k)*x.values[k];
x.values[i] = s;
}
// -> x = U^{-1} (L^{-1} b)
// solve upper right
for(int i=A.num_rows()-1; ; i--)
{
s = x.values[i];
for(int k=i+1; k<A.num_rows(); k++)
s -= A.get(i, k)*x.values[k];
x.values[i] = s/A.get(i,i);
if(i==0) break;
}
}
}