stardis-test

Test Stardis behaviors
git clone git://git.meso-star.fr/stardis-test.git
Log | Files | Refs | README | LICENSE

commit a5e41da8bd3e495a7f3d1f204bc12942900c1607
parent 8c6fcd5e3a3b97f9dafc019587d0de2189eb989a
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue, 25 Jun 2024 14:46:37 +0200

Add a test to the custom sampling of a conductive path

Use a programmable solid on which the conductive path is sampled on the
caller's side.

Diffstat:
MMakefile | 25+++++++++++++++++++++++++
Mconfig.mk | 17++++++++++++++---
Asrc/sadist_custom_conductive_path.c | 283+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/sadist_lib_solid_sphere.c | 397+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4 files changed, 719 insertions(+), 3 deletions(-)

diff --git a/Makefile b/Makefile @@ -20,6 +20,7 @@ include config.mk TESTS =\ sadist_conducto_radiative\ + sadist_custom_conductive_path\ sadist_external_flux\ sadist_probe_boundary\ sadist_unsteady @@ -27,6 +28,7 @@ TESTS =\ LIBS =\ libsadist_radenv_1d.so\ libsadist_solid_fluid.so\ + libsadist_solid_sphere.so\ libsadist_spherical_source.so\ libsadist_trilinear_profile.so\ libsadist_unsteady_profile.so\ @@ -37,8 +39,14 @@ default: .config $(TESTS) $(LIBS) .config: @if ! $(PKG_CONFIG) --atleast-version $(RSYS_VERSION) rsys; then \ echo "rsys $(RSYS_VERSION) not found" >&2; exit 1; fi + @if ! $(PKG_CONFIG) --atleast-version $(S3D_VERSION) s3d; then \ + echo "s3d $(S3D_VERSION) not found" >&2; exit 1; fi @if ! $(PKG_CONFIG) --atleast-version $(S3DUT_VERSION) s3dut; then \ echo "s3dut $(S3DUT_VERSION) not found" >&2; exit 1; fi + @if ! $(PKG_CONFIG) --atleast-version $(SSP_VERSION) star-sp; then \ + echo "star-sp $(SSP_VERSION) not found" >&2; exit 1; fi + @if ! $(PKG_CONFIG) --atleast-version $(SSTL_VERSION) sstl; then \ + echo "sstl $(SSTL_VERSION) not found" >&2; exit 1; fi @echo "config done" > $@ clean: @@ -72,6 +80,15 @@ libsadist_solid_fluid.so: config.mk src/sadist_lib_solid_fluid.o $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -o $@ src/sadist_lib_solid_fluid.o \ $(LDFLAGS_SO) $(RSYS_LIBS) +src/sadist_lib_solid_sphere.o: config.mk src/sadist_lib_solid_sphere.c + $(CC) $(CFLAGS_SO) $(S3D_CFLAGS) $(SSP_CFLAGS) $(SSTL_CFLAGS) $(RSYS_CFLAGS) \ + -c $(@:.o=.c) -o $@ + +libsadist_solid_sphere.so: config.mk src/sadist_lib_solid_sphere.o + $(CC) $(CFLAGS_SO) $(S3D_CFLAGS) $(SSP_CFLAGS) $(SSTL_CFLAGS) $(RSYS_CFLAGS) \ + -o $@ src/sadist_lib_solid_sphere.o $(LDFLAGS_SO) $(S3D_LIBS) $(SSP_LIBS) \ + $(SSTL_LIBS) $(RSYS_LIBS) -lm + src/sadist_lib_spherical_source.o: config.mk src/sadist_lib_spherical_source.c $(CC) $(CFLAGS_SO) $(RSYS_CFLAGS) -c $(@:.o=.c) -o $@ @@ -105,6 +122,14 @@ src/sadist_conducto_radiative.o:\ sadist_conducto_radiative: config.mk src/sadist_conducto_radiative.o $(CC) $(CFLAGS_EXE) -o $@ src/$@.o $(LDFLAGS_EXE) $(RSYS_LIBS) +src/sadist_custom_conductive_path.o:\ + config.mk src/sadist.h src/sadist_custom_conductive_path.c + $(CC) $(CFLAGS_EXE) $(S3DUT_CFLAGS) $(RSYS_CFLAGS) -c $(@:.o=.c) -o $@ + +sadist_custom_conductive_path: config.mk src/sadist_custom_conductive_path.o + $(CC) $(CFLAGS_EXE) $(S3DUT_CFLAGS) $(RSYS_CFLAGS) -o $@ src/$@.o \ + $(LDFLAGS_EXE) $(S3DUT_LIBS) $(RSYS_LIBS) + src/sadist_external_flux.o:\ config.mk src/sadist.h src/sadist_external_flux.c $(CC) $(CFLAGS_EXE) -c $(@:.o=.c) -o $@ diff --git a/config.mk b/config.mk @@ -4,8 +4,8 @@ PREFIX = /usr/local LIB_TYPE = SHARED #LIB_TYPE = STATIC -BUILD_TYPE = RELEASE -#BUILD_TYPE = DEBUG +#BUILD_TYPE = RELEASE +BUILD_TYPE = DEBUG ################################################################################ # Tools @@ -25,11 +25,22 @@ RSYS_VERSION = 0.14 RSYS_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags rsys) RSYS_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs rsys) -# For tests +S3D_VERSION = 0.10 +S3D_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags s3d) +S3D_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs s3d) + S3DUT_VERSION = 0.4 S3DUT_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags s3dut) S3DUT_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs s3dut) +SSP_VERSION = 0.14 +SSP_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags star-sp) +SSP_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs star-sp) + +SSTL_VERSION = 0.5 +SSTL_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags sstl) +SSTL_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs sstl) + ################################################################################ # Compilation options ################################################################################ diff --git a/src/sadist_custom_conductive_path.c b/src/sadist_custom_conductive_path.c @@ -0,0 +1,283 @@ +/* Copyright (C) 2024 |Méso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * 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 /* popen */ + +#include "sadist.h" + +#include <stardis/stardis-prog-properties.h> + +#include <star/s3dut.h> + +#include <rsys/double2.h> +#include <rsys/double3.h> +#include <rsys/math.h> + +#include <errno.h> +#include <float.h> +#include <getopt.h> +#include <string.h> /* strerror */ +#include <wait.h> /* WIFEXITED, WEXITSTATUS */ + +/* + * The system is a trilinear profile of the temperature at steady state, i.e. at + * each point of the system we can calculate the temperature analytically. Two + * forms are immersed in this temperature field: a super shape and a sphere + * included in the super shape. On the Monte Carlo side, the temperature is + * unknown everywhere except on the surface of the super shape whose + * temperature is defined from the aformentionned trilinear profile. + * + * We will estimate the temperature at the position of a probe in solids by + * providing a user-side function to sample the conductive path in the sphere. + * We should find the temperature of the trilinear profile at the probe position + * by Monte Carlo, independently of this coupling with an external path sampling + * routine. + * + * + * /\ <-- T(x,y,z) + * ___/ \___ + * T(z) \ __ / + * | T(y) T=?/. \ / + * |/ / \__/ \ + * o--- T(x) /_ __ _\ + * \/ \/ + */ + +#define FILENAME_SSHAPE "sshape.stl" +#define FILENAME_SPHERE "sphere.stl" +#define FILENAME_SCENE "scene.txt" + +/* Temperature at the upper bound of the X, Y and Z axis. The temperature at the + * lower bound is implicitly 0 K */ +#define TX 333.0 /* [K] */ +#define TY 432.0 /* [K] */ +#define TZ 579.0 /* [K] */ + +/* Probe position */ +#define PX 0.125 +#define PY 0.250 +#define PZ 0.375 + +/* Commands to calculate probe temperature */ +#define COMMAND "stardis -V3 -p "STR(PX)","STR(PY)","STR(PZ)" -M "FILENAME_SCENE + +/* Axis Aligned Bounding Box */ +struct aabb { + double lower[3]; + double upper[3]; +}; +#define AABB_NULL__ {{DBL_MAX,DBL_MAX,DBL_MAX}, {-DBL_MAX,-DBL_MAX,-DBL_MAX}} +static const struct aabb AABB_NULL = AABB_NULL__; + + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +aabb_update(struct aabb* aabb, const struct s3dut_mesh_data* mesh) +{ + size_t ivertex = 0; + ASSERT(aabb); + + FOR_EACH(ivertex, 0, mesh->nvertices) { + const double* vertex = mesh->positions + ivertex*3; + aabb->lower[0] = MMIN(aabb->lower[0], vertex[0]); + aabb->lower[1] = MMIN(aabb->lower[1], vertex[1]); + aabb->lower[2] = MMIN(aabb->lower[2], vertex[2]); + aabb->upper[0] = MMAX(aabb->upper[0], vertex[0]); + aabb->upper[1] = MMAX(aabb->upper[1], vertex[1]); + aabb->upper[2] = MMAX(aabb->upper[2], vertex[2]); + } +} + +static void +setup_sshape(FILE* stream, struct aabb* aabb) +{ + struct s3dut_mesh* sshape = NULL; + struct s3dut_mesh_data sshape_data; + struct s3dut_super_formula f0 = S3DUT_SUPER_FORMULA_NULL; + struct s3dut_super_formula f1 = S3DUT_SUPER_FORMULA_NULL; + const double radius = 2; + const unsigned nslices = 256; + + f0.A = 1.5; f0.B = 1; f0.M = 11.0; f0.N0 = 1; f0.N1 = 1; f0.N2 = 2.0; + f1.A = 1.0; f1.B = 2; f1.M = 3.6; f1.N0 = 1; f1.N1 = 2; f1.N2 = 0.7; + S3DUT(create_super_shape(NULL, &f0, &f1, radius, nslices, nslices/2, &sshape)); + S3DUT(mesh_get_data(sshape, &sshape_data)); + + aabb_update(aabb, &sshape_data); + sadist_write_stl(stream, sshape_data.positions, sshape_data.nvertices, + sshape_data.indices, sshape_data.nprimitives); + + S3DUT(mesh_ref_put(sshape)); +} + +static void +setup_sphere(FILE* stream, struct aabb* aabb) +{ + struct s3dut_mesh* sphere = NULL; + struct s3dut_mesh_data sphere_data; + const double radius = 1; + const unsigned nslices = 128; + + S3DUT(create_sphere(NULL, radius, nslices, nslices/2, &sphere)); + S3DUT(mesh_get_data(sphere, &sphere_data)); + + aabb_update(aabb, &sphere_data); + sadist_write_stl(stream, sphere_data.positions, sphere_data.nvertices, + sphere_data.indices, sphere_data.nprimitives); + + S3DUT(mesh_ref_put(sphere)); +} + +static void +setup_scene + (FILE* fp, + const char* sshape, + const char* sphere, + const struct aabb* aabb, + struct sadist_trilinear_profile* profile) +{ + double low, upp; + ASSERT(sshape && sphere && aabb && profile); + + fprintf(fp, "PROGRAM solid_sphere libsadist_solid_sphere.so\n"); + fprintf(fp, "PROGRAM trilinear_profile libsadist_trilinear_profile.so\n"); + fprintf(fp, "SOLID SuperShape 25 7500 500 0.05 0 UNKNOWN 0 BACK %s FRONT %s\n", + sshape, sphere); + fprintf(fp, "SOLID_PROG Sphere solid_sphere BACK %s ", sphere); + + /* StL lambda rho cp radius */ + fprintf(fp, "PROG_PARAMS -m %s -l25 -r7500 -c500 -R1\n", FILENAME_SPHERE); + + low = MMIN(MMIN(aabb->lower[0], aabb->lower[1]), aabb->lower[2]); + upp = MMAX(MMAX(aabb->upper[0], aabb->upper[1]), aabb->upper[2]); + fprintf(fp, "T_BOUNDARY_FOR_SOLID_PROG Dirichlet trilinear_profile %s", sshape); + fprintf(fp, " PROG_PARAMS -b %g,%g -t %g,%g,%g\n", low, upp, TX, TY, TZ); + + d3_splat(profile->lower, low); + d3_splat(profile->upper, upp); + d2(profile->a, 0, TX); + d2(profile->b, 0, TY); + d2(profile->c, 0, TZ); +} + +static int +init(struct sadist_trilinear_profile* profile) +{ + struct aabb aabb = AABB_NULL; + FILE* fp_sshape = NULL; + FILE* fp_sphere = NULL; + FILE* fp_scene = NULL; + int err = 0; + + #define FOPEN(Fp, Filename) \ + if(((Fp) = fopen((Filename), "w")) == NULL) { \ + fprintf(stderr, "Error opening `%s' -- file %s\n", \ + (Filename), strerror(errno)); \ + err = errno; \ + goto error; \ + } (void)0 + FOPEN(fp_sshape, FILENAME_SSHAPE); + FOPEN(fp_sphere, FILENAME_SPHERE); + FOPEN(fp_scene, FILENAME_SCENE); + #undef FOPEN + + setup_sshape(fp_sshape, &aabb); + setup_sphere(fp_sphere, &aabb); + setup_scene(fp_scene, FILENAME_SSHAPE, FILENAME_SPHERE, &aabb, profile); + +exit: + #define FCLOSE(Fp) \ + if((Fp) && fclose(Fp)) { perror("fclose"); if(!err) err = errno; } (void)0 + FCLOSE(fp_sshape); + FCLOSE(fp_sphere); + FCLOSE(fp_scene); + #undef FCLOSE + return err; +error: + goto exit; +} + +static int +run(const struct sadist_trilinear_profile* profile) +{ + const double P[3] = {PX, PY, PZ}; + + FILE* output = NULL; + double E = 0; + double SE = 0; + double ref = 0; + + int n = 0; + int err = 0; + int status = 0; + + printf("%s\n", COMMAND); + + if(!(output = popen(COMMAND, "r"))) { + fprintf(stderr, "Error executing stardis -- %s\n", strerror(errno)); + err = errno; + goto error; + } + + if((n = fscanf(output, "%lf %lf %*d %*d", &E, &SE)), n != 2 && n != EOF) { + fprintf(stderr, "Error reading the output stream -- %s\n", strerror(errno)); + err = errno; + goto error; + } + + /* Check command exit status */ + if((status=pclose(output)), output=NULL, status) { + if(status == -1) err = errno; + else if(WIFEXITED(status)) err = WEXITSTATUS(status); + else if(WIFSIGNALED(status)) err = WTERMSIG(status); + else if(WIFSTOPPED(status)) err = WSTOPSIG(status); + else FATAL("Unreachable code.\n"); + goto error; + } + + ref = sadist_trilinear_profile_temperature(profile, P); + printf("T = %g ~ %g +/- %g\n", ref, E, SE); + if(!eq_eps(ref, E, SE*3)) { + err = 1; + goto error; + } + +exit: + if(output) pclose(output); + return err; +error: + goto exit; +} + +/******************************************************************************* + * The test + ******************************************************************************/ +int +main(int argc, char** argv) +{ + struct sadist_trilinear_profile profile = SADIST_TRILINEAR_PROFILE_NULL; + int err; + (void)argc, (void)argv; + + if((err = init(&profile))) goto error; + if((err = run(&profile))) goto error; + +exit: + return err; +error: + goto exit; +} diff --git a/src/sadist_lib_solid_sphere.c b/src/sadist_lib_solid_sphere.c @@ -0,0 +1,397 @@ +/* Copyright (C) 2024 |Méso|Star> (contact@meso-star.com) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#include <stardis/stardis-prog-properties.h> + +#include <star/s3d.h> +#include <star/ssp.h> +#include <star/sstl.h> + +#include <rsys/cstr.h> +#include <rsys/double3.h> +#include <rsys/mem_allocator.h> + +#include <getopt.h> + +struct args { + const char* stl; + double lambda; /* [W/m/K] */ + double rho; /* [kg/m^3] */ + double cp; /* [J/K/kg] */ + double radius; /* [m/fp_to_meter] */ +}; +#define ARGS_DEFAULT__ {NULL,1,1,1,1} +static const struct args ARGS_DEFAULT = ARGS_DEFAULT__; + +/* Define a solid sphere */ +struct solid_sphere { + struct s3d_scene_view* view; + double lambda; /* [W/m/K] */ + double rho; /* [kg/m^3] */ + double cp; /* [J/K/kg] */ + double radius; /* [m/fp_to_meter] */ +}; +#define SOLID_SPHERE_NULL__ {NULL,0,0,0,0} +static const struct solid_sphere SOLID_SPHERE_NULL = SOLID_SPHERE_NULL__; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +get_indices(const unsigned itri, unsigned ids[3], void* ctx) +{ + const struct sstl_desc* desc = ctx; + ASSERT(desc && itri < desc->triangles_count); + ids[0] = desc->indices[itri*3+0]; + ids[1] = desc->indices[itri*3+1]; + ids[2] = desc->indices[itri*3+2]; +} + +static void +get_position(const unsigned ivert, float pos[3], void* ctx) +{ + const struct sstl_desc* desc = ctx; + ASSERT(desc && ivert < desc->vertices_count); + pos[0] = desc->vertices[ivert*3+0]; + pos[1] = desc->vertices[ivert*3+1]; + pos[2] = desc->vertices[ivert*3+2]; +} + +static struct s3d_scene_view* +create_scene_view(const char* filename) +{ + /* Star-STL */ + struct sstl_desc desc; + struct sstl* sstl = NULL; + + /* Star3D */ + struct s3d_vertex_data vdata = S3D_VERTEX_DATA_NULL; + struct s3d_device* dev = NULL; + struct s3d_scene* scn = NULL; + struct s3d_shape* shape = NULL; + struct s3d_scene_view* view = NULL; + + res_T res = RES_OK; + ASSERT(filename); + + if((res = sstl_create(NULL, NULL, 1, &sstl)) != RES_OK) goto error; + if((res = sstl_load(sstl, filename)) != RES_OK) goto error; + if((res = sstl_get_desc(sstl, &desc)) != RES_OK) goto error; + + if((res = s3d_device_create(NULL, NULL, 0, &dev)) != RES_OK) goto error; + if((res = s3d_scene_create(dev, &scn)) != RES_OK) goto error; + if((res = s3d_shape_create_mesh(dev, &shape)) != RES_OK) goto error; + if((res = s3d_scene_attach_shape(scn, shape)) != RES_OK) goto error; + + vdata.usage = S3D_POSITION; + vdata.type = S3D_FLOAT3; + vdata.get = get_position; + res = s3d_mesh_setup_indexed_vertices(shape, + (unsigned int)desc.triangles_count, get_indices, + (unsigned int)desc.vertices_count, &vdata, 1, &desc); + if(res != RES_OK) goto error; + + res = s3d_scene_view_create(scn, S3D_TRACE|S3D_GET_PRIMITIVE, &view); + if(res != RES_OK) goto error; + +exit: + if(sstl) SSTL(ref_put(sstl)); + if(dev) S3D(device_ref_put(dev)); + if(scn) S3D(scene_ref_put(scn)); + if(shape) S3D(shape_ref_put(shape)); + return view; +error: + if(view) { S3D(scene_view_ref_put(view)); view = NULL; } + goto exit; +} + +static void +print_usage(FILE* stream, const char* name) +{ + ASSERT(name); + fprintf(stream, + "usage: %s -m mesh [-c capa] [-h] [-l lambda] [-R radius] [-r rho]\n", + name); +} + +static res_T +parse_args + (const struct stardis_description_create_context* ctx, + struct args* args, + const int argc, + char* argv[]) +{ + int opt = 0; + res_T res = RES_OK; + + /* Check pre-conditions */ + ASSERT(ctx && args); + *args = ARGS_DEFAULT; + + optind = 1; + while((opt = getopt(argc, argv, "c:hl:m:R:r:")) != -1) { + switch(opt) { + case 'c': + res = cstr_to_double(optarg, &args->cp); + if(res == RES_OK && args->cp <= 0) res = RES_BAD_ARG; + break; + case 'h': + print_usage(stdout, argv[0]); + break; + case 'l': + res = cstr_to_double(optarg, &args->lambda); + if(res == RES_OK && args->lambda <= 0) res = RES_BAD_ARG; + break; + case 'm': + args->stl = optarg; + break; + case 'R': + res = cstr_to_double(optarg, &args->radius); + if(res == RES_OK && args->radius <= 0) res = RES_BAD_ARG; + break; + case 'r': + res = cstr_to_double(optarg, &args->rho); + if(res == RES_OK && args->rho <= 0) res = RES_BAD_ARG; + break; + default: res = RES_BAD_ARG; break; + } + if(res != RES_OK) { + if(optarg) { + fprintf(stderr, "%s: invalid option argument '%s' -- '%c'\n", + ctx->name, optarg, opt); + } + goto error; + } + } + + if(!args->stl) { + fprintf(stderr, "%s: missing mesh -- option '-m'\n", argv[0]); + res = RES_BAD_ARG; + goto error; + } + +exit: + return res; +error: + goto exit; +} + +/******************************************************************************* + * Create data + ******************************************************************************/ +void* +stardis_create_data + (const struct stardis_description_create_context *ctx, + void* libdata, + size_t argc, + char* argv[]) +{ + struct args args = ARGS_DEFAULT__; + struct solid_sphere* solid = NULL; + res_T res = RES_OK; + (void)libdata; + + solid = mem_alloc(sizeof(*solid)); + if(!solid) { + fprintf(stderr, "%s:%d: error allocating the solid sphere.\n", + __FILE__, __LINE__); + goto error; + } + *solid = SOLID_SPHERE_NULL; + + res = parse_args(ctx, &args, (int)argc, argv); + if(res != RES_OK) goto error; + + solid->lambda = args.lambda; + solid->rho = args.rho; + solid->cp = args.cp; + solid->radius = args.radius; + + if(!(solid->view = create_scene_view(args.stl))) goto error; + +exit: + return solid; +error: + if(solid) { + stardis_release_data(solid); + solid = NULL; + } + goto exit; +} + +void +stardis_release_data(void* data) +{ + struct solid_sphere* solid = data; + ASSERT(solid); + if(solid->view) S3D(scene_view_ref_put(solid->view)); + mem_rm(solid); +} + +/******************************************************************************* + * Solid properties + ******************************************************************************/ +double +stardis_calorific_capacity(const struct stardis_vertex* vtx, void* data) +{ + const struct solid_sphere* sphere = data; + (void)vtx; + return sphere->cp; +} + +double +stardis_volumic_mass(const struct stardis_vertex* vtx, void* data) +{ + const struct solid_sphere* sphere = data; + (void)vtx; + return sphere->rho; +} + +double +stardis_conductivity(const struct stardis_vertex* vtx, void* data) +{ + const struct solid_sphere* sphere = data; + (void)vtx; + return sphere->lambda; +} + +double +stardis_delta_solid(const struct stardis_vertex* vtx, void* data) +{ + const struct solid_sphere* sphere = data; + (void)vtx; + return sphere->radius/20.0; +} + +double +stardis_volumic_power(const struct stardis_vertex* vtx, void* data) +{ + (void)vtx, (void)data; + return STARDIS_VOLUMIC_POWER_NONE; +} + +double +stardis_medium_temperature(const struct stardis_vertex* vtx, void* data) +{ + (void)vtx, (void)data; + return STARDIS_TEMPERATURE_NONE; +} + +int +stardis_sample_conductive_path + (struct sdis_scene* scn, + struct ssp_rng* rng, + struct stardis_path* path, + void* data) +{ + const struct solid_sphere* sphere = data; + struct s3d_hit hit = S3D_HIT_NULL; + struct s3d_attrib attr0, attr1, attr2; + + double pos[3]; + double epsilon = 0; + ASSERT(scn && rng && path && data); + (void)scn; + + epsilon = sphere->radius * 1.e-6; /* Epsilon shell */ + + d3_set(pos, path->vtx.P); + + do { + /* Distance from the geometry center to the current position */ + const double dst = d3_len(pos); + + double dir[3] = {0,0,0}; + double r = 0; /* Radius */ + + r = sphere->radius - dst; + CHK(dst > 0); + + if(r > epsilon) { + /* Uniformly sample a new position on the surrounding sphere */ + ssp_ran_sphere_uniform(rng, dir, NULL); + + /* Move to the new position */ + d3_muld(dir, dir, r); + d3_add(pos, pos, dir); + + /* The current position is in the epsilon shell: + * move it to the nearest interface position */ + } else { + float posf[3]; + + d3_set(dir, pos); + d3_normalize(dir, dir); + d3_muld(pos, dir, sphere->radius); + + /* Map the position to the sphere geometry */ + f3_set_d3(posf, pos); + S3D(scene_view_closest_point(sphere->view, posf, (float)INF, NULL, &hit)); + } + + /* The calculation is performed in steady state, so the path necessarily stops + * at a boundary */ + } while(S3D_HIT_NONE(&hit)); + + /* Setup the path state */ + d3_set(path->vtx.P, pos); + path->weight = 0; + path->at_limit = 0; + + /* Configure the intersecting primitive. The vertices must be exactly the same + * (i.e. bit-compatible) as those used internally by Stardis, as they are used + * as the key to retrieve the corresponding Stardis triangle. Note that + * Stardis also uses Star-STL internally to load its geometry. As a result, + * the in-memory representation of the loaded data is the same between Stardis + * and the current code, i.e. single-precision floating point. And Star-3D + * also uses the same representation. We can therefore use Star-3D data + * directly to define the coordinates of the vertices of the intersecting + * primitive */ + S3D(triangle_get_vertex_attrib(&hit.prim, 0, S3D_POSITION, &attr0)); + S3D(triangle_get_vertex_attrib(&hit.prim, 1, S3D_POSITION, &attr1)); + S3D(triangle_get_vertex_attrib(&hit.prim, 2, S3D_POSITION, &attr2)); + d3_set_f3(path->tri.vtx0, attr0.value); + d3_set_f3(path->tri.vtx1, attr1.value); + d3_set_f3(path->tri.vtx2, attr2.value); + + return RES_OK; +} + +/******************************************************************************* + * Legal notices + ******************************************************************************/ +const char* +get_copyright_notice(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return "Copyright (C) 2024 |Méso|Star> (contact@meso-star.com)"; +} + +const char* +get_license_short(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return "GNU GPL version 3 or later <http://www.gnu.org/licenses/>"; +} + +const char* +get_license_text(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return + "This is free software released under the GPL v3+ license: GNU GPL\n" + "version 3 or later. You are welcome to redistribute it under certain\n" + "conditions; refer to <http://www.gnu.org/licenses/> for details."; +}