Reputation: 25
I am trying to get the function to output an array T that has each value inside the fixed outer rows and columns, averaged with itself and the 4 numbers surrounding it. I made X to recieve all 9 of the values from my larger array, S to select only the ones I wanted and A to use when averaging, yet it will not work, I believe the problem lies in the X(ii,jj) = T((ii-1):(ii+1), (jj-1):(jj+1))
. Any help much appreciated
function T = tempsim(rows, cols, topNsideTemp, bottomTemp, tol)
T = zeros(rows,cols);
T(1,:) = topNsideTemp;
T(:,1) = topNsideTemp;
T(:,rows) = topNsideTemp;
T(rows,:) = bottomTemp;
S = [0 1 0; 1 1 1; 0 1 0];
X = zeros(3,3);
A = zeros(3,3);
for ii = 2:(cols-1);
jj = 2:(rows-1);
X(ii,jj) = T((ii-1):(ii+1), (jj-1):(jj+1))
A = X.*S;
T = (sum(sum(A)))/5
Upvotes: 0
Views: 185
Reputation: 4787
What you are doing looks like a convolution as Jouni points out. So using that knowledge, I came up with following code:
function T = tempsim(rows, cols, topNsideTemp, bottomTemp, tol)
sz = [rows,cols];
topEdge = sub2ind(sz, ones(1,cols) , 1:cols);
bottomEdge = sub2ind(sz, ones(1,cols)*rows, 1:cols);
leftEdge = sub2ind(sz, 1:rows , ones(1,rows));
rightEdge = sub2ind(sz, 1:rows , ones(1,rows)*cols);
otherEdges = [topEdge leftEdge rightEdge];
edges = [bottomEdge otherEdges];
%% set initial grid
T0 = zeros(sz);
T0(otherEdges) = topNsideTemp;
T0(bottomEdge) = bottomTemp;
%% average filter
F = [0 1 0
1 1 1
0 1 0];
F = F/sum(F(:));
%% simulation
T = T0; % initial condition
T = conv2(T, F, 'same');
T(edges) = T0(edges); % this keeps the edges set to the initial values
If you run this, you will get following results:
T = tempsim(10,10,100,-100)
T0 =
100 100 100 100 100 100 100 100 100 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 0 0 0 0 0 0 0 0 100
100 -100 -100 -100 -100 -100 -100 -100 -100 100
T =
100 100 100 100 100 100 100 100 100 100
100 40 20 20 20 20 20 20 40 100
100 20 0 0 0 0 0 0 20 100
100 20 0 0 0 0 0 0 20 100
100 20 0 0 0 0 0 0 20 100
100 20 0 0 0 0 0 0 20 100
100 20 0 0 0 0 0 0 20 100
100 20 0 0 0 0 0 0 20 100
100 0 -20 -20 -20 -20 -20 -20 0 100
100 -100 -100 -100 -100 -100 -100 -100 -100 100
I also showed T0
for clarity as you can see that T(2,2) == 40
, which is equal to (100 + 100 + 0 + 0 + 0)/5
from the same position in T0
.
From the context, I guess you'll be studying the convergence of this problem. If that's the case, you will have to repeat the last 2 lines until it converges.
But depending on your actual problem, I think you can improve the initial conditions to speed up convergence by initializing the grid to a temperature different from 0
. In the current code your boundary conditions will heat up the complete grid, which takes some time. If you just provide a proper guess for the bulk temperature (in lieu of 0
), this can speed up the convergence considerably. In my example I need about 40 steps for convergence up to a certain tolerance, with a proper guess (50
in my case) this can be reduced to about 20 steps for the same tolerance level. For larger grid, I expect to see even larger gains in efficiency.
This converges to the following values (and the mirror image for the other values):
100 100 100 100 100
100 96.502 93.464 91.254 90.097
100 92.989 86.925 82.533 80.245
100 89.229 79.995 73.386 69.974
100 84.579 71.615 62.556 57.963
100 77.78 59.86 47.904 42.037
100 66.515 41.786 26.614 19.565
100 45.939 13.075 -4.3143 -11.72
100 3.4985 -32.392 -46.997 -52.455
100 -100 -100 -100 -100
You can verify that this solution is an approximate fixpoint by verifying that for each element in the bulk it is equal to the calculated average within a certain tolerance.
Upvotes: 1