function M = perform_vf_integration(vf, dt,T_list, options )
% perform_vf_integration - perform a time integration of the vf
%
% M = perform_vf_integration(vf, dt, T_list, options );
%
% If you set options.posx or options.posy, then
% M(i,j,:,t)) is the (X,Y) location of the point (options.posx(i),options.posy(j))
% at timestep T_list(t).
% If you set options.pos, then M(i,:,t) is the location of the point
% options.pos(:,i).
%
% The vf is assumed to be sampled at locations [1,...,n]^2 unless posx and posy are given.
%
% The integrator is a simple explicit euler, but it is very
% fast thanks to vectorization.
%
% Copyright (c) 2005 Gabriel Peyre
n = size(vf,1);
p = size(vf,2);
m = length(T_list);
options.null = 0;
bound = getoptions(options, 'bound', 'sym');
verb = getoptions(options, 'verb', 0);
if isfield(options, 'pos')
pos = options.pos;
posx = [];
else
posx = getoptions(options, 'posx', 1:n);
posy = getoptions(options, 'posy', 1:p);
[Y,X] = meshgrid(posy,posx);
pos = cat(1,X(:)',Y(:)');
end
% number of points
q = size(pos,2);
% M = zeros( length(posx),length(posy),m);
M = zeros(q,2,m);
T_list = [0; sort(T_list(:))];
for i=1:m
if verb
progressbar(i,m);
end
% compute the number of time steps
delta = T_list(i+1)-T_list(i);
nt = ceil(delta/dt);
if nt>0
DT = delta / nt;
% perform each time step
for k=1:nt
dx = interp2(1:p,1:n,vf(:,:,1), pos(2,:),pos(1,:) );
dy = interp2(1:p,1:n,vf(:,:,2), pos(2,:),pos(1,:) );
pos = pos + DT*cat(1,dx,dy);
% X = X + DT*dx; Y = Y + DT*dy;
switch bound
case 'sym'
pos(1,:) = clamp( pos(1,:), 1,n );
pos(2,:) = clamp( pos(2,:), 1,p );
case 'per'
pos(1,:) = mod(pos(1,:)-1,n-1)+1;
pos(2,:) = mod(pos(2,:)-1,p-1)+1;
otherwise
error('Unknown options.bound.');
end
end
end
% record value
M(:,:,i) = pos'; % X + 1i * Y;
% check for early break if nothing is moving anymore
if i>1
d = M(:,:,i) - M(:,:,i-1);
d = mean( sqrt(sum(d.^2,2)) );
if d<1e-6
progressbar(m,m);
break;
end
end
end
M = M(:,:,1:i);
if not(isempty(posx))
M = reshape(M, [length(posx) length(posy) 2 m]);
end