stardis

Perform coupled heat transfer calculations
git clone git://git.meso-star.fr/stardis.git
Log | Files | Refs | README | LICENSE

commit e33c2d32b1676023beec4c3dd9cb1d54af463a85
parent 4bc6aef5b7a422caca699576309edfeb101c73a8
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 17 Jul 2024 11:25:24 +0200

Merge branch 'release_0.11'

Diffstat:
MREADME.md | 47++++++++++++++++++++++++++++++++++++++++++++++-
Mconfig.mk | 8++++----
Mdoc/stardis-output.5 | 26+++++++++-----------------
Mdoc/stardis.1.in | 6+++++-
Msrc/stardis-app.h | 7+++++--
Msrc/stardis-compute-probe-boundary.c | 22++++++++--------------
Msrc/stardis-fbound-prog.c | 6++++--
Msrc/stardis-fluid-prog.c | 12++++++++----
Msrc/stardis-fluid-prog.h | 1-
Msrc/stardis-hbound-prog.c | 7+++++--
Msrc/stardis-hfbound-prog.c | 7+++++--
Msrc/stardis-intface.c | 40+++++++++++++++++++++++++++-------------
Msrc/stardis-parsing.c | 180++++++++++++++++++++++++++++++++++++++-----------------------------------------
Msrc/stardis-prog-properties.h.in | 187++++++++++++++++++++++++++++++++++++++++++++++++-------------------------------
Msrc/stardis-program.c | 6++++--
Msrc/stardis-sfconnect-prog.c | 6++++--
Msrc/stardis-solid-prog.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----
Msrc/stardis-solid-prog.h | 9++++++++-
Msrc/stardis-ssconnect-prog.c | 6++++--
Msrc/stardis-tbound-prog.c | 6++++--
20 files changed, 409 insertions(+), 244 deletions(-)

