diff --git a/BaseLib/TemplateLogogFormatterSuppressedGCC.h b/BaseLib/TemplateLogogFormatterSuppressedGCC.h
new file mode 100644
index 0000000000000000000000000000000000000000..6fa00e00405d731a581f6e9e9e5041285624368e
--- /dev/null
+++ b/BaseLib/TemplateLogogFormatterSuppressedGCC.h
@@ -0,0 +1,40 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file TemplateLogogFormatterSuppressedGCC.h
+ *
+ * Created on 2012-12-06 by Norihiro Watanabe
+ */
+
+#ifndef TEMPLATELOGOGFORMATTERSUPPRESSEDGCC_H_
+#define TEMPLATELOGOGFORMATTERSUPPRESSEDGCC_H_
+
+// ** INCLUDES **
+#include "logog/include/logog.hpp"
+
+namespace BaseLib {
+
+/**
+ * \brief TemplateLogogFormatterSuppressedGCC strips topics given as a template
+ * parameter from logog::FormatterGCC.
+ * See http://johnwbyrd.github.com/logog/customformatting.html for details.
+ **/
+template <int T_SUPPPRESS_TOPIC_FLAG>
+class TemplateLogogFormatterSuppressedGCC : public logog::FormatterGCC
+{
+
+	virtual TOPIC_FLAGS GetTopicFlags( const logog::Topic &topic )
+	{
+	return ( logog::Formatter::GetTopicFlags( topic ) &
+		~( T_SUPPPRESS_TOPIC_FLAG ));
+	}
+
+};
+
+#endif // TEMPLATELOGOGFORMATTERSUPPRESSEDGCC_H_
+
+} // namespace BaseLib
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 384eb58798739aa1409a429cf7fd2b6f9c3b4f15..08dae53b6abe21e9aaa5341860a308b5c1292b83 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -55,6 +55,9 @@ OPTION(OGS_BUILD_UTILS "Should the utilities programms be built?" OFF)
 
 OPTION(OGS_NO_EXTERNAL_LIBS "Builds OGS without any external dependencies." OFF)
 
+# Linear solvers
+OPTION(OGS_USE_LIS "Use Lis" OFF)
+
 # Logging
 OPTION(OGS_DISABLE_LOGGING "Disables all logog messages." OFF)
 
@@ -98,6 +101,10 @@ INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/ThirdParty )
 INCLUDE_DIRECTORIES( ${CMAKE_SOURCE_DIR}/ThirdParty/quickcheck )
 INCLUDE_DIRECTORIES( ${CMAKE_BINARY_DIR}/ThirdParty/zlib )
 
+IF(OGS_USE_LIS)
+    ADD_DEFINITIONS(-DUSE_LIS)
+ENDIF()
+
 ADD_SUBDIRECTORY( BaseLib )
 # TODO This is a hack but we have to make sure that Boost is built first
 ADD_DEPENDENCIES(BaseLib Boost)
diff --git a/MathLib/CMakeLists.txt b/MathLib/CMakeLists.txt
index f6e6b904d90f458a98bd38fd575b55ff24e3103b..1e42e687a7934791f5246e507954ae6cf83539a2 100644
--- a/MathLib/CMakeLists.txt
+++ b/MathLib/CMakeLists.txt
@@ -20,6 +20,16 @@ SET ( SOURCES ${SOURCES} ${SOURCES_LINALG_SOLVERS})
 GET_SOURCE_FILES(SOURCES_LINALG_PRECOND LinAlg/Preconditioner)
 SET ( SOURCES ${SOURCES} ${SOURCES_LINALG_PRECOND})
 
+GET_SOURCE_FILES(SOURCES_LINALG_LEQS LinAlg/SystemOfLinearEquations)
+IF (NOT OGS_USE_LIS)
+    LIST(REMOVE_ITEM SOURCES_LINALG_LEQS 
+        LinAlg/SystemOfLinearEquations/LisOption.h
+        LinAlg/SystemOfLinearEquations/LisOption.cpp
+        LinAlg/SystemOfLinearEquations/LisLinearSystem.h
+        LinAlg/SystemOfLinearEquations/LisLinearSystem.cpp
+    )
+ENDIF ()
+SET ( SOURCES ${SOURCES} ${SOURCES_LINALG_LEQS})
 
 IF (METIS_FOUND)
 	GET_SOURCE_FILES(SOURCES_LINALG_SPARSE_NESTEDDISSECTION LinAlg/Sparse/NestedDissectionPermutation)
@@ -38,8 +48,17 @@ IF(METIS_FOUND)
 	)
 ENDIF()
 
+IF (LIS_FOUND)
+    INCLUDE_DIRECTORIES(${LIS_INCLUDE_DIR})
+ENDIF()
+
+
 # Create the library
 ADD_LIBRARY( MathLib STATIC ${SOURCES} )
 
 SET_TARGET_PROPERTIES(MathLib PROPERTIES LINKER_LANGUAGE CXX)
 
