htrdr

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

commit 8240840d2b1d1e3bf22bdbd245da8c73cbf987be
parent 10e2d67427b685828bea7b84a1e1446982f89fa3
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 24 Mar 2021 18:22:42 +0100

Update the laser API

Add wavelength and flux density to the laser parameters. Add the
htrdr_combustion_laser_get_mesh, htrdr_combustion_laser_get_direction
and htrdr_combustion_laser_compute_surface_plane_distance functions.

Diffstat:
Msrc/combustion/htrdr_combustion.c | 4+++-
Msrc/combustion/htrdr_combustion_args.c | 78+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Msrc/combustion/htrdr_combustion_args.h | 4+++-
Msrc/combustion/htrdr_combustion_laser.c | 105+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/combustion/htrdr_combustion_laser.h | 55++++++++++++++++++++++++++++++++++++++++++++++++++-----
5 files changed, 222 insertions(+), 24 deletions(-)

diff --git a/src/combustion/htrdr_combustion.c b/src/combustion/htrdr_combustion.c @@ -139,6 +139,8 @@ setup_laser ASSERT(cmd && args); cmd->wavelength = args->wavelength; laser_args.surface = args->laser; + laser_args.wavelength = args->wavelength; + laser_args.flux_density = args->laser_flux_density; return htrdr_combustion_laser_create(cmd->htrdr, &laser_args, &cmd->laser); } @@ -193,7 +195,7 @@ setup_medium atrstm_args.spectral_type = ATRSTM_SPECTRAL_SW; atrstm_args.wlen_range[0] = args->wavelength; atrstm_args.wlen_range[1] = args->wavelength; - atrstm_args.gyration_radius_prefactor = args->gyration_radius_prefactor; + atrstm_args.fractal_prefactor = args->fractal_prefactor; atrstm_args.fractal_dimension = args->fractal_dimension; atrstm_args.optical_thickness = args->optical_thickness; atrstm_args.precompute_normals = args->precompute_normals; diff --git a/src/combustion/htrdr_combustion_args.c b/src/combustion/htrdr_combustion_args.c @@ -15,10 +15,14 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ +#define _POSIX_C_SOURCE 200112L /* strtok_r support */ + #include "combustion/htrdr_combustion_args.h" #include <rsys/cstr.h> + #include <getopt.h> +#include <string.h> /******************************************************************************* * Helper functions @@ -38,19 +42,26 @@ print_help(const char* cmd) " -C <camera> define the rendering point of view. Refer to the\n" " %s man page for the list of camera options.\n", cmd); printf( +" -D FLUX_DENSITY\n" +" flux density of the laser in W/m^2. By default the\n" +" flux density is %g W/m^2.\n", + HTRDR_COMBUSTION_ARGS_DEFAULT.laser_flux_density); + printf( " -d dump volumetric acceleration structures to OUTPUT\n" " and exit.\n"); printf( -" -F FRACTAL_DIM value of the fractal dimension to use in the RDG-FA\n" -" model. Its default value is %g.\n", +" -F <fractal-coefs>" +" value of the fractal prefactor and fractal dimension\n" +" to use in the RDG-FA model. Refer to the %s man page\n" +" for the syntax of the <fractal-coefs> option. Default\n" +" fractal prefactor is %g and the default fractal\n" +" dimension is %g.\n", + cmd, + HTRDR_COMBUSTION_ARGS_DEFAULT.fractal_prefactor, HTRDR_COMBUSTION_ARGS_DEFAULT.fractal_dimension); printf( " -f overwrite the OUTPUT file if it already exists.\n"); printf( -" -G PREFACTOR value gyration radius prefactor to use in the RDG-FA\n" -" model. Its default value is %g.\n", - HTRDR_COMBUSTION_ARGS_DEFAULT.gyration_radius_prefactor); - printf( " -g <geometry> define the combustion chamber geometry. Refer to the\n" " %s man page for the list of geometry options.\n", cmd); printf( @@ -147,6 +158,46 @@ error: goto exit; } +static res_T +parse_fractal_parameters(const char* str, void* ptr) +{ + char buf[128]; + struct htrdr_combustion_args* args = ptr; + char* key; + char* val; + char* ctx; + res_T res = RES_OK; + ASSERT(ptr && str); + + if(strlen(str) >= sizeof(buf) -1/*NULL char*/) { + fprintf(stderr, + "Could not duplicate the fractal option string `%s'.\n", str); + res = RES_MEM_ERR; + goto error; + } + strncpy(buf, str, sizeof(buf)); + + key = strtok_r(buf, "=", &ctx); + val = strtok_r(NULL, "", &ctx); + + if(!strcmp(key, "prefactor")) { + res = cstr_to_double(val, &args->fractal_prefactor); + if(res != RES_OK) goto error; + } else if(!strcmp(key, "dimension")) { + res = cstr_to_double(val, &args->fractal_dimension); + if(res != RES_OK) goto error; + } else { + fprintf(stderr, "Invalid fractal parameter `%s'.\n", key); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + /******************************************************************************* * Local functions ******************************************************************************/ @@ -162,25 +213,22 @@ htrdr_combustion_args_init *args = HTRDR_COMBUSTION_ARGS_DEFAULT; - while((opt = getopt(argc, argv, "C:dF:fG:g:hi:l:m:NO:o:p:r:T:t:V:vw:")) != -1) { + while((opt = getopt(argc, argv, "C:D:dF:fg:hi:l:m:NO:o:p:r:T:t:V:vw:")) != -1) { switch(opt) { case 'C': res = htrdr_args_camera_parse(&args->camera, optarg); break; + case 'D': + res = cstr_to_double(optarg, &args->laser_flux_density); + if(res == RES_OK && args->laser_flux_density <= 0) res = RES_BAD_ARG; + break; case 'd': args->dump_volumetric_acceleration_structure = 1; break; case 'F': - res = cstr_to_double(optarg, &args->fractal_dimension); - if(res == RES_OK && args->fractal_dimension <= 0) - res = RES_BAD_ARG; + res = cstr_parse_list(optarg, ':', parse_fractal_parameters, args); break; case 'f': args->force_overwriting = 1; break; - case 'G': - res = cstr_to_double(optarg, &args->gyration_radius_prefactor); - if(res == RES_OK && args->gyration_radius_prefactor <= 0) - res = RES_BAD_ARG; - break; case 'g': res = htrdr_args_geometry_parse(&args->geom, optarg); break; diff --git a/src/combustion/htrdr_combustion_args.h b/src/combustion/htrdr_combustion_args.h @@ -58,11 +58,12 @@ struct htrdr_combustion_args { struct htrdr_args_rectangle laser; /* Laser surface emission */ double wavelength; /* Wavelength of the laser in nanometer */ + double laser_flux_density; /* In W/m^2 */ struct htrdr_args_image image; /* Output Image */ /* RDG-FA parameters */ - double gyration_radius_prefactor; + double fractal_prefactor; double fractal_dimension; struct htrdr_combustion_args_grid_definition grid; @@ -92,6 +93,7 @@ struct htrdr_combustion_args { \ HTRDR_ARGS_RECTANGLE_DEFAULT__, /* Laser surface emission */ \ 532, /* Wavelength in nanometer */ \ + 1, /* FIXME Flux density */ \ \ HTRDR_ARGS_IMAGE_DEFAULT__, /* Image */ \ \ diff --git a/src/combustion/htrdr_combustion_laser.c b/src/combustion/htrdr_combustion_laser.c @@ -30,6 +30,8 @@ struct htrdr_combustion_laser { struct htrdr_rectangle* surface; /* Surface emission */ double world2local[12]; double low_ls[3], upp_ls[3]; /* Local space AABB */ + double flux_density; /* In W/m^2 */ + double wavelength; /* In nm */ ref_T ref; struct htrdr* htrdr; }; @@ -63,15 +65,29 @@ htrdr_combustion_laser_create res_T res = RES_OK; ASSERT(htrdr && args && out_laser); + if(args->flux_density <= 0) { + htrdr_log_err(htrdr, "Invalid flux density %g W.m^2\n", args->flux_density); + res = RES_BAD_ARG; + goto error; + } + + if(args->wavelength <= 0) { + htrdr_log_err(htrdr, "Invalid wavelength %g nm\n", args->wavelength); + res = RES_BAD_ARG; + goto error; + } + laser = MEM_CALLOC(htrdr_get_allocator(htrdr), 1, sizeof(*laser)); if(!laser) { htrdr_log_err(htrdr, "Could not allocate the laser data structure.\n"); - res = RES_BAD_ARG; + res = RES_MEM_ERR; goto error; } ref_init(&laser->ref); htrdr_ref_get(htrdr); laser->htrdr = htrdr; + laser->flux_density = args->flux_density; + laser->wavelength = args->wavelength; res = htrdr_rectangle_create (laser->htrdr, @@ -93,7 +109,7 @@ htrdr_combustion_laser_create laser->upp_ls[1] = args->surface.size[1] * 0.5; laser->upp_ls[2] = 0; laser->low_ls[0] = -laser->upp_ls[0]; - laser->low_ls[2] = -laser->upp_ls[1]; + laser->low_ls[1] = -laser->upp_ls[1]; laser->upp_ls[2] = INF; exit: @@ -163,3 +179,88 @@ htrdr_combustion_laser_trace_ray distance[1] = t_max; } +void +htrdr_combustion_laser_get_mesh + (const struct htrdr_combustion_laser* laser, + const double extend, + struct htrdr_combustion_laser_mesh* mesh) +{ + double transform[12]; + double low[3]; + double upp[3]; + ASSERT(laser && extend > 0 && mesh); + + htrdr_rectangle_get_transform(laser->surface, transform); + + /* Define the laser sheet vertices in local space */ + low[0] = laser->low_ls[0]; + low[1] = laser->low_ls[1]; + low[2] = laser->low_ls[2]; + upp[0] = laser->upp_ls[0]; + upp[1] = laser->upp_ls[1]; + upp[2] = laser->low_ls[2] + extend; + + /* Transform the laser sheet vertices in world space */ + d3(mesh->vertices + 0*3, low[0], low[1], low[2]); + d3(mesh->vertices + 1*3, upp[0], low[1], low[2]); + d3(mesh->vertices + 2*3, low[0], upp[1], low[2]); + d3(mesh->vertices + 3*3, upp[0], upp[1], low[2]); + d3(mesh->vertices + 4*3, low[0], low[1], upp[2]); + d3(mesh->vertices + 5*3, upp[0], low[1], upp[2]); + d3(mesh->vertices + 6*3, low[0], upp[1], upp[2]); + d3(mesh->vertices + 7*3, upp[0], upp[1], upp[2]); + mesh->nvertices = 8; + + /* Define the laser sheet triangles */ + mesh->triangles[0] = 0; mesh->triangles[1] = 2; mesh->triangles[2] = 1; + mesh->triangles[3] = 1; mesh->triangles[4] = 2; mesh->triangles[5] = 3; + mesh->triangles[6] = 0; mesh->triangles[7] = 4; mesh->triangles[8] = 2; + mesh->triangles[9] = 2; mesh->triangles[10] = 4; mesh->triangles[11] = 6; + mesh->triangles[12] = 1; mesh->triangles[13] = 3; mesh->triangles[14] = 5; + mesh->triangles[15] = 5; mesh->triangles[16] = 3; mesh->triangles[17] = 7; + mesh->triangles[18] = 1; mesh->triangles[19] = 5; mesh->triangles[20] = 0; + mesh->triangles[21] = 0; mesh->triangles[22] = 5; mesh->triangles[23] = 4; + mesh->triangles[24] = 3; mesh->triangles[25] = 2; mesh->triangles[26] = 7; + mesh->triangles[27] = 7; mesh->triangles[28] = 2; mesh->triangles[29] = 6; + mesh->ntriangles = 10; +} + +void +htrdr_combustion_laser_get_direction + (const struct htrdr_combustion_laser* laser, + double dir[3]) +{ + ASSERT(laser && dir); + htrdr_rectangle_get_normal(laser->surface, dir); +} + +double +htrdr_combustion_laser_get_flux_density + (const struct htrdr_combustion_laser* laser) +{ + ASSERT(laser); + return laser->flux_density; +} + +double +htrdr_combustion_laser_get_wavelength + (const struct htrdr_combustion_laser* laser) +{ + ASSERT(laser); + return laser->wavelength; +} + +double +htrdr_combustion_laser_compute_surface_plane_distance + (const struct htrdr_combustion_laser* laser, + const double pos[3]) +{ + double center[3]; + double normal[3]; + double vec[3]; + ASSERT(laser && pos); + htrdr_rectangle_get_normal(laser->surface, normal); + htrdr_rectangle_get_center(laser->surface, center); + d3_sub(vec, pos, center); + return d3_dot(normal, vec); +} diff --git a/src/combustion/htrdr_combustion_laser.h b/src/combustion/htrdr_combustion_laser.h @@ -22,35 +22,53 @@ #include <rsys/rsys.h> +/* Monochromatic laser */ struct htrdr_combustion_laser_create_args { struct htrdr_args_rectangle surface; /* Surface emission */ + double wavelength; /* In nanometers */ + double flux_density; /* In W/m^2 */ }; #define HTRDR_COMBUSTION_LASER_CREATE_ARGS_DEFAULT__ { \ - HTRDR_ARGS_RECTANGLE_DEFAULT__ \ + HTRDR_ARGS_RECTANGLE_DEFAULT__, \ + -1, /* Wavelength */ \ + -1, /* Flux density */ \ } static const struct htrdr_combustion_laser_create_args HTRDR_COMBUSTION_LASER_CREATE_ARGS_DEFAULT = HTRDR_COMBUSTION_LASER_CREATE_ARGS_DEFAULT__; +struct htrdr_combustion_laser_mesh { + double vertices[8/*#vertices*/*3/*#coords per vertex*/]; + /* Triangle are clock wise ordered from the inside of the laser sheet */ + unsigned triangles[10/*#triangles*/*3/*#vertices per triangle*/]; + unsigned nvertices; + unsigned ntriangles; +}; + +/* Syntactic sugar to check if a laser sheet hit is valid */ +#define HTRDR_COMBUSTION_LASER_HIT_NONE(Hit) ((Hit)[0] >= DBL_MAX) + /* Forward declaration */ struct htrdr; struct htrdr_combustion_laser; -extern LOCAL_SYM res_T +BEGIN_DECLS + +HTRDR_API res_T htrdr_combustion_laser_create (struct htrdr* htrdr, const struct htrdr_combustion_laser_create_args* args, struct htrdr_combustion_laser** laser); -extern LOCAL_SYM void +HTRDR_API void htrdr_combustion_laser_ref_get (struct htrdr_combustion_laser* laser); -extern LOCAL_SYM void +HTRDR_API void htrdr_combustion_laser_ref_put (struct htrdr_combustion_laser* laser); -extern LOCAL_SYM void +HTRDR_API void htrdr_combustion_laser_trace_ray (struct htrdr_combustion_laser* laser, const double pos[3], @@ -58,4 +76,31 @@ htrdr_combustion_laser_trace_ray const double range[2], double distance[2]); +HTRDR_API void +htrdr_combustion_laser_get_mesh + (const struct htrdr_combustion_laser* laser, + /* Max distance of the laser mesh along its infinite dimension */ + const double extend, + struct htrdr_combustion_laser_mesh* mesh); + +HTRDR_API void +htrdr_combustion_laser_get_direction + (const struct htrdr_combustion_laser* laser, + double dir[3]); /* Normalized */ + +HTRDR_API double /* In W.m^2 */ +htrdr_combustion_laser_get_flux_density + (const struct htrdr_combustion_laser* laser); + +HTRDR_API double /* In nm */ +htrdr_combustion_laser_get_wavelength + (const struct htrdr_combustion_laser* laser); + +HTRDR_API double +htrdr_combustion_laser_compute_surface_plane_distance + (const struct htrdr_combustion_laser* laser, + const double pos[3]); + +END_DECLS + #endif /* HTRDR_COMBUSTION_LASER_H */