convolution integral with ode45

203 visualizzazioni (ultimi 30 giorni)
Angie
Angie il 8 Giu 2019
Commentato: Paul circa 2 ore fa
Hi guys, can someone help me solve this equation of motion using ode45 or any other way? I dont know how to approach the convolution integral. Thank you!

Risposta accettata

Star Strider
Star Strider il 8 Giu 2019
Try this:
odefcn = @(t,y,c,F,k,m,w) [y(2); -(k.*y(1) - F.*cos(t.*w) + integral(@(tau)c(t - tau).*y(2).*tau, 0, t))./m];
c = @(t) exp(-t.^2); % Make Something Up
[F,k,m,w] = deal(rand,rand,rand,rand); % Replace With Correct Values
tspan = [0 10];
ics = [1; 1];
[t,y] = ode45(@(t,y)odefcn(t,y,c,F,k,m,w), tspan, ics);
figure
plot(t, y)
hl = legend('$u(t)$', '$\dot{u}(t)$');
set(hl,'Interpreter','latex')
Noite that ‘c’ actually has to be defined as a function in order for this to work. Supply the correct one.
I derived it with the help of the Symbolic Math Toolbox.
  8 Commenti
JINGYU KANG
JINGYU KANG il 12 Set 2023
Star Strider's answer solves the different differential equation. That is,
where the desired equation to solve is as below
One can verify that by letting c(t) = 1 with k = 0, F = 0 for simplicity
David Goodmanson
David Goodmanson il 11 Dic 2025 alle 1:16
Modificato: David Goodmanson il 11 Dic 2025 alle 7:35
Whether you include a factor of tau or not, I believe both of these solutions are incorrect, and every solution along these lines will be incorrect. The term is
Int{0,t} c(t-tau) u'(tau) dtau % u' instead of udot
i.e. a convolution that depends on the past history of u' from 0 to t. Replacing u'(tau) with u'(t) says that u' is a constant factor in the integrand (which it isn't). This gives
Int{0,t)} c(t-tau) u'(t) dtau = u'(t) Int{0,t)} c(t-tau) dtau.
If you attemp to fix this up by inserting tau or any function f(tau) inside the integral, and then do the integration you get
u'(t) Int{0,t} c(t-tau) f(tau) dtau = u'(t) g(t)
for some function g, which is a pointlike expression that does not involve past history of u' at all.
I have never unaccepted someone else's answer but would encourage Star Strider to take a hard look at that answer.

Accedi per commentare.

Più risposte (4)

Paul
Paul il 7 Dic 2025 alle 3:05
Modificato: Paul il 11 Dic 2025 alle 2:18
If c(t) has a Laplace transform then we can take advantage of the convolution property and convert to the s-domain, solve for U(s), and then convert back to the t-domain. For simple c(t) we can actually get a closed form expression for u(t), though a numerical or vpa solution is more likely going to be needed.
Define the differential equation
syms m k F omega t tau real
syms u(t) c(t)
du(t) = diff(u(t),t);
z(t) = int(c(t-tau)*diff(u(tau),tau),tau,0,t);
eqn = m*diff(u(t),t,2) + z(t) + k*u(t) == F*cos(omega*t)
eqn = 
Take the Laplace transform
Leqn = laplace(eqn)
Leqn = 
Sub in U(s) and C(s)
syms U(s) C(s)
Leqn = subs(Leqn,laplace([u(t),c(t)],t,s),[U(s),C(s)])
Leqn = 
Solve for U(s)
Leqn = isolate(Leqn,U(s))
Leqn = 
At this point we need the expresion for C(s). Assume a simple form of c(t) and sub C(s) into the expression for U(s)
c(t) = exp(-t);
Leqn = subs(Leqn,C,laplace(c(t),t,s))
Leqn = 
Simplify the expression for U(s)
[num,den] = numden(rhs(Leqn));
Leqn = lhs(Leqn) == num/den
Leqn = 
Choose some arbitrary parameters for illustration and sub in
mval = 1; kval = 2; Fval = 3; omegaval = 4;
Leqn = subs(Leqn,[m,k,F,omega,u(0),du(0)],[mval,kval,Fval,omegaval,5,6])
Leqn = 
If we only want a numerical evaluation of the solution, we can just use impulse
figure
[num,den] = numden(rhs(Leqn));
impulse(tf(double(coeffs(num,'all')),double(coeffs(den,'all'))),0:.01:20);grid
Get the solution for u(t)
u(t) = ilaplace(rhs(Leqn),s,t)
u(t) = 
u(t) = rewrite(rewrite(u(t),'expandsum'),'expandroot');
The solution includes some terms in i = sqrt(-1), but we know the solution has to be real. It proved too difficult to simplify u(t) into an expression with only real terms.
Derivative of u(t)
du(t) = diff(u(t),t);
Plot the real and imaginary parts of u(t) to verify the latter is zero, and plot the derivative of u(t)
figure;
fplot([real(u(t)),imag(u(t)),real(du(t))],[0,20]);grid
legend('u(t)','imag(u(t))','du(t)');
Note that u(0) and du(0) satisfy the initial conditions assumed above.
Now verify the solution satisfies the differential equation.
z(t) actually has a closed form expression
z(t) = int(c(t-tau)*du(tau),tau,0,t)
z(t) = 
Subtract the rhs of the differential equation from the lhs and sub in the parameters
check = subs(lhs(eqn) - rhs(eqn),[m,k,F,omega],[mval,kval,Fval,omegaval]);
Sub in the expressions for u(t) and c(t), note we could just set u(t) = real(u(t)) and z(t) = real(z(t)).
check = subs(check);
Check the result at some points in time, the answer should be zero
vpa(subs(check,t,0:10)).'
ans = 
  8 Commenti
