You are on page 1of 9

function [K q T_cal]=oneD_FEM(no_of_elements, no_of_nodes_per_element, inte)

%Function to find global K matrix, q matrix, and temperature distribution.


%input: total no of elements, no of nodes per element i.e. linear,
%qudratic, cubic ....... and inti=1 for Newton_cotes_quadrature and inti=2
%for Gauss_legendre_quadrature.
%output: Global K,q matrix and Temperature distibution.

%Given Parameters
T_0=30+273;
T_1=100+273;
L=1;

%These variable(x_e, x_(e+1)) can be changed for each element globally.


global x_e x_e_1 n
n=no_of_nodes_per_element;

%initialing elemental matrices.


k_e_i=zeros(n,n);
q_e_i=zeros(n,1);

%Defining a vector to add up elemental matrices to get global matrix.


vec=zeros(1,no_of_nodes_per_element);

%Length of an element in global coordinates.


length_of_element=L/no_of_elements;

%Total no of nodes
no_of_nodes=no_of_elements*no_of_nodes_per_element-(no_of_elements-1);

%Initializing global matrices.


k_global=zeros(no_of_nodes,no_of_nodes);
q_global=zeros(no_of_nodes,1);

%initializing vector for 1st element.


for i=1:no_of_nodes_per_element
vec(i)=i;
end

%Loop to calculate global K matrix.


for i=1:no_of_elements

%Global coordinates of x_e and x_(e+1)


x_e=(i-1)*length_of_element;
x_e_1=x_e+length_of_element;

%Integration using N-C-Q to get elemental matrices.


if inte==1
k_e_i=Newton_cotes_quadrature(@elemental_matrix_K,n);
q_e_i=Newton_cotes_quadrature(@elemental_matrix_q,n);
end

%Inegration using G-L-Q to get elemental matrices.


if inte==2
k_e_i=Gauss_legendre_quadrature(@elemental_matrix_K,n);
q_e_i=Gauss_legendre_quadrature(@elemental_matrix_q,n);
end

%To calculate Global matrix by summing up element matrices every time


%we calculate them, instead of caculating all elemental matrices first
%and then adding them.
k_global(vec,vec)=k_global(vec,vec)+k_e_i;
q_global(vec)=q_global(vec)+q_e_i;

if i~=no_of_elements
vec=vec+no_of_nodes_per_element-1;
end
end

%Storing Global Matrices to K and q


K=k_global;
q=q_global;

%Use this loop to solve for Temperature.


%This method modify the K and f matrix such that f_1=T_0 and f_2=T_1.
for i=1:no_of_nodes_per_element
q_global(i,1)=q_global(i,1)-k_global(i,1)*T_0;
q_global(no_of_nodes-(i-1),1)=q_global(no_of_nodes-(i-1),1)-
k_global(no_of_nodes-(i-1),no_of_nodes)*T_1;
k_global(1,i)=0;
k_global(i,1)=0;
k_global(no_of_nodes-(i-1),no_of_nodes)=0;
k_global(no_of_nodes,no_of_nodes-(i-1))=0;
end
k_global(1,1)=1;
k_global(no_of_nodes,no_of_nodes)=1;
q_global(1)=T_0;
q_global(no_of_nodes)=T_1;

%Final Calculation for Temperature Distibution.


%We may also use some modify method to solve for a banded matrix.
T_cal=k_global\q_global;
function integral=Gauss_legendre_quadrature(fun,n)
%This function calculates integral using Newton-Cotes formula.
%input: fun=function to integrate, n=no of base points
%output: integral of the given function from -1 to 1

%Weight coefficients for the Gauss_legendre_quadrature Ref:J.N. Reddy


%Given formulation used to enter different weights and corresponding gauss
%points for the given values of n and i. For example gauss point xeta_i at
%i_th node for n base points is xeta(x) where x=n*(n-1)/2+1. This method
%saves the computational space by creating n*1 matrix instead of n*n.
xeta(1)=0;
xeta(2)=-0.5773502692;
xeta(3)=0.5773502692;
xeta(4)=-0.7745966692;
xeta(5)=0;
xeta(6)=0.7745966692;
xeta(7)=-0.8611363116;
xeta(8)=-0.3399810435;
xeta(9)=0.3399810435;
xeta(10)=0.8611363116;

%weight coefficients using same method.


