stardis

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

commit 1b3c506b37fa3495e6b0b55dccd05696088c9325
parent 64cf7053f23e63ef25582df7ac25b6a6df58b1b1
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri,  1 Mar 2024 11:21:42 +0100

Added support for a programmable external spherical source

Analyzes the description of SPHERICAL_SOURCE_PROG to configure the
spherical_source_prog data structure written for this purpose. The whole
process relies on existing functions and macros provided by Stardis to
analyze programmable properties.

This commit updates the data used by external source. In commit 146bac3,
they had become a copy of the Stardis data instead of a pointer to it,
to avoid hard-to-read pointers. However, the programmable spherical
source is not a POD structure whose copy would be satisfied with a
simple assignment. Although partial copying should not be a problem, we
avoid this dangerous workaround and use a pointer to this structure to
avoid future misunderstandings based on old assumptions. And to make the
code easier to understand, we do the same for the constant spherical
source, whose data reverts to a pointer to the data structure of a
spherical source in Stardis.

Diffstat:
Msrc/stardis-app.c | 4+---
Msrc/stardis-extern-source.c | 114++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-----------
Msrc/stardis-extern-source.h | 56++++++++++++++++++++++++++++++++++++++++++++++++++------
Msrc/stardis-parsing.c | 64+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
4 files changed, 213 insertions(+), 25 deletions(-)

diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -279,12 +279,10 @@ stardis_init stardis->next_medium_id = 0; stardis->undefined_medium_behind_boundary_id = SENC3D_UNSPECIFIED_MEDIUM; stardis->verbose = args->verbose; + stardis->extsrc = EXTERN_SOURCE_NULL; stardis->disable_intrad = args->disable_intrad; darray_media_ptr_init(stardis->allocator, &stardis->media); - /* Init the external source */ - extern_source_init(&stardis->extsrc); - /* If a dump is expected, we won't process any computation */ is_for_compute = (stardis->mode & COMPUTE_MODES) && !(stardis->mode & MODE_DUMP_MODEL); diff --git a/src/stardis-extern-source.c b/src/stardis-extern-source.c @@ -26,28 +26,24 @@ static void sphere_get_position(const double time, double pos[3], struct sdis_data* data) { - const struct extern_source* src = NULL; + const struct spherical_source* src = NULL; ASSERT(pos); (void)time; - src = sdis_data_cget(data); - ASSERT(src->type == EXTERN_SOURCE_SPHERE); - - pos[0] = src->data.sphere.position[0]; - pos[1] = src->data.sphere.position[1]; - pos[2] = src->data.sphere.position[2]; + src = *((const struct spherical_source* const*)sdis_data_cget(data)); + pos[0] = src->position[0]; + pos[1] = src->position[1]; + pos[2] = src->position[2]; } static double sphere_get_power(const double time, struct sdis_data* data) { - const struct extern_source* src = NULL; + const struct spherical_source* src = NULL; (void)time; - src = sdis_data_cget(data); - ASSERT(src->type == EXTERN_SOURCE_SPHERE); - - return src->data.sphere.power; /* [W] */ + src = *((const struct spherical_source* const*)sdis_data_cget(data)); + return src->power; /* [W] */ } static res_T @@ -62,10 +58,10 @@ create_solver_source_sphere ASSERT(src && src->type == EXTERN_SOURCE_SPHERE && stardis); /* Register with the solver source a pointer to the external source */ - res = sdis_data_create(stardis->dev, sizeof(struct extern_source), - ALIGNOF(struct extern_source), NULL, &data); + res = sdis_data_create(stardis->dev, sizeof(struct spherical_source*), + ALIGNOF(struct spherical_source*), NULL, &data); if(res != RES_OK) goto error; - *((struct extern_source*)sdis_data_get(data)) = *src; + *((struct spherical_source**)sdis_data_get(data)) = &src->data.sphere; /* Create the spherical source */ args.position = sphere_get_position; @@ -86,14 +82,98 @@ error: goto exit; } +static void +sphere_prog_get_position(const double time, double pos[3], struct sdis_data* data) +{ + const struct spherical_source_prog* src = NULL; + ASSERT(pos); + (void)time; + + src = *((const struct spherical_source_prog* const*)sdis_data_cget(data)); + src->position(time, pos, src->data);; +} + +static double +sphere_prog_get_power(const double time, struct sdis_data* data) +{ + const struct spherical_source_prog* src = NULL; + (void)time; + + src = *((const struct spherical_source_prog* const*)sdis_data_cget(data)); + return src->power(time, src->data); +} + +static res_T +create_solver_source_sphere_prog + (struct extern_source* src, + struct stardis* stardis) +{ + struct sdis_spherical_source_create_args args = + SDIS_SPHERICAL_SOURCE_CREATE_ARGS_NULL; + struct sdis_data* data = NULL; + res_T res = RES_OK; + ASSERT(src && src->type == EXTERN_SOURCE_SPHERE_PROG && stardis); + + /* Register with the solver source a pointer to the external source */ + res = sdis_data_create(stardis->dev, sizeof(struct spherical_source_prog*), + ALIGNOF(struct spherical_source_prog*), NULL, &data); + if(res != RES_OK) goto error; + *((struct spherical_source_prog**)sdis_data_get(data)) = &src->data.sphere_prog; + + /* Create the spherical source */ + args.position = sphere_prog_get_position; + args.power = sphere_prog_get_power; + args.data = data; + args.radius = src->data.sphere_prog.radius; + res = sdis_spherical_source_create(stardis->dev, &args, &src->sdis_src); + if(res != RES_OK) goto error; + +exit: + /* Release the local reference on the data: it is kept by the sdis source */ + if(data) SDIS(data_ref_put(data)); + return res; +error: + logger_print(stardis->logger, LOG_ERROR, + "Error when creating the external spherical source for the Solver -- %s\n", + res_to_cstr(res)); + goto exit; +} + /******************************************************************************* * Local functions ******************************************************************************/ +res_T +extern_source_init_sphere + (struct mem_allocator* allocator, + struct extern_source* src) +{ + ASSERT(src); + (void)allocator; + src->type = EXTERN_SOURCE_SPHERE; + src->data.sphere = SPHERICAL_SOURCE_NULL; + return RES_OK; +} + +res_T +extern_source_init_sphere_prog + (struct mem_allocator* allocator, + struct extern_source* src) +{ + ASSERT(src); + src->type = EXTERN_SOURCE_SPHERE_PROG; + src->data.sphere_prog = SPHERICAL_SOURCE_PROG_NULL; + str_init(allocator, &src->data.sphere_prog.prog_name); + return RES_OK; +} + void extern_source_release(struct extern_source* src) { ASSERT(src); if(src->sdis_src) SDIS(source_ref_put(src->sdis_src)); + if(src->type == EXTERN_SOURCE_SPHERE_PROG) { + str_release(&src->data.sphere_prog.prog_name); + } } res_T @@ -109,6 +189,10 @@ extern_source_create_solver_source res = create_solver_source_sphere(src, stardis); if(res != RES_OK) goto error; break; + case EXTERN_SOURCE_SPHERE_PROG: + res = create_solver_source_sphere_prog(src, stardis); + if(res != RES_OK) goto error; + break; default: FATAL("Unreachable code\n"); break; } diff --git a/src/stardis-extern-source.h b/src/stardis-extern-source.h @@ -20,9 +20,11 @@ /* Forward declaration */ struct stardis; +struct stardis_description_create_context; enum source_type { EXTERN_SOURCE_SPHERE, + EXTERN_SOURCE_SPHERE_PROG, EXTERN_SOURCE_NONE__ }; @@ -35,11 +37,50 @@ struct spherical_source { static const struct spherical_source SPHERICAL_SOURCE_NULL = SPHERICAL_SOURCE_NULL__; +struct spherical_source_prog { + struct str prog_name; + struct program* program; + void* data; /* Pointer toward the program data */ + + /* Input arguments */ + size_t argc; + char** argv; + + double radius; /* Not programmable */ + + void* + (*create) + (const struct stardis_description_create_context*, + void* lib_data, + size_t argc, + char* argv[]); + + void + (*release) + (void* data); + + double* + (*position) + (const double time, + double position[3], + void* data); + + double + (*power) + (const double time, + void* data); +}; +#define SPHERICAL_SOURCE_PROG_NULL__ \ + {{0}, NULL, NULL, 0, NULL, 0, NULL, NULL, NULL, NULL} +static const struct spherical_source_prog SPHERICAL_SOURCE_PROG_NULL= + SPHERICAL_SOURCE_PROG_NULL__; + /* Interface of an external source */ struct extern_source { enum source_type type; union { struct spherical_source sphere; + struct spherical_source_prog sphere_prog; } data; struct sdis_source* sdis_src; }; @@ -47,12 +88,15 @@ struct extern_source { {EXTERN_SOURCE_NONE__, {SPHERICAL_SOURCE_NULL__}, NULL} static const struct extern_source EXTERN_SOURCE_NULL = EXTERN_SOURCE_NULL__; -static INLINE void -extern_source_init(struct extern_source* src) -{ - ASSERT(src); - *src = EXTERN_SOURCE_NULL; -} +extern LOCAL_SYM res_T +extern_source_init_sphere + (struct mem_allocator* allocator, + struct extern_source* src); + +extern LOCAL_SYM res_T +extern_source_init_sphere_prog + (struct mem_allocator* allocator, + struct extern_source* src); extern LOCAL_SYM void extern_source_release diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -2090,6 +2090,9 @@ process_spherical_source goto error; } + res = extern_source_init_sphere(stardis->allocator, &stardis->extsrc); + if(res != RES_OK) goto error; + CHK_ARG(idx, "radius"); res = cstr_to_double(arg, &src->radius); if(res == RES_OK && src->radius < 0) res = RES_BAD_ARG; @@ -2122,7 +2125,63 @@ process_spherical_source goto error; } - stardis->extsrc.type = EXTERN_SOURCE_SPHERE; + res = extern_source_create_solver_source(&stardis->extsrc, stardis); + if(res != RES_OK) goto error; + +exit: + return res; +error: + extern_source_release(&stardis->extsrc); + stardis->extsrc = EXTERN_SOURCE_NULL; + goto exit; +} + +static res_T +process_spherical_source_prog(struct stardis* stardis, wordexp_t* pwordexp) +{ + struct spherical_source_prog* src = NULL; + char* lib_name = NULL; + char* arg = NULL; + size_t idx = 1; + res_T res = RES_OK; + ASSERT(stardis && pwordexp); + + src = &stardis->extsrc.data.sphere_prog; + + if(stardis->extsrc.type != EXTERN_SOURCE_NONE__) { + logger_print(stardis->logger, LOG_ERROR, + "Only one external source can be defined\n"); + res = RES_BAD_ARG; + goto error; + } + + res = extern_source_init_sphere_prog(stardis->allocator, &stardis->extsrc); + if(res != RES_OK) goto error; + + CHK_ARG(idx, "radius"); + res = cstr_to_double(arg, &src->radius); + if(res == RES_OK && src->radius < 0) res = RES_BAD_ARG; + if(res != RES_OK) { + logger_print(stardis->logger, LOG_ERROR, + "Invalid spherical source radius: %s\n", arg); + goto error; + } + + CHK_ARG(idx, "program name"); + ERR(str_set(&src->prog_name, arg)); + lib_name = arg; + + if(idx < pwordexp->we_wordc + && strcasecmp(pwordexp->we_wordv[idx], "PROG_PARAMS")) { + logger_print(stardis->logger, LOG_ERROR, + "Expecting PROG_PARAMS keyword while parsing `%s'.\n", arg); + goto error; + } + + ERR(set_argc_argv(stardis->allocator, &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); res = extern_source_create_solver_source(&stardis->extsrc, stardis); if(res != RES_OK) goto error; @@ -2130,6 +2189,7 @@ process_spherical_source exit: return res; error: + extern_source_release(&stardis->extsrc); stardis->extsrc = EXTERN_SOURCE_NULL; goto exit; } @@ -2217,6 +2277,8 @@ process_model_line ERR(process_radiative(stardis, pwordexp)); else if(0 == strcasecmp(arg, "SPHERICAL_SOURCE")) ERR(process_spherical_source(stardis, pwordexp)); + else if(0 == strcasecmp(arg, "SPHERICAL_SOURCE_PROG")) + ERR(process_spherical_source_prog(stardis, pwordexp)); else { logger_print(stardis->logger, LOG_ERROR, "Unknown description type: %s\n", arg);