+IF (LIS_FOUND)
+    TARGET_LINK_LIBRARIES( MathLib ${LIS_LIBRARIES} )
+ENDIF()
+
diff --git a/MathLib/LinAlg/Sparse/Sparsity.h b/MathLib/LinAlg/Sparse/Sparsity.h
new file mode 100644
index 0000000000000000000000000000000000000000..63d5ca099938b4c4735034e7a9535063b3315a74
--- /dev/null
+++ b/MathLib/LinAlg/Sparse/Sparsity.h
@@ -0,0 +1,29 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file Sparsity.h
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#ifndef SPARSITY_H_
+#define SPARSITY_H_
+
+#include <vector>
+#include <set>
+
+namespace MathLib 
+{
+
+/**
+ * \brief Row-major sparse pattern
+ */
+typedef std::vector<std::set<std::size_t> > RowMajorSparsity;
+
+} //MathLib
+
+#endif // SPARSITY_H_
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.h b/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.h
new file mode 100644
index 0000000000000000000000000000000000000000..750002822ad378d8db3446b6ab918013cf951b13
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.h
@@ -0,0 +1,202 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file ISystemOfLinearEquations.h
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#ifndef ISYSTEMOFLINEAREQUATIONS_H_
+#define ISYSTEMOFLINEAREQUATIONS_H_
+
+#include <iostream>
+#include <vector>
+#include <boost/property_tree/ptree.hpp>
+#include "MathLib/LinAlg/Sparse/Sparsity.h"
+
+namespace MathLib
+{
+
+/**
+ * \brief Interface to any system of linear equations Ax=b
+ *
+ * This class defines unified interface to a system of linear equations
+ * including linear solvers.
+ *
+ */
+class ISystemOfLinearEquations
+{
+public:
+    /// Index representing invalid
+    const static std::size_t index_npos = -1;
+
+    /// 
+    virtual ~ISystemOfLinearEquations()
+    {
+    }
+
+    /**
+     * set properties
+     *
+     * @param option
+     */
+    virtual void setOption(const boost::property_tree::ptree &option) = 0;
+
+    /**
+     * initialize this system with zero
+     *
+     * This function initialize the system by setting zero to all entries in
+     * a matrix, a RHS vector and solution vector. Dimension of the system is
+     * not changed.
+     */
+    virtual void setZero() = 0;
+
+    /// return dimension of this equation
+    virtual std::size_t getDimension() const = 0;
+
+    /**
+     * set an entry in a matrix
+     *
+     * @param rowId
+     * @param colId
+     * @param v
+     */
+    virtual void setMatEntry(std::size_t rowId, std::size_t colId, double v) = 0;
+
+    /**
+     * add a value into a matrix
+     *
+     * @param rowId
+     * @param colId
+     * @param v
+     */
+    virtual void addMatEntry(std::size_t rowId, std::size_t colId, double v) = 0;
+
+    /**
+     * add a sub-matrix into a matrix at given row and column positions
+     *
+     * @param vec_row_pos
+     *  A vector of global row index. The number of entries of vec_row_pos have
+     *  to be identical to the number of rows of the local matrix.
+     * @param vec_col_pos
+     *  A vector of global column index. The number of vec_col_pos have to be
+     *  identical to the number of columns of the local matrix.
+     * @param sub_matrix    A sub-matrix
+     * @param fac           scaling parameter
+     */
+    template <class T_DENSE_MATRIX>
+    void addSubMat(const std::vector<std::size_t> &vec_row_pos,
+            const std::vector<std::size_t> &vec_col_pos,
+            const T_DENSE_MATRIX &sub_matrix, double fac = 1.0);
+
+    /**
+     * add a sub-matrix into a matrix
+     *
+     * @param vec_row_col_pos
+     *  A vector of global row and column index. The number of entries of
+     *  vec_row_col_pos have to be identical to the number of rows and columns
+     *  of the local matrix.
+     * @param sub_matrix        A sub-matrix
+     * @param fac               scaling parameter
+     */
+    template <class T_DENSE_MATRIX>
+    void addSubMat(const std::vector<std::size_t> &vec_row_col_pos,
+            const T_DENSE_MATRIX &sub_matrix, double fac = 1.0);
+
+    /**
+     * get RHS entry
+     *
+     * @param rowId
+     * @return
+     */
+    virtual double getRHSVec(std::size_t rowId) const = 0;
+
+    /**
+     * set RHS entry
+     *
+     * @param rowId
+     * @param v
+     */
+    virtual void setRHSVec(std::size_t rowId, double v) = 0;
+
+    /**
+     * add RHS entry
+     *
+     * @param rowId
+     * @param v
+     */
+    virtual void addRHSVec(std::size_t rowId, double v) = 0;
+
+    /**
+     * add a sub vector to RHS
+     *
+     * @param vec_row_pos
+     *  A vector of global row index. The number of entries of vec_row_pos
+     *  have to be identical to the number of rows of the sub vector.
+     * @param sub_vector
+     *  Pointer to a sub-vector. Its length must be the same as the length of vec_row_pos.
+     * @param fac
+     *  Scaling parameter. Default value is 1.
+     */
+    inline virtual void addSubRHS(const std::vector<std::size_t> &vec_row_pos,
+            const double* sub_vector, double fac = 1.0);
+
+    /**
+     * add a sub vector to RHS
+     *
+     * @param vec_row_pos
+     *  A vector of global row index. The number of entries of vec_row_pos
+     *  have to be identical to the number of rows of the sub vector.
+     * @param sub_vector    A sub-vector
+     * @param fac           Scaling parameter
+     */
+    template <class T_DENSE_VECTOR>
+    void addSubRHS(const std::vector<std::size_t> &vec_row_pos,
+            const T_DENSE_VECTOR &sub_vector, double fac = 1.0);
+
+    /**
+     * get an entry in a solution vector
+     * @param rowId
+     * @return
+     */
+    virtual double getSolVec(std::size_t rowId) = 0;
+
+    /**
+     * set an entry in a solution vector
+     * @param rowId
+     * @param v
+     */
+    virtual void setSolVec(std::size_t rowId, double v) = 0;
+
+    /**
+     * set prescribed value
+     * @param row_id
+     * @param x
+     */
+    virtual void setKnownSolution(std::size_t row_id, double x) = 0;
+
+    /**
+     * set prescribed value
+     * @param vec_id    A vector of global row index
+     * @param vec_x     A vector of prescribed values
+     */
+    virtual void setKnownSolution(const std::vector<std::size_t> &vec_id,
+            const std::vector<double> &vec_x) = 0;
+
+    /// solve the linear system
+    virtual void solve() = 0;
+
+    /// print out the equation for debugging
+    virtual void printout(std::ostream &os = std::cout) const = 0;
+
+};
+
+}
+
+#include "ISystemOfLinearEquations.tpp"
+
+#endif //ISYSTEMOFLINEAREQUATIONS_H_
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.tpp b/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.tpp
new file mode 100644
index 0000000000000000000000000000000000000000..627ed4b4e45b13810897f88eb6bd69889aeb6a6e
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/ISystemOfLinearEquations.tpp
@@ -0,0 +1,63 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file ISystemOfLinearEquations.tpp
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#ifndef ISYSTEMOFLINEAREQUATIONS_TPP_
+#define ISYSTEMOFLINEAREQUATIONS_TPP_
+
+namespace MathLib
+{
+
+template <class T_DENSE_MATRIX>
+void ISystemOfLinearEquations::addSubMat(const std::vector<std::size_t> &vec_row_pos, const std::vector<std::size_t> &vec_col_pos, const T_DENSE_MATRIX &sub_matrix, double fkt)
+{
+    const std::size_t n_rows = vec_row_pos.size();
+    const std::size_t n_cols = vec_col_pos.size();
+    for (std::size_t i=0; i<n_rows; i++) {
+        const std::size_t rowId = vec_row_pos[i];
+        if (rowId==index_npos) continue;
+        for (std::size_t j=0; j<n_cols; j++) {
+            const std::size_t colId = vec_col_pos[j];
+            if (colId==index_npos) continue;
+            addMatEntry(rowId, colId, fkt*sub_matrix(i,j));
+        }
+    }
+}
+
+template <class T_DENSE_MATRIX>
+void ISystemOfLinearEquations::addSubMat(const std::vector<std::size_t> &vec_pos, const T_DENSE_MATRIX &sub_matrix, double fkt)
+{
+    addSubMat(vec_pos, vec_pos, sub_matrix, fkt);
+}
+
+inline void ISystemOfLinearEquations::addSubRHS(const std::vector<std::size_t> &vec_row_pos, const double *sub_vector, double fkt)
+{
+    for (std::size_t i=0; i<vec_row_pos.size(); i++) {
+        const std::size_t rowId = vec_row_pos[i];
+        if (rowId==index_npos) continue;
+        addRHSVec(rowId, sub_vector[i]*fkt);
+    }
+}
+
+template <class T_DENSE_VECTOR>
+void ISystemOfLinearEquations::addSubRHS(const std::vector<std::size_t> &vec_row_pos, const T_DENSE_VECTOR &sub_vector, double fkt)
+{
+    for (std::size_t i=0; i<vec_row_pos.size(); i++) {
+        const std::size_t rowId = vec_row_pos[i];
+        if (rowId==index_npos) continue;
+        addRHSVec(rowId, sub_vector(i)*fkt);
+    }
+}
+
+}
+
+#endif //ISYSTEMOFLINEAREQUATIONS_TPP_
+
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.cpp b/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..3c24746b71f07a2e618c7decd74539f3dfc0e583
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.cpp
@@ -0,0 +1,189 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file LisLinearSystem.cpp
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#include "LisLinearSystem.h"
+
+#include <string>
+#include <sstream>
+#ifdef _OPENMP
+#include <omp.h>
+#endif
+#include "logog/include/logog.hpp"
+
+namespace MathLib
+{
+
+bool LisLinearSystem::checkError(int err)
+{
+    bool ok = (err == LIS_SUCCESS);
+    if (!ok) {
+        ERR("***ERROR: Lis error code = %d", err);
+    }
+    return ok;
+}
+
+LisLinearSystem::LisLinearSystem(std::size_t dimension)
+: _dim(dimension), _max_diag_coeff(.0)
+{
+    int ierr = 0;
+    ierr = lis_matrix_create(0, &_AA); checkError(ierr);
+    ierr = lis_matrix_set_size(_AA, 0, dimension); checkError(ierr);
+    ierr = lis_vector_duplicate(_AA, &_bb); checkError(ierr);
+    ierr = lis_vector_duplicate(_AA, &_xx); checkError(ierr);
+}
+
+LisLinearSystem::~LisLinearSystem()
+{
+    int ierr = 0;
+    ierr = lis_matrix_destroy(_AA); checkError(ierr);
+    ierr = lis_vector_destroy(_bb); checkError(ierr);
+    ierr = lis_vector_destroy(_xx); checkError(ierr);
+}
+
+void LisLinearSystem::setOption(const boost::property_tree::ptree &option)
+{
+    using boost::property_tree::ptree;
+
+    boost::optional<ptree> ptSolver = option.get_child("LinearSolver");
+    if (!ptSolver)
+        return;
+
+    boost::optional<std::string> solver_type = ptSolver->get_optional<std::string>("solver_type");
+    if (solver_type) {
+        _option.solver_type = _option.getSolverType(*solver_type);
+    }
+    boost::optional<std::string> precon_type = ptSolver->get_optional<std::string>("precon_type");
+    if (precon_type) {
+        _option.precon_type = _option.getPreconType(*precon_type);
+    }
+    boost::optional<std::string> matrix_type = ptSolver->get_optional<std::string>("matrix_type");
+    if (matrix_type) {
+        _option.matrix_type = _option.getMatrixType(*matrix_type);
+    }
+    boost::optional<double> error_tolerance = ptSolver->get_optional<double>("error_tolerance");
+    if (error_tolerance) {
+        _option.error_tolerance = *error_tolerance;
+    }
+    boost::optional<int> max_iteration_step = ptSolver->get_optional<int>("max_iteration_step");
+    if (max_iteration_step) {
+        _option.max_iterations = *max_iteration_step;
+    }
+}
+
+void LisLinearSystem::setZero()
+{
+    int ierr = 0;
+    // A matrix has to be removed and created every time because Lis doesn't provide a
+    // function to set matrix entries to zero
+    ierr = lis_matrix_destroy(_AA); checkError(ierr);
+    ierr = lis_matrix_create(0, &_AA); checkError(ierr);
+    ierr = lis_matrix_set_size(_AA, 0, getDimension()); checkError(ierr);
+    // set zero RHS, x
+    ierr = lis_vector_set_all(0.0, _bb); checkError(ierr);
+    ierr = lis_vector_set_all(0.0, _xx); checkError(ierr);
+
+    _max_diag_coeff = .0;
+}
+
+void LisLinearSystem::applyKnownSolution()
+{
+    //Use penalty parameter
+    const double penalty_scaling = 1e+10;
+    const double penalty = _max_diag_coeff * penalty_scaling;
+    INFO("-> max. absolute value of diagonal entries = %e", _max_diag_coeff);
+    INFO("-> penalty scaling = %e", penalty_scaling);
+    const std::size_t n_bc = _vec_knownX_id.size();
+    for (std::size_t i_bc=0; i_bc<n_bc; i_bc++) {
+        const std::size_t rowId = _vec_knownX_id[i_bc];
+        const double x = _vec_knownX_x[i_bc];
+        //A(k, k) = penalty
+        setMatEntry(rowId, rowId, penalty);
+        //b(k) = x*penalty
+        setRHSVec(rowId, x*penalty);
+    }
+}
+
+void LisLinearSystem::solve()
+{
+    INFO("------------------------------------------------------------------");
+    INFO("*** LIS solver computation");
+#ifdef _OPENMP
+    INFO("-> max number of threads = %d", omp_get_num_procs());
+    INFO("-> number of threads = %d", omp_get_max_threads());
+#endif
+
+    applyKnownSolution();
+    // assemble a matrix
+    int ierr = 0;
+    ierr = lis_matrix_set_type(_AA, static_cast<int>(_option.matrix_type)); checkError(ierr);
+    ierr = lis_matrix_assemble(_AA); checkError(ierr);
+
+    // configure option
+    std::string solver_options;
+    if (_option.solver_precon_arg.empty()) {
+        std::stringstream ss;
+        ss << "-i " << static_cast<int>(_option.solver_type);
+        ss << " -p " << static_cast<int>(_option.precon_type);
+        if (!_option.extra_arg.empty())
+            ss << " " << _option.extra_arg;
+        solver_options = ss.str();
+    } else {
+        solver_options = _option.solver_precon_arg;
+    }
+    std::string tol_option;
+    {
+        std::stringstream ss;
+        ss << "-tol " << _option.error_tolerance;
+        ss << " -maxiter " << _option.max_iterations;
+        ss << " -initx_zeros 0"; //0: use given x as initial guess, 1: x0=0
+#ifdef _OPENMP
+        const int nthreads = omp_get_max_threads();
+        ss << " -omp_num_threads " << nthreads;
+#endif
+        tol_option = ss.str();
+    }
+
+    // Create solver
+    LIS_SOLVER solver;
+    ierr = lis_solver_create(&solver); checkError(ierr);
+    ierr = lis_solver_set_option(const_cast<char*>(solver_options.c_str()), solver); checkError(ierr);
+    ierr = lis_solver_set_option(const_cast<char*>(tol_option.c_str()), solver); checkError(ierr);
+    ierr = lis_solver_set_option(const_cast<char*>("-print mem"), solver); checkError(ierr);
+    
+    // solve
+    INFO("-> solve");
+    ierr = lis_solve(_AA, _bb, _xx, solver); checkError(ierr);
+    checkError(ierr);
+    //lis_output(_AA, _bb, _xx, LIS_FMT_MM, "/home/localadmin/tasks/20120814_ogs6test/matrix1.txt");
+
+    int iter = 0;
+    double resid = 0.0;
+    ierr = lis_solver_get_iters(solver, &iter); checkError(ierr);
+    ierr = lis_solver_get_residualnorm(solver, &resid); checkError(ierr);
+    INFO("\t iteration: %d/%ld\n", iter, _option.max_iterations);
+    INFO("\t residuals: %e\n", resid);
+
+    // Clear solver
+    ierr = lis_solver_destroy(solver); checkError(ierr);
+    INFO("------------------------------------------------------------------");
+}
+
+void LisLinearSystem::printout(std::ostream &os) const
+{
+    os << "#A=" << std::endl;
+    os << "#x=" << std::endl;
+    lis_vector_print(_xx);
+    os << "#b=" << std::endl;
+    lis_vector_print(_bb);
+}
+
+} //MathLib
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.h b/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.h
new file mode 100644
index 0000000000000000000000000000000000000000..8e038b3e43ba82010e397b3a413383676e6d95c3
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.h
@@ -0,0 +1,183 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file LisLinearSystem.h
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#ifndef LISLINEARSYSTEM_H_
+#define LISLINEARSYSTEM_H_
+
+#include <iostream>
+#include <string>
+#include <vector>
+#include <boost/property_tree/ptree.hpp>
+
+#include "lis.h"
+
+#include "LisOption.h"
+
+namespace MathLib
+{
+
+/**
+ * \brief Linear system using Lis solver (http://www.ssisc.org/lis/)
+ *
+ * This class utilizes Lis solver.
+ */
+class LisLinearSystem
+{
+public:
+    //---------------------------------------------------------------
+    // realization of ISystemOfLinearEquations
+    //---------------------------------------------------------------
+
+    /**
+     * Create a linear system using Lis
+     *
+     * @param length    System dimension
+     */
+    LisLinearSystem(std::size_t length);
+
+    /**
+     *
+     */
+    virtual ~LisLinearSystem();
+
+    /**
+     * configure linear solvers
+     * @param option
+     */
+    virtual void setOption(const boost::property_tree::ptree &option);
+
+    /// return the system dimension
+    virtual std::size_t getDimension() const { return _dim; };
+
+    /// reset this equation
+    virtual void setZero();
+
+    /// set entry in A
+    virtual void setMatEntry(std::size_t rowId, std::size_t colId, double v)
+    {
+        if (rowId==colId)
+            _max_diag_coeff = std::max(_max_diag_coeff, std::abs(v));
+        lis_matrix_set_value(LIS_INS_VALUE, rowId, colId, v, _AA);
+    }
+
+    /// add value into A
+    virtual void addMatEntry(std::size_t rowId, std::size_t colId, double v)
+    {
+        if (rowId==colId)
+            _max_diag_coeff = std::max(_max_diag_coeff, std::abs(v));
+        lis_matrix_set_value(LIS_ADD_VALUE, rowId, colId, v, _AA);
+    }
+
+    /// get RHS entry
+    virtual double getRHSVec(std::size_t rowId) const
+    {
+        double v;
+        lis_vector_get_value(_bb, rowId, &v);
+        return v;
+    }
+
+    /// set RHS entry
+    virtual void setRHSVec(std::size_t rowId, double v)
+    {
+        lis_vector_set_value(LIS_INS_VALUE, rowId, v, _bb);
+    }
+
+    /// add RHS entry
+    virtual void addRHSVec(std::size_t rowId, double v)
+    {
+        lis_vector_set_value(LIS_ADD_VALUE, rowId, v, _bb);
+    }
+
+    /// get an entry in a solution vector
+    virtual double getSolVec(std::size_t rowId)
+    {
+        double v;
+        lis_vector_get_value(_xx, rowId, &v);
+        return v;
+    }
+
+    /// set a solution vector
+    virtual void setSolVec(std::size_t rowId, double v)
+    {
+        lis_vector_set_value(LIS_INS_VALUE, rowId, v, _xx);
+    }
+
+    /// set prescribed value
+    virtual void setKnownSolution(std::size_t rowId, double x)
+    {
+        _vec_knownX_id.push_back(rowId);
+        _vec_knownX_x.push_back(x);
+    }
+
+    /// set prescribed values
+    virtual void setKnownSolution(const std::vector<std::size_t> &vec_id, const std::vector<double> &vec_x)
+    {
+        _vec_knownX_id.insert(_vec_knownX_id.end(), vec_id.begin(), vec_id.end());
+        _vec_knownX_x.insert(_vec_knownX_x.end(), vec_x.begin(), vec_x.end());
+    }
+
+    /// solve this equation
+    virtual void solve();
+
+    /// printout this equation for debugging
+    virtual void printout(std::ostream &os=std::cout) const;
+
+    //---------------------------------------------------------------
+    // specific to this class
+    //---------------------------------------------------------------
+    /**
+     * configure linear solvers
+     * @param option
+     */
+    void setOption(const LisOption &option)
+    {
+        _option = option;
+    }
+
+    /**
+     * get linear solver options
+     * @return
+     */
+    LisOption &getOption()
+    {
+        return _option;
+    }
+
+    /**
+     * get a solution vector
+     * @param x
+     */
+    void getSolVec(double* x)
+    {
+        lis_vector_gather(_xx, x);
+    }
+
+private:
+    bool checkError(int err);
+    void applyKnownSolution();
+
+private:
+    const std::size_t _dim;
+    double _max_diag_coeff;
+    LisOption _option;
+    LIS_MATRIX _AA;
+    LIS_VECTOR _bb;
+    LIS_VECTOR _xx;
+    std::vector<std::size_t> _vec_knownX_id;
+    std::vector<double> _vec_knownX_x;
+};
+
+
+} // MathLib
+
+#endif //LISLINEARSYSTEM_H_
+
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/LisOption.cpp b/MathLib/LinAlg/SystemOfLinearEquations/LisOption.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..8ee5d504b0932d7ef41b2be903afc0a6f692dd8f
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/LisOption.cpp
@@ -0,0 +1,100 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file LisOption.cpp
+ *
+ * Created on 2012-12-05 by Norihiro Watanabe
+ */
+
+#include "LisOption.h"
+
+namespace MathLib
+{
+
+LisOption::LisOption()
+{
+    solver_type = SolverType::CG;
+    precon_type = PreconType::NONE;
+    matrix_type = MatrixType::CRS;
+    max_iterations = 500;
+    error_tolerance = 1.e-10;
+}
+
+LisOption::SolverType LisOption::getSolverType(const std::string &solver_name)
+{
+#define RETURN_SOLVER_ENUM_IF_SAME_STRING(str, TypeName) \
+    if (#TypeName==str) return SolverType::TypeName;
+
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, CG);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCG);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, CGS);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCGSTAB);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCGSTABl);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, GPBiCG);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, TFQMR);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, Orthomin);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, GMRES);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, Jacobi);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, GaussSeidel);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, SOR);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCGSafe);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, CR);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCR);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, CRS);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCRSTAB);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, GPBiCR);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, BiCRSafe);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, FGMRESm);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, IDRs);
+    RETURN_SOLVER_ENUM_IF_SAME_STRING(solver_name, MINRES);
+
+    return SolverType::INVALID;
+#undef RETURN_SOLVER_ENUM_IF_SAME_STRING
+}
+
+LisOption::PreconType LisOption::getPreconType(const std::string &precon_name)
+{
+#define RETURN_PRECOM_ENUM_IF_SAME_STRING(str, TypeName) \
+    if (#TypeName==str) return PreconType::TypeName;
+
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, NONE);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, JACOBI);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, ILU);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, SSOR);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, Hybrid);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, IplusS);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, SAINV);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, SAAMG);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, CroutILU);
+    RETURN_PRECOM_ENUM_IF_SAME_STRING(precon_name, ILUT);
+
+    return PreconType::NONE;
+#undef RETURN_PRECOM_ENUM_IF_SAME_STRING
+}
+
+LisOption::MatrixType LisOption::getMatrixType(const std::string &matrix_name)
+{
+#define RETURN_MATRIX_ENUM_IF_SAME_STRING(str, TypeName) \
+    if (#TypeName==str) return MatrixType::TypeName;
+
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, CRS);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, CCS);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, MSR);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, DIA);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, ELL);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, JDS);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, BSR);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, BSC);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, VBR);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, COO);
+    RETURN_MATRIX_ENUM_IF_SAME_STRING(matrix_name, DNS);
+
+    return MatrixType::CRS;
+#undef RETURN_MATRIX_ENUM_IF_SAME_STRING
+}
+
+} //MathLib
diff --git a/MathLib/LinAlg/SystemOfLinearEquations/LisOption.h b/MathLib/LinAlg/SystemOfLinearEquations/LisOption.h
new file mode 100644
index 0000000000000000000000000000000000000000..704b38f80ee8b6d4087ed341cd93e86b493c9793
--- /dev/null
+++ b/MathLib/LinAlg/SystemOfLinearEquations/LisOption.h
@@ -0,0 +1,143 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.org)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.org/project/license
+ *
+ *
+ * \file LisOption.h
+ *
+ * Created on 2012-06-25 by Norihiro Watanabe
+ */
+
+#ifndef LIS_OPTION_H_
+#define LIS_OPTION_H_
+
+#include <string>
+
+namespace MathLib
+{
+
+/**
+ * \brief Option for Lis solver
+ */
+struct LisOption
+{
+    /// Solver type
+    enum class SolverType : int
+    {
+        INVALID = 0,
+        CG = 1,
+        BiCG = 2,
+        CGS = 3,
+        BiCGSTAB = 4,
+        BiCGSTABl = 5,
+        GPBiCG = 6,
+        TFQMR = 7,
+        Orthomin = 8,
+        GMRES = 9,
+        Jacobi = 10,
+        GaussSeidel = 11,
+        SOR = 12,
+        BiCGSafe = 13,
+        CR = 14,
+        BiCR = 15,
+        CRS = 16,
+        BiCRSTAB = 17,
+        GPBiCR = 18,
+        BiCRSafe = 19,
+        FGMRESm = 20,
+        IDRs = 21,
+        MINRES = 22
+    };
+
+    /// Preconditioner type
+    enum class PreconType : int
+    {
+        NONE = 0,
+        JACOBI = 1,
+        ILU = 2,
+        SSOR = 3,
+        Hybrid = 4,
+        IplusS = 5,
+        SAINV = 6,
+        SAAMG = 7,
+        CroutILU = 8,
+        ILUT = 9
+    };
+
+    /// Matrix type
+    enum class MatrixType : int
+    {
+        CRS = 1,
+        CCS = 2,
+        MSR = 3,
+        DIA = 4,
+        ELL = 5,
+        JDS = 6,
+        BSR = 7,
+        BSC = 8,
+        VBR = 9,
+        COO = 10,
+        DNS = 11
+    };
+
+    /// Linear solver type
+    SolverType solver_type;
+    /// Preconditioner type
+    PreconType precon_type;
+    /// Matrix type
+    MatrixType matrix_type;
+    /// Maximum iteration count
+    long max_iterations;
+    /// Error tolerance
+    double error_tolerance;
+    /// Extra option
+    std::string extra_arg;
+    /// Arguments for solver and preconditioner. This variable is always preferred
+    /// to other variables.
+    std::string solver_precon_arg;
+
+    /**
+     * Constructor
+     *
+     * Default options are CG, no preconditioner, iteration count 500 and
+     * tolerance 1e-10. Default matrix storage type is CRS.
+     */
+    LisOption();
+
+    /// Destructor
+    ~LisOption() {};
+
+    /**
+     * return a linear solver type from the solver name
+     *
+     * @param solver_name
+     * @return a linear solver type
+     *      If there is no solver type matched with the given name, INVALID
+     *      is returned.
+     */
+    static SolverType getSolverType(const std::string &solver_name);
+
+    /**
+     * return a preconditioner type from the name
+     *
+     * @param precon_name
+     * @return a preconditioner type
+     *      If there is no preconditioner type matched with the given name, NONE
+     *      is returned.
+     */
+    static PreconType getPreconType(const std::string &precon_name);
+
+    /**
+     * return a matrix type
+     * @param matrix_name
+     * @return
+     *      If there is no matrix type matched with the given name, CRS
+     *      is returned.
+     */
+    static MatrixType getMatrixType(const std::string &matrix_name);
+};
+
+}
+#endif //LIS_OPTION_H_
diff --git a/Tests/CMakeLists.txt b/Tests/CMakeLists.txt
index be2627dea1dfa4bc84baf0cd6f7b19a23cbff050..faee29a1ed283ab9c0b2ba96b1b92e4af193bd76 100644
--- a/Tests/CMakeLists.txt
+++ b/Tests/CMakeLists.txt
@@ -7,13 +7,19 @@ ENDIF()
 APPEND_SOURCE_FILES(TEST_SOURCES)
 APPEND_SOURCE_FILES(TEST_SOURCES BaseLib)
 APPEND_SOURCE_FILES(TEST_SOURCES GeoLib)