Paul
Paul il 15 Dic 2025 alle 14:55
I had been thinking about this approach but wanted to avoid having to define the vector of output times a-priori. I'd rather let the solver figure it out (in general, but there could be exceptions). Of course, the approach I illustrated has the same concern if the user wants to specify a full tspan vector. In that case, maybe better to use 2-element tspan and the structure output from ode45 with subesquent calls to deval, but I didn't check into that option.
In the numerical solutions posted in this thread, the convolution in the derivative function assumes linear interpolation of something. Do you think that more accuracy could be obtained by storing the history of u(t), its derivatives, and any other information and somehow using all of that to get better estimates of udot(t) between the stored points for the convolution operation?
Torsten
Torsten il 15 Dic 2025 alle 15:12
Modificato: Torsten il 15 Dic 2025 alle 16:48
Do you think that more accuracy could be obtained by storing the history of u(t), its derivatives, and any other information and somehow using all of that to get better estimates of udot(t) between the stored points for the convolution operation?
"trapz" on an equidistant grid has integration order 2.
Maybe "interp1" with the "spline" option if you want to use "integral" for the convolution integral ?
And of course the absolute and relative tolerances for ode45 will influence the number of output points, thus the size of the history vector and thus the accuracy of the convolution integral.

Accedi per commentare.


