Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
uvahotspot
GitHub Repository: uvahotspot/HotSpot
Path: blob/master/package.c
612 views
1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
#ifdef _MSC_VER
5
#define strcasecmp _stricmp
6
#define strncasecmp _strnicmp
7
#else
8
#include <strings.h>
9
#endif
10
#include <math.h>
11
12
#include "package.h"
13
#include "temperature.h"
14
#include "flp.h"
15
#include "util.h"
16
17
/* default package configuration parameters */
18
package_config_t default_package_config(void)
19
{
20
package_config_t config;
21
/* 0: forced convection, 1: natural convection */
22
config.natural_convec = 0;
23
24
/* airflow type - 0: lateral airflow from sink side, 1: impinging airflow from sink top*/
25
config.flow_type = 0;
26
27
/* heatsink type - 0: fin-channel sink, 1: pin-fin sink */
28
config.sink_type = 0;
29
30
/* default sink specs */
31
/* sink base size is defined in thermal_config
32
* 1) fin-channel sink
33
*/
34
config.fin_height = 0.03;
35
config.fin_width = 0.001;
36
config.channel_width = 0.002;
37
/* 2) pin-fin sink */
38
config.pin_height = 0.02;
39
config.pin_diam = 0.002;
40
config.pin_dist = 0.005;
41
42
/* fan specs */
43
config.fan_radius = 0.03;
44
config.motor_radius = 0.01;
45
config.rpm = 1000;
46
47
return config;
48
}
49
50
/*
51
* parse a table of name-value string pairs and add the configuration
52
* parameters to package 'config'
53
*/
54
void package_config_add_from_strs(package_config_t *config, str_pair *table, int size)
55
{
56
int idx;
57
if ((idx = get_str_index(table, size, "natural_convec")) >= 0)
58
if(sscanf(table[idx].value, "%d", &config->natural_convec) != 1)
59
fatal("invalid format for heatsink configuration parameter natural_convec\n");
60
if ((idx = get_str_index(table, size, "flow_type")) >= 0)
61
if(sscanf(table[idx].value, "%d", &config->flow_type) != 1)
62
fatal("invalid format for heatsink configuration parameter flow_type\n");
63
if ((idx = get_str_index(table, size, "sink_type")) >= 0)
64
if(sscanf(table[idx].value, "%d", &config->sink_type) != 1)
65
fatal("invalid format for heatsink configuration parameter sink_type\n");
66
if ((idx = get_str_index(table, size, "fin_height")) >= 0)
67
if(sscanf(table[idx].value, "%lf", &config->fin_height) != 1)
68
fatal("invalid format for heatsink configuration parameter fin_height\n");
69
if ((idx = get_str_index(table, size, "fin_width")) >= 0)
70
if(sscanf(table[idx].value, "%lf", &config->fin_width) != 1)
71
fatal("invalid format for heatsink configuration parameter fin_width\n");
72
if ((idx = get_str_index(table, size, "channel_width")) >= 0)
73
if(sscanf(table[idx].value, "%lf", &config->channel_width) != 1)
74
fatal("invalid format for heatsink configuration parameter channel_width\n");
75
if ((idx = get_str_index(table, size, "pin_height")) >= 0)
76
if(sscanf(table[idx].value, "%lf", &config->pin_height) != 1)
77
fatal("invalid format for heatsink configuration parameter pin_height\n");
78
if ((idx = get_str_index(table, size, "pin_diam")) >= 0)
79
if(sscanf(table[idx].value, "%lf", &config->pin_diam) != 1)
80
fatal("invalid format for heatsink configuration parameter pin_diam\n");
81
if ((idx = get_str_index(table, size, "pin_dist")) >= 0)
82
if(sscanf(table[idx].value, "%lf", &config->pin_dist) != 1)
83
fatal("invalid format for heatsink configuration parameter pin_dist\n");
84
if ((idx = get_str_index(table, size, "fan_radius")) >= 0)
85
if(sscanf(table[idx].value, "%lf", &config->fan_radius) != 1)
86
fatal("invalid format for fan configuration parameter fan_radius\n");
87
if ((idx = get_str_index(table, size, "motor_radius")) >= 0)
88
if(sscanf(table[idx].value, "%lf", &config->motor_radius) != 1)
89
fatal("invalid format for fan configuration parameter motor_radius\n");
90
if ((idx = get_str_index(table, size, "rpm")) >= 0)
91
if(sscanf(table[idx].value, "%d", &config->rpm) != 1)
92
fatal("invalid format for configuration parameter rpm\n");
93
94
if ((config->fin_height <= 0) || (config->fin_width <= 0) || (config->channel_width <= 0) ||
95
(config->pin_height <= 0) || (config->pin_diam <= 0) || (config->pin_dist <= 0) ||
96
(config->fan_radius <= 0) || (config->motor_radius <= 0) || (config->rpm <= 0))
97
fatal("heatsink/fan dimensions and fan speed should be greater than zero\n");
98
if ((config->natural_convec != 0) && (config->natural_convec != 1))
99
fatal("invalid convection mode\n");
100
if ((config->flow_type != 0) && (config->flow_type != 1))
101
fatal("invalid air flow type\n");
102
if ((config->sink_type != 0) && (config->sink_type != 1))
103
fatal("invalid heatsink type\n");
104
}
105
106
/*
107
* convert config into a table of name-value pairs. returns the no.
108
* of parameters converted
109
*/
110
int package_config_to_strs(package_config_t *package_config, str_pair *package_table, int max_entries)
111
{
112
if (max_entries < 12)
113
fatal("not enough entries in table\n");
114
115
sprintf(package_table[0].name, "natural_convec");
116
sprintf(package_table[1].name, "flow_type");
117
sprintf(package_table[2].name, "sink_type");
118
sprintf(package_table[3].name, "fin_height");
119
sprintf(package_table[4].name, "fin_width");
120
sprintf(package_table[5].name, "channel_width");
121
sprintf(package_table[6].name, "pin_height");
122
sprintf(package_table[7].name, "pin_diam");
123
sprintf(package_table[8].name, "pin_dist");
124
sprintf(package_table[9].name, "fan_radius");
125
sprintf(package_table[10].name, "motor_radius");
126
sprintf(package_table[11].name, "rpm");
127
128
sprintf(package_table[0].value, "%d", package_config->natural_convec);
129
sprintf(package_table[1].value, "%d", package_config->flow_type);
130
sprintf(package_table[2].value, "%d", package_config->sink_type);
131
sprintf(package_table[3].value, "%lg", package_config->fin_height);
132
sprintf(package_table[4].value, "%lg", package_config->fin_width);
133
sprintf(package_table[5].value, "%lg", package_config->channel_width);
134
sprintf(package_table[6].value, "%lg", package_config->pin_height);
135
sprintf(package_table[7].value, "%lg", package_config->pin_diam);
136
sprintf(package_table[8].value, "%lg", package_config->pin_dist);
137
sprintf(package_table[9].value, "%lg", package_config->fan_radius);
138
sprintf(package_table[10].value, "%lg", package_config->motor_radius);
139
sprintf(package_table[11].value, "%d", package_config->rpm);
140
141
return 12;
142
}
143
144
/* calculate forced air flow and package thermal parameters
145
* references:
146
* 1-1 lateral flow, fin-channel heat sinks:
147
* -laminar flow: P. terrtstra et al. "Analytical Forced Convection Modeling of Plate-Fin Heat Sinks". IEEE SEMI-THERM, pp 34-41, 1999
148
* -turbulent flow: Y. A. Cengel. "Heat and Mass Transfer: A Practical Approach", Mcgraw-Hill Inc. New York 2007
149
* 1-2 lateral flow, pin-fin heat sinks:
150
* R. Ribando et al. "Estimating the Convection Coefficient for Flow Through Banks of Fins on a Heat Sink". U.Va. MAE314 Course Notes, Spring 2007
151
* 2-1 impinging flow for both fin-channel and pin-fin heat sinks:
152
* H. A. El-Sheikh et al. "Heat Transfer from Pin-Fin Heat Sinks under Multiple Impinging Jets", IEEE Trans. on Adv. Packaging, 23(1):113-120, Feb. 2000
153
* 3-1 fan model:
154
* F. P. Bleier. "Fan Handbook: Selection, Application and Design". McGraw-Hill Inc. New York, 1998
155
* 3-2 motor model of the fan:
156
* Y. Zhang et al. "SODA: Sensitivity-Based Optimization of Disk Architecture". IEEE/ACM DAC, pp. 865-870, 2007
157
*/
158
159
void calculate_flow(convection_t *p, package_config_t *config, thermal_config_t *thermal_config)
160
{
161
/* local variables */
162
double n_fin, n_pin;
163
double sur_area_fin, sur_area_pin;
164
double reynolds, nusselt, h_coeff, v, r_th;
165
double dh, a_fan, dr, r_approx, vol_v, rey_star, m, eta, f, c1, c2, a_hs;
166
double t1, t2; /* temporary variables for long formulas*/
167
168
double s_sink = thermal_config->s_sink;
169
double k_sink = thermal_config->k_sink;
170
171
int flow_type = config->flow_type;
172
int sink_type = config->sink_type;
173
double fin_height = config->fin_height;
174
double fin_width = config->fin_width;
175
double channel_width = config->channel_width;
176
double pin_height = config->pin_height;
177
double pin_diam = config->pin_diam;
178
double pin_dist = config->pin_dist;
179
double fan_radius = config->fan_radius;
180
double motor_radius = config->motor_radius;
181
double rpm = config->rpm;
182
183
double temp_val = (s_sink-pin_diam)/(pin_diam+pin_dist);
184
185
n_fin = ceil((s_sink-fin_width)/(fin_width+channel_width)-0.5);
186
sur_area_fin = s_sink*(s_sink+2.0*n_fin*fin_height);
187
n_pin = ceil(temp_val*temp_val-0.5);
188
sur_area_pin = s_sink*s_sink+PI*pin_diam*pin_height*n_pin;
189
190
/* calculate volumetric air speed out of the fan */
191
dr = sqrt(fan_radius * fan_radius - motor_radius * motor_radius);
192
r_approx = motor_radius + dr; /* approximated average fan radius */
193
a_fan = PI * dr * dr; /* total fan blade area */
194
195
/* refer to DAC'07 SODA paper by Zhang, Gurumurthi and Stan
196
* crudely approximating an IC fan motor with a hard drive spindle motor model
197
* the principle is that the dragging momentum on the blades from the air equals to the torque of the motor at steady state
198
* so, torque=b*(omega^alpha)=drag_force*radius (1)
199
* where b=0.5*pi*air_density*C_d*(radius^beta)
200
* drag coeff C_d=drag_force/(0.5*air_density*air_velocity^2*total_blade_area)
201
* manipulate both side of (1), derive volmetric velocity from the fan as...
202
*/
203
vol_v = a_fan * sqrt(0.25 * PI * pow(r_approx,FAN_BETA-1) * pow(rpm * RPM_TO_RAD,FAN_ALPHA) / a_fan);
204
205
/* calculate the actual air velocity through heatsink: vol_velocity/area_duct_sink */
206
if (flow_type==0) { /* lateral airflow */
207
dh = 2.0*channel_width*s_sink/(channel_width+s_sink); /* hydraulic diameter */
208
if (sink_type==0) { /* fin-channel sink */
209
v = vol_v / ((n_fin-1)*channel_width*fin_height);
210
}
211
else { /* pin-fin sink */
212
v = vol_v / ((sqrt(n_pin)-1)*pin_dist*pin_height);
213
}
214
}
215
else { /* impinging flow */
216
dh = 2.0 * s_sink / sqrt(PI); /* equivalent air nozzle diameter */
217
v = vol_v / (s_sink*s_sink-n_pin*PI*(pin_diam*0.5)*(pin_diam*0.5));
218
}
219
220
/* Reynolds number */
221
reynolds = AIR_DSTY * v * dh / AIR_DYNVISC;
222
223
/* calculate nusselt number, heat transfer coeff
224
* and equivalent overall lumped convection resistance
225
*/
226
if (flow_type==0) { /* lateral airflow */
227
if (sink_type==0) { /* fin-channel sink */
228
if (reynolds <= REY_THRESHOLD) { /* laminar flow */
229
rey_star = AIR_DSTY*v*channel_width*channel_width/(AIR_DYNVISC*s_sink);
230
t1 = pow(rey_star*PRANTDL_NUM*0.5,-3);
231
t2 = pow(0.664*sqrt(rey_star)*pow(PRANTDL_NUM,0.33)*sqrt(1+3.65/sqrt(rey_star)),-3);
232
nusselt = pow(t1+t2,-0.33); /* nusselt number */
233
h_coeff = nusselt*AIR_COND/channel_width; /* heat transfer coefficient */
234
m = sqrt(2*h_coeff/(k_sink*fin_width)); /* fin parameter */
235
eta = tanh(m*s_sink)/(m*s_sink); /* fin efficiency */
236
r_th = 1.0/(h_coeff*(channel_width+2*eta*s_sink)*n_fin*s_sink);
237
}
238
else { /* turbulent flow */
239
f = 1.0/pow((0.79*log(reynolds)-1.64),2.0);
240
nusselt = 0.125*f*reynolds*pow(PRANTDL_NUM,0.33);
241
h_coeff = nusselt*AIR_COND/dh;
242
m = sqrt(2*h_coeff/(k_sink*fin_width)); /* fin parameter */
243
eta = tanh(m*s_sink)/(m*s_sink); /* fin efficiency */
244
r_th = 1.0/(h_coeff*(channel_width+2*eta*s_sink)*n_fin*s_sink);
245
}
246
}
247
else { /* pin-fin sink */
248
c1 = 0.6;
249
c2 = 0.8+0.8333*sqrt(sqrt(n_pin)-1)/pow((1+0.03*pow((sqrt(n_pin)-1),2.0)),0.25);
250
nusselt = 0.4+0.9*(1.25*c2*c1*sqrt(reynolds)+0.001*reynolds)*pow(PRANTDL_NUM,0.33);
251
h_coeff = nusselt*AIR_COND/pin_diam;
252
r_th = 1.0/(h_coeff*sur_area_pin);
253
}
254
}
255
else { /* impinging flow */
256
if (sink_type==0) { /* fin-channel sink */
257
a_hs = sur_area_fin;
258
}
259
else { /* pin-fin sink */
260
a_hs = sur_area_pin;
261
}
262
dh = 2.0 * s_sink / sqrt(PI);
263
nusselt = 1.92*pow(reynolds,0.716)*pow(PRANTDL_NUM,0.4)*pow(a_hs/(s_sink*s_sink),-0.698);
264
h_coeff = nusselt*AIR_COND/dh;
265
r_th = 1.0/(h_coeff*a_hs);
266
}
267
p->n_fin = n_fin;
268
p->sur_area_fin = sur_area_fin;
269
p->n_pin = n_pin;
270
p->sur_area_pin = sur_area_pin;
271
p->reynolds = reynolds;
272
p->nusselt = nusselt;
273
p->h_coeff = h_coeff;
274
p->v = v;
275
p->r_th = r_th;
276
}
277
278
/* calculate convection parameters for natural convection.
279
* reference: Y. A. Cengel. "Heat and Mass Transfer: A Practical Approach", Mcgraw-Hill Inc. New York 2007
280
*/
281
void calc_natural_convec(convection_t *p, package_config_t *config, thermal_config_t *thermal_config, double sink_temp)
282
{
283
/* local variables */
284
double rayleigh;
285
double n_fin, n_pin;
286
double w;
287
double sur_area, sur_area_fin, sur_area_pin;
288
double nusselt, h_coeff, r_th, r_th_rad;
289
290
double s_sink = thermal_config->s_sink;
291
double ambient = thermal_config->ambient;
292
293
int sink_type = config->sink_type;
294
double fin_height = config->fin_height;
295
double fin_width = config->fin_width;
296
double channel_width = config->channel_width;
297
double pin_height = config->pin_height;
298
double pin_diam = config->pin_diam;
299
double pin_dist = config->pin_dist;
300
301
double temp_val = (s_sink-pin_diam)/(pin_diam+pin_dist);
302
303
n_fin = ceil((s_sink-fin_width)/(fin_width+channel_width)-0.5);
304
sur_area_fin = s_sink*(s_sink+2.0*n_fin*fin_height);
305
n_pin = ceil(temp_val*temp_val-0.5);
306
sur_area_pin = s_sink*s_sink+PI*pin_diam*pin_height*n_pin;
307
308
if (sink_type==0) { /* fin-channel sink */
309
sur_area = sur_area_fin;
310
w = channel_width;
311
} else { /* pin-fin heatsink */
312
sur_area = sur_area_pin;
313
w = pin_dist;
314
}
315
316
/* CAUTION: equations are derived for fin-channel heatsink, not validated for pin-fin heatsink */
317
rayleigh = GRAVITY*VOL_EXP_COEFF*(sink_temp-ambient)*pow(w,3.0)*PRANTDL_NUM/(AIR_KINVISC*AIR_KINVISC);
318
nusselt = pow((576/((rayleigh*w/s_sink)*(rayleigh*w/s_sink))+2.873/sqrt(rayleigh*w/s_sink)),-0.5);
319
h_coeff = nusselt*AIR_COND/w;
320
r_th = 1.0/(h_coeff*sur_area);
321
322
/* thermal radiation*/
323
r_th_rad = (sink_temp-ambient)/(EMISSIVITY*STEFAN*(pow(sink_temp,4.0)-pow(ambient,4.0))*sur_area);
324
325
/* overall thermal resistance = natural convection in parallel with thermal radiation */
326
r_th = r_th*r_th_rad/(r_th+r_th_rad);
327
328
p->n_fin = n_fin;
329
p->sur_area_fin = sur_area_fin;
330
p->n_pin = n_pin;
331
p->sur_area_pin = sur_area_pin;
332
p->nusselt = nusselt;
333
p->h_coeff = h_coeff;
334
p->r_th = r_th;
335
}
336
337
/* debug print */
338
void debug_print_convection(convection_t *p)
339
{
340
fprintf(stdout, "printing airflow information...\n");
341
fprintf(stdout, "n_fin: %f\n", p->n_fin);
342
fprintf(stdout, "sur_area_fin: %f\n", p->sur_area_fin);
343
fprintf(stdout, "n_pin: %f\n", p->n_pin);
344
fprintf(stdout, "sur_area_pin: %f\n", p->sur_area_pin);
345
fprintf(stdout, "reynolds: %f\n", p->reynolds);
346
fprintf(stdout, "nusselt: %f\n", p->nusselt);
347
fprintf(stdout, "h_coeff: %f\n", p->h_coeff);
348
fprintf(stdout, "v: %f\n", p->v);
349
fprintf(stdout, "r_th: %f\n", p->r_th);
350
}
351
352
/* initialize and calculate package parameters and update r_convec */
353
int package_model(thermal_config_t *thermal_config, str_pair *table, int size, double sink_temp)
354
{
355
int idx;
356
int natural_convec;
357
358
str_pair package_table[MAX_ENTRIES];
359
int package_size;
360
361
/* package config parameters */
362
package_config_t package_config;
363
convection_t p;
364
365
package_size = 0;
366
367
/* get defaults */
368
package_config = default_package_config();
369
/* parse the package config file name */
370
if ((idx = get_str_index(table, size, "package_config_file")) >= 0) {
371
if(sscanf(table[idx].value, "%s", thermal_config->package_config_file) != 1)
372
fatal("invalid format for configuration parameter package_config_file\n");
373
}
374
/* read package config file */
375
if (strcmp(thermal_config->package_config_file, NULLFILE))
376
package_size += read_str_pairs(&package_table[package_size], MAX_ENTRIES, thermal_config->package_config_file);
377
378
/* modify according to package config file */
379
package_config_add_from_strs(&package_config, package_table, package_size);
380
381
natural_convec = package_config.natural_convec;
382
383
/* calculate flow parameters into p */
384
if (!natural_convec) /* forced convection */
385
calculate_flow(&p, &package_config, thermal_config);
386
else /* natural convection */
387
calc_natural_convec(&p, &package_config, thermal_config, sink_temp);
388
389
/* print flow parameters for debug */
390
#if VERBOSE > 1
391
debug_print_convection(&p);
392
#endif
393
/* assign new r_convec calculated from the package model */
394
thermal_config->r_convec = p.r_th;
395
396
return natural_convec;
397
}
398
399