function U = parabolic_cn(a,b,m,At,npast,f0,g0,h0)
% Solves with the Crank-Nicolson method the parabolic pde u_t = u_xx 
% with x in (a,b), and Dirichlet boundary conditions.
%
% U = parabolic_cn(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('Crank-Nicolson method');
disp(strcat('---> r = ',num2str(r))); 
disp(' ')

% Definition of matrix A and decomposition: TO BE CODED
A = zeros(m+1,m+1);
for i=1:m+1
    for j=1:m+1
        if i==j
            A(i,j) = 1+r;
        elseif abs(i-j)==1
            A(i,j) = -r/2;
        end
    end
end

% initial and boundary conditions en the solution matrix
%(each time step is stored in a column): TO BE CODED 
U =  zeros(m+1,npast+2);
U(:,1) = f';
% Initialize F matrix with Boundary Conditions
F=zeros(m+1,1);
if length(g0)==1
    F(1,1) = r*g0;
end
if length(h0)==1
    F(end,1) = r*h0;
end
% Initialize B matrix
B = zeros(m+1,m+1);
for i=1:m+1
    for j=1:m+1
        if i==j
            B(i,j) = 1-r;
        elseif abs(i-j)==1
            B(i,j) = r/2;
        end
    end
end

% Loop in time steps: TO BE CODED
for i=2:npast+1
    if length(g0)~=1
        F(1,1) = (r/2)*(g0(1,i)+g0(1,i-1));
    end
    if length(h0)~=1
        F(end,1) = (r/2)*(h0(1,i)+h0(1,i-1));
    end
     b = B*U(:,i-1)+F;
     [U(:,i), err]=Gaussian_Elimination(A,b);
end

U=U(:,2:end);