+APPEND_SOURCE_FILES(TEST_SOURCES MathLib)
 
 INCLUDE_DIRECTORIES(
 	${CMAKE_SOURCE_DIR}/Tests/gtest
 	${CMAKE_SOURCE_DIR}/BaseLib
 	${CMAKE_SOURCE_DIR}/GeoLib
+	${CMAKE_SOURCE_DIR}/MathLib
 )
 
+IF (LIS_FOUND)
+    INCLUDE_DIRECTORIES(${LIS_INCLUDE_DIR})
+ENDIF()
+
 ADD_EXECUTABLE (testrunner testrunner.cpp ${TEST_SOURCES})
 SET_TARGET_PROPERTIES(testrunner PROPERTIES FOLDER Testing)
 
@@ -21,6 +27,8 @@ TARGET_LINK_LIBRARIES(testrunner
 	GTest
 	BaseLib
 	GeoLib
+	MathLib
+	logog
 	${Boost_LIBRARIES}
 	${CMAKE_THREAD_LIBS_INIT}
 )
diff --git a/Tests/MathLib/TestLinearSystem.cpp b/Tests/MathLib/TestLinearSystem.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..dea1c61aa005a29bc10346f5933b80a0ae17ecc0
--- /dev/null
+++ b/Tests/MathLib/TestLinearSystem.cpp
@@ -0,0 +1,127 @@
+/**
+ * Copyright (c) 2012, OpenGeoSys Community (http://www.opengeosys.com)
+ *            Distributed under a Modified BSD License.
+ *              See accompanying file LICENSE.txt or
+ *              http://www.opengeosys.com/LICENSE.txt
+ *
+ *
+ * \file TestLinearSystem.cpp
+ *
+ * Created on 2012-08-03 by Norihiro Watanabe
+ */
+
+#include <gtest/gtest.h>
+#include <boost/property_tree/ptree.hpp>
+
+#include "MathLib/LinAlg/Sparse/Sparsity.h"
+#ifdef USE_LIS
+#include "MathLib/LinAlg/SystemOfLinearEquations/LisLinearSystem.h"
+#endif
+
+namespace
+{
+
+inline void ASSERT_DOUBLE_ARRAY_EQ(const double* Expected, const double* Actual, size_t N, double epsilon=1.0e-8) {
+    for (size_t i=0; i<N; i++) \
+        ASSERT_NEAR(Expected[i], Actual[i], epsilon);
+}
+
+struct Example1
+{
+    std::vector<double> mat;
+    std::vector<size_t> list_dirichlet_bc_id;
+    std::vector<double> list_dirichlet_bc_value;
+    static const size_t dim_eqs = 9;
+    std::vector<double> exH;
+    MathLib::RowMajorSparsity sparse;
+
+    Example1()
+    {
+        double d_mat[] = {
+            6.66667e-012, -1.66667e-012, 0, -1.66667e-012, -3.33333e-012, 0, 0, 0, 0, 
+            -1.66667e-012, 1.33333e-011, -1.66667e-012, -3.33333e-012, -3.33333e-012, -3.33333e-012, 0, 0, 0, 
+            0, -1.66667e-012, 6.66667e-012, 0, -3.33333e-012, -1.66667e-012, 0, 0, 0, 
+            -1.66667e-012, -3.33333e-012, 0, 1.33333e-011, -3.33333e-012, 0, -1.66667e-012, -3.33333e-012, 0, 
+            -3.33333e-012, -3.33333e-012, -3.33333e-012, -3.33333e-012, 2.66667e-011, -3.33333e-012, -3.33333e-012, -3.33333e-012, -3.33333e-012, 
+            0, -3.33333e-012, -1.66667e-012, 0, -3.33333e-012, 1.33333e-011, 0, -3.33333e-012, -1.66667e-012, 
+            0, 0, 0, -1.66667e-012, -3.33333e-012, 0, 6.66667e-012, -1.66667e-012, 0, 
+            0, 0, 0, -3.33333e-012, -3.33333e-012, -3.33333e-012, -1.66667e-012, 1.33333e-011, -1.66667e-012, 
+            0, 0, 0, 0, -3.33333e-012, -1.66667e-012, 0, -1.66667e-012, 6.66667e-012
+        };
+        mat.assign(d_mat, d_mat+dim_eqs*dim_eqs);
+        size_t int_dirichlet_bc_id[] = {2,5,8,0,3,6};
+        list_dirichlet_bc_id.assign(int_dirichlet_bc_id, int_dirichlet_bc_id+6);
+        list_dirichlet_bc_value.resize(6);
+        fill(list_dirichlet_bc_value.begin(), list_dirichlet_bc_value.begin()+3, .0);
+        fill(list_dirichlet_bc_value.begin()+3, list_dirichlet_bc_value.end(), 1.0);
+        exH.resize(9);
+        for (size_t i=0; i<9; i++) {
+            if (i%3==0) exH[i] = 1.0;
+            if (i%3==1) exH[i] = 0.5;
+            if (i%3==2) exH[i] = 0.;
+        }
+        sparse.resize(dim_eqs);
+        for (size_t i=0; i<dim_eqs; i++) {
+            for (size_t j=0; j<dim_eqs; j++) {
+                if (mat[i*dim_eqs+j]!=.0)
+                    sparse[i].insert(j);
+            }
+        }
+
+    }
+};
+}
+
+#ifdef USE_LIS
+TEST(Math, LinearSystemLis)
+{
+    // set a problem
+    Example1 ex1;
+
+    // create a linear system
+    MathLib::LisLinearSystem eqs(ex1.dim_eqs);
+
+    // construct
+    for (size_t i=0; i<ex1.dim_eqs; i++) {
+        for (size_t j=0; j<ex1.dim_eqs; j++) {
+            double v = ex1.mat[i*ex1.dim_eqs+j];
+            if (v!=.0)
+                eqs.addMatEntry(i, j, v);
+        }
+    }
+
+    // apply BC
+    eqs.setKnownSolution(ex1.list_dirichlet_bc_id, ex1.list_dirichlet_bc_value);
+
+    // set solver options using Boost property tree
+    boost::property_tree::ptree t_root;
+    boost::property_tree::ptree t_solver;
+    t_solver.put("solver_type", "CG");
+    t_solver.put("precon_type", "NONE");
+    t_solver.put("matrix_type", "CCS");
+    t_solver.put("error_tolerance", 1e-15);
+    t_solver.put("max_iteration_step", 1000);
+    t_root.put_child("LinearSolver", t_solver);
+    eqs.setOption(t_root);
+
+    // check if the option was correctly parsed
+    MathLib::LisOption &lisOption = eqs.getOption();
+    ASSERT_EQ(MathLib::LisOption::SolverType::CG, lisOption.solver_type);
+    ASSERT_EQ(MathLib::LisOption::PreconType::NONE, lisOption.precon_type);
+    ASSERT_EQ(MathLib::LisOption::MatrixType::CCS, lisOption.matrix_type);
+    ASSERT_EQ(1e-15, lisOption.error_tolerance);
+    ASSERT_EQ(1000, lisOption.max_iterations);
+
+    // solve
+    eqs.solve();
+
+//    eqs.printout();
+
+    // check solution
+    std::vector<double> vec_x(eqs.getDimension());
+    eqs.getSolVec(&vec_x[0]);
+    ASSERT_DOUBLE_ARRAY_EQ(&ex1.exH[0], &vec_x[0], ex1.dim_eqs, 1.e-5);
+}
+
+#endif
+
diff --git a/Tests/testrunner.cpp b/Tests/testrunner.cpp
index 3d3cf4f5fb858fff5ce1c51c12e98516eeb6126b..1aa85ef15b26b6e592b18f4c59fe4b82e8f1a75f 100644
--- a/Tests/testrunner.cpp
+++ b/Tests/testrunner.cpp
@@ -12,10 +12,43 @@
 
 // ** INCLUDES **
 #include "gtest/gtest.h"
