-
Notifications
You must be signed in to change notification settings - Fork 1
/
Optimizer.m
274 lines (222 loc) · 10.4 KB
/
Optimizer.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
elementsPerCm = 20
maxIterations = 20
createIrregularFins = false
withEqualSpacing = true
solidTop = true
informationInterval = 100
kCopper = 386
kSteel = 17
kAluminum = 180
h = 50
tAmbient = 20
dx = 0.01 / elementsPerCm
dimension = 2 + (5 * elementsPerCm);
finLength = 0.01
heatGenPerSquareCm = 1 / (0.004 * finLength)
heatGenPerElement = heatGenPerSquareCm / (elementsPerCm ^ 2)
%making the conductivity matrix:
if (solidTop)
topLayer = kAluminum .* ones(1 * elementsPerCm, 5 * elementsPerCm);
else
topLayer = zeros(1 * elementsPerCm, 5 * elementsPerCm);
end
aluminumLayer = kAluminum .* ones(1 * elementsPerCm, 5 * elementsPerCm);
steelLayer = kSteel .* ones(1 * elementsPerCm, 5 * elementsPerCm);
steelSegment = kSteel .* ones(1 * elementsPerCm, 2 * elementsPerCm);
copperSegment = kCopper .* ones(1 * elementsPerCm, 1 * elementsPerCm);
conductivityMatrix = [topLayer; aluminumLayer; steelLayer; steelSegment copperSegment steelSegment; steelLayer];
%now adding the surrounding air:
conductivityMatrix = [zeros(5 * elementsPerCm, 1) conductivityMatrix zeros(5 * elementsPerCm, 1)];
conductivityMatrix = [zeros(1, (5 * elementsPerCm) + 2); conductivityMatrix; zeros(1, (5 * elementsPerCm) + 2)];
%making the heat generation matrix:
top = zeros(1 + (3 * elementsPerCm), 2 + (5 * elementsPerCm));
segment = zeros(1 * elementsPerCm, 1 + (2 * elementsPerCm));
copperHeatGen = heatGenPerElement .* (ones(1 * elementsPerCm, 1 * elementsPerCm));
bottom = zeros(1 + (1 * elementsPerCm), 2 + (5 * elementsPerCm));
heatGenMatrix = [top; segment copperHeatGen segment; bottom];
%compute geometry matrix (0 for air, 1 for solid):
geometryMatrix = not(not(conductivityMatrix));
%precompute surface exposure matrix and update later as needed:
nMatrix = zeros(2 + (5 * elementsPerCm), 2 + (5 * elementsPerCm));
for y = 2:(5 * elementsPerCm)
for x = 2:(5 * elementsPerCm)
nMatrix(y, x) = not(geometryMatrix(y + 1, x)) + not(geometryMatrix(y - 1, x)) + not(geometryMatrix(y, x + 1)) + not(geometryMatrix(y, x - 1));
end
end
%insulate the bottom
nMatrix(1 + (5 * elementsPerCm), : ) = zeros(1, 2 + (5 * elementsPerCm));
% everything else before was just setting up the problem
% now the real fun can begin (shape optimization!)
bestConductivityMatrix = conductivityMatrix;
bestGeometryMatrix = geometryMatrix;
bestExposureMatrix = nMatrix;
bestCoreTemp = 10000; % initially high so that the solution can progress
bestTempMatrix = zeros(dimension);
minTemperatures = zeros(1, maxIterations);
%begin the optimization loop
for iteration = 1:maxIterations
%monitor progress
if (mod(iteration, informationInterval) == 0)
iteration
iteration / maxIterations
end
if (createIrregularFins)
mutating = true;
while mutating
conductivityMatrix = bestConductivityMatrix;
geometryMatrix = bestGeometryMatrix;
nMatrix = bestExposureMatrix;
%generate a random mutation of the geometry
xCoord = 1 + ceil(5 * elementsPerCm * rand());
yCoord = 1 + ceil(1 * elementsPerCm * rand());
currentState = geometryMatrix(yCoord, xCoord);
%update model state with the new mutation so it can be tested
newState = not(currentState); %toggle from solid to air, or vice-versa
conductivityMatrix(yCoord, xCoord) = newState * kAluminum;
geometryMatrix(yCoord, xCoord) = newState;
dN = (2 * currentState) - 1;
nMatrix(yCoord + 1, xCoord) = nMatrix(yCoord + 1, xCoord) + dN;
nMatrix(yCoord - 1, xCoord) = nMatrix(yCoord - 1, xCoord) + dN;
nMatrix(yCoord, xCoord + 1) = nMatrix(yCoord, xCoord + 1) + dN;
nMatrix(yCoord, xCoord - 1) = nMatrix(yCoord, xCoord - 1) + dN;
%check if the mutation produces a void
fullySurrounded = geometryMatrix(yCoord + 1, xCoord) + geometryMatrix(yCoord - 1, xCoord) + geometryMatrix(yCoord, xCoord + 1) + geometryMatrix(yCoord, xCoord - 1);
validSurroundings = true;
if (newState == 1 && fullySurrounded == 0)
validSurroundings = false;
elseif (newState == 0 && fullySurrounded == 4)
validSurroundings = false;
end
if (validSurroundings)
topIsValid = isValid(yCoord - 1, xCoord, geometryMatrix, elementsPerCm);
bottomIsValid = isValid(yCoord + 1, xCoord, geometryMatrix, elementsPerCm);
leftIsValid = isValid(yCoord, xCoord - 1, geometryMatrix, elementsPerCm);
rightIsValid = isValid(yCoord, xCoord + 1, geometryMatrix, elementsPerCm);
mutating = not(topIsValid && bottomIsValid && leftIsValid && rightIsValid);
else
mutating = true;
end
end
else
conductivityMatrix = bestConductivityMatrix;
geometryMatrix = bestGeometryMatrix;
nMatrix = bestExposureMatrix;
if (withEqualSpacing)
finIndex = 2;
generateFin = true;
while (finIndex < dimension)
for step = 1:iteration
xCoord = finIndex;
yCoord = 2;
if xCoord < (dimension - 1)
currentState = geometryMatrix(yCoord, xCoord);
if (currentState ~= generateFin)
for yCoord = 2:(1 + (1 * elementsPerCm))
%update model state with the new mutation so it can be tested
newState = not(currentState); %toggle from solid to air, or vice-versa
conductivityMatrix(yCoord, xCoord) = newState * kAluminum;
geometryMatrix(yCoord, xCoord) = newState;
dN = (2 * currentState) - 1;
nMatrix(yCoord + 1, xCoord) = nMatrix(yCoord + 1, xCoord) + dN;
nMatrix(yCoord - 1, xCoord) = nMatrix(yCoord - 1, xCoord) + dN;
nMatrix(yCoord, xCoord + 1) = nMatrix(yCoord, xCoord + 1) + dN;
nMatrix(yCoord, xCoord - 1) = nMatrix(yCoord, xCoord - 1) + dN;
end
end
end
if step == iteration
generateFin = not(generateFin);
end
finIndex = finIndex + 1;
end
end
else
%generate a random mutation of the geometry
xCoord = 1 + ceil(5 * elementsPerCm * rand());
yCoord = 2;
currentState = geometryMatrix(yCoord, xCoord);
for yCoord = 2:(1 + (1 * elementsPerCm))
%update model state with the new mutation so it can be tested
newState = not(currentState); %toggle from solid to air, or vice-versa
conductivityMatrix(yCoord, xCoord) = newState * kAluminum;
geometryMatrix(yCoord, xCoord) = newState;
dN = (2 * currentState) - 1;
nMatrix(yCoord + 1, xCoord) = nMatrix(yCoord + 1, xCoord) + dN;
nMatrix(yCoord - 1, xCoord) = nMatrix(yCoord - 1, xCoord) + dN;
nMatrix(yCoord, xCoord + 1) = nMatrix(yCoord, xCoord + 1) + dN;
nMatrix(yCoord, xCoord - 1) = nMatrix(yCoord, xCoord - 1) + dN;
end
end
end
%%MESH ASSEMBLY
relationMatrix = zeros(dimension .^ 2);
heatGenAndLossVector = zeros(dimension .^ 2, 1);
for y = 1:dimension
for x = 1:dimension
if (y ~= 1) && (y ~= dimension) && (x ~= 1) && (x ~= dimension)
index = ((y - 1) * dimension) + x;
n = nMatrix(y, x);
emptinessFactor = geometryMatrix(y, x);
kU = conductivityMatrix(y - 1, x);
kD = conductivityMatrix(y + 1, x);
kL = conductivityMatrix(y, x - 1);
kR = conductivityMatrix(y, x + 1);
%create entry for this element
relationMatrix(index, index) = emptinessFactor * -1 * ((n .* h) + ((1 ./ dx) * (kU + kD + kL + kR)));
%create entries for the surrounding elements
relationMatrix(index, index - dimension) = kU * emptinessFactor / dx;
relationMatrix(index, index + dimension) = kD * emptinessFactor / dx;
relationMatrix(index, index - 1) = kL * emptinessFactor / dx;
relationMatrix(index, index + 1) = kR * emptinessFactor / dx;
%make entry in heat transfer vector
heatGenAndLossVector(index) = emptinessFactor * -1 * ((n * h * tAmbient) + heatGenMatrix(y, x));
end
end
end
%solving for temperatures
%remove zero columns and rows
[zeroRows, zeroColumns] = find(not(diag(relationMatrix)));
[nonZeroRows, nonZeroColumns] = find(diag(relationMatrix));
relationMatrix(zeroRows, : ) = [];
relationMatrix(:, zeroRows) = [];
length(heatGenAndLossVector);
heatGenAndLossVector(zeroRows) = [];
length(heatGenAndLossVector);
numElements = dimension ^ 2;
indexesRemoved = (numElements + 1) .* ones(numElements, 1);
currentRemoveIndex = 1;
% solve
tempVector = relationMatrix \ heatGenAndLossVector;
%reinflating the temperature vector
resultVector = zeros(1, numElements);
resultVector(nonZeroRows) = tempVector;
%put back in matrix form
tempMatrix = reshape(resultVector, dimension, dimension);
%compute fitness
maxTemp = max(tempVector);
minTemperatures(iteration) = maxTemp;
%if this mutation is more fit than the last version, keep the changes
if maxTemp < bestCoreTemp
bestConductivityMatrix = conductivityMatrix;
bestGeometryMatrix = geometryMatrix;
bestExposureMatrix = nMatrix;
bestTempMatrix = tempMatrix;
bestCoreTemp = maxTemp;
end
end
%plot result
bestCoreTemp
displayTempMatrix = transpose(bestTempMatrix);
displayTempMatrix(displayTempMatrix == 0) = 20; % adjusts temp scale for display
imagesc(displayTempMatrix)
colorbar
if (withEqualSpacing && not(createIrregularFins))
numFins = (dimension - 2) ./ (1:1:maxIterations);
xAxis = numFins;
else
xAxis = (1:1:maxIterations);
end
figure
plot(xAxis, minTemperatures)
ylabel('Max Core Temp. (Celcius)')
xlabel('Number of Fins')