David Goodmanson
David Goodmanson il 13 Dic 2025 alle 10:37
Modificato: David Goodmanson il 16 Dic 2025 alle 9:19
******************** MODIFIED ******(**************
because the method suggested here does not work. I took out some useless text but left the basic idea as an example of what not to do.
Hi Paul, Torsten et. al.
The code below saves the history of udot in ode45 and then does the convolution. I used delt = 1e-2 as Matt did and the plot is pretty similar. Taking delt down to 1e-4 does not change things very much.
A more accurate method might be available and I will add it to this answer if it works.
m = 1;
k = 2;
F = 3;
wF = 4;
a = 1; % c = exp(-a*t)
delt = 1e-2; % step size for the convolution integration
tspan = [0 20];
icond = [5;6];
[t u] = ode45(@(t,u) fun(t,u,m,k,a,delt,F,wF,tspan,icond), tspan, icond);
figure(3); grid on
plot(t,u)
function udot = fun(t,u,m,k,a,delt,F,wF,tspan,icond)
persistent udotstore
persistent tstore
if t == tspan(1)
udotstore = icond(2);
tstore = tspan(1);
G = 0;
else
udotstore = [udotstore u(2)];
tstore = [tstore t];
% sort the times, toss out near-duplcate times
[t1 ind] = sort(tstore);
udot1 = udotstore(ind);
fin = find(diff(t1)<1e-7); % judgment call here
t1(fin) = [];
udot1(fin) = [];
% set up equally spaced time array, do the convolution G
t2 = t1(1):delt:t1(end);
udot2 = interp1(t1,udot1,t2);
c = exp(-a*t2);
G = trapz(t2,flip(c).*(udot2));
end
udot = [0 1; (-k/m) 0]*u -(G/m)*[0;1] + (F/m)*cos(wF*t)*[0;1];
end
  5 Commenti
Paul
Paul il 13 Dic 2025 alle 22:17
Modificato: Paul il 13 Dic 2025 alle 22:46
I didn't see this comment before I prepared and submitted mine. I see that we both have the same fundamental concern (I think).
I did not think of using an OutputFcn.
I think the derivative function can include additional arguments, which won't be used by the ode solver, but can be used in a call from the OutputFcn to pass data from the OutputFcn to the derivative function for the derivative function to store persistently. Don't see why that wouldn't work.
Or the state data could be stored persistently in the OutputFcn and it could be called from the derivative function with an optional second argument and specific value of flag or a fourth argument to return the stored state data. I think that should work too.
David Goodmanson
David Goodmanson il 16 Dic 2025 alle 9:11
I see that persistent is not going to work. Thanks to Torsten and especially Paul for taking the time to point out the flaws in that idea.
Going back somewhere on this thread I mentioned Matt in conndection with delta t = .01 but I meant to say Torsten.

Accedi per commentare.


Sam Chak
Sam Chak il 15 Dic 2025 alle 18:56
In the past few days, I have been closely following the discussions on this intriguing topic of solving the integro-differential equation that involves a convolution integral term using the ode45 solver. It seems challenging to define the time-shifted dummy variable τ, which serves as a temporary placeholder for integration in the ODE function, as pointed out by @Star Strider.
I commend everyone for their contributions, including @JINGYU KANG, who revived this unsolved problem, and @David Goodmanson, who initially implemented storing the historical solutions from ode45 needed to perform the convolution. I would also like to especially recognize @Paul for developing solutions using the Laplace transform method, the fixed-step RK4 method, and the OutputFcn method (under @Torsten's insightful suggestion).
Here is my take: I initially wondered if the product of functions in the convolution integral term could be decomposed using integration by parts, a common mathematical technique that we all learned in high school calculus.
The idea eventually evolved into a mathematical technique inspired by integration by substitution.
Methodology:
The mass-spring-damper system is given by:
where is the convolution integral term.
If the damping function, is differentiable or Laplace transformable, we can introduce an auxiliary variable y to define that
Next, applying Leibniz integral rule for differentiating , we obtain
where the kernel function is
.
Evaluating the two terms:
and
.
Since
it can be rewritten simply as a coupled ODE:
.
Essentially, the integro-differential equation is converted into a coupled ODE system, allowing the ode45 solver to adaptively solve the system.
% Parameters
m = 1; % mass
k = 2; % stiffness
F = 3; % amplitude of the sinusoidal Force
w = 4; % natural angular frequency
% Call ode45 solver
tspan = [0, 20]; % simulation time
icond = [5 % u(0) = 5
6 % u'(0) = 6
0]; % y(0) = 0
[tu, u] = ode45(@(t, u) odefcn(t, u, m, k, F, w), tspan, icond);
% Compare with impulse response
[v, tv] = impulse(tf([5, 11, 94, 179, 176], conv([1, 0, 16], [1, 1, 3, 2])), tspan(2));
% Plot results
figure
hold on
plot(tu, u(:,1), '.')
plot(tv, v)
hold off
grid on
xlabel('Time')
ylabel('Amplitude')
legend('Adaptive ode45', 'Impulse response')
%% Transform the integro-differential equation into a coupled ODE system
function du = odefcn(t, u, m, k, F, w)
du = zeros(3, 1);
du(1) = u(2);
du(2) = 1/m*(F*cos(w*t) - k*u(1) - u(3)); % convolution integral is substituted by u(3) = y
du(3) = u(2) - u(3); % dy/dt = du/dt - y, after applying Leibniz rule
end
  2 Commenti
Torsten
Torsten il 15 Dic 2025 alle 20:05
Modificato: Torsten il 15 Dic 2025 alle 20:17
Very nice solution.
What a luck that
d/dt (c(t-tau)) = -c(t-tau)
in this specific case :-)
Can you think of a similar approach for a general convolution integral
int_{tau = 0}^{tau = t} c(t-tau) * u(tau) d(tau)
with an arbitrary function c ?
Sam Chak
Sam Chak circa 2 ore fa
This high-school integration technique clearly does not work for arbitrary functions. If this technique cannot be applied, then the convolution must be evaluated numerically while integrating the ODE function, as demonstrated by @Paul using the OutputFcn method. In theory, this should be analogous to solving a Volterra integral equation. Are there any examples available in the MathWorks Help Center or official documentation?

Accedi per commentare.


David Goodmanson
David Goodmanson il 16 Dic 2025 alle 9:04
Modificato: David Goodmanson circa 17 ore fa
This is a very interesting problem! Convolution of the loss term for the harmonic oscillator. I had been working on some extensions of the same approach that Sam posted so I will post these. If
c = b e^(-at)
G = Int{0,t} b e^(-a(t-tau)) u'(tau) dtau
then
(d/dt + a) G(t) = b u'(t)
and the system consists of that result combined with
mu'' + G + ku = F cos(wt)
Let
y = [u u' G]' % two different uses of '
The odefun is
ydot = [ 0 1 0
-k/m 0 -1/m
0 b -a ] y + (F/m) cos(wt) [0 1 0]'
with initial condition G(0) = 0, all of which was covered by Sam. An advantage of this method is that as well as u and u' you get the convolution integral as a function of time.
In everything below, the initial condition for every G is zero.
Some generalizations of c are possible. These are sums of functions of the form
% b t^n e^(-at)
which include e.g.
% b1 e^(-a1 t) + b2 e^(-a2 t) + b3 e^(-a3 t) .... sum of exponentials b)
% ( ... b3 t^3 + b2 t^2 + b1 t + b0 ) e^(-a t) polymomials a)
and mixtures of those. If additional easily calculated c functions don't come around, then one task would be to fit an arbitrary c function to sums of these functions There are more possibilites for success there than it might seem. For example in addition to [ t e^(-at) ], the function [ e^(-a1 t) - e^(-a2 t) ] also equals 0 at the origin and has one peak.
a) For polynomials you can define the convolutions
G_n = Int{0,t} b (t-tau)^n e^(-a(t-tau)) u'(tau) dtau
in which case
(d/dt + a) G_n) = n G_(n-1)
(d/dt + a) G_0) = b u' % as before
For a fourth degree polynomial with
y = [u u' G4 G3 G2 G1 G0]'
then after a straightforward process the odefun looks like
ydot= [ 0 1 0 0 0 0 0
-k/m 0 -1/m 0 0 0 0
0 b4 -a 1 0 0 0
0 b3 0 -a 1 0 0
0 2b2 0 0 -a 1 0
0 6b1 0 0 0 -a 1
0 24b0 0 0 0 0 -a] y + (F/m) cos(wt) [0 1 0 0 0 0 0]'
A better loooking result is obtained by rescaling the G's with
Gnew_n = Gold_n / (4-n)!
in which case
ydot= [ 0 1 0 0 0 0 0
-k/m 0 -1/m 0 0 0 0
0 b4 -a 1 0 0 0
0 b3 0 -a 2 0 0
0 b2 0 0 -a 3 0
0 b1 0 0 0 -a 4
0 b0 0 0 0 0 -a] y + (F/m) cos(wt) [0 1 0 0 0 0 0]'
b) An easier process is the sums of terms of the same type. For e.g. three exponentials the odefun is
ydot = [ 0 1 0 0 0
-k/m 0 -1/m -1/m -1/m
0 b1 -a1 0 0 ]
0 b2 0 -a2 0 ]
0 b3 0 0 -a3 ] y + (F/m) cos(wt) [0 1 0 0 0]'
  2 Commenti
