htsky

Load and structure a vertically stratified atmosphere
git clone git://git.meso-star.fr/htsky.git
Log | Files | Refs | README | LICENSE

commit b8624878c2def4826afd1afd90c2a0d49908bdd3
parent c8c0b159392054cb6fb15a28a36662ff6da7a49e
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Thu, 12 Mar 2020 15:36:12 +0100

Add long waves support

Diffstat:
Msrc/htsky.c | 437++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/htsky.h | 23+++++++++++++++++++----
Msrc/htsky_atmosphere.c | 90++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------------
Msrc/htsky_c.h | 11++++++-----
Msrc/htsky_cloud.c | 130++++++++++++++++++++++++++++++++++++++++++++++++++++----------------------------
Msrc/htsky_dump_cloud_vtk.c | 20++++++++++++--------
Msrc/htsky_svx.c | 18+++++++++---------
7 files changed, 524 insertions(+), 205 deletions(-)

diff --git a/src/htsky.c b/src/htsky.c @@ -38,6 +38,11 @@ #include <omp.h> +/* Current version the cache structure. One should increment it and perform a + * version management onto serialized data when the cache data data structure + * is updated. */ +static const int CACHE_VERSION = 0; + /******************************************************************************* * Helper function ******************************************************************************/ @@ -55,48 +60,55 @@ check_args(const struct htsky_args* args) } static res_T -setup_sw_bands_properties(struct htsky* sky) +setup_bands_properties(struct htsky* sky) { - res_T res = RES_OK; size_t nbands; - size_t i; + size_t iband; + res_T res = RES_OK; ASSERT(sky); - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); ASSERT(nbands); - sky->sw_bands = MEM_CALLOC(sky->allocator, nbands, sizeof(*sky->sw_bands)); - if(!sky->sw_bands) { - log_err(sky, "could not allocate the list of SW band properties.\n"); + + sky->bands = MEM_CALLOC(sky->allocator, nbands, sizeof(*sky->bands)); + if(!sky->bands) { + log_err(sky, "could not allocate the list of %s band properties.\n", + sky->is_long_wave ? "long wave" : "short wave"); res = RES_MEM_ERR; goto error; } - FOR_EACH(i, 0, nbands) { + FOR_EACH(iband, sky->bands_range[0], sky->bands_range[1]+1) { struct htgop_spectral_interval band; double band_wlens[2]; + const size_t i = iband - sky->bands_range[0]; - HTGOP(get_sw_spectral_interval(sky->htgop, i+sky->sw_bands_range[0], &band)); + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } band_wlens[0] = wavenumber_to_wavelength(band.wave_numbers[1]); band_wlens[1] = wavenumber_to_wavelength(band.wave_numbers[0]); ASSERT(band_wlens[0] < band_wlens[1]); - sky->sw_bands[i].Ca_avg = htmie_compute_xsection_absorption_average + sky->bands[i].Ca_avg = htmie_compute_xsection_absorption_average (sky->htmie, band_wlens, HTMIE_FILTER_LINEAR); - sky->sw_bands[i].Cs_avg = htmie_compute_xsection_scattering_average + sky->bands[i].Cs_avg = htmie_compute_xsection_scattering_average (sky->htmie, band_wlens, HTMIE_FILTER_LINEAR); - sky->sw_bands[i].g_avg = htmie_compute_asymmetry_parameter_average + sky->bands[i].g_avg = htmie_compute_asymmetry_parameter_average (sky->htmie, band_wlens, HTMIE_FILTER_LINEAR); - ASSERT(sky->sw_bands[i].Ca_avg > 0); - ASSERT(sky->sw_bands[i].Cs_avg > 0); - ASSERT(sky->sw_bands[i].g_avg > 0); + ASSERT(sky->bands[i].Ca_avg > 0); + ASSERT(sky->bands[i].Cs_avg > 0); + ASSERT(sky->bands[i].g_avg > 0); } exit: return res; error: - if(sky->sw_bands) { - MEM_RM(sky->allocator, sky->sw_bands); - sky->sw_bands = NULL; + if(sky->bands) { + MEM_RM(sky->allocator, sky->bands); + sky->bands = NULL; } goto exit; } @@ -123,6 +135,139 @@ sample_sw_spectral_data HTGOP(spectral_interval_sample_quadrature(&specint, r1, iquadrature_pt)); } +static INLINE double +particle_fetch_raw_property + (const struct htsky* sky, + const enum htsky_property prop, + const size_t iband, + const size_t iquad, + const size_t ivox[3]) +{ + double rho_da = 0; /* Dry air density */ + double rct = 0; /* #droplets in kg of water per kg of dry air */ + double ql = 0; /* Droplet density In kg.m^-3 */ + double Ca = 0; /* Massic absorption cross section in m^2.kg^-1 */ + double Cs = 0; /* Massic scattering cross section in m^2.kg^-1 */ + double k_particle = 0; + size_t i = 0; + (void)iquad; + ASSERT(sky && ivox); + + /* Compute he dry air density */ + rho_da = cloud_dry_air_density(&sky->htcp_desc, ivox); + + /* Compute the droplet density */ + rct = htcp_desc_RCT_at(&sky->htcp_desc, ivox[0], ivox[1], ivox[2], 0); + ql = rho_da * rct; + + i = iband - sky->bands_range[0]; + + /* Use the average cross section of the current spectral band */ + if(prop == HTSKY_Ka || prop == HTSKY_Kext) Ca = sky->bands[i].Ca_avg; + if(prop == HTSKY_Ks || prop == HTSKY_Kext) Cs = sky->bands[i].Cs_avg; + + k_particle = ql*(Ca + Cs); + return k_particle; +} + +static INLINE double +gas_fetch_raw_property + (const struct htsky* sky, + const enum htsky_property prop, + const size_t iband, + const size_t iquad, + const int in_clouds, + const double pos[3], + const size_t ivox[3]) +{ + struct htgop_layer layer; + size_t ilayer = 0; + double k_gas = 0; + ASSERT(sky && pos && ivox); + + /* Retrieve the quadrature point into the spectral band of the layer into + * which `pos' lies */ + HTGOP(position_to_layer_id(sky->htgop, pos[2], &ilayer)); + HTGOP(get_layer(sky->htgop, ilayer, &layer)); + + if(sky->is_long_wave) { + struct htgop_layer_lw_spectral_interval band; + HTGOP(layer_get_lw_spectral_interval(&layer, iband, &band)); + + if(!in_clouds) { + /* Pos is outside the clouds. Directly fetch the nominal optical + * properties */ + ASSERT(iquad < band.quadrature_length); + switch(prop) { + case HTSKY_Ka: + case HTSKY_Kext: + k_gas = band.ka_nominal[iquad]; + break; + case HTSKY_Ks: k_gas = 0; break; + default: FATAL("Unreachable code.\n"); break; + } + } else { + /* Pos is inside the clouds. Compute the water vapor molar fraction at + * the current voxel */ + const double x_h2o = cloud_water_vapor_molar_fraction(&sky->htcp_desc, ivox); + struct htgop_layer_lw_spectral_interval_tab tab; + + /* Retrieve the tabulated data for the quadrature point */ + HTGOP(layer_lw_spectral_interval_get_tab(&band, iquad, &tab)); + + /* Fetch the optical properties wrt x_h2o */ + switch(prop) { + case HTSKY_Ka: + case HTSKY_Kext: + HTGOP(layer_lw_spectral_interval_tab_fetch_ka(&tab, x_h2o, &k_gas)); + break; + case HTSKY_Ks: k_gas = 0; break; + default: FATAL("Unreachable code.\n"); break; + } + } + } else { + struct htgop_layer_sw_spectral_interval band; + HTGOP(layer_get_sw_spectral_interval(&layer, iband, &band)); + + if(!in_clouds) { + /* Pos is outside the clouds. Directly fetch the nominal optical + * properties */ + ASSERT(iquad < band.quadrature_length); + switch(prop) { + case HTSKY_Ka: k_gas = band.ka_nominal[iquad]; break; + case HTSKY_Ks: k_gas = band.ks_nominal[iquad]; break; + case HTSKY_Kext: + k_gas = band.ka_nominal[iquad] + band.ks_nominal[iquad]; + break; + default: FATAL("Unreachable code.\n"); break; + } + } else { + /* Pos is inside the clouds. Compute the water vapor molar fraction at + * the current voxel */ + const double x_h2o = cloud_water_vapor_molar_fraction(&sky->htcp_desc, ivox); + struct htgop_layer_sw_spectral_interval_tab tab; + + /* Retrieve the tabulated data for the quadrature point */ + HTGOP(layer_sw_spectral_interval_get_tab(&band, iquad, &tab)); + + /* Fetch the optical properties wrt x_h2o */ + switch(prop) { + case HTSKY_Ka: + HTGOP(layer_sw_spectral_interval_tab_fetch_ka(&tab, x_h2o, &k_gas)); + break; + case HTSKY_Ks: + HTGOP(layer_sw_spectral_interval_tab_fetch_ks(&tab, x_h2o, &k_gas)); + break; + case HTSKY_Kext: + HTGOP(layer_sw_spectral_interval_tab_fetch_kext(&tab, x_h2o, &k_gas)); + break; + default: FATAL("Unreachable code.\n"); break; + } + } + } + return k_gas; +} + static res_T setup_cache_stream (struct htsky* sky, @@ -190,18 +335,24 @@ setup_cache_stream goto error; \ } \ } (void)0 + WRITE(&CACHE_VERSION, 1); WRITE(&htcp_statbuf.st_ino, 1); WRITE(&htcp_statbuf.st_mtim, 1); WRITE(&htgop_statbuf.st_ino, 1); WRITE(&htgop_statbuf.st_mtim, 1); WRITE(&htmie_statbuf.st_ino, 1); WRITE(&htmie_statbuf.st_mtim, 1); + WRITE(&sky->is_long_wave, 1); + WRITE(sky->bands_range, 2); #undef WRITE CHK(fflush(fp) == 0); } else { struct stat htcp_statbuf2; struct stat htgop_statbuf2; struct stat htmie_statbuf2; + int cache_version; + int is_long_wave; + double bands_range[2]; /* Read the cache header */ #define READ(Var, N) { \ @@ -217,12 +368,22 @@ setup_cache_stream goto error; \ } \ } (void)0 + READ(&cache_version, 1); + if(cache_version != CACHE_VERSION) { + log_err(sky, + "%s: invalid cache in version %d. Expecting a cache in version %d.\n", + cache_filename, cache_version, CACHE_VERSION); + res = RES_BAD_ARG; + goto error; + } READ(&htcp_statbuf2.st_ino, 1); READ(&htcp_statbuf2.st_mtim, 1); READ(&htgop_statbuf2.st_ino, 1); READ(&htgop_statbuf2.st_mtim, 1); READ(&htmie_statbuf2.st_ino, 1); READ(&htmie_statbuf2.st_mtim, 1); + READ(&is_long_wave, 1); + READ(bands_range, 2); #undef READ /* Compare the cache header with the input file status to check that the @@ -241,6 +402,17 @@ setup_cache_stream CHK_STAT(&htgop_statbuf, &htgop_statbuf2); CHK_STAT(&htmie_statbuf, &htmie_statbuf2); #undef CHK_STAT + + /* Compare the handled spectral bands with the bands to handled to check + * that the cached octress are the expected ones */ + if(is_long_wave != sky->is_long_wave + || bands_range[0] != sky->bands_range[0] + || bands_range[1] != sky->bands_range[1]) { + log_err(sky, "%s: invalid cache regarding the wavelengths to handle.\n", + cache_filename); + res = RES_BAD_ARG; + goto error; + } } exit: @@ -269,7 +441,7 @@ release_sky(ref_T* ref) if(sky->htcp) HTCP(ref_put(sky->htcp)); if(sky->htgop) HTGOP(ref_put(sky->htgop)); if(sky->htmie) HTMIE(ref_put(sky->htmie)); - if(sky->sw_bands) MEM_RM(sky->allocator, sky->sw_bands); + if(sky->bands) MEM_RM(sky->allocator, sky->bands); darray_split_release(&sky->svx2htcp_z); str_release(&sky->name); ASSERT(MEM_ALLOCATED_SIZE(&sky->svx_allocator) == 0); @@ -324,8 +496,8 @@ htsky_create sky->is_cloudy = args->htcp_filename != NULL; darray_split_init(sky->allocator, &sky->svx2htcp_z); str_init(sky->allocator, &sky->name); - sky->sw_bands_range[0] = 1; - sky->sw_bands_range[1] = 0; + sky->bands_range[0] = 1; + sky->bands_range[1] = 0; sky->nthreads = MMIN(args->nthreads, (unsigned)nthreads_max); if(logger) { @@ -368,9 +540,19 @@ htsky_create goto error; } - /* Fetch short wave bands range */ - res = htgop_get_sw_spectral_intervals_CIE_XYZ(sky->htgop, sky->sw_bands_range); - if(res != RES_OK) goto error; + /* If the long wave range is degenerated use the default wavelength range, + * i.e. the short wave wavelengths of the CIE XYZ color space */ + if(args->wlen_lw_range[0] > args->wlen_lw_range[1]) { + res = htgop_get_sw_spectral_intervals_CIE_XYZ(sky->htgop, sky->bands_range); + if(res != RES_OK) goto error; + } else { + double wnums[2]; + wnums[0] = wavelength_to_wavenumber(args->wlen_lw_range[1]); + wnums[1] = wavelength_to_wavenumber(args->wlen_lw_range[0]); + res = htgop_get_lw_spectral_intervals(sky->htgop, wnums, sky->bands_range); + if(res != RES_OK) goto error; + sky->is_long_wave = 1; + } /* Setup the atmopshere */ time_current(&t0); @@ -407,7 +589,8 @@ htsky_create goto error; } - res = setup_sw_bands_properties(sky); + /* Setup the properties of the Short/Long wave bands */ + res = setup_bands_properties(sky); if(res != RES_OK) goto error; /* Load clouds properties */ @@ -484,14 +667,14 @@ htsky_fetch_particle_phase_function_asymmetry_parameter { size_t i; ASSERT(sky); - ASSERT(ispectral_band >= sky->sw_bands_range[0]); - ASSERT(ispectral_band <= sky->sw_bands_range[1]); + ASSERT(ispectral_band >= sky->bands_range[0]); + ASSERT(ispectral_band <= sky->bands_range[1]); (void)iquad; if(!sky->is_cloudy) { return 0; } else { - i = ispectral_band - sky->sw_bands_range[0]; - return sky->sw_bands[i].g_avg; + i = ispectral_band - sky->bands_range[0]; + return sky->bands[i].g_avg; } } @@ -518,11 +701,11 @@ htsky_fetch_raw_property double k_gas = 0; double k = 0; ASSERT(sky && pos); - ASSERT(iband >= sky->sw_bands_range[0]); - ASSERT(iband <= sky->sw_bands_range[1]); + ASSERT(iband >= sky->bands_range[0]); + ASSERT(iband <= sky->bands_range[1]); ASSERT(comp_mask & HTSKY_CPNT_MASK_ALL); - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; cloud_desc = sky->is_cloudy ? &sky->clouds[i][iquad].octree_desc : NULL; atmosphere_desc = &sky->atmosphere[i][iquad].bitree_desc; ASSERT(atmosphere_desc->frame[0] == SVX_AXIS_Z); @@ -580,111 +763,139 @@ htsky_fetch_raw_property } if(comp_mask & HTSKY_CPNT_FLAG_PARTICLES) { - double rho_da = 0; /* Dry air density */ - double rct = 0; /* #droplets in kg of water per kg of dry air */ - double ql = 0; /* Droplet density In kg.m^-3 */ - double Ca = 0; /* Massic absorption cross section in m^2.kg^-1 */ - double Cs = 0; /* Massic scattering cross section in m^2.kg^-1 */ - ASSERT(in_clouds); + k_particle = particle_fetch_raw_property(sky, prop, iband, iquad, ivox); + } + if(comp_mask & HTSKY_CPNT_FLAG_GAS) { + k_gas = gas_fetch_raw_property + (sky, prop, iband, iquad, in_clouds, pos, ivox); + } + k = k_particle + k_gas; + ASSERT(k >= k_min && k <= k_max); + (void)k_min, (void)k_max; + return k; +} - /* Compute he dry air density */ - rho_da = cloud_dry_air_density(&sky->htcp_desc, ivox); +double +htsky_fetch_temperature(const struct htsky* sky, const double pos[3]) +{ + double temperature = 0; + struct htgop_level lvl0, lvl1; + size_t nlvls = 0; + int in_clouds = 0; + int in_atmosphere = 0; + ASSERT(sky && pos); - /* Compute the droplet density */ - rct = htcp_desc_RCT_at(&sky->htcp_desc, ivox[0], ivox[1], ivox[2], 0); - ql = rho_da * rct; + /* Is the position inside the atmosphere */ + HTGOP(get_levels_count(sky->htgop, &nlvls)); + ASSERT(nlvls > 1); + HTGOP(get_level(sky->htgop, 0, &lvl0)); + HTGOP(get_level(sky->htgop, nlvls-1, &lvl1)); + in_atmosphere = pos[2] >= lvl0.height && pos[2] <= lvl1.height; - /* Use the average cross section of the current spectral band */ - if(prop == HTSKY_Ka || prop == HTSKY_Kext) Ca = sky->sw_bands[i].Ca_avg; - if(prop == HTSKY_Ks || prop == HTSKY_Kext) Cs = sky->sw_bands[i].Cs_avg; + /* Is the position inside the clouds? */ + if(!sky->is_cloudy) { + in_clouds = 0; + } else if(sky->repeat_clouds) { + in_clouds = + pos[2] >= sky->htcp_desc.lower[2] + && pos[2] <= sky->htcp_desc.upper[2]; + } else { + in_clouds = + pos[0] >= sky->htcp_desc.lower[0] + && pos[1] >= sky->htcp_desc.lower[1] + && pos[2] >= sky->htcp_desc.lower[2] + && pos[0] <= sky->htcp_desc.upper[0] + && pos[1] <= sky->htcp_desc.upper[1] + && pos[2] <= sky->htcp_desc.upper[2]; + } - k_particle = ql*(Ca + Cs); + if(in_clouds) { + /* Clouds have priority on atmosphere */ + in_atmosphere = 0; } - if(comp_mask & HTSKY_CPNT_FLAG_GAS) { - struct htgop_layer layer; - struct htgop_layer_sw_spectral_interval band; - size_t ilayer = 0; - ASSERT(in_atmosphere); + if(in_atmosphere) { + double u; + size_t ilayer; - /* Retrieve the quadrature point into the spectral band of the layer into - * which `pos' lies */ + /* Find the layer into which pos is included */ HTGOP(position_to_layer_id(sky->htgop, pos[2], &ilayer)); - HTGOP(get_layer(sky->htgop, ilayer, &layer)); - HTGOP(layer_get_sw_spectral_interval(&layer, iband, &band)); + ASSERT(ilayer < nlvls-1); - if(!in_clouds) { - /* Pos is outside the clouds. Directly fetch the nominal optical - * properties */ - ASSERT(iquad < band.quadrature_length); - switch(prop) { - case HTSKY_Ka: k_gas = band.ka_nominal[iquad]; break; - case HTSKY_Ks: k_gas = band.ks_nominal[iquad]; break; - case HTSKY_Kext: - k_gas = band.ka_nominal[iquad] + band.ks_nominal[iquad]; - break; - default: FATAL("Unreachable code.\n"); break; - } - } else { - /* Pos is inside the clouds. Compute the water vapor molar fraction at - * the current voxel */ - const double x_h2o = cloud_water_vapor_molar_fraction(&sky->htcp_desc, ivox); - struct htgop_layer_sw_spectral_interval_tab tab; + /* Fetch the levels enclosing the current layer */ + HTGOP(get_level(sky->htgop, ilayer+0, &lvl0)); + HTGOP(get_level(sky->htgop, ilayer+1, &lvl1)); + ASSERT(lvl0.height < lvl1.height); + ASSERT(lvl0.height <= pos[2] && pos[2] <= lvl1.height); - /* Retrieve the tabulated data for the quadrature point */ - HTGOP(layer_sw_spectral_interval_get_tab(&band, iquad, &tab)); + /* Linearly interpolate the temperature of the levels into which pos lies */ + u = (pos[2] - lvl0.height) / (lvl1.height - lvl0.height); + temperature = u * (lvl1.temperature - lvl0.temperature) + lvl0.temperature; - /* Fetch the optical properties wrt x_h2o */ - switch(prop) { - case HTSKY_Ka: - HTGOP(layer_sw_spectral_interval_tab_fetch_ka(&tab, x_h2o, &k_gas)); - break; - case HTSKY_Ks: - HTGOP(layer_sw_spectral_interval_tab_fetch_ks(&tab, x_h2o, &k_gas)); - break; - case HTSKY_Kext: - HTGOP(layer_sw_spectral_interval_tab_fetch_kext(&tab, x_h2o, &k_gas)); - break; - default: FATAL("Unreachable code.\n"); break; - } + } else if(in_clouds) { + const struct htcp_desc* desc = &sky->htcp_desc; + size_t ivox[3]; + double pos_cs[3]; + + /* Transform the submitted position in local cloud space */ + world_to_cloud(sky, pos, pos_cs); + + /* Compute the index of the voxel to fetch */ + ivox[0] = (size_t)((pos_cs[0] - desc->lower[0])/desc->vxsz_x); + ivox[1] = (size_t)((pos_cs[1] - desc->lower[1])/desc->vxsz_y); + if(!desc->irregular_z) { + /* The voxels along the Z dimension have the same size */ + ivox[2] = (size_t)((pos_cs[2] - desc->lower[2])/desc->vxsz_z[0]); + } else { + /* Irregular voxel size along the Z dimension. Compute the index of the Z + * position in the svx2htcp_z Look Up Table and use the LUT to define the + * voxel index into the HTCP descripptor */ + const struct split* splits = darray_split_cdata_get(&sky->svx2htcp_z); + const size_t ilut = (size_t)((pos_cs[2] - desc->lower[2]) / sky->lut_cell_sz); + ivox[2] = splits[ilut].index + (pos_cs[2] > splits[ilut].height); } + + /* Fetch the cloud temperature */ + temperature = htcp_desc_T_at(desc, ivox[0], ivox[1], ivox[2], 0); } - k = k_particle + k_gas; - ASSERT(k >= k_min && k <= k_max); - (void)k_min, (void)k_max; - return k; + return temperature; } size_t -htsky_get_sw_spectral_bands_count(const struct htsky* sky) +htsky_get_spectral_bands_count(const struct htsky* sky) { - ASSERT(sky && sky->sw_bands_range[0] <= sky->sw_bands_range[1]); - return sky->sw_bands_range[1] - sky->sw_bands_range[0] + 1; + ASSERT(sky && sky->bands_range[0] <= sky->bands_range[1]); + return sky->bands_range[1] - sky->bands_range[0] + 1; } size_t -htsky_get_sw_spectral_band_id +htsky_get_spectral_band_id (const struct htsky* sky, const size_t i) { - ASSERT(sky && i < htsky_get_sw_spectral_bands_count(sky)); - return sky->sw_bands_range[0] + i; + ASSERT(sky); + ASSERT(i < htsky_get_spectral_bands_count(sky)); + return sky->bands_range[0] + i; } size_t -htsky_get_sw_spectral_band_quadrature_length +htsky_get_spectral_band_quadrature_length (const struct htsky* sky, const size_t iband) { struct htgop_spectral_interval band; ASSERT(sky); - ASSERT(iband >= sky->sw_bands_range[0]); - ASSERT(iband <= sky->sw_bands_range[1]); - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + ASSERT(iband >= sky->bands_range[0]); + ASSERT(iband <= sky->bands_range[1]); + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } return band.quadrature_length; } res_T -htsky_get_sw_spectral_band_bounds +htsky_get_spectral_band_bounds (const struct htsky* sky, const size_t iband, double wavelengths[2]) @@ -693,15 +904,26 @@ htsky_get_sw_spectral_band_bounds res_T res = RES_OK; ASSERT(sky && wavelengths); - res = htgop_get_sw_spectral_interval(sky->htgop, iband, &specint); - if(res != RES_OK) return res; - + if(sky->is_long_wave) { + res = htgop_get_lw_spectral_interval(sky->htgop, iband, &specint); + if(res != RES_OK) return res; + } else { + res = htgop_get_sw_spectral_interval(sky->htgop, iband, &specint); + if(res != RES_OK) return res; + } wavelengths[0] = wavenumber_to_wavelength(specint.wave_numbers[1]); wavelengths[1] = wavenumber_to_wavelength(specint.wave_numbers[0]); ASSERT(wavelengths[0] < wavelengths[1]); return RES_OK; } +int +htsky_is_long_wave(const struct htsky* htsky) +{ + ASSERT(htsky); + return htsky->is_long_wave; +} + void htsky_sample_sw_spectral_data_CIE_1931_X (const struct htsky* sky, @@ -710,6 +932,7 @@ htsky_sample_sw_spectral_data_CIE_1931_X size_t* ispectral_band, size_t* iquadrature_pt) { + ASSERT(!sky->is_long_wave); sample_sw_spectral_data (sky->htgop, r0, r1, htgop_sample_sw_spectral_interval_CIE_1931_X, ispectral_band, iquadrature_pt); @@ -723,6 +946,7 @@ htsky_sample_sw_spectral_data_CIE_1931_Y size_t* ispectral_band, size_t* iquadrature_pt) { + ASSERT(!sky->is_long_wave); sample_sw_spectral_data (sky->htgop, r0, r1, htgop_sample_sw_spectral_interval_CIE_1931_Y, ispectral_band, iquadrature_pt); @@ -736,6 +960,7 @@ htsky_sample_sw_spectral_data_CIE_1931_Z size_t* ispectral_band, size_t* iquadrature_pt) { + ASSERT(!sky->is_long_wave); sample_sw_spectral_data (sky->htgop, r0, r1, htgop_sample_sw_spectral_interval_CIE_1931_Z, ispectral_band, iquadrature_pt); diff --git a/src/htsky.h b/src/htsky.h @@ -69,6 +69,7 @@ struct htsky_args { const char* htmie_filename; const char* cache_filename; /* May be NULL <=> no cached data structure */ const char* name; /* Name of the sky. Used by the Star-MTL binding */ + double wlen_lw_range[2]; /* Long wave wavelength range to handle. In nm */ unsigned grid_max_definition[3]; /* Maximum definition of the grid */ double optical_thickness; /* Threshold used during octree building */ unsigned nthreads; /* Hint on the number of threads to use */ @@ -82,6 +83,7 @@ struct htsky_args { NULL, /* htmie filename */ \ NULL, /* cache filename */ \ "sky", /* Name */ \ + {DBL_MAX,-DBL_MAX}, /* Long wave wavelengths. Degenerated <=> short wave */ \ {UINT_MAX, UINT_MAX, UINT_MAX}, /* Maximum definition of the grid */ \ 1, /* Optical thickness a*/ \ (unsigned)~0, /* #threads */ \ @@ -142,6 +144,11 @@ htsky_fetch_raw_property const double k_max); HTSKY_API double +htsky_fetch_temperature + (const struct htsky* sky, + const double pos[3]); + +HTSKY_API double htsky_fetch_svx_property (const struct htsky* sky, const enum htsky_property prop, @@ -175,25 +182,33 @@ htsky_trace_ray struct svx_hit* hit); HTSKY_API size_t -htsky_get_sw_spectral_bands_count +htsky_get_spectral_bands_count (const struct htsky* sky); HTSKY_API size_t -htsky_get_sw_spectral_band_id +htsky_get_lw_spectral_bands_count + (const struct htsky* sky); + +HTSKY_API size_t +htsky_get_spectral_band_id (const struct htsky* sky, const size_t i); HTSKY_API size_t -htsky_get_sw_spectral_band_quadrature_length +htsky_get_spectral_band_quadrature_length (const struct htsky* sky, const size_t iband); HTSKY_API res_T -htsky_get_sw_spectral_band_bounds +htsky_get_spectral_band_bounds (const struct htsky* sky, const size_t iband, double wavelengths[2]); +HTSKY_API int +htsky_is_long_wave + (const struct htsky* sky); + HTSKY_API void htsky_sample_sw_spectral_data_CIE_1931_X (const struct htsky* sky, diff --git a/src/htsky_atmosphere.c b/src/htsky_atmosphere.c @@ -58,27 +58,53 @@ atmosphere_vox_get(const size_t xyz[3], void* dst, void* context) ka_max = ks_max = kext_max =-DBL_MAX; /* For each atmospheric layer that overlaps the SVX voxel ... */ - FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { - struct htgop_layer layer; - struct htgop_layer_sw_spectral_interval band; - size_t iquad; - - HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); - - /* ... retrieve the considered spectral interval */ - HTGOP(layer_get_sw_spectral_interval(&layer, ctx->iband, &band)); - - /* ... and update the radiative properties bound with the per quadrature - * point nominal values */ - ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); - ASSERT(ctx->quadrature_range[1] < band.quadrature_length); - FOR_EACH(iquad, ctx->quadrature_range[0], ctx->quadrature_range[1]+1) { - ka_min = MMIN(ka_min, band.ka_nominal[iquad]); - ka_max = MMAX(ka_max, band.ka_nominal[iquad]); - ks_min = MMIN(ks_min, band.ks_nominal[iquad]); - ks_max = MMAX(ks_max, band.ks_nominal[iquad]); - kext_min = MMIN(kext_min, band.ka_nominal[iquad]+band.ks_nominal[iquad]); - kext_max = MMAX(kext_max, band.ka_nominal[iquad]+band.ks_nominal[iquad]); + if(ctx->sky->is_long_wave) { + FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { + struct htgop_layer layer; + struct htgop_layer_lw_spectral_interval band; + size_t iquad; + + HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); + + /* ... retrieve the considered spectral interval */ + HTGOP(layer_get_lw_spectral_interval(&layer, ctx->iband, &band)); + + /* ... and update the radiative properties bound with the per quadrature + * point nominal values */ + ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); + ASSERT(ctx->quadrature_range[1] < band.quadrature_length); + FOR_EACH(iquad, ctx->quadrature_range[0], ctx->quadrature_range[1]+1) { + ka_min = MMIN(ka_min, band.ka_nominal[iquad]); + ka_max = MMAX(ka_max, band.ka_nominal[iquad]); + } + } + ks_min = 0; + ks_max = 0; + kext_min = ka_min; + kext_max = ka_max; + } else { + FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { + struct htgop_layer layer; + struct htgop_layer_sw_spectral_interval band; + size_t iquad; + + HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); + + /* ... retrieve the considered spectral interval */ + HTGOP(layer_get_sw_spectral_interval(&layer, ctx->iband, &band)); + + /* ... and update the radiative properties bound with the per quadrature + * point nominal values */ + ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); + ASSERT(ctx->quadrature_range[1] < band.quadrature_length); + FOR_EACH(iquad, ctx->quadrature_range[0], ctx->quadrature_range[1]+1) { + ka_min = MMIN(ka_min, band.ka_nominal[iquad]); + ka_max = MMAX(ka_max, band.ka_nominal[iquad]); + ks_min = MMIN(ks_min, band.ks_nominal[iquad]); + ks_max = MMAX(ks_max, band.ks_nominal[iquad]); + kext_min = MMIN(kext_min, band.ka_nominal[iquad]+band.ks_nominal[iquad]); + kext_max = MMAX(kext_max, band.ka_nominal[iquad]+band.ks_nominal[iquad]); + } } } @@ -170,7 +196,7 @@ atmosphere_setup(struct htsky* sky, const double optical_thickness_threshold) /* Create as many atmospheric data structure than considered SW spectral * bands */ - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); sky->atmosphere = MEM_CALLOC (sky->allocator, nbands, sizeof(*sky->atmosphere)); if(!sky->atmosphere) { @@ -183,9 +209,13 @@ atmosphere_setup(struct htsky* sky, const double optical_thickness_threshold) FOR_EACH(i, 0, nbands) { size_t iquad; struct htgop_spectral_interval band; - ctx.iband = i + sky->sw_bands_range[0]; + ctx.iband = i + sky->bands_range[0]; - HTGOP(get_sw_spectral_interval(sky->htgop, ctx.iband, &band)); + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, ctx.iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, ctx.iband, &band)); + } sky->atmosphere[i] = MEM_CALLOC(sky->allocator, band.quadrature_length, sizeof(*sky->atmosphere[i])); @@ -234,17 +264,21 @@ atmosphere_clean(struct htsky* sky) if(!sky->atmosphere) return; - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); FOR_EACH(i, 0, nbands) { struct htgop_spectral_interval band; size_t iband; size_t iquad; - iband = sky->sw_bands_range[0] + i; - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); - if(!sky->atmosphere[i]) continue; + iband = sky->bands_range[0] + i; + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } + FOR_EACH(iquad, 0, band.quadrature_length) { if(sky->atmosphere[i][iquad].bitree) { SVX(tree_ref_put(sky->atmosphere[i][iquad].bitree)); diff --git a/src/htsky_c.h b/src/htsky_c.h @@ -49,7 +49,7 @@ struct split { #include <rsys/dynamic_array.h> /* Properties of a short wave spectral band */ -struct sw_band_prop { +struct band_prop { /* Average cross section in the band */ double Ca_avg; /* Absorption cross section */ double Cs_avg; /* Scattering cross section */ @@ -79,10 +79,11 @@ struct htsky { struct darray_split svx2htcp_z; double lut_cell_sz; /* Size of a svx2htcp_z cell */ - /* Ids and optical properties of the short wave spectral bands loaded by - * HTGOP and that overlap the CIE XYZ color space */ - size_t sw_bands_range[2]; - struct sw_band_prop* sw_bands; + /* Ids and optical properties of spectral bands loaded by HTGOP and currently + * handled by the sky */ + int is_long_wave; + size_t bands_range[2]; /* Inclusive band ids */ + struct band_prop* bands; int repeat_clouds; /* Make clouds infinite in X and Y */ int is_cloudy; /* The sky has clouds */ diff --git a/src/htsky_cloud.c b/src/htsky_cloud.c @@ -134,11 +134,11 @@ compute_k_bounds_regular_z ASSERT(!sky->htcp_desc.irregular_z && vox_svx_low && vox_svx_upp); ASSERT(ka_bounds && ks_bounds && kext_bounds); - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; /* Fetch the optical properties of the spectral band */ - Ca_avg = sky->sw_bands[i].Ca_avg; - Cs_avg = sky->sw_bands[i].Cs_avg; + Ca_avg = sky->bands[i].Ca_avg; + Cs_avg = sky->bands[i].Cs_avg; /* Compute the *inclusive* bounds of the indices of cloud grid overlapped by * the SVX voxel */ @@ -219,11 +219,11 @@ compute_k_bounds_irregular_z ASSERT(sky->htcp_desc.irregular_z && vox_svx_low && vox_svx_upp); ASSERT(ka_bounds && ks_bounds && kext_bounds); - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; /* Fetch the optical properties of the spectral band */ - Ca_avg = sky->sw_bands[i].Ca_avg; - Cs_avg = sky->sw_bands[i].Cs_avg; + Ca_avg = sky->bands[i].Ca_avg; + Cs_avg = sky->bands[i].Cs_avg; /* Compute the *inclusive* bounds of the indices of cloud grid overlapped by * the SVX voxel along the X and Y axes */ @@ -490,7 +490,6 @@ cloud_vox_get_gas { const struct htcp_desc* htcp_desc; struct htgop_layer layer; - struct htgop_layer_sw_spectral_interval band; size_t ilayer; size_t layer_range[2]; double x_h2o_range[2]; @@ -524,29 +523,54 @@ cloud_vox_get_gas ka[1] = ks[1] = kext[1] =-DBL_MAX; /* For each atmospheric layer that overlaps the SVX voxel ... */ - FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { - double k[2]; - - HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); - - /* ... retrieve the considered spectral interval */ - HTGOP(layer_get_sw_spectral_interval(&layer, ctx->iband, &band)); - ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); - ASSERT(ctx->quadrature_range[1] < band.quadrature_length); - - /* ... and compute the radiative properties and upd their bounds */ - HTGOP(layer_sw_spectral_interval_quadpoints_get_ka_bounds - (&band, ctx->quadrature_range, x_h2o_range, k)); - ka[0] = MMIN(ka[0], k[0]); - ka[1] = MMAX(ka[1], k[1]); - HTGOP(layer_sw_spectral_interval_quadpoints_get_ks_bounds - (&band, ctx->quadrature_range, x_h2o_range, k)); - ks[0] = MMIN(ks[0], k[0]); - ks[1] = MMAX(ks[1], k[1]); - HTGOP(layer_sw_spectral_interval_quadpoints_get_kext_bounds - (&band, ctx->quadrature_range, x_h2o_range, k)); - kext[0] = MMIN(kext[0], k[0]); - kext[1] = MMAX(kext[1], k[1]); + if(ctx->sky->is_long_wave) { + FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { + struct htgop_layer_lw_spectral_interval band; + double k[2]; + + HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); + + /* ... retrieve the considered spectral interval */ + HTGOP(layer_get_lw_spectral_interval(&layer, ctx->iband, &band)); + ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); + ASSERT(ctx->quadrature_range[1] < band.quadrature_length); + + /* ... and compute the radiative properties and upd their bounds */ + HTGOP(layer_lw_spectral_interval_quadpoints_get_ka_bounds + (&band, ctx->quadrature_range, x_h2o_range, k)); + ka[0] = MMIN(ka[0], k[0]); + ka[1] = MMAX(ka[1], k[1]); + } + ks[0] = 0; + ks[1] = 0; + kext[0] = ka[0]; + kext[1] = ka[1]; + } else { + FOR_EACH(ilayer, layer_range[0], layer_range[1]+1) { + struct htgop_layer_sw_spectral_interval band; + double k[2]; + + HTGOP(get_layer(ctx->sky->htgop, ilayer, &layer)); + + /* ... retrieve the considered spectral interval */ + HTGOP(layer_get_sw_spectral_interval(&layer, ctx->iband, &band)); + ASSERT(ctx->quadrature_range[0] <= ctx->quadrature_range[1]); + ASSERT(ctx->quadrature_range[1] < band.quadrature_length); + + /* ... and compute the radiative properties and upd their bounds */ + HTGOP(layer_sw_spectral_interval_quadpoints_get_ka_bounds + (&band, ctx->quadrature_range, x_h2o_range, k)); + ka[0] = MMIN(ka[0], k[0]); + ka[1] = MMAX(ka[1], k[1]); + HTGOP(layer_sw_spectral_interval_quadpoints_get_ks_bounds + (&band, ctx->quadrature_range, x_h2o_range, k)); + ks[0] = MMIN(ks[0], k[0]); + ks[1] = MMAX(ks[1], k[1]); + HTGOP(layer_sw_spectral_interval_quadpoints_get_kext_bounds + (&band, ctx->quadrature_range, x_h2o_range, k)); + kext[0] = MMIN(kext[0], k[0]); + kext[1] = MMAX(kext[1], k[1]); + } } /* Ensure that the single precision bounds include their double precision @@ -646,7 +670,7 @@ cloud_build_octrees struct build_tree_context ctx = BUILD_TREE_CONTEXT_NULL; const size_t iband = darray_specdata_data_get(specdata)[ispecdata].iband; const size_t iquad = darray_specdata_data_get(specdata)[ispecdata].iquad; - const size_t id = iband - sky->sw_bands_range[0]; + const size_t id = iband - sky->bands_range[0]; int32_t pcent; size_t n; res_T res_local = RES_OK; @@ -723,14 +747,18 @@ cloud_write_octrees(const struct htsky* sky, FILE* stream) res_T res = RES_OK; ASSERT(sky && sky->clouds); - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); FOR_EACH(i, 0, nbands) { struct htgop_spectral_interval band; size_t iband; size_t iquad; - iband = sky->sw_bands_range[0] + i; - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + iband = sky->bands_range[0] + i; + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } ASSERT(sky->clouds[i]); FOR_EACH(iquad, 0, band.quadrature_length) { @@ -758,21 +786,25 @@ cloud_read_octrees(struct htsky* sky, const char* stream_name, FILE* stream) ASSERT(sky && sky->clouds && stream_name); log_info(sky, "Loading octrees from `%s'.\n", stream_name); - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); FOR_EACH(i, 0, nbands) { struct htgop_spectral_interval band; size_t iband; size_t iquad; - iband = sky->sw_bands_range[0] + i; - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + iband = sky->bands_range[0] + i; + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } ASSERT(sky->clouds[i]); FOR_EACH(iquad, 0, band.quadrature_length) { /* The octree was already setup */ if(sky->clouds[i][iquad].octree != NULL) continue; - res = svx_tree_create_from_stream + res = svx_tree_create_from_stream (sky->svx, stream, &sky->clouds[i][iquad].octree); if(res != RES_OK) { log_err(sky, "Could not read the octree %lu:%lu from `%s' -- %s.\n", @@ -812,7 +844,7 @@ cloud_setup size_t nbands; size_t i; ATOMIC res = RES_OK; - ASSERT(sky && sky->sw_bands && optical_thickness_threshold >= 0); + ASSERT(sky && sky->bands && optical_thickness_threshold >= 0); ASSERT(grid_max_definition); ASSERT(grid_max_definition[0]); ASSERT(grid_max_definition[1]); @@ -849,7 +881,7 @@ cloud_setup } /* Create as many cloud data structure than considered SW spectral bands */ - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); sky->clouds = MEM_CALLOC(sky->allocator, nbands, sizeof(*sky->clouds)); if(!sky->clouds) { log_err(sky, @@ -861,10 +893,14 @@ cloud_setup /* Compute how many octrees are going to be built */ FOR_EACH(i, 0, nbands) { struct htgop_spectral_interval band; - const size_t iband = i + sky->sw_bands_range[0]; + const size_t iband = i + sky->bands_range[0]; size_t iquad; - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } sky->clouds[i] = MEM_CALLOC(sky->allocator, band.quadrature_length, sizeof(*sky->clouds[i])); @@ -947,14 +983,18 @@ cloud_clean(struct htsky* sky) if(!sky->clouds) return; - nbands = htsky_get_sw_spectral_bands_count(sky); + nbands = htsky_get_spectral_bands_count(sky); FOR_EACH(i, 0, nbands) { struct htgop_spectral_interval band; size_t iband; size_t iquad; - iband = sky->sw_bands_range[0] + i; - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + iband = sky->bands_range[0] + i; + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &band)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &band)); + } if(!sky->clouds[i]) continue; diff --git a/src/htsky_dump_cloud_vtk.c b/src/htsky_dump_cloud_vtk.c @@ -70,8 +70,8 @@ octree_data_init struct octree_data* data) { ASSERT(data); - ASSERT(iband >= sky->sw_bands_range[0]); - ASSERT(iband <= sky->sw_bands_range[1]); + ASSERT(iband >= sky->bands_range[0]); + ASSERT(iband <= sky->bands_range[1]); (void)iquad; htable_vertex_init(sky->allocator, &data->vertex2id); darray_double_init(sky->allocator, &data->vertices); @@ -165,19 +165,19 @@ htsky_dump_cloud_vtk goto error; } - if(iband < sky->sw_bands_range[0] || iband > sky->sw_bands_range[1]) { + if(iband < sky->bands_range[0] || iband > sky->bands_range[1]) { log_err(sky, "%s: invalid spectral band index `%lu'. " "Valid short wave spectral bands lie in [%lu, %lu]\n", FUNC_NAME, (unsigned long)iband, - (unsigned long)sky->sw_bands_range[0], - (unsigned long)sky->sw_bands_range[1]); + (unsigned long)sky->bands_range[0], + (unsigned long)sky->bands_range[1]); res = RES_BAD_ARG; goto error; } - if(iquad >= htsky_get_sw_spectral_band_quadrature_length(sky, iband)) { + if(iquad >= htsky_get_spectral_band_quadrature_length(sky, iband)) { log_err(sky, "invalid quadrature point `%lu' for the spectral band `%lu'.\n", (unsigned long)iquad, (unsigned long)iband); @@ -190,7 +190,7 @@ htsky_dump_cloud_vtk return RES_OK; } - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; octree_data_init(sky, iband, iquad, &data); cloud = &sky->clouds[i][iquad]; @@ -204,7 +204,11 @@ htsky_dump_cloud_vtk ASSERT(ncells == cloud->octree_desc.nleaves); /* Fetch the spectral interval descriptor */ - HTGOP(get_sw_spectral_interval(sky->htgop, iband, &specint)); + if(sky->is_long_wave) { + HTGOP(get_lw_spectral_interval(sky->htgop, iband, &specint)); + } else { + HTGOP(get_sw_spectral_interval(sky->htgop, iband, &specint)); + } /* Write headers */ fprintf(stream, "# vtk DataFile Version 2.0\n"); diff --git a/src/htsky_svx.c b/src/htsky_svx.c @@ -205,11 +205,11 @@ htsky_fetch_svx_property int comp_mask = components_mask; ASSERT(sky && pos); ASSERT(comp_mask & HTSKY_CPNT_MASK_ALL); - ASSERT(iband >= sky->sw_bands_range[0]); - ASSERT(iband <= sky->sw_bands_range[1]); - ASSERT(iquad < htsky_get_sw_spectral_band_quadrature_length(sky, iband)); + ASSERT(iband >= sky->bands_range[0]); + ASSERT(iband <= sky->bands_range[1]); + ASSERT(iquad < htsky_get_spectral_band_quadrature_length(sky, iband)); - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; cloud = sky->is_cloudy ? &sky->clouds[i][iquad] : NULL; atmosphere = &sky->atmosphere[i][iquad]; @@ -317,19 +317,19 @@ htsky_trace_ray goto error; } - if(iband < sky->sw_bands_range[0] || iband > sky->sw_bands_range[1]) { + if(iband < sky->bands_range[0] || iband > sky->bands_range[1]) { log_err(sky, "%s: invalid spectral band index `%lu'. " "Valid short wave spectral bands lie in [%lu, %lu]\n", FUNC_NAME, (unsigned long)iband, - (unsigned long)sky->sw_bands_range[0], - (unsigned long)sky->sw_bands_range[1]); + (unsigned long)sky->bands_range[0], + (unsigned long)sky->bands_range[1]); res = RES_BAD_ARG; goto error; } - if(iquad >= htsky_get_sw_spectral_band_quadrature_length(sky, iband)) { + if(iquad >= htsky_get_spectral_band_quadrature_length(sky, iband)) { log_err(sky, "invalid quadrature point `%lu' for the spectral band `%lu'.\n", (unsigned long)iquad, (unsigned long)iband); @@ -338,7 +338,7 @@ htsky_trace_ray } /* Fetch the clouds/atmosphere corresponding to the submitted spectral data */ - i = iband - sky->sw_bands_range[0]; + i = iband - sky->bands_range[0]; clouds = sky->is_cloudy ? sky->clouds[i][iquad].octree : NULL; atmosphere = sky->atmosphere[i][iquad].bitree;