diff --git a/README.md b/README.md @@ -33,6 +33,52 @@ Edit config.mk as needed, then run: ## Release notes +### Version 0.11 + +#### Programmable properties + +- Custom sampling of conductive paths. On programmable solids, users + can now define the new `stardis_sampling_conductive_path` function, in + which they can write their own sampling process. As input, the + function takes a path whose spatio-temporal position lies within the + programmable solid. Once the path has been sampled, this position is + updated and can be either within the solid if the initial condition is + reached, or at the boundary, i.e. at a boundary condition. Stardis + then continues the path sampling procedure in relation to the returned + state. +- Addition of the property name as the first argument of the input + string sent to the programmable data creation functions. Not only is + this useful information, it also respects the convention of program + arguments. In this way, the standard getopt function can be used + directly to analyze them. +- Addition of symbolic constants to the public API for programmable + properties. The constants added are those defining an unknown + temperature, and constants characterizing null flux or null volumic + power. + +#### Manual pages + +- Document the `-n` option which defines the number of realisations. Its + documentation was missing from the `stardis` manual page. +- Correction of the title of the `stardis-output` manual page. It was + defined as `stardis-input`. +- Updated the layout of the `stardis-output` manual page. When converted + to HTML, the width of the columns changed from one list to another, + resulting in an unstructured layout. + +#### Miscellaneous + +- Correction of the Dirichlet boundary condition definition. No + reference temperature was defined on a surface oriented towards a + fluid and on which a Dirichlet boundary condition was imposed + (keywords `T_BOUNDARY_FOR_SOLID[_PROG]`). Stardis therefore notified an + error and rejected radiative trajectories reaching such interfaces + without a reference temperature. From now on, its reference + temperature is implicitly defined as the set temperature value. +- Removal of a warning message when calculating a list of boundary + probes. It incorrectly warned that the side of the boundary on which + the probe was located was not defined. + ### Version 0.10.1 Add a pkg-config file to support the use of Stardis header files such as @@ -283,4 +329,3 @@ Copyright (C) 2018-2024 |Méso|Star> (<contact@meso-star.com>) Stardis is free software released under the GPL v3+ license: GNU GPL version 3 or later. You are welcome to redistribute it under certain conditions; refer to the COPYING file for details. - diff --git a/config.mk b/config.mk @@ -1,6 +1,6 @@ VERSION_MAJOR = 0 -VERSION_MINOR = 10 -VERSION_PATCH = 1 +VERSION_MINOR = 11 +VERSION_PATCH = 0 VERSION = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) PREFIX = /usr/local @@ -74,11 +74,11 @@ S3D_VERSION = 0.10 S3D_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags s3d) S3D_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs s3d) -SDIS_VERSION = 0.15.1 +SDIS_VERSION = 0.16 SDIS_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags sdis) SDIS_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs sdis) -SENC3D_VERSION = 0.5 +SENC3D_VERSION = 0.7.2 SENC3D_CFLAGS = $$($(PKG_CONFIG) $(PCFLAGS) --cflags senc3d) SENC3D_LIBS = $$($(PKG_CONFIG) $(PCFLAGS) --libs senc3d) diff --git a/doc/stardis-output.5 b/doc/stardis-output.5 @@ -13,7 +13,7 @@ .\" You should have received a copy of the GNU General Public License .\" along with this program. If not, see <http://www.gnu.org/licenses/>. .Dd April 12, 2024 -.Dt STARDIS-INPUT 5 +.Dt STARDIS-OUTPUT 5 .Os .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .\" Name and short description @@ -112,30 +112,26 @@ or an extended format that mixes numbers and their descriptions .It Ta \& \& | Ta Ao Va medium-temp Ac # Option Fl m .It Ta \& \& | Ta Ao Va mean-temp Ac # Option Fl s .It Ta \& \& | Ta Ao Va mean-flux Ac # Option Fl F -.El +.It \ Ta Ta .\" Probe temperature -.Bl -column (******************) (::=) () .It Ao Va probe-temp Ac Ta ::= Ta Ao Va probe-temp-raw Ac | Ao Va probe-temp-ext Ac .It Ao Va probe-temp-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va failures Ac .It Ao Va probe-temp-ext Ac Ta ::= Ta Li Temperature at Ao Va position Ac Ao Va time Ac \e .It Ta Ta Ao Va estimate-temp-ext Ac Ao Va failures-ext Ac -.El +.It \ Ta Ta .\" Medium temperature -.Bl -column (******************) (::=) () .It Ao Va medium-temp Ac Ta ::= Ta Ao Va medium-temp-raw Ac | Ao Va medium-temp-ext Ac .It Ao Va medium-temp-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va failures Ac .It Ao Va medium-temp-ext Ac Ta ::= Ta Li Temperature in medium Ao Va medium-name Ac \e .It Ta Ta Ao Va time Ac Ao Va estimate-temp-ext Ac Ao Va failures-ext Ac -.El +.It \ Ta Ta .\" Mean temperature -.Bl -column (******************) (::=) () .It Ao Va mean-temp Ac Ta ::= Ta Ao Va mean-temp-raw Ac | Ao Va mean-temp-ext Ac .It Ao Va mean-temp-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va failures Ac .It Ao Va mean-temp-ext Ac Ta ::= Ta Li Temperature at boundary Ao Va stl-path Ac \e .It Ta Ta Ao Va time Ac Ao Va estimate-temp-ext Ac Ao Va failures-ext Ac -.El +.It \ Ta Ta .\" Mean flux -.Bl -column (******************) (::=) () .It Ao Va mean-flux Ac Ta ::= Ta Ao Va mean-flux-raw Ac | Ao Va mean-flux-ext Ac .It Ao Va mean-flux-raw Ac Ta ::= Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va estimate Ac \e .It Ta Ta Ao Va estimate Ac Ao Va estimate Ac Ao Va failures Ac @@ -150,21 +146,18 @@ or an extended format that mixes numbers and their descriptions .It Ta Ta Li Total flux at boundary Ao Va stl-path Ac \e .It Ta Ta Ao Va time Ac Ao Va estimate-flux-ext Ac .It Ta Ta Ao Va failures-ext Ac -.El +.It \ Ta Ta .\" Miscellaneous -.Bl -column (******************) (::=) () .It Ao Va estimate Ac Ta ::= Ta Ao Va expected-value Ac Ao Va standard-error Ac .It Ao Va estimate-temp-ext Ac Ta ::= Ta Ao Va expected-value Ac Li K +/- Ao Va standard-error Ac .It Ao Va estimate-flux-ext Ac Ta ::= Ta Ao Va expected-value Ac Li W +/- Ao Va standard-error Ac .It Ao Va expected-value Ac Ta ::= Ta Vt real .It Ao Va standard-error Ac Ta ::= Ta Vt real -.El -.Bl -column (******************) (::=) () +.It \ Ta Ta .It Ao Va failures Ac Ta ::= Ta Ao Va error-count Ac Ao Va success-count Ac .It Ao Va error-count Ac Ta ::= Ta Vt integer .It Ao Va success-count Ac Ta ::= Ta Vt integer -.El -.Bl -column (******************) (::=) () +.It \ Ta Ta .It Ao Va position Ac Ta ::= Ta [ Vt real , Vt real , Vt real ] .It Ao Va time Ac Ta ::= Ta Li at t= Ns Vt real .It Ta \& \& | Ta Li with t in [ Vt real , Vt real ] @@ -510,8 +503,7 @@ List the file identifier in which each triangle first appeared: .It Ta Ta Li LOOKUP_TABLE default .It Ta Ta Aq Va file-rank .It Ta Ta ... # Up to Aq Va #triangles -.El -.Bl -column (******************) (::=) () +.It \ Ta Ta .It Ao Va #vertices Ac Ta ::= Ta Vt integer .It Ao Va #triangles Ac Ta ::= Ta Vt integer .It Ao Va #triangles*4 Ac Ta ::= Ta Vt integer diff --git a/doc/stardis.1.in b/doc/stardis.1.in @@ -12,7 +12,7 @@ .\" .\" You should have received a copy of the GNU General Public License .\" along with this program. If not, see <http://www.gnu.org/licenses/>. -.Dd April 26, 2024 +.Dd June 17, 2024 .Dt STARDIS 1 .Os .Sh NAME @@ -271,6 +271,10 @@ The medium name must be part of the description. By default the compute time is @STARDIS_ARGS_DEFAULT_COMPUTE_TIME@. The medium region does not need to be connex. +.It Fl n Ar samples_count +Number of Monte Carlo realisations. +By default, the number of realisations is +@STARDIS_ARGS_DEFAULT_SAMPLES_COUNT@. .It Fl o Ar picard_order Determine the iteration level used with the Picard method to deal with non-linear radiative transfer accross the model. diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -34,7 +34,7 @@ #include <sdis.h> #ifdef STARDIS_ENABLE_MPI -#include <mpi.h> + #include <mpi.h> #endif /* Forward declarations */ @@ -216,6 +216,10 @@ struct stardis { struct compute_surface compute_surface; /* 2D compute region when mode is [FLUX_]BOUNDARY_COMPUTE or MAP_COMPUTE */ + + /* Min/Max temperatures used to linearize radiative transfer */ + double t_range[2]; /* [K] */ + struct str dump_model_filename; struct str paths_filename; struct str bin_green_filename; @@ -230,7 +234,6 @@ struct stardis { int radenv_def; size_t samples; double scale_factor; - double t_range[2]; double initial_time; /* [s] */ int mode; unsigned nthreads; diff --git a/src/stardis-compute-probe-boundary.c b/src/stardis-compute-probe-boundary.c @@ -342,10 +342,6 @@ move_to_boundary double proj_pos[3] = {0,0,0}; size_t iprim = 0; - /* Properties */ - const struct description* desc_list = NULL; - const struct description* desc = NULL; - unsigned desc_ids[SG3D_PROP_TYPES_COUNT__]; /* Miscellaneous */ size_t nvertices_close = 0; @@ -355,19 +351,17 @@ move_to_boundary ASSERT(stardis && pos && time >= 0 && out_iprim && uv); ERR(find_closest_point(stardis, pos, &filter_ctx, &iprim, uv)); - SG3D(geometry_get_unique_triangle_properties - (stardis->geometry.sg3d, (unsigned)iprim, desc_ids)); - desc_list = darray_descriptions_cdata_get(&stardis->descriptions); + if(filter_ctx.side != SG3D_INTFACE) { + /* Properties */ + const struct description* desc_list = NULL; + const struct description* desc = NULL; + unsigned desc_ids[SG3D_PROP_TYPES_COUNT__]; - /* Undefined medium */ - if(filter_ctx.side == SG3D_INTFACE - || desc_ids[filter_ctx.side] == SG3D_UNSPECIFIED_PROPERTY) { - logger_print(stardis->logger, LOG_WARNING, - "Could not determine the medium probe is in.\n"); - } + SG3D(geometry_get_unique_triangle_properties + (stardis->geometry.sg3d, (unsigned)iprim, desc_ids)); - if(filter_ctx.side != SG3D_INTFACE) { + desc_list = darray_descriptions_cdata_get(&stardis->descriptions); /* Probe is outside the system */ if(desc_ids[filter_ctx.side] == SG3D_UNSPECIFIED_PROPERTY) { diff --git a/src/stardis-fbound-prog.c b/src/stardis-fbound-prog.c @@ -82,14 +82,16 @@ str_print_f_boundary_prog { res_T res = RES_OK; ASSERT(str && b); + ASSERT(b->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed F boundary for SOLID '%s': lib='%s', " "(using medium %u as external medium)", str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); - if(b->argc > 0) { + if(b->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < b->argc; i++) { + for(i = 1; i < b->argc; i++) { ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); } } diff --git a/src/stardis-fluid-prog.c b/src/stardis-fluid-prog.c @@ -24,7 +24,6 @@ #include <limits.h> - /******************************************************************************* * Local Functions ******************************************************************************/ @@ -59,9 +58,11 @@ fluid_prog_get_temperature { const struct fluid_prog* const* fluid_props = sdis_data_cget(data); struct stardis_vertex v; + double temp = 0; d3_set(v.P, vtx->P); v.time = vtx->time; - return (*fluid_props)->temp(&v, (*fluid_props)->prog_data); + temp = (*fluid_props)->temp(&v, (*fluid_props)->prog_data); + return STARDIS_TEMPERATURE_IS_KNOWN(temp) ? temp : SDIS_TEMPERATURE_NONE;; } /******************************************************************************* @@ -188,13 +189,16 @@ str_print_fluid_prog(struct str* str, const struct fluid_prog* f) { res_T res = RES_OK; ASSERT(str && f); + ASSERT(f->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed fluid '%s': lib='%s', it is medium %u)", str_cget(&f->name), str_cget(&f->prog_name), f->fluid_id)); - if(f->argc > 0) { + + if(f->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < f->argc; i++) { + for(i = 1; i < f->argc; i++) { ERR(str_append_printf(str, (i+1 == f->argc ? "\t%s" : "\t%s\n"), f->argv[i])); } } diff --git a/src/stardis-fluid-prog.h b/src/stardis-fluid-prog.h @@ -45,7 +45,6 @@ struct fluid_prog { double (*rho)(const struct stardis_vertex*, void*); double (*cp)(const struct stardis_vertex*, void*); double (*temp)(const struct stardis_vertex*, void*); - double* (*t_range)(void*, double trange[2]); }; res_T diff --git a/src/stardis-hbound-prog.c b/src/stardis-hbound-prog.c @@ -85,17 +85,20 @@ str_print_h_boundary_prog res_T res = RES_OK; const struct h_boundary_prog* b; ASSERT(str && desc && DESC_IS_H(desc)); + b = desc->d.h_boundary_prog; + ASSERT(b->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed H boundary for %s '%s': lib='%s', " "(using medium %u as external medium)", (desc->type == DESC_BOUND_H_FOR_SOLID_PROG ? "solid" : "fluid"), str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); - if(b->argc > 0) { + if(b->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < b->argc; i++) { + for(i = 1; i < b->argc; i++) { ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); } } diff --git a/src/stardis-hfbound-prog.c b/src/stardis-hfbound-prog.c @@ -85,17 +85,20 @@ str_print_hf_boundary_prog res_T res = RES_OK; const struct hf_boundary_prog* b; ASSERT(str && desc && DESC_IS_HF(desc)); + b = desc->d.hf_boundary_prog; + ASSERT(b->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed HF boundary for %s '%s': lib='%s', " "(using medium %u as external medium)", (desc->type == DESC_BOUND_HF_FOR_SOLID_PROG ? "solid" : "fluid"), str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); - if(b->argc > 0) { + if(b->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < b->argc; i++) { + for(i = 1; i < b->argc; i++) { ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); } } diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -126,13 +126,15 @@ intface_prog_get_temp { const struct intface* interface_props = sdis_data_cget(data); struct stardis_interface_fragment f; + double temp; d3_set(f.P, frag->P); d3_set(f.Ng, frag->Ng); d3_set(f.uv, frag->uv); f.time = frag->time; ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; - return interface_props->get_temp(&f, interface_props->prog_data); + temp = interface_props->get_temp(&f, interface_props->prog_data); + return STARDIS_TEMPERATURE_IS_KNOWN(temp) ? temp : SDIS_TEMPERATURE_NONE; } static double @@ -142,13 +144,15 @@ intface_prog_get_flux { const struct intface* interface_props = sdis_data_cget(data); struct stardis_interface_fragment f; + double flux; d3_set(f.P, frag->P); d3_set(f.Ng, frag->Ng); d3_set(f.uv, frag->uv); f.time = frag->time; ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; - return interface_props->get_flux(&f, interface_props->prog_data); + flux = interface_props->get_flux(&f, interface_props->prog_data); + return flux != STARDIS_FLUX_NONE ? flux : SDIS_FLUX_NONE; } static double @@ -170,39 +174,39 @@ intface_prog_get_hc static double intface_prog_get_emissivity (const struct sdis_interface_fragment* frag, - const unsigned source_id, + const unsigned src_id, struct sdis_data* data) { const struct intface* interface_props = sdis_data_cget(data); struct stardis_interface_fragment f; - (void)source_id; + unsigned id; d3_set(f.P, frag->P); d3_set(f.Ng, frag->Ng); d3_set(f.uv, frag->uv); f.time = frag->time; ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; - return interface_props->get_emissivity - (&f, source_id, interface_props->prog_data); + id = src_id != SDIS_INTERN_SOURCE_ID ? src_id : STARDIS_INTERN_SOURCE_ID; + return interface_props->get_emissivity(&f, id, interface_props->prog_data); } static double intface_prog_get_alpha (const struct sdis_interface_fragment* frag, - const unsigned source_id, + const unsigned src_id, struct sdis_data* data) { const struct intface* interface_props = sdis_data_cget(data); struct stardis_interface_fragment f; - (void)source_id; + unsigned id; d3_set(f.P, frag->P); d3_set(f.Ng, frag->Ng); d3_set(f.uv, frag->uv); f.time = frag->time; ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; - return interface_props->get_alpha - (&f, source_id, interface_props->prog_data); + id = src_id != SDIS_INTERN_SOURCE_ID ? src_id : STARDIS_INTERN_SOURCE_ID; + return interface_props->get_alpha(&f, id, interface_props->prog_data); } static double @@ -212,13 +216,15 @@ intface_prog_get_ref_temp { const struct intface* interface_props = sdis_data_cget(data); struct stardis_interface_fragment f; + double temp; d3_set(f.P, frag->P); d3_set(f.Ng, frag->Ng); d3_set(f.uv, frag->uv); f.time = frag->time; ASSERT(frag->side == SDIS_FRONT || frag->side == SDIS_BACK); f.side = (frag->side == SDIS_FRONT) ? FRONT : BACK; - return interface_props->get_ref_temp(&f, interface_props->prog_data); + temp = interface_props->get_ref_temp(&f, interface_props->prog_data); + return STARDIS_TEMPERATURE_IS_KNOWN(temp) ? temp : SDIS_TEMPERATURE_NONE; } static double @@ -554,8 +560,12 @@ create_intface fluid_side_shader->emissivity = interface_get_emissivity; interface_props->emissivity = 1; ASSERT(SDIS_TEMPERATURE_IS_KNOWN(intface->d.t_boundary->imposed_temperature)); - interface_props->imposed_temperature - = intface->d.t_boundary->imposed_temperature; + interface_props->imposed_temperature = intface->d.t_boundary->imposed_temperature; + /* Temporarily set the reference temperature to the set temperature. + * TODO use a different reference temperature when the file format is + * updated to allow explicit definition by the user. */ + fluid_side_shader->reference_temperature = interface_get_ref_temperature; + interface_props->ref_temperature = intface->d.t_boundary->imposed_temperature; break; case DESC_BOUND_T_FOR_SOLID_PROG: if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { @@ -586,6 +596,10 @@ create_intface interface_props->get_emissivity = emissivity_1; interface_props->get_temp = intface->d.t_boundary_prog->temperature; interface_props->prog_data = intface->d.t_boundary_prog->prog_data; + /* Temporarily set the reference temperature to the set temperature. + * TODO use a different reference temperature when the file format is + * updated to allow explicit definition by the user. */ + fluid_side_shader->reference_temperature = intface_prog_get_temp; break; case DESC_BOUND_F_FOR_SOLID: if(sdis_medium_get_type(def_medium) != SDIS_SOLID) { diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -443,8 +443,6 @@ process_h if(res == RES_OK) res = RES_BAD_ARG; goto end; } - stardis->t_range[0] = MMIN(stardis->t_range[0], h_boundary->imposed_temperature); - stardis->t_range[1] = MMAX(stardis->t_range[1], h_boundary->imposed_temperature); if(type == DESC_BOUND_H_FOR_FLUID) ERR(get_dummy_solid_id(stardis, &h_boundary->mat_id)); @@ -568,8 +566,6 @@ process_hf if(res == RES_OK) res = RES_BAD_ARG; goto end; } - stardis->t_range[0] = MMIN(stardis->t_range[0], hf_boundary->imposed_temperature); - stardis->t_range[1] = MMAX(stardis->t_range[1], hf_boundary->imposed_temperature); ASSERT(type == DESC_BOUND_HF_FOR_SOLID); ERR(init_fluid(stardis->allocator, &fluid)); @@ -600,55 +596,54 @@ error: static res_T set_argc_argv (struct mem_allocator* allocator, - size_t* argc, - char** argv[], + const char* prog_name, /* First argument to copy in argv[0] */ + size_t* out_argc, + char** out_argv[], const wordexp_t* pwordexp, size_t idx) { + char** argv = NULL; + size_t argc; size_t i, n; res_T res = RES_OK; - ASSERT(argc && argv && pwordexp); - *argv = NULL; + ASSERT(prog_name && out_argc && out_argv && pwordexp); if(pwordexp->we_wordc < idx) { res = RES_BAD_ARG; goto error; } - *argc = pwordexp->we_wordc - idx; - /* Review: why allocate an extra argument? In fact, it's necessary because - * this function is called even if there are no arguments to analyze. In this - * case, allocation would fail, as the size to be allocated would be zero. - * This +1 therefore guarantees that at least one element will be allocated. - * But this could be eliminated by checking that there are no arguments - * (argc==0) and, if necessary, returning before any allocation. - * - * Nevertheless, this extra argument makes sense. It should be the first - * argument and contain the program name. In this way, the argument list would - * respect the C convention for declaring an argument list. And so, anyone - * could use the getopt analysis function without having to declare a dummy - * argument as the program's first parameter */ - *argv = MEM_CALLOC(allocator, 1 + *argc, sizeof(char *)); - if(*argv == NULL) { - res = RES_MEM_ERR; - goto error; - } - for(i = idx, n = 0; i < pwordexp->we_wordc; i++, n++) { - (*argv)[n] = MEM_CALLOC(allocator, 1, 1 + strlen(pwordexp->we_wordv[i])); - if((*argv)[n] == NULL) { - res = RES_MEM_ERR; - goto error; - } - strcpy((*argv)[n], pwordexp->we_wordv[i]); /* size is adequate */ + + /* Allocate an additional argument to store the program name as the first + * argument. This is not only useful information, but also respects the C + * convention for declaring a list of arguments. So anyone can use the + * standard getopt function to parse input arguments*/ + argc = pwordexp->we_wordc - idx + 1/*program name*/; + argv = MEM_CALLOC(allocator, argc, sizeof(char*)); + if(argv == NULL) { res = RES_MEM_ERR; goto error; } + + #define STRDUP(Dst, Src) { \ + (Dst) = MEM_CALLOC(allocator, 1, 1 + strlen(Src)); \ + if((Dst) == NULL) { res = RES_MEM_ERR; goto error; } \ + strcpy((Dst), (Src)); /* size is adequate */ \ + } (void)0 + STRDUP(argv[0], prog_name); + for(i = idx, n = 1; i < pwordexp->we_wordc; i++, n++) { + STRDUP(argv[n], pwordexp->we_wordv[i]); } + #undef STRDUP + end: + *out_argc = argc; + *out_argv = argv; return res; error: - if(*argv) { - for(i = 0; i < *argc; i++) - if((*argv)[i]) MEM_RM(allocator, (*argv)[i]); - MEM_RM(allocator, *argv); + if(argv) { + FOR_EACH(i, 0, argc) if(argv[i]) MEM_RM(allocator, argv[i]); + MEM_RM(allocator, argv); } + argc = 0; + argv = NULL; goto end; } @@ -798,8 +793,8 @@ process_program } /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &program->argc, &program->argv, - pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&program->name), + &program->argc, &program->argv, pwordexp, idx)); if(program->create) { /* create and init custom data */ struct stardis_program_context ctx; @@ -813,7 +808,7 @@ process_program FATAL("error:" STR(__FILE__) ":" STR(__LINE__)": Invalid type.\n"); } CREATE_DESC_DATA_BASE(program, LIST_ARG2(program->argc, program->argv)); - } else if(program->argc != 0) { + } else if(program->argc != 1) { logger_print(stardis->logger, LOG_ERROR, "Library '%s' has no custom data management functions but has arguments:\n", lib_name); @@ -893,8 +888,8 @@ process_h_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &h_boundary_prog->argc, - &h_boundary_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&h_boundary_prog->name), + &h_boundary_prog->argc, &h_boundary_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &h_boundary_prog->program, &h_boundary_prog->create, &h_boundary_prog->release)); @@ -914,8 +909,10 @@ process_h_prog CREATE_DESC_DATA(h_boundary_prog); h_boundary_prog->t_range(h_boundary_prog->prog_data, h_bound_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], h_bound_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], h_bound_t_range[1]); + if(STARDIS_TEMPERATURE_IS_KNOWN(h_bound_t_range[0])) + stardis->t_range[0] = MMIN(stardis->t_range[0], h_bound_t_range[0]); + if(STARDIS_TEMPERATURE_IS_KNOWN(h_bound_t_range[1])) + stardis->t_range[1] = MMAX(stardis->t_range[1], h_bound_t_range[1]); /* create the media behind the interface */ if(type == DESC_BOUND_H_FOR_FLUID_PROG) { @@ -992,8 +989,8 @@ process_hf_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &hf_boundary_prog->argc, - &hf_boundary_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&hf_boundary_prog->name), + &hf_boundary_prog->argc, &hf_boundary_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &hf_boundary_prog->program, &hf_boundary_prog->create, &hf_boundary_prog->release)); @@ -1010,8 +1007,10 @@ process_hf_prog CREATE_DESC_DATA(hf_boundary_prog); hf_boundary_prog->t_range(hf_boundary_prog->prog_data, hf_bound_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], hf_bound_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], hf_bound_t_range[1]); + if(STARDIS_TEMPERATURE_IS_KNOWN(hf_bound_t_range[0])) + stardis->t_range[0] = MMIN(stardis->t_range[0], hf_bound_t_range[0]); + if(STARDIS_TEMPERATURE_IS_KNOWN(hf_bound_t_range[1])) + stardis->t_range[1] = MMAX(stardis->t_range[1], hf_bound_t_range[1]); /* create the media behind the interface */ ERR(init_fluid_prog(stardis->allocator, &fluid_prog)); @@ -1079,6 +1078,10 @@ process_t if(res == RES_OK) res = RES_BAD_ARG; goto end; } + + /* Temporarily use the set temperature as a reference temperature. + * TODO use a different reference temperature when the file format is updated + * to allow explicit definition by the user. */ stardis->t_range[0] = MMIN(stardis->t_range[0], t_boundary->imposed_temperature); stardis->t_range[1] = MMAX(stardis->t_range[1], t_boundary->imposed_temperature); @@ -1138,8 +1141,8 @@ process_t_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &t_boundary_prog->argc, - &t_boundary_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&t_boundary_prog->name), + &t_boundary_prog->argc, &t_boundary_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &t_boundary_prog->program, &t_boundary_prog->create, &t_boundary_prog->release)); @@ -1150,8 +1153,10 @@ process_t_prog CREATE_DESC_DATA(t_boundary_prog); t_boundary_prog->t_range(t_boundary_prog->prog_data, t_bound_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], t_bound_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], t_bound_t_range[1]); + if(STARDIS_TEMPERATURE_IS_KNOWN(t_bound_t_range[0])) + stardis->t_range[0] = MMIN(stardis->t_range[0], t_bound_t_range[0]); + if(STARDIS_TEMPERATURE_IS_KNOWN(t_bound_t_range[1])) + stardis->t_range[1] = MMAX(stardis->t_range[1], t_bound_t_range[1]); end: return res; @@ -1268,8 +1273,8 @@ process_flx_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &f_boundary_prog->argc, - &f_boundary_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&f_boundary_prog->name), + &f_boundary_prog->argc, &f_boundary_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &f_boundary_prog->program, &f_boundary_prog->create, &f_boundary_prog->release)); @@ -1414,8 +1419,8 @@ process_sfc_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &sf_connect_prog->argc, - &sf_connect_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&sf_connect_prog->name), + &sf_connect_prog->argc, &sf_connect_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &sf_connect_prog->program, &sf_connect_prog->create, &sf_connect_prog->release)); @@ -1430,8 +1435,10 @@ process_sfc_prog CREATE_DESC_DATA(sf_connect_prog); sf_connect_prog->t_range(sf_connect_prog->prog_data, sf_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], sf_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], sf_t_range[1]); + if(STARDIS_TEMPERATURE_IS_KNOWN(sf_t_range[0])) + stardis->t_range[0] = MMIN(stardis->t_range[0], sf_t_range[0]); + if(STARDIS_TEMPERATURE_IS_KNOWN(sf_t_range[1])) + stardis->t_range[1] = MMAX(stardis->t_range[1], sf_t_range[1]); end: return res; @@ -1544,8 +1551,8 @@ process_ssc_prog ERR(read_sides_and_files(stardis, 1, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &ss_connect_prog->argc, - &ss_connect_prog->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&ss_connect_prog->name), + &ss_connect_prog->argc, &ss_connect_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &ss_connect_prog->program, &ss_connect_prog->create, &ss_connect_prog->release)); @@ -1706,8 +1713,6 @@ process_solid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - stardis->t_range[0] = MMIN(stardis->t_range[0], solid->tinit); - stardis->t_range[1] = MMAX(stardis->t_range[1], solid->tinit); ERR(read_imposed_temperature(stardis, &solid->imposed_temperature, pwordexp, &idx)); if(SDIS_TEMPERATURE_IS_KNOWN(solid->imposed_temperature) @@ -1720,10 +1725,7 @@ process_solid res = RES_BAD_ARG; goto end; } - if(SDIS_TEMPERATURE_IS_KNOWN(solid->imposed_temperature)) - stardis->t_range[0] = MMIN(stardis->t_range[0], solid->imposed_temperature); - stardis->t_range[1] = MMAX(stardis->t_range[1], solid->imposed_temperature); CHK_ARG(idx, "volumic power"); res = cstr_to_double(arg, &solid->vpower); if(res != RES_OK) { @@ -1760,7 +1762,6 @@ process_solid_prog char* arg = NULL; struct description* desc; const char *lib_name, *desc_name; - double solid_t_range[2] = {DBL_MAX, -DBL_MAX}; size_t sz; struct solid_prog* solid_prog; struct stardis_description_create_context ctx; @@ -1798,8 +1799,8 @@ process_solid_prog ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &solid_prog->argc, &solid_prog->argv, - pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&solid_prog->name), + &solid_prog->argc, &solid_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &solid_prog->program, &solid_prog->create, &solid_prog->release)); @@ -1809,15 +1810,14 @@ process_solid_prog GET_LIB_SYMBOL(solid_prog, delta, stardis_delta_solid); GET_LIB_SYMBOL(solid_prog, temp, stardis_medium_temperature); GET_LIB_SYMBOL(solid_prog, vpower, stardis_volumic_power); - GET_LIB_SYMBOL(solid_prog, t_range, stardis_t_range); + + GET_LIB_SYMBOL_BASE(&solid_prog->sample_path, solid_prog->program->lib_handle, + stardis_sample_conductive_path, 1); + /* create and init custom data */ ctx.name = desc_name; CREATE_DESC_DATA(solid_prog); - solid_prog->t_range(solid_prog->prog_data, solid_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], solid_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], solid_t_range[1]); - ERR(create_solver_solid_prog(stardis, solid_prog)); end: @@ -1889,8 +1889,6 @@ process_fluid if(res == RES_OK) res = RES_BAD_ARG; goto end; } - stardis->t_range[0] = MMIN(stardis->t_range[0], fluid->tinit); - stardis->t_range[1] = MMAX(stardis->t_range[1], fluid->tinit); ERR(read_imposed_temperature(stardis, &fluid->imposed_temperature, pwordexp, &idx)); if(SDIS_TEMPERATURE_IS_KNOWN(fluid->imposed_temperature) @@ -1902,9 +1900,6 @@ process_fluid res = RES_BAD_ARG; goto end; } - if(SDIS_TEMPERATURE_IS_KNOWN(fluid->imposed_temperature)) - stardis->t_range[0] = MMIN(stardis->t_range[0], fluid->imposed_temperature); - stardis->t_range[1] = MMAX(stardis->t_range[1], fluid->imposed_temperature); ERR(create_solver_fluid(stardis, fluid)); @@ -1925,7 +1920,6 @@ process_fluid_prog char* arg = NULL; struct description* desc; const char *lib_name, *desc_name; - double fluid_t_range[2] = {DBL_MAX, -DBL_MAX}; size_t sz; struct fluid_prog* fluid_prog; struct stardis_description_create_context ctx; @@ -1963,23 +1957,18 @@ process_fluid_prog ERR(read_sides_and_files(stardis, 0, (unsigned)sz, pwordexp, &idx)); /* store the end of line as args for custom init */ - ERR(set_argc_argv(stardis->allocator, &fluid_prog->argc, &fluid_prog->argv, - pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&fluid_prog->name), + &fluid_prog->argc, &fluid_prog->argv, pwordexp, idx)); /* get the user-defined functions from the library */ ERR(get_prog_common(lib_name, stardis, &fluid_prog->program, &fluid_prog->create, &fluid_prog->release)); GET_LIB_SYMBOL(fluid_prog, rho, stardis_volumic_mass); GET_LIB_SYMBOL(fluid_prog, cp, stardis_calorific_capacity); GET_LIB_SYMBOL(fluid_prog, temp, stardis_medium_temperature); - GET_LIB_SYMBOL(fluid_prog, t_range, stardis_t_range); /* create and init custom data */ ctx.name = desc_name; CREATE_DESC_DATA(fluid_prog); - fluid_prog->t_range(fluid_prog->prog_data, fluid_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], fluid_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], fluid_t_range[1]); - ERR(create_solver_fluid_prog(stardis, fluid_prog)); end: @@ -2105,7 +2094,7 @@ process_radiative_prog(struct stardis* stardis, wordexp_t* pwordexp) lib_name = arg; if(idx < pwordexp->we_wordc - && strcasecmp(pwordexp->we_wordv[idx], "PROG_PARAMS")) { + && strcasecmp(pwordexp->we_wordv[idx++], "PROG_PARAMS")) { logger_print(stardis->logger, LOG_ERROR, "Expecting PROG_PARAMS keyword while parsing `%s'.\n", pwordexp->we_wordv[idx]); @@ -2113,8 +2102,8 @@ process_radiative_prog(struct stardis* stardis, wordexp_t* pwordexp) goto error; } - ERR(set_argc_argv - (stardis->allocator, &radenv->argc, &radenv->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&radenv->prog_name), + &radenv->argc, &radenv->argv, pwordexp, idx)); ERR(get_prog_common (lib_name, stardis, &radenv->program, &radenv->create, &radenv->release)); GET_LIB_SYMBOL(radenv, temperature, @@ -2135,8 +2124,10 @@ process_radiative_prog(struct stardis* stardis, wordexp_t* pwordexp) } radenv->t_range(radenv->data, radenv_t_range); - stardis->t_range[0] = MMIN(stardis->t_range[0], radenv_t_range[0]); - stardis->t_range[1] = MMAX(stardis->t_range[1], radenv_t_range[1]); + if(STARDIS_TEMPERATURE_IS_KNOWN(radenv_t_range[0])) + stardis->t_range[0] = MMIN(stardis->t_range[0], radenv_t_range[0]); + if(STARDIS_TEMPERATURE_IS_KNOWN(radenv_t_range[1])) + stardis->t_range[1] = MMAX(stardis->t_range[1], radenv_t_range[1]); exit: return res; @@ -2258,7 +2249,7 @@ process_spherical_source_prog(struct stardis* stardis, wordexp_t* pwordexp) lib_name = arg; if(idx < pwordexp->we_wordc - && strcasecmp(pwordexp->we_wordv[idx], "PROG_PARAMS")) { + && strcasecmp(pwordexp->we_wordv[idx++], "PROG_PARAMS")) { logger_print(stardis->logger, LOG_ERROR, "Expecting PROG_PARAMS keyword while parsing `%s'.\n", pwordexp->we_wordv[idx]); @@ -2266,7 +2257,8 @@ process_spherical_source_prog(struct stardis* stardis, wordexp_t* pwordexp) goto error; } - ERR(set_argc_argv(stardis->allocator, &src->argc, &src->argv, pwordexp, idx)); + ERR(set_argc_argv(stardis->allocator, str_cget(&src->prog_name), &src->argc, + &src->argv, pwordexp, idx)); ERR(get_prog_common(lib_name, stardis, &src->program, &src->create, &src->release)); GET_LIB_SYMBOL(src, position, stardis_spherical_source_position); GET_LIB_SYMBOL(src, power, stardis_spherical_source_power); @@ -2553,7 +2545,7 @@ exp_error: stardis->t_range[1] = MMAX(stardis->t_range[1], trad_ref); } logger_print(stardis->logger, LOG_OUTPUT, - "System T range is [%g %g]\n", SPLIT2(stardis->t_range)); + "System Tref range is [%g %g]\n", SPLIT2(stardis->t_range)); logger_print(stardis->logger, LOG_OUTPUT, "Picard order is %u\n", stardis->picard_order); diff --git a/src/stardis-prog-properties.h.in b/src/stardis-prog-properties.h.in @@ -1,4 +1,4 @@ -/* Copyright (C) 2018-2022 |Meso|Star> (contact@meso-star.com) +/* Copyright (C) 2018-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 Lesser General Public @@ -10,8 +10,9 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * - * You should have received a copy of the GNU Lesser General Public License - * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + * You should have received a copy of the GNU Lesser General Public + * License along with this program. If not, see + * <http://www.gnu.org/licenses/>. */ #ifndef STARDIS_PROG_H__ #define STARDIS_PROG_H__ @@ -32,12 +33,27 @@ #define STARDIS_API extern #endif -/*****************************************************************************/ -/* API types. */ -/* The various functions defining programmed descriptions receive arguments */ -/* of the following types when called from the stardis simulation. */ -/*****************************************************************************/ +/* Constants defining that no power density/imposed flux is defined */ +#define STARDIS_VOLUMIC_POWER_NONE DBL_MAX +#define STARDIS_FLUX_NONE DBL_MAX +/* Syntactic sugar used to define whether a temperature is known or not */ +#define STARDIS_TEMPERATURE_NONE (-(DBL_MAX+DBL_MAX)*0) /* NAN */ +#define STARDIS_TEMPERATURE_IS_KNOWN(Temp) (Temp==Temp) +#define STARDIS_TEMPERATURE_IS_UNKNOWN(Temp) (Temp!=Temp) + +/* Indentifier of the internal source of radiation */ +#define STARDIS_INTERN_SOURCE_ID UINT_MAX + +/* Forward declaration of external data types */ +struct sdis_scene; +struct ssp_rng; + +/******************************************************************************* + * API types. + * The various functions defining programmed descriptions receive arguments + * of the following types when called from the stardis simulation. + ******************************************************************************/ struct stardis_vertex { double P[3]; /* World space position */ double time; /* "Time" of the vertex */ @@ -79,15 +95,51 @@ struct stardis_description_create_context { const char* name; /* Description name */ }; +struct stardis_triangle { + double vtx0[3]; + double vtx1[3]; + double vtx2[3]; +}; +#define STARDIS_TRIANGLE_NULL__ {{0,0,0}, {0,0,0}, {0,0,0}} +static const struct stardis_triangle STARDIS_TRIANGLE_NULL = + STARDIS_TRIANGLE_NULL__; + +/* Helper macro that check if the triangle is NULL */ +#define STARDIS_TRIANGLE_NONE(T) \ + ( (T)->vtx0[0] == 0 && (T)->vtx0[1] == 0 && (T)->vtx0[2] == 0 \ + && (T)->vtx1[0] == 0 && (T)->vtx1[1] == 0 && (T)->vtx1[2] == 0 \ + && (T)->vtx2[0] == 0 && (T)->vtx2[1] == 0 && (T)->vtx2[2] == 0) + +/* A sampled path */ +struct stardis_path { + struct stardis_vertex vtx; /* Current position and time */ + + /* Triangle intersected by the path. When defined, the path is on a border */ + struct stardis_triangle tri; + + double weight; /* Monte Carlo weight update along the path */ + + /* Define whether the path has reached a boundary conduction in time/space */ + int at_limit; +}; +#define STARDIS_PATH_NULL__ { \ + STARDIS_VERTEX_NULL__, \ + STARDIS_TRIANGLE_NULL__, \ + 0, /* MC weight */ \ + 0 /* At limit */ \ +} +static const struct stardis_path STARDIS_PATH_NULL = + STARDIS_PATH_NULL__; + #ifdef __cplusplus extern "C" { #endif -/******************************************************************************/ -/* Optional functions for any programmed library. */ -/* Either all 3 or none of the 3 following functions must be defined. */ -/* If a libray doesn't need its own data, just let these functions undefined. */ -/******************************************************************************/ +/******************************************************************************* + * Optional functions for any programmed library. + * Either all 3 or none of the 3 following functions must be defined. + * If a libray doesn't need its own data, just let these functions undefined. + ******************************************************************************/ /* Create the data attached to a given libray. * A NULL result is interpreted as an error and ends the program. @@ -121,9 +173,9 @@ STARDIS_API void stardis_release_library_data (void* lib_data); -/******************************************************************************/ -/* Mandatory functions for any programmed description regardless of its type. */ -/******************************************************************************/ +/******************************************************************************* + * Mandatory functions for any programmed description regardless of its type. + ******************************************************************************/ /* Create the data attached to a given description. * A NULL result is interpreted as an error and ends the program. @@ -168,15 +220,9 @@ STARDIS_API const char* get_license_text (void* data); -/*****************************************************************************/ -/* Additional mandatory function declarations (sorted by description type). */ -/* Some functions appear multiple times as they are part of more than one */ -/* description requirement. */ -/*****************************************************************************/ - -/*********************************************************/ -/* Additional mandatory functions for a programmed solid */ -/*********************************************************/ +/******************************************************************************* + * Mandatory functions for a solid + ******************************************************************************/ /* Returns the calorific capacity at a given vertex. * This functions is called at every vertex of every path of the computation @@ -233,18 +279,22 @@ stardis_medium_temperature (const struct stardis_vertex* vtx, void* data); -/* Computes the expected temperature range for this solid. - * This functions is called once when initializing the computation. - * data is the pointer returned by stardis_create_data for this solid. - * Returns its modified range argument. */ -STARDIS_API double* -stardis_t_range - (void* data, - double range[2]); +/******************************************************************************* + * Optional function for a solid + ******************************************************************************/ -/*********************************************************/ -/* Additional mandatory functions for a programmed fluid */ -/*********************************************************/ +/* Function used to sample a conductive path. When defined, it is no + * longer Stardis that samples the path, but the user via this function */ +STARDIS_API int /* Error code */ +stardis_sample_conductive_path + (struct sdis_scene* scn, + struct ssp_rng* rng, + struct stardis_path* path, + void* data); + +/******************************************************************************* + * Mandatory functions for a fluid + ******************************************************************************/ /* Returns the calorific capacity at a given vertex. * This functions is called at every vertex of every path of the computation @@ -274,18 +324,9 @@ stardis_medium_temperature (const struct stardis_vertex* vtx, void* data); -/* Computes the expected temperature range for this fluid. - * This functions is called once when initializing the computation. - * data is the pointer returned by stardis_create_data for this fluid. - * Returns its modified range argument. */ -STARDIS_API double* -stardis_t_range - (void* data, - double range[2]); - -/**************************************************************************/ -/* Additional mandatory functions for a programmed H boundary for a fluid */ -/**************************************************************************/ +/******************************************************************************* + * Mandatory functions for a H boundary for a fluid + ******************************************************************************/ /* Returns the boundary temperature at a given fragment. * This functions is called every time a path of the computation reaches @@ -352,9 +393,9 @@ stardis_t_range (void* data, double range[2]); -/**************************************************************************/ -/* Additional mandatory functions for a programmed H boundary for a solid */ -/**************************************************************************/ +/******************************************************************************* + * Mandatory functions for a H boundary for a solid + ******************************************************************************/ /* Returns the emissivity at a given fragment. * This functions is called every time a path of the computation reaches @@ -423,9 +464,9 @@ stardis_t_range (void* data, double range[2]); -/**************************************************************/ -/* Additional mandatory functions for a programmed T boundary */ -/**************************************************************/ +/******************************************************************************* + * Mandatory functions for a T boundary + ******************************************************************************/ /* Returns the boundary temperature at a given fragment. * This functions is called every time a path of the computation reaches @@ -445,9 +486,9 @@ stardis_t_range (void* data, double range[2]); -/****************************************************************/ -/* Additional mandatory functions for a programmed F+H boundary */ -/****************************************************************/ +/******************************************************************************* + * Mandatory functions for a F+H boundary + ******************************************************************************/ /* Returns the emissivity at a given fragment. * This functions is called every time a path of the computation reaches @@ -525,9 +566,9 @@ stardis_t_range (void* data, double range[2]); -/**************************************************************/ -/* Additional mandatory functions for a programmed F boundary */ -/**************************************************************/ +/******************************************************************************* + * Mandatory functions for a F boundary + ******************************************************************************/ /* Returns the flux at the boundary at a given fragment. * This functions is called every time a path of the computation reaches @@ -538,9 +579,9 @@ stardis_boundary_flux (const struct stardis_interface_fragment* frag, void* data); -/**************************************************************************/ -/* Additional mandatory functions for a programmed Solid-Solid connection */ -/**************************************************************************/ +/******************************************************************************* + * Mandatory functions for a solid-solid connection + ******************************************************************************/ /* Returns the thermal contact resistance at a given fragment. * This functions is called every time a path of the computation reaches @@ -551,9 +592,9 @@ stardis_thermal_contact_resistance (const struct stardis_interface_fragment* frag, void* data); -/**************************************************************************/ -/* Additional mandatory functions for a programmed Solid-Fluid connection */ -/**************************************************************************/ +/******************************************************************************* + * Mandatory functions for a solid-fluid connection + ******************************************************************************/ /* Returns the emissivity at a given fragment. * This functions is called every time a path of the computation reaches @@ -611,10 +652,10 @@ stardis_t_range (void* data, double range[2]); -/******************************************************************************/ -/* Additional mandatory functions for a programmed spherical source */ -/* These functions are used to calculate the external flux at the boundaries. */ -/******************************************************************************/ +/******************************************************************************* + * Mandatory functions for a spherical source. + * These functions are used to calculate the external flux at the boundaries + ******************************************************************************/ /* Retrieve the position of the spherical source center. * This function is used to calculate the external flux at the boundaries. @@ -642,9 +683,9 @@ stardis_spherical_source_diffuse_radiance const double dir[3], void* data); -/******************************************************************************/ -/* Additional mandatory functions for a programmed radiative environment */ -/******************************************************************************/ +/******************************************************************************* + * Mandatory functions for a radiative environment + ******************************************************************************/ /* Retrieve the temperature of radiative paths that reach infinity */ STARDIS_API double diff --git a/src/stardis-program.c b/src/stardis-program.c @@ -72,11 +72,13 @@ str_print_program const struct program* p) { res_T res = RES_OK; + ASSERT(p->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "Library %s", str_cget(&p->name))); - if(p->argc > 0) { + if(p->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < p->argc; i++) { + for(i = 1; i < p->argc; i++) { ERR(str_append_printf(str, (i+1 == p->argc ? "\t%s" : "\t%s\n"), p->argv[i])); } } diff --git a/src/stardis-sfconnect-prog.c b/src/stardis-sfconnect-prog.c @@ -81,13 +81,15 @@ str_print_sf_connect_prog { res_T res = RES_OK; ASSERT(str && c); + ASSERT(c->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed Solid-Fluid connection '%s': lib='%s'", str_cget(&c->name), str_cget(&c->prog_name))); - if(c->argc > 0) { + if(c->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < c->argc; i++) { + for(i = 1; i < c->argc; i++) { ERR(str_append_printf(str, (i+1 == c->argc ? "\t%s" : "\t%s\n"), c->argv[i])); } } diff --git a/src/stardis-solid-prog.c b/src/stardis-solid-prog.c @@ -82,9 +82,11 @@ solid_prog_get_volumic_power { const struct solid_prog* const* solid_props = sdis_data_cget(data); struct stardis_vertex v; + double power; d3_set(v.P, vtx->P); v.time = vtx->time; - return (*solid_props)->vpower(&v, (*solid_props)->prog_data); + power = (*solid_props)->vpower(&v, (*solid_props)->prog_data); + return power != STARDIS_VOLUMIC_POWER_NONE ? power : SDIS_VOLUMIC_POWER_NONE; } static double @@ -94,9 +96,56 @@ solid_prog_get_temperature { const struct solid_prog* const* solid_props = sdis_data_cget(data); struct stardis_vertex v; + double temp; d3_set(v.P, vtx->P); v.time = vtx->time; - return (*solid_props)->temp(&v, (*solid_props)->prog_data); + temp = (*solid_props)->temp(&v, (*solid_props)->prog_data); + return STARDIS_TEMPERATURE_IS_KNOWN(temp) ? temp : SDIS_TEMPERATURE_NONE; +} + +static res_T +solid_prog_sample_path + (struct sdis_scene* scn, + struct ssp_rng* rng, + struct sdis_path* path, + struct sdis_data* data) +{ + const struct solid_prog* const* solid_props = sdis_data_cget(data); + struct stardis_path p = STARDIS_PATH_NULL; + int err = 0; + res_T res = RES_OK; + + d3_set(p.vtx.P, path->vtx.P); + p.vtx.time = path->vtx.time; + + err = (*solid_props)->sample_path(scn, rng, &p, (*solid_props)->prog_data); + if(err) { res = RES_UNKNOWN_ERR; goto error; } + + d3_set(path->vtx.P, p.vtx.P); + path->vtx.time = p.vtx.time; + path->weight = p.weight; + path->at_limit = p.at_limit; + + if(!STARDIS_TRIANGLE_NONE(&p.tri)) { + struct sdis_primkey key = SDIS_PRIMKEY_NULL; + + sdis_primkey_setup(&key, p.tri.vtx0, p.tri.vtx1, p.tri.vtx2); + res = sdis_scene_get_s3d_primitive(scn, &key, &path->prim_3d); + + /* In fact, we'd like to log an error notifying us that the returned + * triangle doesn't exist in Stardis. But there's no easy way to retrieve + * the logger since the program has no reference to Stardis. This lack stems + * from design choices where internal data structures are not managed by + * reference and don't take a reference on the Stardis structure. In any + * case, until stardis' internal data structures have been thoroughly + * redesigned, we're only returning an error */ + if(res != RES_OK) goto error; + } + +exit: + return res; +error: + goto exit; } /******************************************************************************* @@ -117,10 +166,13 @@ create_solver_solid_prog solid_shader.calorific_capacity = solid_prog_get_calorific_capacity; solid_shader.thermal_conductivity = solid_prog_get_thermal_conductivity; solid_shader.volumic_mass = solid_prog_get_volumic_mass; - solid_shader.delta= solid_prog_get_delta; + solid_shader.delta = solid_prog_get_delta; solid_shader.volumic_power = solid_prog_get_volumic_power; solid_shader.temperature = solid_prog_get_temperature; solid_shader.t0 = stardis->initial_time; + if(solid_props->sample_path) { + solid_shader.sample_path = solid_prog_sample_path; + } ERR(sdis_data_create(stardis->dev, sizeof(struct solid_prog*), ALIGNOF(struct solid_prog*), NULL, &data)); @@ -189,13 +241,15 @@ str_print_solid_prog(struct str* str, const struct solid_prog* f) { res_T res = RES_OK; ASSERT(str && f); + ASSERT(f->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed solid '%s': lib='%s', it is medium %u)", str_cget(&f->name), str_cget(&f->prog_name), f->solid_id)); - if(f->argc > 0) { + if(f->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < f->argc; i++) { + for(i = 1; i < f->argc; i++) { ERR(str_append_printf(str, (i+1 == f->argc ? "\t%s" : "\t%s\n"), f->argv[i])); } } diff --git a/src/stardis-solid-prog.h b/src/stardis-solid-prog.h @@ -48,7 +48,14 @@ struct solid_prog { double (*delta)(const struct stardis_vertex*, void*); double (*temp)(const struct stardis_vertex*, void*); double (*vpower)(const struct stardis_vertex*, void*); - double* (*t_range)(void*, double trange[2]); + + /* User-defined function for sampling a conductive path */ + int + (*sample_path) + (struct sdis_scene*, + struct ssp_rng*, + struct stardis_path*, + void*); }; res_T diff --git a/src/stardis-ssconnect-prog.c b/src/stardis-ssconnect-prog.c @@ -82,13 +82,15 @@ str_print_ss_connect_prog { res_T res = RES_OK; ASSERT(str && c); + ASSERT(c->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed Solid-Solid connection '%s': lib='%s'", str_cget(&c->name), str_cget(&c->prog_name))); - if(c->argc > 0) { + if(c->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < c->argc; i++) { + for(i = 1; i < c->argc; i++) { ERR(str_append_printf(str, (i+1 == c->argc ? "\t%s" : "\t%s\n"), c->argv[i])); } } diff --git a/src/stardis-tbound-prog.c b/src/stardis-tbound-prog.c @@ -81,14 +81,16 @@ str_print_t_boundary_prog { res_T res = RES_OK; ASSERT(str && b); + ASSERT(b->argc >= 1); /* At least one argument which is the program name */ + ERR(str_append_printf(str, "programmed T boundary for solid '%s': lib='%s', " "(using medium %u as external medium)", str_cget(&b->name), str_cget(&b->prog_name), b->mat_id)); - if(b->argc > 0) { + if(b->argc > 1) { size_t i; ERR(str_append_printf(str, ", provided arguments:\n")); - for(i = 0; i < b->argc; i++) { + for(i = 1; i < b->argc; i++) { ERR(str_append_printf(str, (i+1 == b->argc ? "\t%s" : "\t%s\n"), b->argv[i])); } }