function U = burgers_im(X,T,At,nTimeSteps,u0,uxa,uxb,E)
%
% U = burgers_im(X,T,At,nTimeSteps,u0,uxa,uxb,E)
% Solution of modified Burgers' equation u_t + u?u_xx = E?u_xx
% on (a,b) with Dirichlet boundary conditions on both endpoints,
% using finite differences and an implicit method.
% The non-linear system is solved using Picard's method. 
%
% m:        number of subintervals used in the discretization
% At:       time step
% nTimeSteps:    number of time steps
% u0:       initial conditions (it can be a constant value or a (m+1)-dimensional vector)
% uxa, uxb: essential boundary conditions (they can be a constant value or
%           a (nTimeSteps+1)-dimensional vector corresponding to the conditions at each time step)

m = length(X)-1; 

% Allocate memory for the solution matrix
U = zeros(m+1,nTimeSteps+1);

% Initial condition
U(:,1) = u0;

% Boundary conditions
U(1,:) = uxa';
U(m+1,:) = uxb';

M = computeMassMatrix(X,T); 
K = computeDiffussionMatrix(X,T); 

Accd = zeros(2,m+1); Accd(1,1) = 1; Accd(2,m+1) = 1;  
for n = 1:nTimeSteps
    %fprintf('\nTime step %d\n', n); 
    bccd = [uxa; uxb]; 
    U0 = U(:,n); 
    error_U = 1; k = 0; 
    while (error_U > 0.5e-5) && k < 20
        C = computeConvectionMatrix(X,T,U0); 
        A = M + At*C + At*E*K;
        A_T = [A,Accd'; Accd,zeros(size(Accd,1))]; 
        f = M*U(:,n); 
        f_T = [f;bccd]; 
        sol = A_T\f_T; 
        U1 = sol(1:m+1); 
        error_U = norm(U1-U0)/norm(U1); 
        %fprintf('\t Iteration %d, error_U=%e\n',k,error_U); 
        U0 = U1; k = k+1; 
    end
    U(:,n+1) = U1;  
end