w(1)=2;
w(2)=1;
w(3)=1;
w(5)=0.8888888889;
w(4)=0.5555555555;
w(6)=0.5555555555;
w(7)=0.3478548451;
w(8)=0.6521451548;
w(9)=0.6521451548;
w(10)=0.3478548451;

%To integrate a function using n base points, we may use a gauss palynomial
%of greatest_integer((n+1)/2).
degree=round((n+1)/2);

%integral=summation(w(i)*f(xeta(i)), where i->1,degree_of_gauss_poly


integral=0;
for i=1:degree
x=degree*(degree-1)/2+i;
integral=w(degree*(degree-1)/2+i)*fun(xeta(x))+integral;
end
function [psi d_psi]=shape_function_n(n,xeta)
%Used to calculate shape function at a given point for n base points.
%input: n=no of base points, xeta: point at which shape function is needed.
%output: psi:shape function at xeta, d_psi:differential of shape function
%with respect to xeta at xeta='xeta'

%intializing vector c, where shape_function


%psi_i=c_i*(xeta-xeta_1)*(xeta-xeta_2)...(xeta-xeta_(i-1))*(xeta-xeta_(i+1)
%)......
c=zeros(n);

%We shall use central difference to calculate D(phi)/D(xeta) i.e.


%D(phi)/D(xeta)=(phi(xeta+h)-phi(xeta-h))/2h
h=10^-4/n;

%loop to calculate phi_i and D(phi_i)/D(xeta)


for i=1:n
%for n base points xeta_i=-1+2*(i-1)/(n-1) where xeta->-1 to 1
xeta_i=-1+2*(i-1)/(n-1);

%value initialization to calculate product c_i*(xeta-xeta_j)|j->1 to n


%and i!=j
c=1;
xeta_product=1;
xeta_product_i_p_h=1;
xeta_product_i_m_h=1;

%loop to calculate (xeta-xeta_j), i!=j at xeta='xeta' and


%xeta='xeta+h','xeta-h', to calculate D(psi_i)/D(xeta)
for j=1:n
xeta_j=-1+2*(j-1)/(n-1);
if(i~=j)
c=(xeta_i-xeta_j)^-1*c;
xeta_product=(xeta-xeta_j)*xeta_product;
xeta_product_i_p_h=((xeta+h)-xeta_j)*xeta_product_i_p_h;
xeta_product_i_m_h=((xeta-h)-xeta_j)*xeta_product_i_m_h;
end
end

%Multiplying the above product with c_i to calculate psi_i and


%D(psi_i)/D(xeta)
psi(i)=c*xeta_product;
psi_p_h=c*xeta_product_i_p_h;
psi_m_h=c*xeta_product_i_m_h ;
d_psi(i)=(psi_p_h-psi_m_h)/(2*h);
end

function integral=Newton_cotes_quadrature(fun,n)
%This function calculates integral using Newton-Cotes formula.
%input: fun=function to integrate, n=no of base points
%output: integral of the given function from -1 to 1

%Weighting coefficients for the Newton-Cotes formula Ref:J.N. Reddy


%Given formulation used to enter different weights and corresponding newton
%points for the given values of n and i. For example newton point xeta_i at
%i_th node for degree 'degree' is xeta_degree(i) where x=degree*(degree-1)
%/2+i-1. This method saves the computational space by creating n*1 matrix
%instead of n*n.

w(1)=1/2;
w(2)=1/2;
w(3)=1/6;
w(4)=4/6;
w(5)=1/6;
w(6)=1/8;
w(7)=3/8;
w(8)=3/8;
w(9)=1/8;

%Degree of newton polynomial is n, where n=no of base points


degree=n;
integral=0;

%integral=summation(w(i)*f(x_i), where i->1,degree_of_newton_poly+1


for i=1:degree+1
x=-1+(2/(degree))*(i-1);
integral=2*w(degree*(degree+1)/2+i-1)*fun(x)+integral;
end
L=1;
%input
no_of_elements1(1)=10;
no_of_nodes_per_element1(1)=2;
no_of_elements1(2)=5;
no_of_nodes_per_element1(2)=3;
no_of_elements1(3)=4;
no_of_nodes_per_element1(3)=4;
%which method of integration to use init=1 for newton, init=2 for gauss.
inte=2;
%Uncomment the following to get temperature variation for 10 qudratic
%elements

%\\
no_of_elements=no_of_elements1(2);
no_of_nodes_per_element=no_of_nodes_per_element1(2);
%total no of nodes
no_of_nodes=no_of_elements*no_of_nodes_per_element-(no_of_elements-1);
%length of an element
length_of_element=L/no_of_elements;

m=no_of_nodes;

%intialing parameters so that they won't change size after every


iteration
x=zeros(1,no_of_nodes);

%Global coordinates of each node


for i=1:no_of_nodes
x(i)=0+L/(m-1)*(i-1);
end

%Analytical solution
T_theo=-x/20+2021.2157/20*log(1+x)+303;
T_theo_max=max(T_theo);

%Numerical solution
[K q T_cal]=oneD_FEM(no_of_elements, no_of_nodes_per_element, inte);
%//

%Uncomment the following to find Temp variation for 11 nodes.

%\\
% for j=1:3
% clear K q T_cal T_theo x
% no_of_elements=no_of_elements1(j);
% no_of_nodes_per_element=no_of_nodes_per_element1(j);
% %total no of nodes
% no_of_nodes=no_of_elements*no_of_nodes_per_element-(no_of_elements-1);
% %length of an element
% length_of_element=L/no_of_elements;

% m=no_of_nodes;
%
% %intialing parameters so that they won't change size after every
iteration
% x=zeros(1,no_of_nodes);
%
% %Global coordinates of each node
% for i=1:no_of_nodes
% x(i)=0+L/(m-1)*(i-1);
% end
%
% %Analytical solution
% T_theo=-x/20+2021.2157/20*log(1+x)+303;
% T_theo_max=max(T_theo);
%
% %Numerical solution
% [K q T_cal]=oneD_FEM(no_of_elements, no_of_nodes_per_element, inte);
%
% %plotting parameters
% %T_plot_cal(j,:)=T_cal;
% error(j)=100*(1/(sqrt(m)*abs(T_theo_max))).*sqrt((T_theo.'-
T_cal).'*(T_theo.'-T_cal));
%
% end
%//

%Uncomment the following to get graph of cpu_time vs no of elements

%\\
% for j=1:6
% initialtime=cputime;
% clear K q T_cal T_theo x
% no_of_elements=3^j;
% no_of_nodes_per_element=3;
% %total no of nodes
% no_of_nodes=no_of_elements*no_of_nodes_per_element-(no_of_elements-1);
% m=no_of_nodes;
%
% %intialing parameters so that they won't change size after every
iteration
% x=zeros(1,no_of_nodes);
%
% %Global coordinates of each node
% for i=1:no_of_nodes
% x(i)=0+L/(m-1)*(i-1);
% end
%
% %Analytical solution
% T_theo=-x/20+2021.2157/20*log(1+x)+303;
% T_theo_max=max(T_theo);
%
% %Numerical solution
% [K q T_cal]=oneD_FEM(no_of_elements, no_of_nodes_per_element, inte);
%
% %plotting parameters
% %T_plot_cal(j,:)=T_cal;
% error(j)=100*(1/(sqrt(m)*abs(T_theo_max))).*sqrt((T_theo.'-
T_cal).'*(T_theo.'-T_cal));
% finaltime(j)=cputime-initialtime;
%
% end
%
% for i=1:6
% n(i)=3^i;
% end
% %plotting graphs
% plot(n,finaltime);
% xlabel('no of qudaratic elements');
% ylabel('cpu_{time} (s)');
%//

%Uncomment to get temperature and temperature gradient at a point.


x=0.5;
x_0=0;
x_L=1;

%element no for that x


element_x=floor(x-x_0)/length_of_element+1

%end points for that element


x_e=(element_x-1)*length_of_element;
x_e_1=x_e+length_of_element;

Temp_x=0;

for i=1:3
xeta=-2+i;
strating_note_of_that_element=3*(element_x-1)-(element_x-2);
[psi d_psi]=shape_function_n(3,xeta);
T_cal(strating_note_of_that_element+i-1)
psi(strating_note_of_that_element+i-1)
Temp_x
Temp_x=T_cal(strating_note_of_that_element+i-
1)*psi(strating_note_of_that_element+i-1)+Temp_x;
end
function [jac x]=jacobia(x_e,x_e_1,r,xeta)
%Method to calculate jacobian.

[psi d_psi]=shape_function_n(r,xeta);
jac=0;
for i=1:r
x(i)=x_e+((i-1)/(r-1))*(x_e_1-x_e);
jac=jac+x(i)*d_psi(i);
end

You might also like