1 /*
2   This file is part of MADNESS.
3 
4   Copyright (C) 2007,2010 Oak Ridge National Laboratory
5 
6   This program is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published by
8   the Free Software Foundation; either version 2 of the License, or
9   (at your option) any later version.
10 
11   This program is distributed in the hope that it will be useful,
12   but WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14   GNU General Public License for more details.
15 
16   You should have received a copy of the GNU General Public License
17   along with this program; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 
20   For more information please contact:
21 
22   Robert J. Harrison
23   Oak Ridge National Laboratory
24   One Bethel Valley Road
25   P.O. Box 2008, MS-6367
26 
27   email: harrisonrj@ornl.gov
28   tel:   865-241-3937
29   fax:   865-572-0680
30 */
31 
32 #ifndef EIGSOLVER_H_
33 #define EIGSOLVER_H_
34 #include <madness/mra/mra.h>
35 #include <madness/world/MADworld.h>
36 #include <vector>
37 #include "electronicstructureparams.h"
38 
39 namespace madness
40 {
41 //***************************************************************************
42 /// This is the interface the an observer wishing to receive output must
43 /// implement. This call back gives the current eigenfunctions, eigenvalues,
44 /// and the density.
45 /// This is a test LaTeX formula
46 /// The Pythagorean theorem is
47 /// \f[
48 /// c^2 = a^2 + b^2
49 /// \f]
50 template <typename T, int NDIM>
51 class IEigSolverObserver
52 {
53   typedef Function<T,NDIM> funcT;
54 public:
55   virtual void iterateOutput(const std::vector<funcT>& phis,
56       const std::vector<double>& eigs, const Function<double, NDIM>& rho, const int& iter, bool periodic) = 0;
57 
~IEigSolverObserver()58   virtual ~IEigSolverObserver() {};
59 };
60 //***************************************************************************
61 
62 class KPoint
63 {
64 public:
KPoint(double kx,double ky,double kz,double weight)65   KPoint(double kx, double ky, double kz, double weight)
66   {
67     _kx = kx; _ky = ky; _kz = kz;
68     _weight = weight;
69   }
70 
71   //*************************************************************************
kx()72   double kx() {return _kx;}
ky()73   double ky() {return _ky;}
kz()74   double kz() {return _kz;}
75   //*************************************************************************
76 
77   //*************************************************************************
weight()78   double weight() {return _weight;}
79   //*************************************************************************
80 
81 private:
82   //*************************************************************************
83   // the actual k-point
84   double _kx;
85   double _ky;
86   double _kz;
87   //*************************************************************************
88 
89   //*************************************************************************
90   // weight
91   double _weight;
92   //*************************************************************************
93 
94 };
95 
96 //***************************************************************************
97 template <typename T, int NDIM>
98 class EigSolverOp
99 {
100   // Typedef's
101   typedef Function<T,NDIM> funcT;
102 public:
103   //*************************************************************************
104   // Constructor
EigSolverOp(World & world,double coeff,double thresh)105   EigSolverOp(World& world, double coeff, double thresh)
106     :  _world(world), _coeff(coeff), _thresh(thresh) {}
107   //*************************************************************************
108 
109   //*************************************************************************
110   // Destructor
~EigSolverOp()111   virtual ~EigSolverOp() {}
112   //*************************************************************************
113 
114   //*************************************************************************
115   /// Is there an orbitally-dependent term?
116   virtual bool is_od() = 0;
117   //*************************************************************************
118 
119   //*************************************************************************
120   /// Is there a density-dependent term?
121   virtual bool is_rd() = 0;
122   //*************************************************************************
123 
124   //*************************************************************************
125   /// Build the potential from a density if a density-dependent operator.
prepare_op(funcT rho)126   virtual void prepare_op(funcT rho) {}
127   //*************************************************************************
128 
129   //*************************************************************************
130   /// Orbital-dependent portion of operator
op_o(const std::vector<funcT> & phis,const funcT & psi)131   virtual funcT op_o(const std::vector<funcT>& phis, const funcT& psi)
132   {
133     funcT func = FunctionFactory<T,NDIM>(_world);
134     return func;
135   }
136   //*************************************************************************
137 
138   //*************************************************************************
139   /// Density-dependent portion of operator
op_r(const funcT & rho,const funcT & psi)140   virtual funcT op_r(const funcT& rho, const funcT& psi)
141   {
142     funcT func = FunctionFactory<T,NDIM>(_world);
143     return func;
144   }
145   //*************************************************************************
146 
147   //*************************************************************************
148   /// Orbital-dependent portion of operator
multi_op_o(const std::vector<funcT> & phis)149   virtual std::vector<funcT> multi_op_o(const std::vector<funcT>& phis)
150   {
151     // Collection of empty functions
152     std::vector<funcT> newphis(phis.size(), FunctionFactory<T,NDIM>(_world));
153     for (unsigned int pi = 0; pi < phis.size(); pi++)
154     {
155       newphis[pi] = op_o(phis, phis[pi]);
156     }
157     _world.gop.fence();
158     return newphis;
159   }
160   //*************************************************************************
161 
162   //*************************************************************************
163   /// Density-dependent portion of operator
multi_op_r(const funcT & rho,const std::vector<funcT> & phis)164   virtual std::vector<funcT> multi_op_r(const funcT& rho, const std::vector<funcT>& phis)
165   {
166     std::vector<funcT> newphis(phis.size(), FunctionFactory<T,NDIM>(_world));
167     for (unsigned int pi = 0; pi < phis.size(); pi++)
168     {
169       newphis[pi] = op_r(rho, phis[pi]);
170     }
171     _world.gop.fence();
172     return newphis;
173   }
174   //*************************************************************************
175 
176   //*************************************************************************
coeff()177   double coeff() {return _coeff;}
178   //*************************************************************************
179 
180   //*************************************************************************
messsageME()181   std::string messsageME()
182   {
183     return _messageME;
184   }
185   //*************************************************************************
186 
187   //*************************************************************************
188   World& _world;
189   //*************************************************************************
190 
191 protected:
192   //*************************************************************************
thresh()193   double thresh() {return _thresh;}
194   //*************************************************************************
195 
196   //*************************************************************************
messageME(std::string messageME)197   void messageME(std::string messageME)
198   {
199     _messageME = messageME;
200   }
201   //*************************************************************************
202 
203 private:
204   //*************************************************************************
205   double _coeff;
206   //*************************************************************************
207 
208   //*************************************************************************
209   double _thresh;
210   //*************************************************************************
211 
212   //*************************************************************************
213   std::string _messageME;
214   //*************************************************************************
215 
216 };
217 //***************************************************************************
218 
219 //***************************************************************************
220 /// The EigSolver class is the class that is the workhorse of both the Hartree
221 /// Fock and the DFT algorithms. This class relies on the wrapper class to
222 /// give it a list of operators to implement as its potential. This should
223 /// allow for much more reuse.
224 template <typename T, int NDIM>
225 class EigSolver
226 {
227 public:
228   //*************************************************************************
229   // Typedef's
230   typedef Function<T,NDIM> funcT;
231 //  typedef KPoint<NDIM> kvecT;
232   typedef Vector<double,NDIM> kvecT;
233   typedef SeparatedConvolution<double,NDIM> operatorT;
234   typedef std::shared_ptr<operatorT> poperatorT;
235   //*************************************************************************
236 
237   //*************************************************************************
238   /// Constructor for periodic system
239   EigSolver(World& world, std::vector<funcT> phis, std::vector<double> eigs,
240       std::vector<EigSolverOp<T,NDIM>*> ops, std::vector<kvecT> kpoints,
241       ElectronicStructureParams params);
242   //*************************************************************************
243 
244   //*************************************************************************
245   /// Constructor for non-periodic system
246   EigSolver(World& world, std::vector<funcT> phis, std::vector<double> eigs,
247       std::vector<EigSolverOp<T,NDIM>*> ops, ElectronicStructureParams params);
248   //*************************************************************************
249 
250   //*************************************************************************
251   /// Destructor
252   virtual ~EigSolver();
253   //*************************************************************************
254 
255   //*************************************************************************
256   /// This solver has not been optimized for usage in parallel. This solver
257   /// processes each eigenfunction in a serial fashion.
258   void solve(int maxits);
259   //*************************************************************************
260 
261   //*************************************************************************
262   /// This solver has been optimized for usage in parallel. This solver
263   /// processes each eigenfunction in a parallel fashion.
264   void multi_solve(int maxits);
265   //*************************************************************************
266 
267   //*************************************************************************
get_eig(int indx)268   double get_eig(int indx)
269   {
270     return _eigs[indx];
271   }
272   //*************************************************************************
273 
274   //*************************************************************************
get_phi(int indx)275   funcT get_phi(int indx)
276   {
277     return _phis[indx];
278   }
279   //*************************************************************************
280 
281   //*************************************************************************
phis()282   const std::vector<funcT>& phis()
283   {
284     return _phis;
285   }
286   //*************************************************************************
287 
288   //*************************************************************************
eigs()289   const std::vector<double>& eigs()
290   {
291     return _eigs;
292   }
293   //*************************************************************************
294 
295   //*************************************************************************
addObserver(IEigSolverObserver<T,NDIM> * obs)296   void addObserver(IEigSolverObserver<T,NDIM>* obs)
297   {
298     _obs.push_back(obs);
299   }
300   //*************************************************************************
301 
302   //*************************************************************************
303   /// Computes a matrix element given the left and right functions.
304   T matrix_element(const funcT& phii, const funcT& phij);
305   //*************************************************************************
306 
307   //*************************************************************************
308   /// Prints a matrix element given the left and right functions.
309   void print_matrix_elements(const funcT& phii, const funcT& phij);
310   //*************************************************************************
311 
312   //*************************************************************************
313   /// Preprocesses the operators for doing an iteration of "eigensolving".
314   void prepare_ops();
315   //*************************************************************************
316 
317   //*************************************************************************
318   /// Makes the BSH Green's functions for the parallel solver (multi_solve()).
319   void make_bsh_operators();
320   //*************************************************************************
321 
322   //*************************************************************************
323   void update_occupation();
324   //*************************************************************************
325 
326   //*************************************************************************
327   /// Computes the electronic density
328   static funcT compute_rho(std::vector<funcT> phis, std::vector<double> occs,
329       const World& world);
330   //*************************************************************************
331 
332 private:
333   //*************************************************************************
334   /// List of the functions
335   std::vector<funcT> _phis;
336   //*************************************************************************
337 
338   //*************************************************************************
339   /// List of the eigenvalues
340   std::vector<double> _eigs;
341   //*************************************************************************
342 
343   //*************************************************************************
344   /// List of the ops
345   std::vector< EigSolverOp<T,NDIM>* > _ops;
346   //*************************************************************************
347 
348   //*************************************************************************
349   /// List of the ops
350   std::vector<kvecT> _kpoints;
351   //*************************************************************************
352 
353   //*************************************************************************
354   World& _world;
355   //*************************************************************************
356 
357   //*************************************************************************
358   // List of the obs
359   std::vector<IEigSolverObserver<T,NDIM>*> _obs;
360   //*************************************************************************
361 
362   // Electronic charge density
363   //*************************************************************************
364   Function<double,NDIM> _rho;
365   //*************************************************************************
366 
367   //*************************************************************************
368   // List of the ops
369   std::vector<poperatorT> _bops;
370   //*************************************************************************
371 
372   //*************************************************************************
373   // List of the occupation numbers
374   std::vector<double> _occs;
375   //*************************************************************************
376 
377   //*************************************************************************
378   ElectronicStructureParams _params;
379   //*************************************************************************
380 
381 };
382 //***************************************************************************
383 
384 }
385 
386 #endif /*EIGSOLVER_H_*/
387 
388