stardis

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

commit 592109d9f7f7c323dacb21112662aeb750940cbf
parent c4696a306e1d50ccd05093ee1985e4e64e3044b6
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Tue,  5 Mar 2024 16:31:02 +0100

Merge branch 'feature_external_source' into develop

Diffstat:
MMakefile | 1+
Mdoc/stardis-input.5.in | 32++++++++++++++++++++++----------
Mdoc/stardis.1.in | 8++++++--
Msrc/stardis-app.c | 18+++++++++++++++++-
Msrc/stardis-app.h | 3+++
Msrc/stardis-args.c | 8++++++--
Msrc/stardis-args.h.in | 1+
Asrc/stardis-extern-source.c | 218+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Asrc/stardis-extern-source.h | 111+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Msrc/stardis-intface.c | 2+-
Msrc/stardis-parsing.c | 156++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Msrc/stardis-prog-properties.h.in | 20++++++++++++++++++++
12 files changed, 560 insertions(+), 18 deletions(-)

diff --git a/Makefile b/Makefile @@ -32,6 +32,7 @@ SRC =\ src/stardis-compute.c\ src/stardis-compute-probe-boundary.c\ src/stardis-description.c\ + src/stardis-extern-source.c\ src/stardis-fluid.c\ src/stardis-fluid-prog.c\ src/stardis-fbound.c\ diff --git a/doc/stardis-input.5.in b/doc/stardis-input.5.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 February 19, 2024 +.Dd February 27, 2024 .Dt STARDIS-INPUT 5 .Os .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -128,18 +128,11 @@ The file format is as follows: .It Ta \& \& | Ta Ao Va boundary-condition Ac Op Ao Va comment Ac .It Ta \& \& | Ta Ao Va scaling Ac Op Ao Va comment Ac # At most once -.It Ta \& \& | Ta Ao Va rad-temps Ac Op Ao Va comment Ac -# At most once .It \ Ta Ta .It Ao Va comment Ac Ta ::= Ta Li # Vt string .It Ao Va program Ac Ta ::= Ta Li PROGRAM Ao Va prog-name Ac Ao Va lib-path Ac Op Ao Va args Ac .It Ao Va scaling Ac Ta ::= Ta Li SCALE Vt real # Geometry scaling in ]0, INF) -.It \ Ta Ta -.It Ao Va rad-temps Ac Ta ::= Ta Li TRAD Ao Va temp Ac Ao Va Tref Ac -# Radiative temperatures -.It Ao Va temp Ac Ta ::= Ta Vt real No # Temperature > 0 [K] -.It Ao Va Tref Ac Ta ::= Ta Vt real No # Reference temperature > 0 [K] .El .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .Ss Media @@ -220,6 +213,8 @@ that changes at .It Ta \& \& | Ta Aq Va robin .It Ta \& \& | Ta Aq Va neumann .It Ta \& \& | Ta Aq Va robin-neumann +.It Ta \& \& | Ta Ao Va rad-temp Ac No # \&At most once +.It Ta \& \& | Ta Ao Va ext-source Ac No # \&At most once .It \ Ta Ta .\" Dirichlet .It Ao Va dirichlet Ac Ta ::= Ta Ao Va dirichlet-const Ac | Ao Va dirichlet-prog Ac @@ -259,8 +254,25 @@ that changes at .It Ao Va robin-neumann-prog Ac Ta ::= Ta Li HF_BOUNDARY_FOR_SOLID_PROG Ao Va bound-name Ac \e .It Ta Ta Ao Va prog-desc Ac .It \ Ta Ta -.It Ao Va flux Ac Ta ::= Ta Vt real No # [W/m^2] +.\" Radiative temperature +.It Ao Va rad-temp Ac Ta ::= Ta Li TRAD Ao Va temp Ac Ao Va Tref Ac +# Radiative temperatures +.It \ Ta Ta +.\" External source +.It Ao Va ext-source Ac Ta ::= Ta Ao Va ext-source-const Ac | Ao Va ext-source-prog Ac +.It Ao Va ext-source-const Ac Ta ::= Ta Li SPHERICAL_SOURCE Ao Va radius Ac Ao Va position Ac \e +.It Ta Ta Ao Va power Ac +.It Ao Va ext-source-prog Ac Ta ::= Ta Li SPHERICAL_SOURCE_PROG Ao Va radius Ac \e +.It Ta Ta Ao Va prog-name Ac Op Li PROG_PARAMS Op Ao Va args Ac +.It \ Ta Ta +.\" Miscellaneous +.It Ao Va temp Ac Ta ::= Ta Vt real No # Temperature > 0 [K] +.It Ao Va Tref Ac Ta ::= Ta Vt real No # Reference temperature > 0 [K] .It Ao Va outside-temp Ac Ta ::= Ta Vt real No # Temperature > 0 [K] +.It Ao Va flux Ac Ta ::= Ta Vt real No # [W/m^2] +.It Ao Va power Ac Ta ::= Ta Vt real No # [W] +.It Ao Va position Ac Ta ::= Ta Vt real real real +.It Ao Va radius Ac Ta ::= Ta Vt real .El .\"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" .Ss Miscellaneous @@ -336,7 +348,7 @@ and its volumic power is .Ar 2.5 No W/m^3 . The boundary properties are .No emissivity= Ns Ar 0 , -.No specular-fraction= Ns Ar 0, +.No specular-fraction= Ns Ar 0 , .No hc= Ns Ar 10 No W/m^2/K and .No external-temperature= Ns Ar 100 No K . 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 January 31, 2024 +.Dd February 26, 2024 .Dt STARDIS 1 .Os .Sh NAME @@ -20,7 +20,7 @@ .Nd statistical solving of coupled thermal systems .Sh SYNOPSIS .Nm -.Op Fl eghv +.Op Fl eghiv .Op Fl D Ar path_type , Ns Ar files_name_prefix .Op Fl d Ar file_base_name .Op Fl F Pa surface Ns Op , Ns Ar time Ns Op , Ns Ar time @@ -186,6 +186,10 @@ and cannot be used in conjunction with option .Fl D . .It Fl h Output short help and exit. +.It Fl i +Disable internal radiative exchanges. +External radiative exchanges are still processed, i.e. the external +source. .It Fl L Pa interface_probes Defines a set of interface probes for which .Nm diff --git a/src/stardis-app.c b/src/stardis-app.c @@ -283,6 +283,8 @@ 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); /* If a dump is expected, we won't process any computation */ @@ -511,8 +513,19 @@ stardis_init scn_args.fp_to_meter = stardis->scale_factor; scn_args.trad.temperature = stardis->trad; scn_args.trad.reference = stardis->trad_ref; - d2_set(scn_args.t_range, stardis->t_range); + scn_args.t_range[0] = stardis->t_range[0]; + scn_args.t_range[1] = stardis->t_range[1]; + scn_args.source = stardis->extsrc.sdis_src; scn_args.context = &create_context; + + /* Setting Tmax to 0 is a way of setting the radiative coefficient to 0, and + * thus setting the probability of evolving in a radiative random walk to + * zero. */ + if(stardis->disable_intrad) { + scn_args.t_range[0] = 0; + scn_args.t_range[1] = 0; + } + res = sdis_scene_create(stardis->dev, &scn_args, &stardis->sdis_scn); if(res != RES_OK) { logger_print(stardis->logger, LOG_ERROR, @@ -549,6 +562,9 @@ stardis_release str_release(&stardis->bin_green_filename); str_release(&stardis->end_paths_filename); str_release(&stardis->chunks_prefix); + + extern_source_release(&stardis->extsrc); + /* release non-PROGRAM descritions first */ FOR_EACH(i, 0, darray_descriptions_size_get(&stardis->descriptions)) { struct description* d = darray_descriptions_data_get(&stardis->descriptions) +i; diff --git a/src/stardis-app.h b/src/stardis-app.h @@ -18,6 +18,7 @@ #include "stardis-args.h" #include "stardis-description.h" +#include "stardis-extern-source.h" #include <star/sg3d.h> @@ -241,6 +242,8 @@ struct stardis { int mpi_rank; struct darray_probe_boundary probe_boundary_list; + struct extern_source extsrc; + int disable_intrad; /* Disable internal radiative exchanges */ }; unsigned diff --git a/src/stardis-args.c b/src/stardis-args.c @@ -428,7 +428,7 @@ void usage(FILE* stream) { #define PRINT(Msg) fprintf(stream, Msg) - PRINT("stardis [-eghv] [-D path_type,files_name_prefix] [-d file_base_name]\n"); + PRINT("stardis [-eghiv] [-D path_type,files_name_prefix] [-d file_base_name]\n"); PRINT(" [-F surface[,time[,time]]] [-G green_bin[,green_ascii]]\n"); PRINT(" [-L interface_probes] [-m medium_name[,time[,time]]]\n"); PRINT(" [-n samples_count] [-o picard_order]\n"); @@ -495,7 +495,7 @@ parse_args { int opt = 0, n_used = 0, o_used = 0; size_t len = 0; - const char option_list[] = "c:d:D:eF:gG:hL:m:M:n:o:p:P:R:s:S:t:vV:x:X:"; + const char option_list[] = "c:d:D:eF:gG:hiL:m:M:n:o:p:P:R:s:S:t:vV:x:X:"; char buf[128]; struct str keep; char** line = NULL; @@ -624,6 +624,10 @@ parse_args args->mode |= MODE_DUMP_HELP; break; + case 'i': + args->disable_intrad = 1; + break; + case 'L': if(args->mode & EXCLUSIVE_MODES) { logger_print(args->logger, LOG_ERROR, diff --git a/src/stardis-args.h.in b/src/stardis-args.h.in @@ -142,6 +142,7 @@ struct args { int mode; enum dump_path_type dump_paths; int verbose; + int disable_intrad; /* Disable internal radiative exchanges */ struct darray_probe_boundary probe_boundary_list; }; diff --git a/src/stardis-extern-source.c b/src/stardis-extern-source.c @@ -0,0 +1,218 @@ +/* Copyright (C) 2018-2023 |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-app.h" +#include "stardis-extern-source.h" + +#include <sdis.h> +#include <rsys/cstr.h> +#include <rsys/logger.h> + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +sphere_get_position(const double time, double pos[3], struct sdis_data* data) +{ + const struct spherical_source* src = NULL; + ASSERT(pos); + (void)time; + + 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 spherical_source* src = NULL; + (void)time; + + src = *((const struct spherical_source* const*)sdis_data_cget(data)); + return src->power; /* [W] */ +} + +static res_T +create_solver_source_sphere + (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 && stardis); + + /* Register with the solver source a pointer to the external source */ + res = sdis_data_create(stardis->dev, sizeof(struct spherical_source*), + ALIGNOF(struct spherical_source*), NULL, &data); + if(res != RES_OK) goto error; + *((struct spherical_source**)sdis_data_get(data)) = &src->data.sphere; + + /* Create the spherical source */ + args.position = sphere_get_position; + args.power = sphere_get_power; + args.data = data; + args.radius = src->data.sphere.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; +} + +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; + src->data.sphere_prog.allocator = allocator; + str_init(allocator, &src->data.sphere_prog.prog_name); + return RES_OK; +} + +void +extern_source_release(struct extern_source* src) +{ + ASSERT(src); + if(src->type == EXTERN_SOURCE_SPHERE_PROG) { + struct spherical_source_prog* src_prog = &src->data.sphere_prog; + size_t i; + + if(src_prog->data) { + ASSERT(src_prog->release); + src_prog->release(src_prog->data); + } + + str_release(&src_prog->prog_name); + FOR_EACH(i, 0, src_prog->argc) { + MEM_RM(src_prog->allocator, src_prog->argv[i]); + } + + MEM_RM(src_prog->allocator, src_prog->argv); + } + + if(src->sdis_src) SDIS(source_ref_put(src->sdis_src)); +} + +res_T +extern_source_create_solver_source + (struct extern_source* src, + struct stardis* stardis) +{ + res_T res = RES_OK; + ASSERT(src); + + switch(src->type) { + case EXTERN_SOURCE_SPHERE: + 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; + } + +exit: + return res; +error: + goto exit; +} diff --git a/src/stardis-extern-source.h b/src/stardis-extern-source.h @@ -0,0 +1,111 @@ +/* Copyright (C) 2018-2023 |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/>. */ + +#ifndef SDIS_EXTERN_SOURCE_H +#define SDIS_EXTERN_SOURCE_H + +#include <rsys/rsys.h> + +/* Forward declaration */ +struct stardis; +struct stardis_description_create_context; + +enum source_type { + EXTERN_SOURCE_SPHERE, + EXTERN_SOURCE_SPHERE_PROG, + EXTERN_SOURCE_NONE__ +}; + +struct spherical_source { + double position[3]; + double radius; + double power; /* [W] */ +}; +#define SPHERICAL_SOURCE_NULL__ {{0,0,0}, -1, 0} +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 */ + struct mem_allocator* allocator; + + /* 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, 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; +}; +#define EXTERN_SOURCE_NULL__ \ + {EXTERN_SOURCE_NONE__, {SPHERICAL_SOURCE_NULL__}, NULL} +static const struct extern_source EXTERN_SOURCE_NULL = 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 + (struct extern_source* src); + +extern LOCAL_SYM res_T +extern_source_create_solver_source + (struct extern_source* src, + struct stardis* stardis); + +#endif /* SDIS_EXTERN_SOURCE_H */ diff --git a/src/stardis-intface.c b/src/stardis-intface.c @@ -632,9 +632,9 @@ create_intface } ASSERT(fluid_side_shader); fluid_side_shader->reference_temperature = interface_get_ref_temperature; + fluid_side_shader->specular_fraction = interface_get_alpha; if(intface->d.sf_connect->emissivity > 0) { fluid_side_shader->emissivity = interface_get_emissivity; - fluid_side_shader->specular_fraction = interface_get_alpha; } break; case DESC_SOLID_FLUID_CONNECT_PROG: diff --git a/src/stardis-parsing.c b/src/stardis-parsing.c @@ -303,8 +303,8 @@ description_set_name "H_BOUNDARY_FOR_SOLID", "H_BOUNDARY_FOR_SOLID_PROG", "PROGRAM", "PROG_PARAMS", "SCALE", "SOLID", "SOLID_PROG", "SOLID_FLUID_CONNECTION", "SOLID_FLUID_CONNECTION_PROG", "SOLID_SOLID_CONNECTION", - "SOLID_SOLID_CONNECTION_PROG", "TRAD", "T_BOUNDARY_FOR_SOLID", - "T_BOUNDARY_FOR_SOLID_PROG", "UNKNOWN" }; + "SOLID_SOLID_CONNECTION_PROG", "SPHERICAL_SOURCE", "SPHERICAL_SOURCE_PROG", + "TRAD", "T_BOUNDARY_FOR_SOLID", "T_BOUNDARY_FOR_SOLID_PROG", "UNKNOWN" }; const char* reason = NULL; size_t i; ASSERT(name && arg); @@ -628,6 +628,18 @@ set_argc_argv 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; @@ -2070,6 +2082,142 @@ error: goto end; } +static res_T +process_spherical_source + (struct stardis* stardis, + wordexp_t* pwordexp) +{ + struct spherical_source* src = NULL; + char* arg = NULL; + size_t idx = 1; + res_T res = RES_OK; + ASSERT(stardis && pwordexp); + + src = &stardis->extsrc.data.sphere; + + 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(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; + } + + #define PARSE_POS(Name, Id) { \ + CHK_ARG(idx, "position "Name); \ + res = cstr_to_double(arg, &src->position[Id]); \ + if(res != RES_OK) { \ + logger_print(stardis->logger, LOG_ERROR, \ + "Invalid spherical source "Name" coordinate: %s\n", arg); \ + goto error; \ + } \ + } (void)0 + PARSE_POS("X", 0); + PARSE_POS("Y", 1); + PARSE_POS("Z", 2); + #undef PARSE_POS + + CHK_ARG(idx, "power"); + res = cstr_to_double(arg, &src->power); + if(res == RES_OK && src->power < 0) res = RES_BAD_ARG; + if(res != RES_OK) { + logger_print(stardis->logger, LOG_ERROR, + "Invalid sphercial source power: %s\n", arg); + goto error; + } + + 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 stardis_description_create_context ctx; + 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", + pwordexp->we_wordv[idx]); + res = RES_BAD_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); + + ctx.name = "External spherical source"; + src->data = src->create(&ctx, src->program->prog_data, src->argc, src->argv); + if(!src->data) { + logger_print(stardis->logger, LOG_ERROR, + "Cannot create data for the external spherical source\n"); + res = RES_BAD_ARG; + goto error; + } + + 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; +} + /* Read medium or boundary line; should be one of: * SOLID Name lambda rho cp delta Tinit Timposed volumic_power STL_sides_filenames * FLUID Name rho cp Tinit Timposed STL_filenames @@ -2151,6 +2299,10 @@ process_model_line ERR(process_scale(stardis, pwordexp)); else if(0 == strcasecmp(arg, "TRAD")) 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); diff --git a/src/stardis-prog-properties.h.in b/src/stardis-prog-properties.h.in @@ -592,6 +592,26 @@ 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. */ +/******************************************************************************/ + +/* Retrieve the position of the spherical source center. + * This function is used to calculate the external flux at the boundaries. + * Returns its modified position argument */ +STARDIS_API double* +stardis_spherical_source_position + (const double time, /* [s] */ + double position[3], + void* data); + +/* Retrieve the power of the spherical source. */ +STARDIS_API double /* [W] */ +stardis_spherical_source_power + (const double time, + void* data); + #ifdef __cplusplus } /* extern "C" */ #endif