star-meteo

Time varying meteorological data
git clone git://git.meso-star.fr/star-meteo.git
Log | Files | Refs | README | LICENSE

commit f3dccb003c15a7cc9c8dff4df8ad849ebd2e904a
parent 45786c9616be1e265340d326d869a7869efc7a15
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Wed, 13 Aug 2025 17:49:37 +0200

Add Stardis data creation and one of its getters

Adds an internal function that searches for the time interval in which a
given moment is located. This is actually the only "challenge" for all
getters so that they can return physical properties based on time. From
now on, the remaining getters will be very easy to implement.

Diffstat:
MMakefile | 1+
Asrc/stardis_smeteo.c | 219+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 220 insertions(+), 0 deletions(-)

diff --git a/Makefile b/Makefile @@ -96,6 +96,7 @@ $(UTIL_OBJ): config.mk smeteo-local.pc # Plugin ################################################################################ PLUGIN_SRC =\ + src/stardis_smeteo.c\ src/stardis_smeteo_library.c PLUGIN_OBJ = $(PLUGIN_SRC:.c=.o) PLUGIN_DEP = $(PLUGIN_SRC:.c=.d) diff --git a/src/stardis_smeteo.c b/src/stardis_smeteo.c @@ -0,0 +1,219 @@ +/* Copyright (C) 2025 |Méso|Star> (contact@meso-star.com) + * + * This program is free software: you can redismshbute 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 dismshbuted in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +#define _POSIX_C_SOURCE 200112L /* getopt */ + +#include "smeteo.h" +#include "stardis_smeteo.h" + +#include <rsys/algorithm.h> +#include <rsys/mem_allocator.h> + +#include <getopt.h> + +enum boundary_condition_type { + DIRICHLET, + NEUMANN_ROBIN, + NONE__ +}; + +struct boundary_condition { + struct smeteo* smeteo; + struct smeteo_desc smeteo_desc; + enum boundary_condition_type type; +}; + +struct args { + enum boundary_condition_type bcond_type; +}; +#define ARGS_DEFAULT__ { NEUMANN_ROBIN } +static const struct args ARGS_DEFAULT = ARGS_DEFAULT__; + +/******************************************************************************* + * Helper functions + ******************************************************************************/ +static void +usage(FILE* stream, const char* name) +{ + fprintf(stream, "usage: %s [-d]\n", name); +} + +static res_T +args_init(struct args* args, int argc, char* argv[]) +{ + int opt = 0; + res_T res = RES_OK; + + ASSERT(args && argc && argv); + + optind = 1; + while((opt = getopt(argc, argv, "d")) != -1) { + switch(opt) { + case 'd': args->bcond_type = DIRICHLET; break; + default: res = RES_BAD_ARG; break; + } + if(res != RES_OK) goto error; + } + +exit: + return res; +error: + usage(stderr, argv[0]); + goto exit; +} + +static int +cmp_day_1850(const void* key, const void* val) +{ + const double day_1850 = *(double*)key; + const struct smeteo_entry* entry = val; + if(day_1850 < entry->day_1850) return -1; + else if(day_1850 > entry->day_1850) return +1; + else /* day_1850 == entry->day_1850 */ return 0; +} + +static size_t +get_meteo_entry_id + (const struct boundary_condition* bcond, + const double time) /* [s] */ +{ + struct smeteo_entry* found = NULL; + double time_1850 = 0; + ASSERT(bcond && frag); + + /* Define the input time in relation to January 1, 1850, i.e., in terms of the + * number of days that have elapsed since 00:00 on January 1, 1850 */ + time_1850 = time/*[s]*/ / (24/*hours*/*3600/*[s]*/); + + /* Limit to 0, i.e. January 1, 1850 */ + time_1850 = time_1850 < 0 ? 0 : time_1850; + + /* Search for the time interval whose center date is greater than or equal to + * the input time */ + found = search_lower_bound + (&time_1850, + bcond->smeteo_desc.entries, + bcond->smeteo_desc.nentries, + sizeof(struct smeteo_entry), + cmp_day_1850); + + /* There are no intervals whose center time is greater than the input time. + * The time is therefore either in the upper half of the interval or beyond + * it. In both cases, return the last interval, which, in the case of an input + * time beyond the available time intervals, amounts to repeating the last + * interval indefinitely. */ + if(!found) { + return bcond->smeteo_desc.nentries -1; + + } else { + double half_interval_duration = 0; + + /* Define whether the input time is included in the interval found or in + * the previous one. If the time elapsed between the input time and the + * central time of the current interval is less than half the duration of an + * interval, then the time belongs to the interval found. Otherwise, it + * belongs to the previous one. + * + * Note that there is no need to check that the interval found is the first + * one and that there is therefore no previous interval, because the input + * time has already been truncated to 0, i.e. midnight on January 1, 1850. + * */ + half_interval_duration = bcond->smeteo_desc.entries[0].day_1850; + if(found->day_1850 - time_1850 > half_interval_duration) --found; + + /* Calculate the index of the selected interval */ + ASSERT((intptr_t)found >= (intptr_t)bcond->smeteo_desc.entries); + return (size_t)(found - bcond->smeteo_desc.entries); + } +} + +/******************************************************************************* + * Exported symbols + ******************************************************************************/ +void* +stardis_create_data + (const struct stardis_description_create_context* ctx, + void* lib_data, + size_t argc, + char* argv[]) +{ + struct args args = ARGS_DEFAULT; + struct boundary_condition* bcond = NULL; + res_T res = RES_OK; + + ASSERT(lib_data && argc && argv); + (void)ctx; /* Avoid "unused variable" warning */ + + if((res = args_init(&args, (int)argc, argv)) != RES_OK) goto error; + if(!(bcond = mem_calloc(1, sizeof(*bcond)))) goto error; + + bcond->smeteo = lib_data; + SMETEO(ref_get(bcond->smeteo)); + bcond->type = args.bcond_type; + SMETEO(get_desc(bcond->smeteo, &bcond->smeteo_desc)); + +exit: + return bcond; +error: + if(bcond) { mem_rm(bcond); bcond = NULL; } + goto exit; +} + +void +stardis_release_data(void* data) +{ + struct boundary_condition* bcond = data; + ASSERT(data); + + SMETEO(ref_put(bcond->smeteo)); + mem_rm(bcond); +} + +double +stardis_convection_coefficient + (const struct stardis_interface_fragment* frag, + void* data) +{ + struct boundary_condition* bcond = data; + size_t i= 0; /* Index of the meteo entry including fragment time */ + ASSERT(frag && data); + + i = get_meteo_entry_id(bcond, frag->time); + return bcond->smeteo_desc.entries[i].H; +} + +const char* +get_copyright_notice(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return "Copyright (C) 2025 |Méso|Star> (contact@meso-star.com)"; +} + +const char* +get_license_short(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return "GNU GPL version 3 or later <http://www.gnu.org/licenses/>"; +} + +const char* +get_license_text(void* data) +{ + (void)data; /* Avoid "unused variable" warnings */ + return + "This is free software released under the GPL v3+ license: GNU GPL\n" + "version 3 or later. You are welcome to redistribute it under certain\n" + "conditions; refer to <http://www.gnu.org/licenses/> for details."; +}