diff --git a/Examples/DeformableBody/DeformableBodyExample.cpp b/Examples/DeformableBody/DeformableBodyExample.cpp
index a49faf30dcbb8f0bb199bc3bf57ddbd0510369dd..76d0b99e242809282d922648e3075c49a9669e40 100644
--- a/Examples/DeformableBody/DeformableBodyExample.cpp
+++ b/Examples/DeformableBody/DeformableBodyExample.cpp
@@ -23,7 +23,7 @@
 #include "imstkSimulationManager.h"
 #include "imstkDeformableObject.h"
 #include "imstkBackwardEuler.h"
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 #include "imstkNewtonSolver.h"
 #include "imstkGaussSeidel.h"
 #include "imstkPlane.h"
@@ -112,7 +112,7 @@ main()
     scene->addSceneObject(planeObj);
 
     // create a nonlinear system
-    auto nlSystem = std::make_shared<NonLinearSystem>(
+    auto nlSystem = std::make_shared<NonLinearSystem<SparseMatrixd>>(
         dynaModel->getFunction(),
         dynaModel->getFunctionGradient());
 
@@ -130,7 +130,7 @@ main()
     }
 
     // create a non-linear solver and add to the scene
-    auto nlSolver = std::make_shared<NewtonSolver>();
+    auto nlSolver = std::make_shared<NewtonSolver<SparseMatrixd>>();
     nlSolver->setLinearSolver(linSolver);
     nlSolver->setSystem(nlSystem);
     scene->addNonlinearSolver(nlSolver);
