1
// Copyright (C) 2005-2006 Anders Logg.
2
// Licensed under the GNU LGPL Version 2.1.
4
// First added: 2005-02-02
5
// Last changed: 2006-08-21
7
#include <dolfin/Array.h>
8
#include <dolfin/ComplexODE.h>
10
using namespace dolfin;
12
//-----------------------------------------------------------------------------
13
ComplexODE::ComplexODE(uint n, real T) : ODE(2*n, T), n(n), j(0.0, 1.0),
14
zvalues(0), fvalues(0), yvalues(0)
16
message("Creating complex ODE of size %d (%d complex components).", N, n);
18
// Initialize complex solution vector and right-hand side
19
zvalues = new complex[n];
20
fvalues = new complex[n];
21
for (uint i = 0; i < n; i++)
27
//-----------------------------------------------------------------------------
28
ComplexODE::~ComplexODE()
30
if ( zvalues ) delete [] zvalues;
31
if ( fvalues ) delete [] fvalues;
32
if ( yvalues ) delete [] yvalues;
34
//-----------------------------------------------------------------------------
35
complex ComplexODE::f(const complex z[], real t, uint i)
37
error("Right-hand side for complex ODE not supplied by user.");
42
//-----------------------------------------------------------------------------
43
void ComplexODE::f(const complex z[], real t, complex y[])
45
// If a user of the mono-adaptive solver does not supply this function,
46
// then call f() for each component.
48
for (uint i = 0; i < n; i++)
49
y[i] = this->f(z, t, i);
51
//-----------------------------------------------------------------------------
52
void ComplexODE::M(const complex x[], complex y[], const complex z[], real t)
54
// Assume M is the identity if not supplied by user: y = x
55
for (uint i = 0; i < n; i++)
58
//-----------------------------------------------------------------------------
59
void ComplexODE::J(const complex x[], complex y[], const complex z[], real t)
61
// If a user does not supply J, then compute it by the approximation
63
// Jx = ( f(z + hx) - f(z - hx) ) / 2h
65
error("Not implemented yet...");
67
//-----------------------------------------------------------------------------
68
real ComplexODE::k(uint i)
70
return default_timestep;
72
//-----------------------------------------------------------------------------
73
bool ComplexODE::update(const complex z[], real t, bool end)
77
//-----------------------------------------------------------------------------
78
void ComplexODE::u0(uBlasVector& u)
80
// Translate initial value from complex to real
82
for (uint i = 0; i < N; i++)
84
complex z = zvalues[i / 2];
85
u(i) = ( i % 2 == 0 ? z.real() : z.imag() );
88
//-----------------------------------------------------------------------------
89
real ComplexODE::f(const uBlasVector& u, real t, uint i)
91
// Translate right-hand side from complex to real, assuming that if
92
// u_i depends on u_j, then u_i depends on both the real and
93
// imaginary parts of the corresponding z_i
95
// Update zvalues for correct components
96
const Array<uint>& deps = dependencies[i];
97
for (uint pos = 0; pos < deps.size(); pos++)
99
// Element of u that needs to be updated
100
const uint ju = deps[pos];
102
// Corresponding element of z
103
const uint jz = ju / 2;
106
const complex zvalue(u(2*jz), u(2*jz + 1));
107
zvalues[jz] = zvalue;
110
// Call user-supplied function f(z, t, i)
111
const complex fvalue = f(zvalues, t, i / 2);
114
return ( i % 2 == 0 ? fvalue.real() : fvalue.imag() );
116
//-----------------------------------------------------------------------------
117
void ComplexODE::f(const uBlasVector& u, real t, uBlasVector& y)
119
// Update zvalues for all components
120
for (uint i = 0; i < n; i++)
122
const complex zvalue(u(2*i), u(2*i + 1));
126
// Call user-supplied function f(z, t, y)
127
f(zvalues, t, fvalues);
129
// Translate values into f
130
for (uint i = 0; i < n; i++)
132
const complex fvalue = fvalues[i];
133
y(2*i) = fvalue.real();
134
y(2*i + 1) = fvalue.imag();
137
//-----------------------------------------------------------------------------
138
void ComplexODE::M(const uBlasVector& x, uBlasVector& y,
139
const uBlasVector& u, real t)
141
// Update zvalues and fvalues for all components
142
for (uint i = 0; i < n; i++)
144
const complex zvalue(u(2*i), u(2*i + 1));
145
const complex xvalue(x(2*i), x(2*i + 1));
147
fvalues[i] = xvalue; // Use fvalues for x
150
// Use additional array for y, initialize the first time
153
yvalues = new complex[n];
154
for (uint i = 0; i < n; i++)
158
// Call user-supplied function M(x, y, z, t)
159
M(fvalues, yvalues, zvalues, t);
162
for (uint i = 0; i < n; i++)
164
const complex yvalue = yvalues[i];
165
y(2*i) = yvalue.real();
166
y(2*i + 1) = yvalue.imag();
169
//-----------------------------------------------------------------------------
170
void ComplexODE::J(const uBlasVector& x, uBlasVector& y,
171
const uBlasVector& u, real t)
173
// Update zvalues and fvalues for all components
174
for (uint i = 0; i < n; i++)
176
const complex zvalue(u(2*i), u(2*i + 1));
177
const complex xvalue(x(2*i), x(2*i + 1));
179
fvalues[i] = xvalue; // Use fvalues for x
182
// Use additional array for y, initialize the first time
185
yvalues = new complex[n];
186
for (uint i = 0; i < n; i++)
190
// Call user-supplied function J(x, y, z, t)
191
J(fvalues, yvalues, zvalues, t);
194
for (uint i = 0; i < n; i++)
196
const complex yvalue = yvalues[i];
197
y(2*i) = yvalue.real();
198
y(2*i + 1) = yvalue.imag();
201
//-----------------------------------------------------------------------------
202
real ComplexODE::timestep(uint i)
204
// Translate time step
207
//-----------------------------------------------------------------------------
208
bool ComplexODE::update(const uBlasVector& u, real t, bool end)
210
// Update zvalues for all components
211
for (uint i = 0; i < n; i++)
213
const complex zvalue(u(2*i), u(2*i + 1));
217
// Call user-supplied function update(z, t)
218
return update(zvalues, t, end);
220
//-----------------------------------------------------------------------------