MADNESS  version 0.9
solver.h
Go to the documentation of this file.
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  $Id$
32 */
33 #include <madness/mra/mra.h>
34 //#include <madness/mra/lbdeux.h>
35 #include <madness/world/world.h>
36 #include <madness/tensor/solvers.h>
37 #include <vector>
38 #include <madness/fortran_ctypes.h>
39 #include <cmath>
40 
41 #include "poperator.h"
42 #include "libxc.h"
44 #include "complexfun.h"
45 #include "esolver.h"
46 
47 #ifndef SOLVER_H_
48 
49 using std::endl;
50 using std::setfill;
51 using std::setw;
52 using std::ostream;
53 
61 //*****************************************************************************
62 /* static double onesfunc(const coordT& x) */
63 /* { */
64 /* return 1.0; */
65 /* } */
66 //*****************************************************************************
67 
68 namespace madness
69 {
70  //***************************************************************************
75  template <typename T>
76  T stheta_fd(const T& x)
77  {
78  if (x > 50.0)
79  {
80  return 1.0;
81  }
82  else if (x < -50.0)
83  {
84  return 0.0;
85  }
86  else
87  {
88  return 1.0/(1.0 + exp(-x));
89  }
90  }
91  //***************************************************************************
92 
93  // NOTE: so this is totally hacked because of the requirement of using a box
94  // of L*L*L rather than the convention of using a combination of
95  // lattice vectors and reciprocal lattice vectors (FOR NOW)
96  // On second thought, it might be ok for general use if used "right".
97  //***************************************************************************
98  template <std::size_t NDIM>
99  class ComplexExp : public FunctionFunctorInterface<double_complex,NDIM> {
100  public:
104  const vec3dT exponent;
105 
106  ComplexExp(vec3dT exponent, double_complex coeff)
107  : exponent(exponent), coeff(coeff) {}
108 
109  double_complex operator()(const coordT& x) const {
110  double sum = 0.0;
111  for (std::size_t i=0; i<NDIM; ++i) {
112  sum += x[i]*exponent[i];
113  };
114  return coeff*exp(double_complex(0.0,sum));
115  }
116  };
117  //***************************************************************************
118 
119 
120  //***************************************************************************
121  class WSTAtomicBasisFunctor : public FunctionFunctorInterface<double_complex,3> {
122  private:
123  const AtomicBasisFunction aofunc;
124  double L;
125  double kx, ky, kz;
126 
127  std::vector<coord_3d> specialpt;
128  public:
129  WSTAtomicBasisFunctor(const AtomicBasisFunction& aofunc, double L, double kx, double ky, double kz)
130  : aofunc(aofunc), L(L), kx(kx), ky(ky), kz(kz)
131  {
132  double x, y, z;
133  aofunc.get_coords(x,y,z);
134  coord_3d r;
135  r[0]=x; r[1]=y; r[2]=z;
136  specialpt=std::vector<coord_3d>(1,r);
137  }
138 
140 
142  double_complex sum = 0.0;
143  const int R = 1;
144  const double_complex I = double_complex(0.0,1.0);
145  for (int i=-R; i<=+R; i++) {
146  double xx = x[0]+i*L;
147  for (int j=-R; j<=+R; j++) {
148  double yy = x[1]+j*L;
149  for (int k=-R; k<=+R; k++) {
150  double zz = x[2]+k*L;
151  sum += -exp(-I*(kx*xx+ky*yy+kz*zz+constants::pi/2))*aofunc(xx, yy, zz);
152  //print(kx,ky,kz,exp(-I*(kx*xx+ky*yy+kz*zz+constants::pi/2)),aofunc(xx, yy, zz));
153  }
154  }
155  }
156  return sum;
157  }
158 
159  std::vector<coord_3d> special_points() const {return specialpt;}
160  };
161  //***************************************************************************
162 
163 
165  //***************************************************************************
166  class DipoleFunctor : public FunctionFunctorInterface<double,3> {
167  private:
168  const int axis;
169  public:
170  DipoleFunctor(int axis) : axis(axis) {}
171  double operator()(const coordT& x) const {
172  return x[axis];
173  }
174  virtual ~DipoleFunctor() {}
175  };
176  //***************************************************************************
177 
191  //***************************************************************************
192  template <typename T, int NDIM>
193  class SubspaceK
194  {
195  // Typedef's
196  typedef std::complex<T> valueT;
198  typedef std::vector<functionT> vecfuncT;
199  typedef std::pair<vecfuncT,vecfuncT> pairvecfuncT;
200  typedef std::vector<pairvecfuncT> subspaceT;
201  typedef Tensor<valueT> tensorT;
202  typedef std::vector<tensorT> vectensorT;
203  typedef std::vector<subspaceT> vecsubspaceT;
204 
205  //*************************************************************************
206  World& _world;
207  //*************************************************************************
208 
209  //*************************************************************************
210  vectensorT _Q;
211  //*************************************************************************
212 
213  //*************************************************************************
214  vecsubspaceT _subspace;
215  //*************************************************************************
216 
217  //*************************************************************************
218  std::vector<KPoint> _kpoints;
219  //*************************************************************************
220 
221  //*************************************************************************
223  //*************************************************************************
224 
225  //*************************************************************************
226  double _residual;
227  //*************************************************************************
228 
229  public:
230 
231  //*************************************************************************
233  const std::vector<KPoint>& kpoints) : _world(world), _kpoints(kpoints),
234  _params(params)
235  {
236  _residual = 1e6;
237  for (unsigned int kp = 0; kp < _kpoints.size(); kp++)
238  {
239  _Q.push_back(tensorT(1,1));
240  _subspace.push_back(subspaceT());
241  }
242  }
243  //*************************************************************************
244 
245  //*************************************************************************
246  void update_subspace(vecfuncT& awfs_new,
247  vecfuncT& bwfs_new,
248  const vecfuncT& awfs_old,
249  const vecfuncT& bwfs_old)
250  {
251  // compute residuals (total)
252  vecfuncT t_rm = sub(_world, awfs_old, awfs_new);
253  if (_params.spinpol)
254  {
255  vecfuncT br = sub(_world, bwfs_old, bwfs_new);
256  t_rm.insert(t_rm.end(), br.begin(), br.end());
257  }
258  std::vector<double> rnvec = norm2<valueT,NDIM>(_world, t_rm);
259  if (_world.rank() == 0)
260  {
261  double rnorm = 0.0;
262  for (unsigned int i = 0; i < rnvec.size(); i++) rnorm += rnvec[i];
263  if (_world.rank() == 0) print("residual = ", rnorm);
264  _residual = rnorm;
265  }
266  _world.gop.broadcast(_residual, 0);
267 
268  for (unsigned int kp = 0; kp < _kpoints.size(); kp++)
269  {
270  KPoint kpoint = _kpoints[kp];
271 
272  vecfuncT k_phisa(awfs_old.begin() + kpoint.begin, awfs_old.begin() + kpoint.end);
273  vecfuncT k_phisb(bwfs_old.begin() + kpoint.begin, bwfs_old.begin() + kpoint.end);
274  vecfuncT k_awfs(awfs_new.begin() + kpoint.begin, awfs_new.begin() + kpoint.end);
275  vecfuncT k_bwfs(bwfs_new.begin() + kpoint.begin, bwfs_new.begin() + kpoint.end);
276 
277  // compute residuals for k-point
278  // concatentate up and down spins
279  vecfuncT k_rm = sub(_world, k_phisa, k_awfs);
280  vecfuncT k_vm(k_phisa);
281  if (_params.spinpol)
282  {
283  vecfuncT k_br = sub(_world, k_phisb, k_bwfs);
284  k_rm.insert(k_rm.end(), k_br.begin(), k_br.end());
285  k_vm.insert(k_vm.end(), k_phisb.begin(), k_phisb.end());
286  }
287 
288  // Update subspace and matrix Q
289  compress(_world, k_vm, false);
290  compress(_world, k_rm, false);
291  _world.gop.fence();
292  subspaceT k_subspace = _subspace[kp];
293  k_subspace.push_back(pairvecfuncT(k_vm,k_rm));
294 
295  int m = k_subspace.size();
296  tensorT ms(m);
297  tensorT sm(m);
298  for (int s = 0; s < m; s++)
299  {
300  const vecfuncT& k_vs = k_subspace[s].first;
301  const vecfuncT& k_rs = k_subspace[s].second;
302  for (unsigned int i = 0; i < k_vm.size(); i++)
303  {
304  ms[s] += k_vm[i].inner_local(k_rs[i]);
305  sm[s] += k_vs[i].inner_local(k_rm[i]);
306  }
307  }
308  _world.gop.sum(ms.ptr(),m);
309  _world.gop.sum(sm.ptr(),m);
310 
311  tensorT newQ(m,m);
312  if (m > 1) newQ(Slice(0,-2),Slice(0,-2)) = _Q[kp];
313  newQ(m-1,_) = ms;
314  newQ(_,m-1) = sm;
315 
316  _Q[kp] = newQ;
317  if (_world.rank() == 0) print(_Q[kp]);
318 
319  // Solve the subspace equations
320  tensorT c;
321  if (_world.rank() == 0) {
322  double rcond = 1e-12;
323  while (1) {
324  c = KAIN(_Q[kp],rcond);
325  if (abs(c[m-1]) < 3.0) {
326  break;
327  }
328  else if (rcond < 0.01) {
329  if (_world.rank() == 0)
330  print("Increasing subspace singular value threshold ", c[m-1], rcond);
331  rcond *= 100;
332  }
333  else {
334  if (_world.rank() == 0)
335  print("Forcing full step due to subspace malfunction");
336  c = 0.0;
337  c[m-1] = 1.0;
338  break;
339  }
340  }
341  }
342 
343  _world.gop.broadcast_serializable(c, 0);
344  if (_world.rank() == 0) {
345  //print("Subspace matrix");
346  //print(Q);
347  print("Subspace solution", c);
348  }
349 
350  // Form linear combination for new solution
351  vecfuncT k_phisa_new = zero_functions<valueT,NDIM>(_world, k_phisa.size());
352  vecfuncT k_phisb_new = zero_functions<valueT,NDIM>(_world, k_phisb.size());
353  compress(_world, k_phisa_new, false);
354  compress(_world, k_phisb_new, false);
355  _world.gop.fence();
356  std::complex<double> one = std::complex<double>(1.0,0.0);
357  unsigned int norbitals = awfs_old.size() / _kpoints.size();
358  for (unsigned int m = 0; m < k_subspace.size(); m++)
359  {
360  const vecfuncT& k_vm = k_subspace[m].first;
361  const vecfuncT& k_rm = k_subspace[m].second;
362  // WSTHORNTON Stopped here!
363  const vecfuncT vma(k_vm.begin(),k_vm.begin() + norbitals);
364  const vecfuncT rma(k_rm.begin(),k_rm.begin() + norbitals);
365  const vecfuncT vmb(k_vm.end() - norbitals, k_vm.end());
366  const vecfuncT rmb(k_rm.end() - norbitals, k_rm.end());
367 
368  gaxpy(_world, one, k_phisa_new, c(m), vma, false);
369  gaxpy(_world, one, k_phisa_new,-c(m), rma, false);
370  gaxpy(_world, one, k_phisb_new, c(m), vmb, false);
371  gaxpy(_world, one, k_phisb_new,-c(m), rmb, false);
372  }
373  _world.gop.fence();
374 
375  if (_params.maxsub <= 1) {
376  // Clear subspace if it is not being used
377  k_subspace.clear();
378  }
379  else if (k_subspace.size() == _params.maxsub) {
380  // Truncate subspace in preparation for next iteration
381  k_subspace.erase(k_subspace.begin());
382  _Q[kp] = _Q[kp](Slice(1,-1),Slice(1,-1));
383  }
384  // Save subspace
385  _subspace[kp] = k_subspace;
386 
387  for (unsigned int wi = kpoint.begin, fi = 0; wi < kpoint.end;
388  wi++, fi++)
389  {
390  awfs_new[wi] = k_phisa_new[fi];
391  bwfs_new[wi] = k_phisb_new[fi];
392  }
393  }
394  }
395  //*************************************************************************
396 
397  };
398 
410  //***************************************************************************
411  template <typename T, int NDIM>
412  class Subspace
413  {
414  // Typedef's
415  typedef std::complex<T> valueT;
417  typedef std::vector<functionT> vecfuncT;
418  typedef std::pair<vecfuncT,vecfuncT> pairvecfuncT;
419  typedef std::vector<pairvecfuncT> subspaceT;
420  typedef Tensor<valueT> tensorT;
421 
422  //*************************************************************************
423  World& _world;
424  //*************************************************************************
425 
426  //*************************************************************************
427  tensorT _Q;
428  //*************************************************************************
429 
430  //*************************************************************************
431  subspaceT _subspace;
432  //*************************************************************************
433 
434  //*************************************************************************
435  std::vector<KPoint> _kpoints;
436  //*************************************************************************
437 
438  //*************************************************************************
440  //*************************************************************************
441 
442  public:
443 
444  //*************************************************************************
445  Subspace(World& world, const ElectronicStructureParams& params)
446  : _world(world), _params(params)
447  {
448  }
449  //*************************************************************************
450 
451  //*************************************************************************
452  void update_subspace(vecfuncT& awfs_new,
453  vecfuncT& bwfs_new,
454  const vecfuncT& awfs_old,
455  const vecfuncT& bwfs_old,
456  const vecfuncT& rm)
457  {
458  // concatentate up and down spins
459  vecfuncT vm = awfs_old;
460  if (_params.spinpol)
461  {
462  vm.insert(vm.end(), bwfs_old.begin(), bwfs_old.end());
463  }
464 
465  // Update subspace and matrix Q
466  compress(_world, vm, false);
467  compress(_world, rm, false);
468  _world.gop.fence();
469  _subspace.push_back(pairvecfuncT(vm,rm));
470 
471  int m = _subspace.size();
472  tensorT ms(m);
473  tensorT sm(m);
474  for (int s=0; s<m; s++)
475  {
476  const vecfuncT& vs = _subspace[s].first;
477  const vecfuncT& rs = _subspace[s].second;
478  for (unsigned int i=0; i<vm.size(); i++)
479  {
480  ms[s] += vm[i].inner_local(rs[i]);
481  sm[s] += vs[i].inner_local(rm[i]);
482  }
483  }
484  _world.gop.sum(ms.ptr(),m);
485  _world.gop.sum(sm.ptr(),m);
486 
487  tensorT newQ(m,m);
488  if (m > 1) newQ(Slice(0,-2),Slice(0,-2)) = _Q;
489  newQ(m-1,_) = ms;
490  newQ(_,m-1) = sm;
491 
492  _Q = newQ;
493  if (_world.rank() == 0) print(_Q);
494 
495  // Solve the subspace equations
496  tensorT c;
497  if (_world.rank() == 0) {
498  double rcond = 1e-12;
499  while (1) {
500  c = KAIN(_Q,rcond);
501  if (abs(c[m-1]) < 3.0) {
502  break;
503  }
504  else if (rcond < 0.01) {
505  if (_world.rank() == 0)
506  print("Increasing subspace singular value threshold ", c[m-1], rcond);
507  rcond *= 100;
508  }
509  else {
510  if (_world.rank() == 0)
511  print("Forcing full step due to subspace malfunction");
512  c = 0.0;
513  c[m-1] = 1.0;
514  break;
515  }
516  }
517  }
518 
519  _world.gop.broadcast_serializable(c, 0);
520  if (_world.rank() == 0) {
521  //print("Subspace matrix");
522  //print(Q);
523  print("Subspace solution", c);
524  }
525 
526  // Form linear combination for new solution
527  vecfuncT phisa_new = zero_functions<valueT,NDIM>(_world, awfs_old.size());
528  vecfuncT phisb_new = zero_functions<valueT,NDIM>(_world, bwfs_old.size());
529  compress(_world, phisa_new, false);
530  compress(_world, phisb_new, false);
531  _world.gop.fence();
532  std::complex<double> one = std::complex<double>(1.0,0.0);
533  for (unsigned int m=0; m<_subspace.size(); m++) {
534  const vecfuncT& vm = _subspace[m].first;
535  const vecfuncT& rm = _subspace[m].second;
536  const vecfuncT vma(vm.begin(),vm.begin()+awfs_old.size());
537  const vecfuncT rma(rm.begin(),rm.begin()+awfs_old.size());
538  const vecfuncT vmb(vm.end()-bwfs_old.size(), vm.end());
539  const vecfuncT rmb(rm.end()-bwfs_old.size(), rm.end());
540 
541  gaxpy(_world, one, phisa_new, c(m), vma, false);
542  gaxpy(_world, one, phisa_new,-c(m), rma, false);
543  gaxpy(_world, one, phisb_new, c(m), vmb, false);
544  gaxpy(_world, one, phisb_new,-c(m), rmb, false);
545  }
546  _world.gop.fence();
547 
548  if (_params.maxsub <= 1) {
549  // Clear subspace if it is not being used
550  _subspace.clear();
551  }
552  else if (_subspace.size() == _params.maxsub) {
553  // Truncate subspace in preparation for next iteration
554  _subspace.erase(_subspace.begin());
555  _Q = _Q(Slice(1,-1),Slice(1,-1));
556  }
557  awfs_new = phisa_new;
558  bwfs_new = phisb_new;
559  }
560  //*************************************************************************
561 
562  //*************************************************************************
563  void reproject()
564  {
565  // //if (_world.rank() == 0)
566  // //printf("\n\nreprojecting subspace to wavelet order: %d and thresh: %.5e\n\n",
567  // //FunctionDefaults<3>::get_k(), FunctionDefaults<3>::get_thresh());
568  //
569  // unsigned int m = _subspace.size();
570  // for (unsigned int s = 0; s < m; s++)
571  // {
572  // vecfuncT& vs = _subspace[s].first;
573  // vecfuncT& rs = _subspace[s].second;
574  // reconstruct(_world, vs);
575  // reconstruct(_world, rs);
576  // unsigned int vm = vs.size();
577  // for (unsigned int i = 0; i < vm; i++)
578  // {
579  // vs[i] = madness::project(vs[i], FunctionDefaults<3>::get_k(),
580  // FunctionDefaults<3>::get_thresh(), false);
581  // rs[i] = madness::project(rs[i], FunctionDefaults<3>::get_k(),
582  // FunctionDefaults<3>::get_thresh(), false);
583  // }
584  // _world.gop.fence();
585  // truncate(_world, vs);
586  // truncate(_world, rs);
587  // normalize(_world, vs);
588  // }
589  // _world.gop.fence();
590 
591  }
592  //*************************************************************************
593 
594  };
595 
596 // template <typename T, int NDIM>
597 // struct lbcost {
598 // double leaf_value;
599 // double parent_value;
600 // lbcost(double leaf_value=1.0, double parent_value=0.0) : leaf_value(leaf_value), parent_value(parent_value) {}
601 // double operator()(const Key<NDIM>& key, const FunctionNode<T,NDIM>& node) const {
602 // if (key.level() <= 1) {
603 // return 100.0*(leaf_value+parent_value);
604 // }
605 // else if (node.is_leaf()) {
606 // return leaf_value;
607 // }
608 // else {
609 // return parent_value;
610 // }
611 // }
612 // };
613 
614  //***************************************************************************
615 
623  //***************************************************************************
624  template <typename T, int NDIM>
625  class Solver
626  {
627  // Typedef's
628  typedef std::complex<T> valueT;
632  typedef std::vector<functionT> vecfuncT;
634  typedef Vector<double,NDIM> kvecT;
637  typedef Tensor<double> rtensorT;
638  typedef Tensor<std::complex<double> > ctensorT;
639  typedef Tensor<valueT> tensorT;
640  typedef std::pair<vecfuncT,vecfuncT> pairvecfuncT;
641  typedef std::vector<pairvecfuncT> subspaceT;
642  typedef std::vector<tensorT> vectensorT;
643  typedef std::vector<subspaceT> vecsubspaceT;
644 
645  //*************************************************************************
646  World& _world;
647  //*************************************************************************
648 
649  //*************************************************************************
650  // This variable could either be a nuclear potiential or a nuclear charge
651  // density depending on the "ispotential" boolean variable in the
652  // ElectronicStructureParams class.
653  rfunctionT _vnucrhon;
654  //*************************************************************************
655 
656  //*************************************************************************
657  vecfuncT _phisa;
658  //*************************************************************************
659 
660  //*************************************************************************
661  vecfuncT _phisb;
662  //*************************************************************************
663 
664  //*************************************************************************
665  std::vector<T> _eigsa;
666  //*************************************************************************
667 
668  //*************************************************************************
669  std::vector<T> _eigsb;
670  //*************************************************************************
671 
672  //*************************************************************************
674  //*************************************************************************
675 
676  //*************************************************************************
677  std::vector<KPoint> _kpoints;
678  //*************************************************************************
679 
680  //*************************************************************************
681  std::vector<double> _occsa;
682  //*************************************************************************
683 
684  //*************************************************************************
685  std::vector<double> _occsb;
686  //*************************************************************************
687 
688  //*************************************************************************
689  rfunctionT _rhoa;
690  //*************************************************************************
691 
692  //*************************************************************************
693  rfunctionT _rhob;
694  //*************************************************************************
695 
696  //*************************************************************************
697  rfunctionT _rho;
698  //*************************************************************************
699 
700  //*************************************************************************
701  rfunctionT _vnuc;
702  //*************************************************************************
703 
704  //*************************************************************************
706  //*************************************************************************
707 
708 // //*************************************************************************
709 // vecsubspaceT _subspace;
710 // //*************************************************************************
711 //
712 // //*************************************************************************
713 // vectensorT _Q;
714 // //*************************************************************************
715 
716  //*************************************************************************
717  Subspace<T,NDIM>* _subspace;
718  //*************************************************************************
719 
720  //*************************************************************************
721  MolecularEntity _mentity;
722  //*************************************************************************
723 
724  //*************************************************************************
725  double _residual;
726  //*************************************************************************
727 
728  //*************************************************************************
729  AtomicBasisSet _aobasis;
730  //*************************************************************************
731 
732  //*************************************************************************
733  double _maxthresh;
734  //*************************************************************************
735 
736  //*************************************************************************
737  std::ofstream _outputF;
738  //*************************************************************************
739 
740  //*************************************************************************
741  std::ofstream _matF;
742  //*************************************************************************
743 
744  //*************************************************************************
745  std::ofstream _eigF;
746  //*************************************************************************
747 
748  //*************************************************************************
749  std::ofstream _kmeshF;
750  //*************************************************************************
751 
752  //*************************************************************************
753  int _it;
754  //*************************************************************************
755 
756  //*************************************************************************
757  cvecfuncT _aobasisf;
758  //*************************************************************************
759 
760  //*************************************************************************
761  int _nao;
762  //*************************************************************************
763 
764  public:
765 
766  //*************************************************************************
767  double ttt, sss;
768  void START_TIMER(World& world) {
769  world.gop.fence(); ttt=wall_time(); sss=cpu_time();
770  }
771 
772  void END_TIMER(World& world, const char* msg) {
773  ttt=wall_time()-ttt; sss=cpu_time()-sss; if (world.rank()==0) printf("timer: %20.20s %8.2fs %8.2fs\n", msg, sss, ttt);
774  }
775  //*************************************************************************
776 
777  //*************************************************************************
778  Solver(World& world, const std::string& filename) : _world(world)
779  {
780  init(filename);
782  _residual = 1e5;
784 
785  if (_params.restart==0) initial_guess();
786 // for (unsigned int kp = 0; kp < _kpoints.size(); kp++)
787 // {
788 // _Q.push_back(tensorT(1,1));
789 // _subspace.push_back(subspaceT());
790 // }
791  _subspace = new Subspace<T,NDIM>(world, _params);
792  }
793  //*************************************************************************
794 
795  //*************************************************************************
796  void init(const std::string& filename)
797  {
798 
799  // params
800  if (_world.rank() == 0)
801  {
802  _params.read_file(filename);
803  //_params.fractional = false;
804  }
805  // Send params
806  _world.gop.broadcast_serializable(_params, 0);
807  if (_params.centered)
808  FunctionDefaults<3>::set_cubic_cell(-_params.L/2,_params.L/2);
809  else
810  FunctionDefaults<3>::set_cubic_cell(-_params.L/2,_params.L/2);
811 // FunctionDefaults<3>::set_cubic_cell(0,_params.L);
814 
815  // mentity and aobasis
816  if (_world.rank() == 0)
817  {
818  _aobasis.read_file(_params.basis);
819  _mentity.read_file(filename, _params.fractional);
820  if (_params.centered) _mentity.center();
821  }
822  // Send mentity and aobasis
823  _world.gop.broadcast_serializable(_mentity, 0);
824  _world.gop.broadcast_serializable(_aobasis, 0);
825  // set number of electrons to the total nuclear charge of the mentity
826  _params.nelec = _mentity.total_nuclear_charge();
827  // total number of bands include empty
828  _params.nbands = (_params.nelec/2) + _params.nempty;
829  _params.ncharge = _mentity.total_nuclear_charge();
830  if ((_params.nelec % 2) == 1) _params.nelec++;
831 
832  // Open output files
833  _outputF.open("output.txt");
834  _matF.open("matrix.txt");
835  _eigF.open("eigs.txt");
836 
837  // kmesh
838  if (_params.restart == 0)
839  {
840  if (_params.periodic) // PERIODIC
841  {
842  // GAMMA POINT
843  if ((_params.ngridk0 == 1) && (_params.ngridk1 == 1) && (_params.ngridk2 == 1))
844  {
845  _kpoints.push_back(KPoint(coordT(0.0), 1.0));
846  }
847  if ((_params.ngridk0 == 0) && (_params.ngridk1 == 0) && (_params.ngridk2 == 0))
848  {
849  double TWO_PI = 2.0 * madness::constants::pi;
850  double t1 = TWO_PI/_params.L;
851  coordT c1 = vec(0.0,0.0,0.0);
852  coordT c2 = vec(0.5*t1,0.5*t1,0.5*t1);
853  _kpoints.push_back(KPoint(c1, 0.5));
854  _kpoints.push_back(KPoint(c2, 0.5));
855  }
856  else // NORMAL BANDSTRUCTURE
857  {
858  _kpoints = genkmesh(_params.ngridk0, _params.ngridk1,
859  _params.ngridk2, _params.koffset0,
860  _params.koffset1, _params.koffset2,
861  _params.L);
862  }
863  }
864  else // NOT-PERIODIC
865  {
866  _kpoints.push_back(KPoint(coordT(0.0), 1.0));
867  }
868  if (_world.rank() == 0)
869  {
870  _kmeshF.open("kpoints.txt");
871  _kmeshF << "kpts: " << _kpoints.size() << endl;
872  _kmeshF << "ik" << setw(10) << "kpt" << setw(30) << "weight" << endl;
873  _kmeshF << "--" << setw(10) << "---" << setw(30) << "------" << endl;
874 
875  //_kmeshF << setfill('-') << setw(55) << "-" << endl;
876  //_kmeshF << setfill(' ') << endl;
877  _kmeshF << endl;
878  for (unsigned int i = 0; i < _kpoints.size(); i++)
879  {
880  KPoint kpoint = _kpoints[i];
881  _kmeshF << i << setw(10) << kpoint.k[0];
882  _kmeshF << setw(10) << kpoint.k[1];
883  _kmeshF << setw(10) << kpoint.k[2];
884  _kmeshF << setw(10) << kpoint.weight << endl;
885  }
886  _kmeshF.close();
887  }
888  }
889  else
890  {
891  load_orbitals();
892  }
893  }
894  //*************************************************************************
895 
896  //*************************************************************************
897  std::vector<KPoint> genkmesh(unsigned int ngridk0, unsigned ngridk1, unsigned int ngridk2,
898  double koffset0, double koffset1, double koffset2, double R)
899  {
900  std::vector<KPoint> kmesh;
901  double step0 = 1.0/ngridk0;
902  double step1 = 1.0/ngridk1;
903  double step2 = 1.0/ngridk2;
904  double weight = 1.0/(ngridk0*ngridk1*ngridk2);
905  double TWO_PI = 2.0 * madness::constants::pi;
906  for (unsigned int i = 0; i < ngridk0; i++)
907  {
908  for (unsigned int j = 0; j < ngridk1; j++)
909  {
910  for (unsigned int k = 0; k < ngridk2; k++)
911  {
912  //double k0 = (i*step0 - step0/2) * TWO_PI/R;
913  //double k1 = (j*step1 - step1/2) * TWO_PI/R;
914  //double k2 = (k*step2 - step2/2) * TWO_PI/R;
915  double k0 = ((i*step0)+koffset0) * TWO_PI/R;
916  double k1 = ((j*step1)+koffset1) * TWO_PI/R;
917  double k2 = ((k*step2)+koffset2) * TWO_PI/R;
918  KPoint kpoint(k0, k1, k2, weight);
919  kmesh.push_back(kpoint);
920  }
921  }
922  }
923  return kmesh;
924  }
925  //*************************************************************************
926 
927  //*************************************************************************
929  {
930  archive::ParallelOutputArchive ar(_world, "orbitals", _params.nio);
931  ar & _params.spinpol;
932  ar & (unsigned int)(_kpoints.size());
933  for (unsigned int i = 0; i < _kpoints.size(); i++) ar & _kpoints[i];
934 // ar & (unsigned int)(_occsa.size());
935 // for (unsigned int i = 0; i < _occsa.size(); i++) ar & _occsa[i];
936  ar & (unsigned int)(_phisa.size());
937  for (unsigned int i = 0; i < _phisa.size(); i++) ar & _phisa[i];
938  if (_params.spinpol)
939  {
940 // ar & (unsigned int)(_occsb.size());
941 // for (unsigned int i = 0; i < _occsb.size(); i++) ar & _occsb[i];
942  ar & (unsigned int)(_phisb.size());
943  for (unsigned int i = 0; i < _phisb.size(); i++) ar & _phisb[i];
944  }
945  }
946  //*************************************************************************
947 
948  //*************************************************************************
950  {
951  const double thresh = FunctionDefaults<3>::get_thresh();
952  const int k = FunctionDefaults<3>::get_k();
953 
954  archive::ParallelInputArchive ar(_world, "orbitals");
955 
956  // spin-polarized
957  bool spinrest;
958  ar & spinrest;
959  // kpoints
960  unsigned int nkpts;
961  ar & nkpts;
962  _kpoints.clear();
963  for (unsigned int i = 0; i < nkpts; i++)
964  {
965  KPoint tkpt;
966  ar & tkpt;
967  _kpoints.push_back(tkpt);
968  }
969  // occs
970 // unsigned int noccs;
971 // ar & noccs;
972 // _occs.clear();
973 // for (unsigned int i = 0; i < noccs; i++)
974 // {
975 // double tocc;
976 // ar & tocc;
977 // _occs.push_back(tocc);
978 // }
979  // orbitals
980  unsigned int norbs;
981  ar & norbs;
982  _phisa.clear();
983  _eigsa.clear();
984  for (unsigned int i = 0; i < norbs; i++)
985  {
986  functionT tfunc;
987  ar & tfunc;
988  _phisa.push_back(tfunc);
989  _eigsa.push_back(-0.1);
990  }
991  // check for k mismatch
992  if (_phisa[0].k() != k)
993  {
994  reconstruct(_world,_phisa);
995  for (unsigned int i = 0; i < _phisa.size(); i++)
996  _phisa[i] = madness::project(_phisa[i], k, thresh, false);
997  _world.gop.fence();
998  }
999  // orthonormalize
1000  for (unsigned int i = 0; i < _kpoints.size(); i++)
1001  gram_schmidt(_phisa, _kpoints[i]);
1002 
1003  if (_params.spinpol)
1004  {
1005  _phisb.clear();
1006  _eigsb.clear();
1007  for (unsigned int i = 0; i < norbs; i++)
1008  {
1009  functionT tfunc;
1010  ar & tfunc;
1011  _phisb.push_back(tfunc);
1012  _eigsb.push_back(-0.1);
1013  }
1014  // check for k mismatch
1015  if (_phisb[0].k() != k)
1016  {
1017  reconstruct(_world,_phisb);
1018  for (unsigned int i = 0; i < _phisb.size(); i++)
1019  _phisb[i] = madness::project(_phisb[i], k, thresh, false);
1020  _world.gop.fence();
1021  }
1022  // orthonormalize
1023  for (unsigned int i = 0; i < _kpoints.size(); i++)
1024  gram_schmidt(_phisb, _kpoints[i]);
1025  }
1026  else
1027  {
1028  for (unsigned int i = 0; i < norbs; i++)
1029  {
1030  _phisb.push_back(_phisa[i]);
1031  _eigsb.push_back(_eigsa[i]);
1032  }
1033  }
1034  // create vector for occupation numbers
1035  _occsa = std::vector<double>(norbs, 0.0);
1036  _occsb = std::vector<double>(norbs, 0.0);
1037  }
1038  //*************************************************************************
1039 
1040  //*************************************************************************
1042  {
1043  _vnucrhon = rfactoryT(_world).functor(rfunctorT(new MolecularPotentialFunctor(_mentity))).thresh(_params.thresh * 0.1).truncate_on_project();
1044  _vnuc = copy(_vnucrhon);
1045  }
1046  //*************************************************************************
1047 
1048  //*************************************************************************
1050  {
1051  std::vector<coordT> specialpts;
1052  for (int i = 0; i < _mentity.natom(); i++)
1053  {
1054  coordT pt(0.0);
1055  Atom atom = _mentity.get_atom(i);
1056  pt[0] = atom.x; pt[1] = atom.y; pt[2] = atom.z;
1057  specialpts.push_back(pt);
1058  if (_world.rank() == 0) print("Special point: ", pt);
1059  }
1060  double now = wall_time();
1061  std::cout << "THE FUNCTOR IS " << MolecularNuclearChargeDensityFunctor(_mentity, _params.L, _params.periodic, specialpts)(specialpts[0]) << endl;
1062  // WSTHORNTON
1063  //MADNESS_ASSERT(false);
1064 
1065 
1066  _vnucrhon = rfactoryT(_world).functor(
1067  rfunctorT(new MolecularNuclearChargeDensityFunctor(_mentity, _params.L, _params.periodic, specialpts))).
1068  thresh(_params.thresh).initial_level(6).truncate_on_project();
1069 
1070  if (_world.rank() == 0) printf("%f\n", wall_time() - now);
1071  if (_world.rank() == 0) print("calculating trace of rhon ..\n\n");
1072  double rtrace = _vnucrhon.trace();
1073  if (_world.rank() == 0) print("rhon trace = ", rtrace);
1074  now = wall_time();
1075  _vnucrhon.truncate();
1076  _vnuc = apply(*_cop, _vnucrhon);
1077  if (_world.rank() == 0) printf("%f\n", wall_time() - now);
1078  if (_world.rank() == 0) print("Done creating nuclear potential ..\n");
1079 
1080 
1081  // WSTHORNTON
1082  rfunctionT vnuc2 = rfactoryT(_world).functor(rfunctorT(new
1083  MolecularPotentialFunctor(_mentity))).
1084  thresh(_params.thresh * 0.1).truncate_on_project();
1085  rfunctionT vnucdiff = _vnuc-vnuc2;
1086  double t1 = vnucdiff.trace();
1087  if (_world.rank() == 0) printf("Difference in nuclear potential: %15.8f\n\n", t1);
1088  for (int i = 0; i < 101; i++)
1089  {
1090  double dx = _params.L/100;
1091  double pt2 = -_params.L/2 + dx*i;
1092  coordT cpt(pt2);
1093  double val = vnucdiff(cpt);
1094  if (_world.rank() == 0) printf("%10.5f %15.8f\n",pt2,val);
1095  }
1096  //MADNESS_ASSERT(false);
1097  }
1098  //*************************************************************************
1099 
1100  //*************************************************************************
1102  {
1103  // Make coulomb operator
1104  _cop = CoulombOperatorPtr(_world, _params.lo, FunctionDefaults<3>::get_thresh() * 0.1);
1105 
1106  Tensor<double> csize = FunctionDefaults<3>::get_cell();
1107  if (_world.rank() == 0)
1108  {
1109  printf("Cell parameters\n");
1110  printf("------------------------------\n");
1111  print("cell(x) is ",csize(0,0), csize(0,1));
1112  print("cell(y) is ",csize(1,0), csize(1,1));
1113  print("cell(z) is ",csize(2,0), csize(2,1));
1114  printf("\n");
1115  }
1116  if (_params.ispotential) // potential
1117  {
1119  }
1120  else // charge density
1121  {
1123  }
1124  }
1125  //*************************************************************************
1126 
1127  //*************************************************************************
1128  struct GuessDensity : public FunctionFunctorInterface<double,3> {
1131  double R;
1132  const bool periodic;
1133 
1134  double operator()(const coordT& x) const
1135  {
1136  double value = 0.0;
1137  if (periodic)
1138  {
1139  for (int xr = -2; xr <= 2; xr += 1)
1140  {
1141  for (int yr = -2; yr <= 2; yr += 1)
1142  {
1143  for (int zr = -2; zr <= 2; zr += 1)
1144  {
1145  value += aobasis.eval_guess_density(mentity,
1146  x[0]+xr*R, x[1]+yr*R, x[2]+zr*R);
1147  }
1148  }
1149  }
1150  }
1151  else
1152  {
1153  value = aobasis.eval_guess_density(mentity, x[0], x[1], x[2]);
1154  }
1155  return value;
1156  }
1157 
1158  GuessDensity(const MolecularEntity& mentity, const AtomicBasisSet& aobasis,
1159  const double& R, const bool& periodic)
1160  : mentity(mentity), aobasis(aobasis), R(R), periodic(periodic) {}
1161  };
1162  //*************************************************************************
1163 
1164  //*************************************************************************
1165  template <typename Q>
1167  {
1168  int npts = 101;
1169  double eps = 1e-8;
1170  coordT r(0.0);
1171  double delta = _params.L/(npts-1);
1172  double begin = -_params.L/2;
1173  double end = _params.L/2;
1174  double tol = 1e-6;
1175  // x-axis
1176  printf("periodicity along x-axis: \n");
1177  printf("-------------------------------------------------------------\n\n");
1178  for (int i = 0; i < npts; i++)
1179  {
1180  printf("\n-------------------- edge --------------------\n");
1181  for (int j = 0; j < npts; j++)
1182  {
1183  coordT r1, r2, dr1, dr2;
1184  r1[0] = begin+eps; r1[1] = (i*delta)+begin; r1[2] = (j*delta)+begin;
1185  r2[0] = end-eps; r2[1] = (i*delta)+begin; r2[2] = (j*delta)+begin;
1186  dr1[0] = begin+2*eps; dr1[1] = (i*delta)+begin; dr1[2] = (j*delta)+begin;
1187  dr2[0] = end-2*eps; dr2[1] = (i*delta)+begin; dr2[2] = (j*delta)+begin;
1188  double val = std::abs(f(r1)-f(r2));
1189  std::string success = val < tol ? "PASS!" : "FAIL!";
1190  printf("%10.6f%10.6f%10.6f %10.6f%10.6f%10.6f %10.5e %s\n",
1191  r1[0],r1[1],r1[2],r2[0],r2[1],r2[2],val,success.c_str());
1192  }
1193  }
1194  // y-axis
1195  printf("\nperiodicity along y-axis: \n");
1196  printf("-------------------------------------------------------------\n\n");
1197  for (int i = 0; i < npts; i++)
1198  {
1199  printf("\n-------------------- edge --------------------\n");
1200  for (int j = 0; j < npts; j++)
1201  {
1202  coordT r1, r2, dr1, dr2;
1203  r1[0] = (i*delta)+begin; r1[1] = begin+eps; r1[2] = (j*delta)+begin;
1204  r2[0] = (i*delta)+begin; r2[1] = end-eps; r2[2] = (j*delta)+begin;
1205  dr1[0] = (i*delta)+begin; dr1[1] = begin+2*eps; dr1[2] = (j*delta)+begin;
1206  dr2[0] = (i*delta)+begin; dr2[1] = end-2*eps; dr2[2] = (j*delta)+begin;
1207  double val = std::abs(f(r1)-f(r2));
1208  std::string success = val < tol ? "PASS!" : "FAIL!";
1209  printf("%10.6f%10.6f%10.6f %10.6f%10.6f%10.6f %10.5e %s\n",
1210  r1[0],r1[1],r1[2],r2[0],r2[1],r2[2],val,success.c_str());
1211  }
1212  }
1213  // z-axis
1214  printf("\nperiodicity along z-axis: \n");
1215  printf("-------------------------------------------------------------\n\n");
1216  for (int i = 0; i < npts; i++)
1217  {
1218  printf("\n-------------------- edge --------------------\n");
1219  for (int j = 0; j < npts; j++)
1220  {
1221  coordT r1, r2, dr1, dr2;
1222  r1[0] = (i*delta)+begin; r1[1] = (j*delta)+begin; r1[2] = begin+eps;
1223  r2[0] = (i*delta)+begin; r2[1] = (j*delta)+begin; r2[2] = end-eps;
1224  dr1[0] = (i*delta)+begin; dr1[1] = (j*delta)+begin; dr1[2] = begin+2*eps;
1225  dr2[0] = (i*delta)+begin; dr2[1] = (j*delta)+begin; dr2[2] = end-2*eps;
1226  double val = std::abs(f(r1)-f(r2));
1227  std::string success = val < tol ? "PASS!" : "FAIL!";
1228  printf("%10.6f%10.6f%10.6f %10.6f%10.6f%10.6f %10.5e %s\n",
1229  r1[0],r1[1],r1[2],r2[0],r2[1],r2[2],val,success.c_str());
1230  }
1231  }
1232  }
1233  //*************************************************************************
1234 
1235  //*************************************************************************
1236  rfunctionT
1238  const rfunctionT& arho,
1239  const rfunctionT& brho,
1240  const rfunctionT& adelrhosq,
1241  const rfunctionT& bdelrhosq)
1242  {
1243  // MADNESS_ASSERT(!_params.spinpol);
1244  rfunctionT vlda = copy(arho);
1245 // vlda.unaryop(&::libxc_ldaop<double>);
1246  vlda.unaryop(&::ldaop<double>);
1247  return vlda;
1248  }
1249 
1250  vecfuncT project_ao_basis(World& world, KPoint kpt) {
1251  vecfuncT ao(_aobasis.nbf(_mentity));
1252 
1253 // Level initial_level = 3;
1254 // for (int i=0; i < _aobasis.nbf(_mentity); i++) {
1255 // functorT aofunc(new AtomicBasisFunctor(_aobasis.get_atomic_basis_function(_mentity,i),
1256 // _params.L, _params.periodic, kpt));
1257 // ao[i] = factoryT(world).functor(aofunc).initial_level(initial_level).truncate_on_project().nofence();
1258 // }
1259 // world.gop.fence();
1260 
1261 // WSTAtomicBasisFunctor aofunc(_aobasis.get_atomic_basis_function(_mentity,4),
1262 // _params.L, kpt.k[0], kpt.k[1], kpt.k[2]);
1263 // coord_3d p(5e-2);
1264 // double_complex val = aofunc(p);
1265 // print("AO_PROJECT: val is ", val);
1266 // MADNESS_ASSERT(false);
1267 
1268  for (int i=0; i < _aobasis.nbf(_mentity); i++) {
1269  functorT aofunc(new WSTAtomicBasisFunctor(_aobasis.get_atomic_basis_function(_mentity,i),
1270  _params.L, kpt.k[0], kpt.k[1], kpt.k[2]));
1271  ao[i] = factoryT(world).functor(aofunc).truncate_on_project().truncate_mode(0);
1272  }
1273  world.gop.fence();
1274 
1275 // std::vector<double> norms;
1276 // norms = norm2s(world, ao);
1277 // for (int i=0; i<_aobasis.nbf(_mentity); i++) {
1278 // if (world.rank() == 0 && fabs(norms[i]-1.0)>1e-3) print(i," bad ao norm?", norms[i]);
1279 // norms[i] = 1.0/norms[i];
1280 // }
1281 //
1282 // scale(world, ao, norms);
1283 // norms = norm2s(world, ao);
1284 // for (int i=0; i<_aobasis.nbf(_mentity); i++) {
1285 // if (world.rank() == 0 && fabs(norms[i]-1.0)>1e-3) print(i," bad ao norm?", norms[i]);
1286 // norms[i] = 1.0/norms[i];
1287 // }
1288 // scale(world, ao, norms);
1289 
1290  return ao;
1291  }
1292  //*************************************************************************
1293 
1294  //*************************************************************************
1295  // Constructor
1296  Solver(World& world,
1297  rfunctionT vnucrhon,
1298  vecfuncT phisa,
1299  vecfuncT phisb,
1300  std::vector<T> eigsa,
1301  std::vector<T> eigsb,
1303  MolecularEntity mentity)
1304  : _world(world), _vnucrhon(vnucrhon), _phisa(phisa), _phisb(phisb),
1305  _eigsa(eigsa), _eigsb(eigsb), _params(params), _mentity(mentity)
1306  {
1307  _residual = 1e5;
1308  _cop = CoulombOperatorPtr(const_cast<World&>(world), params.lo, params.thresh * 0.1);
1309 
1310  if (params.ispotential)
1311  {
1312  _vnuc = copy(_vnucrhon);
1313  }
1314  else
1315  {
1316  _vnuc = apply(*_cop, _vnucrhon);
1317  }
1318  }
1319  //*************************************************************************
1320 
1322  //*************************************************************************
1324  {
1325  // Get initial guess for the electronic density
1326  if (_world.rank() == 0) print("Guessing rho ...\n\n");
1327 
1328  rfunctionT rho = rfactoryT(_world);
1329  if (_params.restart == 0)
1330  {
1331  rho = rfactoryT(_world).functor(rfunctorT(new GuessDensity(_mentity,
1332  _aobasis, _params.L, _params.periodic))).initial_level(3);
1333  }
1334  else
1335  {
1336  MADNESS_EXCEPTION("restart not working right now!",0);
1337  }
1338  // This is a cheat
1339  rho.scale(_params.ncharge/rho.trace());
1340 
1341  char fname3[25];
1342  coord_3d rp1(-_params.L/2);
1343  coord_3d rp2(_params.L/2);
1344  plot_line(fname3,101,rp1,rp2,rho);
1345 
1346  // load balance
1347  //if(_world.size() > 1) {
1348  // START_TIMER(_world);
1349  // LoadBalanceDeux<3> lb(_world);
1350  // lb.add_tree(_vnuc, lbcost<double,3>(1.0, 0.0), false);
1351  // lb.add_tree(rho, lbcost<double,3>(1.0, 1.0), true);
1352 
1353  // FunctionDefaults<3>::redistribute(_world, lb.load_balance(6.0));
1354  //}
1355 
1356  if (_params.restart != 1)
1357  {
1358  // build effective potential
1359  rfunctionT vlocal;
1360  // Is this a many-body system?
1361  if (_params.ncharge > 1.0)
1362  {
1363  if (_world.rank() == 0) print("Creating Coulomb op ...\n\n");
1365  // Is this system periodic?
1366  if (_params.periodic)
1367  {
1368  Tensor<double> cellsize = FunctionDefaults<3>::get_cell_width();
1369  //op = PeriodicCoulombOpPtr<double, 3> (_world, _params.waveorder,
1370  // _params.lo, _params.thresh * 0.1, cellsize);
1371  op = CoulombOperatorPtr(_world, _params.lo, _params.thresh * 0.1);
1372  }
1373  else
1374  {
1375  op = CoulombOperatorPtr(_world, _params.lo, _params.thresh * 0.1);
1376  }
1377  if (_world.rank() == 0) print("Building effective potential ...\n\n");
1378  rfunctionT vc = apply(*op, rho);
1379  vlocal = _vnuc + vc; //.scale(1.0-1.0/nel); // Reduce coulomb to increase binding
1380  rho.scale(0.5);
1381  // WSTHORNTON
1382  _rhoa = rho;
1383  _rhob = rho;
1384  // Do the LDA
1385  rfunctionT vlda = make_lda_potential(_world, rho, rho, rfunctionT(), rfunctionT());
1386  vlocal = vlocal + vlda;
1387  delete op;
1388  }
1389  else
1390  {
1391  vlocal = _vnuc;
1392  }
1393 
1394  // Clear these functions
1395 // rho.clear();
1396  vlocal.reconstruct();
1397 
1398  // Get size information from k-points and ao_basis so that we can correctly size
1399  // the _orbitals data structure and the eigs tensor
1400  // number of orbitals in the basis set
1401  int _nao = _aobasis.nbf(_mentity);
1402 
1403  // number of kpoints
1404  int nkpts = _kpoints.size();
1405  // total number of orbitals to be processed (no symmetry)
1406  int norbs = _params.nbands * nkpts;
1407  // Check to see if the basis set can accomodate the number of bands
1408  if (_params.nbands > _nao)
1409  MADNESS_EXCEPTION("Error: basis not large enough to accomodate number of bands", _nao);
1410  // set the number of orbitals
1411  _eigsa = std::vector<double>(norbs, 0.0);
1412  _eigsb = std::vector<double>(norbs, 0.0);
1413  _occsa = std::vector<double>(norbs, 0.0);
1414  _occsb = std::vector<double>(norbs, 0.0);
1415  if (_world.rank() == 0) print("Building kinetic energy matrix ...\n\n");
1416  // Need to do kinetic piece for every k-point
1417  for (int ki = 0; ki < nkpts; ki++)
1418  {
1419  // These are our initial basis functions
1420  if (_world.rank() == 0) print("Projecting atomic orbitals ...\n\n");
1421  START_TIMER(_world);
1422  cvecfuncT ao = project_ao_basis(_world, _kpoints[ki]);
1423  END_TIMER(_world, "projecting atomic orbital basis");
1424 // for (unsigned int iao = 0; iao < _nao; iao)
1425 // {
1426 // _aobasisf.push_back(ao[iao]);
1427 // }
1428 
1429  for (unsigned int ai = 0; ai < ao.size(); ai++)
1430  {
1431  std::vector<long> npt(3,101);
1432  char fnamedx[50];
1433  sprintf(fnamedx, "aofunc_k_%2.2d__%2.2d__.dx",ki,ai);
1434  std::vector<long> npt2(3,101);
1435  plotdx(ao[ai], fnamedx, FunctionDefaults<3>::get_cell(), npt2);
1436  }
1437 
1438  coord_3d p1(-_params.L/2);
1439  coord_3d p2(_params.L/2);
1440  for (int i = 0; i < ao.size(); i++)
1441  {
1442  char fname[25];
1443  sprintf(fname, "ao_line_%d.txt",i);
1444  plot_line(fname,101,p1,p2,ao[i]);
1445  }
1446  char fname2[25];
1447  sprintf(fname2, "vnuc_line.txt");
1448  plot_line(fname2,101,p1,p2,_vnuc);
1449  char fname3[25];
1450  sprintf(fname3, "vlocal_line.txt");
1451  plot_line(fname3,101,p1,p2,vlocal);
1452 
1453 
1454  // load balancing
1455  //if(_world.size() > 1)
1456  //{
1457  // LoadBalanceDeux<3> lb(_world);
1458  // lb.add_tree(_vnuc, lbcost<double,3>(1.0, 1.0), false);
1459  // for(unsigned int i = 0; i < ao.size(); i++)
1460  // {
1461  // lb.add_tree(ao[i], lbcost<valueT,3>(1.0, 1.0), false);
1462  // }
1463 
1464  // FunctionDefaults<3>::redistribute(_world, lb.load_balance(6.0));
1465  //}
1466 
1467  // Get k-point from list
1468  KPoint& kpoint = _kpoints[ki];
1469 
1470 
1471 
1472 
1473  // WSTHORNTON
1474 // ctensorT S = matrix_inner(_world,ao,ao,true);
1475 // print(S);
1476 // ctensorT U = csqrt(S);
1477 // ao = transform(_world, ao, U, _params.thresh, true);
1478 
1479 
1480 
1481 
1482  // Build kinetic matrx
1483  //ctensorT kinetic = ::kinetic_energy_matrix_slow<T,NDIM>(_world, ao, _params.periodic, kpt);
1484  ctensorT kinetic = ::kinetic_energy_matrix_slow<T,NDIM>(_world, ao, _params.periodic, kpoint);
1485  // Build the overlap matrix
1486  if (_world.rank() == 0) print("Building overlap matrix ...\n\n");
1487  ctensorT overlap = matrix_inner(_world, ao, ao, true);
1488  // Build the potential matrix
1489  reconstruct(_world, ao);
1490  if (_world.rank() == 0) print("Building potential energy matrix ...\n\n");
1491  //cvecfuncT vpsi = mul_sparse(_world, vlocal, ao, _params.thresh);
1492  cvecfuncT vpsi;
1493  for (int i = 0; i < ao.size(); i++)
1494  vpsi.push_back(vlocal*ao[i]);
1495  _world.gop.fence();
1496  compress(_world, vpsi);
1497  truncate(_world, vpsi);
1498  compress(_world, ao);
1499  // Build the potential matrix
1500  ctensorT potential = matrix_inner(_world, vpsi, ao, true);
1501  _world.gop.fence();
1502  // free memory
1503  vpsi.clear();
1504  _world.gop.fence();
1505 
1506  // Construct and diagonlize Fock matrix
1507  ctensorT fock = potential + kinetic;
1508  ctensorT fockzero = fock-conj_transpose(fock);
1509  if (_world.rank() == 0)
1510  {
1511  print("Kinetic:");
1512  print(kinetic);
1513  print("Potential:");
1514  print(potential);
1515  print("Fock: (pre-symmetrized)");
1516  print(fock);
1517  print("FockZero: (should be zero)");
1518  print(fockzero);
1519  print("Overlap:");
1520  print(overlap);
1521  }
1522  fock = 0.5 * (fock + conj_transpose(fock));
1523  for (unsigned int i = 0; i < fock.dim(0); i++)
1524  {
1525  fock(i,i) += i*_params.thresh*0.1;
1526  }
1527 
1528  ctensorT c; rtensorT e;
1529  sygv(fock, overlap, 1, c, e);
1530 
1531  // diagonlize kinetic
1532  ctensorT ck; rtensorT ek;
1533  sygv(kinetic, overlap, 1, ck, ek);
1534  // diagonalize potential
1535  ctensorT cp; rtensorT ep;
1536  sygv(potential, overlap, 1, cp, ep);
1537  // diagonalize overlap
1538  ctensorT co; rtensorT eo;
1539  syev(overlap, co, eo);
1540 
1541  if (_world.rank() == 0)
1542  {
1543  print("fock eigenvectors dims:",c.dim(0),c.dim(1));
1544  print("fock eigenvectors:");
1545  print(c);
1546  }
1547 
1548  if (_world.rank() == 0)
1549  {
1550  print("kinetic eigenvalues");
1551  print(ek);
1552  }
1553 
1554  if (_world.rank() == 0)
1555  {
1556  print("potential eigenvalues");
1557  print(ep);
1558  }
1559 
1560  if (_world.rank() == 0)
1561  {
1562  print("overlap eigenvalues");
1563  print(eo);
1564  }
1565  if (_world.rank() == 0)
1566  {
1567  print("fock eigenvalues");
1568  print(e);
1569  }
1570 
1571  if (_world.rank() == 0)
1572  {
1573  printf("Overlap: \n");
1574  for (int i = 0; i < overlap.dim(0); i++)
1575  {
1576  for (int j = 0; j < overlap.dim(1); j++)
1577  {
1578  printf("%10.5f", real(overlap(i,j)));
1579  }
1580  printf("\n");
1581  }
1582  printf("\n");
1583  printf("\n");
1584  }
1585 
1586  compress(_world, ao);
1587  _world.gop.fence();
1588  // Take linear combinations of the gaussian basis orbitals as the starting
1589  // orbitals for solver
1590  vecfuncT tmp_orbitals = transform(_world, ao, c(_, Slice(0, _nao - 1)));
1591 
1592 // tmp_orbitals[0] = ao[0];
1593 // tmp_orbitals[1] = ao[1];
1594 // tmp_orbitals[2] = ao[2];
1595 // tmp_orbitals[3] = ao[3];
1596 // tmp_orbitals[4] = ao[4];
1597 
1598  // WSTHORNTON
1599  // checking the symmetry
1600 // int npts = 101;
1601 // double delta = _params.L/(npts-1);
1602 // double begin = -_params.L/2;
1603 // double end = _params.L/2;
1604 // double tol = 1e-6;
1605 //
1606 // for (int i = 0; i < npts; i++)
1607 // {
1608 // double x = (i*delta)+begin;
1609 // for (int j = 0; j < npts; j++)
1610 // {
1611 // double y = (j*delta)+begin;
1612 // for (int k = 0; k < npts; k++)
1613 // {
1614 // double z = (k*delta)+begin;
1615 // coord_3d r1 = vec(x,y,z);
1616 // coord_3d r2 = vec(y,x,z);
1617 // coord_3d r3 = vec(z,y,x);
1618 // coord_3d r4 = vec(x,z,y);
1619 // double_complex pxr2 = ao[2](r2); double_complex pyr1 = ao[3](r1);
1620 // double_complex pxr3 = ao[2](r3); double_complex pzr1 = ao[4](r1);
1621 // double_complex pyr4 = ao[3](r4);
1622 // double err_xy = std::abs(pxr2-pyr1);
1623 // double err_xz = std::abs(pxr3-pzr1);
1624 // std::string success = err_xy < tol ? "PASS!" : "FAIL!";
1625 // printf("%10.4e + %10.4e %10.4e + %10.4e %15.8e\n %s\n",
1626 // std::real(pxr2), std::imag(pxr2), std::real(pyr1), std::imag(pyr1),
1627 // err_xy, success.c_str());
1628 // }
1629 // }
1630 // }
1631 
1632 // MADNESS_ASSERT(false);
1633 
1634  // WSTHORNTON
1635 // const double PI_OVER_8 = madness::constants::pi/8;
1636 // SeparatedConvolution<double,3> op = CoulombOperator(_world, _params.lo, _params.thresh * 0.1);
1637 // rfunctionT vlda = make_lda_potential(_world, rho, rho, rfunctionT(), rfunctionT());
1638 // rho.scale(2.0);
1639 // rfunctionT vc2 = apply(op,rho);
1640 // double rtr2 = rho.trace();
1641 // rfunctionT vlocal2 = vc2 + _vnuc;
1642 //
1643 // SeparatedConvolution<double,3> op2 = CoulombOperator(_world, _params.lo, _params.thresh * 0.1);
1644 // SeparatedConvolution<double,3> bshop = BSHOperator3D(_world, -0.2, _params.lo, _params.thresh * 0.1);
1645 
1646 
1647 // if (_world.rank() == 0)
1648 // {
1649 // print("trace of rho:");
1650 // print(rtr2);
1651 // }
1652 // for (int i = 0; i < 5; i++)
1653 // {
1654 // double th = i*PI_OVER_8;
1655 // tmp_orbitals[2] = ao[2];
1656 // tmp_orbitals[3] = cos(th)*ao[3] + sin(th)*ao[4];
1657 // tmp_orbitals[4] = -sin(th)*ao[3] + cos(th)*ao[4];
1658 //
1659 // ctensorT fred(3,3);
1660 // for (int ii = 2; ii < 5; ii++)
1661 // {
1662 // for (int jj = 2; jj < 5; jj++)
1663 // {
1664 // fred(ii-2,jj-2) = inner(tmp_orbitals[ii], _vnuc*tmp_orbitals[jj]);
1665 // if (std::abs(fred(ii-2,jj-2)) < 1e-6)
1666 // fred(ii-2,jj-2) = std::complex<double>(0.0,0.0);
1667 //
1668 // }
1669 // }
1670 
1671 // complex_derivative_3d Dx(_world,0);
1672 // complex_derivative_3d Dy(_world,1);
1673 // complex_derivative_3d Dz(_world,2);
1674 //
1675 // ctensorT fred(3,3);
1676 // std::complex<double> I = std::complex<double>(0.0,1.0);
1677 // std::complex<double> one = std::complex<double>(1.0,0.0);
1678 // for (int ii = 2; ii < 5; ii++)
1679 // {
1680 // for (int jj = 2; jj < 5; jj++)
1681 // {
1682 // double ksq = kpoint.k[0]*kpoint.k[0] +
1683 // kpoint.k[1]*kpoint.k[1] +
1684 // kpoint.k[2]*kpoint.k[2];
1685 //
1686 // cfunctionT ct1 = -I*kpoint.k[0]*Dx(tmp_orbitals[jj]) -
1687 // I*kpoint.k[1]*Dy(tmp_orbitals[jj]) -
1688 // I*kpoint.k[2]*Dz(tmp_orbitals[jj]);
1689 //
1690 // cfunctionT ct2 = -0.5*Dx(Dx(tmp_orbitals[jj])) +
1691 // Dy(Dy(tmp_orbitals[jj])) +
1692 // Dz(Dz(tmp_orbitals[jj]));
1693 //
1694 // cfunctionT ct3 = 0.5*ksq*tmp_orbitals[jj];
1695 //
1696 // fred(ii-2,jj-2) = inner(tmp_orbitals[ii], ct1+ct2+ct3);
1697 // if (std::abs(fred(ii-2,jj-2)) < 1e-6)
1698 // fred(ii-2,jj-2) = std::complex<double>(0.0,0.0);
1699 // }
1700 // }
1701 
1702 // ctensorT cf; rtensorT ef;
1703 // syev(fred, cf, ef);
1704 //
1705 // if (_world.rank() == 0)
1706 // {
1707 // print("Fred:", i);
1708 // print(fred);
1709 // print("eigenvalues:");
1710 // print(ef);
1711 // print("eigenvectors:");
1712 // print(cf);
1713 // }
1714 // }
1715 // MADNESS_ASSERT(false);
1716 
1717 
1718  _world.gop.fence();
1719  truncate(_world, tmp_orbitals);
1720  normalize(_world, tmp_orbitals);
1721 
1722  // Build the overlap matrix
1723  if (_world.rank() == 0) print("Building overlap matrix ...\n\n");
1724  ctensorT overlap2 = matrix_inner(_world, tmp_orbitals, tmp_orbitals, true);
1725 
1726  rtensorT tmp_eigs = e(Slice(0, _nao - 1));
1727 
1728  if (_world.rank() == 0) printf("(%8.4f,%8.4f,%8.4f)\n",kpoint.k[0], kpoint.k[1], kpoint.k[2]);
1729  if (_world.rank() == 0) print(tmp_eigs);
1730  if (_world.rank() == 0) print("\n");
1731 
1732  //if (_world.rank() == 0) print("kinetic energy for kp = ", kp);
1733  //if (_world.rank() == 0) print(kinetic);
1734  //if (_world.rank() == 0) print("\n");
1735 
1736  // DEBUG
1737  if (_world.rank() == 0) {
1738  printf("Overlap: \n");
1739  for (int i = 0; i < kinetic.dim(0); i++)
1740  {
1741  for (int j = 0; j < kinetic.dim(1); j++)
1742  {
1743  printf("%10.5f", real(overlap(i,j)));
1744  }
1745  printf("\n");
1746  }
1747  printf("\n");
1748  printf("\n");
1749 
1750  printf("Kinetic: \n");
1751  for (int i = 0; i < kinetic.dim(0); i++)
1752  {
1753  for (int j = 0; j < kinetic.dim(1); j++)
1754  {
1755  printf("%10.5f", real(kinetic(i,j)));
1756  }
1757  printf("\n");
1758  }
1759  printf("\n");
1760  printf("\n");
1761 
1762  printf("V: \n");
1763  for (int i = 0; i < potential.dim(0); i++)
1764  {
1765  for (int j = 0; j < potential.dim(1); j++)
1766  {
1767  printf("%10.5f", real(potential(i,j)));
1768  }
1769  printf("\n");
1770  }
1771  printf("\n");
1772  printf("\n");
1773 
1774  printf("Fock: \n");
1775  for (int i = 0; i < fock.dim(0); i++)
1776  {
1777  for (int j = 0; j < fock.dim(1); j++)
1778  {
1779  printf("%10.5f", real(fock(i,j)));
1780  }
1781  printf("\n");
1782  }
1783  printf("\n");
1784  printf("\n");
1785 
1786  printf("New overlap: \n");
1787  for (int i = 0; i < overlap2.dim(0); i++)
1788  {
1789  for (int j = 0; j < overlap2.dim(1); j++)
1790  {
1791  printf("%10.5f", real(overlap2(i,j)));
1792  }
1793  printf("\n");
1794  }
1795  printf("\n");
1796  printf("\n");
1797  }
1798 
1799  // Fill in orbitals and eigenvalues
1800  kpoint.begin = ki*_params.nbands;
1801  kpoint.end = (ki+1)*_params.nbands;
1802  for (unsigned int oi = kpoint.begin, ti = 0; oi < kpoint.end; oi++, ti++)
1803  {
1804  //if (_world.rank() == 0) print(oi, ti, kpt.begin, kpt.end);
1805  // normalize the orbitals
1806  //tmp_orbitals[ti].scale(1.0/tmp_orbitals[ti].norm2());
1807  _phisa.push_back(tmp_orbitals[ti]);
1808  _phisb.push_back(tmp_orbitals[ti]);
1809  _eigsa[oi] = tmp_eigs[ti];
1810  _eigsb[oi] = tmp_eigs[ti];
1811  }
1812  }
1813  }
1814  }
1815  //*************************************************************************
1816 
1817  //*************************************************************************
1818  // Constructor
1819  Solver(World& world,
1820  const rfunctionT& vnucrhon,
1821  const vecfuncT& phis,
1822  const std::vector<T>& eigs,
1823  const ElectronicStructureParams& params,
1824  MolecularEntity mentity)
1825  : _world(world), _vnucrhon(vnucrhon), _phisa(phis), _phisb(phis),
1826  _eigsa(eigs), _eigsb(eigs), _params(params), _mentity(mentity)
1827  {
1828  _residual = 1e5;
1829  if (params.periodic)
1830  {
1831  Tensor<double> box = FunctionDefaults<NDIM>::get_cell_width();
1832  //_cop = PeriodicCoulombOpPtr<T,NDIM>(const_cast<World&>(world),
1833  // FunctionDefaults<NDIM>::get_k(), params.lo, params.thresh * 0.1, box);
1834  _cop = CoulombOperatorPtr(const_cast<World&>(world), params.lo, params.thresh * 0.1);
1835  }
1836  else
1837  {
1838  _cop = CoulombOperatorPtr(const_cast<World&>(world), params.lo, params.thresh * 0.1);
1839  }
1840 
1841  if (params.ispotential)
1842  {
1843  _vnuc = copy(_vnucrhon);
1844  }
1845  else
1846  {
1847  _vnuc = apply(*_cop, _vnucrhon);
1848  }
1849  }
1850  //*************************************************************************
1851 
1852  //*************************************************************************
1853  // Constructor
1854  Solver(World& world,
1855  rfunctionT vnucrhon,
1856  vecfuncT phis,
1857  std::vector<T> eigs,
1858  std::vector<KPoint> kpoints,
1859  std::vector<double> occs,
1861  MolecularEntity mentity)
1862  : _world(world), _vnucrhon(vnucrhon), _phisa(phis), _phisb(phis),
1863  _eigsa(eigs), _eigsb(eigs), _params(params),
1864  _kpoints(kpoints), _occsa(occs), _occsb(occs), _mentity(mentity)
1865  {
1866  _residual = 1e5;
1867  if (params.periodic)
1868  {
1869  Tensor<double> box = FunctionDefaults<NDIM>::get_cell_width();
1870  _cop = CoulombOperatorPtr(const_cast<World&>(world), params.lo, params.thresh * 0.1);
1871  }
1872  else
1873  {
1874  _cop = CoulombOperatorPtr(const_cast<World&>(world), params.lo, params.thresh * 0.1);
1875  }
1876 
1877  if (params.ispotential)
1878  {
1879  _vnuc = copy(_vnucrhon);
1880  }
1881  else
1882  {
1883  _vnuc = apply(*_cop, _vnucrhon);
1884  }
1885  }
1886  //*************************************************************************
1887 
1888  //*************************************************************************
1889  virtual ~Solver()
1890  {
1891  _outputF.close();
1892  _matF.close();
1893  _eigF.close();
1894  delete _subspace;
1895  }
1896  //*************************************************************************
1897 
1898  //***************************************************************************
1899  // set occupation numbers (only for insulators ... no smearing)
1900  void set_occs2(const std::vector<KPoint>& kpoints,
1901  const std::vector<double>& eigsa,
1902  const std::vector<double>& eigsb,
1903  std::vector<double>& occsa,
1904  std::vector<double>& occsb)
1905  {
1906  for (unsigned int ik = 0; ik < kpoints.size(); ik++)
1907  {
1908  // get k-point
1909  KPoint k = kpoints[ik];
1910 
1911  // pull subset of data that corresponds to k
1912  const std::vector<double> k_eigsa(eigsa.begin() + k.begin, eigsa.begin() + k.end);
1913  const std::vector<double> k_eigsb(eigsb.begin() + k.begin, eigsb.begin() + k.end);
1914  std::vector<double> k_occsa(occsa.begin() + k.begin, occsa.begin() + k.end);
1915  std::vector<double> k_occsb(occsb.begin() + k.begin, occsb.begin() + k.end);
1916 
1917  // demand all vectors have the same size
1918  unsigned int sz = k_eigsa.size();
1919  MADNESS_ASSERT(k_eigsb.size() == sz);
1920  MADNESS_ASSERT(k_occsa.size() == sz);
1921  MADNESS_ASSERT(k_occsb.size() == sz);
1922  // concatenate eigenvalues
1923  std::vector<double> teigs;
1924  //std::copy(k_eigsa.begin(), k_eigsa.end(), teigs.begin());
1925  //teigs.insert(teigs.end(), k_eigsb.begin(), k_eigsb.end());
1926  //std::copy(k_eigsb.begin(), k_eigsb.end(), back_inserter(teigs));
1927  for (unsigned int ist = 0; ist < k_eigsa.size(); ist++) teigs.push_back(k_eigsa[ist]);
1928  for (unsigned int ist = 0; ist < k_eigsb.size(); ist++) teigs.push_back(k_eigsb[ist]);
1929 
1930  if (_world.rank() == 0) printf("setting occs ....\n\n");
1931  for (unsigned int ist = 0; ist < teigs.size(); ist++)
1932  {
1933  if (_world.rank() == 0)
1934  {
1935  printf("%5d %15.8f\n", ist, teigs[ist]);
1936  }
1937  }
1938 
1939  // indicies
1940  std::vector<unsigned int> inds(2*sz);
1941  for (unsigned int i = 0; i < 2*sz; i++) inds[i] = i;
1942  // sort by eigenvalue
1943  for (unsigned int i = 0; i < 2*sz; i++)
1944  {
1945  for (unsigned int j = i+1; j < 2*sz; j++)
1946  {
1947  if (teigs[j] < teigs[i])
1948  {
1949  double t1 = teigs[i];
1950  teigs[i] = teigs[j];
1951  teigs[j] = t1;
1952  int it1 = inds[i];
1953  inds[i] = inds[j];
1954  inds[j] = it1;
1955  }
1956  }
1957  }
1958 
1959  if (_world.rank() == 0)
1960  printf("\nSorted eigenvalues:\n");
1961  for (unsigned int i = 0; i < teigs.size(); i++)
1962  {
1963  if (_world.rank() == 0)
1964  printf("%10d%10d %15.8f\n",i,inds[i],teigs[i]);
1965  }
1966 
1967  // assign occupation numbers
1968  double availablecharge = _params.ncharge;
1969  for (unsigned int i = 0; (i < 2*sz) && (availablecharge > 0.0) ; i++)
1970  {
1971  unsigned int current = inds[i];
1972  if (current >= sz)
1973  {
1974  current -= sz;
1975  k_occsb[current] = 1.0;
1976  availablecharge -= 1.0;
1977  }
1978  else
1979  {
1980  k_occsa[current] = 1.0;
1981  availablecharge -= 1.0;
1982  }
1983  }
1984 
1985  for (unsigned int ik1 = k.begin, ik2 = 0; ik1 < k.end; ik1++,ik2++)
1986  {
1987  occsa[ik1] = k_occsa[ik2];
1988  occsb[ik1] = k_occsb[ik2];
1989  }
1990  }
1991 
1992  for (unsigned int ik = 0; ik < kpoints.size(); ik++)
1993  {
1994  KPoint k = kpoints[ik];
1995  if (_world.rank() == 0)
1996  {
1997  printf("k-point is: %d: \n",ik);
1998  }
1999  for (unsigned int ist = k.begin; ist < k.end; ist++)
2000  {
2001  if (_world.rank() == 0)
2002  {
2003  printf("occa: %12.5f occb: %12.5f \n",occsa[ist],occsb[ist]);
2004  }
2005  }
2006  }
2007 
2008  }
2009  //***************************************************************************
2010 
2011  //***************************************************************************
2017  rfunctionT compute_rho_slow(const vecfuncT& phis, std::vector<KPoint> kpoints,
2018  std::vector<double> occs)
2019  {
2020  // Electron density
2021  rfunctionT rho = rfactoryT(_world);
2022  _world.gop.fence();
2023  if (_world.rank() == 0) _outputF << "computing rho ..." << endl;
2024  // Loop over k-points
2025  for (unsigned int kp = 0; kp < kpoints.size(); kp++)
2026  {
2027  // get k-point
2028  KPoint kpoint = kpoints[kp];
2029  // loop through bands
2030  for (unsigned int j = kpoint.begin; j < kpoint.end; j++)
2031  {
2032  // Get phi(j) from iterator
2033  const functionT& phij = phis[j];
2034  // Compute the j-th density
2035  //rfunctionT prod = abs_square(phij);
2036  rfunctionT prod = abssq(phij,true);
2037  double rnrm = prod.trace();
2038  prod.scale(1/rnrm);
2039 // rho += 0.5 * _occs[j] * kpoint.weight * prod;
2040  rho += occs[j] * kpoint.weight * prod;
2041  }
2042  }
2043  rho.truncate();
2044 
2045  return rho;
2046  }
2047 
2048  // computes the electronic density for 1 spin
2049  rfunctionT compute_rho(const vecfuncT& phis, std::vector<KPoint> kpoints,
2050  std::vector<double> occs)
2051  {
2052  if (_world.rank() == 0) _outputF << "computing rho ..." << endl;
2053  rfunctionT rho = rfactoryT(_world); // Electron density
2054 
2055  reconstruct(_world, phis); // For max parallelism
2056  std::vector<rfunctionT> phisq(phis.size());
2057  for (unsigned int i=0; i<phis.size(); i++) {
2058  phisq[i] = abssq(phis[i],false);
2059  }
2060  _world.gop.fence();
2061  std::vector<double> phinorm = norm2s(_world, phis);
2062 
2063  compress(_world,phisq); // since will be using gaxpy for accumulation
2064  rho.compress();
2065 
2066  // Loop over k-points
2067  for (unsigned int kp = 0; kp < kpoints.size(); kp++)
2068  {
2069  // get k-point
2070  KPoint kpoint = kpoints[kp];
2071  // loop through bands
2072  for (unsigned int j = kpoint.begin; j < kpoint.end; j++)
2073  {
2074  rho.gaxpy(1.0, phisq[j], occs[j] * kpoint.weight / (phinorm[j]*phinorm[j]), false);
2075  }
2076  }
2077  _world.gop.fence();
2078  phisq.clear();
2079  rho.truncate();
2080 
2081  return rho;
2082  }
2083 
2084 
2085  //***************************************************************************
2086 
2087  //***************************************************************************
2088  std::vector<poperatorT> make_bsh_operators(const std::vector<T>& eigs)
2089  {
2090  // Make BSH vector
2091  std::vector<poperatorT> bops;
2092  // Get defaults
2093  double tol = FunctionDefaults<NDIM>::get_thresh();
2094  // Loop through eigenvalues, adding a BSH operator to bops
2095  // for each eigenvalue
2096  int sz = eigs.size();
2097  for (int i = 0; i < sz; i++)
2098  {
2099  T eps = eigs[i];
2100  if (eps > 0)
2101  {
2102  if (_world.rank() == 0)
2103  {
2104  std::cout << "bsh: warning: positive eigenvalue" << i << eps << endl;
2105  }
2106  eps = -0.1;
2107  }
2108 
2109  bops.push_back(poperatorT(BSHOperatorPtr3D(_world, sqrt(-2.0*eps), _params.lo, tol * 0.1)));
2110  }
2111  return bops;
2112  }
2113  //*************************************************************************
2114 
2115  //*************************************************************************
2116 // void loadbal()
2117 // {
2118 // if(_world.size() == 1)
2119 // return;
2120 //
2121 // LoadBalanceDeux<3> lb(_world);
2122 // lb.add_tree(_vnuc, lbcost<double,3>(1.0, 0.0), false);
2123 // lb.add_tree(_rhoa, lbcost<double,3>(1.0, 1.0), false);
2124 // for(unsigned int i = 0;i < _phisa.size();i++)
2125 // {
2126 // lb.add_tree(_phisa[i], lbcost<valueT,3>(1.0, 1.0), false);
2127 // }
2128 // if(_params.spinpol)
2129 // {
2130 // lb.add_tree(_rhob, lbcost<double,3>(1.0, 1.0), false);
2131 // for(unsigned int i = 0;i < _phisb.size();i++)
2132 // {
2133 // lb.add_tree(_phisa[i], lbcost<valueT,3>(1.0, 1.0), false);
2134 // }
2135 // }
2136 //
2137 // FunctionDefaults<3>::redistribute(_world, lb.load_balance(6.0));
2138 // }
2139  //*************************************************************************
2140 
2141  //*************************************************************************
2143  {
2144  double ke = 0.0;
2145  if (!_params.periodic)
2146  {
2147  complex_derivative_3d Dx(_world,0);
2148  complex_derivative_3d Dy(_world,1);
2149  complex_derivative_3d Dz(_world,2);
2150  for (unsigned int i = 0; i < _phisa.size(); i++)
2151  {
2152  functionT dpdx = Dx(_phisa[i]);
2153  functionT dpdy = Dy(_phisa[i]);
2154  functionT dpdz = Dz(_phisa[i]);
2155  ke += 0.5 * (real(inner(dpdx,dpdx)) + real(inner(dpdy,dpdy))
2156  + real(inner(dpdz,dpdz)));
2157  }
2158  if (_params.spinpol)
2159  {
2160  for (unsigned int i = 0; i < _phisb.size(); i++)
2161  {
2162  functionT dpdx = Dx(_phisb[i]);
2163  functionT dpdy = Dy(_phisb[i]);
2164  functionT dpdz = Dz(_phisb[i]);
2165  ke += 0.5 * (real(inner(dpdx,dpdx)) + real(inner(dpdy,dpdy))
2166  + real(inner(dpdz,dpdz)));
2167  }
2168  }
2169  else
2170  {
2171  ke *= 2.0;
2172  }
2173  }
2174  return ke;
2175  }
2176  //*************************************************************************
2177 
2178  //*************************************************************************
2184  void apply_potential(vecfuncT& pfuncsa,
2185  vecfuncT& pfuncsb, const vecfuncT& phisa,
2186  const vecfuncT& phisb, const rfunctionT& rhoa, const rfunctionT& rhob,
2187  const rfunctionT& rho)
2188  {
2189  // Nuclear and coulomb potentials
2190  rfunctionT vc = apply(*_cop, rho);
2191 
2192  // combined density
2193  rfunctionT rho2 = rho + _vnucrhon;
2194  double vnucrhontrace = _vnucrhon.trace();
2195  double rhotrace = rho.trace();
2196  double rho2trace = rho2.trace();
2197  if (_world.rank() == 0) printf("_vnucrhon trace: %10e\n", vnucrhontrace);
2198  if (_world.rank() == 0) printf("rho trace: %10e\n", rhotrace);
2199  if (_world.rank() == 0) printf("rho2 trace: %10e\n", rho2trace);
2200  rfunctionT vlocal = (_params.ispotential) ? _vnuc + vc : apply(*_cop, rho2);
2201  rfunctionT vlocal2 = _vnuc + vc;
2202  double vlerr = (vlocal-vlocal2).norm2();
2203  if (_world.rank() == 0) printf("vlerr trace: %10e\n\n", vlerr);
2204 
2205 
2206  // Calculate energies for Coulomb and nuclear
2207  double ce = 0.5*inner(vc,rho);
2208  double pe = inner(_vnuc,rho);
2209  double xc = 0.0;
2210  double ke = calculate_kinetic_energy();
2211  // Exchange
2212  if (_params.functional == 1)
2213  {
2214  // LDA, is calculation spin-polarized?
2215  if (_params.spinpol)
2216  {
2217  MADNESS_EXCEPTION("Spin polarized not implemented!",0);
2218 // // potential
2219 // rfunctionT vxca = binary_op(rhoa, rhob, &::libxc_ldaop_sp<double>);
2220 // rfunctionT vxcb = binary_op(rhob, rhoa, &::libxc_ldaop_sp<double>);
2221 // pfuncsa = mul_sparse(_world, vlocal + vxca, phisa, _params.thresh * 0.1);
2222 // pfuncsb = mul_sparse(_world, vlocal + vxcb, phisb, _params.thresh * 0.1);
2223 // // energy
2224 // rfunctionT fca = binary_op(rhoa, rhob, &::libxc_ldaeop_sp<double>);
2225 // rfunctionT fcb = binary_op(rhob, rhoa, &::libxc_ldaeop_sp<double>);
2226 // xc = fca.trace() + fcb.trace();
2227  }
2228  else
2229  {
2230  // potential
2231  rfunctionT vxc = copy(rhoa);
2232 // vxc.unaryop(&::libxc_ldaop<double>);
2233  START_TIMER(_world);
2234  vxc.unaryop(&::ldaop<double>);
2235 
2236  //test_periodicity(vc);
2237 // for (unsigned int i = 0; i < phisa.size(); i++)
2238 // {
2239 // test_periodicity(phisa[i]);
2240 // }
2241 
2242  pfuncsa = mul_sparse(_world, vlocal2+vxc, phisa, _params.thresh * 0.1);
2243 // rfunctionT vxc2 = binary_op(rhoa, rhoa, &::libxc_ldaop_sp<double>);
2244 // pfuncsa = mul_sparse(_world, vlocal + vxc2, phisa, _params.thresh * 0.1);
2245 
2246 // for (unsigned int i = 0; i < pfuncsa.size(); i++)
2247 // {
2248 // test_periodicity(pfuncsa[i]);
2249 // }
2250 
2251 
2252  END_TIMER(_world,"Applying LDA potential");
2253  // energy
2254  rfunctionT fc = copy(rhoa);
2255  fc.unaryop(&::ldaeop<double>);
2256  xc = fc.trace();
2257  }
2258  }
2259  else if (_params.functional == 2)
2260  {
2261  START_TIMER(_world);
2262  pfuncsa = mul_sparse(_world, vlocal, phisa, _params.thresh * 0.1);
2263  END_TIMER(_world,"Applying local potential");
2264  START_TIMER(_world);
2265  // gamma-point?
2266  if ((_params.ngridk0 == 1) && (_params.ngridk1 == 1) && (_params.ngridk2 == 1))
2267  {
2268  apply_hf_exchange3(_phisa, _phisb, pfuncsa, pfuncsb, xc);
2269  }
2270  else
2271  {
2272  apply_hf_exchange4(_phisa, _phisb, pfuncsa, pfuncsb, xc);
2273  }
2274  END_TIMER(_world, "Applying HF exchange");
2275  }
2276  std::cout.precision(8);
2277  if (_world.rank() == 0)
2278  {
2279  printf("Energies:\n");
2280  printf("Kinetic energy: %20.10f\n", ke);
2281  printf("Potential energy: %20.10f\n", pe);
2282  printf("Coulomb energy: %20.10f\n", ce);
2283  printf("Exchange energy: %20.10f\n", xc);
2284  printf("Total energy: %20.10f\n\n", ke + pe + ce + xc);
2285  }
2286  }
2287  //*************************************************************************
2288 
2289  // working for a molecule / atom ... need to test with periodic boundary
2290  // conditions as a gamma point only calculation
2291  //*************************************************************************
2292 // void apply_hf_exchange2(vecfuncT& phisa, vecfuncT& phisb,
2293 // vecfuncT& funcsa, vecfuncT& funcsb,
2294 // double& xc)
2295 // {
2296 // Vector<double,3> q = vec(0.0,0.0,0.0);
2297 // SeparatedConvolution<double_complex,3> hfexop =
2298 // PeriodicHFExchangeOperator(_world, q, _params.lo,
2299 // FunctionDefaults<3>::get_thresh() * 0.1);
2300 // for (unsigned int i = 0; i < phisa.size(); i++)
2301 // {
2302 // bool isreal1 = is_real<T,NDIM>(phisa[i]);
2303 // MADNESS_ASSERT(isreal1);
2305 // for (unsigned int j = 0; j < phisa.size(); j++)
2306 // {
2307 // bool isreal2 = is_real<T,NDIM>(phisa[j]);
2308 // MADNESS_ASSERT(isreal2);
2311 // functionT prod = phisa[i]*phisa[j];
2312 // prod.truncate();
2314 // rfunctionT Vex = real(apply(hfexop,prod));
2315 // functionT tf1 = Vex*phisa[j];
2316 // funcsa[i] -= tf1;
2317 // xc -= real(inner(phisa[i],tf1));
2318 // }
2319 // }
2320 // }
2321  //*************************************************************************
2322 
2323  // working for a molecule / atom ... works for a gamma point calculation
2324  //*************************************************************************
2325  void apply_hf_exchange3(vecfuncT& phisa, vecfuncT& phisb,
2326  vecfuncT& funcsa, vecfuncT& funcsb,
2327  double& xc)
2328  {
2329  for (unsigned int j = 0; j < phisa.size(); j++)
2330  {
2331  rfunctionT phi_j = real(phisa[j]);
2332  // do diagonal piece first
2333  rfunctionT dprod = phi_j*phi_j;
2334  dprod.truncate();
2335  rfunctionT dVex = apply(*_cop,dprod);
2336  functionT tf_jjj = dVex*phisa[j];
2337  funcsa[j] -= tf_jjj;
2338  xc -= real(inner(phisa[j],tf_jjj));
2339  for (unsigned int i = j+1; i < phisa.size(); i++)
2340  {
2341  rfunctionT phi_i = real(phisa[i]);
2342  rfunctionT prod = phi_i*phi_j;
2343  prod.truncate();
2344  rfunctionT Vex = apply(*_cop,prod);
2345  // do the jij-th term
2346  functionT tf_jij = Vex*phisa[j];
2347  funcsa[i] -= tf_jij;
2348  xc -= real(inner(phisa[i],tf_jij));
2349  // do the iji-th term (in the complex case, use the complex
2350  // conjugate)
2351  functionT tf_iji = Vex*phisa[i];
2352  funcsa[j] -= tf_iji;
2353  xc -= real(inner(phisa[j],tf_iji));
2354  }
2355  }
2356  }
2357  //*************************************************************************
2358 
2359  //*************************************************************************
2360  KPoint find_kpt_from_orb(unsigned int idx)
2361  {
2362  for (unsigned int i = 0; i < _kpoints.size(); i++)
2363  {
2364  KPoint k1 = _kpoints[i];
2365  if (k1.is_orb_in_kpoint(idx)) return k1;
2366  }
2367  MADNESS_EXCEPTION("Error: find_kpt_from_orb: didn't find kpoint\n", 0);
2368  }
2369  //************************************************************************
2370 
2371  // hf exchange with k-points for periodic solid
2372  //*************************************************************************
2373  void apply_hf_exchange4(vecfuncT& phisa, vecfuncT& phisb,
2374  vecfuncT& funcsa, vecfuncT& funcsb,
2375  double& xc)
2376  {
2377  for (unsigned int i = 0; i < phisa.size(); i++)
2378  {
2379  functionT phi_i = phisa[i];
2380  KPoint k_i = find_kpt_from_orb(i);
2381  for (unsigned int j = 0; j < phisa.size(); j++)
2382  {
2383  functionT phi_j = phisa[j];
2384  KPoint k_j = find_kpt_from_orb(j);
2385  Vector<double,3> q = vec((k_i.k[0]-k_j.k[0])*_params.L,
2386  (k_i.k[1]-k_j.k[1])*_params.L,
2387  (k_i.k[2]-k_j.k[2])*_params.L);
2388  Vector<double,3> q2 = vec(k_i.k[0]-k_j.k[0],
2389  k_i.k[1]-k_j.k[1],
2390  k_i.k[2]-k_j.k[2]);
2391  functionT cexp =
2392  factoryT(_world).functor(functorT(new
2393  ComplexExp<3>(q2, double_complex(1.0,0.0))));
2394  functionT cexp2 = conj(cexp);
2395  cexp.truncate();
2396  cexp2.truncate();
2397  functionT prod = phi_i*phi_j*cexp;
2399  PeriodicHFExchangeOperator(_world, q, _params.lo,
2401  functionT Vex = apply(hfexop,prod);
2402  functionT tf1 = Vex*phisa[j]*cexp2;
2403  funcsa[i] -= tf1;
2404  xc -= real(inner(phisa[i],tf1));
2405  }
2406  }
2407  }
2408  //*************************************************************************
2409 
2410  // not working and not tested .... supposed to be for the periodic boundary
2411  // conditions with k-points
2412  //*************************************************************************
2413  void apply_hf_exchange(vecfuncT& phisa, vecfuncT& phisb,
2414  vecfuncT& funcsa, vecfuncT& funcsb)
2415  {
2416  for (unsigned int ink1 = 0, ik1 = 0; ink1 < _phisa.size(); ++ink1)
2417  {
2418  for (unsigned int ink2 = 0, ik2 = 0; ink2 <= ink1; ink2++)
2419  {
2420  KPoint k1 = _kpoints[ik1];
2421  KPoint k2 = _kpoints[ik2];
2422 
2423  if (ink1 == k1.end) ik1++;
2424  if (ink2 == k2.end) ik2++;
2425 
2426  MADNESS_ASSERT(ik1 == 0);
2427  MADNESS_ASSERT(ik2 == 0);
2428 
2429  // no phase factor
2430  if (ik1 == ik2)
2431  {
2432 // // same state (diagonal piece)
2433 // if (ink1 == ink2)
2434 // {
2435 // rfunctionT prod = abs_square(phisa[ink1]);
2436 // rfunctionT fr = apply(*_cop,prod);
2437 // funcsa[ink1] -= funcsa[ink1]*fr;
2438 // }
2439 // else
2440  {
2441  Vector<double,3> q = 0.0;
2442  functionT f = phisa[ink1]*conj(phisa[ink2]);
2444  PeriodicHFExchangeOperator(_world, q, _params.lo, FunctionDefaults<3>::get_thresh() * 0.1);
2445  functionT fr = apply(hfexop,f);
2446  funcsa[ink1] -= funcsa[ink2]*fr;
2447  funcsa[ink2] -= funcsa[ink1]*conj(fr);
2448 
2449  // test code
2450  rfunctionT g1 = abs(phisa[ink1]);
2451  rfunctionT g2 = abs(phisa[ink2]);
2452  rfunctionT ff = g1*g2;
2453 
2454  printf("norm diff: %20.8f\n", abs(ff.norm2()-f.norm2()));
2455  MADNESS_ASSERT(abs(ff.norm2()-f.norm2()) <= 1e-5);
2456  rfunctionT fr2 = apply(*_cop,ff);
2457  MADNESS_ASSERT(abs(fr.norm2()-fr2.norm2()) <= 1e-5);
2458  }
2459  }
2460 // else
2461 // {
2462 // Vector<double,3> q = VectorFactory(k1.k[0]-k2.k[0],
2463 // k1.k[1]-k2.k[1],
2464 // k1.k[2]-k2.k[2]);
2465 // functionT cexp = factoryT(_world).functor(functorT(new ComplexExp<3>(q, double_complex(1.0,0.0))));
2466 // cexp.truncate();
2467 //
2468 // functionT f = phisa[ink1]*conj(phisa[ink2])*cexp;
2469 // SeparatedConvolution<double_complex,3> hfexop =
2470 // PeriodicHFExchangeOperator(_world, q, _params.lo, FunctionDefaults<3>::get_thresh() * 0.1);
2471 // functionT fr = apply(hfexop,f);
2472 // funcsa[ink1] -= phisa[ink1]*fr*conj(cexp);
2473 // funcsa[ink2] -= phisa[ink2]*conj(fr)*cexp;
2474 // }
2475  }
2476  }
2477  }
2478  //*************************************************************************
2479 
2480  //*************************************************************************
2481  void reproject()
2482  {
2483  _params.waveorder += 2;
2484  _params.thresh /= 100;
2487  if (_world.rank() == 0) _outputF << "reprojecting to wavelet order "
2488  << _params.waveorder << endl;
2489  reconstruct(_world, _phisa);
2490  for(unsigned int i = 0; i < _phisa.size(); i++)
2491  {
2492  _phisa[i] = madness::project(_phisa[i], FunctionDefaults<3>::get_k(),
2494  }
2495  _world.gop.fence();
2496  truncate(_world, _phisa);
2497  normalize(_world, _phisa);
2498  if(_params.spinpol)
2499  {
2500  reconstruct(_world, _phisb);
2501  for(unsigned int i = 0; i < _phisb.size(); i++)
2502  {
2503  _phisb[i] = madness::project(_phisb[i], FunctionDefaults<3>::get_k(),
2505  }
2506  _world.gop.fence();
2507  truncate(_world, _phisb);
2508  normalize(_world, _phisb);
2509  }
2510 
2511  delete _cop;
2513  //_subspace->reproject();
2514  delete _subspace;
2515  _subspace = new Subspace<T,NDIM>(_world, _params);
2516  }
2517  //*************************************************************************
2518 
2519  //*************************************************************************
2520  void solve()
2521  {
2522 
2523  // WSTHORNTON (debug) Test periodicity
2524 // if (_world.rank() == 0) printf("initial orbitals (periodicity) ...\n\n");
2525 // for (unsigned int i = 0; i < _phisa.size(); i++)
2526 // {
2527 // if (_world.rank() == 0) printf("orbital %d\n",i);
2528 // test_periodicity(_phisa[i]);
2529 // if (_world.rank() == 0) printf("\n\n");
2530 // }
2531 // if (_world.rank() == 0) printf("\n\n\n\n");
2532 
2533  if (_world.rank() == 0) print("size of phisa is: ", _phisa.size());
2534  // keep track of how many iterations have gone by without reprojecting
2535  int rit = 0;
2536  int rpthresh = 20;
2537  for (_it = 0; _it < _params.maxits && _residual > _params.rcriterion; _it++, rit++)
2538  {
2539  // should we reproject?
2540  if ((_it > 0) && ((_residual < 20*_params.thresh) || (rit == rpthresh)))
2541  {
2542  // reproject orbitals and reset threshold
2543  reproject();
2544  rit = 0;
2545  }
2546 
2547  if (_world.rank() == 0) _outputF << "_it = " << _it << endl;
2548 
2549  // Set occupation numbers
2550  set_occs2(_kpoints,_eigsa,_eigsb,_occsa,_occsb);
2551 
2552  // Compute density
2553  rfunctionT rhoa = compute_rho(_phisa, _kpoints, _occsa);
2554  rfunctionT rhob = (_params.spinpol) ? compute_rho(_phisb, _kpoints, _occsb) : rhoa;
2555 // rfunctionT rhoa = _rhoa;
2556 // rfunctionT rhob = _rhob;
2557  double drhoa = (_rhoa-rhoa).trace();
2558  double drhob = (_rhob-rhob).trace();
2559  if (_world.rank() == 0)
2560  {
2561  printf("diff of alpha rho: %15.7f\n",drhoa);
2562  printf("diff of beta rho: %15.7f\n",drhob);
2563  }
2564 
2565  _rho = rhoa + rhob;
2566 
2567  _rhoa = rhoa;
2568  _rhob = rhob;
2569  double rtrace = _rho.trace();
2570  if (_world.rank() == 0) _outputF << "trace of rho" << rtrace << endl;
2571 
2572 // if(_it < 2 || (_it % 10) == 0)
2573 // {
2574 // START_TIMER(_world);
2575 // //loadbal();
2576 // END_TIMER(_world, "Load balancing");
2577 // }
2578 
2579  std::vector<functionT> pfuncsa =
2580  zero_functions<valueT,NDIM>(_world, _phisa.size());
2581  std::vector<functionT> pfuncsb =
2582  zero_functions<valueT,NDIM>(_world, _phisb.size());
2583 
2584  // Apply the potentials to the orbitals
2585  if (_world.rank() == 0) _outputF << "applying potential ...\n" << endl;
2586  //START_TIMER(_world);
2587  apply_potential(pfuncsa, pfuncsb, _phisa, _phisb, _rhoa, _rhob, _rho);
2588  //END_TIMER(_world,"apply potential");
2589 
2590  // Do right hand side for all k-points
2591  std::vector<double> alpha(pfuncsa.size(), 0.0);
2592  do_rhs_simple(_phisa, pfuncsa, _kpoints, alpha, _eigsa);
2593 
2594  if (_params.plotorbs)
2595  {
2596  std::vector<long> npt(3,101);
2597  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2598  {
2599  KPoint kpoint = _kpoints[ik];
2600  int ist = 0;
2601  for (unsigned int kst = kpoint.begin; kst < kpoint.end; kst++, ist++)
2602  {
2603  std::ostringstream strm;
2604  strm << "pre_unk_" << ik << "_" << ist << ".dx";
2605  std::string fname = strm.str();
2606  plotdx(_phisa[kst], fname.c_str(), FunctionDefaults<3>::get_cell(), npt);
2607  }
2608  }
2609  }
2610  // WSTHORNTON
2611  // DEBUG
2612  if (_world.rank() == 0)
2613  printf("\n\n\n\n------ Debugging BSH operator -----");
2614  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2615  {
2616  KPoint kpoint = _kpoints[ik];
2617  std::vector<double> k_alpha(alpha.begin() + kpoint.begin, alpha.begin() + kpoint.end);
2618  if (_world.rank() == 0)
2619  printf("alpha: (%6.4f,%6.4f,%6.4f)\n",kpoint.k[0],kpoint.k[1],kpoint.k[2]);
2620  for (unsigned int ia = 0; ia < k_alpha.size(); ia++)
2621  {
2622  if (_world.rank() == 0) printf("%15.8f\n", k_alpha[ia]);
2623  }
2624  }
2625  if (_world.rank() == 0) printf("\n\n\n\n");
2626 
2627  // WSTHORNTON (debug)
2628  if (_world.rank() == 0) printf("before BSH application ...\n\n");
2629  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2630  {
2631  KPoint kpoint = _kpoints[ik];
2632  double k0 = kpoint.k[0];
2633  double k1 = kpoint.k[1];
2634  double k2 = kpoint.k[2];
2635  if (_world.rank() == 0)
2636  printf("(%6.5f, %6.5f, %6.5f)\n",k0,k1,k2);
2637  std::vector<functionT> k_phisa(_phisa.begin() + kpoint.begin, _phisa.begin() + kpoint.end);
2638  std::vector<functionT> k_pfuncsa(pfuncsa.begin() + kpoint.begin, pfuncsa.begin() + kpoint.end);
2639  KPoint kpoint_gamma;
2640  print_fock_matrix_eigs(k_phisa, k_pfuncsa, kpoint_gamma);
2641 
2642  // diagonalize overlap
2643  tensorT overlap = matrix_inner(_world,k_pfuncsa,k_pfuncsa,true);
2644  ctensorT co; rtensorT eo;
2645  syev(overlap, co, eo);
2646 
2647  if (_world.rank() == 0) printf("Overlap eigenvalues: \n");
2648  if (_world.rank() == 0) print(overlap);
2649  for (unsigned int ie = 0; ie < eo.dim(0); ie++)
2650  {
2651  if (_world.rank() == 0) printf("%d %15.8e\n", ie, eo(ie,ie));
2652  }
2653 
2654  }
2655  if (_world.rank() == 0) printf("\n\n\n\n");
2656 
2657  // WSTHORNTON (debug) Test periodicity
2658 // if (_world.rank() == 0) printf("before BSH application (periodicity) ...\n\n");
2659 // for (unsigned int i = 0; i < _phisa.size(); i++)
2660 // {
2661 // if (_world.rank() == 0) printf("orbital %d\n",i);
2662 // test_periodicity(_phisa[i]);
2663 // if (_world.rank() == 0) printf("\n\n");
2664 // }
2665 // if (_world.rank() == 0) printf("\n\n\n\n");
2666 
2667  // Make BSH Green's function
2668  std::vector<poperatorT> bopsa = make_bsh_operators(alpha);
2669  std::vector<T> sfactor(pfuncsa.size(), -2.0);
2670  scale(_world, pfuncsa, sfactor);
2671 
2672  // Apply Green's function to orbitals
2673  if (_world.rank() == 0) std::cout << "applying BSH operator ...\n" << endl;
2674  truncate<valueT,NDIM>(_world, pfuncsa);
2675  START_TIMER(_world);
2676  std::vector<functionT> tmpa = apply(_world, bopsa, pfuncsa);
2677  END_TIMER(_world,"apply BSH");
2678  bopsa.clear();
2679 
2680  // WSTHORNTON
2681  // norms
2682  if (_world.rank() == 0) printf("norms of tmpa\n");
2683  std::vector<double> tmpa_norms = norm2s(_world, tmpa);
2684  for (unsigned int i = 0; i < tmpa_norms.size(); i++)
2685  {
2686  if (_world.rank() == 0) printf("%10d %15.8f\n", i, tmpa_norms[i]);
2687  }
2688  if (_world.rank() == 0) printf("\n\n\n\n");
2689 
2690  // Do other spin
2691  vecfuncT tmpb = zero_functions<valueT,NDIM>(_world, _phisb.size());
2692  if (_params.spinpol)
2693  {
2694  alpha = std::vector<double>(_phisb.size(), 0.0);
2695  do_rhs_simple(_phisb, pfuncsb, _kpoints, alpha, _eigsb);
2696  std::vector<poperatorT> bopsb = make_bsh_operators(alpha);
2697  scale(_world, pfuncsb, sfactor);
2698  truncate<valueT,NDIM>(_world, pfuncsb);
2699  tmpb = apply(_world, bopsb, pfuncsb);
2700  bopsb.clear();
2701  }
2702  else
2703  {
2704  for (unsigned int i = 0; i < _eigsa.size(); i++) _eigsb[i] = _eigsa[i];
2705  }
2706 
2707  // WSTHORNTON (debug)
2708  std::vector<functionT> pfuncsa2=
2709  zero_functions<valueT,NDIM>(_world, _phisa.size());
2710  std::vector<functionT> pfuncsb2=
2711  zero_functions<valueT,NDIM>(_world, _phisa.size());
2712 
2713  // Apply the potentials to the orbitals
2714  if (_world.rank() == 0) _outputF << "applying potential2 ...\n" << endl;
2715  apply_potential(pfuncsa2, pfuncsb2, tmpa, tmpb, _rhoa, _rhob, _rho);
2716  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2717  {
2718  KPoint kpoint = _kpoints[ik];
2719  double k0 = kpoint.k[0];
2720  double k1 = kpoint.k[1];
2721  double k2 = kpoint.k[2];
2722  if (_world.rank() == 0)
2723  printf("(%6.5f, %6.5f, %6.5f)\n",k0,k1,k2);
2724  std::vector<functionT> k_tmpa(tmpa.begin() + kpoint.begin, tmpa.begin() + kpoint.end);
2725  std::vector<functionT> k_pfuncsa2(pfuncsa2.begin() + kpoint.begin, pfuncsa2.begin() + kpoint.end);
2726  print_fock_matrix_eigs(k_tmpa, k_pfuncsa2, kpoint);
2727 
2728 
2729  // diagonalize overlap
2730 // tensorT overlap = matrix_inner(_world,k_tmpa,k_tmpa,true);
2731 // if (_world.rank() == 0) print(overlap);
2732 // ctensorT co; rtensorT eo;
2733 // syev(overlap, co, eo);
2734 //
2735 // if (_world.rank() == 0) printf("Overlap eigenvalues: \n");
2736 // for (unsigned int ie = 0; ie < eo.dim(0); ie++)
2737 // {
2738 // if (_world.rank() == 0) printf("%d %15.8e\n", ie, eo(ie,ie));
2739 // }
2740  }
2741  if (_world.rank() == 0) printf("\n\n\n\n");
2742 
2743 
2744 
2745  if (_world.rank() == 0) printf("\n\n\n\n");
2746 
2747  // Update orbitals
2748  update_orbitals(tmpa, tmpb, _kpoints);
2749  save_orbitals();
2750 
2751  // WSTHORNTON
2752  if (_world.rank() == 0) _outputF << "after update_orbitals() ...\n" << endl;
2753  pfuncsa2=zero_functions<valueT,NDIM>(_world, _phisa.size());
2754  pfuncsb2=zero_functions<valueT,NDIM>(_world, _phisa.size());
2755  apply_potential(pfuncsa2, pfuncsb2, _phisa, _phisb, _rhoa, _rhob, _rho);
2756  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2757  {
2758  KPoint kpoint = _kpoints[ik];
2759  double k0 = kpoint.k[0];
2760  double k1 = kpoint.k[1];
2761  double k2 = kpoint.k[2];
2762  if (_world.rank() == 0)
2763  printf("(%6.5f, %6.5f, %6.5f)\n",k0,k1,k2);
2764  std::vector<functionT> k_phisa(_phisa.begin() + kpoint.begin, _phisa.begin() + kpoint.end);
2765  std::vector<functionT> k_pfuncsa2(pfuncsa2.begin() + kpoint.begin, pfuncsa2.begin() + kpoint.end);
2766  print_fock_matrix_eigs(k_phisa, k_pfuncsa2, kpoint);
2767  }
2768  if (_world.rank() == 0) printf("\n\n\n\n");
2769 
2770  }
2771 
2772  if (_params.plotorbs)
2773  {
2774  std::vector<long> npt(3,101);
2775  for (unsigned int ik = 0; ik < _kpoints.size(); ik++)
2776  {
2777  KPoint kpoint = _kpoints[ik];
2778  int ist = 0;
2779  for (unsigned int kst = kpoint.begin; kst < kpoint.end; kst++, ist++)
2780  {
2781  std::ostringstream strm;
2782  strm << "unk_" << ik << "_" << ist << ".dx";
2783  std::string fname = strm.str();
2784  plotdx(_phisa[kst], fname.c_str(), FunctionDefaults<3>::get_cell(), npt);
2785  }
2786  }
2787  }
2788  save_orbitals();
2789  }
2790  //*************************************************************************
2791 
2792  //*************************************************************************
2793  ctensorT matrix_exponential(const ctensorT& A) {
2794  const double tol = 1e-13;
2795  MADNESS_ASSERT(A.dim(0) == A.dim(1));
2796 
2797  // Scale A by a power of 2 until it is "small"
2798  double anorm = A.normf();
2799  int n = 0;
2800  double scale = 1.0;
2801  while (anorm*scale > 0.1)
2802  {
2803  n++;
2804  scale *= 0.5;
2805  }
2806  tensorT B = scale*A; // B = A*2^-n
2807 
2808  // Compute exp(B) using Taylor series
2809  ctensorT expB = ctensorT(2, B.dims());
2810  for (int i = 0; i < expB.dim(0); i++) expB(i,i) = std::complex<T>(1.0,0.0);
2811 
2812  int k = 1;
2813  ctensorT term = B;
2814  while (term.normf() > tol)
2815  {
2816  expB += term;
2817  term = inner(term,B);
2818  k++;
2819  term.scale(1.0/k);
2820  }
2821 
2822  // Repeatedly square to recover exp(A)
2823  while (n--)
2824  {
2825  expB = inner(expB,expB);
2826  }
2827 
2828  return expB;
2829  }
2830  //*************************************************************************
2831 
2832  //*************************************************************************
2833  template<typename Q>
2834  void print_tensor2d(ostream& os, Tensor<Q> t)
2835  {
2836  os.precision(5);
2837  for (int i = 0; i < t.dim(0); i++)
2838  {
2839  for (int j = 0; j < t.dim(1); j++)
2840  {
2841  os << t(i,j) << setw(12);
2842  }
2843  os << endl;
2844  }
2845  os << endl;
2846  }
2847  //*************************************************************************
2848 
2849  //*************************************************************************
2850  void print_potential_matrix_eigs(const vecfuncT& wf, const vecfuncT& vwf)
2851  {
2852  // Build the potential matrix
2853  START_TIMER(_world);
2854  tensorT potential = matrix_inner(_world, wf, vwf, true);
2855  _world.gop.fence();
2856  END_TIMER(_world,"potential energy matrix");
2857  if (_world.rank()==0) printf("\n");
2858  tensorT overlap = matrix_inner(_world,wf,wf,true);
2859  _world.gop.fence();
2860 
2861  // diagonalize potential
2862  ctensorT cp; rtensorT ep;
2863  sygv(potential, overlap, 1, cp, ep);
2864  if (_world.rank() == 0)
2865  {
2866  print("potential eigenvectors dims:",cp.dim(0),cp.dim(1));
2867  print("potential eigenvectors:");
2868  print(cp);
2869  printf("\n\n");
2870  print("potential eigenvalues:");
2871  print(ep);
2872  printf("\n\n");
2873  }
2874 
2875  }
2876  //*************************************************************************
2877 
2878  //*************************************************************************
2879  void print_fock_matrix_eigs(const vecfuncT& wf, const vecfuncT& vwf, KPoint kpoint)
2880  {
2881  // Build the potential matrix
2882  START_TIMER(_world);
2883  tensorT potential = matrix_inner(_world, wf, vwf, true);
2884  _world.gop.fence();
2885  END_TIMER(_world,"potential energy matrix");
2886  if (_world.rank()==0) printf("\n");
2887 
2888  START_TIMER(_world);
2889  if (_world.rank() == 0) _outputF << "Building kinetic energy matrix ...\n\n" << endl;
2890  //tensorT kinetic = ::kinetic_energy_matrix_slow<T,NDIM>(_world, psi,
2891  // _params.periodic,
2892  // kpoint);
2893  tensorT kinetic = ::kinetic_energy_matrix<T,NDIM>(_world, wf,
2894  _params.periodic,
2895  kpoint);
2896  _world.gop.fence();
2897  END_TIMER(_world,"kinetic energy matrix");
2898  if (_world.rank() == 0) printf("\n");
2899 
2900  if (_world.rank() == 0) _outputF << "Constructing Fock matrix ...\n\n" << endl;
2901  tensorT fock = potential + kinetic;
2902  fock = 0.5 * (fock + conj_transpose(fock));
2903  _world.gop.fence();
2904 
2905  // DEBUG
2906  tensorT overlap = matrix_inner(_world,wf,wf,true);
2907  _world.gop.fence();
2908 
2909  // diagonlize kinetic
2910  ctensorT ck; rtensorT ek;
2911  sygv(kinetic, overlap, 1, ck, ek);
2912  // diagonalize potential
2913  ctensorT cp; rtensorT ep;
2914  sygv(potential, overlap, 1, cp, ep);
2915  // diagonalize overlap
2916  ctensorT co; rtensorT eo;
2917  syev(overlap, co, eo);
2918  ctensorT c; rtensorT e;
2919  sygv(fock, overlap, 1, c, e);
2920 
2921  if (_world.rank() == 0)
2922  {
2923  print("kinetic matrix:");
2924  print(kinetic);
2925  print("\nkinetic eigenvalues:");
2926  print(ek);
2927  print("\n");
2928 
2929  print("potential matrix:");
2930  print(potential);
2931  print("\npotential eigenvalues:");
2932  print(ep);
2933  print("\n");
2934 
2935  print("fock matrix:");
2936  print(fock);
2937  print("\nfock eigenvalues:");
2938  print(e);
2939  print("\n");
2940  }
2941 
2942  }
2943  //*************************************************************************
2944 
2945  //*************************************************************************
2946  void do_rhs(vecfuncT& wf,
2947  vecfuncT& vwf,
2948  std::vector<KPoint> kpoints,
2949  std::vector<T>& alpha,
2950  std::vector<double>& eigs)
2951  {
2952  // tolerance
2953  double trantol = 0.1*_params.thresh/std::min(30.0,double(wf.size()));
2954  double thresh = 1e-4;
2955 
2956  if (_world.rank() == 0) _eigF << "Iteration: " << _it << endl;
2957  for (unsigned int kp = 0; kp < kpoints.size(); kp++)
2958  {
2959  // Get k-point and orbitals for this k-point
2960  KPoint kpoint = kpoints[kp];
2961  double k0 = kpoint.k[0];
2962  double k1 = kpoint.k[1];
2963  double k2 = kpoint.k[2];
2964  // Extract the relevant portion of the list of orbitals and the list of the
2965  // V times the orbitals
2966  vecfuncT k_wf(wf.begin() + kpoint.begin, wf.begin() + kpoint.end);
2967  vecfuncT k_vwf(vwf.begin() + kpoint.begin, vwf.begin() + kpoint.end);
2968  // Build fock matrix
2969  tensorT fock = build_fock_matrix(k_wf, k_vwf, kpoint);
2970  tensorT overlap = matrix_inner(_world, k_wf, k_wf, true);
2971 
2972 // // Do right hand side stuff for kpoint
2973 // bool isgamma = (is_equal(k0,0.0,1e-5) &&
2974 // is_equal(k1,0.0,1e-5) &&
2975 // is_equal(k2,0.0,1e-5));
2976 // if (_params.periodic && !isgamma) // Non-zero k-point
2977 // {
2978 // // Do the gradient term and k^2/2
2979 // vecfuncT d_wf = zero_functions<valueT,NDIM>(_world, k_wf.size());
2980 // complex_derivative_3d Dx(_world,0);
2981 // complex_derivative_3d Dy(_world,1);
2982 // complex_derivative_3d Dz(_world,2);
2983 // for (unsigned int i = 0; i < k_wf.size(); i++)
2984 // {
2985 // // gradient
2986 // functionT dx_wf = Dx(k_wf[i]);
2987 // functionT dy_wf = Dy(k_wf[i]);
2988 // functionT dz_wf = Dz(k_wf[i]);
2989 // d_wf[i] = std::complex<T>(0.0,k0)*dx_wf +
2990 // std::complex<T>(0.0,k1)*dy_wf +
2991 // std::complex<T>(0.0,k2)*dz_wf;
2992 // // k^/2
2993 // double ksq = k0*k0 + k1*k1 + k2*k2;
2994 // k_vwf[i] += 0.5 * ksq * k_wf[i];
2995 // k_vwf[i] -= d_wf[i];
2996 // }
2997 // }
2998 
2999  if (_params.canon) // canonical orbitals
3000  {
3001  ctensorT U; rtensorT e;
3002  sygv(fock, overlap, 1, U, e);
3003 
3004  unsigned int nmo = k_wf.size();
3005  // Fix phases.
3006  long imax;
3007  for (long j = 0; j < nmo; j++)
3008  {
3009  // Get index of largest value in column
3010  U(_,j).absmax(&imax);
3011  T ang = arg(U(imax,j));
3012  std::complex<T> phase = exp(std::complex<T>(0.0,-ang));
3013  // Loop through the rest of the column and divide by the phase
3014  for (long i = 0; i < nmo; i++)
3015  {
3016  U(i,j) *= phase;
3017  }
3018  }
3019 
3020  // Within blocks with the same occupation number attempt to
3021  // keep orbitals in the same order (to avoid confusing the
3022  // non-linear solver). Have to run the reordering multiple
3023  // times to handle multiple degeneracies.
3024  int maxpass = 5;
3025  for (int pass = 0; pass < maxpass; pass++)
3026  {
3027  long j;
3028  for (long i = 0; i < nmo; i++)
3029  {
3030  U(_, i).absmax(&j);
3031  if (i != j)
3032  {
3033  tensorT tmp = copy(U(_, i));
3034  U(_, i) = U(_, j);
3035  U(_, j) = tmp;
3036  //swap(e[i], e[j]);
3037  T ti = e[i];
3038  T tj = e[j];
3039  e[i] = tj; e[j] = ti;
3040  }
3041  }
3042  }
3043 
3044  // Rotations between effectively degenerate states confound
3045  // the non-linear equation solver ... undo these rotations
3046  long ilo = 0; // first element of cluster
3047  while (ilo < nmo-1) {
3048  long ihi = ilo;
3049  while (fabs(real(e[ilo]-e[ihi+1])) < thresh*10.0*max(fabs(real(e[ilo])),1.0)) {
3050  ihi++;
3051  if (ihi == nmo-1) break;
3052  }
3053  long nclus = ihi - ilo + 1;
3054  if (nclus > 1) {
3055  if (_world.rank() == 0) print(" found cluster", ilo, ihi);
3056  tensorT q = copy(U(Slice(ilo,ihi),Slice(ilo,ihi)));
3057  //print(q);
3058  // Special code just for nclus=2
3059  // double c = 0.5*(q(0,0) + q(1,1));
3060  // double s = 0.5*(q(0,1) - q(1,0));
3061  // double r = sqrt(c*c + s*s);
3062  // c /= r;
3063  // s /= r;
3064  // q(0,0) = q(1,1) = c;
3065  // q(0,1) = -s;
3066  // q(1,0) = s;
3067 
3068  // Iteratively construct unitary rotation by
3069  // exponentiating the antisymmetric part of the matrix
3070  // ... is quadratically convergent so just do 3
3071  // iterations
3072  ctensorT rot = matrix_exponential(-0.5*(q - conj_transpose(q)));
3073  q = inner(q,rot);
3074  ctensorT rot2 = matrix_exponential(-0.5*(q - conj_transpose(q)));
3075  q = inner(q,rot2);
3076  ctensorT rot3 = matrix_exponential(-0.5*(q - conj_transpose(q)));
3077  q = inner(rot,inner(rot2,rot3));
3078  U(_,Slice(ilo,ihi)) = inner(U(_,Slice(ilo,ihi)),q);
3079  }
3080  ilo = ihi+1;
3081  }
3082 
3083  // Debug output
3084  if (_params.print_matrices && _world.rank() == 0)
3085  {
3086  printf("(%10.5f, %10.5f, %10.5f)\n", k0, k1, k2);
3087  print("Overlap matrix:");
3088  print(overlap);
3089 
3090  print("Fock matrix:");
3091  print(fock);
3092 
3093  print("U matrix: (eigenvectors)");
3094  print(U);
3095 
3096  print("Fock matrix eigenvalues:");
3097  print(e);
3098  }
3099 
3100  // WSTHORNTON
3101  //print_fock_matrix_eigs(k_wf, k_vwf, kpoint);
3102 
3103  // transform orbitals and V * (orbitals)
3104  //k_vwf = transform(_world, k_vwf, U, 1e-5 / std::min(30.0, double(k_wf.size())), false);
3105  //k_wf = transform(_world, k_wf, U, FunctionDefaults<3>::get_thresh() / std::min(30.0, double(k_wf.size())), true);
3106 
3107  // WSTHORNTON
3108  //print_fock_matrix_eigs(k_wf, k_vwf, kpoint);
3109 
3110  // Do right hand side stuff for kpoint
3111  bool isgamma = (is_equal(k0,0.0,1e-5) &&
3112  is_equal(k1,0.0,1e-5) &&
3113  is_equal(k2,0.0,1e-5));
3114  if (_params.periodic && !isgamma) // Non-zero k-point
3115  {
3116  // Do the gradient term and k^2/2
3117  vecfuncT d_wf = zero_functions<valueT,NDIM>(_world, k_wf.size());
3118  complex_derivative_3d Dx(_world,0);
3119  complex_derivative_3d Dy(_world,1);
3120  complex_derivative_3d Dz(_world,2);
3121  for (unsigned int i = 0; i < k_wf.size(); i++)
3122  {
3123  // gradient
3124  functionT dx_wf = Dx(k_wf[i]);
3125  functionT dy_wf = Dy(k_wf[i]);
3126  functionT dz_wf = Dz(k_wf[i]);
3127  d_wf[i] = std::complex<T>(0.0,k0)*dx_wf +
3128  std::complex<T>(0.0,k1)*dy_wf +
3129  std::complex<T>(0.0,k2)*dz_wf;
3130  // k^/2
3131  double ksq = k0*k0 + k1*k1 + k2*k2;
3132  k_vwf[i] += 0.5 * ksq * k_wf[i];
3133  k_vwf[i] -= d_wf[i];
3134  }
3135  }
3136 
3137  // WSTHORNTON (new code)
3138  unsigned int eimax = -1;
3139  double eimaxval = -1e10;
3140  for (unsigned int ei = kpoint.begin, fi = 0; ei < kpoint.end;
3141  ei++, fi++)
3142  {
3143  if ((real(e(fi,fi)) > 0.0) && (real(e(fi,fi)) > eimaxval))
3144  {
3145  eimax = fi;
3146  eimaxval = real(e(fi,fi));
3147  }
3148  }
3149 
3150  double eshift = (eimaxval > 0.0) ? eimaxval + 0.1 : 0.0;
3151  for (unsigned int ei = kpoint.begin, fi = 0; ei < kpoint.end;
3152  ei++, fi++)
3153  {
3154  // Save the latest eigenvalues
3155  eigs[ei] = real(e(fi,fi));
3156  alpha[ei] = e(fi,fi)-eshift;
3157  k_vwf[fi] += (alpha[ei]-eigs[ei])*k_wf[fi];
3158  }
3159 
3160  if (_world.rank() == 0)
3161  {
3162  _eigF << "kpt: " << kp << endl;
3163  _eigF << setfill('-') << setw(20) << " " << endl;
3164  for (unsigned int ei = kpoint.begin; ei < kpoint.end; ei++)
3165  {
3166  char eigstr[50];
3167  printf("%3d%15.10f",ei,real(eigs[ei]));
3168 // _eigF << ei << setfill(' ') << setw(12) << real(eigs[ei]) << endl;
3169  _eigF << eigstr << endl;
3170  }
3171  _eigF << "\n\n" << endl;
3172  }
3173  }
3174  else // non-canonical orbitals
3175  {
3176  // diagonlize just to print eigenvalues
3177  tensorT overlap = matrix_inner(_world, k_wf, k_wf, true);
3178  ctensorT c; rtensorT e;
3179  sygv(fock, overlap, 1, c, e);
3180  for (unsigned int ei = 0; ei < e.dim(0); ei++)
3181  {
3182  double diffe = (ei == 0) ? 0.0 : real(e(ei,ei))-real(e(ei-1,ei-1));
3183  if (_world.rank() == 0)
3184  print("kpoint ", kp, "ei ", ei, "eps ", real(e(ei,ei)), "\tdiff\t", diffe);
3185  }
3186 
3187  for (unsigned int ei = kpoint.begin, fi = 0;
3188  ei < kpoint.end; ei++, fi++)
3189  {
3190  alpha[ei] = std::min(-0.1, real(fock(fi,fi)));
3191  fock(fi,fi) -= std::complex<T>(alpha[ei], 0.0);
3192  }
3193 
3194  std::vector<functionT> fwf = transform(_world, k_wf, fock, trantol);
3195  gaxpy(_world, 1.0, k_vwf, -1.0, fwf);
3196  fwf.clear();
3197  }
3198  for (unsigned int wi = kpoint.begin, fi = 0; wi < kpoint.end;
3199  wi++, fi++)
3200  {
3201  wf[wi] = k_wf[fi];
3202  vwf[wi] = k_vwf[fi];
3203  }
3204  }
3205  }
3206  //*************************************************************************
3207 
3208  //*************************************************************************
3209  void do_rhs_simple(vecfuncT& wf,
3210  vecfuncT& vwf,
3211  std::vector<KPoint> kpoints,
3212  std::vector<T>& alpha,
3213  std::vector<double>& eigs)
3214  {
3215  // tolerance
3216  double trantol = 0.1*_params.thresh/std::min(30.0,double(wf.size()));
3217  double thresh = 1e-4;
3218 
3219  if (_world.rank() == 0) _eigF << "Iteration: " << _it << endl;
3220  for (unsigned int kp = 0; kp < kpoints.size(); kp++)
3221  {
3222  // Get k-point and orbitals for this k-point
3223  KPoint kpoint = kpoints[kp];
3224  double k0 = kpoint.k[0];
3225  double k1 = kpoint.k[1];
3226  double k2 = kpoint.k[2];
3227  // Extract the relevant portion of the list of orbitals and the list of the
3228  // V times the orbitals
3229  vecfuncT k_wf(wf.begin() + kpoint.begin, wf.begin() + kpoint.end);
3230  vecfuncT k_vwf(vwf.begin() + kpoint.begin, vwf.begin() + kpoint.end);
3231 
3232  // Build fock matrix
3233  tensorT fock = build_fock_matrix(k_wf, k_vwf, kpoint);
3234  tensorT overlap = matrix_inner(_world, k_wf, k_wf, true);
3235  for (unsigned int i = 0; i < k_wf.size(); i++)
3236  fock(i,i) += std::complex<double>(i*_params.thresh*0.1,0.0);
3237 
3238  ctensorT U; rtensorT e;
3239  sygv(fock, overlap, 1, U, e);
3240 
3241  if (_params.print_matrices && _world.rank() == 0)
3242  {
3243  printf("(%10.5f, %10.5f, %10.5f)\n", k0, k1, k2);
3244  print("Overlap matrix:");
3245  print(overlap);
3246 
3247  print("Fock matrix:");
3248  print(fock);
3249 
3250  print("U matrix: (eigenvectors)");
3251  print(U);
3252 
3253  print("Fock matrix eigenvalues:");
3254  print(e);
3255  }
3256 
3257 
3258  // this is all of the B.S. for the solver
3259  if (_params.solver == 1)
3260  {
3261  unsigned int nmo = k_wf.size();
3262  // Fix phases.
3263  long imax;
3264  for (long j = 0; j < nmo; j++)
3265  {
3266  // Get index of largest value in column
3267  U(_,j).absmax(&imax);
3268  T ang = arg(U(imax,j));
3269  std::complex<T> phase = exp(std::complex<T>(0.0,-ang));
3270  // Loop through the rest of the column and divide by the phase
3271  for (long i = 0; i < nmo; i++)
3272  {
3273  U(i,j) *= phase;
3274  }
3275  }
3276 
3277  // Within blocks with the same occupation number attempt to
3278  // keep orbitals in the same order (to avoid confusing the
3279  // non-linear solver). Have to run the reordering multiple
3280  // times to handle multiple degeneracies.
3281  int maxpass = 5;
3282  for (int pass = 0; pass < maxpass; pass++)
3283  {
3284  long j;
3285  for (long i = 0; i < nmo; i++)
3286  {
3287  U(_, i).absmax(&j);
3288  if (i != j)
3289  {
3290  tensorT tmp = copy(U(_, i));
3291  U(_, i) = U(_, j);
3292  U(_, j) = tmp;
3293  //swap(e[i], e[j]);
3294  T ti = e[i];
3295  T tj = e[j];
3296  e[i] = tj; e[j] = ti;
3297  }
3298  }
3299  }
3300 
3301  // Rotations between effectively degenerate states confound
3302  // the non-linear equation solver ... undo these rotations
3303  long ilo = 0; // first element of cluster
3304  while (ilo < nmo-1) {
3305  long ihi = ilo;
3306  while (fabs(real(e[ilo]-e[ihi+1])) < thresh*10.0*max(fabs(real(e[ilo])),1.0)) {
3307  ihi++;
3308  if (ihi == nmo-1) break;
3309  }
3310  long nclus = ihi - ilo + 1;
3311  if (nclus > 1) {
3312  if (_world.rank() == 0) print(" found cluster", ilo, ihi);
3313  tensorT q = copy(U(Slice(ilo,ihi),Slice(ilo,ihi)));
3314  //print(q);
3315  // Special code just for nclus=2
3316  // double c = 0.5*(q(0,0) + q(1,1));
3317  // double s = 0.5*(q(0,1) - q(1,0));
3318  // double r = sqrt(c*c + s*s);
3319  // c /= r;
3320  // s /= r;
3321  // q(0,0) = q(1,1) = c;
3322  // q(0,1) = -s;
3323  // q(1,0) = s;
3324 
3325  // Iteratively construct unitary rotation by
3326  // exponentiating the antisymmetric part of the matrix
3327  // ... is quadratically convergent so just do 3
3328  // iterations
3329  ctensorT rot = matrix_exponential(-0.5*(q - conj_transpose(q)));
3330  q = inner(q,rot);
3331  ctensorT rot2 = matrix_exponential(-0.5*(q - conj_transpose(q)));
3332  q = inner(q,rot2);
3333  ctensorT rot3 = matrix_exponential(-0.5*(q - conj_transpose(q)));
3334  q = inner(rot,inner(rot2,rot3));
3335  U(_,Slice(ilo,ihi)) = inner(U(_,Slice(ilo,ihi)),q);
3336  }
3337  ilo = ihi+1;
3338  }
3339  }
3340 
3341  // transform orbitals and V * (orbitals)
3342  k_vwf = transform(_world, k_vwf, U, 1e-5 / std::min(30.0, double(k_wf.size())), false);
3343  k_wf = transform(_world, k_wf, U, FunctionDefaults<3>::get_thresh() / std::min(30.0, double(k_wf.size())), true);
3344 
3345  // Do right hand side stuff for kpoint
3346  bool isgamma = (is_equal(k0,0.0,1e-5) &&
3347  is_equal(k1,0.0,1e-5) &&
3348  is_equal(k2,0.0,1e-5));
3349  if (_params.periodic && !isgamma) // Non-zero k-point
3350  {
3351  // Do the gradient term and k^2/2
3352  vecfuncT d_wf = zero_functions<valueT,NDIM>(_world, k_wf.size());
3353  complex_derivative_3d Dx(_world,0);
3354  complex_derivative_3d Dy(_world,1);
3355  complex_derivative_3d Dz(_world,2);
3356  for (unsigned int i = 0; i < k_wf.size(); i++)
3357  {
3358  // gradient
3359  functionT dx_wf = Dx(k_wf[i]);
3360  functionT dy_wf = Dy(k_wf[i]);
3361  functionT dz_wf = Dz(k_wf[i]);
3362 
3363  // WSTHORNTON
3364 // double delxx = std::abs(inner(k_wf[i],Dx(Dx(k_wf[i]))));
3365 // double delyy = std::abs(inner(k_wf[i],Dy(Dy(k_wf[i]))));
3366 // double delzz = std::abs(inner(k_wf[i],Dz(Dz(k_wf[i]))));
3367 
3368 // if (_world.rank() == 0)
3369 // printf("orb %2.2d delxx: %15.8e delyy: %15.8e delzz: %15.8e\n",i, delxx, delyy, delzz);
3370 
3371  // WSTHORNTON
3372 // std::vector<long> npt(3,101);
3373 // char fnamedx[50];
3374 // sprintf(fnamedx, "xorb%2.2d__.dx",i);
3375 // plotdx(k_wf[i], fnamedx, FunctionDefaults<3>::get_cell(), npt);
3376 //
3377 // char fnamedx_dx[50];
3378 // sprintf(fnamedx_dx, "xorb%2.2d__dx.dx",i);
3379 // plotdx(dx_wf, fnamedx_dx, FunctionDefaults<3>::get_cell(), npt);
3380 // char fnamedx_dy[50];
3381 // sprintf(fnamedx_dy, "xorb%2.2d__dy.dx",i);
3382 // plotdx(dy_wf, fnamedx_dy, FunctionDefaults<3>::get_cell(), npt);
3383 // char fnamedx_dz[50];
3384 // sprintf(fnamedx_dz, "xorb%2.2d__dz.dx",i);
3385 // plotdx(dz_wf, fnamedx_dz, FunctionDefaults<3>::get_cell(), npt);
3386 //
3387 // rfunctionT xfunc = rfactoryT(_world).functor(
3388 // rfunctorT(new DipoleFunctor(0))).
3389 // thresh(_params.thresh).truncate_on_project();
3390 // rfunctionT yfunc = rfactoryT(_world).functor(
3391 // rfunctorT(new DipoleFunctor(1))).
3392 // thresh(_params.thresh).truncate_on_project();
3393 // rfunctionT zfunc = rfactoryT(_world).functor(
3394 // rfunctorT(new DipoleFunctor(2))).
3395 // thresh(_params.thresh).truncate_on_project();
3396 //
3397 // double xdip = std::abs(inner(k_wf[i],xfunc*k_wf[i]));
3398 // double ydip = std::abs(inner(k_wf[i],yfunc*k_wf[i]));
3399 // double zdip = std::abs(inner(k_wf[i],zfunc*k_wf[i]));
3400 //
3401 // if (_world.rank() == 0)
3402 // printf("orb: %1d dipole moment: (%7.5e,%7.5e,%7.5e)\n",i,xdip,ydip,zdip);
3403 //
3404 // double xdip1 = std::real(inner(k_wf[i],xfunc*k_wf[i]));
3405 // double ydip1 = std::real(inner(k_wf[i],yfunc*k_wf[i]));
3406 // double zdip1 = std::real(inner(k_wf[i],zfunc*k_wf[i]));
3407 //
3408 // if (_world.rank() == 0)
3409 // printf("orb: %1d dipole moment: (%7.5e,%7.5e,%7.5e)\n",i,xdip1,ydip1,zdip1);
3410 //
3411 // double xdip2 = std::imag(inner(k_wf[i],xfunc*k_wf[i]));
3412 // double ydip2 = std::imag(inner(k_wf[i],yfunc*k_wf[i]));
3413 // double zdip2 = std::imag(inner(k_wf[i],zfunc*k_wf[i]));
3414 //
3415 // if (_world.rank() == 0)
3416 // printf("orb: %1d dipole moment: (%7.5e,%7.5e,%7.5e)\n\n\n",i,xdip2,ydip2,zdip2);
3417 //
3418 // // WSTHORNTON
3419 // char fname_x[50];
3420 // char fname_y[50];
3421 // char fname_z[50];
3422 //
3423 // char fnamex_x[50];
3424 // char fnamex_y[50];
3425 // char fnamex_z[50];
3426 //
3427 // char fnamey_x[50];
3428 // char fnamey_y[50];
3429 // char fnamey_z[50];
3430 //
3431 // char fnamez_x[50];
3432 // char fnamez_y[50];
3433 // char fnamez_z[50];
3434 //
3435 // sprintf(fname_x, "orb%2.2d__x.dat",i);
3436 // sprintf(fname_y, "orb%2.2d__y.dat",i);
3437 // sprintf(fname_z, "orb%2.2d__z.dat",i);
3438 //
3439 // sprintf(fnamex_x, "orb%2.2d_dx_x.dat",i);
3440 // sprintf(fnamex_y, "orb%2.2d_dx_y.dat",i);
3441 // sprintf(fnamex_z, "orb%2.2d_dx_z.dat",i);
3442 //
3443 // sprintf(fnamey_x, "orb%2.2d_dy_x.dat",i);
3444 // sprintf(fnamey_y, "orb%2.2d_dy_y.dat",i);
3445 // sprintf(fnamey_z, "orb%2.2d_dy_z.dat",i);
3446 //
3447 // sprintf(fnamez_x, "orb%2.2d_dz_x.dat",i);
3448 // sprintf(fnamez_y, "orb%2.2d_dz_y.dat",i);
3449 // sprintf(fnamez_z, "orb%2.2d_dz_z.dat",i);
3450 //
3451 // coord_3d pt1x = vec(-_params.L/2,0.0,0.0);
3452 // coord_3d pt2x = vec( _params.L/2,0.0,0.0);
3453 //
3454 // coord_3d pt1y = vec(0.0,-_params.L/2,0.0);
3455 // coord_3d pt2y = vec(0.0, _params.L/2,0.0);
3456 //
3457 // coord_3d pt1z = vec(0.0,0.0,-_params.L/2);
3458 // coord_3d pt2z = vec(0.0,0.0, _params.L/2);
3459 //
3460 // plot_line(fname_x,30000,pt1x,pt2x,k_wf[i]);
3461 // plot_line(fname_y,30000,pt1y,pt2y,k_wf[i]);
3462 // plot_line(fname_z,30000,pt1z,pt2z,k_wf[i]);
3463 //
3464 // plot_line(fnamex_x,30000,pt1x,pt2x,dx_wf);
3465 // plot_line(fnamex_y,30000,pt1y,pt2y,dx_wf);
3466 // plot_line(fnamex_z,30000,pt1z,pt2z,dx_wf);
3467 //
3468 // plot_line(fnamey_x,30000,pt1x,pt2x,dy_wf);
3469 // plot_line(fnamey_y,30000,pt1y,pt2y,dy_wf);
3470 // plot_line(fnamey_z,30000,pt1z,pt2z,dy_wf);
3471 //
3472 // plot_line(fnamez_x,30000,pt1x,pt2x,dz_wf);
3473 // plot_line(fnamez_y,30000,pt1y,pt2y,dz_wf);
3474 // plot_line(fnamez_z,30000,pt1z,pt2z,dz_wf);
3475 
3476 
3477 
3478  d_wf[i] = std::complex<T>(0.0,k0)*dx_wf +
3479  std::complex<T>(0.0,k1)*dy_wf +
3480  std::complex<T>(0.0,k2)*dz_wf;
3481  // k^/2
3482  double ksq = k0*k0 + k1*k1 + k2*k2;
3483  k_vwf[i] += 0.5 * ksq * k_wf[i];
3484  k_vwf[i] -= d_wf[i];
3485  }
3486  }
3487 
3488 
3489  // WSTHORNTON (new code)
3490  unsigned int eimax = -1;
3491  double eimaxval = -1e10;
3492  for (unsigned int ei = kpoint.begin, fi = 0; ei < kpoint.end;
3493  ei++, fi++)
3494  {
3495  if ((real(e(fi,fi)) > 0.0) && (real(e(fi,fi)) > eimaxval))
3496  {
3497  eimax = fi;
3498  eimaxval = real(e(fi,fi));
3499  }
3500  }
3501 
3502  double eshift = (eimaxval > 0.0) ? eimaxval + 0.1 : 0.0;
3503  for (unsigned int ei = kpoint.begin, fi = 0; ei < kpoint.end;
3504  ei++, fi++)
3505  {
3506  // Save the latest eigenvalues
3507  eigs[ei] = real(e(fi,fi));
3508  alpha[ei] = e(fi,fi)-eshift;
3509  k_vwf[fi] += (alpha[ei]-eigs[ei])*k_wf[fi];
3510  }
3511 
3512 // if (_world.rank() == 0) printf("do_rhs_simple: (3) ...\n\n");
3513 // print_fock_matrix_eigs(k_wf, k_vwf, kpoint_gamma);
3514 
3515  if (_world.rank() == 0)
3516  {
3517  _eigF << "kpt: " << kp << endl;
3518  _eigF << setfill('-') << setw(20) << " " << endl;
3519  for (unsigned int ei = kpoint.begin; ei < kpoint.end; ei++)
3520  {
3521  char eigstr[50];
3522  sprintf(eigstr,"%3d%15.10f",ei,real(eigs[ei]));
3523  _eigF << eigstr << endl;
3524  }
3525  _eigF << "\n\n" << endl;
3526  }
3527  for (unsigned int wi = kpoint.begin, fi = 0; wi < kpoint.end;
3528  wi++, fi++)
3529  {
3530  wf[wi] = k_wf[fi];
3531  vwf[wi] = k_vwf[fi];
3532  }
3533  }
3534  }
3535  //*************************************************************************
3536 
3537  //*************************************************************************
3539  const double_complex I = double_complex(0.0,1.0);
3540  double kx = k.k[0];
3541  double ky = k.k[1];
3542  double kz = k.k[2];
3543 
3544  complex_derivative_3d Dx(world, 0);
3545  complex_derivative_3d Dy(world, 1);
3546  complex_derivative_3d Dz(world, 2);
3547 
3548  vector_complex_function_3d dvx = apply(world, Dx, v);
3549  vector_complex_function_3d dvy = apply(world, Dy, v);
3550  vector_complex_function_3d dvz = apply(world, Dz, v);
3551 
3552  // -1/2 (del + ik)^2 = -1/2 del^2 - i k.del + 1/2 k^2
3553  // -1/2 <p|del^2|q> = +1/2 <del p | del q>
3554 
3555  tensor_complex f1 = 0.5 * (matrix_inner(world, dvx, dvx, true) +
3556  matrix_inner(world, dvy, dvy, true) +
3557  matrix_inner(world, dvz, dvz, true));
3558 
3559  tensor_complex f2 =
3560  (-I*kx)*matrix_inner(world, v, dvx, false) +
3561  (-I*ky)*matrix_inner(world, v, dvy, false) +
3562  (-I*kz)*matrix_inner(world, v, dvz, false);
3563 
3564  tensor_complex f3 = (0.5 * (kx*kx + ky*ky + kz*kz)) * matrix_inner(world, v, v, true);
3565 
3566  return f1 + f2 + f3;
3567  }
3568  //*************************************************************************
3569 
3570  //*************************************************************************
3571  tensorT build_fock_matrix(vecfuncT& psi,
3572  vecfuncT& vpsi,
3573  KPoint kpoint)
3574  {
3575  // Build the potential matrix
3576  START_TIMER(_world);
3577  tensorT potential = matrix_inner(_world, psi, vpsi, true);
3578  _world.gop.fence();
3579  END_TIMER(_world,"potential energy matrix");
3580  if (_world.rank()==0) printf("\n");
3581 
3582  START_TIMER(_world);
3583  if (_world.rank() == 0) _outputF << "Building kinetic energy matrix ...\n\n" << endl;
3584  tensorT kinetic = ::kinetic_energy_matrix<T,NDIM>(_world, psi,
3585  _params.periodic,
3586  kpoint);
3587  tensorT kinetic2 = make_kinetic_matrix(_world, psi, kpoint);
3588  _world.gop.fence();
3589  END_TIMER(_world,"kinetic energy matrix");
3590  if (_world.rank() == 0) printf("\n");
3591 
3592  if (_world.rank() == 0) _outputF << "Constructing Fock matrix ...\n\n" << endl;
3593  tensorT fock = potential + kinetic;
3594  fock = 0.5 * (fock + conj_transpose(fock));
3595  _world.gop.fence();
3596 
3597  if (_world.rank() == 0)
3598  {
3599  print("KINETIC:");
3600  print(kinetic);
3601  print("KINETIC2:");
3602  print(kinetic2);
3603  print("POTENTIAL:");
3604  print(potential);
3605  print("FOCK:");
3606  print(fock);
3607  }
3608 
3609  return fock;
3610  }
3611  //*************************************************************************
3612 
3613  //*************************************************************************
3614  void gram_schmidt(vecfuncT& f, KPoint kpoint)
3615  {
3616  for (unsigned int fi = kpoint.begin; fi < kpoint.end; ++fi)
3617  {
3618  // Project out the lower states
3619  for (unsigned int fj = kpoint.begin; fj < fi; ++fj)
3620  {
3621  valueT overlap = inner(f[fj], f[fi]);
3622  f[fi] -= overlap*f[fj];
3623  }
3624  f[fi].scale(1.0/f[fi].norm2());
3625  }
3626  }
3627  //*************************************************************************
3628 
3629  //*************************************************************************
3631  tensorT Q3(const tensorT& s) {
3632  tensorT Q = inner(s,s);
3633  Q.gaxpy(0.2,s,-2.0/3.0);
3634  for (int i=0; i<s.dim(0); ++i) Q(i,i) += 1.0;
3635  return Q.scale(15.0/8.0);
3636  }
3637  //*************************************************************************
3638 
3639  //*************************************************************************
3641  ctensorT csqrt(const ctensorT& s, double tol=1e-8) {
3642  int n=s.dim(0), m=s.dim(1);
3643  MADNESS_ASSERT(n==m);
3644  ctensorT c; rtensorT e;
3645  //s.gaxpy(0.5,conj_transpose(s),0.5); // Ensure exact symmetry
3646  syev(s, c, e);
3647  for (int i=0; i<n; ++i) {
3648  if (e(i) < -tol) {
3649  MADNESS_EXCEPTION("Matrix square root: negative eigenvalue",i);
3650  }
3651  else if (e(i) < tol) { // Ugh ..
3652  print("Matrix square root: Warning: small eigenvalue ", i, e(i));
3653  e(i) = tol;
3654  }
3655  e(i) = 1.0/sqrt(e(i));
3656  }
3657  for (int j=0; j<n; ++j) {
3658  for (int i=0; i<n; ++i) {
3659  c(j,i) *= e(i);
3660  }
3661  }
3662  return c;
3663  }
3664  //*************************************************************************
3665 
3666  //*************************************************************************
3667  void orthonormalize(vecfuncT& wf, KPoint kpoint)
3668  {
3669  // extract k-point orbitals
3670  vecfuncT k_wf(wf.begin() + kpoint.begin, wf.begin() + kpoint.end);
3671  ctensorT S = matrix_inner(_world,k_wf,k_wf,true);
3672  printf("orthonormalize: \n");
3673  printf("before matrix (after): \n");
3674  print(S);
3675  ctensorT U = csqrt(S);
3676  k_wf = transform(_world, k_wf, U, _params.thresh, true);
3677 
3678  ctensorT S2 = matrix_inner(_world,k_wf,k_wf,true);
3679  printf("overlap matrix (after): \n");
3680  print(S2);
3681  for (unsigned int wi = kpoint.begin, fi = 0; wi < kpoint.end;
3682  wi++, fi++)
3683  {
3684  wf[wi] = k_wf[fi];
3685  }
3686  }
3687  //*************************************************************************
3688 
3689  //*************************************************************************
3690  vecfuncT compute_residual(const vecfuncT& awfs,
3691  const vecfuncT& bwfs)
3692  {
3693  // vector of residual functions
3694  vecfuncT rm = sub(_world, _phisa, awfs);
3695  // if spin-polarized insert beta spin-orbital residual functions
3696  if (_params.spinpol)
3697  {
3698  vecfuncT br = sub(_world, _phisb, bwfs);
3699  rm.insert(rm.end(), br.begin(), br.end());
3700  }
3701  // scalar residual
3702  std::vector<double> rnvec = norm2s<valueT,NDIM>(_world, rm);
3703  double rnorm = 0.0;
3704  for (unsigned int i = 0; i < rnvec.size(); i++) rnorm += rnvec[i];
3705  // renormalize and print
3706  _residual = rnorm / rnvec.size();
3707  if (_world.rank() == 0) _outputF << "\nResiduals\n---------" << endl;
3708  if (_world.rank() == 0) _outputF << std::setiosflags(std::ios::scientific) << "residual = " << _residual << endl;
3709  if (_world.rank() == 0)
3710  {
3711  _outputF << endl;
3712  for (unsigned int i = 0; i < rnvec.size(); i++)
3713  {
3714  _outputF << "residual" << i << "\t" << rnvec[i] << endl;
3715  }
3716  _outputF << endl;
3717  }
3718 
3719  return rm;
3720  }
3721 
3722  //*************************************************************************
3723  void update_orbitals(vecfuncT& awfs,
3724  vecfuncT& bwfs,
3725  std::vector<KPoint> kpoints)
3726  {
3727  // truncate before we do anyting
3728  truncate<valueT,NDIM> (_world, awfs);
3729  truncate<valueT,NDIM> (_world, _phisa);
3730  if (_params.spinpol)
3731  {
3732  truncate<valueT,NDIM> (_world, bwfs);
3733  truncate<valueT,NDIM> (_world, _phisb);
3734  }
3735  // compute residual
3736  vecfuncT rm = compute_residual(awfs, bwfs);
3737  if (_params.solver > 0 && _params.maxsub > 1)
3738  {
3739  // nonlinear solver
3740  _subspace->update_subspace(awfs, bwfs, _phisa, _phisb, rm);
3741  }
3742 
3743  // do step restriction
3744  step_restriction(_phisa, awfs, 0);
3745  if (_params.spinpol)
3746  {
3747  step_restriction(_phisb, bwfs, 1);
3748  }
3749  // do gram-schmidt
3750  for (unsigned int kp = 0; kp < kpoints.size(); kp++)
3751  {
3752  gram_schmidt(awfs, kpoints[kp]);
3753 // orthonormalize(awfs, kpoints[kp]);
3754  if (_params.spinpol)
3755  {
3756  gram_schmidt(bwfs, kpoints[kp]);
3757 // orthonormalize(bwfs, kpoints[kp]);
3758  }
3759  }
3760 
3761  // update alpha and beta orbitals
3762  truncate<valueT,NDIM>(_world, awfs);
3763  for (unsigned int ai = 0; ai < awfs.size(); ai++) {
3764  _phisa[ai] = awfs[ai].scale(1.0 / awfs[ai].norm2());
3765  }
3766  if (_params.spinpol)
3767  {
3768  truncate<valueT,NDIM>(_world, bwfs);
3769  for (unsigned int bi = 0; bi < bwfs.size(); bi++)
3770  {
3771  _phisb[bi] = bwfs[bi].scale(1.0 / bwfs[bi].norm2());
3772  }
3773  }
3774  else
3775  {
3776  for (unsigned int ia = 0; ia < awfs.size(); ia++)
3777  {
3778  _phisb[ia] = _phisa[ia];
3779  }
3780  }
3781  }
3782  //*************************************************************************
3783 
3784  //*************************************************************************
3785  void step_restriction(vecfuncT& owfs,
3786  vecfuncT& nwfs,
3787  int aorb)
3788  {
3789  double s = (_it < 4) ? 0.75 : _params.sd;
3790  if (_world.rank() == 0) print("damping factor: ", s);
3791  for (unsigned int i = 0; i < owfs.size(); i++)
3792  nwfs[i].gaxpy(1.0 - s, owfs[i], s, false);
3793 // std::vector<double> rnorm = norm2s(_world, sub(_world, owfs, nwfs));
3794 // // Step restriction
3795 // int nres = 0;
3796 // for (unsigned int i = 0; i < owfs.size(); i++)
3797 // {
3798 // if (rnorm[i] > _params.maxrotn)
3799 // {
3800 // double s = _params.maxrotn / rnorm[i];
3801 // nres++;
3802 // if (_world.rank() == 0)
3803 // {
3804 // if (!aorb && nres == 1) _outputF << " restricting step for alpha orbitals:" << endl;
3805 // if (aorb && nres == 1) _outputF << " restricting step for beta orbitals:" << endl;
3806 // _outputF << i;
3807 // }
3808 // nwfs[i].gaxpy(s, owfs[i], 1.0 - s, false);
3809 // }
3810 // }
3811 // if (nres > 0 && _world.rank() == 0) printf("\n");
3812 // _world.gop.fence();
3813  }
3814  //*************************************************************************
3815 
3816  //*************************************************************************
3817  void fix_occupations(const std::vector<T>& eps,
3818  std::vector<double>& occs)
3819  {
3820  // Find max/min eigenvalues
3821  double emax = eps[0];
3822  double emin = emax;
3823  for (int i = 0; i < eps.size(); i++)
3824  {
3825  emax = (eps[i] > emax) ? eps[i] : emax;
3826  emin = (eps[i] < emin) ? eps[i] : emin;
3827  }
3828 
3829  int maxits = 1000;
3830  // This is hardcoded to 2.0 (non-spinpolarized case) for now.
3831  double occmax = 2.0;
3832  // Fermi energy
3833  double efermi = 0.0;
3834  // Use bisection method to find the fermi energy and update occupation numbers
3835  bool bstop = false;
3836  // Some smoothing parameter
3837  double t1 = 1.0/_params.swidth;
3838  for (int it = 0; (it < maxits)&&(!bstop); it++)
3839  {
3840  // Proposed fermi energy
3841  efermi = 0.5 * (emax + emin);
3842  // Accumulated charge
3843  double charge = 0.0;
3844  // Loop over all eigenvalues and count the charge
3845  for (int i = 0; i < eps.size(); i++)
3846  {
3847  double x = (efermi-eps[i]) * t1;
3848  // need to add some smearing function here
3849  occs[i] = occmax*stheta_fd(x);
3850  charge += _kpoints[i].weight() * occs[i];
3851  }
3852  if (fabs(emax-emin) < 1e-5)
3853  bstop = true;
3854  else if (charge < _params.ncharge)
3855  emin = efermi;
3856  else
3857  emax = efermi;
3858  }
3859  }
3860  //*************************************************************************
3861 
3862 // //*************************************************************************
3863 // void update_eigenvalues(const vecfuncT& wavefs,
3864 // const vecfuncT& pfuncs, const vecfuncT& phis,
3865 // std::vector<T>& eigs)
3866 // {
3867 // // Update e
3868 // if (_world.rank() == 0) printf("Updating e ...\n\n");
3869 // for (unsigned int ei = 0; ei < eigs.size(); ei++)
3870 // {
3871 // functionT r = wavefs[ei] - phis[ei];
3872 // double tnorm = wavefs[ei].norm2();
3873 // // Compute correction to the eigenvalues
3874 // T ecorrection = -0.5*real(inner(pfuncs[ei], r)) / (tnorm*tnorm);
3875 // T eps_old = eigs[ei];
3876 // T eps_new = eps_old + ecorrection;
3879 // // Sometimes eps_new can go positive, THIS WILL CAUSE THE ALGORITHM TO CRASH. So,
3880 // // I bounce the new eigenvalue back into the negative side of the real axis. I
3881 // // keep doing this until it's good or I've already done it 10 times.
3882 // int counter = 50;
3883 // while (eps_new >= 0.0 && counter < 20)
3884 // {
3885 // // Split the difference between the new and old estimates of the
3886 // // pi-th eigenvalue.
3887 // eps_new = eps_old + 0.5 * (eps_new - eps_old);
3888 // counter++;
3889 // }
3890 // // Still no go, forget about it. (1$ to Donnie Brasco)
3891 // if (eps_new >= 0.0)
3892 // {
3893 // if (_world.rank() == 0) printf("FAILURE OF WST: exiting!!\n\n");
3894 // _exit(0);
3895 // }
3896 // // Set new eigenvalue
3897 // eigs[ei] = eps_new;
3898 // }
3899 // }
3900 // //*************************************************************************
3901 
3902 // //*************************************************************************
3903 // double get_eig(int indx)
3904 // {
3905 // return _solver->get_eig(indx);
3906 // }
3907 // //*************************************************************************
3908 //
3909 // //*************************************************************************
3910 // functionT get_phi(int indx)
3911 // {
3912 // return _solver->get_phi(indx);
3913 // }
3914 // //*************************************************************************
3915 //
3916 // //*************************************************************************
3917 // const std::vector<double>& eigs()
3918 // {
3919 // return _solver->eigs();
3920 // }
3921 // //*************************************************************************
3922 //
3923 // //*************************************************************************
3924 // const vecfuncT& phis()
3925 // {
3926 // return _solver->phis();
3927 // }
3928 // //*************************************************************************
3929 
3930  };
3931  //***************************************************************************
3932 
3933 }
3934 #define SOLVER_H_
3935 
3936 #endif /* SOLVER_H_ */
void matrix_inner(DistributedMatrix< T > &A, const std::vector< Function< T, NDIM > > &f, const std::vector< Function< T, NDIM > > &g, bool sym=false)
Definition: chem/distpm.cc:38
const double thresh
Definition: dielectric.cc:185
tensor_complex make_kinetic_matrix(World &world, const vector_complex_function_3d &v, const KPoint &k)
Definition: solver.h:3538
WorldGopInterface & gop
Global operations.
Definition: worldfwd.h:462
Corresponding C and Fortran types.
Tensor< double > B
Definition: tdse1d.cc:167
void apply_hf_exchange4(vecfuncT &phisa, vecfuncT &phisb, vecfuncT &funcsa, vecfuncT &funcsb, double &xc)
Definition: solver.h:2373
void reconstruct(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Reconstruct a vector of functions.
Definition: vmra.h:149
bool centered
Definition: electronicstructureparams.h:113
const mpreal exp(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2234
const double pi
Mathematical constant pi.
Definition: constants.h:44
const double R
Definition: dielectric.cc:191
double thresh
Definition: electronicstructureparams.h:64
std::complex< double > double_complex
Definition: lineplot.cc:16
Main include file for MADNESS and defines Function interface.
Function< T, NDIM > & truncate(double tol=0.0, bool fence=true)
Truncate the function with optional fence. Compresses with fence if not compressed.
Definition: mra.h:577
const T1 const T2 const T3 & f3
Definition: gtest-tuple.h:686
void do_rhs_simple(vecfuncT &wf, vecfuncT &vwf, std::vector< KPoint > kpoints, std::vector< T > &alpha, std::vector< double > &eigs)
Definition: solver.h:3209
double operator()(const coordT &x) const
Definition: solver.h:1134
FunctionDefaults holds default paramaters as static class members.
Definition: funcdefaults.h:175
Tensor< T > conj_transpose(const Tensor< T > &t)
Returns a new deep copy of the complex conjugate transpose of the input tensor.
Definition: tensor.h:1954
int solver
Definition: electronicstructureparams.h:92
static void set_bc(const BoundaryConditions< NDIM > &value)
Sets the default boundary conditions.
Definition: funcdefaults.h:350
void gaxpy(World &world, Q alpha, std::vector< Function< T, NDIM > > &a, Q beta, const std::vector< Function< R, NDIM > > &b, bool fence=true)
Generalized A*X+Y for vectors of functions -— a[i] = alpha*a[i] + beta*b[i].
Definition: vmra.h:680
WSTAtomicBasisFunctor(const AtomicBasisFunction &aofunc, double L, double kx, double ky, double kz)
Definition: solver.h:129
double swidth
Definition: electronicstructureparams.h:105
bool spinpol
Definition: electronicstructureparams.h:56
GuessDensity(const MolecularEntity &mentity, const AtomicBasisSet &aobasis, const double &R, const bool &periodic)
Definition: solver.h:1158
SubspaceK(World &world, const ElectronicStructureParams &params, const std::vector< KPoint > &kpoints)
Definition: solver.h:232
Vector< double, NDIM > coordT
Definition: solver.h:101
The SubspaceK class is a container class holding previous orbitals and residuals. ...
Definition: solver.h:412
std::vector< coord_3d > special_points() const
Override this to return list of special points to be refined more deeply.
Definition: solver.h:159
const int NDIM
Definition: tdse1.cc:44
Definition: solver.h:1128
An archive for storing local or parallel data wrapping BinaryFstreamOutputArchive.
Definition: parar.h:241
Vector< double, NDIM > vec3dT
Definition: solver.h:102
Definition: eigsolver.h:63
const Function< T, NDIM > & compress(bool fence=true) const
Compresses the function, transforming into wavelet basis. Possible non-blocking comm.
Definition: mra.h:683
Implements derivatives operators with variety of boundary conditions on simulation domain...
Definition: derivative.h:272
Definition: electronicstructureparams.h:45
void update_subspace(vecfuncT &awfs_new, vecfuncT &bwfs_new, const vecfuncT &awfs_old, const vecfuncT &bwfs_old, const vecfuncT &rm)
Definition: solver.h:452
double z
Definition: chem/molecule.h:57
double L
Definition: electronicstructureparams.h:48
void plotdx(const Function< T, NDIM > &f, const char *filename, const Tensor< double > &cell=FunctionDefaults< NDIM >::get_cell(), const std::vector< long > &npt=std::vector< long >(NDIM, 201L), bool binary=true)
Writes an OpenDX format file with a cube/slice of points on a uniform grid.
Definition: mraimpl.h:3228
void truncate(World &world, std::vector< Function< T, NDIM > > &v, double tol=0.0, bool fence=true)
Truncates a vector of functions.
Definition: vmra.h:194
::std::string string
Definition: gtest-port.h:872
Convolutions in separated form (including Gaussian)
Definition: operator.h:117
double rcriterion
Definition: electronicstructureparams.h:111
bool canon
Definition: electronicstructureparams.h:90
bool periodic
Definition: electronicstructureparams.h:58
A MADNESS functor to compute either x, y, or z.
Definition: chem/SCF.h:194
bool fractional
Definition: electronicstructureparams.h:84
XCfunctional xc
Definition: hedft.cc:54
void reproject()
Definition: solver.h:2481
NDIM & f
Definition: mra.h:2179
Definition: funcdefaults.h:56
ProcessID size() const
Returns the number of processes in this world (same as MPI_Comm_size())
Definition: worldfwd.h:533
static const double & get_thresh()
Returns the default threshold.
Definition: funcdefaults.h:225
Defines interfaces for optimization and non-linear equation solvers.
AtomicBasisFunction get_atomic_basis_function(const Molecule &molecule, int ibf) const
Returns the ibf'th atomic basis function.
Definition: chem/molecularbasis.h:474
Vector< double, 3 > coordT
Definition: chem/corepotential.cc:57
ctensorT matrix_exponential(const ctensorT &A)
Definition: solver.h:2793
const vec3dT exponent
Definition: solver.h:104
rfunctionT make_lda_potential(World &world, const rfunctionT &arho, const rfunctionT &brho, const rfunctionT &adelrhosq, const rfunctionT &bdelrhosq)
Definition: solver.h:1237
rfunctionT compute_rho_slow(const vecfuncT &phis, std::vector< KPoint > kpoints, std::vector< double > occs)
Compute the electronic density for either a molecular or periodic system.
Definition: solver.h:2017
Definition: electronicstructureapp.h:85
Function< T, NDIM > & scale(const Q q, bool fence=true)
Inplace, scale the function by a constant. No communication except for optional fence.
Definition: mra.h:896
Tensor< typename Tensor< T >::scalar_type > arg(const Tensor< T > &t)
Return a new tensor holding the argument of each element of t (complex types only) ...
Definition: tensor.h:2429
static const Tensor< double > & get_cell()
Gets the user cell for the simulation.
Definition: funcdefaults.h:369
This header should include pretty much everything needed for the parallel runtime.
T inner(const vecfunc< T, NDIM > &a, const vecfunc< T, NDIM > &b)
the non-linear solver requires an inner product
Definition: nemo.h:112
Definition: potentialmanager.h:54
KPoint find_kpt_from_orb(unsigned int idx)
Definition: solver.h:2360
tensorT Q3(const tensorT &s)
Given overlap matrix, return rotation with 3rd order error to orthonormalize the vectors.
Definition: solver.h:3631
std::vector< double > norm2s(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norms of a vector of functions.
Definition: vmra.h:312
ComplexExp(vec3dT exponent, double_complex coeff)
Definition: solver.h:106
void syev(const Tensor< T > &A, Tensor< T > &V, Tensor< typename Tensor< T >::scalar_type > &e)
Real-symmetric or complex-Hermitian eigenproblem.
Definition: lapack.cc:478
void init(const std::string &filename)
Definition: solver.h:796
void END_TIMER(World &world, const char *msg)
Definition: solver.h:772
Function< double, NDIM > abssq(const Function< double_complex, NDIM > &z, bool fence=true)
Returns a new function that is the square of the absolute value of the input.
Definition: mra.h:2255
void save_orbitals()
Definition: solver.h:928
ctensorT csqrt(const ctensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: solver.h:3641
Solver(World &world, const std::string &filename)
Definition: solver.h:778
double ncharge
Definition: electronicstructureparams.h:103
bool plotorbs
Definition: electronicstructureparams.h:109
std::shared_ptr< FunctionFunctorInterface< double, 3 > > functorT
Definition: chem/corepotential.cc:58
std::vector< KPoint > genkmesh(unsigned int ngridk0, unsigned ngridk1, unsigned int ngridk2, double koffset0, double koffset1, double koffset2, double R)
Definition: solver.h:897
double_complex operator()(const coordT &x) const
You should implement this to return f(x)
Definition: solver.h:109
int nbf(const Molecule &molecule) const
Given a molecule count the number of basis functions.
Definition: chem/molecularbasis.h:498
void orthonormalize(vecfuncT &wf, KPoint kpoint)
Definition: solver.h:3667
Solver(World &world, const rfunctionT &vnucrhon, const vecfuncT &phis, const std::vector< T > &eigs, const ElectronicStructureParams &params, MolecularEntity mentity)
Definition: solver.h:1819
FLOAT weight(const FLOAT &x)
Definition: y.cc:309
void broadcast_serializable(objT &obj, ProcessID root)
Broadcast a serializable object.
Definition: worldgop.h:707
double R
Definition: solver.h:1131
double norm2() const
Returns the 2-norm of the function ... global sum ... works in either basis.
Definition: mra.h:650
const T1 &f1 return GTEST_2_TUPLE_() T(f0, f1)
#define max(a, b)
Definition: lda.h:53
void step_restriction(vecfuncT &owfs, vecfuncT &nwfs, int aorb)
Definition: solver.h:3785
Vector< T, 1 > vec(T x)
Your friendly neighborhood factory function.
Definition: array.h:456
void scale(World &world, std::vector< Function< T, NDIM > > &v, const std::vector< Q > &factors, bool fence=true)
Scales inplace a vector of functions by distinct values.
Definition: vmra.h:290
int functional
Definition: electronicstructureparams.h:52
void reconstruct(bool fence=true) const
Reconstructs the function, transforming into scaling function basis. Possible non-blocking comm...
Definition: mra.h:737
const int k
Definition: dielectric.cc:184
void initial_guess()
Initializes alpha and beta mos, occupation numbers, eigenvalues.
Definition: solver.h:1323
std::vector< poperatorT > make_bsh_operators(const std::vector< T > &eigs)
Definition: solver.h:2088
tensorT build_fock_matrix(vecfuncT &psi, vecfuncT &vpsi, KPoint kpoint)
Definition: solver.h:3571
static int get_k()
Returns the default wavelet order.
Definition: funcdefaults.h:212
Used to represent one basis function from a shell on a specific center.
Definition: chem/molecularbasis.h:335
int ngridk2
Definition: electronicstructureparams.h:78
void read_file(std::string filename)
read the atomic basis set from file
Definition: chem/molecularbasis.cc:107
The main class of the periodic DFT solver .
Definition: solver.h:625
Function< T, NDIM > copy(const Function< T, NDIM > &f, const std::shared_ptr< WorldDCPmapInterface< Key< NDIM > > > &pmap, bool fence=true)
Create a new copy of the function with different distribution and optional fence. ...
Definition: mra.h:1835
double sd
Definition: electronicstructureparams.h:115
double sss
Definition: solver.h:767
T trace() const
Returns global value of int(f(x),x) ... global comm required.
Definition: mra.h:1034
double total_nuclear_charge() const
Definition: mentity.cc:444
const mpreal min(const mpreal &x, const mpreal &y)
Definition: mpreal.h:2675
Function< TENSOR_RESULT_TYPE(L, R), NDIM > sub(const Function< L, NDIM > &left, const Function< R, NDIM > &right, bool fence=true)
Same as operator- but with optional fence and no automatic compression.
Definition: mra.h:1778
const complexd one(1, 0)
int nempty
Definition: electronicstructureparams.h:72
int waveorder
Definition: electronicstructureparams.h:66
Definition: mentity.h:95
unsigned int maxsub
Definition: electronicstructureparams.h:86
double psi(const Vector< double, 3 > &r)
Definition: apps/ii/hatom_energy.cc:42
double koffset0
Definition: electronicstructureparams.h:94
int nelec
Definition: electronicstructureparams.h:50
void center()
Moves the center of nuclear charge to the origin.
Definition: mentity.cc:413
void print_potential_matrix_eigs(const vecfuncT &wf, const vecfuncT &vwf)
Definition: solver.h:2850
double operator()(const coordT &x) const
Definition: solver.h:171
void load_orbitals()
Definition: solver.h:949
bool print_matrices
Definition: electronicstructureparams.h:107
void read_file(const std::string &filename, bool fractional)
Definition: mentity.cc:289
void gram_schmidt(vecfuncT &f, KPoint kpoint)
Definition: solver.h:3614
std::string basis
Definition: electronicstructureparams.h:96
const MolecularEntity & mentity
Definition: solver.h:1129
const double_complex coeff
Definition: solver.h:103
Subspace(World &world, const ElectronicStructureParams &params)
Definition: solver.h:445
double ttt
Definition: solver.h:767
int nio
Definition: electronicstructureparams.h:98
const AtomicBasisSet & aobasis
Definition: solver.h:1130
void print_fock_matrix_eigs(const vecfuncT &wf, const vecfuncT &vwf, KPoint kpoint)
Definition: solver.h:2879
void sum(T *buf, size_t nelem)
Inplace global sum while still processing AM & tasks.
Definition: worldgop.h:767
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
virtual ~DipoleFunctor()
Definition: solver.h:174
A parallel world with full functionality wrapping an MPI communicator.
Definition: worldfwd.h:416
const Atom & get_atom(unsigned int i) const
Definition: mentity.cc:369
void fence()
Synchronizes all processes in communicator AND globally ensures no pending AM or tasks.
Definition: worldgop.cc:52
vecfuncT project_ao_basis(World &world, KPoint kpt)
Definition: solver.h:1250
void make_nuclear_potential()
Definition: solver.h:1101
double norm2(World &world, const std::vector< Function< T, NDIM > > &v)
Computes the 2-norm of a vector of functions.
Definition: vmra.h:325
vecfuncT compute_residual(const vecfuncT &awfs, const vecfuncT &bwfs)
Definition: solver.h:3690
double potential(const coord_3d &r)
Definition: 3dharmonic.cc:133
DipoleFunctor(int axis)
Definition: solver.h:170
Definition: solver.h:121
Definition: solver.h:99
double x
Definition: chem/molecule.h:57
int ngridk0
Definition: electronicstructureparams.h:78
void set_occs2(const std::vector< KPoint > &kpoints, const std::vector< double > &eigsa, const std::vector< double > &eigsb, std::vector< double > &occsa, std::vector< double > &occsb)
Definition: solver.h:1900
A multiresolution adaptive numerical function.
Definition: derivative.h:61
Definition: chem/molecule.h:55
double eval_guess_density(const Molecule &molecule, double x, double y, double z) const
Evaluates the guess density.
Definition: chem/molecularbasis.h:520
std::vector< complex_functionT > cvecfuncT
Definition: chem/SCF.h:73
int nbands
Definition: electronicstructureparams.h:76
void read_file(const std::string &filename)
Definition: electronicstructureparams.h:170
std::shared_ptr< FunctionFunctorInterface< double, 3 > > rfunctorT
Definition: esolver.h:46
double calculate_kinetic_energy()
Definition: solver.h:2142
double y
Definition: chem/molecule.h:57
static void set_thresh(double value)
Sets the default threshold.
Definition: funcdefaults.h:232
const mpreal sum(const mpreal tab[], unsigned long int n, mp_rnd_t rnd_mode)
Definition: mpreal.cc:241
Abstract base class interface required for functors used as input to Functions.
Definition: function_interface.h:58
const complexd I(0, 1)
const double m
Definition: gfit.cc:199
#define rot(x, k)
Definition: lookup3.c:72
ProcessID rank() const
Returns the process rank in this world (same as MPI_Comm_rank()))
Definition: worldfwd.h:526
void START_TIMER(World &world)
Definition: solver.h:768
std::vector< complex_function_3d > vector_complex_function_3d
Definition: functypedefs.h:86
double real(double x)
Definition: complexfun.h:52
Function< TENSOR_RESULT_TYPE(L, R), NDIM > mul_sparse(const Function< L, NDIM > &left, const Function< R, NDIM > &right, double tol, bool fence=true)
Sparse multiplication — left and right must be reconstructed and if tol!=0 have tree of norms alread...
Definition: mra.h:1569
void plot_line(const char *filename, int npt, const Vector< double, NDIM > &lo, const Vector< double, NDIM > &hi, const Function< T, NDIM > &f)
Generates ASCII file tabulating f(r) at npoints along line r=lo,...,hi.
Definition: funcplot.h:388
void apply_potential(vecfuncT &pfuncsa, vecfuncT &pfuncsb, const vecfuncT &phisa, const vecfuncT &phisb, const rfunctionT &rhoa, const rfunctionT &rhob, const rfunctionT &rho)
Applies the LDA effective potential to each orbital. Currently only lda and spin-polarized is not imp...
Definition: solver.h:2184
double abs(double x)
Definition: complexfun.h:48
rfunctionT compute_rho(const vecfuncT &phis, std::vector< KPoint > kpoints, std::vector< double > occs)
Definition: solver.h:2049
~WSTAtomicBasisFunctor()
Definition: solver.h:139
const bool periodic
Definition: solver.h:1132
const double delta
Definition: dielectric_external_field.cc:120
Solver(World &world, rfunctionT vnucrhon, vecfuncT phis, std::vector< T > eigs, std::vector< KPoint > kpoints, std::vector< double > occs, ElectronicStructureParams params, MolecularEntity mentity)
Definition: solver.h:1854
int ngridk1
Definition: electronicstructureparams.h:78
static const Tensor< double > & get_cell_width()
Returns the width of each user cell dimension.
Definition: funcdefaults.h:391
static void set_cubic_cell(double lo, double hi)
Sets the user cell to be cubic with each dimension having range [lo,hi].
Definition: funcdefaults.h:384
Function< T, NDIM > & gaxpy(const T &alpha, const Function< Q, NDIM > &other, const R &beta, bool fence=true)
Inplace, general bi-linear operation in wavelet basis. No communication except for optional fence...
Definition: mra.h:924
virtual ~Solver()
Definition: solver.h:1889
double koffset2
Definition: electronicstructureparams.h:94
void make_nuclear_charge_density_impl()
Definition: solver.h:1049
void sygv(const Tensor< T > &A, const Tensor< T > &B, int itype, Tensor< T > &V, Tensor< typename Tensor< T >::scalar_type > &e)
Generalized real-symmetric or complex-Hermitian eigenproblem.
Definition: lapack.cc:519
void unaryop(T(*f)(T))
Inplace unary operation on function values.
Definition: mra.h:840
void make_nuclear_potential_impl()
Definition: solver.h:1041
Tensor< double > op(const Tensor< double > &x)
Definition: kain.cc:508
void apply_hf_exchange(vecfuncT &phisa, vecfuncT &phisb, vecfuncT &funcsa, vecfuncT &funcsb)
Definition: solver.h:2413
int restart
Definition: electronicstructureparams.h:101
const T1 & f1
Definition: gtest-tuple.h:680
double lo
Definition: electronicstructureparams.h:54
Contracted Gaussian basis.
Definition: chem/molecularbasis.h:391
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
Function< T, NDIM > project(const Function< T, NDIM > &other, int k=FunctionDefaults< NDIM >::get_k(), double thresh=FunctionDefaults< NDIM >::get_thresh(), bool fence=true)
Definition: mra.h:2162
#define MADNESS_EXCEPTION(msg, value)
Definition: worldexc.h:88
A slice defines a sub-range or patch of a dimension.
Definition: slice.h:103
void update_orbitals(vecfuncT &awfs, vecfuncT &bwfs, std::vector< KPoint > kpoints)
Definition: solver.h:3723
double thresh() const
Returns value of truncation threshold. No communication.
Definition: mra.h:542
double koffset1
Definition: electronicstructureparams.h:94
const T1 const T2 & f2
Definition: gtest-tuple.h:680
void solve()
Definition: solver.h:2520
FunctionFactory implements the named-parameter idiom for Function.
Definition: funcimpl.h:70
bool is_equal(double val1, double val2, double eps)
Definition: esolver.h:190
const mpreal fabs(const mpreal &v, mp_rnd_t rnd_mode)
Definition: mpreal.h:2187
Tensor< double_complex > tensor_complex
Definition: functypedefs.h:44
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
T stheta_fd(const T &x)
Definition: solver.h:76
Function< T, NDIM > apply(const Derivative< T, NDIM > &D, const Function< T, NDIM > &f, bool fence=true)
Applies derivative operator to function (for syntactic equivalence to integral operator apply) ...
Definition: derivative.h:613
const double c
Definition: gfit.cc:200
double weight()
Definition: eigsolver.h:79
std::vector< Function< TENSOR_RESULT_TYPE(T, R), NDIM > > transform(World &world, const std::vector< Function< T, NDIM > > &v, const DistributedMatrix< R > &c, bool fence=true)
Definition: chem/SCF.cc:86
double wall_time()
Returns the wall time in seconds relative to arbitrary origin.
Definition: world.cc:248
void normalize(World &world, std::vector< Function< T, NDIM > > &v, bool fence=true)
Normalizes a vector of functions — v[i] = v[i].scale(1.0/v[i].norm2())
Definition: vmra.h:765
An archive for storing local or parallel data wrapping BinaryFstreamInputArchive. ...
Definition: parar.h:266
void get_coords(double &x, double &y, double &z) const
Definition: chem/molecularbasis.h:380
void apply_hf_exchange3(vecfuncT &phisa, vecfuncT &phisb, vecfuncT &funcsa, vecfuncT &funcsb, double &xc)
Definition: solver.h:2325
void print_tensor2d(ostream &os, Tensor< Q > t)
Definition: solver.h:2834
static void set_k(int value)
Sets the default wavelet order.
Definition: funcdefaults.h:219
void reproject()
Definition: solver.h:563
int natom() const
Definition: mentity.h:112
double_complex operator()(const coord_3d &x) const
Definition: solver.h:141
The SubspaceK class is a container class holding previous orbitals and residuals. ...
Definition: solver.h:193
void fix_occupations(const std::vector< T > &eps, std::vector< double > &occs)
Definition: solver.h:3817
bool ispotential
Definition: electronicstructureparams.h:62
Function< T, NDIM > conj(const Function< T, NDIM > &f, bool fence=true)
Return the complex conjugate of the input function with the same distribution and optional fence...
Definition: mra.h:1879
Tensor< T > KAIN(const Tensor< T > &Q, double rcond=1e-12)
Solves non-linear equation using KAIN (returns coefficients to compute next vector) ...
Definition: solvers.h:98
void do_rhs(vecfuncT &wf, vecfuncT &vwf, std::vector< KPoint > kpoints, std::vector< T > &alpha, std::vector< double > &eigs)
Definition: solver.h:2946
void update_subspace(vecfuncT &awfs_new, vecfuncT &bwfs_new, const vecfuncT &awfs_old, const vecfuncT &bwfs_old)
Definition: solver.h:246
Solver(World &world, rfunctionT vnucrhon, vecfuncT phisa, vecfuncT phisb, std::vector< T > eigsa, std::vector< T > eigsb, ElectronicStructureParams params, MolecularEntity mentity)
Definition: solver.h:1296
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition: vmra.h:130
void test_periodicity(const Function< Q, 3 > &f)
Definition: solver.h:1166
int maxits
Definition: electronicstructureparams.h:60