diff --git a/Examples/NonlinearSolver/CMakeLists.txt b/Examples/NonlinearSolver/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..a66dd3fc570afa0725ae5830d17ba193ce86e329
--- /dev/null
+++ b/Examples/NonlinearSolver/CMakeLists.txt
@@ -0,0 +1,35 @@
+###########################################################################
+#
+# Copyright (c) Kitware, Inc.
+#
+#  Licensed under the Apache License, Version 2.0 (the "License");
+#  you may not use this file except in compliance with the License.
+#  You may obtain a copy of the License at
+#
+#      http://www.apache.org/licenses/LICENSE-2.0.txt
+#
+#  Unless required by applicable law or agreed to in writing, software
+#  distributed under the License is distributed on an "AS IS" BASIS,
+#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+#  See the License for the specific language governing permissions and
+#  limitations under the License.
+#
+###########################################################################
+
+project(Example-NonlinearSolver)
+
+#-----------------------------------------------------------------------------
+# Create executable
+#-----------------------------------------------------------------------------
+imstk_add_executable(${PROJECT_NAME} nonlinearSolver.cpp)
+
+#-----------------------------------------------------------------------------
+# Add the target to Examples folder
+#-----------------------------------------------------------------------------
+SET_TARGET_PROPERTIES (${PROJECT_NAME} PROPERTIES FOLDER Examples)
+
+#-----------------------------------------------------------------------------
+# Link libraries to executable
+#-----------------------------------------------------------------------------
+target_link_libraries(${PROJECT_NAME} Solvers Common)
+
diff --git a/Examples/NonlinearSolver/nonlinearSolver.cpp b/Examples/NonlinearSolver/nonlinearSolver.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..1725f74c8351bfb07f27fed3fbb7c273434782d9
--- /dev/null
+++ b/Examples/NonlinearSolver/nonlinearSolver.cpp
@@ -0,0 +1,91 @@
+/*=========================================================================
+
+   Library: iMSTK
+
+   Copyright (c) Kitware, Inc. & Center for Modeling, Simulation,
+   & Imaging in Medicine, Rensselaer Polytechnic Institute.
+
+   Licensed under the Apache License, Version 2.0 (the "License");
+   you may not use this file except in compliance with the License.
+   You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0.txt
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+=========================================================================*/
+
+#include <ios>
+#include <iostream>
+#include <vector>
+#include <iomanip>
+
+#include "imstkMath.h"
+#include "imstkNewtonSolver.h"
+#include "imstkDirectLinearSolver.h"
+#include "imstkNonLinearSolver.h"
+
+using namespace imstk;
+
+int
+main(int argc, char** argv)
+{
+    const int N = 2;
+    auto      x = Vectord(N);
+    auto      xe = Vectord(N);
+    auto      y = Vectord(N);
+    auto      A = Matrixd(N, N);
+
+    x[0] = 100.0;
+    x[1] = 100.0;
+    xe[0] = 1.0;
+    xe[1] = 10.0;
+
+    auto func = [&y](const Vectord& x, const bool isSemiImplicit) -> const Vectord& {
+        // auto y = Vectord(x.size());
+        y[0] = x[0] * x[0] - 1.0;
+        y[1] = x[1] * x[1] - 100.0;
+
+        return y;
+    };
+
+    auto jac = [&A](const Vectord& x) -> const Matrixd& {
+        // auto A = Matrixd(x.size(), x.size());
+        A(0, 0) = 2 * x[0];
+        A(0, 1) = 0.0;
+        A(1, 0) = 0.0;
+        A(1, 1) = 2 * x[1];
+
+        return A;
+    };
+
+    auto updateX = [&x](const Vectord& du, const bool isSemiImplicit)
+    {
+        x -= du;
+        return;
+    };
+
+    auto updateXold = [](void) {};
+
+    auto nlSystem = std::make_shared<NonLinearSystem<Matrixd>>(func, jac);
+    nlSystem->setUnknownVector(x);
+    nlSystem->setUpdateFunction(updateX);
+    nlSystem->setUpdatePreviousStatesFunction(updateXold);
+
+    auto linSolver = std::make_shared<DirectLinearSolver<Matrixd>>();
+    auto nlSolver  = std::make_shared<NewtonSolver<Matrixd>>();
+    nlSolver->setMaxIterations(100);
+    nlSolver->setRelativeTolerance(1e-8);
+    nlSolver->setAbsoluteTolerance(1e-10);
+    nlSolver->setSystem(nlSystem);
+    nlSolver->setLinearSolver(linSolver);
+
+    std::cout << "init_error = " << std::setprecision(12) << std::scientific << (x-xe).norm() << std::endl;
+    nlSolver->solve();
+
+    std::cout << "final_error = " << std::setprecision(12) << std::scientific << (x-xe).norm() << std::endl;
+}
diff --git a/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.cpp b/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.cpp
index fd2f00405633c7fa323f53093af627720964cf38..02d42bdfcfbfad82ad859c45fbcf1eb9547f8c2e 100644
--- a/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.cpp
+++ b/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.cpp
@@ -261,7 +261,7 @@ FEMDeformableBodyModel::loadBoundaryConditions()
         if (file.is_open())
         {
             size_t index;
-            auto   maxAllowed = m_vegaPhysicsMesh->getNumVertices();
+            size_t maxAllowed = m_vegaPhysicsMesh->getNumVertices();
             while (!file.eof())
             {
                 file >> index;
@@ -689,7 +689,7 @@ FEMDeformableBodyModel::updateBodyIntermediateStates(
     m_qSol = m_currentState->getQ();
 }
 
-NonLinearSystem::VectorFunctionType
+NonLinearSystem<SparseMatrixd>::VectorFunctionType
 FEMDeformableBodyModel::getFunction()
 {
 #pragma warning( push )
@@ -711,7 +711,7 @@ FEMDeformableBodyModel::getFunction()
 #pragma warning( pop )
 }
 
-NonLinearSystem::MatrixFunctionType
+NonLinearSystem<SparseMatrixd>::MatrixFunctionType
 FEMDeformableBodyModel::getFunctionGradient()
 {
 #pragma warning( push )
@@ -731,7 +731,7 @@ FEMDeformableBodyModel::getFunctionGradient()
 #pragma warning( pop )
 }
 
-NonLinearSystem::UpdateFunctionType
+NonLinearSystem<SparseMatrixd>::UpdateFunctionType
 FEMDeformableBodyModel::getUpdateFunction()
 {
     // Function to evaluate the nonlinear objective function given the current state
@@ -743,7 +743,7 @@ FEMDeformableBodyModel::getUpdateFunction()
            };
 }
 
-NonLinearSystem::UpdatePrevStateFunctionType
+NonLinearSystem<SparseMatrixd>::UpdatePrevStateFunctionType
 FEMDeformableBodyModel::getUpdatePrevStateFunction()
 {
     // Function to evaluate the nonlinear objective function given the current state
diff --git a/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.h b/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.h
index ce911e5ef0d97f7573ec98b683ecdbd2ec185924..9641e0cba7dfb8409c037f238f0619cd75070c82 100644
--- a/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.h
+++ b/Source/DynamicalModels/ObjectModels/imstkFEMDeformableBodyModel.h
@@ -24,7 +24,7 @@
 // imstk
 #include "imstkDynamicalModel.h"
 #include "imstkInternalForceModelTypes.h"
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 
 // vega
 #include "sparseMatrix.h"
@@ -38,7 +38,9 @@ namespace imstk
 {
 class TimeIntegrator;
 class VegaMeshIO;
-class NewtonSolver;
+// class NewtonSolver<SparseMatrixd>;
+// template <typename SystemMatrix>
+// class NewtonSolver;
 class InternalForceModel;
 
 struct FEMModelConfig
@@ -72,6 +74,8 @@ struct FEMModelConfig
 class FEMDeformableBodyModel : public DynamicalModel<FeDeformBodyState>
 {
 using kinematicState = FeDeformBodyState;
+using System = NonLinearSystem<SparseMatrixd>;
+
 public:
     ///
     /// \brief Constructor
@@ -209,19 +213,19 @@ public:
     /// \brief Returns the "function" that evaluates the nonlinear function given
     /// the state vector
     ///
-    NonLinearSystem::VectorFunctionType getFunction();
+    System::VectorFunctionType getFunction();
 
     ///
     /// \brief Get the function that updates the model given the solution
     ///
-    NonLinearSystem::UpdateFunctionType getUpdateFunction();
-    NonLinearSystem::UpdatePrevStateFunctionType getUpdatePrevStateFunction();
+    System::UpdateFunctionType getUpdateFunction();
+    System::UpdatePrevStateFunctionType getUpdatePrevStateFunction();
 
     ///
     /// \brief Returns the "function" that evaluates the gradient of the nonlinear
     /// function given the state vector
     ///
-    NonLinearSystem::MatrixFunctionType getFunctionGradient();
+    System::MatrixFunctionType getFunctionGradient();
 
     ///
     /// \brief Get the contact force vector
@@ -268,7 +272,7 @@ public:
 protected:
     std::shared_ptr<InternalForceModel> m_internalForceModel;       ///> Mathematical model for intenal forces
     std::shared_ptr<TimeIntegrator>     m_timeIntegrator;           ///> Time integrator
-    std::shared_ptr<NonLinearSystem>    m_nonLinearSystem;          ///> Nonlinear system resulting from TI and force model
+    std::shared_ptr<System>    m_nonLinearSystem;          ///> Nonlinear system resulting from TI and force model
 
     std::shared_ptr<FEMModelConfig> m_FEModelConfig;
 
diff --git a/Source/Solvers/imstkDirectLinearSolver.cpp b/Source/Solvers/imstkDirectLinearSolver.cpp
index e8ee18238bf9700fa08a86e478a024e876223c80..77b4018ee1db170783bed698d08968edaaf57dce 100644
--- a/Source/Solvers/imstkDirectLinearSolver.cpp
+++ b/Source/Solvers/imstkDirectLinearSolver.cpp
@@ -21,6 +21,7 @@
 
 #include "imstkDirectLinearSolver.h"
 #include "imstkLinearSystem.h"
+#include "imstkLogger.h"
 #include <iostream>
 
 namespace imstk
@@ -58,17 +59,14 @@ setSystem(std::shared_ptr<LinearSystem<SparseMatrixd>> newSystem)
 void
 DirectLinearSolver<SparseMatrixd>::solve(const Vectord& rhs, Vectord& x)
 {
+    if(!m_linearSystem) LOG(FATAL) << "Linear system has not been set";
     x = m_solver.solve(rhs);
 }
 
 void
 DirectLinearSolver<SparseMatrixd>::solve(Vectord& x)
 {
-    if (!m_linearSystem)
-    {
-        return;
-    }
-
+    if(!m_linearSystem) LOG(FATAL) << "Linear system has not been set";
     x.setZero();
 
     auto b = m_linearSystem->getRHSVector();
@@ -78,21 +76,17 @@ DirectLinearSolver<SparseMatrixd>::solve(Vectord& x)
 void
 DirectLinearSolver<Matrixd>::solve(const Vectord& rhs, Vectord& x)
 {
+    if(!m_linearSystem) LOG(FATAL) << "Linear system has not been set";
     x = m_solver.solve(rhs);
 }
 
 void
 DirectLinearSolver<Matrixd>::solve(Vectord& x)
 {
-    if (!m_linearSystem)
-    {
-        /// \todo Log this
-        return;
-    }
-
+    if(!m_linearSystem) LOG(FATAL) << "Linear system has not been set";
     x.setZero();
 
     auto b = m_linearSystem->getRHSVector();
     x = m_solver.solve(b);
 }
-} // imstk
\ No newline at end of file
+} // imstk
diff --git a/Source/Solvers/imstkDirectLinearSolver.h b/Source/Solvers/imstkDirectLinearSolver.h
index 848fd52bf19692657ee8b89bda0982f476ffb24c..e586d811f03ec1e8fb0b21dd0cdc961d23616017 100644
--- a/Source/Solvers/imstkDirectLinearSolver.h
+++ b/Source/Solvers/imstkDirectLinearSolver.h
@@ -46,7 +46,8 @@ public:
     ///
     /// \brief Default constructor/destructor.
     ///
-    DirectLinearSolver() = delete;
+    // DirectLinearSolver() = delete;
+    DirectLinearSolver()  {}
     ~DirectLinearSolver() {};
 
     ///
@@ -69,6 +70,11 @@ public:
     ///
     void setSystem(std::shared_ptr<LinearSystemType> newSystem) override;
 
+    ///
+    /// \brief Sets the matrix
+    ///
+    void setSystem(std::shared_ptr<Matrixd> matrix);
+
     ///
     /// \brief Returns true if the solver is iterative
     ///
diff --git a/Source/Solvers/imstkLinearSolver.h b/Source/Solvers/imstkLinearSolver.h
index e49596b25b1e3709cd5e7dbf3ebe36a753be2c37..7b279c1db9f4828b5996159d90acf2d98b0d1c16 100644
--- a/Source/Solvers/imstkLinearSolver.h
+++ b/Source/Solvers/imstkLinearSolver.h
@@ -52,7 +52,7 @@ public:
     ///
     /// \brief Default constructor/destructor
     ///
-    LinearSolver() {};
+    LinearSolver() : m_linearSystem(nullptr) {};
     virtual ~LinearSolver() {};
 
     ///
diff --git a/Source/Solvers/imstkLinearSystem.h b/Source/Solvers/imstkLinearSystem.h
index 660b3ba0c8eacf14a32ba47d1808d941895ad5c5..5c0814258a80dd0e654bbfcdaf44e4e519d12b3b 100644
--- a/Source/Solvers/imstkLinearSystem.h
+++ b/Source/Solvers/imstkLinearSystem.h
@@ -21,7 +21,7 @@
 
 #pragma once
 
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 
 namespace imstk
 {
@@ -30,7 +30,7 @@ namespace imstk
 /// \brief Represents the linear system of the form \f$ Ax = b \f$
 ///
 template<typename SystemMatrixType>
-class LinearSystem : public NonLinearSystem
+class LinearSystem : public NonLinearSystem<SystemMatrixType>
 {
 public:
     ///
@@ -91,7 +91,7 @@ public:
     ///
     /// \brief Set the system matrix corresponding to this ODE system.
     ///
-    void setMatrix(const SparseMatrixd& newMatrix)
+    void setMatrix(const SystemMatrixType& newMatrix)
     {
         m_A = newMatrix;
     }
diff --git a/Source/Solvers/imstkNewtonSolver.cpp b/Source/Solvers/imstkNewtonSolver.cpp
index 70fbb6074914cf7ca725f93f4f804d5f097c2280..7632722119b1635cff0efc2ee94d6dd36e8faf57 100644
--- a/Source/Solvers/imstkNewtonSolver.cpp
+++ b/Source/Solvers/imstkNewtonSolver.cpp
@@ -20,15 +20,18 @@
 =========================================================================*/
 
 #include <iostream>
+#include <memory>
 
 #include "imstkNewtonSolver.h"
 #include "imstkIterativeLinearSolver.h"
 #include "imstkConjugateGradient.h"
+#include "imstkDirectLinearSolver.h"
 #include "imstkLogger.h"
 
 namespace imstk
 {
-NewtonSolver::NewtonSolver() :
+template <> 
+NewtonSolver<SparseMatrixd>::NewtonSolver() :
     m_linearSolver(std::make_shared<ConjugateGradient>()),
     m_forcingTerm(0.9),
     m_absoluteTolerance(1e-3),
@@ -40,17 +43,32 @@ NewtonSolver::NewtonSolver() :
 {
 }
 
+template <>
+NewtonSolver<Matrixd>::NewtonSolver() :
+    m_linearSolver(std::make_shared<DirectLinearSolver<Matrixd>>()),
+    m_forcingTerm(0.9),
+    m_absoluteTolerance(1e-3),
+    m_relativeTolerance(1e-6),
+    m_gamma(0.9),
+    m_etaMax(0.9),
+    m_maxIterations(1),
+    m_useArmijo(true)
+{
+}
+
+
+template <typename SystemMatrix> 
 void
-NewtonSolver::solveGivenState(Vectord& x)
+NewtonSolver<SystemMatrix>::solveGivenState(Vectord& x)
 {
-    if (!m_nonLinearSystem)
+    if (!this->m_nonLinearSystem)
     {
         LOG(WARNING) << "NewtonMethod::solve - nonlinear system is not set to the nonlinear solver";
         return;
     }
 
     // Compute norms, set tolerances and other temporaries
-    double fnorm = m_nonLinearSystem->evaluateF(x, m_isSemiImplicit).norm();
+    double fnorm = this->m_nonLinearSystem->evaluateF(x, this->m_isSemiImplicit).norm();
     double stopTolerance = m_absoluteTolerance + m_relativeTolerance * fnorm;
 
     m_linearSolver->setTolerance(stopTolerance);
@@ -65,7 +83,7 @@ NewtonSolver::solveGivenState(Vectord& x)
         }
         this->updateJacobian(x);
         m_linearSolver->solve(dx);
-        m_updateIterate(-dx, x);
+        this->m_updateIterate(-dx, x);
 
         double newNorm = this->armijo(dx, x, fnorm);
 
@@ -83,23 +101,24 @@ NewtonSolver::solveGivenState(Vectord& x)
     }
 }
 
+template <typename SystemMatrix> 
 void
-NewtonSolver::solve()
+NewtonSolver<SystemMatrix>::solve()
 {
-    if (!m_nonLinearSystem)
+    if (!this->m_nonLinearSystem)
     {
         LOG(WARNING) << "NewtonMethod::solve - nonlinear system is not set to the nonlinear solver";
         return;
     }
 
     size_t      iterNum;
-    const auto& u  = m_nonLinearSystem->getUnknownVector();
+    const auto& u  = this->m_nonLinearSystem->getUnknownVector();
     Vectord     du = u; // make this a class member in future
+    double error0 = MAX_D;
 
     double epsilon = m_relativeTolerance * m_relativeTolerance;
     for (iterNum = 0; iterNum < m_maxIterations; ++iterNum)
     {
-        double error0 = MAX_D;
         double error  = updateJacobian(u);
 
         if (iterNum == 0)
@@ -109,49 +128,52 @@ NewtonSolver::solve()
 
         if (error / error0 < epsilon && iterNum > 0)
         {
-            //std::cout << "Num. of Newton Iterations: " << i << "\tError ratio: " << error/error0 << std::endl;
+            // std::cout << "Num. of Newton Iterations: " << iterNum << "\tError ratio: " << error/error0 << ", " << error << " " << error0 << std::endl;
             break;
         }
 
         m_linearSolver->solve(du);
-        m_nonLinearSystem->m_FUpdate(du, m_isSemiImplicit);
+        this->m_nonLinearSystem->m_FUpdate(du, this->m_isSemiImplicit);
     }
-    m_nonLinearSystem->m_FUpdatePrevState();
 
-    if (iterNum == m_maxIterations && !m_isSemiImplicit)
+    this->m_nonLinearSystem->m_FUpdatePrevState();
+
+    if (iterNum == m_maxIterations && !this->m_isSemiImplicit)
     {
         LOG(WARNING) << "NewtonMethod::solve - The solver did not converge after max. iterations";
     }
 }
 
+template <typename SystemMatrix> 
 double
-NewtonSolver::updateJacobian(const Vectord& x)
+NewtonSolver<SystemMatrix>::updateJacobian(const Vectord& x)
 {
     // Evaluate the Jacobian and sets the matrix
-    if (!m_nonLinearSystem)
+    if (!this->m_nonLinearSystem)
     {
         LOG(WARNING) << "NewtonMethod::updateJacobian - nonlinear system is not set to the nonlinear solver";
         return -1;
     }
 
-    auto& A = m_nonLinearSystem->m_dF(x);
+    auto& A = this->m_nonLinearSystem->m_dF(x);
     if (A.innerSize() == 0)
     {
         LOG(WARNING) << "NewtonMethod::updateJacobian - Size of matrix is 0!";
         return -1;
     }
 
-    auto& b = m_nonLinearSystem->m_F(x, m_isSemiImplicit);
+    auto& b = this->m_nonLinearSystem->m_F(x, this->m_isSemiImplicit);
 
-    auto linearSystem = std::make_shared<LinearSolverType::LinearSystemType>(A, b);
-    //linearSystem->setLinearProjectors(m_nonLinearSystem->getLinearProjectors()); /// \todo Left for near future reference. Clear in future.
+    auto linearSystem = std::make_shared<typename LinearSolverType::LinearSystemType>(A, b);
+    //linearSystem->setLinearProjectors(this->m_nonLinearSystem->getLinearProjectors()); /// \todo Left for near future reference. Clear in future.
     m_linearSolver->setSystem(linearSystem);
 
-    return b.dot(b);
+    return std::sqrt(b.dot(b));
 }
 
+template <typename SystemMatrix> 
 void
-NewtonSolver::updateForcingTerm(const double ratio, const double stopTolerance, const double fnorm)
+NewtonSolver<SystemMatrix>::updateForcingTerm(const double ratio, const double stopTolerance, const double fnorm)
 {
     double eta = m_gamma * ratio * ratio;
     double forcingTermSqr = m_forcingTerm * m_forcingTerm;
@@ -166,27 +188,36 @@ NewtonSolver::updateForcingTerm(const double ratio, const double stopTolerance,
     m_forcingTerm = std::max(std::min(eta, m_etaMax), 0.5 * stopTolerance / fnorm);
 }
 
+template <typename SystemMatrix> 
 void
-NewtonSolver::setLinearSolver(std::shared_ptr<NewtonSolver::LinearSolverType> newLinearSolver)
+NewtonSolver<SystemMatrix>::setLinearSolver(std::shared_ptr<NewtonSolver::LinearSolverType> newLinearSolver)
 {
     m_linearSolver = newLinearSolver;
 }
 
-std::shared_ptr<NewtonSolver::LinearSolverType>
-NewtonSolver::getLinearSolver() const
+template <typename SystemMatrix> 
+// std::shared_ptr<NewtonSolver<SystemMatrix>::LinearSolverType>
+auto
+NewtonSolver<SystemMatrix>::getLinearSolver() const -> std::shared_ptr<LinearSolverType>
 {
     return m_linearSolver;
 }
 
+template <typename SystemMatrix> 
 void
-NewtonSolver::setAbsoluteTolerance(const double aTolerance)
+NewtonSolver<SystemMatrix>::setAbsoluteTolerance(const double aTolerance)
 {
     m_absoluteTolerance = aTolerance;
 }
 
+template <typename SystemMatrix> 
 double
-NewtonSolver::getAbsoluteTolerance() const
+NewtonSolver<SystemMatrix>::getAbsoluteTolerance() const
 {
     return m_absoluteTolerance;
 }
+
+
+template class NewtonSolver<SparseMatrixd>;
+template class NewtonSolver<Matrixd>;
 } // imstk
diff --git a/Source/Solvers/imstkNewtonSolver.h b/Source/Solvers/imstkNewtonSolver.h
index 047f58392e255641d9034d534b8a4d69fc9c677d..b06e0d977f2441602f3347abe80838107a1d1f30 100644
--- a/Source/Solvers/imstkNewtonSolver.h
+++ b/Source/Solvers/imstkNewtonSolver.h
@@ -33,10 +33,11 @@ namespace imstk
 ///     root of F or fails. Global convergence is achieved using a line search sub-process
 ///     and the Armijo rule
 ///
-class NewtonSolver : public NonLinearSolver
+template <typename SystemMatrix> 
+class NewtonSolver : public NonLinearSolver<SystemMatrix>
 {
 public:
-    using LinearSolverType = LinearSolver<SparseMatrixd>;
+    using LinearSolverType = LinearSolver<SystemMatrix>;
 
 public:
     ///
@@ -78,7 +79,8 @@ public:
     ///
     /// \brief Get LinearSolver
     ///
-    std::shared_ptr<LinearSolverType> getLinearSolver() const;
+    // std::shared_ptr<LinearSolverType> getLinearSolver() const;
+    auto getLinearSolver() const -> std::shared_ptr<LinearSolverType>;
 
     ///
     /// \brief Update jacobians
@@ -90,7 +92,7 @@ public:
     ///
     /// \brief Get JacobianMatrix. Returns jacobian matrix
     ///
-    SparseMatrixd& getJacobianMatrix();
+    SystemMatrix& getJacobianMatrix();
 
     ///
     /// \brief Set AbsoluteTolerance
@@ -169,7 +171,7 @@ public:
     void setUseArmijo(const bool value)
     {
         m_useArmijo = value;
-        (value) ? m_armijoMax = 30 : m_armijoMax = 0;
+        (value) ? this->m_armijoMax = 30 : this->m_armijoMax = 0;
     }
 
     ///
@@ -193,7 +195,7 @@ public:
     ///
     virtual void setToFullyImplicit() override
     {
-        m_isSemiImplicit = false;
+        this->m_isSemiImplicit = false;
     }
 
     ///
@@ -201,7 +203,7 @@ public:
     ///
     virtual void setToSemiImplicit() override
     {
-        m_isSemiImplicit = true;
+        this->m_isSemiImplicit = true;
         m_maxIterations  = 1;
     }
 
diff --git a/Source/Solvers/imstkNonLinearSolver.cpp b/Source/Solvers/imstkNonLinearSolver.cpp
index efad583aba8c50c47e9cfbcf16f19054e04e2c60..c0f7f8b80454b93ae0af5609d1b68650c8b8b073 100644
--- a/Source/Solvers/imstkNonLinearSolver.cpp
+++ b/Source/Solvers/imstkNonLinearSolver.cpp
@@ -20,10 +20,12 @@
 =========================================================================*/
 
 #include "imstkNonLinearSolver.h"
+#include "imstkMath.h"
 
 namespace imstk
 {
-NonLinearSolver::NonLinearSolver() : m_sigma(std::array<double, 2>
+template <typename SystemMatrix>
+NonLinearSolver<SystemMatrix>::NonLinearSolver() : m_sigma(std::array<double, 2>
     {
         { 0.1, 0.5 }
     }),
@@ -36,8 +38,9 @@ NonLinearSolver::NonLinearSolver() : m_sigma(std::array<double, 2>
                       };
 }
 
+template <typename SystemMatrix>
 double
-NonLinearSolver::armijo(const Vectord& dx, Vectord& x, const double previousFnorm)
+NonLinearSolver<SystemMatrix>::armijo(const Vectord& dx, Vectord& x, const double previousFnorm)
 {
     /// Temporaries used in the line search
     std::array<double, 3> fnormSqr = { previousFnorm* previousFnorm, 0.0, 0.0 };
@@ -96,8 +99,9 @@ NonLinearSolver::armijo(const Vectord& dx, Vectord& x, const double previousFnor
     return currentFnorm;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::parabolicModel(const std::array<double, 3>& fnorm, std::array<double, 3>& lambda)
+NonLinearSolver<SystemMatrix>::parabolicModel(const std::array<double, 3>& fnorm, std::array<double, 3>& lambda)
 {
     /// Compute the coefficients for the interpolation polynomial:
     ///     p(lambda) = fnorm[0] + (b*lambda + a*lambda^2)/d1, where
@@ -130,57 +134,69 @@ NonLinearSolver::parabolicModel(const std::array<double, 3>& fnorm, std::array<d
     lambda[0] = newLambda;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::setSigma(const std::array<double, 2>& newSigma)
+NonLinearSolver<SystemMatrix>::setSigma(const std::array<double, 2>& newSigma)
 {
     m_sigma = newSigma;
 }
 
+template <typename SystemMatrix>
 const std::array<double, 2>&
-NonLinearSolver::getSigma() const
+NonLinearSolver<SystemMatrix>::getSigma() const
 {
     return m_sigma;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::setAlpha(const double newAlpha)
+NonLinearSolver<SystemMatrix>::setAlpha(const double newAlpha)
 {
     m_alpha = newAlpha;
 }
 
+template <typename SystemMatrix>
 double
-NonLinearSolver::getAlpha() const
+NonLinearSolver<SystemMatrix>::getAlpha() const
 {
     return m_alpha;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::setArmijoMax(const size_t newArmijoMax)
+NonLinearSolver<SystemMatrix>::setArmijoMax(const size_t newArmijoMax)
 {
     m_armijoMax = newArmijoMax;
 }
 
+template <typename SystemMatrix>
 size_t
-NonLinearSolver::getArmijoMax() const
+NonLinearSolver<SystemMatrix>::getArmijoMax() const
 {
     return m_armijoMax;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::setSystem(std::shared_ptr<NonLinearSystem> newSystem)
+NonLinearSolver<SystemMatrix>::setSystem(std::shared_ptr<NonLinearSystem<SystemMatrix>> newSystem)
 {
     m_nonLinearSystem = newSystem;
 }
 
-std::shared_ptr<NonLinearSystem>
-NonLinearSolver::getSystem() const
+template <typename SystemMatrix>
+std::shared_ptr<NonLinearSystem<SystemMatrix>>
+NonLinearSolver<SystemMatrix>::getSystem() const
 {
     return m_nonLinearSystem;
 }
 
+template <typename SystemMatrix>
 void
-NonLinearSolver::setUpdateIterate(const NonLinearSolver::UpdateIterateType& newUpdateIterate)
+NonLinearSolver<SystemMatrix>::setUpdateIterate(const NonLinearSolver<SystemMatrix>::UpdateIterateType& newUpdateIterate)
 {
     m_updateIterate = newUpdateIterate;
 }
-} // imstk
\ No newline at end of file
+
+template class NonLinearSolver<SparseMatrixd>;
+template class NonLinearSolver<Matrixd>;
+} // imstk
diff --git a/Source/Solvers/imstkNonLinearSolver.h b/Source/Solvers/imstkNonLinearSolver.h
index 05c2ea9604bb521074b48c2b2020c6fd10e254f0..3902fb310a54ca81f1e11733ed556ce8efcc15de 100644
--- a/Source/Solvers/imstkNonLinearSolver.h
+++ b/Source/Solvers/imstkNonLinearSolver.h
@@ -26,7 +26,7 @@
 #include <functional>
 
 // imstk includes
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 #include "imstkMath.h"
 #include "imstkSolverBase.h"
 
@@ -35,12 +35,13 @@ namespace imstk
 ///
 /// \brief Base class for non-linear solvers
 ///
+template <typename SystemMatrix>
 class NonLinearSolver : public SolverBase
 {
 public:
-    using JacobianType      = std::function<const SparseMatrixd& (const Vectord&)>;
+    using JacobianType      = std::function<const SystemMatrix& (const Vectord&)>;
     using UpdateIterateType = std::function<void (const Vectord&, Vectord&)>;
-    using FunctionType      = NonLinearSystem::VectorFunctionType;
+    using FunctionType      = NonLinearSystem<SparseMatrixd>::VectorFunctionType;
 
 public:
     ///
@@ -105,8 +106,8 @@ public:
     ///
     /// \param newSystem Non-linear system replacement.
     ///
-    void setSystem(std::shared_ptr<NonLinearSystem> newSystem);
-    std::shared_ptr<NonLinearSystem> getSystem() const;
+    void setSystem(std::shared_ptr<NonLinearSystem<SystemMatrix>> newSystem);
+    std::shared_ptr<NonLinearSystem<SystemMatrix>> getSystem() const;
 
     ///
     /// \brief Set a customized iterate update function.
@@ -136,7 +137,7 @@ protected:
     double m_alpha;                                     ///< Parameter to measure decrease
     size_t m_armijoMax;                                 ///< Maximum number of step length reductions
 
-    std::shared_ptr<NonLinearSystem> m_nonLinearSystem; ///< System of non-linear equations
+    std::shared_ptr<NonLinearSystem<SystemMatrix>> m_nonLinearSystem; ///< System of non-linear equations
     UpdateIterateType m_updateIterate;                  ///< Update iteration function
     bool m_isSemiImplicit = true;                       ///> Semi-Implicit solver
 };
diff --git a/Source/Solvers/imstkNonlinearSystem.cpp b/Source/Solvers/imstkNonLinearSystem.cpp
similarity index 58%
rename from Source/Solvers/imstkNonlinearSystem.cpp
rename to Source/Solvers/imstkNonLinearSystem.cpp
index 8da916dd00e427f72673dbe9523a2e453e114d26..92c688c54b8a1ac4b4e0409814c7fdfb58b6bc80 100644
--- a/Source/Solvers/imstkNonlinearSystem.cpp
+++ b/Source/Solvers/imstkNonLinearSystem.cpp
@@ -19,37 +19,47 @@
 
 =========================================================================*/
 
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
+#include "imstkMath.h"
 
-#include <g3log/g3log.hpp>
+// #include <g3log/g3log.hpp>
 
 namespace imstk
 {
-NonLinearSystem::NonLinearSystem(const VectorFunctionType& F, const MatrixFunctionType& dF) : m_F(F), m_dF(dF)
+template <typename Matrix>
+NonLinearSystem<Matrix>::NonLinearSystem(const VectorFunctionType& F, const MatrixFunctionType& dF) : m_F(F), m_dF(dF)
 {
 }
 
+template <typename Matrix>
 void
-NonLinearSystem::setFunction(const VectorFunctionType& function)
+NonLinearSystem<Matrix>::setFunction(const VectorFunctionType& function)
 {
     m_F = function;
 }
 
+template <typename Matrix>
 void
-NonLinearSystem::setJacobian(const MatrixFunctionType& function)
+NonLinearSystem<Matrix>::setJacobian(const MatrixFunctionType& function)
 {
     m_dF = function;
 }
 
+template <typename Matrix>
 const Vectord&
-NonLinearSystem::evaluateF(const Vectord& x, const bool isSemiImplicit)
+NonLinearSystem<Matrix>::evaluateF(const Vectord& x, const bool isSemiImplicit)
 {
     return m_F(x, isSemiImplicit);
 }
 
-const SparseMatrixd&
-NonLinearSystem::evaluateJacobian(const Vectord& x)
+template <typename Matrix>
+const Matrix&
+NonLinearSystem<Matrix>::evaluateJacobian(const Vectord& x)
 {
     return m_dF(x);
 }
-} //imstk
\ No newline at end of file
+
+template class NonLinearSystem<SparseMatrixd>;
+template class NonLinearSystem<Matrixd>;
+
+} //imstk
diff --git a/Source/Solvers/imstkNonlinearSystem.h b/Source/Solvers/imstkNonLinearSystem.h
similarity index 95%
rename from Source/Solvers/imstkNonlinearSystem.h
rename to Source/Solvers/imstkNonLinearSystem.h
index 941387064002f836d9160338239a061a439a4019..d631063b9b287bb562a671059b09ea35e92ca1bf 100644
--- a/Source/Solvers/imstkNonlinearSystem.h
+++ b/Source/Solvers/imstkNonLinearSystem.h
@@ -31,11 +31,12 @@ namespace imstk
 ///
 /// \brief Base class for a multi-variable nonlinear system
 ///
+template <typename Matrix>
 class NonLinearSystem
 {
 public:
     using VectorFunctionType = std::function<const Vectord& (const Vectord&, const bool)>;
-    using MatrixFunctionType = std::function<const SparseMatrixd& (const Vectord&)>;
+    using MatrixFunctionType = std::function<const Matrix& (const Vectord&)>;
     using UpdateFunctionType = std::function<void (const Vectord&, const bool)>;
     using UpdatePrevStateFunctionType = std::function<void ()>;
 
@@ -66,7 +67,7 @@ public:
     ///
     /// \brief Evaluate gradient of the function at a given state
     ///
-    virtual const SparseMatrixd& evaluateJacobian(const Vectord& x);
+    virtual const Matrix& evaluateJacobian(const Vectord& x);
 
     ///
     /// \brief
diff --git a/Source/Solvers/imstkSOR.h b/Source/Solvers/imstkSOR.h
index f310b48bc70d1dde34f439fdf74cdf76864ade3d..d71a93fd9af8aeea16b06a432ab856f6723d3c0e 100644
--- a/Source/Solvers/imstkSOR.h
+++ b/Source/Solvers/imstkSOR.h
@@ -22,7 +22,7 @@
 #pragma once
 
 // iMSTK includes
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 #include "imstkIterativeLinearSolver.h"
 
 // Eigen includes
diff --git a/Source/apiUtilities/imstkAPIUtilities.cpp b/Source/apiUtilities/imstkAPIUtilities.cpp
index ef6930160251d2533a82d66a71c6ee7714b018a8..82bfcb51e895fd2093cfd7cf062fa32cf12ff387 100644
--- a/Source/apiUtilities/imstkAPIUtilities.cpp
+++ b/Source/apiUtilities/imstkAPIUtilities.cpp
@@ -30,7 +30,7 @@
 #include "imstkColor.h"
 
 // Solvers
-#include "imstkNonlinearSystem.h"
+#include "imstkNonLinearSystem.h"
 
 // Geometry
 #include "imstkPlane.h"
@@ -177,12 +177,12 @@ createAndAddVisualSceneObject(std::shared_ptr<Scene> scene,
 ///
 /// \brief Create a non-linear system using FEM dynamic model
 ///
-std::shared_ptr<NonLinearSystem>
+std::shared_ptr<NonLinearSystem<SparseMatrixd>>
 createNonLinearSystem(std::shared_ptr<FEMDeformableBodyModel> dynaModel)
 {
     CHECK(dynaModel != nullptr) << "createNonLinearSystem: Dynamic model is not valid!";
 
-    auto nlSystem = std::make_shared<NonLinearSystem>(
+    auto nlSystem = std::make_shared<NonLinearSystem<SparseMatrixd>>(
                 dynaModel->getFunction(),
                 dynaModel->getFunctionGradient());
 
@@ -255,4 +255,4 @@ getMeshGraph(std::shared_ptr<TetrahedralMesh> m)
     return gMesh;
 }
 }     //apiutils
-} // imstk
\ No newline at end of file
+} // imstk
diff --git a/Source/apiUtilities/imstkAPIUtilities.h b/Source/apiUtilities/imstkAPIUtilities.h
index a13b953d01e3555e384094305c87e028d98665ef..f39515b79aa620b9c7a23580a178117a2fe608cc 100644
--- a/Source/apiUtilities/imstkAPIUtilities.h
+++ b/Source/apiUtilities/imstkAPIUtilities.h
@@ -33,6 +33,7 @@ class PointSet;
 class SceneManager;
 class Scene;
 class FEMDeformableBodyModel;
+template <typename Matrix>
 class NonLinearSystem;
 class CollidingObject;
 class Graph;
@@ -67,7 +68,7 @@ std::shared_ptr<SceneObject> createAndAddVisualSceneObject(std::shared_ptr<Scene
 ///
 /// \brief Create a non-linear system using FEM dynamic model
 ///
-std::shared_ptr<NonLinearSystem> createNonLinearSystem(std::shared_ptr<FEMDeformableBodyModel> dynaModel);
+std::shared_ptr<NonLinearSystem<SparseMatrixd>> createNonLinearSystem(std::shared_ptr<FEMDeformableBodyModel> dynaModel);
 
 ///
 /// \brief Print number of updates for second for a given scene