htrdr

Solving radiative transfer in heterogeneous media
git clone git://git.meso-star.fr/htrdr.git
Log | Files | Refs | README | LICENSE

commit c6d6772a4922c273c7b7dd05d3ec3b7251dcdf3d
parent 9103614c15cbb99d9f00765d4d9bc9b8ba1a0ebf
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 10 Jul 2018 14:27:12 +0200

Implement the sun API

Diffstat:
Mcmake/CMakeLists.txt | 2+-
Msrc/htrdr_c.h | 2+-
Msrc/htrdr_sun.c | 104+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------------
Msrc/htrdr_sun.h | 11++++++++---
4 files changed, 90 insertions(+), 29 deletions(-)

diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt @@ -25,7 +25,7 @@ option(NO_TEST "Do not build the tests" OFF) ################################################################################ find_package(RCMake 0.3 REQUIRED) find_package(RSys 0.6 REQUIRED) -find_package(StarSP 0.7 REQUIRED) +find_package(StarSP 0.8 REQUIRED) find_package(SVX REQUIRED) find_package(HTCP REQUIRED) find_package(HTMIE REQUIRED) diff --git a/src/htrdr_c.h b/src/htrdr_c.h @@ -27,7 +27,7 @@ wavenumber_to_wavelength(const double nu/*In cm^-1*/) static FINLINE double wavelength_to_wavenumber(const double lambda/*In nanometer*/) { - return 1.e7 / lambda; + return wavenumber_to_wavelength(lambda); } #endif /* HTRDR_C_H */ diff --git a/src/htrdr_sun.c b/src/htrdr_sun.c @@ -14,24 +14,28 @@ * along with this program. If not, see <http://www.gnu.org/licenses/>. */ #include "htrdr.h" +#include "htrdr_c.h" #include "htrdr_sun.h" -#include <rsys/double3.h> +#include <rsys/algorithm.h> +#include <rsys/double33.h> #include <rsys/dynamic_array_double.h> #include <rsys/ref_count.h> #include <rsys/math.h> +#include <star/ssp.h> + struct htrdr_sun { /* Short wave radiance in W.m^-2.sr^-1, for each spectral interval */ - struct darray_double radiance_sw; + struct darray_double radiances_sw; /* Short wave spectral interval boundaries, in cm^-1 */ struct darray_double wavenumbers_sw; double half_angle; /* In radian */ - double solid_angle; /* In sr; solid_angle = 2*PI(1 - cos(half_angle)) */ - - double main_dir[3]; /* Direction *toward* the sun */ + double cos_half_angle; + double solid_angle; /* In sr; solid_angle = 2*PI*(1 - cos(half_angle)) */ + double frame[9]; ref_T ref; struct htrdr* htrdr; @@ -40,13 +44,21 @@ struct htrdr_sun { /******************************************************************************* * Helper functions ******************************************************************************/ +static INLINE int +cmp_dbl(const void* a, const void* b) +{ + const double d0 = *((const double*)a); + const double d1 = *((const double*)b); + return d0 < d1 ? -1 : (d0 > d1 ? 1 : 0); +} + static void release_sun(ref_T* ref) { struct htrdr_sun* sun; ASSERT(ref); sun = CONTAINER_OF(ref, struct htrdr_sun, ref); - darray_double_release(&sun->radiance_sw); + darray_double_release(&sun->radiances_sw); darray_double_release(&sun->wavenumbers_sw); MEM_RM(sun->htrdr->allocator, sun); } @@ -71,6 +83,7 @@ htrdr_sun_create(struct htrdr* htrdr, struct htrdr_sun** out_sun) }; const size_t nspectral_intervals = sizeof(incoming_flux_sw)/sizeof(double); + const double main_dir[3] = {0, 0, 1}; /* Default main sun direction */ struct htrdr_sun* sun = NULL; size_t i; res_T res = RES_OK; @@ -85,12 +98,14 @@ htrdr_sun_create(struct htrdr* htrdr, struct htrdr_sun** out_sun) } ref_init(&sun->ref); sun->htrdr = htrdr; - darray_double_init(htrdr->allocator, &sun->radiance_sw); + darray_double_init(htrdr->allocator, &sun->radiances_sw); darray_double_init(htrdr->allocator, &sun->wavenumbers_sw); sun->half_angle = 4.6524e3; - sun->solid_angle = 2*PI*(1-cos(sun->half_angle)); + sun->cos_half_angle = cos(sun->half_angle); + sun->solid_angle = 2*PI*(1-sun->cos_half_angle); + d33_basis(sun->frame, main_dir); - res = darray_double_resize(&sun->radiance_sw, nspectral_intervals); + res = darray_double_resize(&sun->radiances_sw, nspectral_intervals); if(res != RES_OK) { htrdr_log_err(htrdr, "could not allocate the list of per spectral band radiance of the sun.\n"); @@ -103,18 +118,14 @@ htrdr_sun_create(struct htrdr* htrdr, struct htrdr_sun** out_sun) goto error; } - FOR_EACH(i, 0, darray_double_size_get(&sun->radiance_sw)) { + FOR_EACH(i, 0, darray_double_size_get(&sun->radiances_sw)) { /* Convert the incoming flux in radiance */ - darray_double_data_get(&sun->radiance_sw)[i] = incoming_flux_sw[i] / PI; + darray_double_data_get(&sun->radiances_sw)[i] = incoming_flux_sw[i] / PI; } FOR_EACH(i, 0, darray_double_size_get(&sun->wavenumbers_sw)) { darray_double_data_get(&sun->wavenumbers_sw)[i] = wavenumbers_sw[i]; } - sun->main_dir[0] = 0; - sun->main_dir[1] = 0; - sun->main_dir[2] = 1; - exit: *out_sun = sun; return res; @@ -140,13 +151,22 @@ htrdr_sun_ref_put(struct htrdr_sun* sun) ref_put(&sun->ref, release_sun); } -res_T +void htrdr_sun_set_direction(struct htrdr_sun* sun, const double dir[3]) { - double len; - ASSERT(sun && dir); - len = d3_normalize(sun->main_dir, dir); - return len <= 0 ? RES_BAD_ARG : RES_OK; + ASSERT(sun && dir && d3_is_normalized(dir)); + d33_basis(sun->frame, dir); +} + +double* +htrdr_sun_sample_direction + (struct htrdr_sun* sun, + struct ssp_rng* rng, + double dir[3]) +{ + ASSERT(sun && rng && dir); + ssp_ran_sphere_cap_uniform_local(rng, sun->cos_half_angle, dir, NULL); + return d33_muld3(dir, sun->frame, dir); } double @@ -156,12 +176,48 @@ htrdr_sun_get_solid_angle(const struct htrdr_sun* sun) return sun->solid_angle; } +double +htrdr_sun_get_radiance(const struct htrdr_sun* sun, const double wavelength) +{ + const double* wavenumbers; + const double wnum = wavelength_to_wavenumber(wavelength); + const double* wnum_upp; + size_t nwavenumbers; + size_t ispectral_band; + ASSERT(sun && wavelength > 0); + + wavenumbers = darray_double_cdata_get(&sun->wavenumbers_sw); + nwavenumbers = darray_double_size_get(&sun->wavenumbers_sw); + ASSERT(nwavenumbers); + + if(wnum < wavenumbers[0] || wnum > wavenumbers[nwavenumbers-1]) { + htrdr_log_warn(sun->htrdr, + "the submitted wavelength is outside the sun spectrum.\n"); + } + + wnum_upp = search_lower_bound + (&wnum, wavenumbers, nwavenumbers, sizeof(double), cmp_dbl); + + if(!wnum_upp) { /* Clamp to the upper spectral band */ + ispectral_band = nwavenumbers - 2; + ASSERT(ispectral_band == darray_double_size_get(&sun->radiances_sw)-1); + } else if(wnum_upp == wavenumbers) { /* Clamp to the lower spectral band */ + ispectral_band = 0; + } else { + ispectral_band = (size_t)(wnum_upp - wavenumbers - 1); + } + return darray_double_cdata_get(&sun->radiances_sw)[ispectral_band]; +} + int htrdr_sun_is_dir_in_solar_cone(const struct htrdr_sun* sun, const double dir[3]) { - double alpha; + const double* main_dir; + double dot; ASSERT(sun && dir && d3_is_normalized(dir)); - ASSERT(d3_is_normalized(sun->main_dir)); - alpha = acos(d3_dot(dir, sun->main_dir)); - return alpha < sun->half_angle; + ASSERT(d3_is_normalized(sun->frame + 6)); + main_dir = sun->frame + 6; + dot = d3_dot(dir, main_dir); + return dot >= sun->cos_half_angle; } + diff --git a/src/htrdr_sun.h b/src/htrdr_sun.h @@ -37,13 +37,13 @@ htrdr_sun_ref_put (struct htrdr_sun* sun); /* Setup the direction *toward* the sun "center" */ -extern LOCAL_SYM res_T +extern LOCAL_SYM void htrdr_sun_set_direction (struct htrdr_sun* sun, - const double direction[3]); + const double direction[3]); /* Must be normalized */ /* Return a direction that points *toward* the sun */ -extern LOCAL_SYM res_T +extern LOCAL_SYM double* htrdr_sun_sample_direction (struct htrdr_sun* sun, struct ssp_rng* rng, @@ -53,6 +53,11 @@ extern LOCAL_SYM double htrdr_sun_get_solid_angle (const struct htrdr_sun* sun); +extern LOCAL_SYM double /* W.sr^-1.m^-2 */ +htrdr_sun_get_radiance + (const struct htrdr_sun* sun, + const double wavelength); + extern LOCAL_SYM int htrdr_sun_is_dir_in_solar_cone (const struct htrdr_sun* sun,