1.3.49
 
Loading...
Searching...
No Matches
InitializeRadiation.cpp
1#include "InitializeRadiation/InitializeRadiation.h"
2#include "SolarPosition.h"
3
4using namespace helios;
5
6void InitializeRadiation(const std::string &xml_input_file, SolarPosition *solarposition_ptr, RadiationModel *radiation_ptr, helios::Context *context_ptr) {
7
8 pugi::xml_document xmldoc;
9
10 std::string xml_error_string;
11 if (!open_xml_file(xml_input_file, xmldoc, xml_error_string)) {
12 helios_runtime_error(xml_error_string);
13 }
14
15 pugi::xml_node helios = xmldoc.child("helios");
16 pugi::xml_node node;
17
18 // *** Parsing of general inputs *** //
19
20 int radiation_block_count = 0;
21 for (pugi::xml_node radiation_block = helios.child("radiation"); radiation_block; radiation_block = radiation_block.next_sibling("radiation")) {
22 radiation_block_count++;
23
24 if (radiation_block_count > 1) {
25 std::cout << "WARNING: Only one 'radiation' block is allowed in the input file. Skipping any others..." << std::endl;
26 break;
27 }
28
29 int direct_ray_count = 100;
30 node = radiation_block.child("direct_ray_count");
31 if (node.empty()) {
32 direct_ray_count = 0;
33 } else {
34
35 const char *direct_ray_count_str = node.child_value();
36 if (!parse_int(direct_ray_count_str, direct_ray_count)) {
37 helios_runtime_error("ERROR: Value given for 'direct_ray_count' could not be parsed.");
38 } else if (direct_ray_count < 0) {
39 helios_runtime_error("ERROR: Value given for 'direct_ray_count' must be greater than or equal to 0.");
40 }
41 }
42
43 int diffuse_ray_count = 1000;
44 node = radiation_block.child("diffuse_ray_count");
45 if (node.empty()) {
46 diffuse_ray_count = 0;
47 } else {
48
49 const char *diffuse_ray_count_str = node.child_value();
50 if (!parse_int(diffuse_ray_count_str, diffuse_ray_count)) {
51 helios_runtime_error("ERROR: Value given for 'diffuse_ray_count' could not be parsed.");
52 } else if (diffuse_ray_count < 0) {
53 helios_runtime_error("ERROR: Value given for 'diffuse_ray_count' must be greater than or equal to 0.");
54 }
55 }
56
57 float diffuse_extinction_coeff = 0;
58 node = radiation_block.child("diffuse_extinction_coeff");
59 if (node.empty() && diffuse_ray_count > 0) {
60 std::cout << "WARNING: No value given for 'diffuse_extinction_coeff'. Assuming a uniform overcast sky." << std::endl;
61 } else {
62
63 const char *diffuse_extinction_coeff_str = node.child_value();
64 if (!parse_float(diffuse_extinction_coeff_str, diffuse_extinction_coeff)) {
65 helios_runtime_error("ERROR: Value given for 'diffuse_extinction_coeff' could not be parsed.");
66 } else if (diffuse_extinction_coeff < 0) {
67 helios_runtime_error("ERROR: Value given for 'diffuse_extinction_coeff' must be greater than or equal to 0.");
68 }
69 }
70 context_ptr->setGlobalData("diffuse_extinction_coeff", diffuse_extinction_coeff);
71
72 int scattering_depth = 0;
73 node = radiation_block.child("scattering_depth");
74 if (!node.empty()) {
75
76 const char *scattering_depth_str = node.child_value();
77 if (!parse_int(scattering_depth_str, scattering_depth)) {
78 helios_runtime_error("ERROR: Value given for 'scattering_depth' could not be parsed.");
79 } else if (scattering_depth < 0) {
80 helios_runtime_error("ERROR: Value given for 'scattering_depth' must be greater than or equal to 0.");
81 }
82 }
83
84 float air_turbidity = 0;
85 node = radiation_block.child("air_turbidity");
86 if (!node.empty()) {
87
88 const char *air_turbidity_str = node.child_value();
89
90 // first try parsing as a float to see if an actual turbidity value was specified
91 if (!parse_float(air_turbidity_str, air_turbidity)) {
92
93 // if parsing fails, try parsing as a string to see if 'calibrate' was specified
94 if (trim_whitespace(std::string(air_turbidity_str)) == "calibrate") {
95 air_turbidity = -1; // set to -1 to indicate calibration mode
96 } else {
97 helios_runtime_error("ERROR: Value given for 'air_turbidity' could not be parsed.");
98 }
99 } else if (air_turbidity < 0) {
100 helios_runtime_error("ERROR: Value given for 'air_turbidity' must be greater than or equal to 0.");
101 }
102 }
103
104 // *** Loading any XML files needed for spectra *** //
105
106 for (pugi::xml_node p = radiation_block.child("load_xml_library_file"); p; p = p.next_sibling("load_xml_library_file")) {
107
108 const char *xml_library_file_str = p.child_value();
109 std::string xml_library_file = trim_whitespace(std::string(xml_library_file_str));
110
111 if (xml_library_file.empty() || !std::filesystem::exists(xml_library_file)) {
112 std::cout << "WARNING: Could not find XML library file: " + xml_library_file << ". Skipping..." << std::endl;
113 continue;
114 }
115
116 context_ptr->loadXML(xml_library_file.c_str());
117 }
118
119 // *** Spectral data *** //
120
121 std::string solar_direct_spectrum;
122 node = radiation_block.child("solar_direct_spectrum");
123 if (!node.empty()) {
124
125 const char *solar_direct_spectrum_str = node.child_value();
126 solar_direct_spectrum = trim_whitespace(std::string(solar_direct_spectrum_str));
127 }
128
129 std::string leaf_reflectivity_spectrum;
130 node = radiation_block.child("leaf_reflectivity_spectrum");
131 if (!node.empty()) {
132
133 const char *leaf_reflectivity_spectrum_str = node.child_value();
134 leaf_reflectivity_spectrum = trim_whitespace(std::string(leaf_reflectivity_spectrum_str));
135 }
136
137 std::string leaf_transmissivity_spectrum;
138 node = radiation_block.child("leaf_transmissivity_spectrum");
139 if (!node.empty()) {
140
141 const char *leaf_transmissivity_spectrum_str = node.child_value();
142 leaf_transmissivity_spectrum = trim_whitespace(std::string(leaf_transmissivity_spectrum_str));
143 }
144
145 float leaf_emissivity = -1.f;
146 node = radiation_block.child("leaf_emissivity");
147 if (!node.empty()) {
148
149 const char *leaf_emissivity_str = node.child_value();
150 if (!parse_float(leaf_emissivity_str, leaf_emissivity)) {
151 helios_runtime_error("ERROR: Value given for 'leaf_emissivity' could not be parsed.");
152 } else if (leaf_emissivity < 0 || leaf_emissivity > 1.f) {
153 helios_runtime_error("ERROR: Value given for 'leaf_emissivity' must be between 0 and 1.");
154 }
155 }
156
157 std::string ground_reflectivity_spectrum;
158 node = radiation_block.child("ground_reflectivity_spectrum");
159 if (!node.empty()) {
160
161 const char *ground_reflectivity_spectrum_str = node.child_value();
162 ground_reflectivity_spectrum = trim_whitespace(std::string(ground_reflectivity_spectrum_str));
163 }
164
165 float ground_emissivity = -1.f;
166 node = radiation_block.child("ground_emissivity");
167 if (!node.empty()) {
168
169 const char *ground_emissivity_str = node.child_value();
170 if (!parse_float(ground_emissivity_str, ground_emissivity)) {
171 helios_runtime_error("ERROR: Value given for 'ground_emissivity' could not be parsed.");
172 } else if (ground_emissivity < 0 || ground_emissivity > 1.f) {
173 helios_runtime_error("ERROR: Value given for 'ground_emissivity' must be between 0 and 1.");
174 }
175 }
176
177 // *** Set up simulation *** //
178
179 radiation_ptr->addRadiationBand("PAR", 400, 700);
180 radiation_ptr->disableEmission("PAR");
181 radiation_ptr->addRadiationBand("NIR", 701, 2500);
182 radiation_ptr->disableEmission("NIR");
183 radiation_ptr->addRadiationBand("LW");
184
185 uint sun_ID = radiation_ptr->addSunSphereRadiationSource();
186 context_ptr->setGlobalData("sun_ID", sun_ID);
187
188 if (direct_ray_count > 0) {
189 radiation_ptr->setDirectRayCount("PAR", direct_ray_count);
190 radiation_ptr->setDirectRayCount("NIR", direct_ray_count);
191 }
192
193 if (diffuse_ray_count > 0) {
194 radiation_ptr->setDiffuseRayCount("PAR", diffuse_ray_count);
195 radiation_ptr->setDiffuseRayCount("NIR", diffuse_ray_count);
196 radiation_ptr->setDiffuseRayCount("LW", diffuse_ray_count);
197 }
198
199 if (scattering_depth > 0) {
200 radiation_ptr->setScatteringDepth("PAR", scattering_depth);
201 radiation_ptr->setScatteringDepth("NIR", scattering_depth);
202 } else {
203 std::cout << "WARNING: No value given for 'scattering_depth'. All objects will be assumed to be black." << std::endl;
204 }
205
206 if (air_turbidity > 0) {
207 context_ptr->setGlobalData("air_turbidity", air_turbidity);
208 } else if (air_turbidity < 0) { // try calibration
209 if (context_ptr->doesTimeseriesVariableExist("net_radiation")) {
210 air_turbidity = solarposition_ptr->calibrateTurbidityFromTimeseries("net_radiation");
211 if (air_turbidity > 0 && air_turbidity < 1) {
212 context_ptr->setGlobalData("air_turbidity", air_turbidity);
213 }
214 }
215 }
216 if (!context_ptr->doesGlobalDataExist("air_turbidity")) {
217 std::cout << "WARNING: Air turbidity could not be determined. Setting to a default value of 0.05." << std::endl;
218 context_ptr->setGlobalData("air_turbidity", 0.05f);
219 }
220
221 if (!solar_direct_spectrum.empty()) {
222
223 if (solar_direct_spectrum == "ASTMG173" || solar_direct_spectrum == "solar_spectrum_direct_ASTMG173") {
224 solar_direct_spectrum = "solar_spectrum_direct_ASTMG173";
225 context_ptr->loadXML("plugins/radiation/spectral_data/solar_spectrum_ASTMG173.xml", true);
226 } else if (!context_ptr->doesGlobalDataExist(solar_direct_spectrum.c_str())) {
227 helios_runtime_error("ERROR: The specified solar direct spectrum '" + solar_direct_spectrum + "' could not be found in existing global data. Make sure to load the XML file containing this spectral data.");
228 }
229
230 radiation_ptr->setSourceSpectrum(sun_ID, solar_direct_spectrum);
231 } else {
232 std::cout << "WARNING: No value given for 'solar_direct_spectrum'. Using a uniform spectral distribution." << std::endl;
233 }
234
235 std::vector<uint> leaf_UUIDs;
236 try {
237 // assert( context_ptr->doesGlobalDataExist( "leaf_UUIDs" ) );
238 context_ptr->getGlobalData("leaf_UUIDs", leaf_UUIDs);
239 } catch (...) {
240 std::cout << "WARNING: No leaf UUIDs found." << std::endl;
241 }
242
243 std::vector<uint> ground_UUIDs;
244 try {
245 // assert( context_ptr->doesGlobalDataExist( "ground_UUIDs" ) );
246 context_ptr->getGlobalData("ground_UUIDs", ground_UUIDs);
247 } catch (...) {
248 std::cout << "WARNING: No ground UUIDs found." << std::endl;
249 }
250
251 if (!leaf_UUIDs.empty()) {
252 if (!leaf_reflectivity_spectrum.empty()) {
253 context_ptr->setPrimitiveData(leaf_UUIDs, "reflectivity_spectrum", leaf_reflectivity_spectrum);
254 } else {
255 std::cout << "WARNING: No value given for 'leaf_reflectivity_spectrum'. Assuming leaves are black across all shortwave bands." << std::endl;
256 }
257
258 if (!leaf_transmissivity_spectrum.empty()) {
259 context_ptr->setPrimitiveData(leaf_UUIDs, "transmissivity_spectrum", leaf_transmissivity_spectrum);
260 } else {
261 std::cout << "WARNING: No value given for 'leaf_transmissivity_spectrum'. Assuming leaves are black across all shortwave bands." << std::endl;
262 }
263
264 if (leaf_emissivity >= 0.f && leaf_emissivity <= 1.f) {
265 context_ptr->setPrimitiveData(leaf_UUIDs, "emissivity", leaf_emissivity);
266 } else {
267 std::cout << "WARNING: No value given for 'leaf_emissivity'. Assuming leaves are perfect emitters." << std::endl;
268 }
269 }
270
271 if (!ground_UUIDs.empty()) {
272 if (!ground_reflectivity_spectrum.empty()) {
273 if (context_ptr->doesGlobalDataExist(ground_reflectivity_spectrum.c_str())) {
274 context_ptr->setPrimitiveData(ground_UUIDs, "reflectivity_spectrum", ground_reflectivity_spectrum);
275 } else {
276 std::cout << "WARNING: The specified ground reflectivity spectrum '" + ground_reflectivity_spectrum + "' could not be found in existing global data. Assuming the ground is black across all shortwave bands." << std::endl;
277 }
278 } else {
279 std::cout << "WARNING: No value given for 'ground_reflectivity_spectrum'. Assuming the ground is black across all shortwave bands." << std::endl;
280 }
281
282 if (ground_emissivity >= 0.f && ground_emissivity <= 1.f) {
283 context_ptr->setPrimitiveData(ground_UUIDs, "emissivity", ground_emissivity);
284 } else {
285 std::cout << "WARNING: No value given for 'ground_emissivity'. Assuming ground is a perfect emitter." << std::endl;
286 }
287 }
288 radiation_ptr->updateGeometry();
289 }
290
291 if (radiation_block_count == 0) {
292 context_ptr->setGlobalData("radiation_enabled", false);
293 } else {
294 context_ptr->setGlobalData("radiation_enabled", true);
295 }
296}