function U = parabolic_im(a,b,m,At,npast,f0,g0,h0)
% Solves with the implicit method the parabolic pde u_t = u_xx 
% with x in (a,b), and Dirichlet boundary conditions.
%
% U = parabolic_im(a,b,m,At,npast,f0,g0,h0) generates a matrix which
% stores the solution in each time step in a column.
%
% m    : number of subintervals for the x discretization
% At   : length of the time steps
% npast: number of time steps
% f0   : initial conditions u(0,x)
%        it can be a constant value or a column vector with the m+1 initial
%        values
% g0,h0: boundary conditions u(t,a) and u(t,b)
%        they can be a constant value or a column vector with the npast+1 
%        values in each extrem.



% Check initial and boundary conditions
[n0 m0] = size(f0);
if((n0==1) && (m0==1)), f = f0*ones(1,m+1);
elseif((n0==1) && (m0==m+1)), f = f0;
else error('Error in the dimension of the initial conditions vector.')
end
[n0 m0] = size(g0);
if((n0==1) && (m0==1)), g = g0*ones(1,npast+1);
elseif((n0==1) && (m0==npast+1)), g = g0;
else error(strcat('Error in the boundary conditions in x=',num2str(a)))
end
[n0 m0] = size(h0);
if((n0==1) && (m0==1)), h = h0*ones(1,npast+1);
elseif((n0==1) && (m0==npast+1)), h = h0;
else error(strcat('Error in the boundary conditions in x=',num2str(b)))
end

%constants computing
Ax = (b-a)/m;
r = At/(Ax^2);
disp(' ');
disp('Implicit method');
disp(strcat('---> r = ',num2str(r))); 
disp(' ')

% Definition of matrix A and decomposition: TO BE CODED
zeta = 1;
da = (1 + 2*r*zeta) * ones(m-1,1);
A = diag(da,0);
da1 = -r*zeta * ones(m-2,1);
A = A + diag(da1,1) + diag(da1,-1 );

db = (1 - 2*r*(1-zeta)) * ones(m-1,1);
db1 = r * (1-zeta) * ones(m-2,1);
B = diag(db,0) + diag(db1,1) + diag(db1,-1);


% initial and boundary conditions en the solution matrix
%(each time step is stored in a column): TO BE CODED 
U = zeros(m+1,npast+1);
%Introduce f,g,h
U(:,1) = f;
U(1,:) = g;
U(end,:) = h;

% Loop in time steps: TO BE CODED
% for j = 1:npast-1
for j = 1:npast
    F = zeros(m-1,1);
    F(1) = r*zeta*U(1,j+1) + r*(1-zeta)*U(1,j);
    F(end) = r*zeta*U(end,j+1) + r*(1-zeta)*U(end,j);
%U(i,j+1) = r*U(i-1,j) + (1-2*r)*U(i,j) +r*U(i+1,j);
    U(2:m,j+1) = A\(B*U(2:m,j) + F);
end

