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 //***************************************************************************
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 //*************************************************************************
23 tensor_complex _Q;
24 //*************************************************************************
25
26 //*************************************************************************
28 //*************************************************************************
29
30 //*************************************************************************
32 //*************************************************************************
33
34 //*************************************************************************
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,
49 vector_complex_function_3d& awfs_new,
50 vector_complex_function_3d& bwfs_new,
51 const vector_complex_function_3d& awfs_old,
52 const vector_complex_function_3d& bwfs_old,
53 const vector_complex_function_3d& rm)
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
93 tensor_complex c;
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
194 tensor_complex c;
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 //*************************************************************************
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
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
static const double c
Definition relops.cc:10
static const double m
Definition relops.cc:9
void e()
Definition test_sig.cc:75