+#include "logog/include/logog.hpp"
+#ifdef USE_LIS
+#include "lis.h"
+#endif
+#include "BaseLib/TemplateLogogFormatterSuppressedGCC.h"
 
 /// Implementation of the googletest testrunner
 int main(int argc, char* argv[])
 {
-	testing::InitGoogleTest ( &argc, argv );
-	return RUN_ALL_TESTS();
+    int ret = 0;
+    LOGOG_INITIALIZE();
+    {
+        logog::Cout out;
+        BaseLib::TemplateLogogFormatterSuppressedGCC<TOPIC_LEVEL_FLAG | TOPIC_FILE_NAME_FLAG | TOPIC_LINE_NUMBER_FLAG> custom_format;
+        out.SetFormatter(custom_format);
+
+        try {
+            // initialize libraries which will be used while testing
+#ifdef USE_LIS
+            lis_initialize(&argc, &argv);
+#endif
+            // start google test
+            testing::InitGoogleTest ( &argc, argv );
+            ret = RUN_ALL_TESTS();
+        } catch (char* e) {
+            ERR(e);
+        } catch (std::exception& e) {
+            ERR(e.what());
+        } catch (...) {
+            ERR("Unknown exception occurred!");
+        }
+        // finalize libraries
+#ifdef USE_LIS
+        lis_finalize();
+#endif
+    } // make sure no logog objects exist when LOGOG_SHUTDOWN() is called.
+    LOGOG_SHUTDOWN();
+
+    return ret;
 }