Paul
Paul circa 16 ore fa
Modificato: Paul circa 13 ore fa
Hi David,
In case there's any interest, Matlab can help with the differentiation of the convolution as shown by you and @Sam Chak
syms t tau real
syms n integer
syms u(t) c(t) G(t,n)
du(t) = diff(u(t),t);
eqn1 = G(t,n) == int(c(t-tau)*du(tau),tau,0,t)
eqn1 = 
eqn2 = diff(eqn1,t)
eqn2 = 
syms a b
c(t) = t^n*b*exp(-a*t);
eqn3 = subs(eqn2)
eqn3 = 
eqn4 = lhs(eqn3) == expand(rhs(eqn3))
eqn4 = 
The first term on the RHS is -a*G(t,n), the second terms is n*G(t,n-1). We could do a little more work to get the software to express the RHS explicitly in terms of G(t,n) and G(t,n-1). Note that the third term is 0 unless n == 0, in which case (with Matlab convention that 0^0 = 1)
eqn5 = subs(eqn4,n,0)
eqn5 = 
eqn4 and eqn5 are what you derived in the middle of your post.
This statement "then one task would be to fit an arbitrary c function to sums of these functions" got me thinking. I have no idea what types of c(t) functions are of interest for these types of problems. In my example, I chose c(t) = exp(-t) just for simplicity. Now we have your type (a) and (b) functions and, as you say, mixtures of those. I'm not familiar with curve fitting with exponentials and so don't know what the possibilities are there. But some other functions might be of interest.
a) If c(t) is sinusoidal (or sums thereof), then it can expressed as a sum of complex sinusoids, which gets us back to your type (b). I've never tried use an ode solver for a system with complex coefficients; is there any reason to think it wouldn't work (doing appropriate things to maintain a real solution)?
b) If c(t) is periodic, then we can expand it in a complex exponential Fourier series. Hopefully, we can truncate to a finite number of terms in the series to maintain a good approximation to c(t), and we're back to type (b).
I have no idea if any these types of c functions are applicable to these types of problems, nor if the proposed solutions can work, but I found the thought experiment interesting.
Paul
Paul circa 2 ore fa
I ran an example with c(t) = 1 + cos(t) and it worked just fine after expanding cos(t) into its complex exponential form.

Accedi per commentare.

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by