MADNESS  0.10.1
subspace.h
Go to the documentation of this file.
1 #ifndef SUBSPACE_H
2 #define SUBSPACE_H
3 
4  /*!
5  \ingroup periodic_solver
6 
7  \brief The Subspace class is a container class holding previous orbitals
8  and residuals.
9  \par
10  The Solver class uses the Krylov Accelerated Inexact Newton Solver (KAIN)
11  accelerate the convergence a given calculation. The KAIN solver needs to
12  store a subspace of previous orbitals and residuals.
13  */
14 
15  //***************************************************************************
16  class Subspace
17  {
18  // Typedef's
19  typedef std::pair<vector_complex_function_3d,vector_complex_function_3d> pairvecT;
20  typedef std::vector<pairvecT> subspaceT;
21 
22  //*************************************************************************
24  //*************************************************************************
25 
26  //*************************************************************************
28  //*************************************************************************
29 
30  //*************************************************************************
31  bool _spinpol;
32  //*************************************************************************
33 
34  //*************************************************************************
35  int _maxsub;
36  //*************************************************************************
37 
38  public:
39 
40  //*************************************************************************
41  Subspace(bool spinpol=false, int maxsub=4)
42  : _spinpol(spinpol), _maxsub(maxsub)
43  {
44  }
45  //*************************************************************************
46 
47  //*************************************************************************
48  void update_subspace(World& world,
51  const vector_complex_function_3d& awfs_old,
52  const vector_complex_function_3d& bwfs_old,
54  {
55  // concatenate up and down spins
56  vector_complex_function_3d vm = awfs_old;
57  if (_spinpol)
58  {
59  vm.insert(vm.end(), bwfs_old.begin(), bwfs_old.end());
60  }
61 
62  // Update subspace and matrix Q
63  compress(world, vm, false);
64  compress(world, rm, false);
65  world.gop.fence();
66  _subspace.push_back(pairvecT(vm,rm));
67 
68  int m = _subspace.size();
69  tensor_complex ms(m);
70  tensor_complex sm(m);
71  for (int s=0; s<m; s++)
72  {
73  const vector_complex_function_3d& vs = _subspace[s].first;
74  const vector_complex_function_3d& rs = _subspace[s].second;
75  for (unsigned int i=0; i<vm.size(); i++)
76  {
77  ms[s] += vm[i].inner_local(rs[i]);
78  sm[s] += vs[i].inner_local(rm[i]);
79  }
80  }
81  world.gop.sum(ms.ptr(),m);
82  world.gop.sum(sm.ptr(),m);
83 
84  tensor_complex newQ(m,m);
85  if (m > 1) newQ(Slice(0,-2),Slice(0,-2)) = _Q;
86  newQ(m-1,_) = ms;
87  newQ(_,m-1) = sm;
88 
89  _Q = newQ;
90  if (world.rank() == 0) print(_Q);
91 
92  // Solve the subspace equations
94  if (world.rank() == 0) {
95  double rcond = 1e-12;
96  while (1) {
97  c = KAIN(_Q,rcond);
98  if (abs(c[m-1]) < 3.0) {
99  break;
100  }
101  else if (rcond < 0.01) {
102  if (world.rank() == 0)
103  print("Increasing subspace singular value threshold ", c[m-1], rcond);
104  rcond *= 100;
105  }
106  else {
107  if (world.rank() == 0)
108  print("Forcing full step due to subspace malfunction");
109  c = 0.0;
110  c[m-1] = 1.0;
111  break;
112  }
113  }
114  }
115 
116  world.gop.broadcast_serializable(c, 0);
117  if (world.rank() == 0) {
118  print("Subspace solution", c);
119  }
120 
121  // Form linear combination for new solution
122  vector_complex_function_3d phisa_new = zero_functions_compressed<double_complex,3>(world, awfs_old.size());
123  vector_complex_function_3d phisb_new = zero_functions_compressed<double_complex,3>(world, bwfs_old.size());
124  std::complex<double> one = std::complex<double>(1.0,0.0);
125  for (unsigned int m=0; m<_subspace.size(); m++) {
126  const vector_complex_function_3d& vm = _subspace[m].first;
127  const vector_complex_function_3d& rm = _subspace[m].second;
128  const vector_complex_function_3d vma(vm.begin(),vm.begin()+awfs_old.size());
129  const vector_complex_function_3d rma(rm.begin(),rm.begin()+awfs_old.size());
130  const vector_complex_function_3d vmb(vm.end()-bwfs_old.size(), vm.end());
131  const vector_complex_function_3d rmb(rm.end()-bwfs_old.size(), rm.end());
132 
133  gaxpy(world, one, phisa_new, c(m), vma, false);
134  gaxpy(world, one, phisa_new,-c(m), rma, false);
135  gaxpy(world, one, phisb_new, c(m), vmb, false);
136  gaxpy(world, one, phisb_new,-c(m), rmb, false);
137  }
138  world.gop.fence();
139 
140  if (_maxsub <= 1) {
141  // Clear subspace if it is not being used
142  _subspace.clear();
143  }
144  else if (_subspace.size() == size_t(_maxsub)) {
145  // Truncate subspace in preparation for next iteration
146  _subspace.erase(_subspace.begin());
147  _Q = _Q(Slice(1,-1),Slice(1,-1));
148  }
149  awfs_new = phisa_new;
150  bwfs_new = phisb_new;
151  }
152  //*************************************************************************
153 
154  //*************************************************************************
155  void update_subspace(World& world,
156  vector_complex_function_3d& awfs_new,
157  const vector_complex_function_3d& awfs_old,
158  const vector_complex_function_3d& rm)
159  {
160  // concatenate up and down spins
161  vector_complex_function_3d vm = awfs_old;
162 
163  // Update subspace and matrix Q
164  compress(world, vm, false);
165  compress(world, rm, false);
166  world.gop.fence();
167  _subspace.push_back(pairvecT(vm,rm));
168 
169  int m = _subspace.size();
170  tensor_complex ms(m);
171  tensor_complex sm(m);
172  for (int s=0; s<m; s++)
173  {
174  const vector_complex_function_3d& vs = _subspace[s].first;
175  const vector_complex_function_3d& rs = _subspace[s].second;
176  for (unsigned int i=0; i<vm.size(); i++)
177  {
178  ms[s] += vm[i].inner_local(rs[i]);
179  sm[s] += vs[i].inner_local(rm[i]);
180  }
181  }
182  world.gop.sum(ms.ptr(),m);
183  world.gop.sum(sm.ptr(),m);
184 
185  tensor_complex newQ(m,m);
186  if (m > 1) newQ(Slice(0,-2),Slice(0,-2)) = _Q;
187  newQ(m-1,_) = ms;
188  newQ(_,m-1) = sm;
189 
190  _Q = newQ;
191  if (world.rank() == 0) print(_Q);
192 
193  // Solve the subspace equations
195  if (world.rank() == 0) {
196  double rcond = 1e-12;
197  while (1) {
198  c = KAIN(_Q,rcond);
199  if (abs(c[m-1]) < 3.0) {
200  break;
201  }
202  else if (rcond < 0.01) {
203  if (world.rank() == 0)
204  print("Increasing subspace singular value threshold ", c[m-1], rcond);
205  rcond *= 100;
206  }
207  else {
208  if (world.rank() == 0)
209  print("Forcing full step due to subspace malfunction");
210  c = 0.0;
211  c[m-1] = 1.0;
212  break;
213  }
214  }
215  }
216 
217  world.gop.broadcast_serializable(c, 0);
218  if (world.rank() == 0) {
219  print("Subspace solution", c);
220  }
221 
222  // Form linear combination for new solution
223  vector_complex_function_3d phisa_new = zero_functions_compressed<double_complex,3>(world, awfs_old.size());
224  std::complex<double> one = std::complex<double>(1.0,0.0);
225  for (unsigned int m=0; m<_subspace.size(); m++) {
226  const vector_complex_function_3d& vm = _subspace[m].first;
227  const vector_complex_function_3d& rm = _subspace[m].second;
228  const vector_complex_function_3d vma(vm.begin(),vm.begin()+awfs_old.size());
229  const vector_complex_function_3d rma(rm.begin(),rm.begin()+awfs_old.size());
230 
231  gaxpy(world, one, phisa_new, c(m), vma, false);
232  gaxpy(world, one, phisa_new,-c(m), rma, false);
233  }
234  world.gop.fence();
235 
236  if (_maxsub <= 1) {
237  // Clear subspace if it is not being used
238  _subspace.clear();
239  }
240  else if (_subspace.size() == size_t(_maxsub)) {
241  // Truncate subspace in preparation for next iteration
242  _subspace.erase(_subspace.begin());
243  _Q = _Q(Slice(1,-1),Slice(1,-1));
244  }
245  awfs_new = phisa_new;
246  }
247  //*************************************************************************
248 
249  //*************************************************************************
250  void reproject()
251  {
252  // //if (world.rank() == 0)
253  // //printf("\n\nreprojecting subspace to wavelet order: %d and thresh: %.5e\n\n",
254  // //FunctionDefaults<3>::get_k(), FunctionDefaults<3>::get_thresh());
255  //
256  // unsigned int m = _subspace.size();
257  // for (unsigned int s = 0; s < m; s++)
258  // {
259  // vector_complex_function_3d& vs = _subspace[s].first;
260  // vector_complex_function_3d& rs = _subspace[s].second;
261  // reconstruct(world, vs);
262  // reconstruct(world, rs);
263  // unsigned int vm = vs.size();
264  // for (unsigned int i = 0; i < vm; i++)
265  // {
266  // vs[i] = madness::project(vs[i], FunctionDefaults<3>::get_k(),
267  // FunctionDefaults<3>::get_thresh(), false);
268  // rs[i] = madness::project(rs[i], FunctionDefaults<3>::get_k(),
269  // FunctionDefaults<3>::get_thresh(), false);
270  // }
271  // world.gop.fence();
272  // truncate(world, vs);
273  // truncate(world, rs);
274  // normalize(world, vs);
275  // }
276  // world.gop.fence();
277 
278  }
279  //*************************************************************************
280 
281  };
282 
283 // template <typename T, int NDIM>
284 // struct lbcost {
285 // double leaf_value;
286 // double parent_value;
287 // lbcost(double leaf_value=1.0, double parent_value=0.0) : leaf_value(leaf_value), parent_value(parent_value) {}
288 // double operator()(const Key<NDIM>& key, const FunctionNode<T,NDIM>& node) const {
289 // if (key.level() <= 1) {
290 // return 100.0*(leaf_value+parent_value);
291 // }
292 // else if (node.is_leaf()) {
293 // return leaf_value;
294 // }
295 // else {
296 // return parent_value;
297 // }
298 // }
299 // };
300 
301  //***************************************************************************
302 
303  /*! \ingroup periodic_solver
304  \brief The main class of the periodic DFT solver
305  \f[
306  z = frac{x}{1 - y^2}
307  \f]
308  */
309 
310 #endif
The Subspace class is a container class holding previous orbitals and residuals.
Definition: subspace.h:17
bool _spinpol
Definition: subspace.h:31
void reproject()
Definition: subspace.h:250
int _maxsub
Definition: subspace.h:35
void update_subspace(World &world, vector_complex_function_3d &awfs_new, const vector_complex_function_3d &awfs_old, const vector_complex_function_3d &rm)
Definition: subspace.h:155
subspaceT _subspace
Definition: subspace.h:27
std::pair< vector_complex_function_3d, vector_complex_function_3d > pairvecT
Definition: subspace.h:19
std::vector< pairvecT > subspaceT
Definition: subspace.h:20
tensor_complex _Q
Definition: subspace.h:23
Subspace(bool spinpol=false, int maxsub=4)
Definition: subspace.h:41
void update_subspace(World &world, vector_complex_function_3d &awfs_new, vector_complex_function_3d &bwfs_new, const vector_complex_function_3d &awfs_old, const vector_complex_function_3d &bwfs_old, const vector_complex_function_3d &rm)
Definition: subspace.h:48
const double m
Definition: gfit.cc:199
Tensor< T > KAIN(const Tensor< T > &Q)
Solves the KAIN equations for coefficients to compute the next vector.
Definition: kain.cc:60
void print(const tensorT &t)
Definition: mcpfit.cc:140
std::vector< complex_function_3d > vector_complex_function_3d
Definition: functypedefs.h:86
double abs(double x)
Definition: complexfun.h:48
void compress(World &world, const std::vector< Function< T, NDIM > > &v, bool fence=true)
Compress a vector of functions.
Definition: vmra.h:133
static const Slice _(0,-1, 1)
Tensor< double_complex > tensor_complex
Definition: functypedefs.h:44
void gaxpy(const double a, ScalarResult< T > &left, const double b, const T &right, const bool fence=true)
the result type of a macrotask must implement gaxpy
Definition: macrotaskq.h:140
static const double c
Definition: relops.cc:10
void e()
Definition: test_sig.cc:75