1.3.64
 
Loading...
Searching...
No Matches
BoundaryLayerConductanceModel.cpp
Go to the documentation of this file.
1
17
18using namespace helios;
19
21
22 wind_speed_default = 1.f;
23
24 air_temperature_default = 293.f;
25
26 surface_temperature_default = 303.f;
27
28 message_flag = true; // print messages to screen by default
29
30 // Copy pointer to the context
31 context = __context;
32}
33
35 message_flag = true;
36}
37
39 message_flag = false;
40}
41
43 std::vector<uint> UUIDs = context->getAllUUIDs();
44 setBoundaryLayerModel(UUIDs, gH_model);
45}
46
47void BLConductanceModel::setBoundaryLayerModel(uint UUID, const char *gH_model) {
48 std::vector<uint> UUIDs{UUID};
49 setBoundaryLayerModel(UUIDs, gH_model);
50}
51
52void BLConductanceModel::setBoundaryLayerModel(const std::vector<uint> &UUIDs, const char *gH_model) {
53
54 uint model = 0;
55
56 if (strcmp(gH_model, "Pohlhausen") == 0 || strcmp(gH_model, "Polhausen") == 0) {
57 model = 0;
58 } else if (strcmp(gH_model, "InclinedPlate") == 0) {
59 model = 1;
60 } else if (strcmp(gH_model, "Sphere") == 0) {
61 model = 2;
62 } else if (strcmp(gH_model, "Ground") == 0) {
63 model = 3;
64 } else {
65 std::cerr << "WARNING (EnergyBalanceModel::setBoundaryLayerModel): Boundary-layer conductance model " << gH_model << " is unknown. Skipping this function call.." << std::endl;
66 return;
67 }
68
69 for (uint UUID: UUIDs) {
70 boundarylayer_model[UUID] = model;
71 }
72}
73
75
76 run(context->getAllUUIDs());
77}
78
79void BLConductanceModel::run(const std::vector<uint> &UUIDs) {
80
81 for (uint UUID: UUIDs) {
82
83 float U;
84 if (context->doesPrimitiveDataExist(UUID, "wind_speed")) {
85 context->getPrimitiveData(UUID, "wind_speed", U);
86 } else {
87 U = wind_speed_default;
88 }
89
90 float Ta;
91 if (context->doesPrimitiveDataExist(UUID, "air_temperature")) {
92 context->getPrimitiveData(UUID, "air_temperature", Ta);
93 } else {
94 Ta = air_temperature_default;
95 }
96
97 float T;
98 if (context->doesPrimitiveDataExist(UUID, "temperature")) {
99 context->getPrimitiveData(UUID, "temperature", T);
100 } else {
101 T = surface_temperature_default;
102 }
103
104 float L;
105 if (context->doesPrimitiveDataExist(UUID, "object_length")) {
106 context->getPrimitiveData(UUID, "object_length", L);
107 if (L == 0) {
108 L = sqrt(context->getPrimitiveArea(UUID));
109 }
110 } else if (context->getPrimitiveParentObjectID(UUID) > 0) {
111 uint objID = context->getPrimitiveParentObjectID(UUID);
112 L = sqrt(context->getObjectArea(objID));
113 } else {
114 L = sqrt(context->getPrimitiveArea(UUID));
115 }
116
117 // Number of primitive faces - check material first, then primitive data
118 uint twosided_flag = context->getPrimitiveTwosidedFlag(UUID, 1);
119 char Nsides = (twosided_flag == 0) ? 1 : 2;
120
121 vec3 norm = context->getPrimitiveNormal(UUID);
122 float inclination = cart2sphere(norm).zenith;
123
124 float gH = calculateBoundaryLayerConductance(boundarylayer_model[UUID], U, L, Nsides, inclination, T, Ta);
125
126 context->setPrimitiveData(UUID, "boundarylayer_conductance", gH);
127 }
128}
129
130float BLConductanceModel::calculateBoundaryLayerConductance(uint gH_model, float U, float L, char Nsides, float inclination, float TL, float Ta) {
131
132
133 assert(gH_model < 4);
134
135 float gH = 0;
136
137 if (L == 0) {
138 return 0;
139 }
140
141 if (gH_model == 0) { // Pohlhausen equation
142 // This comes from the correlation by Pohlhausen - see Eq. XX of Campbell and Norman (1998). It assumes a flat plate parallel to the direction of the flow, which extends infinitely in the cross-stream direction and "L" in the streamwise
143 // direction. It also assumes that the air is at standard temperature and pressure, and flow is laminar, forced convection.
144
145 gH = 0.135f * sqrt(U / L) * float(Nsides);
146
147 } else if (gH_model == 1) { // Inclined Plate
148
149 float Pr = 0.7f; // air Prandtl number
150
151 float nu = 1.568e-5; // air viscosity (m^2/sec)
152 float alpha = nu / Pr; // air diffusivity (m^2/sec)
153
154 float Re = U * L / nu;
155
156 float Gr = 9.81f * fabs(TL - Ta) * std::pow(L, 3) / ((Ta) *nu * nu);
157
158 // For zero or very low wind speed, revert to pure free convection
159 if (U <= 1e-6f || Re <= 1e-6f) {
160 // Pure natural convection correlation for inclined plates
161 float Nu_free;
162 if (inclination < 75.f * M_PI / 180.f || inclination > 105.f * M_PI / 180.f) {
163 // Nearly horizontal plates - use horizontal plate correlation
164 Nu_free = 0.54f * std::pow(Gr * fabs(cos(inclination)), 0.25f);
165 } else {
166 // Nearly vertical plates - use vertical plate correlation
167 Nu_free = 0.59f * std::pow(Gr, 0.25f);
168 }
169 gH = Nu_free * (alpha / L);
170 return gH;
171 }
172
173 float F1 = 0.399f * std::pow(Pr, 1.f / 3.f) * pow(1.f + pow(0.0468f / Pr, 2.f / 3.f), -0.25f);
174 float F2 = 0.75f * std::pow(Pr, 0.5f) * pow(2.5f * (1.f + 2.f * pow(Pr, 0.5f) + 2.f * Pr), -0.25f);
175
176 // direction of free convection
177 float free_direction;
178 if (TL >= Ta) {
179 free_direction = 1;
180 } else {
181 free_direction = -1;
182 }
183
184 // free_direction=1;
185
186 if (inclination < 75.f * M_PI / 180.f || inclination > 105.f * M_PI / 180.f) {
187
188 gH = 41.4f * alpha / L * 2.f * F1 * sqrtf(Re) * std::pow(1.f + free_direction * std::pow(2.f * F2 * std::pow(Gr * fabs(cos(inclination)) / (Re * Re), 0.25f) / (3.f * F1), 3), 1.f / 3.f);
189
190 } else {
191
192 float C = 0.07f * sqrtf(fabs(cos(inclination)));
193 float F3 = std::pow(Pr, 0.5f) * std::pow(0.25f + 1.6f * std::pow(Pr, 0.5f), -1.f) * std::pow(Pr / 5.f, 1.f / 5.f + C);
194
195 gH = 41.4f * alpha / L * 2.f * F1 * sqrtf(Re) * std::pow(1.f + free_direction * std::pow((F3 * pow(Gr * pow(Re, -5.f / 2.f), 1.f / 5.f) * std::pow(Gr, C)) / (6.f * (1.f / 5.f + C) * F1), 3.f), 1.f / 3.f);
196 }
197
198 } else if (gH_model == 2) { // Sphere
199
200 // Laminar flow around a sphere (L is sphere diameter). From Eq. 4 of Smart and Sinclair (1976).
201
202 float Pr = 0.7f; // air Prandtl number
203 float nu = 1.568e-5; // air viscosity (m^2/sec)
204 float ka = 0.024; // air thermal conductivity (W/m-K)
205 float cp = 29.25; // air heat capacity (J/mol-K)
206
207 float Re = U * L / nu;
208
209 gH = (ka / cp) / L * (2.0 + 0.6 * sqrtf(Re) * pow(Pr, 1.f / 3.f));
210
211 } else if (gH_model == 3) { // Ground
212 // From Eq. A17 of Kustas and Norman (1999). For the soil-air interface.
213
214 gH = 0.004f + 0.012f * U; // units in (m^3 air)/(m^2-sec.)
215
216 // assuming standard temperature and pressure, (m^3 air)*(1.2041 kg/m^3)/(0.02897 kg/mol) = 41.56 (mol air)/(m^2-sec.)
217
218 gH = gH * 41.56f;
219 }
220
221 return gH;
222}