diff --git a/AMDiS/src/BFGS_Precond.cc b/AMDiS/src/BFGS_Precond.cc
new file mode 100755
index 0000000000000000000000000000000000000000..0a31bb1d68b93e50f7145c1c758c9d0b75fadde7
--- /dev/null
+++ b/AMDiS/src/BFGS_Precond.cc
@@ -0,0 +1,68 @@
+#include "BFGS_Precond.h"
+#include "QN_Precond.h"
+#include "FiniteElemSpace.h"
+#include "DOFAdmin.h"
+#include "DOFVector.h"
+#include "DOFMatrix.h"
+#include "DOFIterator.h"
+
+namespace AMDiS
+{
+
+  void BFGS_Precond::addPair(DOFVector<double> *s, DOFVector<double> *y,
+			     double sy)
+  {
+    FUNCNAME("BFGS_Preconditioner::addPair()");
+
+    if (!sy)
+      sy = *s * *y;
+    TEST_EXIT(sy > 0)("Vectors do not satisfy the curvature condition!\n");
+
+    BFGS_Vectors newPair(s->getFESpace());
+    newPair.setVectors(s, y, sy);
+
+    if (k < m) {
+      k++;
+    } else {
+      pairsVec.pop_back();
+    }
+
+    pairsVec.push_front(newPair);
+
+    return;
+  }
+
+  void BFGS_Precond::precon(DOFVector<double> *vec)
+  {
+    FUNCNAME("BFGS_Preconditioner::precon()");
+
+    int    i      = 0;
+    double beta;
+    double *alpha = GET_MEMORY(double, k);
+
+    ::std::deque<BFGS_Vectors>::iterator pairsIterator(pairsVec.begin());
+
+    while (pairsIterator != pairsVec.end()) {
+      alpha[i]  = pairsIterator->s * *vec;
+      alpha[i] /= pairsIterator->sy;
+      aXpY(-alpha[i], pairsIterator->y, *vec, bound);
+      ++i;
+      ++pairsIterator;
+    }
+
+    diagPrecond(*matrix[row], vec, bound);
+
+    while (pairsIterator != pairsVec.begin()) {
+      --pairsIterator;
+      --i;
+      beta  = pairsIterator->y * *vec;
+      beta /= pairsIterator->sy;
+      aXpY(alpha[i]-beta, pairsIterator->s, *vec, bound);
+    }
+    
+    FREE_MEMORY(alpha, double, k);
+    
+    return;
+  }
+
+}
diff --git a/AMDiS/src/BFGS_Precond.h b/AMDiS/src/BFGS_Precond.h
new file mode 100755
index 0000000000000000000000000000000000000000..5629330327dd060a81f49b6907e876b7f6a62cff
--- /dev/null
+++ b/AMDiS/src/BFGS_Precond.h
@@ -0,0 +1,168 @@
+// ============================================================================
+// ==                                                                        ==
+// == AMDiS - Adaptive multidimensional simulations                          ==
+// ==                                                                        ==
+// ============================================================================
+// ==                                                                        ==
+// ==  crystal growth group                                                  ==
+// ==                                                                        ==
+// ==  Stiftung caesar                                                       ==
+// ==  Ludwig-Erhard-Allee 2                                                 ==
+// ==  53175 Bonn                                                            ==
+// ==  germany                                                               ==
+// ==                                                                        ==
+// ============================================================================
+// ==                                                                        ==
+// ==  http://www.caesar.de/cg/AMDiS                                         ==
+// ==                                                                        ==
+// ============================================================================
+
+/** \file BFGS_Precond.h */
+
+#ifndef AMDIS_BFGS_PRECONDITIONER_H
+#define AMDIS_BFGS_PRECONDITIONER_H
+
+#include "Parameters.h"
+#include "Preconditioner.h"
+#include "QN_Precond.h"
+
+namespace AMDiS
+{
+
+  template<typename T> class DOFVector;
+  template<typename T> class OEMSolver;
+
+  // ============================================================================
+  // ===== class BFGS_Vectors ===================================================
+  // ============================================================================
+
+  // Auxiliar class por storing pairs of DOFVectors and their scalar products.
+  class BFGS_Vectors
+  {
+  public:
+    MEMORY_MANAGED(BFGS_Vectors);
+
+    /** \brief
+     * Constructor.
+     */
+  BFGS_Vectors(const FiniteElemSpace *fe_space)
+    : s(fe_space, "BFGS->s"), y(fe_space, "BFGS->y")
+      {};
+
+    inline void setVectors(DOFVector<double> *s_, DOFVector<double> *y_,
+			   double sy_=0.0)
+    {
+      s = *s_;
+      y = *y_;
+
+      if (!sy_)
+	sy = s * y;
+      else
+	sy = sy_;
+
+      return;
+    };
+
+  private:
+    DOFVector<double> s, y;
+    double sy;
+
+    friend class BFGS_Precond;
+  };
+
+  // ============================================================================
+  // ===== class BFGS_Precond ===================================================
+  // ============================================================================
+
+  /**
+   * \ingroup Solver
+   *
+   * \brief
+   * BFGS preconditioner.
+   */
+  class BFGS_Precond : public PreconditionerScal
+  {
+  public:
+    MEMORY_MANAGED(BFGS_Precond);
+
+    /** \brief
+     * Creator class used in the PreconditionerMap.
+     */
+    class Creator : public PreconditionerScalCreator
+    {
+    public:
+      MEMORY_MANAGED(Creator);
+
+      /** \brief
+       * Creates a new BFGS Preconditioner.
+       */
+      PreconditionerScal *create()
+      {
+	return NEW BFGS_Precond(size, row);
+      };
+    };
+
+    /** \brief
+     * Constructor.
+     */
+  BFGS_Precond(int size_ = 1, int row_ = 0) : PreconditionerScal(size_, row_) {
+      k = 0;
+      
+      m = 2 * Global::getGeo(WORLD);
+      GET_PARAMETER(1, "preconditioner->max. number of pairs", "%d", &m);
+      m = std::max(0, std::min(m, 32));
+    };
+    
+    /** \brief
+     * Destructor.
+     */
+    virtual ~BFGS_Precond() {};
+
+    /** \brief
+     * realisation of Preconditioner::init
+     */
+    inline void init()
+    {
+      FUNCNAME("BFGS_Precond::init()");
+      TEST_EXIT(matrix[row])("no matrix\n");
+    };
+
+    /** \brief
+     * realisation of Preconditioner::precon
+     */
+    void precon(DOFVector<double> *vec);
+
+    /** \brief
+     * realisation of Preconditioner::exit
+     */
+    inline void exit() {};
+
+
+    /* ----- Specific functions ----- */
+
+    /** \brief
+     * add pair of vectors
+     */
+    void addPair(DOFVector<double> *s, DOFVector<double> *y, double sy = 0.0);
+
+  protected:
+
+    /** \brief
+     * list of pairs
+     */
+    std::deque<BFGS_Vectors> pairsVec;
+
+    /** \brief
+     * maximal number of pairs
+     */
+    int m;
+
+    /** \brief
+     * actual number of pairs
+     */
+    int k;
+  };
+
+}
+
+#endif // AMDIS_BFGS_PRECONDITIONER_H
diff --git a/AMDiS/src/QN_Precond.h b/AMDiS/src/QN_Precond.h
new file mode 100755
index 0000000000000000000000000000000000000000..edc038d085d592a635e21735a8e5aa525cec4094
--- /dev/null
+++ b/AMDiS/src/QN_Precond.h
@@ -0,0 +1,26 @@
+/** \file QN_Precond.h */
+
+#ifndef QN_PRECOND_H
+#define QN_PRECOND_H
+
+#include "DOFVector.h"
+
+namespace AMDiS
+{
+
+  template<typename T>
+    void diagPrecond(const DOFMatrix *A, DOFVector<T>* vec,
+		     DOFVector<BoundaryType> *bound = NULL);
+
+  template<typename T>
+    void aXpY(double a, const DOFVector<T>& x, DOFVector<T>& y,
+	      DOFVector<BoundaryType> *bound = NULL);
+
+  template<typename T>
+    void XpaY(double a, const DOFVector<T>& x, DOFVector<T>& y,
+	      DOFVector<BoundaryType> *bound = NULL);
+
+}
+
+#include "QN_Precond.hh"
+#endif // QN_PRECOND_H
diff --git a/AMDiS/src/QN_Precond.hh b/AMDiS/src/QN_Precond.hh
new file mode 100755
index 0000000000000000000000000000000000000000..5bb4a35e865a4757c603d9dd3832df5a09780b1e
--- /dev/null
+++ b/AMDiS/src/QN_Precond.hh
@@ -0,0 +1,141 @@
+#include "DOFVector.h"
+
+namespace AMDiS
+{
+
+  template<typename T>
+  void diagPrecond(DOFMatrix *A, DOFVector<T> *vec,
+		   DOFVector<BoundaryType> *bound)
+  {
+    FUNCNAME("QN_Precond::diagPrecond()");
+
+    TEST(A)("No matrix; doing nothing\n");
+
+    DOFMatrix::Iterator rowIterator(A, USED_DOFS);
+    typename DOFVector<T>::Iterator vecIterator(vec, USED_DOFS);
+
+    if (bound) {
+      DOFVector<BoundaryType>::Iterator
+	bIterator(const_cast<DOFVector<BoundaryType>*>(bound), USED_DOFS);
+      
+      for (vecIterator.reset(), rowIterator.reset(), bIterator.reset();
+	   !vecIterator.end(); ++vecIterator, ++bIterator, ++rowIterator)
+	{
+	  // only non-dirichlet nodes will be preconditioned
+	  if ((*bIterator) <= 0 && rowIterator->size() != 0)
+	    (*vecIterator) *= (1.0 / (*rowIterator)[0].entry);
+	}
+    } else {
+      for (vecIterator.reset(), rowIterator.reset(); !vecIterator.end();
+	   ++vecIterator, ++rowIterator)
+	{
+	  if (rowIterator->size() != 0)
+	    (*vecIterator) *= (1.0 / (*rowIterator)[0].entry);
+	}
+    }
+    
+    return;
+  }
+
+  template<typename T>
+  void aXpY(double alpha, const DOFVector<T>& x, DOFVector<T>& y,
+	    DOFVector<BoundaryType> *bound)
+  {
+    FUNCNAME("QN_Precond::aXpY()");
+    const DOFAdmin *admin;
+
+    TEST_EXIT(x.getFESpace() && y.getFESpace())
+      ("feSpace is NULL: %8X, %8X\n", x.getFESpace(), y.getFESpace());
+    TEST_EXIT((admin = x.getFESpace()->getAdmin()) &&
+	      (admin == y.getFESpace()->getAdmin()))
+      ("no admin or different admins: %8X, %8X\n",
+       x.getFESpace()->getAdmin(), y.getFESpace()->getAdmin());
+    TEST_EXIT(static_cast<int>(x.getSize()) >= admin->getUsedSize())
+      ("size = %d too small: admin->size = %d\n", x.getSize(),
+       admin->getUsedSize());
+    TEST_EXIT(static_cast<int>(y.getSize()) >= admin->getUsedSize())
+      ("y.size = %d too small: admin->size = %d\n", y.getSize(),
+       admin->getUsedSize());
+
+    typename DOFVector<T>::Iterator
+      xIterator(dynamic_cast<DOFIndexed<T>*>(const_cast<DOFVector<T>*>(&x)),
+		USED_DOFS);
+    typename DOFVector<T>::Iterator yIterator(dynamic_cast<DOFIndexed<T>*>(&y),
+					      USED_DOFS);
+
+    if (bound) {
+      DOFVector<BoundaryType>::Iterator
+	bIterator(const_cast<DOFVector<BoundaryType>*>(bound), USED_DOFS);
+      
+      for (xIterator.reset(), yIterator.reset(), bIterator.reset();
+	   !xIterator.end();
+	     ++xIterator, ++yIterator, ++bIterator)
+	{
+	  // only non-dirichlet nodes will be updated
+	  if ((*bIterator) <= 0 )
+	    *yIterator += alpha * (*xIterator);
+	}
+    } else {
+      for (xIterator.reset(), yIterator.reset(); !xIterator.end();
+	   ++xIterator, ++yIterator)
+	{
+	  *yIterator += alpha * (*xIterator);
+	}
+    }
+
+    return;
+  }
+
+  template<typename T>
+  void XpaY(double alpha, const DOFVector<T>& x, DOFVector<T>& y,
+	    DOFVector<BoundaryType> *bound)
+  {
+    FUNCNAME("QN_Precond::aXpY()");
+    const DOFAdmin *admin;
+
+    TEST_EXIT(x.getFESpace() && y.getFESpace())
+      ("feSpace is NULL: %8X, %8X\n", x.getFESpace(), y.getFESpace());
+    TEST_EXIT((admin = x.getFESpace()->getAdmin()) &&
+	      (admin == y.getFESpace()->getAdmin()))
+      ("no admin or different admins: %8X, %8X\n",
+       x.getFESpace()->getAdmin(), y.getFESpace()->getAdmin());
+    TEST_EXIT(static_cast<int>(x.getSize()) >= admin->getUsedSize())
+      ("size = %d too small: admin->size = %d\n", x.getSize(),
+       admin->getUsedSize());
+    TEST_EXIT(static_cast<int>(y.getSize()) >= admin->getUsedSize())
+      ("y.size = %d too small: admin->size = %d\n", y.getSize(),
+       admin->getUsedSize());
+
+    typename DOFVector<T>::Iterator
+      xIterator(dynamic_cast<DOFIndexed<T>*>(const_cast<DOFVector<T>*>(&x)),
+		USED_DOFS);
+    typename DOFVector<T>::Iterator yIterator(dynamic_cast<DOFIndexed<T>*>(&y),
+					      USED_DOFS);
+
+    if (bound) {
+      DOFVector<BoundaryType>::Iterator
+	bIterator(const_cast<DOFVector<BoundaryType>*>(bound), USED_DOFS);
+      
+      for (xIterator.reset(), yIterator.reset(), bIterator.reset();
+	   !xIterator.end();
+	   ++xIterator, ++yIterator, ++bIterator)
+	{
+	  // only non-dirichlet nodes will be updated
+	  if ((*bIterator) <= 0 ) {
+	    *yIterator *= alpha;
+	    *yIterator += *xIterator;
+	  }
+	}
+    } else {
+      for (xIterator.reset(), yIterator.reset(); !xIterator.end();
+	   ++xIterator, ++yIterator)
+	{
+	  *yIterator *= alpha;
+	  *yIterator += *xIterator;
+	}
+    }
+
+    return;
+  }
+
+}