stardis-test

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

commit e03b02486597aabc4ffaa48edeffca7182fcbd5e
parent e9f711caabd8d9bc9b36ab208033b91db40ed7c7
Author: Vincent Forest <vincent.forest@meso-star.com>
Date:   Fri, 23 Feb 2024 18:19:42 +0100

Test the resolution of several boundary probes

The sadist_probe_boundary test now offers an option for defining the
number of probe points to be resolved. When this is greater than 1,
invoke stardis with the -L option to define a list of probe points to be
resolved.

Diffstat:
MMakefile | 3++-
Msrc/sadist_probe_boundary.c | 203+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 196 insertions(+), 10 deletions(-)

diff --git a/Makefile b/Makefile @@ -52,7 +52,8 @@ src/sadist_probe_boundary.o:\ sadist_probe_boundary: src/sadist_probe_boundary.o libsadist-triprof.so $(CC) $(CFLAGS_EXE) $(S3DUT_CFLAGS) $(RSYS_CFLAGS) -o $@ src/$@.o \ - $(LDFLAGS_EXE) $(S3DUT_LIBS) $(RSYS_LIBS) + $(LDFLAGS_EXE) $(S3DUT_LIBS) $(RSYS_LIBS) -lm test: $(TESTS) ./sadist_probe_boundary + ./sadist_probe_boundary -p 4 diff --git a/src/sadist_probe_boundary.c b/src/sadist_probe_boundary.c @@ -21,6 +21,7 @@ #include <star/s3dut.h> +#include <rsys/cstr.h> #include <rsys/double2.h> #include <rsys/double3.h> #include <rsys/math.h> @@ -28,6 +29,7 @@ #include <errno.h> #include <float.h> +#include <getopt.h> #include <string.h> /* strerror */ /* Axis Aligned Bounding Box */ @@ -38,6 +40,13 @@ struct aabb { #define AABB_NULL__ {{DBL_MAX,DBL_MAX,DBL_MAX}, {-DBL_MAX,-DBL_MAX,-DBL_MAX}} static const struct aabb AABB_NULL = AABB_NULL__; +struct args { + unsigned nprobes; /* Number of probes to solve */ + int quit; +}; +#define ARGS_DEFAULT__ {1, 0} +static const struct args ARGS_DEFAULT = ARGS_DEFAULT__; + /* * The system is a trilinear profile of the temperature at steady state, i.e. at * each point of the system we can calculate the temperature analytically. Two @@ -60,6 +69,7 @@ static const struct aabb AABB_NULL = AABB_NULL__; #define FILENAME_SSHAPE "sshape.stl" #define FILENAME_SPHERE "sphere.stl" +#define FILENAME_PROBES "probes.txt" #define FILENAME_SCENE "scene.txt" /* Temperature at the upper bound of the X, Y and Z axis. The temperature at the @@ -73,12 +83,31 @@ static const struct aabb AABB_NULL = AABB_NULL__; #define PY 0.0 #define PZ 0.0 -/* The executed command */ -#define COMMAND "stardis -V3 -P "STR(PX)","STR(PY)","STR(PZ)" -M "FILENAME_SCENE +/* Commands to calculate 1 or N probes */ +#define COMMAND1 "stardis -V3 -P "STR(PX)","STR(PY)","STR(PZ)" -M "FILENAME_SCENE +#define COMMANDN "stardis -V3 -L "FILENAME_PROBES" -M "FILENAME_SCENE /******************************************************************************* * Helper functions ******************************************************************************/ +static double +rand_canonic(void) +{ + return (double)rand() / (double)((long)RAND_MAX - 1); +} + +static void +sample_unit_sphere(double p[3]) +{ + const double phi = rand_canonic() * 2*PI; + const double v = rand_canonic(); + const double cos_theta = 1 - 2*v; + const double sin_theta = 2 * sqrt(v*(1-v)); + p[0] = cos(phi) * sin_theta; + p[1] = sin(phi) * sin_theta; + p[2] = cos_theta; +} + static void aabb_update(struct aabb* aabb, const struct s3dut_mesh_data* mesh) { @@ -164,6 +193,48 @@ setup_scene d2(profile->c, 0, TZ); } +static void +usage(const char* name, FILE* stream) +{ + ASSERT(name && stream); + fprintf(stream, "usage: %s [-h] [-p probes_count]\n", name); +} + +static int +args_init(struct args* args, int argc, char** argv) +{ + int opt = 0; + int err = 0; + + ASSERT(args); + while((opt = getopt(argc, argv, "hp:")) != -1) { + switch(opt) { + case 'h': + usage(argv[0], stdout); + args->quit = 1; + break; + case 'p': + err = (cstr_to_uint(optarg, &args->nprobes) != RES_OK); + if(!err && args->nprobes == 0) err = 1; + break; + default: err = 1; break; + } + if(err) { + if(optarg) { + fprintf(stderr, "%s: invalid option argument `%s' -- `%c'\n", + argv[0], optarg, opt); + } + goto error; + } + } + +exit: + return err; +error: + usage(argv[0], stderr); + goto exit; +} + static int init(struct sadist_trilinear_profile* profile) { @@ -206,7 +277,38 @@ error: } static int -run(const struct sadist_trilinear_profile* profile) +init_probe_list(double* probes, const size_t nprobes) +{ + FILE* fp_probes = NULL; + size_t i = 0; + int err = 0; + ASSERT(probes && nprobes); + + if((fp_probes = fopen(FILENAME_PROBES, "w")) == NULL) { + fprintf(stderr, "Error opening `"FILENAME_PROBES"' file -- %s\n", + strerror(errno)); + err = errno; + goto error; + } + + FOR_EACH(i, 0, nprobes) { + sample_unit_sphere(probes+i*3); + if(fprintf(fp_probes, "%g,%g,%g\n", SPLIT3(probes+i*3)) < 0) { + fprintf(stderr, "Error writing probes -- %s\n", strerror(errno)); + err = errno; + goto error; + } + } + +exit: + if(fp_probes && fclose(fp_probes)) { perror("fclose"); if(!err) err = errno; } + return err; +error: + goto exit; +} + +static int +run1(const struct sadist_trilinear_profile* profile) { const double P[3] = {PX, PY, PZ}; FILE* output = NULL; @@ -216,16 +318,16 @@ run(const struct sadist_trilinear_profile* profile) int n = 0; int err = 0; - printf(COMMAND"\n"); + printf(COMMAND1"\n"); - if(!(output = popen(COMMAND, "r"))) { + if(!(output = popen(COMMAND1, "r"))) { fprintf(stderr, "Error executing stardis -- %s\n", strerror(errno)); - fprintf(stderr, "\t"COMMAND"\n"); + fprintf(stderr, "\t"COMMAND1"\n"); err = errno; goto error; } - if((n = fscanf(output, "%lf %lf", &E, &SE)), n != 2 && n != EOF) { + if((n = fscanf(output, "%lf %lf %*d %*d", &E, &SE)), n != 2 && n != EOF) { fprintf(stderr, "Error reading the output stream -- %s\n", strerror(errno)); err = errno; goto error; @@ -233,16 +335,90 @@ run(const struct sadist_trilinear_profile* profile) /* Check command exit status */ if((err = pclose(output))) goto error; + output = NULL; ref = sadist_trilinear_profile(profile, P); printf("T = %g ~ %g +/- %g\n", ref, E, SE); if(!eq_eps(ref, E, SE*3)) { - fprintf(stderr, "Test failed\n"); err = 1; goto error; } exit: + if(output) pclose(output); + return err; +error: + goto exit; +} + +static int +runN(const struct sadist_trilinear_profile* profile, const size_t nprobes) +{ + double* probes = NULL; /* Positions */ + double* results = NULL; /* Expected values and standard deviations */ + FILE* output = NULL; + size_t i = 0; + int err = 0; + ASSERT(profile && nprobes); + + if(!(probes = mem_calloc(nprobes, sizeof(double)*3))) { + err = errno = ENOMEM; + perror("mem_calloc"); + goto error; + } + + if(!(results = mem_calloc(nprobes, sizeof(double)*2))) { + err = errno = ENOMEM; + perror("mem_calloc"); + goto error; + } + + if((err = init_probe_list(probes, nprobes))) goto error; + + printf(COMMANDN"\n"); + + if(!(output = popen(COMMANDN, "r"))) { + fprintf(stderr, "Error executing stardis -- %s\n", strerror(errno)); + fprintf(stderr, "\t"COMMAND1"\n"); + err = errno; + goto error; + } + + /* Fetch the result */ + FOR_EACH(i, 0, nprobes) { + double* E = results + i*2 + 0; + double* SE = results + i*2 + 1; + int n = 0; + + if((n = fscanf(output, "%lf %lf %*d %*d", E, SE)), n != 2 && n != EOF) { + perror("fscanf"); + err = errno; + goto error; + } + } + + /* Check command exit status */ + if((err = pclose(output))) goto error; + output = NULL; + + /* Validate the calculations */ + FOR_EACH(i, 0, nprobes) { + const double* P = probes + i*3; + const double E = results[i*2 + 0]; + const double SE = results[i*2 + 1]; + const double ref = sadist_trilinear_profile(profile, P); + + printf("T = %g ~ %g +/- %g\n", ref, E, SE); + if(!eq_eps(ref, E, SE*3)) { + err = 1; + goto error; + } + } + +exit: + if(probes) mem_rm(probes); + if(results) mem_rm(results); + if(output) pclose(output); return err; error: goto exit; @@ -254,12 +430,21 @@ error: int main(int argc, char** argv) { + struct args args = ARGS_DEFAULT; struct sadist_trilinear_profile profile = SADIST_TRILINEAR_PROFILE_NULL; int err = 0; (void)argc, (void)argv; + if((err = args_init(&args, argc, argv))) goto error; + if(args.quit) goto exit; + if((err = init(&profile))) goto error; - if((err = run(&profile))) goto error; + + if(args.nprobes == 1) { + if((err = run1(&profile))) goto error; + } else { + if((err = runN(&profile, args.nprobes))) goto error; + } exit: if(mem_allocated_size() != 0) {