MADNESS  version 0.9
spectralprop.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 */
85 #include <madness/mra/legendre.h>
86 #include <madness/world/worldexc.h>
87 
88 #include <algorithm>
89 #include <cmath>
90 #include <complex>
91 
92 namespace madness {
93 
95  inline double distance(double a, double b)
96  {
97  return std::sqrt((a-b)*(a-b));
98  }
99 
101  template <typename T>
102  inline double distance(std::complex<T>& a, std::complex<T>& b)
103  {
104  return std::abs(a-b);
105  }
106 
107 
110  const int NPT;
111  std::vector<double> x;
112  std::vector<double> w;
114 
116  double p(int i, double t) {
117  double top=1.0, bot=1.0;
118  for (int j=0; j<i; j++) {
119  top *= (t-x[j]);
120  bot *= (x[i]-x[j]);
121  }
122  for (int j=i+1; j<=NPT; j++) {
123  top *= (t-x[j]);
124  bot *= (x[i]-x[j]);
125  }
126  return top/bot;
127  }
128 
130  template <typename uT>
131  uT u(double dt, const std::vector<uT>& v) {
132  uT U = v[0]*p(0,dt);
133  for (int i=1; i<=NPT; i++) {
134  U += v[i]*p(i,dt);
135  }
136  return U;
137  }
138 
139  // Separated this out to enable recursive use of solver ... but this
140  // turned out to be largely not useful.
141  template <typename uT, typename expLT, typename NT>
142  std::vector<uT> solve(double t, double Delta, const uT& u0, const expLT& expL, const NT& N, const double eps, bool doprint, bool recurinit, int& napp) {
143  if (doprint) madness::print("solving with NPT", NPT);
144  std::vector<uT> v(NPT+1,u0);
145 
146  if (!recurinit || NPT==1) {
147  // Initialize using explicit first-order accurate rule
148  for (int i=1; i<=NPT; i++) {
149  double dt = x[i] - x[i-1];
150  v[i] = expL(dt*Delta,v[i-1]);
151  v[i] += expL(Delta*dt,N(t+Delta*x[i-1],v[i-1]))*(dt*Delta);
152  }
153  }
154  else {
155  // Recur down to lower-order quadrature rules for initial guess
156  std::vector<uT> vx = q->solve(t, Delta, u0, expL, N, eps*10000.0, doprint, recurinit, napp);
157  for (int i=1; i<=NPT; i++) {
158  v[i] = q->u(x[i],vx);
159  }
160  }
161 
162  // Precompute G(x[1]-x[0])*v[0]
163  uT Gv0 = expL((x[1] - x[0])*Delta,v[0]); napp++;
164 
165  // Crude fixed point iteration
166  uT vold = v[NPT]; // Track convergence thru change at last quadrature point
167  bool converged = false;
168  for (int iter=0; iter<20; iter++) {
169  for (int i=1; i<=NPT; i++) {
170  double dt = x[i] - x[i-1];
171  uT vinew = (i==0) ? Gv0*1.0 : expL(dt*Delta,v[i-1]); // *1.0 in case copy is shallow
172  if (i != 0) napp++;
173  for (int k=1; k<=NPT; k++) {
174  double ddt = x[i-1] + dt*x[k];
175  vinew += expL(dt*Delta*(1.0-x[k]), N(t + Delta*ddt, u(ddt, v)))*(dt*Delta*w[k]); napp++;
176  }
177  v[i] = vinew;
178  }
179  double err = ::madness::distance(v[NPT],vold);
180  vold = v[NPT];
181  if (doprint) print("spectral",iter,err);
182  converged = (err < eps);
183  if (converged) break;
184  }
185  if (!converged) throw "spectral propagator failed to converge";
186 
187  return v;
188  }
189 
190  public:
193  : NPT(NPT)
194  , x(NPT+1)
195  , w(NPT+1)
196  , q(0)
197  {
198  x[0] = w[0] = 0.0;
199  MADNESS_ASSERT(gauss_legendre(NPT, 0.0, 1.0, &x[1], &w[1]));
200 
201  // The iterative solution requires quadrature points in increasing
202  // order corresponding to shooting forward.
203  std::reverse(x.begin()+1, x.end());
204  std::reverse(w.begin()+1, w.end());
205 
206  if (NPT > 1) q = new SpectralPropagator(NPT-1);
207  }
208 
210  {
211  delete q;
212  }
213 
215 
239  template <typename uT, typename expLT, typename NT>
240  uT step(double t, double Delta, const uT& u0, const expLT& expL, const NT& N, const double eps=1e-12, bool doprint=false, bool recurinit=true) {
241  int napp = 0;
242 
243  // Compute solution at quadrature points
244  std::vector<uT> v = solve(t, Delta, u0, expL, N, eps, doprint, recurinit, napp);
245 
246  // Integrate forward from last quadrature point to the end point
247  double dt = 1.0 - x[NPT];
248  uT vinew = expL(dt*Delta,v[NPT]);
249  for (int k=1; k<=NPT; k++) {
250  double ddt = x[NPT] + dt*x[k];
251  vinew += expL(dt*Delta*(1.0-x[k]), N(t + Delta*ddt, u(ddt, v)))*(dt*Delta*w[k]); napp++;
252  }
253 
254  if (doprint) print("number of operator applications", napp);
255  return vinew;
256  }
257  };
258 
260  const int NPT;
261  std::vector<double> x;
262  std::vector<double> w;
263 
264  // Makes interpolating polyn p[i](t), i=0..NPT-1
265  double p(int i, double t) {
266  double top=1.0, bot=1.0;
267  for (int j=0; j<i; j++) {
268  top *= (t-x[j]);
269  bot *= (x[i]-x[j]);
270  }
271  for (int j=i+1; j<NPT; j++) {
272  top *= (t-x[j]);
273  bot *= (x[i]-x[j]);
274  }
275  return top/bot;
276  }
277 
278  template <typename uT>
279  uT u(double dt, const std::vector<uT>& v) {
280  uT U = v[0]*p(0,dt);
281  for (int i=1; i<NPT; i++) {
282  U += v[i]*p(i,dt);
283  }
284  return U;
285  }
286 
287  public:
288  // Constructor
289  // ... input ... npt,
290  // ... makes ... x, w, p
291  //
292  // Apply
293  // ... input ... u(0)
294  // ... makes guess v(i), i=0..npt using explicit 1st order rule.
295 
297  : NPT(NPT)
298  , x(NPT)
299  , w(NPT)
300  {
301  MADNESS_ASSERT(NPT>=2 && NPT<=6);
302  // Gauss Lobatto on [-1,1]
303  x[0] = -1.0; x[NPT-1] = 1.0; w[0] = w[NPT-1] = 2.0/(NPT*(NPT-1));
304  if (NPT == 2) {
305  }
306  else if (NPT == 3) {
307  x[1] = 0.0; w[1] = 4.0/3.0;
308  }
309  else if (NPT == 4) {
310  x[1] = -1.0/std::sqrt(5.0); w[1] = 5.0/6.0;
311  x[2] = -x[1]; w[2] = w[1];
312  }
313  else if (NPT == 5) {
314  x[1] = -std::sqrt(3.0/7.0); w[1] = 49.0/90.0;
315  x[2] = 0.0; w[2] = 32.0/45.0;
316  x[3] = -x[1]; w[3] = w[1];
317  }
318  else if (NPT == 6) {
319  x[1] = -std::sqrt((7.0+2.0*std::sqrt(7.0))/21.0); w[1] = (14.0-std::sqrt(7.0))/30.0;
320  x[2] = -std::sqrt((7.0-2.0*std::sqrt(7.0))/21.0); w[2] = (14.0+std::sqrt(7.0))/30.0;
321  x[3] = -x[2]; w[3] = w[2];
322  x[4] = -x[1]; w[4] = w[1];
323  }
324  else {
325  throw "bad NPT";
326  }
327 
328  // Map from [-1,1] onto [0,1]
329  for (int i=0; i<NPT; i++) {
330  x[i] = 0.5*(1.0 + x[i]);
331  w[i] = 0.5*w[i];
332  }
333  }
334 
335  template <typename uT, typename expLT, typename NT>
336  uT step(double t, double Delta, const uT& u0, const expLT& expL, const NT& N, const double eps=1e-12, bool doprint=false) {
337  std::vector<uT> v(NPT,u0);
338 
339  // Initialize using explicit first-order accurate rule
340  for (int i=1; i<NPT; i++) {
341  double dt = x[i] - x[i-1];
342  v[i] = expL(dt*Delta,v[i-1]);
343  v[i] += expL(Delta*dt,N(t+Delta*x[i-1],v[i-1]))*(dt*Delta);
344  }
345 
346  // Crude fixed point iteration
347  uT vold = v[NPT-1];
348  for (int iter=0; iter<12; iter++) {
349  for (int i=1; i<NPT; i++) {
350  double dt = x[i] - x[i-1];
351  uT vinew = expL(dt*Delta,v[i-1]);
352  for (int k=0; k<NPT; k++) {
353  double ddt = x[i-1] + dt*x[k];
354  vinew += expL(dt*Delta*(1.0-x[k]), N(t + Delta*ddt, u(ddt, v)))*(dt*Delta*w[k]);
355  }
356  v[i] = vinew;
357  }
358  double err = ::madness::distance(vold, v[NPT-1]);
359  if (doprint) print("hello",iter,err);
360  vold = v[NPT-1];
361  if (err < eps) break;
362  }
363 
364  return vold;
365  }
366  };
367 
368 }
uT step(double t, double Delta, const uT &u0, const expLT &expL, const NT &N, const double eps=1e-12, bool doprint=false, bool recurinit=true)
Step forward in time from to .
Definition: spectralprop.h:240
SpectralPropagatorGaussLobatto(int NPT)
Definition: spectralprop.h:296
SpectralPropagator(int NPT)
Construct propagator using NPT points.
Definition: spectralprop.h:192
uT step(double t, double Delta, const uT &u0, const expLT &expL, const NT &N, const double eps=1e-12, bool doprint=false)
Definition: spectralprop.h:336
const int k
Definition: dielectric.cc:184
FLOAT a(int j, FLOAT z)
Definition: y1.cc:86
bool gauss_legendre(int n, double xlo, double xhi, double *x, double *w)
Definition: legendre.cc:231
Definition: spectralprop.h:259
tensorT sqrt(const tensorT &s, double tol=1e-8)
Computes matrix square root (not used any more?)
Definition: DFcode/moldft.cc:446
Spectral propagtor in time. Refer to documentation of file spectralprop.h for math detail...
Definition: spectralprop.h:109
~SpectralPropagator()
Definition: spectralprop.h:209
Implements MadnessException.
void print(const A &a)
Print a single item to std::cout terminating with new line.
Definition: print.h:122
Holds machinery to set up Functions/FuncImpls using various Factories and Interfaces.
Definition: chem/atomutil.cc:45
FLOAT b(int j, FLOAT z)
Definition: y1.cc:79
double distance(const madness::coord_3d &a, const madness::coord_3d &b)
Definition: molecularmask.h:10