diff --git a/scripts/cmake/Find.cmake b/scripts/cmake/Find.cmake
index 4feea6704f4d5ca2c681a5bf9a4e3b3ca65ec3a5..fdff334950dbfd024ed2971aaedd3ca9c096e14f 100644
--- a/scripts/cmake/Find.cmake
+++ b/scripts/cmake/Find.cmake
@@ -138,6 +138,11 @@ IF(Shapelib_FOUND)
 	ADD_DEFINITIONS(-DShapelib_FOUND)
 ENDIF() # Shapelib_FOUND
 
+## lis ##
+IF(OGS_USE_LIS)
+    FIND_PACKAGE( LIS REQUIRED )
+ENDIF()
+
 ########################
 ### Find other stuff ###
 ########################
diff --git a/scripts/cmake/Functions.cmake b/scripts/cmake/Functions.cmake
index a759e11b3f369da64464e7f4d764d50b0b295fd5..8c1c0b833a77284541b6ec7c08767dc4f6d46ce9 100644
--- a/scripts/cmake/Functions.cmake
+++ b/scripts/cmake/Functions.cmake
@@ -15,8 +15,9 @@ MACRO(GET_SOURCE_FILES SOURCE_FILES)
 	ENDIF()
 
 	# Get all files in the directory
-	FILE(GLOB GET_SOURCE_FILES_HEADERS ${DIR}/*.h)
-	FILE(GLOB GET_SOURCE_FILES_SOURCES ${DIR}/*.cpp)
+	FILE(GLOB GET_SOURCE_FILES_HEADERS RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${DIR}/*.h)
+	FILE(GLOB GET_SOURCE_FILES_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${DIR}/*.tpp)
+	FILE(GLOB GET_SOURCE_FILES_SOURCES RELATIVE ${CMAKE_CURRENT_SOURCE_DIR} ${DIR}/*.cpp)
 
 	SET(${SOURCE_FILES} ${GET_SOURCE_FILES_HEADERS} ${GET_SOURCE_FILES_SOURCES})
 
@@ -54,4 +55,4 @@ MACRO(ADD_GOOGLE_TESTS executable)
 			# message ("Adding test: ${test_name}")
 		ENDFOREACH(hit)
 	ENDFOREACH()
-ENDMACRO()
\ No newline at end of file
+ENDMACRO()
diff --git a/scripts/cmake/cmake/FindLIS.cmake b/scripts/cmake/cmake/FindLIS.cmake
new file mode 100644
index 0000000000000000000000000000000000000000..4deb12a127f3ce1160d59360c321749ce6eb6c75
--- /dev/null
+++ b/scripts/cmake/cmake/FindLIS.cmake
@@ -0,0 +1,34 @@
+# - Try to find LIS
+# Once done, this will define
+#
+#  LIS_FOUND
+#  LIS_INCLUDE_DIRS
+#  LIS_LIBRARIES
+
+set(LIS_ROOT_DIR
+    "${LIS_ROOT_DIR}"
+    CACHE
+    PATH
+    "Directory to search for Lis library")
+	
+find_path( LIS_INCLUDE_DIR
+	NAMES lis.h
+	HINTS
+	${LIS_ROOT_DIR}/include
+    /usr/include/lis
+    $ENV{HOME}/include/
+	)
+
+find_library(LIS_LIBRARY
+    NAMES lis
+    HINTS 
+    ${LIS_ROOT_DIR}/lib
+    /usr/lib
+    $ENV{HOME}/lib/
+    ) 
+
+SET(LIS_LIBRARIES ${LIS_LIBRARY})
+
+INCLUDE(FindPackageHandleStandardArgs)
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(LIS DEFAULT_MSG LIS_LIBRARY LIS_INCLUDE_DIR)
+