function U = parabolic_cn(a,b,m,At,npast,f0,g0,h0)
% Solves with the explicit method the parabolic pde u_t = u_xx 
% with x in (a,b), and Dirichlet boundary conditions.
%
% U = parabolic_ex(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 extreme.


% 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);
th = 1/2;
disp(' ');
disp('Crank-Nicholson method');
disp('No oscillations for r<=1/2')
disp(strcat('---> r = ',num2str(r))); 
disp(' ')

% Definition of matrix A and B
a = ones(1,m-1)*(1+2*r*th);
a1 = ones(1,m-2)*(-r*th);
A = diag(a)+diag(a1,-1)+diag(a1,1);
b = ones(1,m-1)*(1-2*r*(1-th));
b1 = ones(1,m-2)*(r*(1-th));
B = diag(b)+diag(b1,-1)+diag(b1,1);

% initial and boundary conditions en the solution matrix
U = zeros(length(f),length(g));
U(:,1) = f;
U(1,:) = g;
U(end,:) = h;

% Loop in time steps
for n = 1:npast
    UB = U(2:(end-1),n);
    F = zeros(size(UB));
    F(1) = r*th*U(1,n+1)+r*(1-th)*U(1,n);
    F(end) = r*th*U(end,n+1)+r*(1-th)*U(end,n);
    
    U(2:(end-1),n+1) = A\(B*UB+F);
end