MADNESS 0.10.1
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*/
33/*!
34 \file spectralprop.h
35 \brief Spectral propagator in time using semigroup approach
36 \defgroup spectralprop Spectral propagator in time using semigroup approach
37 \ingroup examples
38
39 The source is <a href=http://code.google.com/p/m-a-d-n-e-s-s/source/browse/local/trunk/src/apps/examples/spectralprop.h>here</a>.
40
41 \par Points of interest
42 - high-order integration of general time-dependent problems
43 - semigroup approach
44
45 \par Background
46
47 Given \f$ u(0) \f$, we seek to solve the PDE
48 \f[
49 \frac{du}{dt} = \hat{L} u + N(u)
50 \f]
51 for the function at some future time \f$ t \f$ (i.e., for \f$ u(t) \f$).
52 \f$ \hat{L} \f$ is a linear operator that we are
53 able to exponentiate, and \f$ N \f$ is everything else
54 including linear and non-linear parts.
55
56 In the semigroup approach the formal solution to the PDE
57 is written
58 \f[
59 u(t) = \exp(t \hat{L} ) u(0) + \int_0^t \exp((t-\tau)\hat{L}) N(u(\tau)) d\tau
60 \f]
61 Numerical quadrature of the integral using Gauss-Legendre
62 quadrature points is used resulting in a set of equations
63 that are iteratively solved (presently using simple fixed
64 point iteration from a first-order explicit rule).
65
66 The user provides
67 - functors to apply the exponential and non-linear parts, and
68 - if necessary a user-defined data type that supports
69 a copy constructor, assignment, inplace addition, multiplication
70 from the right by a double, and computation of the distance
71 between two solutions \f$ a \f$ and \f$ b \f$ with the api
72 \verb+double distance(a,b)+
73
74 Have a look in testspectralprop.cc for example use.
75
76 With \f$ n \f$ quadrature points, the error is \f$ O\left(t^{2n+1}\right) \f$
77 and the number of applications of the exponential operator per
78 time step is \f$ 1+(n_{it}+1)n +n_{it}n^2 \f$ where \f$ n_{it} \f$
79 is the number of iterations necessary to solve the equations
80 (typically about 5 but this is problem dependent).
81
82*/
83
84
87
88#include <algorithm>
89#include <cmath>
90#include <complex>
91
92namespace madness {
93
94 /// Default function for computing the distance between two doubles
95 inline double distance(double a, double b)
96 {
97 return std::sqrt((a-b)*(a-b));
98 }
99
100 /// Default function for computing the distance between two complex numbers
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
108 /// Spectral propagtor in time. Refer to documentation of file spectralprop.h for math detail.
110 const int NPT; ///< Number of quadrature points
111 std::vector<double> x; ///< Quadrature points on [0,1] with value 0 prepended
112 std::vector<double> w; ///< Quadrature weights on [0,1] with value 0 prepended
114
115 /// Private: Makes interpolating polyn p[i](t), i=0..NPT
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
129 /// Private: Computes interpolated solution
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:
191 /// Construct propagator using \c NPT points
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
214 /// Step forward in time from \f$ t \f$ to \f$ t+\Delta \f$
215
216 /// The template types should be automatically inferred from
217 /// the invocation. \c uT is the C++ type for the solution.
218 ///
219 /// @param[in] t The current time
220 /// @param[in] Delta The time step
221 /// @param[in] u0 The solution at the current time
222 /// @param[in] expL A function or functor to compute \f$ \exp{\tau \hat{L}} u \f$ for \f$ \tau \in (0,\Delta) \f$
223 /// @param[in] N A function to compute the non-linear part
224 /// @param[in] eps Threshold for convergence of iteration on norm of change in solution at last quadrature point.
225 /// @param[in] doprint If true will print some info on convergence
226 /// @param[in] recurinit If true initial guess is recursion from lower order quadrature instead of default explicit rule
227 /// @returns The solution at time \f$ t+\Delta \f$
228 ///
229 /// The user provided operators are invoked as
230 /// \code
231 /// uT expL(double tau, const uT& u)
232 /// \endcode
233 /// where \f$ \tau \in (0,\Delta) \f$
234 /// and
235 /// \code
236 /// uT N(double T, const uT& u)
237 /// \endcode
238 /// where \f$ T \in (t,t+\Delta) \f$ and \f$ u \f$ is a trial solution at time \f$ T \f$.
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}
Definition spectralprop.h:259
uT u(double dt, const std::vector< uT > &v)
Definition spectralprop.h:279
std::vector< double > x
Definition spectralprop.h:261
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
double p(int i, double t)
Definition spectralprop.h:265
const int NPT
Definition spectralprop.h:260
std::vector< double > w
Definition spectralprop.h:262
SpectralPropagatorGaussLobatto(int NPT)
Definition spectralprop.h:296
Spectral propagtor in time. Refer to documentation of file spectralprop.h for math detail.
Definition spectralprop.h:109
std::vector< double > x
Quadrature points on [0,1] with value 0 prepended.
Definition spectralprop.h:111
double p(int i, double t)
Private: Makes interpolating polyn p[i](t), i=0..NPT.
Definition spectralprop.h:116
SpectralPropagator(int NPT)
Construct propagator using NPT points.
Definition spectralprop.h:192
uT u(double dt, const std::vector< uT > &v)
Private: Computes interpolated solution.
Definition spectralprop.h:131
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
~SpectralPropagator()
Definition spectralprop.h:209
const int NPT
Number of quadrature points.
Definition spectralprop.h:110
SpectralPropagator * q
Definition spectralprop.h:113
std::vector< double > w
Quadrature weights on [0,1] with value 0 prepended.
Definition spectralprop.h:112
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)
Definition spectralprop.h:142
static const double v
Definition hatom_sf_dirac.cc:20
Defines madness::MadnessException for exception handling.
#define MADNESS_ASSERT(condition)
Assert a condition that should be free of side-effects since in release builds this might be a no-op.
Definition madness_exception.h:134
Namespace for all elements and tools of MADNESS.
Definition DFParameters.h:10
double distance(double a, double b)
Default function for computing the distance between two doubles.
Definition spectralprop.h:95
bool gauss_legendre(int n, double xlo, double xhi, double *x, double *w)
Definition legendre.cc:226
void print(const T &t, const Ts &... ts)
Print items to std::cout (items separated by spaces) and terminate with a new line.
Definition print.h:225
static long abs(long a)
Definition tensor.h:218
static const double b
Definition nonlinschro.cc:119
static const double a
Definition nonlinschro.cc:118
static const long k
Definition rk.cc:44
void e()
Definition test_sig.cc:75
#define N
Definition testconv.cc:37
Fred expL(double dt, const Fred &f)
Definition testspectralprop.cc:98