htrdr

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

commit 5cfeac159892a245957b0f9d16d47a6714e87f07
parent 2172c05c7483399eb5e732ca18e8304213b14773
Author: Arfaux Anthony <anthony.arfaux@obspm.fr>
Date:   Fri, 16 May 2025 14:43:44 +0200

Improve volumic radiative budget

Reduce variance by separating sampling of directions within the sun cone
from sampling of directions outside it.

Diffstat:
MMakefile | 10+++++-----
MMakefile.core | 2+-
Msrc/planets/htrdr_planets_compute_radiance.c | 5+++--
Msrc/planets/htrdr_planets_solve_volrad_budget.c | 132+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/planets/htrdr_planets_source.c | 34++++++++++++++++++++++++++++++++++
Msrc/planets/htrdr_planets_source.h | 7+++++++
6 files changed, 180 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile @@ -28,13 +28,13 @@ include config.mk default install uninstall lint clean: @$(MAKE) -fMakefile.core $@ - @if [ "$(ATMOSPHERE)" == "ENABLE" ]; then $(MAKE) -fMakefile.atmosphere $@; fi - @if [ "$(COMBUSTION)" == "ENABLE" ]; then $(MAKE) -fMakefile.combustion $@; fi - @if [ "$(PLANETS)" == ENABLE ]; then $(MAKE) -fMakefile.planets $@; fi + @if [ "$(ATMOSPHERE)" = "ENABLE" ]; then $(MAKE) -fMakefile.atmosphere $@; fi + @if [ "$(COMBUSTION)" = "ENABLE" ]; then $(MAKE) -fMakefile.combustion $@; fi + @if [ "$(PLANETS)" = ENABLE ]; then $(MAKE) -fMakefile.planets $@; fi test: - @if [ "$(COMBUSTION)" == "ENABLE" ]; then $(MAKE) -fMakefile.combustion $@; fi - @if [ "$(PLANETS)" == ENABLE ]; then $(MAKE) -fMakefile.planets $@; fi + @if [ "$(COMBUSTION)" = "ENABLE" ]; then $(MAKE) -fMakefile.combustion $@; fi + @if [ "$(PLANETS)" = ENABLE ]; then $(MAKE) -fMakefile.planets $@; fi default: htrdr install: install_common diff --git a/Makefile.core b/Makefile.core @@ -147,7 +147,7 @@ htrdr-core.pc: config.mk htrdr-core.pc.in # Miscellaneous ################################################################################ install: - @if [ "$(LIB_TYPE)" == "SHARED" ]; then \ + @if [ "$(LIB_TYPE)" = "SHARED" ]; then \ $(SHELL) install.sh 755 "$(DESTDIR)$(LIBPREFIX)" $(LIBNAME); \ fi diff --git a/src/planets/htrdr_planets_compute_radiance.c b/src/planets/htrdr_planets_compute_radiance.c @@ -504,8 +504,6 @@ volume_scattering ssf_phase_sample(phase, args->rng, wo, sc_dir, NULL); - /* Sample a direction toward the source */ - pdf = htrdr_planets_source_sample_direction(cmd->source, args->rng, sc_pos, wi); /* In short wave, manage the contribution of the external source */ switch(cmd->spectral_domain.type) { @@ -515,6 +513,9 @@ volume_scattering case HTRDR_SPECTRAL_SW: case HTRDR_SPECTRAL_SW_CIE_XYZ: + + /* Sample a direction toward the source */ + pdf = htrdr_planets_source_sample_direction(cmd->source, args->rng, sc_pos, wi); /* Calculate the direct contribution at the scattering position */ Ld = direct_contribution(cmd, args, sc_pos, wi, NULL); rho = ssf_phase_eval(phase, wo, wi); diff --git a/src/planets/htrdr_planets_solve_volrad_budget.c b/src/planets/htrdr_planets_solve_volrad_budget.c @@ -237,6 +237,126 @@ realisation return weight; } +static double +realisation_cone + (struct htrdr_planets* cmd, + const struct htrdr_solve_item_args* args, + const struct smsh_desc* volrad_mesh_desc) +{ + struct planets_compute_radiance_args rad_args = + PLANETS_COMPUTE_RADIANCE_ARGS_NULL; + + /* Spectral integration */ + double wlen = 0; /* Wavelength [nm] */ + double wlen_pdf_nm = 0; /* Wavelength pdf [nm^-1] */ + double wlen_pdf_m = 0; /* Wavelength pdf [m^-1] */ + size_t iband = 0; /* Spectral band */ + size_t iquad = 0; /* Quadrature point */ + + /* Spatial & angular integration */ + double dir[3] = {0,0,0}; + double pos[3] = {0,0,0}; + + double S = 0; /* Source [W/m^2/sr/m] */ + double L = 0; /* Radiance [W/m^2/sr/m] */ + double ka = 0; /* Absorption coefficient */ + + /* Monte Carlo weight */ + double weight = 0; /* weight [W/m^3] */ + + /* For sampling in cone */ + const struct htrdr_planets_source* source; + double dir_pdf=0; + source = cmd->source; + + /* Preconditions */ + ASSERT(cmd && args && volrad_mesh_desc); + ASSERT(cmd->output_type == HTRDR_PLANETS_ARGS_OUTPUT_VOLUMIC_RADIATIVE_BUDGET); + ASSERT(source); + + spectral_sampling(cmd, args, &wlen, &wlen_pdf_nm, &iband, &iquad); + position_sampling(args, volrad_mesh_desc, pos); + dir_pdf = htrdr_planets_source_sample_direction(source, args->rng, pos, dir); + + /* Compute the radiance in W/m^2/sr/m */ + d3_set(rad_args.path_org, pos); + d3_set(rad_args.path_dir, dir); + rad_args.rng = args->rng; + rad_args.ithread = args->ithread; + rad_args.wlen = wlen; /* [nm] */ + rad_args.iband = iband; + rad_args.iquad = iquad; + L = planets_compute_radiance(cmd, &rad_args); /* [W/m^2/sr/m] */ + + S = get_source(cmd, pos, wlen); /* [W/m^2/sr/m] */ + + ka = get_ka(cmd, pos, iband, iquad); + wlen_pdf_m = wlen_pdf_nm * 1.e9; /* Transform pdf from nm^-1 to m^-1 */ + + weight = ka * (L - S) / (wlen_pdf_m * dir_pdf); /* [W/m^3] */ + return weight; +} + +static double +realisation_out_of_cone + (struct htrdr_planets* cmd, + const struct htrdr_solve_item_args* args, + const struct smsh_desc* volrad_mesh_desc) +{ + struct planets_compute_radiance_args rad_args = + PLANETS_COMPUTE_RADIANCE_ARGS_NULL; + + /* Spectral integration */ + double wlen = 0; /* Wavelength [nm] */ + double wlen_pdf_nm = 0; /* Wavelength pdf [nm^-1] */ + double wlen_pdf_m = 0; /* Wavelength pdf [m^-1] */ + size_t iband = 0; /* Spectral band */ + size_t iquad = 0; /* Quadrature point */ + + /* Spatial & angular integration */ + double dir[3] = {0,0,0}; + double pos[3] = {0,0,0}; + + double S = 0; /* Source [W/m^2/sr/m] */ + double L = 0; /* Radiance [W/m^2/sr/m] */ + double ka = 0; /* Absorption coefficient */ + + /* Monte Carlo weight */ + double weight = 0; /* weight [W/m^3] */ + + /* For sampling out of cone cone */ + const struct htrdr_planets_source* source; + double dir_pdf=0; + source = cmd->source; + + /* Preconditions */ + ASSERT(cmd && args && volrad_mesh_desc); + ASSERT(cmd->output_type == HTRDR_PLANETS_ARGS_OUTPUT_VOLUMIC_RADIATIVE_BUDGET); + ASSERT(source); + + spectral_sampling(cmd, args, &wlen, &wlen_pdf_nm, &iband, &iquad); + position_sampling(args, volrad_mesh_desc, pos); + dir_pdf = htrdr_planets_source_sample_direction_out(source, args->rng, pos, dir); + + /* Compute the radiance in W/m^2/sr/m */ + d3_set(rad_args.path_org, pos); + d3_set(rad_args.path_dir, dir); + rad_args.rng = args->rng; + rad_args.ithread = args->ithread; + rad_args.wlen = wlen; /* [nm] */ + rad_args.iband = iband; + rad_args.iquad = iquad; + L = planets_compute_radiance(cmd, &rad_args); /* [W/m^2/sr/m] */ + + S = get_source(cmd, pos, wlen); /* [W/m^2/sr/m] */ + + ka = get_ka(cmd, pos, iband, iquad); + wlen_pdf_m = wlen_pdf_nm * 1.e9; /* Transform pdf from nm^-1 to m^-1 */ + + weight = ka * (L - S) / (wlen_pdf_m * dir_pdf); /* [W/m^3] */ + return weight; +} + static void solve_volumic_radiative_budget (struct htrdr* htrdr, @@ -276,8 +396,16 @@ solve_volumic_radiative_budget /* Start of realisation time recording */ time_current(&t0); - /* Run the realisation */ - w = realisation(cmd, args, &volrad_mesh_desc); + if (cmd->spectral_domain.type == HTRDR_SPECTRAL_LW) { + /* Run the realisation */ + w = realisation(cmd, args, &volrad_mesh_desc); + } + else{ + /* Run the realisation within source cone */ + w = realisation_cone(cmd, args, &volrad_mesh_desc); + /* Run the realisation out of source cone */ + w += realisation_out_of_cone(cmd, args, &volrad_mesh_desc); + } /* Stop time recording */ time_sub(&t0, time_current(&t1), &t0); diff --git a/src/planets/htrdr_planets_source.c b/src/planets/htrdr_planets_source.c @@ -296,6 +296,40 @@ htrdr_planets_source_sample_direction return pdf; } +double +htrdr_planets_source_sample_direction_out + (const struct htrdr_planets_source* source, + struct ssp_rng* rng, + const double pos[3], + double dir[3]) +{ + double main_dir[3]; + double half_angle; /* In radians */ + double cos_half_angle; + double dst; /* In m */ + double pdf; + ASSERT(source && rng && pos && dir); + + /* compute the direction of `pos' toward the center of the source */ + d3_sub(main_dir, source->position, pos); + + /* Normalize the direction and keep the distance from `pos' to the center of + * the source */ + dst = d3_normalize(main_dir, main_dir); + CHK(dst > source->radius); + + /* Sample the source according to its solid angle, + * i.e. 2*PI*(1 - cos(half_angle)) */ + half_angle = asin(source->radius/dst); + cos_half_angle = - cos(half_angle); + main_dir[0] = -main_dir[0]; + main_dir[1] = -main_dir[1]; + main_dir[2] = -main_dir[2]; + ssp_ran_sphere_cap_uniform(rng, main_dir, cos_half_angle, dir, &pdf); + + return pdf; +} + double /* In W/m²/sr/m */ htrdr_planets_source_get_radiance (const struct htrdr_planets_source* source, diff --git a/src/planets/htrdr_planets_source.h b/src/planets/htrdr_planets_source.h @@ -64,6 +64,13 @@ htrdr_planets_source_sample_direction const double pos[3], /* Position from which direction is sampled */ double dir[3]); +extern LOCAL_SYM double +htrdr_planets_source_sample_direction_out + (const struct htrdr_planets_source* source, + struct ssp_rng* rng, + const double pos[3], /* Position from which direction is sampled */ + double dir[3]); + extern LOCAL_SYM double /* In W/m²/sr/m */ htrdr_planets_source_get_radiance (const struct htrdr_planets_source* source,