LisaPizzoExercises/Project/Main.m
2026-01-28 13:13:13 +01:00

303 lines
No EOL
8.7 KiB
Matlab
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

% Axisymmetric mug
% rz plane, rotation around r = 0
clear; clc; close all;
%% General values that we use in the entire script
%Task 3) Thermal conductivity
lambda_wall = 1.5; % ceramic
lambda_fluid = 0.6; % water
lambda_air = 0.026; % air
%Task 4) heat transfer coefficient
alpha=10;
u_out = 18; % ambient air temperature (°C)
%Task 6) Volumetric heat capacities: rho * c_p
% Densities [kg/m^3]
rho_wall = 2400; % ceramic
rho_fluid = 1000; % water
rho_air = 1.2; % air
% Specific heats [J/(kg*K)]
cp_wall = 1085;
cp_fluid = 4186;
cp_air = 1005;
% Volumetric heat capacities [J/(m^3*K)]
c_wall = rho_wall * cp_wall;
c_fluid = rho_fluid * cp_fluid;
c_air = rho_air * cp_air;
%% Task 1: Mesh definition
% Create PDE model
model = createpde();
% Points (meters)
A = [0, 0]; B = [0.055, 0];
C = [0.083, 0.105]; H = [0.078, 0.105];
F = [0.050, 0.005]; E = [0, 0.005];
G = [0.067, 0.066]; I = [0, 0.066];
D = [0, 0.105];
% Geometry matrix (edges)
g1 = [2; A(1); E(1); A(2); E(2); 1; 0]; % Axis - ceramic
g2 = [2; E(1); I(1); E(2); I(2); 2; 0]; % Axis - fluid
g3 = [2; I(1); D(1); I(2); D(2); 3; 0]; % Axis - air
g4 = [2; A(1); B(1); A(2); B(2); 1; 0]; % Outer ceramic
g5 = [2; B(1); C(1); B(2); C(2); 1; 0]; % Outer ceramic
g6 = [2; C(1); H(1); C(2); H(2); 1; 3]; % Top rim: (C-H) ceramic-air
g7 = [2; H(1); F(1); H(2); F(2); 1; 3]; % Inner ceramic wall (H-F) ceramic-air
g8 = [2; F(1); E(1); F(2); E(2); 1; 2]; % Inner ceramic bottom (F-E) ceramic-fluid
g9 = [2; F(1); G(1); F(2); G(2); 2; 3]; % Fluid surface (F-G) fluid - ceramic
g10 = [2; G(1); I(1); G(2); I(2); 2; 3]; % Fluid surface (G-I) fluid-air
g11 = [2; D(1); H(1); D(2); H(2); 3; 0]; % Air top boundary: (D-H) air-outside
% Assemble geometry
g = [g1 g2 g3 g4 g5 g6 g7 g8 g9 g10 g11];
geometryFromEdges(model, g);
% figure(1);
% pdegplot(model, 'EdgeLabels','on', 'FaceLabels','on');
% axis equal;
% hold on;
%
% % Plot points
% Pts = [A; B; C; D; E; F; G; H; I];
% plot(Pts(:,1), Pts(:,2), 'ro', 'MarkerFaceColor','r');
% % Label points
% labels = {'A','B','C','D','E','F','G','H','I'};
% for k = 1:length(labels)
% text(Pts(k,1), Pts(k,2), [' ' labels{k}], ...
% 'FontSize',10, 'Color','r', 'FontWeight','bold');
% end
% title('Geometry with edge, face, and point labels');
% hold off;
% Generate mesh, linear and 3 nodes per element
mesh = generateMesh(model, 'Hmax', 0.002, 'GeometricOrder','linear');
% figure(2);
% pdemesh(model);
% axis equal;
% title('Generated mesh');
%% Task 2: Direct solver with constant lambda
nodes = mesh.Nodes; % coordinates of all mesh nodes
elements = mesh.Elements; % which nodes make up each triangle element
Nnodes = size(nodes,2);
Nelems = size(elements,2);
% Define material properties (for simplicity, lambda = 1 everywhere)
lambda = ones(Nelems,1); % thermal conductivity
% Initialize global stiffness matrix and RHS
K = sparse(Nnodes, Nnodes);
F = zeros(Nnodes,1);
% Assemble K and F
for e = 1:Nelems %Loop over each triangle element
vert = elements(:,e); %nodes of element
x = nodes(1,vert);
y = nodes(2,vert);
Ae = polyarea(x,y); % Compute area of the triangle
% Linear triangle gradients
b = [y(2)-y(3); y(3)-y(1); y(1)-y(2)]; % derivative with respect to x
c = [x(3)-x(2); x(1)-x(3); x(2)-x(1)]; % derivative with respect to y
% Element stiffness matrix
Ke = (lambda(e)/(4*Ae)) * (b*b.' + c*c.');
% Assemble
K(vert,vert) = K(vert,vert) + Ke;
% Element load vector (f=0)
F(vert) = F(vert) + zeros(3,1);
end
% Find boundary nodes (couldn't find a better way)
edgesAll = [elements([1 2],:), elements([2 3],:), elements([3 1],:)]; % all edges -> 2x(3*Nelems) awway since each triangle has 3 edges
edgesSorted = sort(edgesAll,1); % sort nodes of each edge, ensure that [i,j] and [j,i] are the same
[~,~,ic] = unique(edgesSorted','rows'); % identifies unique edges and assignes indices ic
counts = accumarray(ic,1); % counts how many times each edge appears in the mesh
boundaryEdges = find(counts==1); %edges belonging to only 1 element: hence on the boundary
boundaryNodes = unique(edgesSorted(:,boundaryEdges)); % nodes belonging to these boundary edges
% Direct solver
% Enforce Dirichlet BC strongly
K(boundaryNodes,:) = 0;
K(:,boundaryNodes) = 0;
K(boundaryNodes,boundaryNodes) = speye(length(boundaryNodes));
F(boundaryNodes) = 0;
% Direct solve
u = K \ F;
% figure(3)
% pdeplot(model, 'XYData', u, 'Mesh','on');
% axis equal;
% title('Stationary Dirichlet solution');
% colorbar;
%% Task 3: Laplace with multiple lambdas
[K, F] = CalculateLaplace_mult(model, lambda_wall, lambda_fluid, lambda_air);
% Enforce Dirichlet BC strongly
K(boundaryNodes,:) = 0;
K(:,boundaryNodes) = 0;
K(boundaryNodes,boundaryNodes) = speye(length(boundaryNodes));
F(boundaryNodes) = 0;
% Direct solve
u = K \ F;
% % Plot solution
% figure(4)
% pdeplot(model,'XYData',u, 'Mesh','on');
% axis equal
% title('Task 3: Stationary solution with multiple conductivities');
% colorbar
%% Task 4: Robin boundary condition
[K, F] = CalculateLaplace_mult(model, lambda_wall, lambda_fluid, lambda_air);
[K, F] = ApplyRobinBC_mult(model, K, F, alpha, u_out);
% Direct solve
u = K \ F;
% figure(5)
% pdeplot(model, 'XYData', u, 'Mesh','on');
% axis equal
% title('Task 4: Stationary solution with Robin BC');
% colorbar
%% Task 5: Axisymmetric Laplace + Robin BC
[K, F] = CalculateLaplace_mult_rot(model, lambda_wall, lambda_fluid, lambda_air);
[K,F] = ApplyRobinBC_mult_rot(model, K, F, alpha, u_out);
% Direct solve
u = K \ F;
% figure(6)
% pdeplot(model, 'XYData', u, 'Mesh','on');
% axis equal
% title('Task 5: Axisymmetric stationary solution with Robin BC');
% colorbar
%To see it in 3D paste here the code in "AdditionalPlotCodes.txt".
%% Task 6: Axisymmetric mass matrix
M = sparse(Nnodes, Nnodes);
M = AddMass_mult_rot(model, M, c_wall, c_fluid, c_air);
%% Task 7: Initial solution
u0 = Init_Solution_mult(model, 18, 80, 18);
% TRY WITH HOTTER LIQUID
% figure(7)
% pdeplot(model, 'XYData', u0, 'Mesh','on');
% axis equal
% title('Initial temperature distribution');
% colorbar
%% Task 8: Time-dependent simulation (explicit scheme)
tau = 1; % time step in seconds
T_end = 1000; % total simulation time (seconds)
Nt = ceil(T_end/tau); % number of time steps
A = (1/tau)*M+K; % Left-hand side matrix
u = u0;
for k = 1:Nt
b = (1/tau)*M*u + F; % F is the load vector, F=0
u_next = A\b;
u = u_next; % Update
if mod(k,20) == 0
% figure(8)
% pdeplot(model, 'XYData', u, 'Mesh','on');
% axis equal
% title(['Temperature at t = ', num2str(k*tau), ' s']);
% colorbar
% drawnow
end
end
%To see the 9 snapshots paste here the codes in "AdditionalPlotCodes.txt"
M = sparse(Nnodes, Nnodes);
M = AddMass_mult_rot(model, M, c_wall, c_fluid, c_air);
%% Task 9 (i): Heating time using inner ceramic wall temperature
T_target = 67; % [°C]
tau = 0.1; % time step in seconds
T_end = 1000; % total simulation time (seconds)
Nt = ceil(T_end/tau); % number of time steps
[K,F] = CalculateLaplace_mult_rot(model, lambda_wall, lambda_fluid, lambda_air);
[K,F] = ApplyRobinBC_mult_rot(model, K, F, alpha, u_out);
A = (1/tau)*M+K; % Left-hand side matrix
innerWallNodes = unique([findNodes(model.Mesh,'region','Edge',8), findNodes(model.Mesh,'region','Edge',9)]);
%innerWallNodes = findNodes(model.Mesh,'region','Edge',9);
u= u0;
% Storage
timeVec = (0:Nt-1)' * tau;
innerWallTemp = zeros(Nt,1);
Twarm = NaN;
for k = 1:Nt
b = (1/tau)*M*u + F;
u = A\b;
innerWallTemp(k) = mean(u(innerWallNodes));
%innerWallTemp(k) = max(u(innerWallNodes));
% Check heating criterion
if innerWallTemp(k) >= T_target
Twarm = k * tau;
fprintf('Task 9 (i): Inner wall reaches %.1f°C at T = %.1f s\n', ...
T_target, Twarm);
break
end
end
figure(9)
plot(timeVec(1:k), innerWallTemp(1:k), 'LineWidth', 2)
hold on
yline(T_target,'r--','67°C','LineWidth',1.5)
xlabel('Time [s]')
ylabel('Average inner wall temperature [°C]')
title('Heating of the inner ceramic wall')
grid on
%% CHECK: Insulated mug transient redistribution
[K_neu, F_neu] = CalculateLaplace_mult_rot(model,lambda_wall,lambda_fluid,lambda_air);
M_neu = sparse(Nnodes, Nnodes);
M_neu = AddMass_mult_rot(model,M_neu,c_wall,c_fluid,c_air);
% Time stepping parameters
tau = 0.5;
T_end = 100;
Nt = ceil(T_end / tau);
A_neu = (1/tau) * M_neu + K_neu;
% Initial condition
u = u0;
for k = 1:Nt
b = (1/tau) * M_neu * u + F_neu;
u = A_neu \ b;
if mod(k,20) == 0
% figure(10)
% pdeplot(model, 'XYData', u, 'Mesh','on');
% axis equal
% title(['Insulated mug, t = ', num2str(k*tau), ' s']);
% colorbar
% drawnow
end
end