All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cern.colt.matrix.tdouble.algo.solver.preconditioner.DoubleILU Maven / Gradle / Ivy

Go to download

Parallel Colt is a multithreaded version of Colt - a library for high performance scientific computing in Java. It contains efficient algorithms for data analysis, linear algebra, multi-dimensional arrays, Fourier transforms, statistics and histogramming.

The newest version!
/*
 * Copyright (C) 2003-2006 Bjørn-Ove Heimsund
 * 
 * This file is part of MTJ.
 * 
 * This library is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by the
 * Free Software Foundation; either version 2.1 of the License, or (at your
 * option) any later version.
 * 
 * This library is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
 * for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library; if not, write to the Free Software Foundation,
 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

package cern.colt.matrix.tdouble.algo.solver.preconditioner;

import cern.colt.matrix.tdouble.DoubleMatrix1D;
import cern.colt.matrix.tdouble.DoubleMatrix2D;
import cern.colt.matrix.tdouble.impl.DenseDoubleMatrix1D;
import cern.colt.matrix.tdouble.impl.SparseRCDoubleMatrix2D;

/**
 * ILU(0) preconditioner using a compressed row matrix as internal storage
 */
public class DoubleILU implements DoublePreconditioner {

    /**
     * Factorisation matrix
     */
    private SparseRCDoubleMatrix2D LU;

    /**
     * Temporary vector for solving the factorised system
     */
    private final DoubleMatrix1D y;

    private int[] diagind;

    private final int n;

    /**
     * Sets up the ILU preconditioner
     * 
     * @param n
     *            Problem size (number of rows)
     */
    public DoubleILU(int n) {
        this.n = n;
        y = new DenseDoubleMatrix1D(n);
    }

    public DoubleMatrix1D apply(DoubleMatrix1D b, DoubleMatrix1D x) {
        if (x == null) {
            x = b.like();
        }

        // Ly = b, y = L\b
        lowerUnitSolve(b, y);

        // Ux = L\b = y
        return upperSolve(y, x);
    }

    public DoubleMatrix1D transApply(DoubleMatrix1D b, DoubleMatrix1D x) {
        if (x == null) {
            x = b.like();
        }

        // U'y = b, y = U'\b
        upperTransSolve(b, y);

        // L'x = U'\b = y
        return loverUnitTransSolve(y, x);
    }

    public void setMatrix(DoubleMatrix2D A) {
        if (A.rows() != n) {
            throw new IllegalArgumentException("A.rows() != n");
        }
        LU = new SparseRCDoubleMatrix2D(n, n);
        LU.assign(A);
        if (!LU.hasColumnIndexesSorted()) {
            LU.sortColumnIndexes();
        }
        factor();
    }

    private void factor() {

        // Internal CRS matrix storage
        int[] colind = LU.getColumnIndexes();
        int[] rowptr = LU.getRowPointers();
        double[] data = LU.getValues();

        // Find the indexes to the diagonal entries
        diagind = findDiagonalIndexes(n, colind, rowptr);

        // Go down along the main diagonal
        for (int k = 1; k < n; ++k)
            for (int i = rowptr[k]; i < diagind[k]; ++i) {

                // Get the current diagonal entry
                int index = colind[i];
                double LUii = data[diagind[index]];

                if (LUii == 0)
                    throw new RuntimeException("Zero pivot encountered on row " + (i + 1) + " during ILU process");

                // Elimination factor
                double LUki = (data[i] /= LUii);

                // Traverse the sparse row i, reducing on row k
                for (int j = diagind[index] + 1, l = rowptr[k] + 1; j < rowptr[index + 1]; ++j) {

                    while (l < rowptr[k + 1] && colind[l] < colind[j])
                        l++;

                    if (colind[l] == colind[j])
                        data[l] -= LUki * data[j];
                }
            }

    }

    private int[] findDiagonalIndexes(int m, int[] colind, int[] rowptr) {
        int[] diagind = new int[m];

        for (int k = 0; k < m; ++k) {
            diagind[k] = cern.colt.Sorting.binarySearchFromTo(colind, k, rowptr[k], rowptr[k + 1] - 1);

            if (diagind[k] < 0)
                throw new RuntimeException("Missing diagonal entry on row " + (k + 1));
        }

        return diagind;
    }

    private DoubleMatrix1D lowerUnitSolve(DoubleMatrix1D b, DoubleMatrix1D x) {
        double[] bd = ((DenseDoubleMatrix1D) b).elements();
        double[] xd = ((DenseDoubleMatrix1D) x).elements();
        int[] colind = LU.getColumnIndexes();
        int[] rowptr = LU.getRowPointers();
        double[] data = LU.getValues();
        int rows = LU.rows();
        for (int i = 0; i < rows; ++i) {

            // xi = bi - sum[j= 0; --i)

            // At this stage, x[i] is known, so move it over to the right hand
            // side for the remaining equations
            for (int j = rowptr[i]; j < diagind[i]; ++j)
                xd[colind[j]] -= data[j] * xd[i];

        return x;
    }

    private DoubleMatrix1D upperSolve(DoubleMatrix1D b, DoubleMatrix1D x) {
        double[] bd = ((DenseDoubleMatrix1D) b).elements();
        double[] xd = ((DenseDoubleMatrix1D) x).elements();
        int[] colind = LU.getColumnIndexes();
        int[] rowptr = LU.getRowPointers();
        double[] data = LU.getValues();
        int rows = LU.rows();
        for (int i = rows - 1; i >= 0; --i) {

            // xi = (bi - sum[j>i] Uij * xj) / Uii
            double sum = 0;
            for (int j = diagind[i] + 1; j < rowptr[i + 1]; ++j)
                sum += data[j] * xd[colind[j]];

            xd[i] = (bd[i] - sum) / data[diagind[i]];
        }

        return x;
    }

    private DoubleMatrix1D upperTransSolve(DoubleMatrix1D b, DoubleMatrix1D x) {
        x.assign(b);
        double[] xd = ((DenseDoubleMatrix1D) x).elements();
        int[] colind = LU.getColumnIndexes();
        int[] rowptr = LU.getRowPointers();
        double[] data = LU.getValues();
        int rows = LU.rows();

        for (int i = 0; i < rows; ++i) {

            // Solve for the current entry
            xd[i] /= data[diagind[i]];

            // Move this known solution over to the right hand side for the
            // remaining equations
            for (int j = diagind[i] + 1; j < rowptr[i + 1]; ++j)
                xd[colind[j]] -= data[j] * xd[i];
        }

        return x;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy