</table>
<hr>
<pre>/***************************************************************************
 * $Id: schrodinger2.cpp,v 1.9 2004/02/21 09:51:20 troyer Exp $
 *
 * Another example of the Lanczos method with Scrodinger wave 
 * equation in a potential field.
 *
 * Copyright (C) 2001-2003 by Prakash Dayal &lt;prakash@comp-phys.org&gt;
 *                            Matthias Troyer &lt;troyer@comp-phys.org&gt;
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program 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 General Public License for more details.
 *
 **************************************************************************/

#include &lt;ietl/lanczos.h&gt;
#include &lt;ietl/vectorspace.h&gt;
#include &lt;ietl/interface/blitz.h&gt;
#include &lt;boost/random/lagged_fibonacci.hpp&gt;
#include &lt;blitz/array.h&gt;
#include &lt;blitz/range.h&gt;
#include &lt;blitz/array/stencil-et.h&gt;
#include &lt;cmath&gt;
#include &lt;limits&gt;
#include &lt;iterator&gt;
#include &lt;iostream&gt;

template &lt;class T=double&gt;
class Hamiltonian {
  static const int dim=2;
public:
  Hamiltonian(int N_, double m_, double k, double deltax)
    : N(N_), m(m_), V(N,N), I(1,N-2),deltax_(deltax) {
    V.resize(N,N);
    blitz::firstIndex i;
    blitz::secondIndex j;
    V = (blitz::pow2((i - N/2)*deltax) + blitz::pow2((j - N/2)*deltax)) * k;
  }
  
  void mult(const blitz::Array&lt;T,dim&gt;&amp; x, blitz::Array&lt;T,dim&gt;&amp; y) const {
    y=0.;
    blitz::Array&lt;T,dim&gt; xi = x(I,I);
    blitz::Array&lt;T,dim&gt; yi = y(I,I);
    blitz::Array&lt;T,dim&gt; Vi = V(I,I);
    yi = -blitz::Laplacian2D(xi)/(2*m)/(deltax_*deltax_) + Vi*xi; 
  }  
private:
  int N;
  double m;
  blitz::Array&lt;T,dim&gt; V;
  blitz::Range I;
  double deltax_;
};

namespace ietl {
  template&lt;class T, int D&gt;
  inline void mult (const Hamiltonian&lt;T&gt;&amp; h, const blitz::Array&lt;T,D&gt;&amp; x, blitz::Array&lt;T,D&gt;&amp; y) {
    h.mult(x,y);
  }

  template&lt;class VectorType&gt;
  class vectorspace2d {
  public:
    typedef VectorType vector_type; 
    typedef typename  VectorType::T_numtype scalar_type;
    typedef int size_type;    
    vectorspace2d(size_type n, size_type m):n_(n), m_(m){}
    inline size_type vec_dimension() const{
      return n_ * m_;
    }
  
    void project(vector_type&amp; vector) const {
      vector(blitz::Range(0,n_-1),0) = 0.;
      vector(blitz::Range(0,n_-1),m_-1) = 0.;
      vector(0,blitz::Range(0,m_-1)) = 0.;
      vector(n_-1,blitz::Range(0,m_-1)) = 0.;
    }
    
    vector_type new_vector()const {
      return VectorType(n_,m_);
    }
  
  private:
    size_type n_; 
    size_type m_;
  };
}

int main() {  
  double m = 1.;
  int N =4;
  typedef blitz::Array&lt;double,2&gt; Vector;
  typedef ietl::vectorspace2d&lt;Vector&gt; Vecspace;
  typedef boost::lagged_fibonacci607 Gen;  
  Vecspace vec(N,N);
  
  double k = 1.;
  double deltax = 0.1;
  Hamiltonian&lt;double&gt; ham(N,m,k,deltax);
  
  Gen mygen;
  ietl::lanczos&lt;Hamiltonian&lt;double&gt;,Vecspace&gt; lanczos(ham,vec);    
  int max_iter =  100*N;  
  double rel_tol = 500*std::numeric_limits&lt;double&gt;::epsilon();
  double abs_tol = std::pow(std::numeric_limits&lt;double&gt;::epsilon(),2./3);
  std::cout &lt;&lt; &quot;Calculation of 3 lowest converged eigenvalues\n\n&quot;;
  std::cout &lt;&lt; &quot;-----------------------------------\n\n&quot;;
  
  int n_lowest_eigenval = 3;
  std::vector&lt;double&gt; eigen;
  std::vector&lt;double&gt; err;
  std::vector&lt;int&gt; multiplicity;
                                          
  ietl::lanczos_iteration_nlowest&lt;double&gt; 
    iter(max_iter, n_lowest_eigenval, rel_tol, abs_tol);
  try {
    lanczos.calculate_eigenvalues(iter,mygen);
    eigen = lanczos.eigenvalues();
    err = lanczos.errors();
    multiplicity = lanczos.multiplicities();
  }
  catch (std::runtime_error&amp; e) {
    std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
  } 

  std::cout &lt;&lt; &quot;#            eigenvalue                error             multiplicity\n&quot;;

  for (int i=0;i&lt;eigen.size();++i) {
    std::cout &lt;&lt; i &lt;&lt; &quot;\t&quot; &lt;&lt; eigen[i] &lt;&lt; &quot;\t&quot; &lt;&lt; err[i] &lt;&lt; &quot;\t&quot; 
	      &lt;&lt; multiplicity[i] &lt;&lt; &quot;\n&quot;;
  }
  
  // call of eigenvectors function follows: 
  
  std::cout &lt;&lt; &quot;\nEigen vectors computations for 3 lowest eigenvalues:\n\n&quot;;
  std::cout.precision(10);  
  std::vector&lt;double&gt;::iterator start = eigen.begin();
  std::vector&lt;double&gt;::iterator end = eigen.begin()+3;
  std::vector&lt;Vector&gt; eigenvectors; // for storing the eigen vectors. 
  ietl::Info&lt;double&gt; info; // (m1, m2, ma, eigenvalue, residual, status).
  
  try {
    lanczos.eigenvectors(start, end, std::back_inserter(eigenvectors),info, mygen); 
  }
  catch (std::runtime_error&amp; e) {
    std::cout &lt;&lt; e.what() &lt;&lt; std::endl;
  }  
  
  std::cout &lt;&lt; &quot;Printing eigen Vectors:&quot; &lt;&lt; std::endl &lt;&lt; std::endl; 
  for(std::vector&lt;Vector&gt;::iterator it = eigenvectors.begin(); it != eigenvectors.end(); it++){    
    std::cout &lt;&lt; *it &lt;&lt; &quot;\n\n&quot;;
    //std::copy((it)-&gt;begin(),(it)-&gt;end(),std::ostream_iterator&lt;double&gt;(std::cout,&quot; &quot;));
    //std::cout &lt;&lt; &quot;\n\n&quot;;
  }
  
  std::cout &lt;&lt; &quot; Information about the eigen vectors computations:\n\n&quot;;
  for(int i = 0; i &lt; info.size(); i++) 
    std::cout &lt;&lt; &quot; m1(&quot; &lt;&lt; i+1 &lt;&lt; &quot;): &quot; &lt;&lt; info.m1(i) &lt;&lt; &quot;, m2(&quot; &lt;&lt; i+1 &lt;&lt; &quot;): &quot;
	      &lt;&lt; info.m2(i) &lt;&lt; &quot;, ma(&quot; &lt;&lt; i+1 &lt;&lt; &quot;): &quot; &lt;&lt; info.ma(i) &lt;&lt; &quot; eigenvalue(&quot;
	      &lt;&lt; i+1 &lt;&lt; &quot;): &quot; &lt;&lt; info.eigenvalue(i) &lt;&lt; &quot; residual(&quot; &lt;&lt; i+1 &lt;&lt; &quot;): &quot;
	      &lt;&lt; info.residual(i) &lt;&lt; &quot; error_info(&quot; &lt;&lt; i+1 &lt;&lt; &quot;): &quot;
	      &lt;&lt; info.error_info(i) &lt;&lt; std::endl &lt;&lt; std::endl;
  return 0;
}
</pre>
